125 lines
2.3 KiB
Go
125 lines
2.3 KiB
Go
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"sort"
|
|
"strconv"
|
|
"strings"
|
|
)
|
|
|
|
func main() {
|
|
filename := "input0.txt"
|
|
if len(os.Args) > 1 {
|
|
filename = os.Args[1]
|
|
}
|
|
lines := readLines(filename)
|
|
kitchen := parseKitchen(lines)
|
|
fmt.Printf("%d\n", kitchen.countFreshIngredients())
|
|
fmt.Printf("%d\n", kitchen.countEverythingFresh())
|
|
}
|
|
|
|
func readLines(filename string) []string {
|
|
raw, err := os.ReadFile(filename)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
return strings.Split(string(raw), "\n")
|
|
}
|
|
|
|
type container struct {
|
|
start uint64
|
|
stop uint64
|
|
}
|
|
|
|
func (i container) contains(id uint64) bool {
|
|
return i.start <= id && i.stop >= id
|
|
}
|
|
|
|
type kitchen struct {
|
|
coolers []container
|
|
ingredients []uint64
|
|
}
|
|
|
|
func (k kitchen) countFreshIngredients() uint64 {
|
|
total := uint64(0)
|
|
INGREDIENTS:
|
|
for _, ingredient := range k.ingredients {
|
|
for _, cooler := range k.coolers {
|
|
if cooler.contains(ingredient) {
|
|
total++
|
|
continue INGREDIENTS
|
|
}
|
|
}
|
|
}
|
|
return total
|
|
}
|
|
|
|
func parseKitchen(lines []string) kitchen {
|
|
k := kitchen{
|
|
coolers: []container{},
|
|
ingredients: []uint64{},
|
|
}
|
|
coolers := true
|
|
for _, line := range lines {
|
|
if line == "" {
|
|
coolers = false
|
|
continue
|
|
}
|
|
if coolers {
|
|
parts := strings.Split(line, "-")
|
|
cooler := container{}
|
|
cooler.start, _ = strconv.ParseUint(parts[0], 10, 64)
|
|
cooler.stop, _ = strconv.ParseUint(parts[1], 10, 64)
|
|
k.coolers = append(k.coolers, cooler)
|
|
} else {
|
|
id, _ := strconv.ParseUint(line, 10, 64)
|
|
k.ingredients = append(k.ingredients, id)
|
|
}
|
|
}
|
|
return k
|
|
}
|
|
|
|
func (k kitchen) countEverythingFresh() uint64 {
|
|
type pivot struct {
|
|
id uint64
|
|
start bool
|
|
}
|
|
pivots := []pivot{}
|
|
for _, cooler := range k.coolers {
|
|
pivots = append(pivots,
|
|
pivot{id: cooler.start, start: true},
|
|
pivot{id: cooler.stop, start: false},
|
|
)
|
|
}
|
|
sort.Slice(pivots, func(i, j int) bool {
|
|
pi, pj := pivots[i], pivots[j]
|
|
if pi.id < pj.id {
|
|
return true
|
|
}
|
|
if pi.id > pj.id {
|
|
return false
|
|
}
|
|
if !pi.start && pj.start {
|
|
return false
|
|
}
|
|
return true
|
|
})
|
|
total := uint64(0)
|
|
insideStarted := uint64(0)
|
|
within := uint16(0)
|
|
for _, pivot := range pivots {
|
|
if pivot.start {
|
|
if within == 0 {
|
|
insideStarted = pivot.id
|
|
}
|
|
within++
|
|
} else {
|
|
within--
|
|
if within == 0 {
|
|
total += 1 + pivot.id - insideStarted
|
|
}
|
|
}
|
|
}
|
|
return total
|
|
}
|