commit - 2b9c8dd94c27169b528d83a00011cc6f90e4a151
commit + 66456ba8fb5ceb69ad7ea2f2c8fcc757a6b6e405
blob - 660c062466a831c0ef2e5c93314490beeee4977a
blob + 1036bc1e737e5c62bc10c1cd37ac1db41248b47a
--- src/day-17.lisp
+++ src/day-17.lisp
: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))
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))
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)
(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))))
blob - 69b37d077a002083a45fe874593fa7fe0bedb42b
blob + cea9875edf37d4f4fda410891d36561f47df7383
--- t/day-17.lisp
+++ t/day-17.lisp
(define-test test-day-17
()
- (multiple-value-bind (task-1)
+ (multiple-value-bind (task-1 task-2)
(aoc:run-day 17 "2413432311323
3215453535623
3255245654254
1224686865563
2546548887735
4322674655533")
- (assert= 102 task-1)))
+ (assert= 102 task-1)
+ (assert= 94 task-2)))