~shunter/advent2021

b630e47e3df46339ec3cd2fa2e1bbf43aafdd489 — Samuel Hunter 2 years ago 5930f5e
Refactor Day 09
1 files changed, 21 insertions(+), 20 deletions(-)

M day09.lisp
M day09.lisp => day09.lisp +21 -20
@@ 20,22 20,20 @@
(defparameter +width+ (array-dimension +input+ 1))
(defparameter +height+ (array-dimension +input+ 0))

(defun adjacents (x y)
  (flet ((access (x y)
           (if (and (>= x 0)
                    (>= y 0)
                    (< x +width+)
                    (< y +height+))
               (aref +input+ y x)
               9999)))
    (list (access x (1- y))
          (access x (1+ y))
          (access (1- x) y)
          (access (1+ x) y))))
(defun height (x y)
  (if (and (>= x 0)
           (>= y 0)
           (< x +width+)
           (< y +height+))
      (aref +input+ y x)
      9))

(defun low-point? (x y)
  (loop :with point := (aref +input+ y x)
        :for adjacent :in (adjacents x y)
  (loop :with point := (height x y)
        :for adjacent :in (list (height (1- x) y)
                                (height (1+ x) y)
                                (height x (1- y))
                                (height x (1+ y)))
        :always (< point adjacent)))

(defun solve-part-1 ()


@@ 45,12 43,12 @@
                     :sum (1+ (aref +input+ y x)))))

(defun fill-basin (x y touch-array)
  (when (or (< x 0) (< y 0)
            (>= x +width+) (>= y +height+)
            (= 1 (aref touch-array y x))
            (= 9 (aref +input+ y x)))
  "Fill the basin located at the given point, marking it as already visited on the touch-array and returning the baisn's size."
  (when (or (= 9 (height x y))
            (= 1 (aref touch-array y x)))
    (return-from fill-basin 0))

  ;; Good ol' Fill Algorithm
  (setf (aref touch-array y x) 1)
  (+ 1
     (fill-basin (1- x) y touch-array)


@@ 59,13 57,16 @@
     (fill-basin x (1+ y) touch-array)))

(defun basin-sizes ()
  "Return an unordered list of all basin sizes"
  (loop :with touch-array := (make-array (list +height+ +width+)
                                         :element-type 'bit)
        :for y :below +height+
        :append (loop :for x :below +width+
                      :for score := (fill-basin x y touch-array)
                      :when (> score 0)
                      :collect score)))
                        :collect score)))

(defun solve-part-2 ()
  (reduce #'* (subseq (sort (basin-sizes) #'>) 0 3)))
  "Multiply the largest 3 basin sizes."
  (reduce #'* (subseq (sort (basin-sizes) #'>)
                      0 3)))