Solve day 5
This commit is contained in:
123
day5/main.go
Normal file
123
day5/main.go
Normal file
@@ -0,0 +1,123 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"cmp"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"os"
|
||||
"slices"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func main() {
|
||||
f := os.Stdin
|
||||
if len(os.Args) > 1 && os.Args[1] != "-" {
|
||||
var err error
|
||||
f, err = os.Open(os.Args[1])
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
defer f.Close()
|
||||
}
|
||||
|
||||
fresh, available, err := readIngredients(f)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
var availableFresh int
|
||||
for _, id := range available {
|
||||
for _, r := range fresh {
|
||||
if r.Includes(id) {
|
||||
availableFresh++
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var freshIds int
|
||||
compactFresh := compactedRanges(fresh)
|
||||
for _, r := range compactFresh {
|
||||
freshIds += r.to - r.from + 1
|
||||
}
|
||||
|
||||
fmt.Println("available fresh:", availableFresh)
|
||||
fmt.Println("total fresh:", freshIds)
|
||||
}
|
||||
|
||||
type idsRange struct {
|
||||
from, to int
|
||||
}
|
||||
|
||||
func (r idsRange) Includes(n int) bool {
|
||||
return r.from <= n && n <= r.to
|
||||
}
|
||||
|
||||
func readIngredients(r io.Reader) (fresh []idsRange, available []int, err error) {
|
||||
seenEmptyLine := false
|
||||
sc := bufio.NewScanner(r)
|
||||
for sc.Scan() {
|
||||
if sc.Text() == "" {
|
||||
seenEmptyLine = true
|
||||
continue
|
||||
}
|
||||
if seenEmptyLine {
|
||||
id, err := strconv.ParseUint(sc.Text(), 10, 0)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
available = append(available, int(id))
|
||||
} else {
|
||||
r, err := parseRange(sc.Text())
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
fresh = append(fresh, r)
|
||||
}
|
||||
}
|
||||
return fresh, available, nil
|
||||
}
|
||||
|
||||
func parseRange(s string) (idsRange, error) {
|
||||
before, after, ok := strings.Cut(s, "-")
|
||||
if !ok {
|
||||
return idsRange{}, fmt.Errorf("range %q: missing hyphen", s)
|
||||
}
|
||||
from, err := strconv.ParseUint(before, 10, 0)
|
||||
if err != nil {
|
||||
return idsRange{}, fmt.Errorf("range from: %w", err)
|
||||
}
|
||||
to, err := strconv.ParseUint(after, 10, 0)
|
||||
if err != nil {
|
||||
return idsRange{}, fmt.Errorf("range to: %w", err)
|
||||
}
|
||||
return idsRange{
|
||||
from: int(from),
|
||||
to: int(to),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func compactedRanges(ranges []idsRange) []idsRange {
|
||||
ranges = slices.Clone(ranges)
|
||||
|
||||
slices.SortFunc(ranges, func(a, b idsRange) int {
|
||||
if x := cmp.Compare(a.from, b.from); x != 0 {
|
||||
return x
|
||||
}
|
||||
return cmp.Compare(a.to, b.to)
|
||||
})
|
||||
|
||||
i := 0
|
||||
for j := 1; j < len(ranges); j++ {
|
||||
if !ranges[i].Includes(ranges[j].from) {
|
||||
i++
|
||||
ranges[i] = ranges[j]
|
||||
continue
|
||||
}
|
||||
ranges[i].to = max(ranges[i].to, ranges[j].to)
|
||||
}
|
||||
return ranges[:i+1]
|
||||
}
|
||||
Reference in New Issue
Block a user