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.
106 lines
2.7 KiB
106 lines
2.7 KiB
#!/usr/bin/env julia
|
|
|
|
using Test
|
|
|
|
function is_visible(tree_map, i, j)
|
|
v = tree_map[i, j]
|
|
less_v(x) = x < v
|
|
if all(less_v, tree_map[i, 1:j-1])
|
|
return true
|
|
end
|
|
if all(less_v, tree_map[i, j+1:end])
|
|
return true
|
|
end
|
|
if all(less_v, tree_map[1:i-1, j])
|
|
return true
|
|
end
|
|
if all(less_v, tree_map[i+1:end, j])
|
|
return true
|
|
end
|
|
return false
|
|
end
|
|
|
|
function visible_trees_at(tree_map, i, j)
|
|
nrows, ncols = size(tree_map)
|
|
v = tree_map[i, j]
|
|
ge_v(x) = x >= v
|
|
up_idx = findfirst(ge_v, tree_map[i-1:-1:1, j])
|
|
up_score = up_idx === nothing ? i - 1 : up_idx
|
|
down_idx = findfirst(ge_v, tree_map[i+1:end, j])
|
|
down_score = down_idx === nothing ? nrows - i : down_idx
|
|
left_idx = findfirst(ge_v, tree_map[i, j-1:-1:1])
|
|
left_score = left_idx === nothing ? j - 1 : left_idx
|
|
right_idx = findfirst(ge_v, tree_map[i, j+1:end])
|
|
right_score = right_idx === nothing ? ncols - j : right_idx
|
|
return (up_score, down_score,left_score, right_score)
|
|
end
|
|
|
|
function scenic_score(tree_map, i, j)
|
|
return prod(visible_trees_at(tree_map, i, j))
|
|
end
|
|
|
|
function read_uint_matrix(io)
|
|
lines = readlines(io)
|
|
matrix = Matrix{UInt8}(undef, length(lines), length(lines[1]))
|
|
for (i, line) in enumerate(lines)
|
|
matrix[i, :] = parse.(UInt8, collect(line))
|
|
end
|
|
return matrix
|
|
end
|
|
|
|
function count_visible(tree_map)
|
|
nrows, ncols = size(tree_map)
|
|
nvisible = 2 * (nrows + ncols) - 4
|
|
nvisible += sum([is_visible(tree_map, i, j) ? 1 : 0
|
|
for j in 2:nrows-1
|
|
for i in 2:ncols-1])
|
|
return nvisible
|
|
end
|
|
|
|
function max_scenic_score(tree_map)
|
|
nrows, ncols = size(tree_map)
|
|
return maximum([scenic_score(tree_map, i, j)
|
|
for j in 2:nrows-1
|
|
for i in 2:ncols-1])
|
|
end
|
|
|
|
function visiblility_map(tree_map)
|
|
nrows, ncols = size(tree_map)
|
|
vmap = Matrix{NTuple{4, Int}}(undef, nrows-2, ncols-2)
|
|
for j in 2:nrows-1
|
|
for i in 2:ncols-1
|
|
vmap[i-1, j-1] = visible_trees_at(tree_map, i, j)
|
|
end
|
|
end
|
|
return vmap
|
|
end
|
|
|
|
function test()
|
|
@testset "visible trees" verbose=true begin
|
|
@test count_visible(read_uint_matrix("example.txt")) == 21
|
|
@test count_visible(read_uint_matrix("input.txt")) == 1845
|
|
end
|
|
@testset "max score" verbose=true begin
|
|
@test max_scenic_score(read_uint_matrix("example.txt")) == 8
|
|
@test max_scenic_score(read_uint_matrix("input.txt")) == 230112
|
|
end
|
|
end
|
|
|
|
function main()
|
|
if size(ARGS, 1) == 0
|
|
test()
|
|
else
|
|
infile = ARGS[1]
|
|
println("infile = ", infile)
|
|
tree_map = read_uint_matrix(infile)
|
|
println("matrix: ", tree_map)
|
|
println("visible: ", count_visible(tree_map))
|
|
println("max score: ", max_scenic_score(tree_map))
|
|
println("visible at: ")
|
|
display(visiblility_map(tree_map))
|
|
println()
|
|
end
|
|
end
|
|
|
|
main()
|