blob: aedf0786b4d0130340822cdb305e212db21dec3d (
plain) (
blame)
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
108
109
110
111
112
113
114
115
116
117
118
119
|
(defun input-lines (f)
(with-open-file (s f)
(loop for line = (read-line s nil 'eof)
until (eq line 'eof)
collect line)))
(defun is-symbol (s i)
(and (>= i 0)
(< i (length s))
(let ((c (aref s i)))
(and (not (digit-char-p c))
(not (equal #\. c))))))
(defun has-symbol (s j k)
(and s
(loop for i from j upto k
if (is-symbol s i)
return t)))
(defun is-valid-number (prv cur nxt j k)
(or (is-symbol cur (1- j))
(is-symbol cur k)
(has-symbol prv (1- j) k)
(has-symbol nxt (1- j) k)))
(defun sum-valid-numbers-line (prv cur nxt &key (start 0) (acc 0))
(if (= start (length cur))
acc
(multiple-value-bind (n end)
(parse-integer cur :start start :junk-allowed t)
(if (and n (digit-char-p (aref cur start)))
(if (is-valid-number prv cur nxt start end)
(sum-valid-numbers-line prv cur nxt :start end :acc (+ acc n))
(sum-valid-numbers-line prv cur nxt :start end :acc acc))
(sum-valid-numbers-line prv cur nxt :start (1+ start) :acc acc)))))
(defun sum-valid-numbers (rem &key prv (acc 0))
(if rem
(sum-valid-numbers (cdr rem)
:prv (car rem)
:acc (+ acc (sum-valid-numbers-line prv (car rem) (cadr rem))))
acc))
(defun solve1(f)
(let ((lines (input-lines f)))
(sum-valid-numbers lines)))
(defstruct mynumber
num
loweri
lowerj
upperi
upperj)
(defstruct mysymbol
symb
i
j)
(defun collect-numbers (lines)
(labels ((collect-numbers-line (line i start acc)
(if (< start (length line))
(if (digit-char-p (aref line start))
(multiple-value-bind (n end)
(parse-integer line :start start :junk-allowed t)
(collect-numbers-line line i end (cons (make-mynumber :num n
:loweri (1- i)
:lowerj (1- start)
:upperi (1+ i)
:upperj end)
acc)))
(collect-numbers-line line i (1+ start) acc))
acc))
(collect-numbers-rec (lines i acc)
(if lines
(collect-numbers-rec (cdr lines)
(1+ i)
(collect-numbers-line (car lines) i 0 acc))
acc)))
(collect-numbers-rec lines 0 ())))
(defun has-adjacent-symbol (gear numbers)
(loop for number in numbers
if (is-adjacent number gear)
collect (mynumber-num number)))
(defun collect-gears (lines)
(loop for i = 0 then (1+ i)
for line in lines
append (loop for j = 0 then (1+ j)
for c across line
if (equal #\* c)
collect (make-mysymbol :symb c :i i :j j))))
(defun is-adjacent (number symbol)
(and (>= (mysymbol-i symbol) (mynumber-loweri number))
(<= (mysymbol-i symbol) (mynumber-upperi number))
(>= (mysymbol-j symbol) (mynumber-lowerj number))
(<= (mysymbol-j symbol) (mynumber-upperj number))))
(defun find-adjacent-numbers (gear numbers)
(loop for number in numbers
if (is-adjacent number gear)
collect (mynumber-num number)))
(defun solve2 (f)
(let ((lines (input-lines f)))
(let ((numbers (collect-numbers lines))
(gears (collect-gears lines)))
(loop for gear in gears
as nums = (find-adjacent-numbers gear numbers)
if (= (length nums) 2)
sum (* (car nums) (cadr nums))))))
(print (solve1 "data/03/example.txt")) ;; 4361
(print (solve1 "data/03/input.txt")) ;; 553079
(print (solve2 "data/03/example.txt")) ;; 467835
(print (solve2 "data/03/input.txt")) ;; 84363105
|