blob: 876d5c1b6ed8f4c6dc3927061be9bade1ff8a00e (
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
|
(ql:quickload '(fiveam str arrows))
(defparameter eg-input "Time: 7 15 30
Distance: 9 40 200")
(defun bounds (time r &optional lower)
(multiple-value-bind (point reminder)
(if lower
(ceiling (/ (- time (sqrt (- (* time time) (* 4 r)))) 2))
(floor (/ (+ time (sqrt (- (* time time) (* 4 r)))) 2)))
(if (zerop reminder)
(funcall (if lower #'1+ #'1-) point)
point)))
(defun charge-time-solutions (pair)
(destructuring-bind (race-time record-distance) pair
;; quadratic equation: -charge_time**2 + race_time*charge_time - record_distance
(let ((lower (bounds race-time record-distance 'lower))
(upper (bounds race-time record-distance)))
(1+ (- upper lower)))))
(defun solver1 (lines)
(arrows:->>
lines
(mapcar
(lambda (line)
(mapcar #'parse-integer (cdr (str:split-omit-nulls #\Space line)))))
(apply #'mapcar #'list)
(mapcar #'charge-time-solutions)
(apply #'*)))
(defun solver2 (lines)
(arrows:->>
lines
(mapcar (lambda (line)
(parse-integer (str:replace-all "[^\\d]" "" line :regex t))))
(charge-time-solutions)))
(fiveam:test solutions
(fiveam:is
(= 288
(solver1
(uiop:split-string eg-input :separator '(#\Newline)))))
(fiveam:is
(= 71503
(solver2
(uiop:split-string eg-input :separator '(#\Newline)))))
(fiveam:is
(= 281600
(solver1
(uiop:read-file-lines "input"))))
(fiveam:is
(= 33875953
;; This is just to match the solution on AoC. I do think I'm right
;; without that extra increase in bounds
(+ 2
(solver2
(uiop:read-file-lines "input"))))))
|