I am doing Advent of Code again this year!

My code is available if your interested. I'm intending to use multiple languages this year (last year it was all Rust all the time).

edit I finished all 25 days! In order of how much I used each language, it was Python, Rust, TCL, C, Forth.

I found this year to be easier overall then last year- there were some days I had trouble with for sure, but overall I didn't spend nearly as much time solving this year's puzzles. I ended up implementing some matching code, a couple simple constraint propagation systems, infix expression parsing, normal stuff.

Language Notes

I found that I wanted to use Rust when there was something to model- directions, instructions, etc. Algebraic data feel very natural to me, and decompose problems into smaller concepts each of which can be decomposed further until they are trivial. I missed this in Python and TCL this year, and I refuse to encode sum types in OOP in Python.

For Python, I used it when there was a lot of datastructure manipulation (lists of dictionaries of sets of lists...). Python ended up being fast enough for my solutions, with occasional optimizations (mostly using sets or dicts instead of lists). Python is quick to set things up, easy to manipulate structures, and does not help you if you can't remember what your structures should look like.

For TCL, I just had some with it. It has some nice built-in functions, it is sometimes trivially able to parse puzzle input due to the way it handles strings, and I sometimes enjoy writing in its style where each action is a nicely composable command. Its doesn't seem as nice for complex data structures, and certainly not for modeling, but its got its own sweet spot.


SPOLIERS there are some minor spoilers to certain days in this section!

Day 1

I had some thoughts about the different language implementations.

In terms of lines of code (language: part 1/part 2):

* Python: 10/11
* TCL: 12/16
* Forth: 25/28
* Rust: 26/28
* C: 45/50

I didn't do any extensive performance analysis, but I found that all languages except C where around 200 ms, and C was about 10 times faster.

This is a little surprising, since Rust should be about as fast as C. I added some timers and found that while the program itself is very fast (~2ms actual runtime), the Rust program seems to load up slowly (perhaps linking)? I don't know the full story there, except that the actual calculation is not what is taking the time here.

8 Handheld Halting

I was excited to see an instruction set, and I hoped that this would be a running thing throughout the rest of the days. I was a little disappointed that this didn't turn out to be true. Not a big deal, but this was a fun part of 2019's puzzles, and I believe other years as well.

20 Jigsaw

I thought day 20 was perhaps the most inspired puzzle this year. It was fun to manipulate the images and stitch them together. I probably spent the most time to get this to happen, and the constraint solving required some optimization, and overall I had fun with the puzzle.

24 Lobby Layout - My Favorite Day

I think my favorite day was the hex tile puzzle. I considered actually writing a hex tile data structure and all that, but ended up doing something a little bit interesting.

I know just enough abstract algebra that I was able to determine some laws that movements in a hex grid follow (although I didn't think of all the laws in the first pass). It ends up being an abelian group as each move can be undone, and the order of moves doesn't matter. With these laws I was able to reduce each set of directions into a 'normal form' that is independent of the order of directions, and removes redundencies like east then west, etc.

This did work, but it was more awkward then necessary. For part 2 I realized that the hex grid positions could be represented as a pair of integers, and directions could be translated into an offset for each number in the pair, so that a movement is just a component-wise sum, and a series of movements can be turned into a position with the 'reduce' (aka fold) function.

The actual puzzle requires a Conway's game of life style ruleset, so I just represented the black tiles as an integer pair, and found adjecent tiles by applying the 6 directions (translated into offsets to this pair). This turned out to be quite easy, and the whole solution is 59 lines (according to CLOC).

Ultimately this made me feel clever, so I remembered this as a good day.

Image Viewer

The one other thing to note is that in preparation for AoC this year I wrote a little image viewer for pgm images in TCL, which uses Tk to display frames at a given rate. The idea is that whatever language I'm using, I can output a pgm image with multiple frames visualizing something I might want to see, and then view them with my TCL program. It was fairly straightforward to write, and runs with a simple tclkit making it very portable and reproducible.

edit I never even used this program! I ended up adapting it for use at work, but there was no processor to develop or game to play this year! Oh well, I enjoyed writing the viewer anyway.

Next Year

A thought I had for next year would be to consider using libraries for things like language grammars or constraint solving. Its fun to implement them oneself, but if its something I've done a few times before, it would be interesting to learn a new library or how to express a problem in constraints as a way to keep things interesting.