[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