Raw source code chameneos.erl.
Transcript chameneos.txt.
-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.