src/2020/days/day-11.lisp @ 166414163a73

2021/11
author Steve Losh <steve@stevelosh.com>
date Wed, 01 Dec 2021 21:48:27 -0500
parents (none)
children bd509ececdf0
(advent:defpackage* :advent/2020/11)
(in-package :advent/2020/11)

(defun sref (seats row col)
  (when (array-in-bounds-p seats row col)
    (aref seats row col)))

(defun count-neighbors (seats row col &aux (result 0))
  (do-irange ((dr -1 1)
              (dc -1 1))
    (unless (= 0 dr dc)
      (when (eql #\# (sref seats (+ row dr) (+ col dc)))
        (incf result))))
  result)

(defun count-visible (seats row col &aux (result 0))
  (do-irange ((dr -1 1)
              (dc -1 1))
    (unless (= 0 dr dc)
      (iterate (for r :from (+ row dr) :by dr)
               (for c :from (+ col dc) :by dc)
               (for ch = (sref seats r c))
               (ecase ch
                 ((#\L nil) (return))
                 (#\# (progn (incf result) (return)))
                 (#\.)))))
  result)

(defun simulate (seats &key neighbors crowded)
  (let ((seats (alexandria:copy-array seats))
        (next (alexandria:copy-array seats)))
    (loop (iterate
            (with changed = nil)
            (for (current row col) :in-array seats)
            (unless (char= current #\.)
              (for n = (funcall neighbors seats row col))
              (setf (aref next row col)
                    (ecase current
                      (#\L (if (= n 0)
                             (progn (setf changed t) #\#)
                             #\L))
                      (#\# (if (>= n crowded)
                             (progn (setf changed t) #\L)
                             #\#)))))
            (finally
              (rotatef seats next)
              (when (not changed) (return-from simulate seats)))))))

(defun count-total (seats)
  (iterate (for ch :across-flat-array seats) (counting (char= ch #\#))))

(define-problem (2020 11) (data read-2d-array) (2261 2039)
  (values (count-total (simulate data :neighbors #'count-neighbors :crowded 4))
          (count-total (simulate data :neighbors #'count-visible :crowded 5))))


#; Scratch --------------------------------------------------------------------