diff --git a/day11/prod.in.txt b/day11/prod.in.txt new file mode 100644 index 0000000..2e2bd25 --- /dev/null +++ b/day11/prod.in.txt @@ -0,0 +1,55 @@ +Monkey 0: + Starting items: 50, 70, 89, 75, 66, 66 + Operation: new = old * 5 + Test: divisible by 2 + If true: throw to monkey 2 + If false: throw to monkey 1 + +Monkey 1: + Starting items: 85 + Operation: new = old * old + Test: divisible by 7 + If true: throw to monkey 3 + If false: throw to monkey 6 + +Monkey 2: + Starting items: 66, 51, 71, 76, 58, 55, 58, 60 + Operation: new = old + 1 + Test: divisible by 13 + If true: throw to monkey 1 + If false: throw to monkey 3 + +Monkey 3: + Starting items: 79, 52, 55, 51 + Operation: new = old + 6 + Test: divisible by 3 + If true: throw to monkey 6 + If false: throw to monkey 4 + +Monkey 4: + Starting items: 69, 92 + Operation: new = old * 17 + Test: divisible by 19 + If true: throw to monkey 7 + If false: throw to monkey 5 + +Monkey 5: + Starting items: 71, 76, 73, 98, 67, 79, 99 + Operation: new = old + 8 + Test: divisible by 5 + If true: throw to monkey 0 + If false: throw to monkey 2 + +Monkey 6: + Starting items: 82, 76, 69, 69, 57 + Operation: new = old + 7 + Test: divisible by 11 + If true: throw to monkey 7 + If false: throw to monkey 4 + +Monkey 7: + Starting items: 65, 79, 86 + Operation: new = old + 5 + Test: divisible by 17 + If true: throw to monkey 5 + If false: throw to monkey 0 diff --git a/day11/solution.go b/day11/solution.go new file mode 100644 index 0000000..e1baf78 --- /dev/null +++ b/day11/solution.go @@ -0,0 +1,164 @@ +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) + } +} diff --git a/day11/test.in.txt b/day11/test.in.txt new file mode 100644 index 0000000..c04eddb --- /dev/null +++ b/day11/test.in.txt @@ -0,0 +1,27 @@ +Monkey 0: + Starting items: 79, 98 + Operation: new = old * 19 + Test: divisible by 23 + If true: throw to monkey 2 + If false: throw to monkey 3 + +Monkey 1: + Starting items: 54, 65, 75, 74 + Operation: new = old + 6 + Test: divisible by 19 + If true: throw to monkey 2 + If false: throw to monkey 0 + +Monkey 2: + Starting items: 79, 60, 97 + Operation: new = old * old + Test: divisible by 13 + If true: throw to monkey 1 + If false: throw to monkey 3 + +Monkey 3: + Starting items: 74 + Operation: new = old + 3 + Test: divisible by 17 + If true: throw to monkey 0 + If false: throw to monkey 1 \ No newline at end of file diff --git a/main.go b/main.go index 07cf341..15a6e42 100644 --- a/main.go +++ b/main.go @@ -16,6 +16,7 @@ import ( "snikolov.me/aoc2022/day08" "snikolov.me/aoc2022/day09" "snikolov.me/aoc2022/day10" + "snikolov.me/aoc2022/day11" "snikolov.me/aoc2022/utils" ) @@ -60,6 +61,7 @@ func solve(args Args, inputFileName string) { 8: &day08.Solver{}, 9: &day09.Solver{}, 10: &day10.Solver{}, + 11: &day11.Solver{}, } solver, ok := solvers[args.DayNumber] if !ok {