My (attempted) solutions to the 2022 Advent of Code
Log | Files | Refs | README

```commit c1f3cd0bf3859795b4ebce2aa04094990424224c
parent b0b0af461faa5613705241360c59e33741d28575
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)
```