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.