diff options
Diffstat (limited to 'AoC2022/08/solver.lisp')
-rw-r--r-- | AoC2022/08/solver.lisp | 91 |
1 files changed, 59 insertions, 32 deletions
diff --git a/AoC2022/08/solver.lisp b/AoC2022/08/solver.lisp index 9031e19..3cab1c0 100644 --- a/AoC2022/08/solver.lisp +++ b/AoC2022/08/solver.lisp @@ -11,35 +11,62 @@ (lambda (y x) (funcall xminor x y)))) -(let* ((data (uiop:read-file-lines "input")) - (width (length (car data))) - (height (length data)) - (forest-arr - (apply #'vector - (mapcan (lambda (row) - (map 'list (lambda (x) (- (char-code x) 48)) row)) data))) - (visibility-mask (make-array (* width height) :initial-element nil)) - (location-x (coord-x-minor width height)) - (location-y (coord-y-minor width height)) - ) - (flet ((toggle-visibility (major minor location reverse) - (dotimes (m major) - (let ((range (loop for i below minor collect i))) - (loop - for n in (if reverse (nreverse range) range) - for maxh = -1 then (max maxh tree-height) - for tree-height = (aref forest-arr (funcall location n m)) - when (> tree-height maxh) - do (setf (aref visibility-mask (funcall location n m)) t)))))) - (toggle-visibility height width location-x nil) - (toggle-visibility height width location-x t) - (toggle-visibility width height location-y nil) - (toggle-visibility width height location-y t) - ) - - - - - (loop for v across visibility-mask counting v) - ;; visibility-mask - ) +(defun flatten-data (data) + (apply #'vector + (mapcan (lambda (row) + (map 'list (lambda (x) (- (char-code x) 48)) row)) data))) + +(defun forest (data) + (let ((width (length (car data))) + (height (length data))) + (values (flatten-data data) width height))) + +(defun solver-p1 (filename) + (multiple-value-bind (forest-arr width height) (forest (uiop:read-file-lines filename)) + (let ((visibility-mask (make-array (* width height) :initial-element nil)) + (location-x (coord-x-minor width height)) + (location-y (coord-y-minor width height))) + (flet ((toggle-visibility (major minor location reverse) + (let ((range (if reverse + (loop for i downfrom (1- minor) to 0 collect i) + (loop for i below minor collect i)))) + (dotimes (m major) + (loop + for n in range + for maxh = -1 then (max maxh tree-height) + for tree-height = (aref forest-arr (funcall location n m)) + when (> tree-height maxh) + do (setf (aref visibility-mask (funcall location n m)) t)))))) + (toggle-visibility height width location-x nil) + (toggle-visibility height width location-x t) + (toggle-visibility width height location-y nil) + (toggle-visibility width height location-y t)) + (loop for v across visibility-mask counting v)))) + +(defun solver-p2 (filename) + (multiple-value-bind (forest-arr width height) (forest (uiop:read-file-lines filename)) + (let ((score (make-array (* width height))) + (location-x (coord-x-minor width height))) + + (flet ((score-direction (base dir) + (loop for l in dir + for tree-height = (aref forest-arr l) + count l until (>= tree-height base)))) + (dotimes (y height) + (dotimes (x width) + (let ((base (aref forest-arr (funcall location-x x y)))) + (setf (aref score (funcall location-x x y)) + (* + (score-direction base (loop for l from (1+ x) below width collect (funcall location-x l y))) ;; to right + (score-direction base (loop for l from (1+ y) below height collect (funcall location-x x l))) ;; to bottom + (score-direction base (loop for l downfrom (1- x) to 0 collect (funcall location-x l y))) ;; to left + (score-direction base (loop for l downfrom (1- y) to 0 collect (funcall location-x x l)))))))) ;; to top + (loop for v across score maximize v))))) + +(fiveam:test solutions + (fiveam:is (= 21 (solver-p1 "eg-in"))) + (fiveam:is (= 1672 (solver-p1 "input"))) + (fiveam:is (= 8 (solver-p2 "eg-in"))) + (fiveam:is (= 327180 (solver-p2 "input")))) + +(fiveam:run-all-tests) |