Something I keep having use for in these problems where you have to walk around in a matrix is to use a list of “vectors” instead of hardcoding the movements.
This is for part 2, made a more “clever”/convoluted solution for part 1… but I had no use for in part 2.
defmodule VisibilityChecker do
def max_visibility(grid) do
heights = for {rows, y} <- Enum.with_index(grid),
{h, x} <- Enum.with_index(rows), into: %{} do
{{x, y}, h}
end
heights
|> Stream.map(&elem(&1, 0))
|> Stream.map(&score(&1, heights))
|> Enum.max()
end
@directions [{-1, 0},{1, 0},{0, -1},{0, 1},]
defp score(pos, heights) do
for dir <- @directions, reduce: 1 do
score -> score * visible(heights, pos, dir, heights[pos], 0)
end
end
defp visible(heights, pos, direction, max_height, line_height) do
new_pos = translate(pos, direction)
case heights[new_pos] do
nil -> 0
tree_height when tree_height >= max_height -> 1
tree_height when tree_height >= line_height ->
1 + visible(heights, new_pos, direction, max_height, tree_height)
_ ->
1 + visible(heights, new_pos, direction, max_height, line_height)
end
end
defp translate({x, y}, {dx, dy}), do: {x + dx, y + dy}
end
# input is a list of lists with the three heights [ [ 1, 2], [ 3, 4 ]]
#
# 1 2
# 3 4
#
# would be
# [
#. [ 1, 2 ],
# [ 3, 4 ]
# ]
VisibilityChecker.max_visibility(input)






















