165 lines
4.1 KiB
Go
165 lines
4.1 KiB
Go
package day11
|
|
|
|
import (
|
|
"fmt"
|
|
"sort"
|
|
"strconv"
|
|
"strings"
|
|
)
|
|
|
|
type Solver struct {
|
|
monkeys []*MonkeySpec
|
|
}
|
|
|
|
type MonkeySpec struct {
|
|
itemWorryLevels []uint64
|
|
advancedItemWorryLevels []ItemWorryLevel
|
|
opType string
|
|
opValue uint64
|
|
testDivisor uint64
|
|
targetMonkeyIfTrue int
|
|
targetMonkeyIfFalse int
|
|
numInspections int
|
|
}
|
|
|
|
type ItemWorryLevel struct {
|
|
multipliers []uint64
|
|
additive uint64
|
|
}
|
|
|
|
func (i *ItemWorryLevel) Value() uint64 {
|
|
v := uint64(1)
|
|
for _, m := range i.multipliers {
|
|
v *= m
|
|
}
|
|
return v + i.additive
|
|
}
|
|
|
|
func (i *ItemWorryLevel) Mod(d uint64) uint64 {
|
|
currentDivisor := uint64(1)
|
|
for _, m := range i.multipliers {
|
|
currentDivisor *= m % d
|
|
}
|
|
currentDivisor += i.additive
|
|
currentDivisor %= d
|
|
|
|
return currentDivisor
|
|
}
|
|
|
|
func (i *ItemWorryLevel) TimesConst(c uint64) *ItemWorryLevel {
|
|
r := *i
|
|
r.multipliers = append(r.multipliers, c)
|
|
r.additive *= c
|
|
return &r
|
|
}
|
|
|
|
// func (i *ItemWorryLevel) Squared() *ItemWorryLevel {
|
|
// r := *i
|
|
// r.multipliers = append(r.multipliers, (2*i.additive)%allDivisors)
|
|
// r.multipliers = append(r.multipliers, i.multipliers...)
|
|
// r.additive *= i.additive
|
|
// return &r
|
|
// }
|
|
|
|
func (s *Solver) ParseInput(input []string) {
|
|
s.monkeys = make([]*MonkeySpec, 1+len(input)/7)
|
|
for m := 0; m < len(s.monkeys); m++ {
|
|
offset := 7 * m
|
|
|
|
startingItemsLine := strings.Split(strings.Split(input[offset+1], ": ")[1], ", ")
|
|
startingItems := make([]uint64, len(startingItemsLine))
|
|
advancedStartingItems := make([]ItemWorryLevel, len(startingItemsLine))
|
|
for i, item := range startingItemsLine {
|
|
startingItems[i], _ = strconv.ParseUint(item, 10, 64)
|
|
advancedStartingItems[i] = ItemWorryLevel{[]uint64{startingItems[i]}, 0}
|
|
}
|
|
|
|
operationLine := strings.Split(strings.Split(input[offset+2], " old ")[1], " ")
|
|
opType := operationLine[0]
|
|
opValue, _ := strconv.ParseUint(operationLine[1], 10, 64)
|
|
|
|
divisor, _ := strconv.ParseUint(strings.Split(input[offset+3], " by ")[1], 10, 64)
|
|
|
|
trueTargetMonkey, _ := strconv.Atoi(strings.Split(input[offset+4], " monkey ")[1])
|
|
falseTargetMonkey, _ := strconv.Atoi(strings.Split(input[offset+5], " monkey ")[1])
|
|
|
|
s.monkeys[m] = &MonkeySpec{
|
|
itemWorryLevels: startingItems,
|
|
advancedItemWorryLevels: advancedStartingItems,
|
|
opType: opType,
|
|
opValue: opValue,
|
|
testDivisor: divisor,
|
|
targetMonkeyIfTrue: trueTargetMonkey,
|
|
targetMonkeyIfFalse: falseTargetMonkey,
|
|
}
|
|
}
|
|
}
|
|
|
|
func (s *Solver) SolvePart1() any {
|
|
return s.solve(20, true)
|
|
}
|
|
|
|
func (s *Solver) SolvePart2() any {
|
|
return s.solve(10000, false)
|
|
}
|
|
|
|
func (s *Solver) solve(numberOfRounds uint64, divideByThree bool) any {
|
|
allDivisors := uint64(1)
|
|
for _, d := range s.monkeys {
|
|
allDivisors *= d.testDivisor
|
|
}
|
|
|
|
for r := 0; r < int(numberOfRounds); r++ {
|
|
for _, monkey := range s.monkeys {
|
|
for _, item := range monkey.itemWorryLevels {
|
|
monkey.numInspections++
|
|
|
|
newWorryLevel := item
|
|
var opValue uint64
|
|
if monkey.opValue == 0 {
|
|
opValue = item
|
|
} else {
|
|
opValue = monkey.opValue
|
|
}
|
|
switch monkey.opType {
|
|
case "*":
|
|
newWorryLevel *= opValue
|
|
case "+":
|
|
newWorryLevel += opValue
|
|
}
|
|
if divideByThree {
|
|
newWorryLevel /= 3
|
|
} else {
|
|
newWorryLevel %= allDivisors
|
|
}
|
|
|
|
var targetMonkey int
|
|
if newWorryLevel%monkey.testDivisor == 0 {
|
|
targetMonkey = monkey.targetMonkeyIfTrue
|
|
} else {
|
|
targetMonkey = monkey.targetMonkeyIfFalse
|
|
}
|
|
s.monkeys[targetMonkey].itemWorryLevels = append(s.monkeys[targetMonkey].itemWorryLevels, newWorryLevel)
|
|
// fmt.Printf("-> Throwing to monkey: %d\n", targetMonkey)
|
|
}
|
|
monkey.itemWorryLevels = []uint64{}
|
|
}
|
|
// fmt.Printf("\nround %d:\n", r)
|
|
// s.printMonkeys()
|
|
}
|
|
|
|
var numInspections []int
|
|
for _, m := range s.monkeys {
|
|
numInspections = append(numInspections, m.numInspections)
|
|
}
|
|
sort.Ints(numInspections)
|
|
|
|
return uint64(numInspections[len(numInspections)-1]) * uint64(numInspections[len(numInspections)-2])
|
|
}
|
|
|
|
func (s *Solver) printMonkeys() {
|
|
for _, m := range s.monkeys {
|
|
fmt.Printf("%+v\n", m)
|
|
}
|
|
}
|