adventofcode2022

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

commit dae046eb5523b5e39bd17661f61fb520cb638fb2
parent 65dd74b013d4e656f3d4efb67eb3ae8e71d9d588
Author: Lukas Henkel <lh@entf.net>
Date:   Sat, 24 Dec 2022 12:02:12 +0100

Day 24 task 1

Diffstat:
Madventofcode2022.asd | 8++++++--
Ainput/day24.txt | 27+++++++++++++++++++++++++++
Asrc/day24.lisp | 137+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
At/day24.lisp | 24++++++++++++++++++++++++
4 files changed, 194 insertions(+), 2 deletions(-)

diff --git a/adventofcode2022.asd b/adventofcode2022.asd @@ -33,7 +33,9 @@ (:file "day19") (:file "day20") (:file "day21") - (:file "day22"))) + (:file "day22") + (:file "day23") + (:file "day24"))) (defsystem "adventofcode2022/test" :description "My solutions to the advent of code 2022" @@ -65,4 +67,6 @@ (:file "day19") (:file "day20") (:file "day21") - (:file "day22"))) + (:file "day22") + (:file "day23") + (:file "day24"))) diff --git a/input/day24.txt b/input/day24.txt @@ -0,0 +1,27 @@ +#.######################################################################################################################## +#<>v^<vv<v<><.^v><<.>v><<^^<v..<>.v^>^v<^><vv>.>^v>^>>v^v>><^><><<^><^>.^>^<vv>v>^>>^<^v.^<^v<.><.v><<.^v^.^<v^v<<vv><<v># +#<>.vv^^vv<^v.^><^v<>>.<<<.^<^<>v<v<<>v>^vv..<<.^>^>>>.<>>^.^<^<<<^<>vv>.<<><^>.^>.vv^^v..v^<v^<vv.^.>v<^<^.<>^^v>^>v^<^># +#<<>v>v>v.^<><^><>^>.v<<>.^v.v<<v<^^v>v<^^<<>^>vv<vvv>^v^.<>>^^^^<><vvv<v^>^<vv.><..><^>^<<^><^.v>>^>>>v>v>>vv^v<<.<v^<^># +#<^.vv><^>^^>v<.>^vvv>v^v>><v>><v<><^.>v^v<v<<<>v.^>>^>v>^.>><<<v.^^^v^.v>^^vv^<<.v^<^v.v<<>><><vv.vv<^..<vv^.^<>>>.<<^^># +#<^<v<.>vvvvvv^>>.^v>.<<v^^^><^<^^<^>v><>>><>>vv^v><^>v>>v.^>>>v^v^^^.^^>^v<.v^>^^v<vv.<.<^v>vv^v>^v>>v<^^>>^^<><^>v<v>.># +#<vvvv<<^<v^vvv<.^<vv>.>v<v><<^v>^^<^v<^>vv^.<^vvv<^>^^vv^.v.^^..><<>^.>...^<<^>^^<^vvv>.^<>>^.v^v.^<>v^<vvvv>^.<>v>><v<># +#>.^>.vv^<^^<v><><<>>>vv>.<><^^<>>v><<>>v^vv.>^.>v^^<^<^.>>v<<<vv<<>>.<^<><.<<^v^><>.<>^<<.^>^v<>^^>><<>vv.v<>v^^>>>>>v><# +#<.^<>.>.^>v><.^<>>>^^<^v^>^<^.>^^^v.<>vv><>v^v^v^^<^>^<<.v^>^v.<>.<^.>v><>>.<<v<^>>v>>>.^<><v<vv.<^^>^v<<<^^.<v<^>v>v^<<# +#><^>.<<<^..>>>^>.>^<vv.<.v^><>>>^<.v<^^^><>v.>.v^v<^^v><^.^.><^^<>^^v<>><^<.v>><>>>>.>^v<^v^<<^v>>.v<^<>vv<>v>vv.^<<<v.<# +#>.^^<<><v.>^^>>.^>^v>^>..>>>^v^<v^^^>v>>v>>v.^<>vv><>.<>vvvvv.vvv..><>v.vv<^v^v>^>^vv^<v<.^>>.>v^><<v>^v^>>.>^v><<^^^<v<# +#.^<>>.v<>vv<vvv^^>vv><<.^>><^.v>>^v<.v^<^v^.<vvv^^>^^>^>>>.^.>vvv>>^^^^<^^v>^>v^<v><v^<><><<^v<<<><><<v^.vv><^vv^v<<vv<># +#<..vvv>><.v<^><v.v^^^v>^^v<<^v<>^><^v>^vvv^<^v>>^>>^<v>^<<^v^v.^vv>^><^v<^v^v>vv>^<^^^v>^^^<.>^v.v^<^>>^>^^^^^^vv<.v^^><# +#<v><<v>>^v<>>v^^v<^v<<><<^><^<<^^>.<.^v>^>>v<>^><.^<<<.>^^v^vvv><<^>>^^<^^<><v.^v<<^..v^.<v>>^v.>^<^^v<<vvv^v<^<<<<<v>^># +#<v<<v^<^<^^v^vv<<<.>v<<><<^v^.^>><.v<^<v<^<<<<.<v^^vvv^>^^^>.><<><><<<^>v.>>>vv<.<v.><>^v^>^^^^.>v^<>.v>^.<v>v<^.v>vv<>># +#>v<v..<^v^<<<>><>>^<^v>>v>v^>vv^v<^.vv^vv>v<<<vv.v^.>^v><<v<vv>>^<.>vvv...v<^><>>.^v>v<^^>v^v<<>v>.^>><<<><<v^<v^.^v^>v># +#<<>^v>v>v<<<vvvv^^>v^..>..>^<>^>>><><<><v><^vv.>^v>v^v<<<vv><<.>><<<<<.<<<>^><v><vv^^v>^>>>><.^.^^>v<^<^>>.^>>^v.<>^>v>># +#>v<<<>^^>..^>>v.v^<><^>^^<<vv<<>>^<<>v^.<^><.v>>vv^v<v<^^v..>>^^^>^v>^v^^v^>^.<^>>>v^<><v>^.<>>^^<vv>>>^><^>>.<<>>v>vv<># +#<^^^..>>><>v>v>.>^.<.vv.vv<>v^vv<<^^>>v<^^<vv><^>><v>>>^^^><^^<.<^^>v>^^><v<vv^>vvv<^<..^>>>^v^v^^v>^^^.<.>v<^v><><>^^.># +#>^^>^^^^.<<.v^.><v<^^.<<<.><<><>.<<<^^><.>>..<>v^^^>^v<^>>.>v><^^vvv^>>^<v>v><^<>^<>>^^v>^.v>v<<>>>^v^vv<<<^..<>^><>>^>.# +#.^<<<^^vv<.>v<.<>.>v.^..^^.>.vv.v>^>v.^.v<>v>>^^<^<^^^>>^>vvv.<^>><^>><^^>^>..^><.<v>.<^>^^v^v.>v<v^^><<>>vv^vv><v<>v^<># +#<vvv><<>v<^<^.>..^<.<v^v^v>.^<^vv^v>v<vvv<>><>vv.vvv<^><^^>><>vv>^^^><>^<^^><^>.>v<>^.vv<v<<v^^>v<v.^^^><>^<v^<>.>.^^v^># +#>v.^>..^>v>v>^^<^v>..>..^<.^..>>v<>.<>.<v>>>vv^<<>>>v<v^v^^vv<^vvvv<^v<^v<^^>>v>v><v><<v><v><^v<v>^>^^<>v.v<<^<.<><<<>.># +#>>v><..^^^.<v<^^<v<><<<<<^^^<>^^v^.>vv<v><<>>^^^<v^vv^v^<>...>^.<v><<^^v^..><>vv>v^>^v>.vv<v<^.<<<v^<^v^<<v^.<.^<.>v^<><# +#>^v<..<>>v^v>v>v^v^<^<^^<..><v>^^>><<><>.^v.v<^>^<v><.^vv^.>v^>^v>^^v^>v<v^...><<<>><>>>^<vv<<^^^.<^vv^^^.v<vv<<<>>^><^<# +#>><<v<>>>vv>>^^^v^^^>^>><v<>><^vv><>>>^.v^>^>^vv<>>..^v.^^^vvvv<><^><^v>vv<<^vv>^>v..<><.>^^^v.v>vvvv>>>><<vv<>.<v^<vv>># +########################################################################################################################.# diff --git a/src/day24.lisp b/src/day24.lisp @@ -0,0 +1,137 @@ +(defpackage #:adventofcode2022/day24 + (:use #:cl #:adventofcode2022) + (:import-from #:queues + #:make-queue + #:qpush + #:qpop)) +(in-package #:adventofcode2022/day24) + +(defparameter *neighbor-deltas* (list '(-1 0) + '(0 -1) + '(1 0) + '(0 1))) + +(defun coord+ (a b) + (list (+ (car a) (car b)) + (+ (cadr a) (cadr b)))) + +(defun analyze-inputs (inputs) + (loop with blizzards = (make-hash-table :test 'equal) + with min-pos = (list 1 1) + with max-pos = (list 0 0) + with start-pos = (list 1 0) + with end-pos = (list 0 0) + for row in inputs + for y from 0 + when (= y 0) + do (setf (car max-pos) (- (length row) 2) + (car end-pos) (- (length row) 2)) + + do (loop for column across row + for x from 0 + for blizzard-direction = (case column + (#\^ :up) + (#\< :left) + (#\> :right) + (#\v :down)) + when blizzard-direction + do (setf (gethash (list x y) blizzards) + (append (gethash (list x y) blizzards) + (list blizzard-direction)))) + finally (progn + (setf (cadr max-pos) (1- y) + (cadr end-pos) y) + (return (values + blizzards + min-pos + max-pos + start-pos + end-pos))))) + +(defun get-next-blizzard-state (blizzards min-pos max-pos) + (loop with next-blizzards = (make-hash-table :test 'equal) + with width = (1+ (- (car max-pos) (car min-pos))) + with height = (1+ (- (cadr max-pos) (cadr min-pos))) + for pos being the hash-key of blizzards using (hash-value dirs) + do (loop for dir in dirs + for next-pos = (copy-seq pos) + do (case dir + (:up (decf (cadr next-pos))) + (:left (decf (car next-pos))) + (:right (incf (car next-pos))) + (:down (incf (cadr next-pos)))) + do (setf next-pos (list + (+ (mod (- (car next-pos) (car min-pos)) + width) + (car min-pos)) + (+ (mod (- (cadr next-pos) (cadr min-pos)) + height) + (cadr min-pos)))) + do (setf (gethash next-pos next-blizzards) + (append (gethash next-pos next-blizzards) + (list dir)))) + finally (return next-blizzards))) + +(defun print-map (min-pos max-pos current-pos blizzards) + (loop for y from (cadr min-pos) to (cadr max-pos) + do (loop for x from (car min-pos) to (car max-pos) + for pos = (list x y) + for bs = (gethash pos blizzards) + do (format t "~A" (cond + ((equal pos current-pos) "E") + ((> (length bs) 9) "*") + ((> (length bs) 1) (length bs)) + (bs (case (car bs) + (:up "^") + (:left "<") + (:right ">") + (:down "v"))) + (t ".")))) + do (format t "~%")) + (format t "~%")) + +(defun test-blizzards (inputs rounds) + (multiple-value-bind (blizzards min-pos max-pos start-pos end-pos) + (analyze-inputs inputs) + (declare (ignore start-pos end-pos)) + (loop with current-blizzards = blizzards + initially (print-map min-pos max-pos (list 0 0) current-blizzards) + repeat rounds + do (setf current-blizzards (get-next-blizzard-state current-blizzards min-pos max-pos)) + do (print-map min-pos max-pos (list 0 0) current-blizzards)))) + +(defun task1 (inputs) + (multiple-value-bind (blizzards min-pos max-pos start-pos end-pos) + (analyze-inputs inputs) + (loop named outer + with visited = (make-hash-table :test 'equal) + with blizzard-states = (make-hash-table) + with queue = (make-queue :simple-queue) + initially (qpush queue (list 0 start-pos)) + (setf (gethash 0 blizzard-states) blizzards) + for (minute current-pos) = (qpop queue) + while current-pos + for next-minute = (1+ minute) + for current-blizzards = (gethash minute blizzard-states) + for next-blizzards = (or (gethash next-minute blizzard-states) + (setf (gethash next-minute blizzard-states) + (get-next-blizzard-state current-blizzards min-pos max-pos))) + do (loop for neighbor-delta in *neighbor-deltas* + for next-pos = (coord+ current-pos neighbor-delta) + when (equal next-pos end-pos) + do (return-from outer next-minute) + when (and (>= (car next-pos) (car min-pos)) + (>= (cadr next-pos) (cadr min-pos)) + (<= (car next-pos) (car max-pos)) + (<= (cadr next-pos) (cadr max-pos)) + (null (gethash next-pos next-blizzards)) + (null (gethash (list next-pos next-minute) visited))) + do (qpush queue (list next-minute next-pos)) + and do (setf (gethash (list next-pos next-minute) visited) t)) + when (not (gethash current-pos next-blizzards)) + do (qpush queue (list next-minute current-pos))))) + +(define-day 24 + () + #'task1 + nil) diff --git a/t/day24.lisp b/t/day24.lisp @@ -0,0 +1,24 @@ +(in-package #:adventofcode2022/test) + +(define-constant +testdata-day24+ "#.###### +#>>.<^<# +#.<..<<# +#>v.><># +#<^v^^># +######.#" + :test 'equal) + +(define-constant +testdata-day24-simple+ "#.##### +#.....# +#>....# +#.....# +#...v.# +#.....# +#####.#" + :test 'equal) + +(def-test day24-task1 () + (is-true + (= 18 + (run-task 24 1 + (make-string-input-stream +testdata-day24+)))))