Yes, or perhaps just well suited to Erlang. And unlike yesterday, it’s not a test of how efficiently you can write a file parser or manipulate text in your favourite editor.
I feel happy enough with my code today to post it (although having seen it, I like @ danilagamma’s from_to/2
better than my dir/2
- though I’d implement it as clauses rather than a case
):
p1(InputData) ->
count_points(fun points_p1/2, InputData).
p2(InputData) ->
count_points(fun points_p2/2, InputData).
count_points(F, InputData) ->
AllPoints = lists:foldl(
fun(E, A) ->
maps:put(E, maps:get(E, A, 0) + 1, A)
end,
#{},
lists:flatten([F(StartPos, EndPos) || {StartPos, EndPos} <- InputData])),
maps:size(maps:filter(fun(_K, V) -> V >= 2 end, AllPoints)).
points_p1({X1, Y}, {X2, Y}) ->
[{X, Y} || X <- lists:seq(X1, X2, dir(X1, X2))];
points_p1({X, Y1}, {X, Y2}) ->
[{X, Y} || Y <- lists:seq(Y1, Y2, dir(Y1, Y2))];
points_p1(_, _) ->
[].
points_p2({X1, Y1}, {X2, Y2}) when abs(X2 - X1) =:= abs(Y2 - Y1) ->
Xs = [X || X <- lists:seq(X1, X2, dir(X1, X2))],
Ys = [Y || Y <- lists:seq(Y1, Y2, dir(Y1, Y2))],
lists:zip(Xs, Ys);
points_p2(P1, P2) ->
points_p1(P1, P2).
dir(A, B) when A < B ->
1;
dir(_, _) ->
-1.