-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathday-25.el
114 lines (99 loc) · 2.72 KB
/
day-25.el
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
;; -*- lexical-binding: t -*-
(defun next-paragraph ()
(save-excursion
(forward-paragraph)
(1- (point))))
(defun read-line ()
(buffer-substring (point) (line-end-position)))
(defun read-grid ()
(let ((width (- (line-end-position) (point))))
(when (> width 0)
(let* ((line (line-number-at-pos))
(height (- (line-number-at-pos (next-paragraph)) line))
(grid (make-grid height width)))
(dotimes (i height)
(let ((row (read-line)))
(dotimes (j width)
(gset grid (cons i j) (aref row j)))
(forward-line)))
(forward-line)
(forward-line)
grid))))
(defun read-grids (file)
(with-temp-buffer
(insert-file-contents file)
(let ((grids nil))
(while-let ((grid (read-grid)))
(push grid grids))
(nreverse grids))))
(defun make-grid (height width &optional blank)
(let ((grid (make-vector height nil)))
(dotimes (i height)
(aset grid i (make-vector width blank)))
grid))
(defun insert-grid (grid)
(seq-do (lambda (row)
(seq-do #'insert row)
(insert ?\n))
grid))
(defun grid-height (grid)
(length grid))
(defun grid-width (grid)
(length (aref grid 0)))
(defun gset (grid pos value)
"Ignores out-of-bounds references"
(pcase-let* ((`(,i . ,j) pos))
(when (and (>= i 0) (< i (length grid)))
(let ((row (aref grid i)))
(when (and (>= j 0) (< j (length row)))
(aset row j value))))))
(defun gref (grid pos)
"Returns nil for out-of-bounds references"
(pcase-let* ((`(,i . ,j) pos))
(when (and (>= i 0) (< i (length grid)))
(let ((row (aref grid i)))
(when (and (>= j 0) (< j (length row)))
(aref row j))))))
(defun lock-p (grid)
(eq (gref grid (cons 0 0)) ?#))
(defun heights (grid)
(let ((height (grid-height grid))
(heights nil)
(c (if (lock-p grid) ?# ?.)))
(dotimes (j (grid-width grid))
(let ((n 0))
(dotimes (i height)
(when (eq (gref grid (cons i j)) c)
(setq n (if (lock-p grid) i (- height i 1)))))
(push n heights)))
(nreverse heights)))
(defun triage (grids)
(let ((locks nil)
(keys nil))
(dolist (grid grids)
(let ((heights (heights grid)))
(if (lock-p grid)
(push heights locks)
(push heights keys))))
(cons locks keys)))
(defun overlap-p (lock key height)
(catch :overlap
(while-let ((l (car lock))
(k (car key)))
(when (> (+ l k) height)
(throw :overlap t))
(setq lock (cdr lock))
(setq key (cdr key)))))
(defun puzzle-25a ()
(let* ((file "data/input-25.txt")
(grids (read-grids file))
(height (1- (grid-height (car grids))))
(heights (triage grids))
(locks (car heights))
(keys (cdr heights))
(fit 0))
(dolist (lock locks)
(dolist (key keys)
(unless (overlap-p lock key height)
(setq fit (1+ fit)))))
fit))