Advent Of Code in Clojure

Posted on December 1, 2023
aoc, clojure

Advent of Code

Another year has passed, which means it’s time to start solving Advent of Code again. Probably everyone is already familiar with AoC, but let me still remind you that this site provides you with a new coding problem every day and by solving them gets us closer to the actual Christmas.

This is third year when I use only functional programming languages to solve the AoC problems.

This time additionally to solutions of the problems in GitHub, I am going to publish explanations which will be generated automatically from code online.

All of it became possible with extensive capabilities of Clojure and Clerk library. In this note I will share how online publishing works in details.

Clojure

Clojure is a functional programming language (not exclusively) which has Lisp-like syntax. Which means that main statements and expressions will look like S-expressions.

For example to add several numbers together you can use the following expression.

(+ 1 2 3)

It may not be quite obvious why it’s beneficial, but if you would dig deeper you could see that this unblock endless possibilities for meta-programming. Your source code will look like bunch of s-expressions (which are essentially lists) and the language itself is designed to process lists efficiently and easily, hard to imagine a better setup for meta-programming (which is in general valid for all Lisp languages). We will probably cover meta-programming in Common Lisp or Clojure in the future (someday).

The Clojure itself is implemented to work under JVM which brings all pros and cons of having Java runtime. To pros you can include very rich standard library, and to cons having JVM as a runtime (just joking).

Clerk

Clerk is Clojure library which allows you to generate jupyter-like notebooks viewable through the web browser.

The main difference with jupyter is that source code is not supposed to be changed through the browser itself, only through your editor/IDE. But the idea is very similar, to get similar experience as in jupyter you can open browser next to your editor and see all the changes applied there online (using watchdog capabilities of Clerk). Moreover Clerk will be tracking which parts of the code were changed and not recomputing unchanged parts to save you compute time.

Advent Of Code

This combination of incredibly rich language and efficient visualization fits format of Advent of Code very well.

The biggest deal will be to setup auto-publishing of generated notebooks to GitHub pages. The main implementation was inspired by Elken’s approach to do that for previous Advent of Codes, kudos to him!

The first thing we need to do before publishing is to annotate the source code. Please take a look to the solution of the first day as an example.

Clerk allows you to use Markdown directly in the annotations, which I use to add comments explaining the solution itself.

;; #### Solution

;; Helper function which we will be using for testing solutions on different input files.
^{:nextjournal.clerk/visibility {:code :show :result :hide}}
(defn solve-with [filename solution]
  (with-open [rdr (io/reader filename)]
    (solution (line-seq rdr))))

Also through the visibility annotations you can specify which blocks of code (and their output) should be visible or hidden in the generated notebook.

After we added all required annotations to the solution file we will need to compile everything into the final notebook. The easiest way to do that is to define alias inside of deps.edn. This alias will be initiating compilation of all specified notebooks saving all output files into public directory.

Now we create a building hook inside of GitHub to re-generate and publish all notebooks to GitHub pages on every commit we do. All of it can be done with yml configuration of the build.

In the end all of it gives us always fresh and actual solutions of Advent Of Code 2023 (with explanations!). Isn’t it cool?

Hope it was interesting and useful to you, as always you can find solutions of all AoC 2023 problems inside of my repository on the GitHub.