Sim's blog

Advent of Code 2023

4 min read

Advent Of Code is a series of 25 2-part puzzles that must be solved programmatically. The answer of all puzzles is always an integer value.

I’ll try to make a small visualization for each exercise, so I’ll use PICO-8 (Lua) or TIC-80 (TypeScript), since both engines make it possible to quickly draw something with just a few more lines.

Day 1

A partial listing of input values, their extracted digits, and the current sum

This first day was (surprisingly?) quite easy. Looking at posts on Mastodon, it seems that many participants struggled with regexes and edge cases like oneight and twone. Since I don’t have access to regexes with PICO-8, I just checked for substrings 🤷‍♂️

And since PICO-8 can’t easily handle big numbers (signed integers can’t go over 2^15-1), I found a function that adds strings.

I wasn’t really inspired for this 1st day visualization, so I lazily printed out the values as the algo was processing them.

Day 2

Colorful snowflakes falling and stacking at the bottom of the screen

I had to cheat a bit today. Since PICO-8’s Lua is so limited in features, splitting and parsing strings can get tedious very fast; so I “manually” cleaned some spaces from the input, to make it easier to split lines.

The problem was overall simpler than yesterday’s, just a bunch of ifs and additions. Almost half of my code is dedicated to the falling snowflakes. This is a classic animation: snowflakes fall 1pixel/second, I used a sin() function to make them sway left and right. They stop falling once they reach the bottom of the screen, or if there’s already a snowflake right beneath them. Each snowflake corresponds to a red/green/blue cube from the input.

Day 3

Various colorful numbers rotating around gears

Yes I know that's not how gears work, thank you very much.

This one was hard.

Not that the problem is particularly hard — finding adjacent items on a 2D grid isn’t really complicated — but I had a bug in my first Lua script, and I absolutely could not find it. The example input was correct, the logs were correct, the different test cases were correct, and yet the end result was incorrect. I trashed the code and tried a different algorithm in TypeScript, which worked. I still don’t know what was wrong in my first draft 😑 I can only guess it was some edge case that I overlooked…

Anyway, once the 1st part was finally done, the second part went smoothly.

I also wrote a small animation that fit the “gears” theme ⚙️ I take 1 out of 10 so-called gears from part 2, report their position on the TIC-80 space, print a * surrounded by the corresponding numbers, and make those numbers rotate around the cog.

Day 4

Falling green lines slowly turning red and then disappearing

I had to cheat again by pre-cleaning the input. I’m ok with this as it’s kinda necessary with PICO-8 if you want to spend more time solving the problem than cleaning the input.

Anyway, today was quick and easy, perfect for a Monday. I had to read the second part a few times to make sure I understood it correctly. No wonder those elves have issues with that many scratch cards. Gambling addicts.

I was not really inspired for the visualization, as PICO-8 is difficult to work with big numbers. I mean, I do have ideas, but they’re kinda hard to combine with the input/output numbers from the exercises without spending hours on the execution.

Day 5

A visualization of transformations from the seed value to the location value. The 'seed' drops from state to state, leaving a trail behind it.

I was definitely not going to try PICO-8 for this one. With numbers and loops going into the billions, I would have to find an incredibly efficient way to make it work with PICO-8’s neutered CPU. Back to TypeScript.

Reading about this problem on Mastodon, it looks like a many people had run times of hours to find the solution to Part 2. It personally took me 4-5 minutes, so not bad (compared to others), but it could probably be improved.

My solution is not super elegant, but it is readable:

  • Parse all map inputs and save them as arrays of tuples in aptly-named variables (seedToSoil, soilToFertilizer, fertilizerToWater, etc.) (code)
    • The tuples are [destination source range], literally as described in the input
  • Write a function that takes a source value, an array of tuples, and returns the destination (code)
  • Sequentially call the function for all steps, feeding the resulting destination as the source for the next step (code)
  • Log the smallest final destination

For the visualization, I used the example input to illustrate the value transformations from “seed” to “location”.

1: This a subset-slash-custom version of Lua, with most of the standard lib removed.