Advent of code at Technolution

Advent of Code 2024

Tijs’ experience on day 21

Advent of Code 2024 is over: 25 days, each with a new puzzle. Day 21 was the ultimate brain teaser. But the real challenge for Tijs this year? Solving puzzles while managing life with a toddler. Tijs describes how he juggles family life with his urge to compete in Advent of Code this year.

How did you solve this puzzle?

We’re heading to my toddler’s grandparents’ house to celebrate Christmas. I used to prefer to wake up as late as possible, but ever since I became a father, that custom has gone to ruin. We now typically wake up at 6:30 in the morning. Being somewhat accustomed to this new biorhythm, I might finally try to compete for the Advent of Code leaderboard, which opens up at 6 a.m. in my time zone.

Unfortunately, my partner still has to entertain our son several times during the night, and therefore doesn’t look kindly on me taking the morning off to help some virtual elves save Christmas. So in the end, I still wind up competing for the first star at 8:30 during my morning commute, just as in previous years. Luckily, we have a private leaderboard at Technolution that only reports stars, and not the time it took one to obtain them. The Advent of Code API does export the timestamps though, so after hacking up a script I can now confirm that we have at least two colleagues who have no kids!

No commute today

During the first days of Advent of Code, my thirty-minute train ride is sufficient to mess with my phone and laptop to set up an internet connection, and solve two stars, but we are currently at day 21 and I’m falling behind. My one-and-a-half-year-old pitches in with my stress levels this morning, and feels the urge to assist in cleaning up the breakfast table. Unfortunately, he starts by removing the placemats, even before he gets around to the two glasses of water still sitting on them.

Worse yet for my coding desires, we have to take the car to get to my parents, and I am driving. No programming during commute today. It feels a bit like cheating, but I tell myself that it’s okay to read the assignment for part 1, so that I can overthink it a bit while driving. Little do I know that day 21 turns out to be the hardest day of this year’s Advent of Code calendar.

Push buttons to push buttons

My thought process works like this: “So I push buttons on a keypad that controls a robot arm that pushes buttons on a keypad that controls a robot arm that pushes buttons on a keypad that controls a robot arm, which eventually pushes buttons on the final keypad.” Not having pen and paper behind the wheel means that I have to make sense of this in my head. After the entire two-hour trip, I can only conclude that I either have to start searching from the first keypad to the last, or from the last to the first. But I’m not quite sure which direction is better.

When we finally reach my parents, I suppress the urge to start coding directly, and waste an entire afternoon on social talk. I check our local Advent of Code chat room, and a colleague mentions that they have spent the entire afternoon solving part 2. I don’t know if this means that I should be jealous of them having the time to spare, or that I should be outright frightened about how to solve this beast.

Finally, ready to code!

In the evening, I sneak out with my laptop, and eventually manage to come up with one function that does a breadth-first search through both keypads. This will never pass a code review during my day job at Technolution, but I still feel some sense of accomplishment.

@functools.cache
def calc_dist(level, a, b):
    if level <= 0:
        return 1
    pad = get_pad(level)
    ai, aj = find_pos(pad, a)
    q = PriorityQueue()
    q.put((0, ai, aj, "A"))
    visited = {}
    options = []
    while not q.empty():
        cost, i, j, prev = q.get()
        if (i, j, prev) in visited:
            if visited[(i, j, prev)] < cost:
                continue
        visited[(i, j, prev)] = cost
        if pad[i][j] == b:
            options.append(cost + calc_dist(level - 1, prev, "A"))
        for di, dj, d in [(0, 1, ">"), (0, -1, "<"), (1, 0, "v"), (-1, 0, "^")]:
            ni, nj = i + di, j + dj
            if 0 <= ni < len(pad) and 0 <= nj < len(pad[ni]):
                if pad[ni][nj] != " ":
                    dist = calc_dist(level - 1, prev, d)
                    q.put((cost + dist, ni, nj, d))
    return min(options)
  

Advent of Code

Jan's solution for day 5

We are Technolution

And this is my implementation

This is how I solved the puzzle