Back to blog
Jan 03, 2025
5 min read

Advent of Code - Day 21, 2024

Keypad Conundrum.

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 …