Moved Life implementations into 'life' directory.
[cellular-automata.git] / life / 001 / src / life.erl
diff --git a/life/001/src/life.erl b/life/001/src/life.erl
new file mode 100644 (file)
index 0000000..2c0f3d3
--- /dev/null
@@ -0,0 +1,86 @@
+-module(life).
+-behaviour(application).
+
+
+%% API
+-export([bang/0]).
+
+%% Callbacks
+-export([start/2, stop/1]).
+
+
+-define(DIRECTIONS, ['N', 'NE', 'E', 'SE', 'S', 'SW', 'W', 'NW']).
+
+
+%% ============================================================================
+%% API
+%% ============================================================================
+
+bang() ->
+    application:start(?MODULE).
+
+
+%% ============================================================================
+%% Callbacks
+%% ============================================================================
+
+start(_StartType, _StartArgs) ->
+    {ok, X} = application:get_env(?MODULE, x),
+    {ok, Y} = application:get_env(?MODULE, y),
+    CellData = cell_data(X, Y),
+    life_god:start_link(X, Y, CellData).
+
+
+stop(_State) ->
+    ok.
+
+
+%% ============================================================================
+%% Internal
+%% ============================================================================
+
+cell_data(X, Y) ->
+    N = X * Y,
+    [cell_datum(X, N, ID) || ID <- lists:seq(1, N)].
+
+
+cell_datum(X, N, ID) ->
+    Name = integer_to_atom(ID),
+    NeighborNames = filter_offsides(N,
+        [integer_to_atom(neighbor_id(Dir, X, ID)) || Dir <- ?DIRECTIONS]
+    ),
+    {ID, Name, NeighborNames}.
+
+
+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).
+
+
+ensure_negative(N) when N < 0 -> N;
+ensure_negative(N) -> -(N).
+
+
+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.
+
+
+atom_to_integer(Atom) ->
+    list_to_integer(atom_to_list(Atom)).
+
+
+integer_to_atom(Integer) ->
+    list_to_atom(integer_to_list(Integer)).
This page took 0.029582 seconds and 4 git commands to generate.