blob: 72abf4309b270351933f2c8e8c6b56ecc9474f1b (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
|
;;8:57
;;10:26 part1
;;10:53 part2
(ql:quickload '(fiveam arrows alexandria))
(defun in-bounds (field ray)
(destructuring-bind (maxrow maxcol) (array-dimensions field)
(destructuring-bind (dir row col) ray
(declare (ignorable dir))
(and (< -1 row maxrow)
(< -1 col maxcol)))))
(defun next-direction (ray)
(destructuring-bind (dir row col) ray
(cons dir
(ecase dir
(up (list (1- row) col))
(lf (list row (1- col)))
(dw (list (1+ row) col))
(rt (list row (1+ col)))))))
(defun mirror-bs (ray)
(destructuring-bind (dir row col) ray
(arrows:->
(ecase dir
(up 'lf)
(lf 'up)
(dw 'rt)
(rt 'dw))
(list row col)
(list))))
(defun mirror-fs (ray)
(destructuring-bind (dir row col) ray
(arrows:->
(ecase dir
(up 'rt)
(lf 'dw)
(dw 'lf)
(rt 'up))
(list row col)
(list))))
(defun split-v (ray)
(destructuring-bind (dir row col) ray
(ecase dir
((up dw) (list ray))
((lf rt) (list (list 'up row col) (list 'dw row col)) ))))
(defun split-h (ray)
(destructuring-bind (dir row col) ray
(ecase dir
((lf rt) (list ray))
((up dw) (list (list 'lf row col) (list 'rt row col)) ))))
(defun energized-p (energized ray)
(destructuring-bind (dir row col) ray
(find dir (gethash (cons row col) energized))))
(defun action (field ray energized)
(destructuring-bind (dir row col) ray
(unless (find dir (gethash (cons row col) energized)))
(arrows:->>
(ecase (aref field row col)
(#\. (list ray))
(#\\ (mirror-bs ray))
(#\/ (mirror-fs ray))
(#\| (split-v ray))
(#\- (split-h ray)))
(mapcar #'next-direction)
(remove-if-not (alexandria:curry #'in-bounds field))
(remove-if (alexandria:curry #'energized-p energized)))))
(defun advancer (field rays energized)
(loop for (dir row col) in rays do
(push dir (gethash (cons row col) energized)))
(if (null rays)
energized
(let ((next-moves (mapcan (lambda (ray) (action field ray energized)) rays)))
;; (format t "~d Next: ~a~%" maxi next-moves)
(advancer field next-moves energized))))
(defun boundary-rays (field)
(destructuring-bind (maxrow maxcol) (array-dimensions field)
(append
(loop for i below maxrow collect (list 'rt i 0))
(loop for i below maxrow collect (list 'lf i (1- maxcol)))
(loop for i below maxcol collect (list 'dw 0 i))
(loop for i below maxcol collect (list 'up (1- maxrow) i)))))
(defun solver (field)
(lambda (start)
(hash-table-count
(advancer field (list start)
(make-hash-table :test #'equal)))))
(defun solution (input &optional (starter (constantly (list (list 'rt 0 0)))))
(let* ((rows (length input))
(field
(make-array (list rows (length (car input))) :initial-contents input)))
(reduce #'max (funcall starter field) :key (solver field))))
(fiveam:test solutions
(fiveam:is (= 46 (solution (uiop:read-file-lines "eg-in"))))
(fiveam:is (= 7996 (solution (uiop:read-file-lines "input"))))
(fiveam:is (= 51 (solution (uiop:read-file-lines "eg-in") #'boundary-rays)))
(fiveam:is (= 8239 (solution (uiop:read-file-lines "input") #'boundary-rays))))
|