diff --git a/aoc.asd b/aoc.asd index 831d582..f1d17ea 100644 --- a/aoc.asd +++ b/aoc.asd @@ -34,6 +34,7 @@ (:file "2024/day07") (:file "2024/day08") (:file "2024/day09") + (:file "2024/day10") ))) :description "Advent of Code challenges and solutions." :long-description "Solutions for the AOC challenges." @@ -59,6 +60,7 @@ (:file "2024/day07-test") (:file "2024/day08-test") (:file "2024/day09-test") + (:file "2024/day10-test") ))) :description "Test system for aoc" :perform (test-op (op c) (symbol-call :parachute :test :aoc/tests))) diff --git a/src/2024/day10.lisp b/src/2024/day10.lisp new file mode 100644 index 0000000..b9dfcdd --- /dev/null +++ b/src/2024/day10.lisp @@ -0,0 +1,155 @@ +(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)))) diff --git a/tests/2024/day10-test.lisp b/tests/2024/day10-test.lisp new file mode 100644 index 0000000..939051a --- /dev/null +++ b/tests/2024/day10-test.lisp @@ -0,0 +1,16 @@ +(defpackage :aoc/2024/10/tests + (:use :cl :aoc :aoc/tests :aoc/2024/tests :parachute :aoc/2024/10)) + +(in-package :aoc/2024/10/tests) + +(define-test suite-2024-10 + ;:parent suite-2024 + ) + +(define-test+run test-part1 + :parent suite-2024-10 + (is equal "36" (part1 sample-data))) + +(define-test+run test-part2 + :parent suite-2024-10 + (is equal "81" (part2 sample-data)))