summaryrefslogtreecommitdiffstats
path: root/src/04.lisp
diff options
context:
space:
mode:
Diffstat (limited to 'src/04.lisp')
-rw-r--r--src/04.lisp64
1 files changed, 64 insertions, 0 deletions
diff --git a/src/04.lisp b/src/04.lisp
new file mode 100644
index 0000000..33436c2
--- /dev/null
+++ b/src/04.lisp
@@ -0,0 +1,64 @@
+(use-package 'cl-ppcre)
+(use-package 'cl-utilities)
+(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))
+ (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))))))