diff --git a/day15/part2.jl b/day15/part2.jl index c86ccbf..208a1ac 100755 --- a/day15/part2.jl +++ b/day15/part2.jl @@ -171,10 +171,35 @@ function neighbor_idx(nrows, ncols, y, x) return v end +function relax(nrows, ncols, R, costs, row, col; first=false) + idx = neighbor_idx(nrows, ncols, row, col) + c = minimum(costs[i] for i in idx) + R[row, col] + if first || c < costs[row, col] + costs[row, col] = c + return true + end + return false +end + +function relax_all(nrows, ncols, R, costs) + relaxed = false + for row in 1:nrows + for col in 1:ncols + v_relaxed = relax(nrows, ncols, R, costs, row, col) + relaxed = relaxed || v_relaxed + end + end + return relaxed +end + function get_costs(R) costs = zeros(Int, size(R)) dirs = zeros(Int, size(R)) nrows, ncols = size(R) + + # first pass, unconditional update looking only right/down. Avoids + # having to add an infinity value + costs[1,1] = 0 for col in 2:ncols costs[1, col] = costs[1, col-1] + R[1, col] end @@ -190,90 +215,24 @@ function get_costs(R) 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 i in 1:max(nrows, ncols) + edges = ( (nrows-2)*(ncols-2)*4 + +(nrows+ncols-4)*3 + +4*2 ) + max_passes = (nrows*ncols - 1) * edges - 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 + i = 1 + while i <= max_passes + relaxed = relax_all(nrows, ncols, R, costs) + if !relaxed + break end - + i += 1 end + println("passes ", i) return costs, dirs end -#= -cost, path = least_risk(risk_map) - -display(path) -println() - -println("cost = ", cost) -=# - costs, dirs = get_costs(risk_map) if length(costs) < 1000