adventofcode2022

My solutions for Advent of Code 2022
Log | Files | Refs

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)