advent2022

Advent of Code 2022 Solutions
git clone https://todayiwilllaunchmyinfantsonintoorbit.com/advent2022.git
Log | Files | Refs

commit e3c183033e6829f9ee1d3259430cdba48b473b59
parent dd52ea67739b8e0b7b3409f84f6b4583e4f23a02
Author: Decay <decay@todayiwilllaunchmyinfantsonintoorbit.com>
Date:   Mon, 12 Dec 2022 16:42:46 -0800

Day 12 in Julia

Slow and inefficient, please do not copy this implementation of Dijkstra's
algorithm or you will be sad.

Diffstat:
A12/12.jl | 108+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 108 insertions(+), 0 deletions(-)

diff --git a/12/12.jl b/12/12.jl @@ -0,0 +1,108 @@ +function popmin!(avail, dist) + local min = () + local mindist = length(dist) + for v in avail + if (dist[v[1], v[2]] < mindist) + mindist = dist[v[1], v[2]] + min = v + end + end + delete!(avail, min) + return min +end + +# Slow and brute force implementation; would be much better using a priority queue implementation +function dijkstra(map, width, height, startpos, searchbackward::Bool) + # Initialize our data structures + dist = Array{Int32, 2}(undef, height, width) + prev = Array{Tuple, 2}(undef, height, width) + avail = Set() + for row = 1:height + for col = 1:width + push!(avail, (row, col)) + prev[row, col] = () + if (row != startpos[1] || col != startpos[2]) + dist[row, col] = (height * width) # Greater than max possible distance + else + dist[row, col] = 0 + end + end + end + + while length(avail) > 0 + next = popmin!(avail, dist) + + # Nothing else is accessible + if next == () + return (dist, prev) + end + + # Find all neighbors of next still in avail + for n in [(next[1] - 1, next[2]), (next[1] + 1, next[2]), + (next[1], next[2] - 1), (next[1], next[2] + 1)] + row = n[1] + col = n[2] + if row >= 1 && row <= height && col >= 1 && col <= width && in(n, avail) + if searchbackward + elevationok = (map[n[1]][n[2]] - map[next[1]][next[2]]) >= -1 + else + elevationok = (map[n[1]][n[2]] - map[next[1]][next[2]]) <= 1 + end + if elevationok + # There's a path to n from next + alt = dist[next[1], next[2]] + 1 + if alt < dist[n[1], n[2]] + dist[n[1], n[2]] = alt + prev[n[1], n[2]] = next + end + end + end + end + end + + return (dist, prev) +end + +function dijkstra(map, width, height, startpos, endpos::Tuple) + (dist, prev) = dijkstra(map, width, height, startpos, false) + + return dist[endpos[1], endpos[2]] +end + +begin + map = open("input", "r") do input + readlines(input) + end + mapwidth = length(map[1]) + mapheight = length(map) + local startrow = local startcol = local endrow = local endcol = 0 + for row = 1:mapheight + for col = 1:mapwidth + if map[row][col] == 'S' + startrow = row + startcol = col + rowtochange = map[row] + map[row] = rowtochange[1:col - 1] * 'a' * rowtochange[col + 1:end] + elseif map[row][col] == 'E' + endrow = row + endcol = col + rowtochange = map[row] + map[row] = rowtochange[1:col - 1] * 'z' * rowtochange[col + 1:end] + end + end + end + + dist = dijkstra(map, mapwidth, mapheight, (startrow, startcol), (endrow, endcol)) + println("Shortest distance to E (star 1): ", dist) + + (distmatrix, prev) = dijkstra(map, mapwidth, mapheight, (endrow, endcol), true) + local mindist = mapwidth * mapheight + for row = 1:mapheight + for col = 1:mapwidth + if map[row][col] == 'a' && distmatrix[row, col] < mindist + mindist = distmatrix[row, col] + end + end + end + println("Shortest distance to E from any starting point (star 2):", mindist) +end