blob: b326a88e941864b1940a262de16243005393dc77 (
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
|
(ql:quickload '(fiveam cl-ppcre))
(defparameter eg-input "467..114..
...*......
..35..633.
......#...
617*......
.....+.58.
..592.....
......755.
...$.*....
.664.598..")
(defun inbounds (row-max col-max)
(lambda (cell)
(destructuring-bind (row . col) cell
(and (<= 0 row row-max)
(<= 0 col col-max)))))
(defun in-line-numbers (line symbol-pos)
(loop for (num-start num-end) on (cl-ppcre:all-matches "\\d+" line) by #'cddr
when (<= (1- num-start) symbol-pos num-end)
collect (parse-integer (subseq line num-start num-end))))
(defun adjacent-numbers (rows row limits symbol-pos)
(loop for y in (list (1- row) row (1+ row))
when (funcall limits (cons y symbol-pos))
nconc (in-line-numbers (aref rows y) symbol-pos)))
(defun solver (lines symbol-regex reducer)
(let* ((rows (make-array (length lines) :initial-contents lines
:adjustable t))
(limits (inbounds (1- (length lines))
(1- (length (car lines))))))
(loop for row below (length lines)
sum (loop for (start _end) on (cl-ppcre:all-matches symbol-regex (aref rows row)) by #'cddr
sum (funcall reducer (adjacent-numbers rows row limits start))))))
(defun solver1 (lines)
(solver lines "[^.\\d]" (lambda (numbers) (apply #'+ numbers))))
(defun solver2 (lines)
(solver lines "\\*"
(lambda (ratios)
(if (= 2 (length ratios))
(* (car ratios) (cadr ratios))
0))))
(fiveam:test solutions
(fiveam:is (= 4361 (solver1 (uiop:split-string eg-input :separator '(#\Newline)))))
(fiveam:is (= 467835 (solver2 (uiop:split-string eg-input :separator '(#\Newline)))))
(fiveam:is (= 531561 (solver1 (uiop:read-file-lines "input"))))
(fiveam:is (= 83279367(solver2 (uiop:read-file-lines "input")))))
|