Advent of Code is a truly wonderful thing … I’ve written about it before, but 2024 was a great year. I generated some interest at work, and it got a little competitive … and drove me to successfully every day but 1 before the end of the year.
Day 21, Keypad Conumdrum was my nemesis - and was agreed to be one of the two most, if not the most, challenging examples this year. The challenge describes it well, but basically you need to type out a simple 4 digit code - such as 378A
on a keypad that looks like this …
+---+---+---+
| 7 | 8 | 9 |
+---+---+---+
| 4 | 5 | 6 |
+---+---+---+
| 1 | 2 | 3 |
+---+---+---+
| 0 | A |
+---+---+
… which would be easy, except you don’t have direct access to the keypad : instead, you have access to a robot that has an arm, that you can control. The robot has a directional keypad that looks like this …
+---+---+
| ^ | A |
+---+---+---+
| < | v | > |
+---+---+---+
The arm starts over the letter A on the numeric keypad … so to type out the code 378A
you’d need to tap an ^
to go up from the A
to the 3
; then tap the A
on the directional keypad to get the robot to press the 3
on the numeric keypad; then you’d need to tap <
twice followed by ^
twice to move the arm up to the 7
, and then tap another A
; then >
to move across to the 8
, and another A
; and finally a >
and then three v
to get down to the A
on the numeric keypad, which you then tap A
on the robot’s directional keypad to actually press it and complete the code.
Straight forward at least. Only this is Advent of Code, and it’s (a) a weekend (which Eric always makes harder) and (b) into the last week, so it’s not that simple. You don’t have access to that robot either - you have access to another one, which you can use to drive the first one, which is driving the numeric keypad.
So, to press a ‘3’ on the numeric keypad, you need to get the first robot to tap a ^
followed by a A
- which actually means you tap a sequence of v
followed by two <
and finally an A
… this drives the second robot to move the first robot’s arm left, across to the <
… and then you reverse that sequence to get back to to the A
on the first robot.
And that’s just confusing.
There’s a couple of gotchas to consider : first of all, both keypads have voids - go left twice from either starting A
and you’ll fail, so you need to avoid those. Then you need to think about moving diagonally - you can’t, so to move the first robot’s arm from 3
to 7
, you can go left twice, then up twice; up twice and then left twice; or zig-zag in two ways. Does this make a difference ?
Dear reader, it does.
I kept up with the challenges throughout December pretty closely, but day 21 part 1 took weeks, and part 2 I only finished in mid January. I made two mistakes in my original implementation : one was subtle premature optimization, and one was a classic AoC problem … you write code supporting integer numbers (up to 2 billion) which works well for a while, then you realize you need to support “long” integers, up to 9 followed by 18 zeros (2^63 - 1). So you do a quick search and replace … and don’t notice that you have code testing values to see if they are less than the maximum integer value, and I should have changed this to the maximum long value …
Oh, and part 2 takes you up to 26 robots in one long chain - no, don’t ask me why, but I did calculate that if I tap a key every second, it will take 5.3 million years to work through the sequences.
My bugs only showed up once you got 3 or 4 robots deep - and at that point, the sequences of key presses you need are simply too long to hold in memory, making it impossible to debug. I only solved it by starting again from scratch in a different language (Python) and suddenly noticing I was getting very slightly different results early on …