advent_of_code_2022

My (attempted) solutions to the 2022 Advent of Code
git clone https://git.eamoncaddigan.net/advent_of_code_2022.git
Log | Files | Refs | README

commit c1f3cd0bf3859795b4ebce2aa04094990424224c
parent b0b0af461faa5613705241360c59e33741d28575
Author: Eamon Caddigan <eamon.caddigan@gmail.com>
Date:   Tue,  3 Jan 2023 22:16:50 -0800

Solution to day 24, part 2.

Only needed relatively minor updates to make part 2 work, but it's
pretty hacky (and slow). Oh well, a star's a star.

Diffstat:
Msrc/day_24.jl | 63++++++++++++++++++++++++++++++++++++++++++++++++++-------------
1 file changed, 50 insertions(+), 13 deletions(-)

diff --git a/src/day_24.jl b/src/day_24.jl @@ -61,21 +61,22 @@ function setmaptime!(blizzardmap::BlizzardMap, newtime::Int) if timeoffset == 0 blizzardmap else - oldmap = copy(blizzardmap.blizzards) + newmap = similar(blizzardmap.blizzards) for y = 1:size(blizzardmap, 1), x = 1:size(blizzardmap, 2) - blizzardmap.blizzards[y, x, 1] = oldmap[ + newmap[y, x, 1] = blizzardmap.blizzards[ 1+mod(y-1+timeoffset, size(blizzardmap, 1)), x, 1 ] - blizzardmap.blizzards[y, x, 2] = oldmap[ + newmap[y, x, 2] = blizzardmap.blizzards[ 1+mod(y-1-timeoffset, size(blizzardmap, 1)), x, 2 ] - blizzardmap.blizzards[y, x, 3] = oldmap[ + newmap[y, x, 3] = blizzardmap.blizzards[ y, 1+mod(x-1+timeoffset, size(blizzardmap, 2)), 3 ] - blizzardmap.blizzards[y, x, 4] = oldmap[ + newmap[y, x, 4] = blizzardmap.blizzards[ y, 1+mod(x-1-timeoffset, size(blizzardmap, 2)), 4 ] end + blizzardmap.blizzards = newmap blizzardmap end end @@ -136,11 +137,14 @@ function manhattandist(node::Node, blizzardmap::BlizzardMap) size(blizzardmap, 1) - node[2] + size(blizzardmap, 2) - node[3] + 1 end +""" +Reconstruct the path in reverse-chronological order. +""" function reconstruct_path(camefrom::Dict{Node, Node}, current::Node) totalpath = [current] while current ∈ keys(camefrom) current = camefrom[current] - pushfirst!(totalpath, current) + push!(totalpath, current) end totalpath end @@ -149,16 +153,17 @@ end Find the shortest path from the beginning to end of the map. This looks like A* search (I even cribbed from wikipedia's pseudocode, again), -but I think it's actually just breadth-first search. Might need to fix that -depending on the non-example input and part 2 requirements. +but I think it just reduces to a slightly smarter breadth-first search. Might +need to fix that depending on the non-example input and part 2 requirements. +This also changes blizzardmap. """ -function navigatemap(blizzardmap::BlizzardMap, h::Function) +function navigatemap!(blizzardmap::BlizzardMap, h::Function = manhattandist) start = (0, 0, 1) camefrom = Dict{Node, Node}() # This is usually a map giving the lowest known cost path from start to - # each known. Since the first element of each node codes that implicitly, - # we can just use a set. + # each known node. Since the first element of each node codes that + # implicitly, we can just use a set. gscore = Set([start]) # The set of discovered nodes @@ -168,6 +173,7 @@ function navigatemap(blizzardmap::BlizzardMap, h::Function) current = dequeue!(openset) if isgoal(current, blizzardmap) + setmaptime!(blizzardmap, current[1]) return reconstruct_path(camefrom, current) end @@ -183,12 +189,43 @@ function navigatemap(blizzardmap::BlizzardMap, h::Function) end function part_1(input) - length(navigatemap(BlizzardMap(input), manhattandist))-1 + navigatemap!(BlizzardMap(input))[1][1] end @assert part_1(example) == 18 @info part_1(input) +""" +Flip a map, as if you are turning around and retracing your steps. + +As hacks go, I'm not sure where this approach lands between 'clever' and +'hideous', but if we can flip the map around, then solving part 2 is just a +matter of solving part 1 two additional times. +""" +function flipmap!(blizzardmap::BlizzardMap) + newmap = similar(blizzardmap.blizzards) + + for y = 1:size(blizzardmap, 1), x = 1:size(blizzardmap, 2) + oldy = size(blizzardmap, 1) - y + 1 + oldx = size(blizzardmap, 2) - x + 1 + for z = 1:4 + oldz = z % 2 == 1 ? z + 1 : z - 1 + newmap[y, x, z] = blizzardmap.blizzards[oldy, oldx, oldz] + end + end + + blizzardmap.blizzards = newmap + blizzardmap.timestep = 0 + blizzardmap +end + function part_2(input) - nothing + blizzardmap = BlizzardMap(input) + steps = 0 + for i = 1:3 + steps += navigatemap!(blizzardmap)[1][1] + i < 3 && flipmap!(blizzardmap) + end + steps end +@assert part_2(example) == 54 @info part_2(input)