Last active
December 4, 2021 10:07
-
-
Save death/511551a7b937340abcda2929020b2597 to your computer and use it in GitHub Desktop.
aoc2021-day4
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| ;;;; +----------------------------------------------------------------+ | |
| ;;;; | Advent of Code 2021 | | |
| ;;;; +----------------------------------------------------------------+ | |
| (defpackage #:snippets/aoc2021/day4 | |
| (:use #:cl) | |
| (:export | |
| #:day4)) | |
| (in-package #:snippets/aoc2021/day4) | |
| (defconstant board-size 5) | |
| (defstruct entry | |
| (row 0) | |
| (column 0) | |
| (markedp nil)) | |
| (defstruct board | |
| (numbers (make-hash-table)) | |
| (marked-in-column (make-array board-size :initial-element 0)) | |
| (marked-in-row (make-array board-size :initial-element 0)) | |
| (last-number-called 0) | |
| (tick 0)) | |
| (defstruct game | |
| (drawn-numbers '()) | |
| (boards '())) | |
| (defun create-board (lists-of-numbers) | |
| (let ((board (make-board))) | |
| (loop for row upfrom 0 | |
| for row-of-numbers in lists-of-numbers | |
| do (loop for column upfrom 0 | |
| for number in row-of-numbers | |
| do (push (make-entry :row row :column column :markedp nil) | |
| (gethash number (board-numbers board))))) | |
| board)) | |
| (defun create-game (lists-of-numbers) | |
| (setf lists-of-numbers (remove nil lists-of-numbers)) | |
| (make-game | |
| :drawn-numbers (first lists-of-numbers) | |
| :boards (loop for board-numbers-head = (rest lists-of-numbers) then board-numbers-tail | |
| for board-numbers-tail = (nthcdr board-size board-numbers-head) | |
| until (null board-numbers-head) | |
| collect (create-board (ldiff board-numbers-head board-numbers-tail))))) | |
| (defun winningp (board) | |
| (or (find board-size (board-marked-in-column board)) | |
| (find board-size (board-marked-in-row board)))) | |
| (defun score (board) | |
| (* (board-last-number-called board) | |
| (loop for number being each hash-key of (board-numbers board) | |
| using (hash-value entries) | |
| sum (* number (count-if-not #'entry-markedp entries))))) | |
| (defun call-number (game number) | |
| (dolist (board (game-boards game)) | |
| (unless (winningp board) | |
| (dolist (entry (gethash number (board-numbers board))) | |
| (assert (not (entry-markedp entry))) | |
| (setf (entry-markedp entry) t) | |
| (incf (aref (board-marked-in-column board) (entry-column entry))) | |
| (incf (aref (board-marked-in-row board) (entry-row entry)))) | |
| (setf (board-last-number-called board) number) | |
| (incf (board-tick board))))) | |
| (defun play (game) | |
| (dolist (number-to-call (game-drawn-numbers game)) | |
| (call-number game number-to-call))) | |
| (defun winner (game betterp) | |
| (reduce (lambda (leader board) | |
| (if (funcall betterp | |
| (board-tick leader) | |
| (board-tick board)) | |
| leader | |
| board)) | |
| (game-boards game))) | |
| (defun day4 (input) | |
| (let ((game (create-game input))) | |
| (play game) | |
| (list (score (winner game #'<)) | |
| (score (winner game #'>))))) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment