(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))))))