Skip to content

Instantly share code, notes, and snippets.

@death
Last active December 4, 2021 10:07
Show Gist options
  • Select an option

  • Save death/511551a7b937340abcda2929020b2597 to your computer and use it in GitHub Desktop.

Select an option

Save death/511551a7b937340abcda2929020b2597 to your computer and use it in GitHub Desktop.
aoc2021-day4
;;;; +----------------------------------------------------------------+
;;;; | 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