Dec 29, 2017
Advent of Code is a series of daily programming puzzles created by Eric Wastl and published daily in the month of December. As of yesterday, I completed all of them! Here are a few reflections:
I no longer write Clojure as part of my job, and even then I would have considered myself somewhere between Beginner and Advanced Beginner, so these puzzles were a nice opportunity to get back into it. In the end:
loop
/recur
, but I apologize for nothing.interleave
, iterate
, partition
to my toolboxcomp
and partial
are the big three that come to mind.frequencies
and take-last
after I’d reimplemented them.
I wonder: are there Clojure docs which just highlight functions which operate on sequences?
The main clojure.core docs are tough to scan.Generating a radial grid of numbers in Day 3 was a lot of fun:
17 16 15 14 13
18 5 4 3 12
19 6 1 2 11
20 7 8 9 10
21 22 23---> ...
Oooh, strategy!
Writing interpreters on Days 8, 9, 16, 18, and 23 was fun.
Day 21 was really, really challenging for me.
I was pleased with being able to project “natural” matrix coordinates (i.e. (n / 2, n / 2)
is the middle) to “planar” coordinates (i.e. (0, 0)
is the middle) to simplify and generalize rotations/flips.
But figuring out how to write a function that would take a whole matrix, split it into submatrices, enhance those submatrices, and the re-assemble the matrix took a lot of squinting at the problem and some judicious use of partition
and interleave
.
The resulting code is very much write-once, read-never and I’m still not sure what to name most of the intermediate representations of matrix elements.
The second part of Day 23 was genuinely new for me, in that it required analyzing an assembly-like language by hand, and could not be solved by writing an interpreter for the assembly (at least, I was not able to write one that would produce a solution in a reasonable amount of time!). I felt elated when I figured out what the horribly inefficient assembly was trying to do.
My goal for next year is to be able to do these puzzles in a language with a static type checker – one of Rust, Haskell, PureScript, or Scala.