-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathday08.lisp
More file actions
94 lines (73 loc) · 3.29 KB
/
Copy pathday08.lisp
File metadata and controls
94 lines (73 loc) · 3.29 KB
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
(defpackage :aoc/2021/08 #.cl-user::*aoc-use*)
(in-package :aoc/2021/08)
(defun parse-entries (data)
(loop for string in data
for parts = (cl-ppcre:all-matches-as-strings "[a-z]+" string)
collect (cons (subseq parts 0 10) (subseq parts 10))))
(defun inputs (entry) (car entry))
(defun outputs (entry) (cdr entry))
(defun part1 (entries)
(loop for e in entries sum
(loop for d in (outputs e) count (member (length d) '(2 4 3 7)))))
(defun decode (mapping signals &aux (rez 0))
(dolist (s signals)
(let ((d (signal->digit mapping s)))
(setf rez (+ (* rez 10) d))))
rez)
(defparameter *digits->segments* '((0 . #b1110111)
(1 . #b0100100)
(2 . #b1011101)
(3 . #b1101101)
(4 . #b0101110)
(5 . #b1101011)
(6 . #b1111011)
(7 . #b0100101)
(8 . #b1111111)
(9 . #b1101111)))
(defun signal->digit (mapping s &aux (segments-mask 0))
(doseq (ch s)
(let ((i (position ch mapping)))
(setf segments-mask (dpb 1 (byte 1 i) segments-mask))))
(car (rassoc segments-mask *digits->segments*)))
(defun part2 (entries)
(loop for e in entries
for m = (find-mapping (inputs e))
sum (decode m (outputs e))))
(defun find-mapping (signals)
(labels ((recur (curr remaining)
(cond ((loop for x in curr always (= (length x) 1))
(return-from find-mapping (mapcar #'car curr)))
((loop for x in curr thereis (zerop (length x))) nil)
((null remaining) nil)
(t (let ((s (first remaining)))
(dolist (d (possible-digits s))
(let ((segs (cdr (assoc d *digits->segments*))))
(recur
(loop for c in curr for i below 7
collect (if (= (ldb (byte 1 i) segs) 1)
(intersection c (coerce s 'list))
(set-difference c (coerce s 'list))))
(rest remaining)))))))))
(recur
(loop repeat 7 collect (coerce "abcdefg" 'list))
(sort (copy-seq signals) #'possible-digits<))))
(defparameter *length->digits* '((2 1)
(3 7)
(4 4)
(5 2 3 5)
(6 0 6 9)
(7 8)))
(defun possible-digits (s) (cdr (assoc (length s) *length->digits*)))
(defun possible-digits< (s1 s2)
(< (length (possible-digits s1)) (length (possible-digits s2))))
#+#:alternate-solution-with-bruteforce (defun part2 (entries)
(let ((all-mappings (all-permutations (coerce "abcdefg" 'list)))
(sum 0))
(dolist (e entries)
(dolist (m all-mappings)
(when (every (partial-1 #'signal->digit m) (inputs e))
(return (incf sum (decode m (outputs e)))))))
sum))
(define-solution (2021 08) (entries parse-entries)
(values (part1 entries) (part2 entries)))
(define-test (2021 08) (330 1010472))