For all those little papers scattered across your desk
We begin the Advent of Code journey, commit by commit…
I’ve seen Advent of Code for the last few years, but never participated. This year, after a challenge from a friend to compete on a private leaderboard, I decided not to win, by learning a new language for the challenges.
So I began my journey with SML/NJ on Day 1.
I’m too used to shell scripts, so I tried to write the SML code like a script: give me your input on stdin, and I’ll compute the output.
The code works, though.
It’s not even very interesting: we map
the fuel
calculation over all the
masses, and sum
it.
I did have to learn how to parse the input with SML. Fortunately it wasn’t
terribly difficult. The function String.tokens
tokenizes a string s
according to a function f
; effectively, it returns a string list
where each
item in the list was separated by a character c
such that f c = True
.
Examples:
- String.tokens (fn c => c = #" ") "a b c";
val it = ["a","b","c"] : string list
- String.tokens Char.isSpace "a b c";
val it = ["a","b","c"] : string list
- String.tokens (fn c => c = #".") "a.b.c.";
val it = ["a","b","c"] : string list
And now I learn to adjust to the lisp/sml/prolog-style of program.
I supply the source files, you load them up in an interpreter, and code the query that gives you the answer.
This actually cleans up the code quite a bit.
Well, that and point-free style. It can be harder to read sometimes, but the idea is that
fun foo s = map (fn x => ...) s
is equivalent to
val foo = map (fn x => ...)
modulo possible type constraints. This is because of a little currying in most standard library functions: it is possible to partially apply functions, and get functions back as a result.
This goes nicely with the composition operator o
(which my syntax files
conceal to ←
). I can chain functions together as long as the outputs match
the inputs, and build up a single function value to apply all at once to an
input. (The reality is probably that it’s one big series of lambdas or closures
or something, so it’s probably not super efficient for the runtime system, but
it sure is fun to read and write).
For fun, I did this one in awk(1)
as well. It was straightforward, to say the
least.
If that isn’t the strangest “short” commit name… I didn’t notice that until now.
For Part 2, I had to adjust my fuel calculation a bit. Then it was off to the races.
Deciding the types for values and then making them match was slightly trickier
in this one because of the need to toggle between real
s and int
s.