Converted to OTP app.
[cellular-automata.git] / 001 / life.erl
diff --git a/001/life.erl b/001/life.erl
deleted file mode 100644 (file)
index c44674d..0000000
+++ /dev/null
@@ -1,207 +0,0 @@
--module(life).
-
--export([bang/1]).
-
-
--define(DIRECTIONS, ['N', 'NE', 'E', 'SE', 'S', 'SW', 'W', 'NW']).
-
--define(INTERVAL, 0).  % In milliseconds
-
--define(CHAR_DEAD,   32).  % Space
--define(CHAR_ALIVE, 111).  % o
--define(CHAR_BAR,    61).  % =
-
-
-%% ============================================================================
-%% Life processes
-%% ============================================================================
-
-%% ----------------------------------------------------------------------------
-%% Big bang
-%% ----------------------------------------------------------------------------
-
-bang([X, Y]) ->
-    bang(atom_to_integer(X), atom_to_integer(Y)).
-
-
-bang(X, Y) ->
-    N = X * Y,
-    CellIDs = lists:seq(1, N),
-
-    Graph =
-        lists:foldl(
-            fun(ID, Pairs) ->
-                Neighbors = [
-                    integer_to_atom(neighbor_id(D, X, ID))
-                    || D <- ?DIRECTIONS
-                ],
-                [{integer_to_atom(ID), Neighbors} | Pairs]
-            end,
-            [],
-            CellIDs
-        ),
-
-    Parent = self(),
-
-    lists:foreach(
-        fun({ID, Neighbors}) ->
-            register(
-                ID,
-                spawn(fun() -> cell(ID, Parent, Neighbors) end)
-            )
-        end,
-        [{ID, filter_offsides(N, Neighbors)} || {ID, Neighbors} <- Graph]
-    ),
-
-    CellNames = [integer_to_atom(ID) || ID <- CellIDs],
-
-    tick(X, CellNames).
-
-
-%% ----------------------------------------------------------------------------
-%% Tick / tock
-%% ----------------------------------------------------------------------------
-
-tick(X, Cells) ->
-    ok = send_all(Cells, {tick, self()}),
-    All = Cells,
-    Pending = Cells,
-    StatePairs = [],
-    tock(X, All, Pending, StatePairs).
-
-
-tock(X, All, [], StatePairs) ->
-    States =
-        lists:foldl(
-            fun({_ID, State}, States) -> [State | States] end,
-            [],
-            lists:sort(
-                fun({A, _}, {B, _}) ->
-                    atom_to_integer(A) < atom_to_integer(B)
-                end,
-                StatePairs
-            )
-        ),
-    ok = do_print_bar(X),
-    ok = do_print_states(X, States),
-    ok = do_print_bar(X),
-    ok = timer:sleep(?INTERVAL),
-    tick(X, All);
-
-tock(X, All, Pending, StatePairs) ->
-    receive
-        {tock, {ID, State}} ->
-            NewPending = lists:delete(ID, Pending),
-            NewStatePairs = [{ID, State} | StatePairs],
-            tock(X, All, NewPending, NewStatePairs)
-    end.
-
-
-%% ----------------------------------------------------------------------------
-%% Cell
-%% ----------------------------------------------------------------------------
-
-% Init
-cell(MyID, MyParent, MyNeighbors) ->
-    MyState = crypto:rand_uniform(0, 2),
-    cell(MyID, MyParent, MyNeighbors, MyState).
-
-
-cell(MyID, MyParent, MyNeighbors, MyState) ->
-    receive
-        {tick, MyParent} ->
-            ok = send_all(MyNeighbors, {request_state, MyID}),
-            cell(MyID, MyParent, MyNeighbors, MyState, {MyNeighbors, []})
-    end.
-
-
-% All neighbors replied
-cell(MyID, MyParent, MyNeighbors, MyState, {[], States}) ->
-    LiveNeighbors = lists:sum(States),
-    MyNewState = new_state(MyState, LiveNeighbors),
-    MyParent ! {tock, {MyID, MyState}},
-    cell(MyID, MyParent, MyNeighbors, MyNewState);
-
-% Awaiting requests and replies
-cell(MyID, MyParent, MyNeighbors, MyState, {Pending, States}) ->
-    receive
-        {request_state, ID} ->
-            ID ! {response_state, MyID, MyState},
-            cell(MyID, MyParent, MyNeighbors, MyState, {Pending, States});
-
-        {response_state, ID, State} ->
-            NewPending = lists:delete(ID, Pending),
-            NewStates = [State | States],
-            cell(MyID, MyParent, MyNeighbors, MyState, {NewPending, NewStates})
-    end.
-
-
-%% ============================================================================
-%% Rules
-%% ============================================================================
-
-new_state(1, LiveNeighbors) when LiveNeighbors  <  2 -> 0;
-new_state(1, LiveNeighbors) when LiveNeighbors  <  4 -> 1;
-new_state(1, LiveNeighbors) when LiveNeighbors  >  3 -> 0;
-new_state(0, LiveNeighbors) when LiveNeighbors =:= 3 -> 1;
-new_state(State, _LiveNeighbors) -> State.
-
-
-neighbor_id(Direction, X, ID) ->
-    ID + offset(Direction, X).
-
-
-offset('N' , X) -> ensure_negative(X);
-offset('NE', X) -> ensure_negative(X - 1);
-offset('E' , _) ->                     1;
-offset('SE', X) ->                 X + 1;
-offset('S' , X) ->                 X;
-offset('SW', X) ->                 X - 1;
-offset('W' , _) -> ensure_negative(    1);
-offset('NW', X) -> ensure_negative(X + 1).
-
-
-filter_offsides(N, IDs) ->
-    [ID || ID <- IDs, is_onside(N, atom_to_integer(ID))].
-
-
-is_onside(_, ID) when ID < 1 -> false;
-is_onside(N, ID) when ID > N -> false;
-is_onside(_, _) -> true.
-
-
-%% ============================================================================
-%% Plumbing
-%% ============================================================================
-
-ensure_negative(N) when N < 0 -> N;
-ensure_negative(N) -> -(N).
-
-
-atom_to_integer(Atom) ->
-    list_to_integer(atom_to_list(Atom)).
-
-
-integer_to_atom(Integer) ->
-    list_to_atom(integer_to_list(Integer)).
-
-
-send_all([], _) -> ok;
-send_all([PID | PIDs], Msg) ->
-    PID ! Msg,
-    send_all(PIDs, Msg).
-
-
-do_print_states(_, []) -> ok;
-do_print_states(X, States) ->
-    {XStates, RestStates} = lists:split(X, States),
-    ok = io:format([state_to_char(S) || S <- XStates] ++ "\n"),
-    do_print_states(X, RestStates).
-
-
-do_print_bar(X) ->
-    io:format("~s~n", [[?CHAR_BAR || _ <- lists:seq(1, X - 1)]]).
-
-
-state_to_char(0) -> ?CHAR_DEAD;
-state_to_char(1) -> ?CHAR_ALIVE.
This page took 0.031553 seconds and 4 git commands to generate.