Erlang Largest String
-module(largest_string).
-export([largest_string/1]).
largest_string(S) ->
Len = length(S),
Arr0 = array:from_list(S),
ArrFinal = process(Len - 1, Arr0, Len),
array:to_list(ArrFinal).
%% Fewer than 3 characters remain before the current position, so no more
%% "abb" windows can be completed.
process(P, Arr, _Len) when P < 2 ->
Arr;
process(P, Arr, Len) ->
I = P - 2,
{Arr1, I2} = handle_triple(I, Arr, Len),
process(I2 - 1, Arr1, Len).
handle_triple(I, Arr, Len) ->
Window = [array:get(I, Arr), array:get(I + 1, Arr), array:get(I + 2, Arr)],
case Window of
"abb" ->
Arr1 = array:set(I, $b, array:set(I + 1, $a, array:set(I + 2, $a, Arr))),
I1 = advance_on_b(I, Arr1, Len),
final_adjust(I1, Arr1, Len);
_ ->
final_adjust(I, Arr, Len)
end.
advance_on_b(I, Arr, Len) ->
case I + 4 < Len andalso array:get(I + 4, Arr) =:= $b of
true -> I + 4 + 1;
false ->
case I + 3 < Len andalso array:get(I + 3, Arr) =:= $b of
true -> I + 3 + 1;
false -> I
end
end.
final_adjust(I, Arr, Len) ->
case I + 1 < Len andalso array:get(I + 1, Arr) =:= $b of
true -> {Arr, I + 2};
false -> {Arr, I + 1}
end.
This builds the biggest valid string it can under the challenge rules by always choosing the best next character it is allowed to use.
Erlang Max Counters
-module(max_counters).
-export([max_counters/2]).
max_counters(N, A) ->
Condition = N + 1,
{CountersMap, _MaxCounter, LastUpdate} = lists:foldl(fun(V, {Map, MaxC, Last}) ->
case V of
Condition ->
{Map, MaxC, MaxC};
_ when V =< N ->
Index = V - 1,
NewVal = max(maps:get(Index, Map, 0), Last) + 1,
{maps:put(Index, NewVal, Map), max(MaxC, NewVal), Last};
_ ->
{Map, MaxC, Last}
end
end, {#{}, 0, 0}, A),
[max(maps:get(I, CountersMap, 0), LastUpdate) || I <- lists:seq(0, N - 1)].
This delays the expensive “set all counters to max” work until it is really needed, which keeps the solution fast.
Erlang Max Double Slice Sum
-module(max_double_slice_sum).
-export([max_double_slice_sum/1]).
max_double_slice_sum(A) ->
Size = length(A),
case Size < 3 of
true -> 0;
false ->
Arr = array:from_list(A),
P1 = build_p1(Arr, Size),
P2 = build_p2(Arr, Size),
lists:max([array:get(I, P1) + array:get(I, P2) || I <- lists:seq(1, Size - 2)])
end.
build_p1(Arr, Size) ->
P0 = array:set(1, 0, array:new(Size)),
lists:foldl(fun(I, Acc) ->
V = max(0, array:get(I - 1, Acc) + array:get(I - 1, Arr)),
array:set(I, V, Acc)
end, P0, lists:seq(2, Size - 2)).
build_p2(Arr, Size) ->
P0 = array:set(Size - 2, 0, array:new(Size)),
lists:foldl(fun(J, Acc) ->
V = max(0, array:get(J + 1, Acc) + array:get(J + 1, Arr)),
array:set(J, V, Acc)
end, P0, lists:seq(Size - 3, 1, -1)).
This keeps the best sum ending on the left and starting on the right, then combines them around each middle position.
Erlang Max Product Of Three
-module(max_product_of_three).
-export([max_product_of_three/1]).
max_product_of_three(A) ->
Sorted = lists:sort(A),
N = length(Sorted),
Top3 = lists:nth(N, Sorted) * lists:nth(N - 1, Sorted) * lists:nth(N - 2, Sorted),
TwoLowOneHigh = lists:nth(1, Sorted) * lists:nth(2, Sorted) * lists:nth(N, Sorted),
max(Top3, TwoLowOneHigh).
This checks the useful extremes, because the best product can come from either the three largest numbers or two negatives plus one large positive.
Erlang Max Profit
-module(max_profit).
-export([max_profit/1]).
max_profit([H | T]) ->
{_, Profit} = lists:foldl(fun(V, {MinPrice, MaxProfit}) ->
MinPrice1 = min(MinPrice, V),
{MinPrice1, max(MaxProfit, V - MinPrice1)}
end, {H, 0}, T),
Profit.
This tracks the lowest buy price seen so far and updates the best profit as it scans the prices once.
Erlang Max Slice Sum
-module(max_slice_sum).
-export([max_slice_sum/1]).
max_slice_sum([H | T]) ->
{_, Max} = lists:foldl(fun(V, {Tmp, MaxV}) ->
Tmp1 = max(Tmp + V, V),
{Tmp1, max(MaxV, Tmp1)}
end, {H, H}, T),
Max.
This is a Kadane-style scan: keep the best running sum and the best overall sum while moving once through the array.
Erlang Min Avg Two Slice
-module(min_avg_two_slice).
-export([min_avg_two_slice/1]).
min_avg_two_slice(A) ->
N = length(A),
Arr = array:from_list(A),
Init = (array:get(0, Arr) + array:get(1, Arr)) / 2,
{_, Idx} = lists:foldl(fun(I, {MinV, IdxAcc}) ->
Two = (array:get(I, Arr) + array:get(I + 1, Arr)) / 2,
Cur = case I + 2 < N of
true ->
Three = (array:get(I, Arr) + array:get(I + 1, Arr) + array:get(I + 2, Arr)) / 3,
min(Two, Three);
false ->
Two
end,
case Cur < MinV of
true -> {Cur, I};
false -> {MinV, IdxAcc}
end
end, {Init, 0}, lists:seq(0, N - 2)),
Idx.
This leans on the key trick for this problem: the minimum average slice is always length 2 or 3.
Erlang Min Perimeter Rectangle
-module(min_perimeter_rectangle).
-export([min_perimeter_rectangle/1]).
min_perimeter_rectangle(N) ->
find_min(1, N, 1 bsl 128).
find_min(I, N, Min) when I * I >= N ->
Min;
find_min(I, N, Min) ->
Min1 = case N rem I of
0 -> min(Min, 2 * (I + (N div I)));
_ -> Min
end,
find_min(I + 1, N, Min1).
This searches factor pairs up to the square root and picks the pair with the smallest perimeter.
Erlang Missing Integer
-module(missing_integer).
-export([missing_integer/1]).
missing_integer(A) ->
Positives = [V || V <- lists:usort(A), V > 0],
find_missing(Positives, 1).
find_missing([], Min) ->
Min;
find_missing([V | Rest], Min) ->
case V =:= Min of
true -> find_missing(Rest, Min + 1);
false -> Min
end.
This records the positive numbers that exist, then returns the smallest positive value that is still missing.
Erlang Nesting
-module(nesting).
-export([nesting/1]).
nesting(S) ->
case close_stack(S, []) of
[] -> 1;
_ -> 0
end.
close_stack([], Stack) -> Stack;
close_stack([$) | T], [$( | Rest]) -> close_stack(T, Rest);
close_stack([$) | _], _Stack) -> error;
close_stack([C | T], Stack) -> close_stack(T, [C | Stack]).
This treats the string like a balance counter: open parentheses add one, closing ones remove one.