This was my first time participating in an Advent of Code challenge, so I didn’t have a huge frame of reference of what to expect. I think in general some days were more time-consuming than I had anticipated, but it wasn’t without reward. There was considerable variety in the sorts of problems presented, which helped to maintain interest, and many of them presented opportunities to apply knowledge/concepts that I previously had only learned about.

Rust’s “panic on overflow” feature (when in debug builds) proved quite useful for finding out when I needed to increase the size of integer fields.

Lows

  • Some of the days had a Question 2 that differed significantly in what was being asked for in comparison to the Question 1 for that day, sometimes going as far to render irrelevant (for the sake of Question 2) any work past just parsing the input into a meaningful data structure. If the first question was super quick, this wasn’t always an issue, but otherwise it could considerably increase the amount of time required (for me) to get all the stars for the day. An example of this was Day 15, which only required iterating over a sorted list once for Question 1 then implementing a quadtree for Question 2.
  • Day 16: Question 2 was quite difficult and taxing. Day 16 was a graph traversal maximization problem, in loose terms. It didn’t necessarily belong to the category described in the bullet above, but my approach to Question 1 (which simplified the graph due to there only being one actor present) wasn’t really compatible with Question 2 (which asked the same question, but with two actors present). I spent a couple days on an attempt to modify my approach to Question 1 for Question 2, only to end up with code that did not scale sufficiently well with the non-example input: I let the program run while I was sleeping, and the process had been killed when I woke up. Whether this was due to a failed allocation due to requesting too much memory or some other reason is unknown. I took a day-long break from Advent after this and returned by doing some internet searching on the problem. I found that for some participant’s input, it was sufficient to find a local maximum obtained by trimming the graph after the first actor’s path is found. This didn’t feel great, as I don’t believe it’s a fully correct solution. This approach worked for my input, and I didn’t want to not finish the challenge due to this one question, so I proceeded after receiving this somewhat ill-gotten second star.
  • This isn’t as much of a “low” as the other two, by which I mean I still enjoyed the question in question. Day 22: Question 2 required finding coincident edge pairs from a flattened cube net, which was a surprisingly difficult problem to solve. My initial approach to this was pretty gross, but I think the approach I ended up with is quite clean. As of the time writing this, Day 22 has the lowest percentage of two-star completion this year (out of the days with two questions), and I think that speaks to the difficulty of this question.

Highs

  • Day 10 (generating a “CRT” output signal from a sequence of “assembly instructions”) was super cool. Question 1 was kind of irrelevant, but the payoff of Question 2 made it worth it. Having spent some time working with VGA in VHDL in college, this was a really neat throwback to that.
  • Day 11: Question 2 required application of a concept I only knew about from watching YouTube videos about cryptography. Having an opportunity to apply this knowledge was quite satisfactory.
  • Day 13 called for implementing a specific ordering function for a recursive data structure. The specific problem asked didn’t take too long, but this day provided a good opportunity to review the relationships between the traits in std::cmp in a specific context.
  • Day 20 seemed to call for a linked list (of sorts). Self-referential structs are more complicated in Rust than some other languages as a trade-off for its data safety, so this was a revealing exercise. As I generally try to avoid unnecessary dynamic allocation, I tackled this by having individual list elements store an index for the Vec that contained the elements, which also simplified the second question for this day.
  • Day 21 was the perfect example of taking a straight-forward Question 1 (solve an algebraic expression binary tree for the value at the root node) and “turning it on its head” for Question 2 (solve an algebraic expression binary tree for the value at a leaf node). This was very satisfying.

Repository

Details

  • Language: Rust