Erlang Number Of Disc Intersections
-module(number_of_disc_intersections).
-export([number_of_disc_intersections/1]).
number_of_disc_intersections(A) ->
C = length(A),
Indexed = lists:zip(lists:seq(0, C - 1), A),
{Start, End} = lists:foldl(fun({K, V}, {S, E}) ->
KeyS = case K < V of true -> 0; false -> K - V end,
KeyE = case K + V >= C of true -> C - 1; false -> K + V end,
{array:set(KeyS, array:get(KeyS, S) + 1, S),
array:set(KeyE, array:get(KeyE, E) + 1, E)}
end, {array:new(C, {default, 0}), array:new(C, {default, 0})}, Indexed),
compute_sum(0, 0, 0, C, Start, End).
compute_sum(K, _Active, Sum, C, _Start, _End) when K >= C ->
Sum;
compute_sum(K, Active, Sum, C, Start, End) ->
StartK = array:get(K, Start),
EndK = array:get(K, End),
Sum1 = Sum + Active * StartK + (StartK * (StartK - 1)) div 2,
case Sum1 > 10000000 of
true -> -1;
false -> compute_sum(K + 1, Active + StartK - EndK, Sum1, C, Start, End)
end.
This sorts disc start and end points and counts active overlaps without comparing every pair directly.