The Right Lang for the Job

Exploring the abbyss of non-mainstream programming languages

Advent of Code - Feeding hungry Elves, with Elisp

Surprisingly fun exercise!

Created: · Updated:

Solutions to the previous (2022) year AoC first puzzle.

Input looks like this:

123
324

2

4322
3

IOW, a list of lists of numbers. We need to sum the sublists and find the biggest sum.

First solution uses Calc: it grabs one sublist and puts it on the stack as a vector. It then reduces the vector by applying + function, leaving only the sum on the stack. This repeats in a loop until we have a stack of sums. Finally, we pack the whole stack into a single vector and select the maximum element from it. That's it!

1: (save-excursion
2:   (calc-pop (calc-stack-size))
3:   (while (progn (skip-chars-forward " \t\n") (not (eobp)))
4:     (save-selected-window
5:       (calc-grab-region (point) (progn (forward-paragraph) (point)) nil)
6:       (calc-eval "VR+" 'macro)))
7:   (calc-pack (calc-stack-size))
8:   (calc-vector-max nil)
9:   (calc-top-n 1))

However, it's INCREDIBLY slow 🙂 There are many reasons for that, I think the major one is that we're scripting an actual Calc instance and we need to wait for it to update its display after every command.

The second solution is instantaneous - it reads the whole buffer at once, splits the lines, converts textual representation to actual numbers, sums sublists, sorts them and returns the biggest element.

1: (cl-labels
2:     ((split-to-numbers (lst)
3:        (--map (->> (s-split "\n" it) (-map #'string-to-number)) lst)))
4:   (skip-chars-forward " \t\n")
5:   (let* ((input (buffer-substring-no-properties (point) (point-max)))
6:          (subs (->> input s-trim (s-split "\n\n") split-to-numbers))
7:          (sorted (cl-sort (-map #'-sum subs) #'>)))
8:     (message "Winner: %s" (car sorted))))

That's it for the last year. Let's see if I can play a little with the 2023 edition! 🙂