summaryrefslogtreecommitdiffstats
path: root/src/04.lisp
blob: b58825cdfa765229aeceb906b3dab0c35126796e (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
59
60
61
62
63
64
65
66
67
(use-package 'cl-ppcre)
(use-package 'trivia)

(defun 04/parse-input-direct (input)
  (let ((in-list (mapcar #'parse-integer (split "," (car input))))
        (boards (mapcar
                 (lambda (x)
                   (mapcar
                    (lambda (y)
                      (mapcar
                       (lambda (z)
                         (list (parse-integer z) nil)) (split " +" (trim y)))) x))
                 (cl-utilities:split-sequence-if (lambda (x) (equalp x "")) (cddr input)))))
    (list in-list boards)))

(defun 04/parse-input (input-file)
  (04/parse-input-direct (get-file-lines input-file)))

(defun 04/update-board (num board)
  (mapcar (lambda (row)
            (mapcar (lambda (val)
                      (if (equalp num (car val)) (list (car val) t) val))
                    row))
          board))

(defun rotate (list-of-lists)
  (apply #'mapcar #'list list-of-lists))

(defun 04/check-rows (row) (every #'cadr row))

(defun 04/check-board (board)
  (if (or (some #'04/check-rows board)
          (some #'04/check-rows (rotate board)))
      board nil))

;; (04/check-board '(((2 t) (3 nil)) ((2 nil) (3 t))))
;; ==> nil

(defun 04/to-val (v) (if (cadr v) 0 (car v)))

(defun 04/sum-unmarked (board)
  (apply #'+ (mapcar (compose
                      (partial #'apply #'+)
                      (partial #'mapcar #'04/to-val))
                     board)))

(defun 04/part-a (parsed-input)
  (let ((inputs (car parsed-input))
        (boards (cadr parsed-input)))
    (match (loop :for i :in inputs
                 :do (setf boards (mapcar (partial #'04/update-board i) boards))
                 :when (some #'04/check-board boards)
                   :return (list i (some #'04/check-board boards)))
      ((list i board)
       (* i (04/sum-unmarked board))))))

(defun 04/part-b (parsed-input)
  (let ((inputs (car parsed-input))
        (boards (cadr parsed-input)))
    (match (loop :for i :in inputs
                 :do (setf boards (mapcar (partial #'04/update-board i) boards))
                 :when (not (equalp (list-length boards) 1))
                   :do (setf boards (filter (compose #'not #'04/check-board) boards))
                 :when (and (equalp (list-length boards) 1) (04/check-board (car boards)))
                   :return (list i (car boards)))
      ((list i board)
       (* i (04/sum-unmarked board))))))