day08.lisp (3159B)
1 (defpackage #:adventofcode2022/day08 2 (:use #:cl #:adventofcode2022)) 3 (in-package #:adventofcode2022/day08) 4 5 (defun look-at-trees (map 6 seen-trees 7 max-d-1 8 max-d-2 9 init-d-1 10 init-d-2 11 d-1-step-fun 12 d-2-step-fun 13 d-1-is-x-p) 14 (loop for d-1 = init-d-1 then (funcall d-1-step-fun d-1) 15 while (and (>= d-1 0) (< d-1 max-d-1)) 16 sum (loop with last-tree-height = -1 17 for d-2 = init-d-2 then (funcall d-2-step-fun d-2) 18 while (and (>= d-2 0) (< d-2 max-d-2)) 19 for x = (if d-1-is-x-p d-1 d-2) 20 for y = (if d-1-is-x-p d-2 d-1) 21 for tree-height = (aref (aref map y) x) 22 when (> tree-height last-tree-height) 23 do (setf last-tree-height tree-height) 24 and unless (gethash (cons x y) seen-trees) 25 do (setf (gethash (cons x y) seen-trees) t) 26 and sum 1))) 27 28 (defun task1 (inputs) 29 (let* ((height (length inputs)) 30 (width (length (car inputs))) 31 (map (coerce inputs 'vector)) 32 (seen-trees (make-hash-table :test 'equal))) 33 (+ 34 (look-at-trees map seen-trees height width 0 0 #'1+ #'1+ nil) 35 (look-at-trees map seen-trees height width 0 (1- width) #'1+ #'1- nil) 36 (look-at-trees map seen-trees width height 0 0 #'1+ #'1+ t) 37 (look-at-trees map seen-trees width height 0 (1- height) #'1+ #'1- t)))) 38 39 (defun get-viewing-distance (map max-tree-height static-d static-d-is-x-p init max step-fun) 40 (loop with count-trees = 0 41 for d = init then (funcall step-fun d) 42 while (and (>= d 0) (< d max)) 43 for x = (if static-d-is-x-p static-d d) 44 for y = (if static-d-is-x-p d static-d) 45 for tree-height = (aref (aref map y) x) 46 do (incf count-trees) 47 if (>= tree-height max-tree-height) 48 return count-trees 49 finally (return count-trees))) 50 51 (defun calculate-tree-scenic-score (map width height x y) 52 (let ((spot-height (aref (aref map y) x))) 53 (* 54 (get-viewing-distance map spot-height y nil (1+ x) width #'1+) 55 (get-viewing-distance map spot-height y nil (1- x) width #'1-) 56 (get-viewing-distance map spot-height x t (1+ y) height #'1+) 57 (get-viewing-distance map spot-height x t (1- y) height #'1-)))) 58 59 (defun task2 (inputs) 60 (loop with height = (length inputs) 61 with width = (length (car inputs)) 62 with map = (coerce inputs 'vector) 63 for x from 0 below width 64 maximizing (loop for y from 0 below height 65 maximizing (calculate-tree-scenic-score 66 map 67 width height 68 x y)))) 69 70 (define-day 8 71 (:translate-input (lambda (input) 72 (map 'vector 73 (lambda (char) 74 (- (char-code char) 48)) 75 input))) 76 #'task1 77 #'task2)