[erlang-questions] Hi everyone
Ivan Carmenates García
<>
Thu Feb 28 19:42:00 CET 2013
Hi all!, I would like to introduce myself, I'm Ivan I was here two years ago
posting in this mail list, I'm from Cuba I was down for so long and I would
like to get active again. I don't know if some of you remember me, I was
posting the subject of Pythagorean's numbers and the best way to solve it in
Erlang, here is some of your solutions by then. I also was doing a framework
called EVO (Extended Visual Otp) to communicate CSharp with Erlang to make
client-server applications. I was down for private reasons but I never
forgot about Erlang that I have in my defense. Now I would like to post
again and continue my learning in Erlang. Thanks and sorry about all this,
but I really missed this mailing list. I would like to send specials thanks
to Joe Armstrong, Hynek, Willem, Tony, a friend from Spain who lived in
Cuba, Vertientes, I don't remember his name, and all of you that make this
possible.
Best, your friend Ivan.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Tony's improvement of the original form 3.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
pythag1(N) ->
L = lists:seq(1,N),
[ {A,B,C} ||
A<- L,
B<- L,
C<- L,
A+B+C =< N,
A*A+B*B =:= C*C].
%% Tony's implementation.
pythag2(N) ->
lists:reverse(pythan2_A(1, N, [])).
pythan2_A(A, N, Acc) when A> N -> Acc; pythan2_A(A, N, Acc) ->
pythan2_A(A+1,N,pythan2_B(A, 1, N, Acc)).
pythan2_B(A, B, N, Acc) when A+B> N -> Acc; pythan2_B(A, B, N, Acc) ->
pythan2_B(A,B+1,N,pythan2_C(A, B, 1, N, Acc)).
pythan2_C(A, B, C, N, Acc) when A+B+C> N -> Acc; pythan2_C(A, B, C, N,
Acc) ->
if A*A+B*B =:= C*C ->
pythan2_C(A, B, C+1, N, [{A,B,C}|Acc]);
true ->
pythan2_C(A, B, C+1, N, Acc)
end.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Hynek's implementation.
%% Simpler and about 5% faster version:
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
pythag3(N) when is_integer(N) -> pythag3(N,1).
pythag3(N, A) when A+2> N -> [];
pythag3(N, A) -> pythag3(N, A, 1).
pythag3(N, A, B) when A+B+1> N -> pythag3(N, A+1); pythag3(N, A, B)
-> pythag3(N, A, B, 1).
pythag3(N, A, B, C) when A+B+C> N -> pythag3(N, A, B+1); pythag3(N,
A, B, C) when A*A + B*B =:= C*C -> [{A, B, C}|pythag3(N, A, B,
C+1)]; pythag3(N, A, B, C) -> pythag3(N, A, B, C+1).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Edmond's implementation using parallelism.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%---- START CODE ----
py2E(Max)->
lists:flatten(lpmap(fun(A) ->
forbE(A, 1, [], Max)
end, lists:seq(1, Max), ordered)).
forbE(A, B, Acc, Max) ->
Acc1 = forcE(A, B, 1, Acc, Max),
case B< Max of
true -> forbE(A, B+1, Acc1, Max);
false -> Acc1
end.
forcE(A, B, C, Acc, Max) ->
Acc1 = case (A*A + B*B =:= C*C) andalso (A+B+C =< Max) of
true -> [{A,B,C}|Acc];
_ -> Acc
end,
case C< Max of
true-> forcE(A, B, C+1, Acc1, Max);
false-> Acc1
end.
pythag2E(N)->
lists:flatten(lpmap(fun(A) ->
pythan2_BE(A, 1, N, [])
end, lists:seq(1, N), ordered)).
pythan2_AE(A, N, Acc) when A> N -> Acc; pythan2_AE(A, N, Acc) ->
pythan2_AE(A+1,N,pythan2_BE(A, 1, N, Acc)).
pythan2_BE(A, B, N, Acc) when A+B> N -> Acc; pythan2_BE(A, B, N,
Acc) -> pythan2_BE(A,B+1,N,pythan2_CE(A, B, 1, N, Acc)).
pythan2_CE(A, B, C, N, Acc) when A+B+C> N -> Acc; pythan2_CE(A, B,
C, N, Acc) ->
if A*A+B*B =:= C*C ->
pythan2_CE(A, B, C+1, N, [{A,B,C}|Acc]);
true ->
pythan2_CE(A, B, C+1, N, Acc)
end.
%% @spec lpmap(fun(), list(), (atom() = ordered|unordered)) -> list()
%% @doc Spawns a process for each element in list L, performs specified
%% function F against each in parallel and then returns results
either
%% same order as L (ordered) or in any order (unordered).
%% NB: See also lpmap/4.
lpmap(F, L, ordered) ->
Ref = erlang:make_ref(),
Pids = [lpmap_spawn_link(self(), Ref, F, I) || I<- L],
lpmap_gather_ordered(Pids, Ref, [], 0, void); lpmap(F, L,
unordered) ->
Ref = erlang:make_ref(),
lists:foreach(fun(I) ->
lpmap_spawn_link(self(), Ref, F, I)
end, L),
lpmap_gather_unordered(length(L), Ref, [], 0, void).
%% @spec lpmap(fun(), integer(), list(), (atom() =ordered|unordered)) ->
list()
%% @doc Same as lpmap/3 except ensures only a maximum of MaxPs parallel
%% processes execute function F at any one time (i.e. first takes
MaxPs
%% items from list, executes F in parallel against each, then as
each
%% process returns, spawns another process on next item in L as
long as
%% active processes are less than MaxPs).
%% NB: See also lpmap/4.
lpmap(F, L, MaxPs, ordered) when MaxPs>0 ->
Ref = erlang:make_ref(),
{HPids, TPids} = if
length(L)> MaxPs -> lists:split(MaxPs, L);
true -> {L, []}
end,
Pids = [lpmap_spawn_link(self(), Ref, F, I) || I<- HPids],
lpmap_gather_ordered(Pids, Ref, TPids, MaxPs, F); lpmap(F, L,
MaxPs, unordered) when MaxPs>0 ->
Ref = erlang:make_ref(),
{HPids, TPids} = if
length(L)> MaxPs -> lists:split(MaxPs, L);
true -> {L, []}
end,
lists:foreach(fun(I) ->
lpmap_spawn_link(self(), Ref, F, I)
end, HPids),
lpmap_gather_unordered(length(HPids), Ref, TPids, MaxPs, F).
%% lpmap internal functions
lpmap_spawn_link(Parent, Ref, F, I) ->
spawn_link(fun() ->
Parent ! {self(), Ref, F(I)}
end).
lpmap_gather_ordered([], _Ref, [], _MaxPs, _F) ->
[];
lpmap_gather_ordered([HPid|TPids], Ref, L, MaxPs, F) ->
receive
{HPid, Ref, Ret} when length(TPids)<MaxPs, L=/=[] ->
[H | T] = L,
[Ret | lpmap_gather_ordered(
lists:append(TPids, [lpmap_spawn_link(self(), Ref, F,
H)]),
Ref, T, MaxPs, F)];
{HPid, Ref, Ret} ->
[Ret | lpmap_gather_ordered(TPids, Ref, L, MaxPs, F)]
end.
lpmap_gather_unordered(0, _Ref, [], _MaxPs, _F) ->
[];
lpmap_gather_unordered(NPs, Ref, L, MaxPs, F) ->
receive
{_Pid, Ref, Ret} when NPs-1<MaxPs, L=/=[] ->
[H | T] = L,
lpmap_spawn_link(self(), Ref, F, H),
[Ret | lpmap_gather_unordered(NPs, Ref, T, MaxPs, F)];
{_Pid, Ref, Ret} ->
[Ret | lpmap_gather_unordered(NPs-1, Ref, L, MaxPs, F)]
end.
%%---- END CODE -----
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Willem's implementation.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
wpythag2(N) ->
L = [{A, A*A} || A<- lists:seq(1,N)],
lists:flatten([forAllBs(A, A2, L, N) || {A, A2}<- L]).
forAllBs(A, A2, L, N) ->
[forAllCs(A, B, A + B, A2 + B2, L, N) || {B, B2}<- L, A + B< N].
forAllCs(A, B, AB, A2B2, L, N) ->
[{A, B, C} || {C, C2}<- L, A2B2 =:= C2, AB + C =< N].
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Hynek's new version
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
pythag4(N) when is_integer(N) -> pythag4(N,1).
pythag4(N, A) when A+2> N -> [];
pythag4(N, A) -> pythag4(N, A, A*A, 1).
pythag4(N, A, _A2, B) when A+B+1> N -> pythag4(N, A+1); pythag4(N,
A, A2, B) -> pythag4(N, A, A2, B, B*B, 1).
pythag4(N, A, A2, B, _B2, C) when A+B+C> N -> pythag4(N, A, A2,
B+1); pythag4(N, A, A2, B, B2, C) when A2 + B2 =:= C*C ->
[{A, B, C}|pythag4(N, A, A2, B, B2, C+1)]; pythag4(N, A, A2, B, B2,
C) -> pythag4(N, A, A2, B, B2, C+1).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Willem's implementation in parallel by Hynek
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
wpythag2P(N) ->
L = [{A, A*A} || A<- lists:seq(1,N)], % For all A's
lists:flatten(lpmap(fun({A, A2}) -> % For all B's in parallel
[forAllCsWH(A, B, A + B, A2 + B2, L, N)
|| {B, B2}<- L, A + B< N]
end, L, 2000, ordered)).
forAllCsWH(A, B, AB, A2B2, L, N) ->
[{A, B, C} || {C, C2}<- L, A2B2 =:= C2, AB + C =< N].
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Morten's implementation.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
pythag5(N) when is_integer(N) ->
Primes = sieve(N div 2),
M1M2s = incorporate_primes([{1,1}], N, Primes),
lists:usort(lists:flatten([ [{A,B,C}, {B,A,C}] || {M1, M2}<- M1M2s,
M1> M2, A<- [M1-M2], B<- [2*round(math:sqrt(M1*M2))], C<- [M1+M2],
A+B+C =< N])).
sieve(N) when is_integer(N) ->
erase(),
sieve(N,2).
sieve(N, K) when K>= N ->
[X || X<- lists:seq(2, N), erase(X) == undefined]; sieve(N, K) ->
cross_off(K, K, N div K - 1),
sieve(N, find_next_in_sieve(K + 1)).
cross_off(_K, _Current, 0) ->
ok;
cross_off(K, Current, Left) ->
Next = Current + K,
put(Next, out),
cross_off(K, Next, Left - 1).
find_next_in_sieve(K) ->
case get(K) of
undefined ->
K;
_ ->
find_next_in_sieve(K+1)
end.
incorporate_prime(M1M2s, N, P) ->
lists:flatten([incorporate_prime_single({M1,M2}, N, P)|| {M1, M2}<-
M1M2s]).
incorporate_prime_single({M1,M2}, N, P) ->
Evens = [{X, Y} || X<- incorporate_prime_even(M1, N, P), Y<-
incorporate_prime_even(M2, N, P)],
Odds = [{X, Y} || X<- incorporate_prime_odd(M1, N, P), Y<-
incorporate_prime_odd(M2, N, P)],
Evens ++ Odds.
incorporate_prime_even(M, N, P) ->
incorporate_prime(M, N, P, []).
incorporate_prime_odd(M, N, P) ->
incorporate_prime(M * P, N, P, []).
incorporate_prime(M, N, _P, Acc) when M> N/2 ->
Acc;
incorporate_prime(M, N, P, Acc) ->
incorporate_prime(M * P * P, N, P, [M|Acc]).
incorporate_primes(M1M2s, _N, []) ->
M1M2s;
incorporate_primes(M1M2s, N, [P|Rest]) ->
M1M2s_new = incorporate_prime(M1M2s, N, P),
incorporate_primes(M1M2s_new, N, Rest).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Richard's improvement.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
py3R(N)->
[{A,B,C} ||
A <- lists:seq(1, N div 2),
B <- lists:seq(1, N - A),
C <- [trunc(math:sqrt(A * A + B * B))],
A + B + C =< N,
A*A + B*B =:= C*C].
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Joe's improvement.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
py3a(Max) ->
N = Max div 2,
[{A,B,C} ||
A <- lists:seq(1,N+1),
B <- lists:seq(1,Max-A),
C <- lists:seq(1,Max-A-B),
A*A + B*B =:= C*C].
More information about the erlang-questions
mailing list