@@ 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)))