Raw source code chameneos.erl.

Transcript chameneos.txt.

chameneos.erl

-module(chameneos).
-export([run/0, run/1]).

run() ->
    run(100).

run(N) ->
    mall(N, [blue,red,yellow]),
    io:fwrite("~n~n"),
    mall(N, [blue,red,yellow,red,yellow,blue,red,yellow,red,blue]),
    io:fwrite("~n~n").

mall(N, Colours) ->
  % Create the chameneos
    Mall = self(),
    Pids = mapi(Colours, fun (Index, Colour) ->
        spawn(fun () -> chameneo(Index, Colour, Mall, 0) end)
    end),
  % N meeting interactions
    for(1, N, fun (_) ->
        receive {join,A_pid,A_name,A_colour} ->
            receive {join,B_pid,B_name,B_colour} ->
                A_pid ! {meet,B_name,B_colour},
                B_pid ! {meet,A_name,A_colour},
                ok
            end
        end
    end),
  % Tell the chameneos to stop.
    for_each(Pids, fun (_) ->
        receive {join,C_pid,_,_} ->
            C_pid ! {quit}
        end
    end),
  % Retrieve their results and print them.
    for_each(Pids, fun (_) ->
        receive {done,D_name,D_colour,D_meets} ->
            io:fwrite("~w\t~w\t~w\tzero~n", [D_name, D_colour, D_meets])
        end
    end).

chameneo(Name, Colour, Mall, Meets) ->
    Mall ! {join,self(),Name,Colour},
    receive
        {meet,_,Other_Colour} ->
            chameneo(Name, new_colour(Colour, Other_Colour), Mall, Meets+1)
      ; {quit} ->
            Mall ! {done,Name,Colour,Meets}
    end.

new_colour(red,    red   ) -> red;
new_colour(red,    blue  ) -> yellow;
new_colour(red,    yellow) -> blue;
new_colour(blue,   red   ) -> yellow;
new_colour(blue,   blue  ) -> blue;
new_colour(blue,   yellow) -> red;
new_colour(yellow, red   ) -> blue;
new_colour(yellow, blue  ) -> red;
new_colour(yellow, yellow) -> yellow.

%-----------------------------------------------------------------------

% The following functions are provided here for clarity.
% Such functions are normally obtained from the library.

% mapi([X1,...,Xn], F) => [F(1,X1),...,F(n,Xn)]

mapi(L, F) ->
    mapi_loop(L, 0, F).

mapi_loop([X|Xs], I, F) ->
    J = I+1,
    [F(J, X) | mapi_loop(Xs, J, F)];
mapi_loop([], _, _) ->
    [].

% for(L, U, F) calls F(L), F(L+1), ..., F(U), discarding the results.

for(L, U, _) when L > U ->
    ok;
for(L, U, F) ->
    F(L),
    for(L+1, U, F).

% for_each([X1,...,Xn], F) calls F(X1), ..., F(Xn), discarding the results.

for_each([X|Xs], F) ->
    F(X),
    for_each(Xs, F);
for_each([], _) ->
    ok.