-module(ral).
-vsn('1.0').
-author('Lon.Willett@sse.ie').
-export([new/0, is_empty/1, cons/2, head/1, tail/1]).
-export([sz/1, len/1, elt/2, nth/2, last/1, nthtail/2, setelt/3, update/3]).
-export([delnth/2, insnth/3, locate/2, take/2, split/2]).
-export([to_list/1, from_list/1, from_list/2,
from_list_reversed/1, from_list_reversed/2,
seq/2, seq/3, duplicate/2, split/1]).
-export([sort/1, sort/2, merge/2, merge/3,
s_member/2, s_member/3, s_locate/2, s_locate/3]).
-export([keymember/3, keysearch/3, keylocate/3, keydelete/3, keyreplace/4,
keysort/2, keymerge/3, s_keysearch/3, s_keylocate/3,
s_keydelete/3, s_keyenter/3]).
-export([foreach/2, map/2, flatmap/2, mapfoldl/3, mapfoldr/3,
foldl/3, foldl/4, foldl/5, foldr/3, foldr/4, foldr/5,
cfoldl/4, cfoldr/4,
linear_search/2, linear_search/3,
binary_search/2, binary_search/3]).
-export([append/2, append/1, reverse/1, reverse/2, sublist/2, sublist/3,
member/2, delete/2, subtract/2, all/2, any/2,
dropwhile/2, takewhile/2, splitwith/2, filter/2,
min/1, max/1, sum/1]).
-define(tsize_plus_one(Height),(1 bsl (Height))).
-define(tsize(Height),(1 bsl (Height) - 1)).
log2(X) when integer(X), X > 0 ->
log2_loop(X, 1, 2).
log2_loop(X,_,ExpB) when X < ExpB ->
0;
log2_loop(X,B,ExpB) ->
Y = log2_loop(X, 2*B, ExpB bsl B),
if X bsr Y < ExpB ->
Y;
true ->
Y+B
end.
new() -> [].
is_empty([]) -> true;
is_empty(_) -> false.
cons(X,[{Height,Tree1},{Height,Tree2}|Rest]) ->
[{Height+1,{X,Tree1,Tree2}}|Rest];
cons(X,RAL) ->
[{1,X}|RAL].
head([{1,X}|_]) -> X;
head([{_,{X,_,_}}|_]) -> X.
tail([{1,_}|Rest]) -> Rest;
tail([{Height,{_,Tree1,Tree2}}|Rest]) ->
[{Height-1,Tree1},{Height-1,Tree2}|Rest].
len(RAL) -> sz(RAL).
sz(RAL) ->
SumTreeSize = fun({Height,_},Sum) -> Sum+?tsize(Height) end,
lists:foldl(SumTreeSize, 0, RAL).
nth(N,RAL) -> elt(N,RAL).
elt(N,[{Height,Tree}|Rest]) ->
Size=?tsize(Height),
if N =< Size ->
tree_elt(N,Height,Tree);
true ->
elt(N-Size,Rest)
end.
tree_elt(1,1,X) -> X;
tree_elt(1,_,{X,_,_}) -> X;
tree_elt(N,Height,{_,Tree1,Tree2}) ->
Size1 = ?tsize_plus_one(Height-1),
if N =< Size1 ->
tree_elt(N-1,Height-1,Tree1);
true ->
tree_elt(N-Size1,Height-1,Tree2)
end.
last(RAL) ->
{Height,Tree} = lists:last(RAL),
tree_last(Height,Tree).
tree_last(1,X) -> X;
tree_last(Height,{_,_,Tree2}) ->
tree_last(Height-1,Tree2).
nthtail(N,RAL) -> drop(N,RAL).
drop(0,RAL) -> RAL;
drop(N,[{Height,Tree}|Rest]) ->
Size = ?tsize(Height),
if N < Size ->
tree_drop(N,Height,Tree,Rest);
true ->
drop(N-Size,Rest)
end.
tree_drop(0,Height,Tree,Rest) -> [{Height,Tree}|Rest];
tree_drop(N,Height,{_,Tree1,Tree2},Rest) ->
Size1 = ?tsize_plus_one(Height-1),
if N < Size1 ->
tree_drop(N-1,Height-1,Tree1,[{Height-1,Tree2}|Rest]);
true ->
tree_drop(N-Size1,Height-1,Tree2,Rest)
end.
setelt(N,[HTree|Rest],Y) ->
{Height,Tree} = HTree,
Size = ?tsize(Height),
if N =< Size ->
[{Height,tree_setelt(N,Height,Tree,Y)}|Rest];
true ->
[HTree|setelt(N-Size,Rest,Y)]
end.
tree_setelt(N,Height,{X,Tree1,Tree2},Y) when N > 1 ->
Size1 = ?tsize_plus_one(Height-1),
if N =< Size1 ->
{X,tree_setelt(N-1,Height-1,Tree1,Y),Tree2};
true ->
{X,Tree1,tree_setelt(N-Size1,Height-1,Tree2,Y)}
end;
tree_setelt(1,1,_,Y) ->
Y;
tree_setelt(1,_,{_,Tree1,Tree2},Y) ->
{Y,Tree1,Tree2}.
update(N,[HTree|Rest],Fun) ->
{Height,Tree} = HTree,
Size = ?tsize(Height),
if N =< Size ->
[{Height,tree_update(N,Height,Tree,Fun)}|Rest];
true ->
[HTree|update(N-Size,Rest,Fun)]
end.
tree_update(N,Height,{X,Tree1,Tree2},Fun) when N > 1 ->
Size1 = ?tsize_plus_one(Height-1),
if N =< Size1 ->
{X,tree_update(N-1,Height-1,Tree1,Fun),Tree2};
true ->
{X,Tree1,tree_update(N-Size1,Height-1,Tree2,Fun)}
end;
tree_update(1,1,X,Fun) ->
Fun(X);
tree_update(1,_,{X,Tree1,Tree2},Fun) ->
{Fun(X),Tree1,Tree2}.
delnth(N,RAL) when N > 1 ->
delnth_loop(N-1,head(RAL),tail(RAL));
delnth(1,RAL) ->
tail(RAL).
delnth_loop(1,Y,RAL) ->
case RAL of
[{1,_}|Rest] ->
[{1,Y}|Rest];
[{Height,{_,Tree1,Tree2}}|Rest] ->
[{Height,{Y,Tree1,Tree2}}|Rest]
end;
delnth_loop(N,Y,[{Height,Tree}|Rest]) ->
Size = ?tsize(Height),
if N =< Size ->
[{Height,tree_delnth_loop(N,Y,Height,Tree)}|Rest];
true ->
{Y1,Tree1} = tree_shift_right(Y,Height,Tree),
[{Height,Tree1}|delnth_loop(N-Size,Y1,Rest)]
end.
tree_delnth_loop(N,Y,Height,{X,Tree1,Tree2}) when N > 1 ->
Size1 = ?tsize_plus_one(Height-1),
if N =< Size1 ->
{Y,tree_delnth_loop(N-1,X,Height-1,Tree1),Tree2};
true ->
{X1,NewTree1} = tree_shift_right(X,Height-1,Tree1),
{Y,NewTree1,tree_delnth_loop(N-Size1,X1,Height-1,Tree2)}
end;
tree_delnth_loop(1,Y,1,_) ->
Y;
tree_delnth_loop(1,Y,_,{_,Tree1,Tree2}) ->
{Y,Tree1,Tree2}.
tree_shift_right(Y,1,X) ->
{X,Y};
tree_shift_right(Y,Height,{X,Tree1,Tree2}) ->
{X1,NewTree1} = tree_shift_right(X,Height-1,Tree1),
{X2,NewTree2} = tree_shift_right(X1,Height-1,Tree2),
{X2,{Y,NewTree1,NewTree2}}.
insnth(1,RAL,Y) -> cons(Y,RAL);
insnth(N,RAL,Y) -> cons(head(RAL),insnth_loop(N-1,RAL,Y)).
insnth_loop(N,[{Height,Tree}|Rest],Y) ->
Size = ?tsize(Height),
if N =< Size ->
Tree1 = tree_insnth_loop(N,Height,Tree,Y),
[{Height,Tree1}|Rest];
true ->
Tree1 = tree_shift_left(Height,Tree,head(Rest)),
[{Height,Tree1}|insnth_loop(N-Size, Rest, Y)]
end.
tree_insnth_loop(N,Height,{_,Tree1,Tree2},Y) when N > 1, Height > 2 ->
Size1 = ?tsize_plus_one(Height-1),
{X1,_,_} = Tree1,
if N =< Size1 ->
{X1,tree_insnth_loop(N-1,Height-1,Tree1,Y),Tree2};
true ->
{X2,_,_} = Tree2,
{X1,
tree_shift_left(Height-1,Tree1,X2),
tree_insnth_loop(N-Size1,Height-1,Tree2,Y)}
end;
tree_insnth_loop(1,1,_,Y) ->
Y;
tree_insnth_loop(N,_Height,{_,X1,X2},Y) ->
case N of
1 -> {Y,X1,X2};
2 -> {X1,Y,X2};
3 -> {X1,X2,Y}
end.
tree_shift_left(Height,{_,Tree1,Tree2},Y) when Height > 2 ->
{X1,_,_} = Tree1,
{X2,_,_} = Tree2,
{X1,tree_shift_left(Height-1,Tree1,X2),tree_shift_left(Height-1,Tree2,Y)};
tree_shift_left(2,{_,X1,X2},Y) ->
{X1,X2,Y};
tree_shift_left(1,_,Y) ->
Y.
locate(X,RAL) ->
Fun = fun(Y,Index) when Y =:= X -> Index; (_,_) -> false end,
linear_search(Fun,RAL,1).
take(N,RAL) ->
foldr(fun cons/2, [], RAL, 1, N).
split(N,RAL) ->
{take(N,RAL),drop(N,RAL)}.
to_list(RAL) ->
foldr(fun(X,List) -> [X|List] end, [], RAL).
from_list_reversed(List) ->
from_list_reversed(List,[]).
from_list_reversed(List,RAL) ->
lists:foldl(fun cons/2, RAL, List).
from_list(List) ->
from_list_loop(List,tree_heights(length(List))).
from_list(List,Len) when integer(Len), Len >= 0 ->
from_list_loop(List,tree_heights(Len)).
from_list_loop(_,[]) ->
[];
from_list_loop(Xs,[Height|Heights]) ->
[Tree|Xs1] = tree_from_list(Xs,Height),
[{Height,Tree}|from_list_loop(Xs1,Heights)].
tree_from_list(List,1) ->
List;
tree_from_list([X|Xs],Height) ->
[Tree1|Xs1] = tree_from_list(Xs,Height-1),
[Tree2|Xs2] = tree_from_list(Xs1,Height-1),
[{X,Tree1,Tree2}|Xs2].
seq(From,To) ->
seq_loop(From,1,tree_heights(To-From+1)).
seq(From,To,Incr) ->
Steps = (To - From) div Incr,
seq_loop(From,Incr,tree_heights(Steps+1)).
seq_loop(_,_,[]) ->
[];
seq_loop(From,Incr,[Height|Heights]) ->
[{Height,tree_seq(From,Incr,Height)}
| seq_loop(From+Incr*?tsize(Height),Incr,Heights)].
tree_seq(From,_,1) ->
From;
tree_seq(From,Incr,Height) ->
{From,
tree_seq(From+Incr,Incr,Height-1),
tree_seq(From+Incr*?tsize_plus_one(Height-1),Incr,Height-1)}.
tree_heights(N) when N < 0 ->
[];
tree_heights(N) ->
build_decomposition(N,log2(N+1),[]).
build_decomposition(0, _, List) ->
List;
build_decomposition(N, Height, List) ->
Size = ?tsize(Height),
if N < Size ->
build_decomposition(N, Height-1, List);
true ->
build_decomposition(N-Size, Height, [Height|List])
end.
duplicate(0,_) -> [];
duplicate(N,X) when integer(N), N > 0 ->
build_trees_loop(N,X,1,X,[]).
build_trees_loop(N,X,Height,Tree,HTrees) ->
Size = ?tsize(Height+1),
if N >= Size ->
build_trees_loop(N,X,Height+1,{X,Tree,Tree},
[{Height,Tree}|HTrees]);
true ->
HTree={Height,Tree},
select_trees_loop(N-?tsize(Height),[HTree|HTrees],[HTree])
end.
select_trees_loop(0,_,RAL) ->
RAL;
select_trees_loop(N,HTrees,RAL) ->
[HTree|Rest] = HTrees,
{Height,_} = HTree,
Size=?tsize(Height),
if N < Size ->
select_trees_loop(N,Rest,RAL);
true ->
select_trees_loop(N-Size,HTrees,[HTree|RAL])
end.
split([]) ->
{[],[]};
split(RAL) ->
split(RAL,0,[]).
split([HTree|Rest], _, Acc) when Rest /= [] ->
{Height,_} = HTree,
split(Rest,Height,[HTree|Acc]);
split([{H1,{X,Tree1,Tree2}}], H0, Acc) when H1 > H0+1 ->
RAL1 = lists:foldl(fun({H,T},RALAcc) ->
tree_foldr(fun cons/2,RALAcc,H,T)
end,
[{1,X},{H1-1,Tree1}],
Acc),
RAL2 = [{H1-1,Tree2}],
{RAL1,RAL2};
split(RAL, _, Acc) ->
{lists:reverse(Acc),RAL}.
sort(RAL) ->
Len = len(RAL),
from_list(lists:sort(to_list(RAL)),Len).
sort(Compare,RAL) ->
Len = len(RAL),
from_list(lists:sort(Compare,to_list(RAL)),Len).
merge(RAL1,[]) ->
RAL1;
merge(RAL1,RAL2) ->
merge_loop(RAL1, head(RAL2), RAL2, []).
merge_loop([], _, RAL2, List) ->
from_list_reversed(List,RAL2);
merge_loop(RAL1, H2, RAL2, List) ->
H1 = head(RAL1),
if H1 =< H2 ->
merge_loop(tail(RAL1), H2, RAL2, [H1|List]);
true ->
merge_loop(tail(RAL2), H1, RAL1, [H2|List])
end.
merge(_Compare, RAL1, []) ->
RAL1;
merge(Compare, RAL1, RAL2) ->
merge_loop(Compare, RAL1, head(RAL2), RAL2, []).
merge_loop(_Compare, [], _, RAL2, List) ->
from_list_reversed(List,RAL2);
merge_loop(Compare, RAL1, H2, RAL2, List) ->
H1 = head(RAL1),
case Compare(H1, H2) of
true ->
merge_loop(Compare, tail(RAL1), H2, RAL2, [H1|List]);
false ->
merge_loop(Compare, tail(RAL2), H1, RAL1, [H2|List])
end.
s_member(Elt,RAL) ->
Pred = fun(X) -> X =< Elt end,
case binary_search(Pred,RAL) of
false -> false;
{true, X1} -> Elt =< X1
end.
s_member(Compare, Elt, RAL) ->
Pred = fun(X) -> Compare(X, Elt) end,
case binary_search(Pred,RAL) of
false ->
false;
{true, Value} ->
case Compare(Elt,Value) of
false -> false;
true -> true
end
end.
s_locate(Elt,RAL) ->
Pred = fun(X,_) -> X =< Elt end,
case binary_search(Pred,RAL,1) of
false -> {false, 0};
{true, I, XI} -> {Elt =< XI, I}
end.
s_locate(Compare,Elt,RAL) ->
Pred = fun(X,_) -> Compare(X,Elt) end,
case binary_search(Pred,RAL,1) of
false ->
{false, 0};
{true, I, Value} ->
case Compare(Elt,Value) of
false -> {false, I};
true -> {true, I}
end
end.
keymember(Key,N,Tuples) when integer(N), N > 0 ->
Fun = fun(Tuple) -> element(N,Tuple) == Key end,
linear_search(Fun,Tuples).
keysearch(Key,N,Tuples) when integer(N), N > 0 ->
Fun = fun(Tuple) when element(N,Tuple) == Key -> {value,Tuple};
(_) -> false
end,
linear_search(Fun,Tuples).
keylocate(Key,N,Tuples) when integer(N), N > 0 ->
Fun = fun(Tuple,Pos) when element(N,Tuple) == Key ->
{value,Pos,Tuple};
(_,_) ->
false
end,
linear_search(Fun,Tuples,1).
keydelete(Key,N,Tuples) ->
case keylocate(Key,N,Tuples) of
false -> Tuples;
{value,Pos,_} -> delnth(Pos,Tuples)
end.
keyreplace(Key,N,Tuples,NewTuple) ->
case keylocate(Key,N,Tuples) of
false -> Tuples;
{value,Pos,_} -> setelt(Pos,Tuples,NewTuple)
end.
keysort(N,Tuples) ->
Compare = fun(T1,T2) -> element(N,T1) =< element(N,T2) end,
sort(Compare, Tuples).
keymerge(N,Tuples1,Tuples2) ->
Compare = fun(T1,T2) -> element(N,T1) =< element(N,T2) end,
merge(Compare, Tuples1, Tuples2).
s_keysearch(Key,N,Tuples) ->
Pred = fun(T) -> element(N,T) =< Key end,
case binary_search(Pred, Tuples) of
false -> false;
{true, Tuple} ->
if
element(N,Tuple) < Key -> false;
true -> {value,Tuple}
end
end.
s_keylocate(Key,N,Tuples) ->
Pred = fun(T,_) -> element(N,T) =< Key end,
case binary_search(Pred, Tuples, 1) of
false -> 0;
{true, Pos, Tuple} ->
if
element(N,Tuple) < Key -> Pos;
true -> {value,Pos,Tuple}
end
end.
s_keydelete(Key,N,Tuples) ->
case s_keylocate(Key,N,Tuples) of
{value,Pos,_} ->
delnth(Pos,Tuples);
_Count ->
Tuples
end.
s_keyenter(N,Tuples,NewTuple) ->
case s_keylocate(element(N,NewTuple),N,Tuples) of
{value,Pos,_} ->
setelt(Pos,Tuples,NewTuple);
Count ->
insnth(Count+1,Tuples,NewTuple)
end.
foreach(_Fun,[]) -> ok;
foreach(Fun,[{Height,Tree}|Rest]) ->
tree_foreach(Fun,Height,Tree),
foreach(Fun,Rest).
tree_foreach(Fun,1,X) -> Fun(X);
tree_foreach(Fun,Height,{X,Tree1,Tree2}) ->
Fun(X),
tree_foreach(Fun,Height-1,Tree1),
tree_foreach(Fun,Height-1,Tree2).
map(_Fun,[]) -> [];
map(Fun,[{Height,Tree}|Rest]) ->
[{Height,tree_map(Fun,Height,Tree)} | map(Fun,Rest)].
tree_map(Fun,1,X) -> Fun(X);
tree_map(Fun,Height,{X,Tree1,Tree2}) ->
{Fun(X), tree_map(Fun,Height-1,Tree1), tree_map(Fun,Height-1,Tree2)}.
flatmap(_Fun,[]) -> [];
flatmap(Fun,[{Height,Tree}|Rest]) ->
tree_flatmap(Fun,Height,Tree,flatmap(Fun,Rest)).
tree_flatmap(Fun,1,X,Tail) ->
lists:foldr(fun cons/2,Tail,Fun(X));
tree_flatmap(Fun,Height,{X,Tree1,Tree2},Tail) ->
Tail1 = tree_flatmap(Fun,Height-1,Tree2,Tail),
Tail2 = tree_flatmap(Fun,Height-1,Tree1,Tail1),
lists:foldr(fun cons/2, Tail2, Fun(X)).
mapfoldl(_Fun,Acc,[]) -> {[], Acc};
mapfoldl(Fun,Acc,[{Height,Tree}|Rest]) ->
{NewTree,Acc1} = tree_mapfoldl(Fun,Acc,Height,Tree),
{NewRest,Acc2} = mapfoldl(Fun,Acc1,Rest),
{[{Height,NewTree}|NewRest], Acc2}.
tree_mapfoldl(Fun,Acc,1,X) -> Fun(X,Acc);
tree_mapfoldl(Fun,Acc,Height,{X,Tree1,Tree2}) ->
{NewX,Acc1} = Fun(X,Acc),
{NewTree1,Acc2} = tree_mapfoldl(Fun,Acc1,Height-1,Tree1),
{NewTree2,Acc3} = tree_mapfoldl(Fun,Acc2,Height-1,Tree2),
{{NewX,NewTree1,NewTree2},Acc3}.
mapfoldr(_Fun,Acc,[]) -> {[], Acc};
mapfoldr(Fun,Acc,[{Height,Tree}|Rest]) ->
{NewRest,Acc1} = mapfoldr(Fun,Acc,Rest),
{NewTree,Acc2} = tree_mapfoldr(Fun,Acc1,Height,Tree),
{[{Height,NewTree}|NewRest], Acc2}.
tree_mapfoldr(Fun,Acc,1,X) -> Fun(X,Acc);
tree_mapfoldr(Fun,Acc,Height,{X,Tree1,Tree2}) ->
{NewTree2, Acc1} = tree_mapfoldr(Fun,Acc,Height-1,Tree2),
{NewTree1, Acc2} = tree_mapfoldr(Fun,Acc1,Height-1,Tree1),
{NewX, Acc3} = Fun(X,Acc2),
{{NewX,NewTree1,NewTree2}, Acc3}.
foldl(Fun,Acc,RAL,Start) ->
foldl_s(Fun,Acc,RAL,Start).
foldl(Fun,Acc,RAL,Start,Len) ->
foldl_sl(Fun,Acc,RAL,Start,Len).
foldl(_Fun,Acc,[]) -> Acc;
foldl(Fun,Acc,[{Height,Tree}|Rest]) ->
Acc1 = tree_foldl(Fun,Acc,Height,Tree),
foldl(Fun,Acc1,Rest).
foldl_s(Fun,Acc,RAL,1) -> foldl(Fun,Acc,RAL);
foldl_s(Fun,Acc,[{Height,Tree}|Rest],Start) ->
Size = ?tsize(Height),
if Start > Size ->
foldl_s(Fun,Acc,Rest,Start-Size);
true ->
Acc1 = tree_foldl_s(Fun,Acc,Height,Tree,Start),
foldl(Fun,Acc1,Rest)
end.
foldl_l(_Fun,Acc,_,0) -> Acc;
foldl_l(Fun,Acc,[{Height,Tree}|Rest],Len) ->
Size = ?tsize(Height),
if Len < Size ->
tree_foldl_l(Fun,Acc,Height,Tree,Len);
true ->
Acc1 = tree_foldl(Fun,Acc,Height,Tree),
foldl_l(Fun,Acc1,Rest,Len-Size)
end.
foldl_sl(Fun,Acc,RAL,1,Len) -> foldl_l(Fun,Acc,RAL,Len);
foldl_sl(Fun,Acc,[{Height,Tree}|Rest],Start,Len) ->
Size = ?tsize(Height),
if Start > Size ->
foldl_sl(Fun,Acc,Rest,Start-Size,Len);
Start+Len-1 =< Size ->
tree_foldl_sl(Fun,Acc,Height,Tree,Start,Len);
true ->
Acc1 = tree_foldl_s(Fun,Acc,Height,Tree,Start),
foldl_l(Fun,Acc1,Rest,Start+Len-Size-1)
end.
tree_foldl(Fun,Acc,1,X) -> Fun(X,Acc);
tree_foldl(Fun,Acc,Height,{X,Tree1,Tree2}) ->
Acc1 = Fun(X,Acc),
Acc2 = tree_foldl(Fun,Acc1,Height-1,Tree1),
tree_foldl(Fun,Acc2,Height-1,Tree2).
tree_foldl_s(Fun,Acc,Height,Tree,1) -> tree_foldl(Fun,Acc,Height,Tree);
tree_foldl_s(Fun,Acc,Height,{_,Tree1,Tree2},Start) ->
Size1 = ?tsize_plus_one(Height-1),
if Start > Size1 ->
tree_foldl_s(Fun,Acc,Height-1,Tree2,Start-Size1);
true ->
Acc1 = tree_foldl_s(Fun,Acc,Height-1,Tree1,Start-1),
tree_foldl(Fun,Acc1,Height-1,Tree2)
end.
tree_foldl_l(_Fun,Acc,_,_,0) -> Acc;
tree_foldl_l(Fun,Acc,1,X,1) -> Fun(X,Acc);
tree_foldl_l(Fun,Acc,Height,{X,Tree1,Tree2},Len) ->
Acc1 = Fun(X,Acc),
Size1 = ?tsize_plus_one(Height-1),
if Len < Size1 ->
tree_foldl_l(Fun,Acc1,Height-1,Tree1,Len-1);
true ->
Acc2 = tree_foldl(Fun,Acc1,Height-1,Tree1),
tree_foldl_l(Fun,Acc2,Height-1,Tree2,Len-Size1)
end.
tree_foldl_sl(Fun,Acc,Height,Tree,1,Len) ->
tree_foldl_l(Fun,Acc,Height,Tree,Len);
tree_foldl_sl(Fun,Acc,Height,{_,Tree1,Tree2},Start,Len) ->
Size1 = ?tsize_plus_one(Height-1),
if Start > Size1 ->
tree_foldl_sl(Fun,Acc,Height-1,Tree2,Start-Size1,Len);
Start+Len-1 =< Size1 ->
tree_foldl_sl(Fun,Acc,Height-1,Tree1,Start-1,Len);
true ->
Acc1 = tree_foldl_s(Fun,Acc,Height-1,Tree1,Start-1),
tree_foldl_l(Fun,Acc1,Height-1,Tree2,Start+Len-1-Size1)
end.
foldr(Fun,Acc,RAL,Start) ->
foldr_s(Fun,Acc,RAL,Start).
foldr(Fun,Acc,RAL,Start,Len) ->
foldr_sl(Fun,Acc,RAL,Start,Len).
foldr(_Fun,Acc,[]) -> Acc;
foldr(Fun,Acc,[{Height,Tree}|Rest]) ->
Acc1 = foldr(Fun,Acc,Rest),
tree_foldr(Fun,Acc1,Height,Tree).
foldr_s(Fun,Acc,RAL,1) -> foldr(Fun,Acc,RAL);
foldr_s(Fun,Acc,[{Height,Tree}|Rest],Start) ->
Size = ?tsize(Height),
if Start > Size ->
foldr_s(Fun,Acc,Rest,Start-Size);
true ->
Acc1 = foldr(Fun,Acc,Rest),
tree_foldr_s(Fun,Acc1,Height,Tree,Start)
end.
foldr_l(_Fun,Acc,_,0) -> Acc;
foldr_l(Fun,Acc,[{Height,Tree}|Rest],Len) ->
Size = ?tsize(Height),
if Len < Size ->
tree_foldr_l(Fun,Acc,Height,Tree,Len);
true ->
Acc1 = foldr_l(Fun,Acc,Rest,Len-Size),
tree_foldr(Fun,Acc1,Height,Tree)
end.
foldr_sl(Fun,Acc,RAL,1,Len) -> foldr_l(Fun,Acc,RAL,Len);
foldr_sl(Fun,Acc,[{Height,Tree}|Rest],Start,Len) ->
Size = ?tsize(Height),
if Start > Size ->
foldr_sl(Fun,Acc,Rest,Start-Size,Len);
Start+Len-1 =< Size ->
tree_foldr_sl(Fun,Acc,Height,Tree,Start,Len);
true ->
Acc1 = foldr_l(Fun,Acc,Rest,Start+Len-Size-1),
tree_foldr_s(Fun,Acc1,Height,Tree,Start)
end.
tree_foldr(Fun,Acc,1,X) -> Fun(X,Acc);
tree_foldr(Fun,Acc,Height,{X,Tree1,Tree2}) ->
Acc1 = tree_foldr(Fun,Acc,Height-1,Tree2),
Acc2 = tree_foldr(Fun,Acc1,Height-1,Tree1),
Fun(X,Acc2).
tree_foldr_s(Fun,Acc,Height,Tree,1) -> tree_foldr(Fun,Acc,Height,Tree);
tree_foldr_s(Fun,Acc,Height,{_,Tree1,Tree2},Start) ->
Size1 = ?tsize_plus_one(Height-1),
if Start > Size1 ->
tree_foldr_s(Fun,Acc,Height-1,Tree2,Start-Size1);
true ->
Acc1 = tree_foldr(Fun,Acc,Height-1,Tree2),
tree_foldr_s(Fun,Acc1,Height-1,Tree1,Start-1)
end.
tree_foldr_l(_Fun,Acc,_,_,0) -> Acc;
tree_foldr_l(Fun,Acc,1,X,1) -> Fun(X,Acc);
tree_foldr_l(Fun,Acc,Height,{X,Tree1,Tree2},Len) ->
Size1 = ?tsize_plus_one(Height-1),
if Len < Size1 ->
Acc1 = tree_foldr_l(Fun,Acc,Height-1,Tree1,Len-1),
Fun(X,Acc1);
true ->
Acc1 = tree_foldr_l(Fun,Acc,Height-1,Tree2,Len-Size1),
Acc2 = tree_foldr(Fun,Acc1,Height-1,Tree1),
Fun(X,Acc2)
end.
tree_foldr_sl(Fun,Acc,Height,Tree,1,Len) ->
tree_foldr_l(Fun,Acc,Height,Tree,Len);
tree_foldr_sl(Fun,Acc,Height,{_,Tree1,Tree2},Start,Len) ->
Size1 = ?tsize_plus_one(Height-1),
if Start > Size1 ->
tree_foldr_sl(Fun,Acc,Height-1,Tree2,Start-Size1,Len);
Start+Len-1 =< Size1 ->
tree_foldr_sl(Fun,Acc,Height-1,Tree1,Start-1,Len);
true ->
Acc1 = tree_foldr_l(Fun,Acc,Height-1,Tree2,Start+Len-1-Size1),
tree_foldr_s(Fun,Acc1,Height-1,Tree1,Start-1)
end.
cfoldl(_Cond,_Fun,Acc,[]) ->
Acc;
cfoldl(Cond,Fun,Acc,[{Height,Tree}|Rest]) ->
case Cond(Acc) of
false -> Acc;
true ->
Acc1 = tree_cfoldl(Cond,Fun,Acc,Height,Tree),
cfoldl(Cond,Fun,Acc1,Rest)
end.
tree_cfoldl(_Cond,Fun,Acc,1,X) ->
Fun(X,Acc);
tree_cfoldl(Cond,Fun,Acc,Height,{X,Tree1,Tree2}) ->
Acc1 = Fun(X,Acc),
case Cond(Acc1) of
false -> Acc1;
true ->
Acc2 = tree_cfoldl(Cond,Fun,Acc1,Height-1,Tree1),
case Cond(Acc2) of
false -> Acc2;
true ->
tree_cfoldl(Cond,Fun,Acc2,Height-1,Tree2)
end
end.
cfoldr(_Cond,_Fun,Acc,[]) ->
Acc;
cfoldr(Cond,Fun,Acc,[{Height,Tree}|Rest]) ->
Acc1 = cfoldr(Cond,Fun,Acc,Rest),
case Cond(Acc1) of
false -> Acc1;
true ->
tree_cfoldr(Cond,Fun,Acc1,Height,Tree)
end.
tree_cfoldr(_Cond,Fun,Acc,1,X) ->
Fun(X,Acc);
tree_cfoldr(Cond,Fun,Acc,Height,{X,Tree1,Tree2}) ->
Acc1 = tree_cfoldr(Cond,Fun,Acc,Height-1,Tree2),
case Cond(Acc1) of
false -> Acc1;
true ->
Acc2 = tree_cfoldr(Cond,Fun,Acc1,Height-1,Tree1),
case Cond(Acc2) of
false -> Acc2;
true ->
Fun(X,Acc2)
end
end.
linear_search(_,[]) -> false;
linear_search(Pred,[{Height,Tree}|Rest]) ->
case tree_linear_search(Pred, Height, Tree) of
false ->
linear_search(Pred,Rest);
OtherValue ->
OtherValue
end.
tree_linear_search(Pred,1,X) -> Pred(X);
tree_linear_search(Pred,Height,{X,Tree1,Tree2}) ->
case Pred(X) of
false ->
case tree_linear_search(Pred,Height-1,Tree1) of
false ->
tree_linear_search(Pred,Height-1,Tree2);
OtherValue ->
OtherValue
end;
OtherValue ->
OtherValue
end.
linear_search(_,[],_) -> false;
linear_search(Pred,[{Height,Tree}|Rest],I) ->
case tree_linear_search(Pred, Height, Tree, I) of
false ->
linear_search(Pred,Rest,I+?tsize(Height));
OtherValue ->
OtherValue
end.
tree_linear_search(Pred,1,X,I) -> Pred(X,I);
tree_linear_search(Pred,Height,{X,Tree1,Tree2},I) ->
case Pred(X,I) of
false ->
case tree_linear_search(Pred,Height-1,Tree1,I+1) of
false ->
tree_linear_search(Pred,Height-1,Tree2,
I+?tsize_plus_one(Height-1));
OtherValue ->
OtherValue
end;
OtherValue ->
OtherValue
end.
binary_search(_Pred, []) ->
false;
binary_search(Pred, [{Height,Tree}|Rest]) ->
case binary_search(Pred,Rest) of
false -> tree_bsearch_r(Pred,Height,Tree);
Value -> Value
end.
tree_bsearch_r(Pred,1,X) ->
case Pred(X) of
false -> false;
Other -> {Other, X}
end;
tree_bsearch_r(Pred,Height,{X,Tree1,Tree2}) ->
case Pred(X) of
false ->
false;
true ->
case tree_bsearch_r(Pred,Height-1,Tree2) of
false ->
case tree_bsearch_l(Pred,Height-1,Tree1) of
false ->
{true,X};
Value ->
Value
end;
Value ->
Value
end;
Other ->
{Other, X}
end.
tree_bsearch_l(Pred,1,X) ->
case Pred(X) of
false -> false;
Other -> {Other, X}
end;
tree_bsearch_l(Pred,Height,{X,Tree1,Tree2}) ->
case tree_bsearch_r(Pred,Height-1,Tree2) of
false ->
case tree_bsearch_l(Pred,Height-1,Tree1) of
false ->
case Pred(X) of
false -> false;
Other -> {Other, X}
end;
Value ->
Value
end;
Value ->
Value
end.
binary_search(_Pred, [], _) ->
false;
binary_search(Pred, [{Height,Tree}|Rest], I) ->
case binary_search(Pred,Rest,I+?tsize(Height)) of
false ->
tree_bsearch_r(Pred,Height,Tree,I);
Value ->
Value
end.
tree_bsearch_r(Pred,1,X,I) ->
case Pred(X,I) of
false ->
false;
Other ->
{Other, I, X}
end;
tree_bsearch_r(Pred,Height,{X,Tree1,Tree2},I) ->
case Pred(X,I) of
false ->
false;
true ->
case tree_bsearch_r(Pred,Height-1,Tree2,
I+?tsize_plus_one(Height-1)) of
false ->
case tree_bsearch_l(Pred,Height-1,Tree1,I+1) of
false ->
{true,I,X};
Value ->
Value
end;
Value ->
Value
end;
Other ->
{Other, I, X}
end.
tree_bsearch_l(Pred,1,X,I) ->
case Pred(X,I) of
false ->
false;
Other ->
{Other, I, X}
end;
tree_bsearch_l(Pred,Height,{X,Tree1,Tree2},I) ->
case tree_bsearch_r(Pred,Height-1,Tree2, I+?tsize_plus_one(Height-1)) of
false ->
case tree_bsearch_l(Pred,Height-1,Tree1,I+1) of
false ->
case Pred(X,I) of
false -> false;
Other -> {Other,I,X}
end;
Value ->
Value
end;
Value ->
Value
end.
append(RAL1,[]) -> RAL1;
append(RAL1,RAL2) -> foldr(fun cons/2, RAL2, RAL1).
append(RALs) -> lists:foldr(fun append/2, [], RALs).
reverse(RAL) -> reverse(RAL, []).
reverse(RAL1,RAL2) -> foldl(fun cons/2, RAL2, RAL1).
sublist(RAL,Len) -> sublist(RAL,1,Len).
sublist(RAL,Start,Len) -> foldr(fun cons/2, [], RAL, Start, Len).
member(X,RAL) -> linear_search(fun(Y) -> Y =:= X end, RAL).
any(Pred,RAL) ->
case linear_search(Pred,RAL) of
false -> false;
true -> true
end.
all(Pred,RAL) ->
not linear_search(fun(X) -> not Pred(X) end, RAL).
sum(RAL) -> foldl(fun(X,Sum) -> Sum+X end, 0, RAL).
min(RAL) ->
foldl(fun(X,Min) when X < Min -> X; (_,Min) -> Min end, head(RAL), RAL, 2).
max(RAL) ->
foldl(fun(X,Max) when X > Max -> X; (_,Max) -> Max end, head(RAL), RAL, 2).
delete(Y,RAL) ->
case locate(Y,RAL) of
false -> RAL;
Pos -> delnth(Pos,RAL)
end.
subtract(RAL1,RAL2) -> foldl(fun delete/2, RAL1, RAL2).
locate_split(Pred,RAL) ->
Fun = fun(X,Offset) ->
case Pred(X) of
true -> false;
false -> Offset
end
end,
linear_search(Fun,RAL,0).
takewhile(Pred,RAL) ->
case locate_split(Pred,RAL) of
false -> RAL;
N -> take(N,RAL)
end.
dropwhile(Pred,RAL) ->
case locate_split(Pred,RAL) of
false -> [];
N -> drop(N,RAL)
end.
splitwith(Pred,RAL) ->
case locate_split(Pred,RAL) of
false -> {RAL,[]};
N -> split(N,RAL)
end.
filter(Pred,RAL) ->
Fun = fun(X,Acc) ->
case Pred(X) of
true -> cons(X,Acc);
false -> Acc
end
end,
foldr(Fun,[],RAL).