|
5 | 5 | strings) |
6 | 6 | #+#:excluded (parse-input) |
7 | 7 |
|
| 8 | + |
8 | 9 | (defparameter *num-keypad* (make-array (list 4 3) :initial-contents '("789" |
9 | 10 | "456" |
10 | 11 | "123" |
|
18 | 19 | (dotimes (j cols) |
19 | 20 | (if (char= (aref keypad i j) char) |
20 | 21 | (return-from coords-for (list i j))))))) |
21 | | -#+#:excluded (coords-for *num-keypad* #\A) |
22 | | -#+#:excluded (coords-for *num-keypad* #\0) |
23 | | -#+#:excluded (coords-for *num-keypad* #\1) |
24 | 22 |
|
25 | 23 | (defun button-at (keypad row col) |
26 | 24 | (when (array-in-bounds-p keypad row col) |
27 | 25 | (let1 b (aref keypad row col) |
28 | 26 | (when (char/= b #\Space) |
29 | 27 | b)))) |
30 | | -#+#:excluded (button-at *num-keypad* 3 2) |
31 | | -#+#:excluded (button-at *num-keypad* 3 1) |
32 | | -#+#:excluded (button-at *num-keypad* 3 0) |
33 | | -#+#:excluded (button-at *num-keypad* 4 0) |
34 | 28 |
|
35 | 29 | (defun move-to (keypad start end) |
36 | 30 | (let ((hq (make-hq :key #'car)) |
|
53 | 47 | (when (button-at keypad ni nj) |
54 | 48 | (assert (char/= (aref keypad ni nj) #\Space)) |
55 | 49 | (hq-insert hq (list (1+ cost) (list ni nj) (cons ch path))))))))))))) |
56 | | -#+#:excluded (move-to *num-keypad* (coords-for *num-keypad* #\A) (coords-for *num-keypad* #\A)) |
57 | | -#+#:excluded (move-to *num-keypad* (coords-for *num-keypad* #\A) (coords-for *num-keypad* #\0)) |
58 | | -#+#:excluded (move-to *num-keypad* (coords-for *num-keypad* #\A) (coords-for *num-keypad* #\2)) |
| 50 | + |
59 | 51 |
|
60 | 52 | (defun robot (keypad) (list keypad (coords-for keypad #\A))) |
61 | 53 | (defaccessor keypad (robot) (accesses (car robot))) |
62 | 54 | (defaccessor pos (robot) (accesses (cadr robot))) |
63 | 55 |
|
64 | | -(defun type-code (robot code) |
65 | | - (let1 keypad (keypad robot) |
66 | | - (recursively ((code (coerce code 'list))) |
67 | | - (cond ((zerop (length code)) (list "")) |
68 | | - (t (let1 to-ch (move-to keypad (pos robot) (coords-for keypad (car code))) |
69 | | - (assert to-ch () "A path to ~A should exist" (car code)) |
70 | | - (setf (pos robot) (coords-for keypad (car code))) |
71 | | - (let1 from-ch-to-end (recur (cdr code)) |
72 | | - (looping |
73 | | - (doseq (seq1 to-ch) |
74 | | - (doseq (seq2 from-ch-to-end) |
75 | | - (collect! (spr seq1 #\A seq2)))))))))))) |
76 | | - |
77 | | -; robots always seem to start and end at A, so we might as well recreate them every time |
78 | | -(defun shortest-path-to-code (code3) |
79 | | - (~> (looping |
80 | | - (dolist (code2 (type-code (robot *num-keypad*) code3)) |
81 | | - (dolist (code1 (type-code (robot *dir-keypad*) code2)) |
82 | | - (dolist (code (type-code (robot *dir-keypad*) code1)) |
83 | | - (collect! code))))) |
84 | | - (sort ~ #'< :key #'length) |
85 | | - first |
86 | | - length)) |
87 | | -#+#:excluded (shortest-path-to-code "029A") |
88 | | -#+#:excluded (shortest-path-to-code "0") |
89 | | - |
90 | | -(defun complexity (code3) |
91 | | - (* (dbg (shortest-path-to-code code3)) |
92 | | - (dbg (first (extract-integers code3))))) |
93 | | -#+#:excluded (complexity "029A") |
94 | | -#+#:excluded (complexity "980A") |
95 | | -#+#:excluded (complexity "179A") |
96 | | -#+#:excluded (complexity "456A") |
97 | | -#+#:excluded (complexity "379A") |
98 | | - |
99 | | -#; |
100 | | -#+#:excluded (reduce #'+ (parse-input) :key #'complexity) |
101 | | -176870 |
102 | | - |
103 | | -(defun type-code (code &rest robots) |
| 56 | +(defun min-steps-for-code (code robots) |
104 | 57 | (let1 memo (make-hash-table :test 'equal) |
105 | 58 | (recursively ((code code) |
106 | 59 | (robots robots)) |
107 | | - |
108 | 60 | (memoizing (memo code robots) |
109 | 61 | (cond ((null robots) (length code)) |
110 | 62 | (t (destructuring-bind (robot . robots) robots |
|
116 | 68 | (looping |
117 | 69 | (dolist (code1 codes1) |
118 | 70 | (minimize! (recur (spr code1 #\A) robots))))))))))))))) |
119 | | -#+#:excluded (type-code "029A" (robot *num-keypad*) (robot *dir-keypad*) (robot *dir-keypad*)) |
120 | 71 |
|
121 | 72 | (defun complexity (code robots) |
122 | | - (* (dbg (apply 'type-code code robots)) |
123 | | - (dbg (first (extract-integers code))))) |
| 73 | + (* (min-steps-for-code code robots) |
| 74 | + (~> code extract-integers first))) |
| 75 | + |
124 | 76 |
|
125 | | -(let1 robots (list* (robot *num-keypad*) |
126 | | - (looping (repeat 2 (collect! (robot *dir-keypad*))))) |
127 | | - (reduce #'+ (parse-input) :key [complexity _ robots])) |
| 77 | +(define-solution (2024 21) (strings) |
| 78 | + (flet ((mkrobots (n) |
| 79 | + (list* (robot *num-keypad*) |
| 80 | + (looping (repeat n (collect! (robot *dir-keypad*))))))) |
| 81 | + (values (let1 rbts (mkrobots 2) |
| 82 | + (reduce #'+ strings :key [complexity _ rbts])) |
| 83 | + (let1 rbts (mkrobots 25) |
| 84 | + (reduce #'+ strings :key [complexity _ rbts]))))) |
128 | 85 |
|
129 | | -(let1 robots (list* (robot *num-keypad*) |
130 | | - (looping (repeat 25 (collect! (robot *dir-keypad*))))) |
131 | | - (reduce #'+ (parse-input) :key [complexity _ robots])) |
| 86 | +(define-test (2024 21) (176870 223902935165512)) |
0 commit comments