|
|
|
@ -0,0 +1,53 @@ |
|
|
|
-module(day8). |
|
|
|
|
|
|
|
-export([solve/1]). |
|
|
|
|
|
|
|
-compile(export_all). |
|
|
|
|
|
|
|
solve(Input) -> |
|
|
|
Grid = parse_grid(Input), |
|
|
|
{map_size(visible_trees(Grid)), none}. |
|
|
|
|
|
|
|
visible_trees({_, H, W} = Grid) -> |
|
|
|
%top |
|
|
|
Visible0 = #{}, |
|
|
|
%Left |
|
|
|
Visible1 = range_fold(0, H-1, fun(Row, Acc) -> element(2, grid_traverse(fun visible_path/3, {-1, Acc}, Grid, {0, Row}, {1, 0})) end, Visible0), |
|
|
|
%Right |
|
|
|
Visible2 = range_fold(0, H-1, fun(Row, Acc) -> element(2, grid_traverse(fun visible_path/3, {-1, Acc}, Grid, {W-1, Row}, {-1, 0})) end, Visible1), |
|
|
|
%Top |
|
|
|
Visible3 = range_fold(0, W-1, fun(Col, Acc) -> element(2, grid_traverse(fun visible_path/3, {-1, Acc}, Grid, {Col, 0}, {0, 1})) end, Visible2), |
|
|
|
%Bottom |
|
|
|
range_fold(0, W-1, fun(Col, Acc) -> element(2, grid_traverse(fun visible_path/3, {-1, Acc}, Grid, {Col, H-1}, {0, -1})) end, Visible3). |
|
|
|
|
|
|
|
visible_path(Tree, Position, {MaxHeight, Visible}) when Tree > MaxHeight -> {Tree, Visible#{Position => []}}; |
|
|
|
visible_path(_Tree, _Position, State) -> State. |
|
|
|
|
|
|
|
grid_traverse(Fun, AccIn, Grid, {XPos, YPos}, {XVec, YVec}) -> |
|
|
|
case grid_at(Grid, XPos, YPos) of |
|
|
|
error -> AccIn; |
|
|
|
{ok, Item} -> grid_traverse(Fun, Fun(Item, {XPos, YPos}, AccIn), Grid, {XPos+XVec, YPos+YVec}, {XVec, YVec}) |
|
|
|
end. |
|
|
|
|
|
|
|
parse_grid(Data) -> |
|
|
|
{W, H} = dimensions(Data), |
|
|
|
{Data, H, W}. |
|
|
|
|
|
|
|
dimensions(Grid) -> dimensions(Grid, 1, 0). |
|
|
|
dimensions(<<>>, Height, Width) -> {Width, Height}; |
|
|
|
dimensions(<<$\n>>, Height, Width) -> {Width, Height}; |
|
|
|
dimensions(<<$\n, Rest/binary>>, Height, _Width) -> |
|
|
|
dimensions(Rest, Height+1, 0); |
|
|
|
dimensions(<<_Digit, Rest/binary>>, Height, Width) -> |
|
|
|
dimensions(Rest, Height, Width+1). |
|
|
|
|
|
|
|
grid_at({_Data, _H, _W}, X, Y) when X < 0 orelse Y < 0 -> error; |
|
|
|
grid_at({_Data, H, W}, X, Y) when X >= W orelse Y >= H -> error; |
|
|
|
grid_at({Data, _H, W}, X, Y) -> |
|
|
|
Index = X + Y * (W+1), |
|
|
|
<<_:Index/binary, Tree, _/binary>> = Data, |
|
|
|
{ok, Tree-$0}. |
|
|
|
|
|
|
|
range_fold(End, End, Fun, Acc) -> Fun(End, Acc); |
|
|
|
range_fold(Start, End, Fun, Acc) when Start < End -> range_fold(Start+1, End, Fun, Fun(Start, Acc)); |
|
|
|
range_fold(Start, End, Fun, Acc) when Start > End -> range_fold(Start-1, End, Fun, Fun(Start, Acc)). |