(defpackage :aoc/2024/10 (:use :cl :aoc :alexandria :trivia :lla) (:export #:sample-data #:sample-data2 #:part1 #:part2 )) (in-package :aoc/2024/10) (defun parse-line (line) (map 'vector (lambda (c) (or (digit-char-p c) 0)) (coerce line 'list))) (defun parse-input (lines) (let ((heights (mapcar #'parse-line lines))) (make-array `(,(length (first heights)) ,(length heights)) :initial-contents heights)) ) (defparameter input-text (test-input 2024 10)) (defparameter input-data (parse-input input-text)) (defparameter sample-text (aoc:split-lines "89010123 78121874 87430965 96549874 45678903 32019012 01329801 10456732")) (defparameter sample-data (parse-input sample-text)) (defparameter sample-data-0 (parse-input (aoc:split-lines "...0... ...1... ...2... 6543456 7.....7 8.....8 9.....9"))) (defparameter sample-data-1 (parse-input (aoc:split-lines "..90..9 ...1.98 ...2..7 6543456 765.987 876.... 987...."))) (defun find-heights(h map) (loop for y from 0 below (array-dimension map 1) append (loop for x from 0 below (array-dimension map 1) if (= h (aref map x y)) collect (cons x y)))) (defun find-trailheads (map) (find-heights 1 map)) (defun find-trailends (map) (find-heights 9 map)) (defun get-xy (map x y) (if (array-in-bounds-p map x y) (aref map x y) 0)) (defun surrounding-paths (trails x y) (remove-duplicates (append (gethash (cons (1+ x) y) trails) (gethash (cons (1- x) y) trails) (gethash (cons x (1+ y)) trails) (gethash (cons x (1- y)) trails) ))) (defun trails-update (trails map h) (let ((nt (make-hash-table :test #'equal :size 100))) (loop for pt in (find-heights h map) do (setf (gethash pt nt) (if (= h 9) (list pt) (surrounding-paths trails (car pt) (cdr pt)))) ) nt)) (defun map-endpoints (map) (let ((ep-map (make-hash-table :test #'equal))) (loop for h from 9 downto 0 do (setf ep-map (trails-update ep-map map h))) ep-map)) (defun score (map) (loop for v being the hash-values in (map-endpoints map) sum (length v))) (defun sum-surrounding (map x y) (+ (get-xy map (1+ x) y) (get-xy map (1- x) y) (get-xy map x (1+ y)) (get-xy map x (1- y)) ) ) (defun ratings-update (ratings map h) (let ((nr (make-array (array-dimensions ratings) :initial-element 0))) (loop for pt in (find-heights h map) do (let ((x (car pt)) (y (cdr pt))) (setf (aref nr x y) (if (= h 9) 1 (sum-surrounding ratings x y)))) ) nr)) (defun ratings (map) (let ((ratings (make-array (array-dimensions map) :initial-element 0))) (loop for h from 9 downto 0 do (setf ratings (ratings-update ratings map h))) ratings)) (defun rating (map) (loop for r across (aops:flatten (ratings map)) sum r) ) (defun part1 (data) (format nil "~A" (score data))) (defun part2 (data) (format nil "~A" (rating data))) (defun solve-day () (format t "part1: ~A~%" (part1 input-data)) (format t "part2: ~A~%" (part2 input-data))) (defun submit () (let ((p1 (part1 input-data)) (p2 (part2 input-data))) (if p1 (submit-part1 2024 10 p1)) (if p2 (submit-part2 2024 10 p2))))