## 2021-12-02 (permalink)

Advent of Code: [2021/02](https://adventofcode.com/2018/day/2)

It seems like the submarine can take a series of commands like `forward 1`, `down 2`, or `up 3`:

>

`forward X` increases the horizontal position by X units.

`down X` increases the depth by X units.

`up X` decreases the depth by X units.

>

Note that since you're on a submarine, down and up affect your depth, and so they have the opposite result of what you might expect.

>

[...]

>

Calculate the horizontal position and depth you would have after following the planned course. What do you get if you multiply your final horizontal position by your final depth?

OK, let's start by parsing our input, i.e. the list of instructions, into `<direction,unit>` pairs: - CL-PPCRE:REGISTER-GROUPS-BIND to parse our instructions using regexps (we could have also used SPLIT-SEQUENCE) - AS-KEYWORD to convert a string into a _keyword_, i.e. `:forward`, `:up`, and `:down`

(defun parse-instructions (data) (mapcar #'parse-instruction data)) (defun parse-instruction (string) (cl-ppcre:register-groups-bind ((#'as-keyword dir) (#'parse-integer delta)) ("(\\w+) (\\d+)" string) (cons dir delta))) (defun dir (i) (car i)) (defun delta (i) (cdr i))

Now to get the answer for part two: - Iterate over the instructions - If `:forward`, we move our horizontal position - If `:up`, we reduce our depth - If `:down`, we increase our depth - Last, we return the product of our horizontal position and depth

(defun part1 (instructions &aux (horiz 0) (depth 0)) (dolist (i instructions (* horiz depth)) (ecase (dir i) (:forward (incf horiz (delta i))) (:up (decf depth (delta i))) (:down (incf depth (delta i))))))

For part 2 instead, the `:up` and `:down` instructions seem to assume a different meaning:

In addition to horizontal position and depth, you'll also need to track a third value, aim, which also starts at 0. The commands also mean something entirely different than you first thought:

>

- `down X` increases your aim by X units.

- `up X` decreases your aim by X units.

- `forward X` does two things:

>

- It increases your horizontal position by X units.

- It increases your depth by your aim multiplied by X.

>

Again note that since you're on a submarine, down and up do the opposite of what you might expect: "down" means aiming in the positive direction.

>

[...]

>

Using this new interpretation of the commands, calculate the horizontal position and depth you would have after following the planned course. What do you get if you multiply your final horizontal position by your final depth?

Nothing fancy, let's just implement this: - Iterate over the instructions - If `:forward`, we move our horizontal position and descend / ascend based on the current aim - If `:up`, we increase our aim - If `:down`, we decrease our aim - Last, we return the product of our horizontal position and depth

(defun part2 (instructions &aux (horiz 0) (depth 0) (aim 0)) (dolist (i instructions (* horiz depth)) (ecase (dir i) (:forward (incf horiz (delta i)) (decf depth (* (delta i) aim))) (:up (incf aim (delta i))) (:down (decf aim (delta i))))))

Final plumbing:

(define-solution (2021 02) (instructions parse-instructions) (values (part1 instructions) (part2 instructions))) (define-test (2021 02) (1648020 1759818555))

And that's it:

> (time (test-run)) TEST-2021/02.. Success: 1 test, 2 checks. Evaluation took: 0.002 seconds of real time 0.002600 seconds of total run time (0.001565 user, 0.001035 system) 150.00% CPU 6,082,778 processor cycles 327,536 bytes consed

PS. My [original solution](https://topaz.github.io/paste/#XQAAAQD2AgAAAAAAAAAUGQimgx+p6PZhRh7uIO5BVe7pcMkiG6eOV22j2MYKuFs91c+ybCSTgFinLxYMDBog9+B+g/uA1iuHBXT5kPl5FbfHsjTt/UH6LeDhwtxS++LtE/cfL47hqbZilPQVUp7nWL834NkL1xo124ObhgTHG4Vaq0sDvXEWYVT61bdI9njY95YkUyYD8jeF6mdT+45tB+epQP+OgkkUyyWgSGXG3mXlBPAuGtfQ2d6F6X56fu266chYGK/yaubPY1GuajRiidCeYijfEAPoeMsgyIZcp6U4hgNM0D1M6vPzyThdMrcJtAwVid8BqQUE8ebzylpWag4uZPUQgHKdoZTgteopbArgU34gzK34OzvfXyvwL063kO+uz3rYxgePqqnFxROOQdSe0tseMzpTFeHv+lLiE+efMBoId4Ao8BsmGov79aT/8r1yLg==) parsed instructions into COMPLEX numbers (e.g. `down 4` into `#C(0 -4)`); this way, for part 1 all I had to do was summing all the deltas together; for part 2 instead, I had to check if the delta was horizontal or vertical, and adjust the aim accordingly. I figured a more readable solution would be better, hence the rewrite.