Advent of Code 2024 - Day 22Monkey Market
| Problem statement | Source code | Tags: Bitwise operationsData structures
This problem pays tribute to 2022 day 11.
Part 1
The process of finding the next secret is all about bitwise operations: * 64 is equivalent to << 6, / 32 is equivalent to >> 5, and % 16777216 is equivalent to & 0xFFFFFF (because 16777216 is 2^24).
Just apply this function 2000 times to the initial secret.
Part 2
Now we have a list of diffs, where each 4-window corresponds to a gain. Naturally, we want a mapping from these 4-windows to their gains, and then we can combine the mappings from different diff lists to find the maximum.
There are some low-hanging optimizations we can do. For example, because OCaml is eager, precomputing the whole diff list is a waste when we only need 4-windows. Instead, we can compute the diff list on the fly as we call next_secret. Also, instead of using tuples as keys, we can pack the 4 numbers (which only range from -9 to 9) into a single integer using base 19. Then, when moving from one number to the next, we can update the 4-window by removing the leftmost number and adding the new number on the right.
The following spaghetti first computes the initial mapping from the first 4-window, and then iteratively updates the 4-window for the next 1996 numbers, updating the mapping if it's new.
Now I just need to combine the mappings from all initial secrets, and find the maximum gain.
This runs in slightly less than 1 second, which is okay considering we have 1500 initial secrets and 2000 iterations each. I suspect that all this mod 19 stuff is slower than bitwise operations, but if I'm to use base-32 numbers as keys instead, it requires a much larger array and worse cache performance.