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.
147 lines
3.2 KiB
147 lines
3.2 KiB
#!/usr/bin/env julia
|
|
|
|
#= --- Part Two ---
|
|
|
|
Next, you need to find the largest basins so you know what areas are most important to avoid.
|
|
|
|
A basin is all locations that eventually flow downward to a single low point. Therefore, every low point has a basin, although some basins are very small. Locations of height 9 do not count as being in any basin, and all other locations will always be part of exactly one basin.
|
|
|
|
The size of a basin is the number of locations within the basin, including the low point. The example above has four basins.
|
|
|
|
The top-left basin, size 3:
|
|
|
|
2199943210
|
|
3987894921
|
|
9856789892
|
|
8767896789
|
|
9899965678
|
|
|
|
The top-right basin, size 9:
|
|
|
|
2199943210
|
|
3987894921
|
|
9856789892
|
|
8767896789
|
|
9899965678
|
|
|
|
The middle basin, size 14:
|
|
|
|
2199943210
|
|
3987894921
|
|
9856789892
|
|
8767896789
|
|
9899965678
|
|
|
|
The bottom-right basin, size 9:
|
|
|
|
2199943210
|
|
3987894921
|
|
9856789892
|
|
8767896789
|
|
9899965678
|
|
|
|
Find the three largest basins and multiply their sizes together. In the above example, this is 9 * 14 * 9 = 1134.
|
|
|
|
What do you get if you multiply together the sizes of the three largest basins?
|
|
=#
|
|
|
|
infile = length(ARGS) > 0 ? ARGS[1] : "input.txt"
|
|
println("infile = ", infile)
|
|
|
|
depth_map = reduce(vcat, [parse.(Int, split(line, ""))'
|
|
for line in eachline(infile)])
|
|
|
|
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 neighbors(m, y, x)
|
|
nrows, ncols = size(m)
|
|
v = eltype(m)[]
|
|
if x > 1
|
|
push!(v, m[y, x-1])
|
|
end
|
|
if x < ncols
|
|
push!(v, m[y, x+1])
|
|
end
|
|
if y > 1
|
|
push!(v, m[y-1, x])
|
|
end
|
|
if y < nrows
|
|
push!(v, m[y+1, x])
|
|
end
|
|
return v
|
|
end
|
|
|
|
function flow_neighbors(m, y, x, flow_map, flow_count)
|
|
nrows, ncols = size(m)
|
|
nidx = neighbor_idx(nrows, ncols, y, x)
|
|
v = m[y, x]
|
|
if v == 9
|
|
flow_count[y, x] = 0
|
|
return
|
|
end
|
|
smallest_v = v
|
|
flow_idx = flow_map[y, x]
|
|
for idx in nidx
|
|
if m[idx] < smallest_v
|
|
smallest_v = m[idx]
|
|
flow_idx = flow_map[idx]
|
|
while flow_map[flow_idx] != flow_idx
|
|
flow_idx = flow_map[flow_idx]
|
|
end
|
|
end
|
|
end
|
|
if smallest_v != v
|
|
flow_count[flow_idx] += flow_count[y, x]
|
|
flow_count[y, x] = 0
|
|
flow_map[y, x] = flow_idx
|
|
end
|
|
#println(y, "x", x)
|
|
#display(flow_count)
|
|
#println()
|
|
end
|
|
|
|
function flow_all(m)
|
|
total = 0
|
|
nrows, ncols = size(m)
|
|
flow_count = ones(Int, nrows, ncols)
|
|
flow_map = reshape([CartesianIndex(y, x)
|
|
for x in 1:ncols
|
|
for y in 1:nrows], nrows, ncols)
|
|
for x in 1:ncols
|
|
for y in 1:nrows
|
|
flow_neighbors(m, y, x, flow_map, flow_count)
|
|
end
|
|
end
|
|
return flow_map, flow_count
|
|
end
|
|
|
|
map, count = flow_all(depth_map)
|
|
|
|
if (length(depth_map) < 100)
|
|
display(count)
|
|
println()
|
|
end
|
|
|
|
basins = sort(filter(x -> x > 0, count))
|
|
display(basins)
|
|
println()
|
|
|
|
println("nbasins = ", length(basins))
|
|
println("largest_prod = ", prod(basins[end-2:end]))
|