====== Erlang - Lista 3. ======
===== Zadanie 1. ======
==== Wersja 1. (drx) ====
-module(zad1).
-export([amicable/1, rozklad/1]).
rozklad(N) -> rozklad(N, 2, []).
addfactor(F, Fs) ->
T = lists:keyfind(F, 1, Fs),
if
T == false -> lists:keystore(F, 1, Fs, {F, 1});
true ->
{F, N} = T,
lists:keyreplace(F, 1, Fs, {F, N+1})
end.
rozklad(N, F, Fs) ->
M = N rem F,
if
F > N -> Fs;
M =:= 0 -> rozklad(N div F, 2, addfactor(F, Fs));
M =/= 0 -> rozklad(N, F+1, Fs)
end.
divisors(N) -> divisors(N, 1, []).
divisors(N, N, Ds) -> Ds;
divisors(N, D, Ds) ->
if
N rem D =:= 0 -> divisors(N, D+1, [D|Ds]);
true -> divisors(N, D+1, Ds)
end.
amicable(A,B) ->
(lists:sum(divisors(A)) =:= B)
and
(lists:sum(divisors(B)) =:= A).
amicable(N) ->
[ {A,B} ||
A <- lists:seq(1,N),
B <- lists:seq(A+1,N),
amicable(A,B)
].
==== Wersja 2. (dude) ====
-module(l2z1).
-export([zaprzyjaznione/1, rozklad/1]).
divisors(N) -> divisors(N, 1, []).
divisors(N, N, L) -> L;
divisors(N, M, L) -> if N rem M =:= 0 -> divisors(N, M+1, [M|L]);
true -> divisors(N, M+1, L)
end.
divs(N) -> [lists:sum(divisors(X)) || X <- lists:seq(1, N)].
zaprzyjaznione(N) -> L = divs(N),
[ {A, B} ||
A <- lists:seq(1, N-1),
B <- lists:seq(A+1, N),
lists:nth(A, L) =:= B,
lists:nth(B, L) =:= A
].
group([], _) -> [];
group([H,H|T], N) -> group([H|T], N+1);
group([H|T], N) -> [{H, N} | group(T, 1)].
rozklad(N) -> group(rozklad(N, [2|lists:seq(3,round(math:sqrt(N)), 2)]), 1).
rozklad(_, []) -> [];
rozklad(N, [H|T]) -> if
N rem H =:= 0 -> [H|rozklad(N div H, [H|T])];
true -> rozklad(N, T)
end.
===== Zadanie 2. (dude) =====
kurwa mac
-module(l2z2).
-export([format/2]).
format(Width, Indent) -> Input = lists:map(fun (X) -> string:tokens(string:strip(join(lists:reverse(X))), " ") end, readl()),
Output = lists:reverse(lists:map(fun (X) -> justify(Width - Indent, Width, X) end, Input)),
print(Output).
print([]) -> ok;
print([H]) -> print2(H);
print([H|T]) -> print2(H),
io:format("~n"),
print(T).
print2([]) -> ok;
print2([H|T]) -> io:format("~s~n", [H]),
print2(T).
justify(I, W, S) -> First = take(I, S),
[string:concat(string:copies(" ", W - I), pad(I, First)) | justify(W, lists:nthtail(length(First), S))].
justify(_, []) -> [];
justify(W, S) -> Line = take(W, S),
Ls = length(S),
Ll = length(Line),
if
Ls == Ll -> [nopad(S)];
true -> [pad(W, Line) | justify(W, lists:nthtail(length(Line), S))]
end.
pad(W, []) -> "";
pad(W, L) ->
Spaces = length(L) - 1,
if
Spaces =:= 0 -> [H|_] = L,
H;
true ->
Strlen = lists:foldl(fun(X, Sum) -> X + Sum end, 0, lists:map(fun (X) -> length(X) end, L)),
Topad = W - Strlen,
Bspace = ceiling(Topad / Spaces),
Sspaces = Bspace * Spaces - Topad,
Sspace = Bspace - 1,
Bspaces = Spaces - Sspaces,
Big = lists:duplicate(Bspaces, string:copies(" ", Bspace)),
Small = lists:duplicate(Sspaces, string:copies(" ", Sspace)),
interleave(lists:append(Big, Small), L)
end.
interleave([], []) -> [];
interleave([], [W]) -> W;
interleave([S|Ss], [W|Ws]) -> string:concat(string:concat(W, S), interleave(Ss, Ws)).
nopad([X]) -> X;
nopad([H|T]) -> string:concat(string:concat(H, " "), nopad(T)).
ceiling(X) -> T = trunc(X),
case (X - T) of
Neg when Neg < 0 -> T;
Pos when Pos > 0 -> T + 1;
_ -> T
end.
take(N, []) -> [];
take(N, [H|T]) -> HLen = string:len(H),
if
(N < HLen) -> [];
true -> [H | take(N - length(H) - 1, T)]
end.
noempty([]) -> [];
noempty([[]|T]) -> noempty(T);
noempty([H|T]) -> [H | noempty(T)].
join([]) -> "";
join([H|T]) -> lists:append([H, " ", join(T)]).
addtab(_, []) -> [];
addtab(I, [[H|T]|TT]) -> [[(lists:append(string:copies(" ", I), H)) | T] | addtab(I, TT)].
readl() -> noempty(readl([[]])).
readl([H|T]) ->
case io:get_line("") of
eof -> [H|T];
Line ->
S = string:strip(Line),
SLine = string:substr(S, 1, length(S) - 1),
if
SLine == [] -> readl([[] | [H|T]]);
true -> readl([[SLine | H] | T])
end
end.
===== Zadanie 3. ======
-module(zad3).
-export([new/1, singleton/2, insert/3, delete/2, search/2, split/2, join/2]).
% a test:
% (fun({ok,X,new})->zad3:delete(3, X) end)(zad3:new(lists:zip(lists:seq(1,10), lists:seq(501,510)))).
singleton(K, V) -> {K, V, leaf, leaf}.
new(L) ->
lists:foldl(
fun({K,V}, {ok, Acc, new})->insert(K, V, Acc) end,
{ok, leaf, new},
L
).
search(SK, T) ->
T2 = lookup(SK, T),
case T2 of
leaf -> {error, not_found};
{K, V, _, _} -> if
SK =:= K -> {ok, T2, V};
true -> {error, not_found}
end
end.
lookup(_, leaf) -> leaf;
lookup(SK, T) ->
{K, V, L, R} = T,
if
SK =:= K -> T;
SK < K -> case lookup(SK, L) of
leaf -> T;
{K1, V1, L1, R1} -> {K1, V1, L1, {K, V, R1, R}}
end;
true -> case lookup(SK, R) of
leaf -> T;
{K1, V1, L1, R1} -> {K1, V1, {K, V, L, L1}, R1}
end
end.
insert(K, V, T) ->
case lookup(K, T) of
leaf -> {ok, singleton(K, V), new};
{K1, V1, L, R} -> if
K1 =:= K -> {ok, {K, V, L, R}, V1};
K1 < K -> {ok, {K, V, {K1, V1, L, leaf}, R}, new};
true -> {ok, {K, V, L, {K1, V1, leaf, R}, new}}
end
end.
delete(SK, T) -> case lookup(SK, T) of
{SK, V, L, R} -> {ok, join(L, R), V};
true -> {error, not_found}
end.
split(SK, T) -> case lookup(SK, T) of
{SK, _, L, R} -> {ok, L, R};
true -> {error, not_found}
end.
join(T1, T2) -> case splayRight(T1) of
{K, V, L, leaf} -> {K, V, L, T2};
leaf -> T2
end.
splayRight(leaf) -> leaf;
splayRight({K, V, L, leaf}) -> {K, V, L, leaf};
splayRight({K1, V1, L1, {K2, V2, L2, R2}}) ->
splayRight({K2, V2, {K1, V1, L1, L2}, R2}).