advent-of-code-2023

My solutions to AoC 2023
git clone git://git.entf.net/advent-of-code-2023
Log | Files | Refs

commit 66456ba8fb5ceb69ad7ea2f2c8fcc757a6b6e405
parent 2b9c8dd94c27169b528d83a00011cc6f90e4a151
Author: Lukas Henkel <lh@entf.net>
Date:   Sun, 17 Dec 2023 08:00:40 +0100

Day 17 task 2

Diffstat:
Msrc/day-17.lisp | 49+++++++++++++++++++++++++++++++++++--------------
Mt/day-17.lisp | 5+++--
2 files changed, 38 insertions(+), 16 deletions(-)

diff --git a/src/day-17.lisp b/src/day-17.lisp @@ -13,7 +13,15 @@ :right (:up :down) :down (:left :right))) -(defun next-steps (map pos dir steps closed) +(defun make-side-in-map-p (map closed) + (lambda (side) + (or (< (point-x (car side)) 0) + (< (point-y (car side)) 0) + (>= (point-x (car side)) (input-map-width map)) + (>= (point-y (car side)) (input-map-height map)) + (gethash side closed)))) + +(defun next-steps-crucible (map pos dir steps closed) (let (sides) (when (< steps 3) (push (list (point+ pos (getf *dirs* dir)) @@ -25,17 +33,25 @@ next 1) sides)) - (remove-if (lambda (side) - (or (< (point-x (car side)) 0) - (< (point-y (car side)) 0) - (>= (point-x (car side)) (input-map-width map)) - (>= (point-y (car side)) (input-map-height map)) - (gethash side closed))) - sides))) + (remove-if (make-side-in-map-p map closed) sides))) -(defun day-17 (input) - (loop with map = (make-map input) - with todo = (let ((q (make-queue :priority-queue :compare (lambda (a b) +(defun next-steps-ultra-crucible (map pos dir steps closed) + (let (sides) + (when (< steps 10) + (push (list (point+ pos (getf *dirs* dir)) + dir + (1+ steps)) + sides)) + (when (> steps 3) + (loop for next in (getf *next-dirs* dir) + do (push (list (point+ pos (getf *dirs* next)) + next + 1) + sides))) + (remove-if (make-side-in-map-p map closed) sides))) + +(defun find-path-with-lowest-head-loss (map next-steps) + (loop with todo = (let ((q (make-queue :priority-queue :compare (lambda (a b) (< (fourth a) (fourth b)))))) (qpush q (list (cons 0 0) :right 0 0 nil)) @@ -45,11 +61,11 @@ with goal = (cons (1- (input-map-width map)) (1- (input-map-height map))) while (> (qsize todo) 0) - for (pos dir steps heat-loss history) = (qpop todo) + for (pos dir steps heat-loss) = (qpop todo) when (equal pos goal) do (return heat-loss) do (setf (gethash (list pos dir steps) closed) t) - do (loop for (next next-dir steps) in (next-steps map pos dir steps closed) + do (loop for (next next-dir steps) in (funcall next-steps map pos dir steps closed) for cost = (char-number (map-cell map next)) for next-heat-cost = (+ heat-loss cost) for existing = (queue-find todo (lambda (existing) @@ -65,4 +81,9 @@ (nth 2 existing-value) steps (nth 1 existing-value) next-dir)) ((null existing-value) - (qpush todo (list next next-dir steps next-heat-cost (cons pos history)))))))) + (qpush todo (list next next-dir steps next-heat-cost))))))) + +(defun day-17 (input) + (let ((map (make-map input))) + (values (find-path-with-lowest-head-loss map #'next-steps-crucible) + (find-path-with-lowest-head-loss map #'next-steps-ultra-crucible)))) diff --git a/t/day-17.lisp b/t/day-17.lisp @@ -4,7 +4,7 @@ (define-test test-day-17 () - (multiple-value-bind (task-1) + (multiple-value-bind (task-1 task-2) (aoc:run-day 17 "2413432311323 3215453535623 3255245654254 @@ -18,4 +18,5 @@ 1224686865563 2546548887735 4322674655533") - (assert= 102 task-1))) + (assert= 102 task-1) + (assert= 94 task-2)))