|
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