Created
December 24, 2020 13:30
-
-
Save death/8dd5f03b41b517c19fdf41ecf20f0ac1 to your computer and use it in GitHub Desktop.
aoc2020 day24
This file contains 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 2020 | | |
;;;; +----------------------------------------------------------------+ | |
(defpackage #:snippets/aoc2020/day24 | |
(:use #:cl) | |
(:export | |
#:day24)) | |
(in-package #:snippets/aoc2020/day24) | |
(defun parse (input) | |
(mapcar #'parse-tile input)) | |
(defun parse-tile (string) | |
(reduce #'+ (parse-path string))) | |
(defconstant east #C(+1 0)) | |
(defconstant west #C(-1 0)) | |
(defconstant southeast #C(+1/2 +1)) | |
(defconstant southwest #C(-1/2 +1)) | |
(defconstant northeast #C(+1/2 -1)) | |
(defconstant northwest #C(-1/2 -1)) | |
(defun parse-path (string) | |
(with-input-from-string (in string) | |
(loop for char = (read-char in nil nil) | |
while char | |
collect (ecase char | |
(#\e east) | |
(#\w west) | |
(#\s | |
(ecase (read-char in) | |
(#\e southeast) | |
(#\w southwest))) | |
(#\n | |
(ecase (read-char in) | |
(#\e northeast) | |
(#\w northwest))))))) | |
(defun flip (tiles) | |
(let ((tile-floor (make-hash-table))) | |
(dolist (tile tiles) | |
(if (gethash tile tile-floor) | |
(remhash tile tile-floor) | |
(setf (gethash tile tile-floor) t))) | |
tile-floor)) | |
(defun num-black (tile-floor) | |
(hash-table-count tile-floor)) | |
(defvar *directions* | |
(list east west southeast southwest northeast northwest)) | |
(defun neighbor-counts (tile-floor) | |
(let ((counts (make-hash-table))) | |
(loop for black-tile being each hash-key of tile-floor | |
do (dolist (direction *directions*) | |
(incf (gethash (+ black-tile direction) counts 0)))) | |
counts)) | |
(defun day-flip (tile-floor) | |
(let ((new-tile-floor (make-hash-table)) | |
(counts (neighbor-counts tile-floor))) | |
(loop for tile being each hash-key of counts | |
using (hash-value num-black) | |
when (if (gethash tile tile-floor) | |
(not (or (zerop num-black) | |
(> num-black 2))) | |
(= num-black 2)) | |
do (setf (gethash tile new-tile-floor) t)) | |
new-tile-floor)) | |
(defun game-of-tiles (tile-floor n) | |
(if (plusp n) | |
(game-of-tiles (day-flip tile-floor) (1- n)) | |
tile-floor)) | |
(defun day24 (input) | |
(let ((tiles (parse input))) | |
(list (num-black (flip tiles)) | |
(num-black (game-of-tiles (flip tiles) 100))))) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment