AoC 2022 D11: Monkey in the Middle
| Problem statement | Source code | Tags: Modular arithmetic
← Previous Back to AoC Index Next →
Part 1 is straightforward to simulate, and has the exact same idea as part 2 anyway, so I describe my part 2 solution here. Because the numbers get large, we need a way to keep them manageable. The key observation is that we don't care about the actual numbers: all tests are testing divisibility, so only the remainders matter. If for monkeys , we have divisors , then keeping track of the remainder modulo is sufficient to determine the outcome of all tests. (To be fully robust we should probably use lcm instead of multiplication, but it turned out that all are prime numbers.) Because modular arithmetic is closed under addition and multiplication, nothing else changes.
I parse the monkeys into the following record type:
(old * old is represented as (^ 2); all other operations are either addition or multiplication by a constant.)
The main function just calls the passAround function, which runs the given number of rounds. The reducer is used to reduce the worry level after each inspection, which is ```divreliefmoddivisor``. In part 1,reliefis 3, and in part 2,reliefis 1. Each time we fold over the monkeys and update themonkeysmap by passing items around, as inmonkeyDoRound`.
In monkeyDoRound, the items get emptied and appended to the target monkeys' item lists. The inspectTimes is incremented by the number of items inspected.
The target determination is done by the monkeyInspect function, which applies the operation, reduces the worry level, and checks the test condition.
Other than the modular arithmetic, everything else is straightforward simulation, which is slightly awkward in Haskell, but not too bad.