-
Notifications
You must be signed in to change notification settings - Fork 0
/
03.lisp
51 lines (38 loc) · 1.39 KB
/
03.lisp
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
;; --- Day 3: Binary Diagnostic ---
(load "aoc")
(defparameter +day3+ (mapcar #'aoc:str->digits (uiop:read-file-lines "03.in")))
;; Commons
(defun most-least (xs ll)
(let ((len (length ll)))
(loop for n in '(1 0) for c = (count n xs)
collect (if (= c (/ len 2)) n (round (/ c len))))))
(defun bin->dec (xs)
(reduce (lambda (x y) (+ (* 2 x) y)) xs))
(defun multiply-bins (xs)
(apply #'* (mapcar #'bin->dec xs)))
;; I
(defun solution1 (data)
(multiply-bins (aoc:rotate (mapcar (lambda (l) (most-least l data)) (aoc:rotate data)))))
;; II
(defun get-rating (ll &key (pos 0) subs)
(if (cdr ll)
(let ((bit (funcall subs (most-least (nth pos (aoc:rotate ll)) ll))))
(get-rating (remove-if-not (lambda (l) (= (nth pos l) bit)) ll)
:pos (incf pos) :subs subs))
(first ll)))
(setf (fdefinition 'oxygen) #'car
(fdefinition 'co2) #'cadr)
(defun solution2 (data)
(multiply-bins (loop for s in '(oxygen co2) collect (get-rating data :subs s))))
(aoc:solve
(solution1 +day3+)
(solution2 +day3+))
;; Tests
(use-package :lisp-unit)
(define-test day3
(let ((input (mapcar #'aoc:str->digits
'("00100" "11110" "10110" "10111" "10101" "01111"
"00111" "11100" "10000" "11001" "00010" "01010"))))
(assert-equal 198 (solution1 input))
(assert-equal 230 (solution2 input))))
(run-tests '(day3))