Erlang Flags
-module(flags).
-export([flags/1]).
flags(A) ->
Size = length(A),
Arr = array:from_list(A),
Peaks = compute_peaks(Arr, Size),
Next = compute_next(Peaks, Size),
max_flags(1, Size, Next, 0).
compute_peaks(_Arr, Size) when Size =< 1 ->
array:new(max(Size, 1), {default, false});
compute_peaks(Arr, Size) ->
Peaks0 = array:new(Size, {default, false}),
lists:foldl(fun(I, Acc) ->
Ai = array:get(I, Arr),
Prev = array:get(I - 1, Arr),
Next = case I + 1 < Size of
true -> array:get(I + 1, Arr);
false -> 0
end,
IsPeak = Prev < Ai andalso Ai > Next,
array:set(I, IsPeak, Acc)
end, Peaks0, lists:seq(1, Size - 1)).
compute_next(_Peaks, Size) when Size =:= 0 ->
array:new(0);
compute_next(Peaks, Size) ->
NextArr0 = array:set(Size - 1, -1, array:new(Size)),
lists:foldl(fun(I, Acc) ->
Val = case array:get(I, Peaks) of
true -> I;
false -> array:get(I + 1, Acc)
end,
array:set(I, Val, Acc)
end, NextArr0, lists:seq(Size - 2, 0, -1)).
max_flags(I, Size, _Next, Result) when I * (I - 1) > Size ->
Result;
max_flags(I, Size, Next, Result) ->
Num = count_flags(0, 0, I, Size, Next),
max_flags(I + 1, Size, Next, max(Result, Num)).
count_flags(Pos, Num, I, Size, _Next) when Pos >= Size orelse Num >= I ->
Num;
count_flags(Pos, Num, I, Size, Next) ->
case array:get(Pos, Next) of
-1 -> Num;
NextPos -> count_flags(NextPos + I, Num + 1, I, Size, Next)
end.
This finds all peaks first, then checks how many flags can be placed while keeping the required distance.