You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

193 lines
5.1 KiB

#!/usr/bin/env julia
#=
--- Day 15: Chiton ---
You've almost reached the exit of the cave, but the walls are getting closer together. Your submarine can barely still fit, though; the main problem is that the walls of the cave are covered in chitons, and it would be best not to bump any of them.
The cavern is large, but has a very low ceiling, restricting your motion to two dimensions. The shape of the cavern resembles a square; a quick scan of chiton density produces a map of risk level throughout the cave (your puzzle input). For example:
1163751742
1381373672
2136511328
3694931569
7463417111
1319128137
1359912421
3125421639
1293138521
2311944581
You start in the top left position, your destination is the bottom right position, and you cannot move diagonally. The number at each position is its risk level; to determine the total risk of an entire path, add up the risk levels of each position you enter (that is, don't count the risk level of your starting position unless you enter it; leaving it adds no risk to your total).
Your goal is to find a path with the lowest total risk. In this example, a path with the lowest total risk is highlighted here:
1163751742
1381373672
2136511328
3694931569
7463417111
1319128137
1359912421
3125421639
1293138521
2311944581
The total risk of this path is 40 (the starting position is never entered, so its risk is not counted).
What is the lowest total risk of any path from the top left to the bottom right?
=#
infile = length(ARGS) > 0 ? ARGS[1] : "input.txt"
println("infile = ", infile)
risk_map = reduce(vcat, [parse.(Int, split(line, ""))'
for line in eachline(infile)])
function least_risk(E)
nrows, ncols = size(E)
row = nrows
col = ncols
cost = 0
path = zeros(Int, size(E))
while row > 1 || col > 1
cost += E[row, col]
path[row, col] = 1
if col == 1
row -= 1
elseif row == 1
col -= 1
else
if E[row, col-1] < E[row-1, col]
col -= 1
else
row -= 1
end
end
end
return cost, path
end
function neighbor_idx(nrows, ncols, y, x)
v = CartesianIndex[]
if x > 1
push!(v, CartesianIndex(y, x-1))
end
if x < ncols
push!(v, CartesianIndex(y, x+1))
end
if y > 1
push!(v, CartesianIndex(y-1, x))
end
if y < nrows
push!(v, CartesianIndex(y+1, x))
end
return v
end
function get_costs(R)
costs = zeros(Int, size(R))
dirs = zeros(Int, size(R))
nrows, ncols = size(R)
for col in 2:ncols
costs[1, col] = costs[1, col-1] + R[1, col]
end
for row in 2:nrows
costs[row, 1] = costs[row-1, 1] + R[row, 1]
for col in 2:ncols
if costs[row-1, col] < costs[row, col-1]
dirs[row, col] = 1
costs[row, col] = costs[row-1, col] + R[row, col]
else
costs[row, col] = costs[row, col-1] + R[row, col]
end
end
end
if false
# more passes
for i in 1:max(nrows, ncols)
for col in ncols-1:-1:1
rcost = costs[end, col+1] + R[end, col]
if rcost < costs[end, col]
costs[end, col] = rcost
end
end
for row in nrows-1:-1:1
dcost = costs[row+1, end] + R[row, end]
if dcost < costs[row, end]
costs[row, end] = dcost
end
for col in ncols-1:-1:1
rcost = costs[row, col+1] + R[row, col]
if rcost < costs[row, col]
costs[row, col] = rcost
end
dcost = costs[row+1, col] + R[row, col]
if dcost < costs[row, col]
costs[row, col] = dcost
end
end
end
end
end
for row in nrows:-1:1
for col in ncols:-1:1
idx = neighbor_idx(nrows, ncols, row, col)
c = minimum(costs[i] for i in idx) + R[row, col]
if c < costs[row, col]
costs[row, col] = c
end
end
end
for row in nrows:-1:1
for col in 1:ncols
idx = neighbor_idx(nrows, ncols, row, col)
c = minimum(costs[i] for i in idx) + R[row, col]
if c < costs[row, col]
costs[row, col] = c
end
end
end
for row in 1:nrows
for col in ncols:-1:1
idx = neighbor_idx(nrows, ncols, row, col)
c = minimum(costs[i] for i in idx) + R[row, col]
if c < costs[row, col]
costs[row, col] = c
end
end
end
for row in 1:nrows
for col in 1:ncols
idx = neighbor_idx(nrows, ncols, row, col)
c = minimum(costs[i] for i in idx) + R[row, col]
if c < costs[row, col]
costs[row, col] = c
end
end
end
return costs, dirs
end
#=
cost, path = least_risk(risk_map)
display(path)
println()
println("cost = ", cost)
=#
costs, dirs = get_costs(risk_map)
display(costs)
println()
println("cost = ", costs[end, end])