]>
Commit | Line | Data |
---|---|---|
1 | (asdf:load-system :adventofcode2020) | |
2 | (in-package #:adventofcode2020) | |
3 | (named-readtables:in-readtable :adventofcode2020) | |
4 | ||
5 | (defun parse-action (str) | |
6 | (cl-ppcre:register-groups-bind | |
7 | ((λ(char _ 0) action) (#'parse-integer scalar)) ("([NSEWLRF])([0-9]+)" str) | |
8 | (list action scalar))) | |
9 | ||
10 | (defstruct ship | |
11 | (heading #\E) | |
12 | (ns-coord 0) | |
13 | (ew-coord 0) | |
14 | (waypoint-ns 1) | |
15 | (waypoint-ew 10)) | |
16 | ||
17 | (defun apply-turn-heading (heading degree) | |
18 | (let ((directions #(#\N #\E #\S #\W)) | |
19 | (heading-delta (/ degree 90))) | |
20 | (-<> | |
21 | (position heading directions) | |
22 | (+ heading-delta) | |
23 | (mod 4) | |
24 | (aref directions <>)))) | |
25 | ||
26 | (defun apply-turn-space (x y degree) | |
27 | (if (= degree 0) (list x y) | |
28 | (destructuring-bind (x y) (apply-turn-space x y (- degree (* (signum degree) 90))) | |
29 | (if (> degree 0) | |
30 | (list y (* -1 x)) | |
31 | (list (* -1 y) x))))) | |
32 | ||
33 | (defun apply-action-ship (ship act-pair) | |
34 | (destructuring-bind (action scalar) act-pair | |
35 | (let ((new-ship (copy-structure ship))) | |
36 | (case action | |
37 | (#\N (setf (ship-ns-coord new-ship) (+ (ship-ns-coord ship) scalar))) | |
38 | (#\S (setf (ship-ns-coord new-ship) (- (ship-ns-coord ship) scalar))) | |
39 | (#\E (setf (ship-ew-coord new-ship) (+ (ship-ew-coord ship) scalar))) | |
40 | (#\W (setf (ship-ew-coord new-ship) (- (ship-ew-coord ship) scalar))) | |
41 | (#\L (setf (ship-heading new-ship) (apply-turn-heading (ship-heading ship) (* -1 scalar)))) | |
42 | (#\R (setf (ship-heading new-ship) (apply-turn-heading (ship-heading ship) (* +1 scalar)))) | |
43 | (#\F (setf new-ship (apply-action-ship new-ship (list (ship-heading ship) scalar))))) | |
44 | new-ship))) | |
45 | ||
46 | (defun apply-action-waypoint (ship act-pair) | |
47 | (destructuring-bind (action scalar) act-pair | |
48 | (let ((new-ship (copy-structure ship))) | |
49 | (case action | |
50 | (#\N (setf (ship-waypoint-ns new-ship) (+ (ship-waypoint-ns ship) scalar))) | |
51 | (#\S (setf (ship-waypoint-ns new-ship) (- (ship-waypoint-ns ship) scalar))) | |
52 | (#\E (setf (ship-waypoint-ew new-ship) (+ (ship-waypoint-ew ship) scalar))) | |
53 | (#\W (setf (ship-waypoint-ew new-ship) (- (ship-waypoint-ew ship) scalar))) | |
54 | (#\L (destructuring-bind (x y) (apply-turn-space (ship-waypoint-ew ship) (ship-waypoint-ns ship) (* -1 scalar)) | |
55 | (setf (ship-waypoint-ew new-ship) x) | |
56 | (setf (ship-waypoint-ns new-ship) y))) | |
57 | (#\R (destructuring-bind (x y) (apply-turn-space (ship-waypoint-ew ship) (ship-waypoint-ns ship) (* +1 scalar)) | |
58 | (setf (ship-waypoint-ew new-ship) x) | |
59 | (setf (ship-waypoint-ns new-ship) y))) | |
60 | (#\F (setf (ship-ns-coord new-ship) (+ (ship-ns-coord ship) (* scalar (ship-waypoint-ns ship)))) | |
61 | (setf (ship-ew-coord new-ship) (+ (ship-ew-coord ship) (* scalar (ship-waypoint-ew ship)))))) | |
62 | new-ship))) | |
63 | ||
64 | ||
65 | (day 12 input | |
66 | (let ((actions (mapcar #'parse-action (list-from input)))) | |
67 | (part1 (let ((final-ship (reduce #'apply-action-ship actions :initial-value (make-ship)))) | |
68 | (manhattan-distance (list 0 0) (list (ship-ew-coord final-ship) | |
69 | (ship-ns-coord final-ship))))) | |
70 | (part2 (let ((final-ship (reduce #'apply-action-waypoint actions :initial-value (make-ship)))) | |
71 | (manhattan-distance (list 0 0) (list (ship-ew-coord final-ship) | |
72 | (ship-ns-coord final-ship))))))) | |
73 | ||
74 | (def-suite day12) | |
75 | (in-suite day12) | |
76 | ||
77 | (defvar *simple-actions* | |
78 | '("F10" "N3" "F7" "R90" "F11")) | |
79 | ||
80 | (test apply-turns-heading | |
81 | (is (equal #\S (apply-turn-heading #\E 90))) | |
82 | (is (equal #\W (apply-turn-heading #\E 180))) | |
83 | (is (equal #\N (apply-turn-heading #\E 270))) | |
84 | (is (equal #\N (apply-turn-heading #\E -90))) | |
85 | (is (equal #\W (apply-turn-heading #\E -180)))) | |
86 | ||
87 | (test apply-actions-ship | |
88 | (is (equalp | |
89 | (make-ship :heading #\S :ns-coord -8 :ew-coord 17) | |
90 | (reduce #'apply-action-ship (mapcar #'parse-action *simple-actions*) | |
91 | :initial-value (make-ship))))) | |
92 | ||
93 | (run! 'day12) |