From 7f9686038d197c41aeb768b6862135a5ca68322b Mon Sep 17 00:00:00 2001 From: Siraaj Khandkar Date: Wed, 8 Aug 2012 18:51:16 -0400 Subject: [PATCH] Matrix approach in Erlang, using array module. --- 003/.gitignore | 2 + 003/Makefile | 10 ++++ 003/src/life.app.src | 12 ++++ 003/src/life.erl | 134 +++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 158 insertions(+) create mode 100644 003/.gitignore create mode 100644 003/Makefile create mode 100644 003/src/life.app.src create mode 100644 003/src/life.erl diff --git a/003/.gitignore b/003/.gitignore new file mode 100644 index 0000000..8c6a311 --- /dev/null +++ b/003/.gitignore @@ -0,0 +1,2 @@ +ebin +data diff --git a/003/Makefile b/003/Makefile new file mode 100644 index 0000000..d715fdb --- /dev/null +++ b/003/Makefile @@ -0,0 +1,10 @@ +REBAR=rebar + + +compile: + @$(REBAR) compile + + +clean: + @$(REBAR) clean + @rm -rf ebin diff --git a/003/src/life.app.src b/003/src/life.app.src new file mode 100644 index 0000000..b4663c2 --- /dev/null +++ b/003/src/life.app.src @@ -0,0 +1,12 @@ +{application, life, + [ + {description, "Conway's Game of Life."}, + {vsn, "dev"}, + {registered, []}, + {applications, [ + kernel, + stdlib + ]}, + {mod, { life, []}}, + {env, []} + ]}. diff --git a/003/src/life.erl b/003/src/life.erl new file mode 100644 index 0000000..2e7114c --- /dev/null +++ b/003/src/life.erl @@ -0,0 +1,134 @@ +-module(life). + +-export([bang/1]). + + +-define(CHAR_DEAD, 32). % " " +-define(CHAR_ALIVE, 111). % "o" +-define(INTERVAL, 100). + + +%% ============================================================================ +%% API +%% ============================================================================ + +bang(Args) -> + [X, Y] = [atom_to_integer(A) || A <- Args], + Board = init_board(X, Y), + life_loop(Board). + + +%% ============================================================================ +%% Internal +%% ============================================================================ + +life_loop(Board) -> + ok = do_print_board(Board), + timer:sleep(?INTERVAL), + life_loop(next_generation(Board)). + + +do_print_board(Board) -> + CharLists = array:to_list( + array:map( + fun(_, Row) -> + array:to_list( + array:map( + fun(_, State) -> + state_to_char(State) + end, + Row + ) + ) + end, + Board + ) + ), + + ok = lists:foreach( + fun(CharList) -> + ok = io:format("~s~n", [CharList]) + end, + CharLists + ). + + +state_to_char(0) -> ?CHAR_DEAD; +state_to_char(1) -> ?CHAR_ALIVE. + + +next_generation(Board) -> + H = array:size(Board), + W = array:size(array:get(0, Board)), + + array:map( + fun(Y, Row) -> + array:map( + fun(X, State) -> + Neighbors = filter_offsides(H, W, neighbors(X, Y)), + States = neighbor_states(Board, Neighbors), + LiveNeighbors = lists:sum(States), + new_state(State, LiveNeighbors) + end, + Row + ) + end, + Board + ). + + +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_states(Board, Neighbors) -> + [array:get(X, array:get(Y, Board)) || {X, Y} <- Neighbors]. + + +filter_offsides(H, W, Coordinates) -> + [{X, Y} || {X, Y} <- Coordinates, is_onside(X, Y, H, W)]. + + +is_onside(X, Y, H, W) when (X >= 0) and (Y >= 0) and (X < W) and (Y < H) -> true; +is_onside(_, _, _, _) -> false. + + +neighbors(X, Y) -> + [{X + OffX, Y + OffY} || {OffX, OffY} <- offsets()]. + + +offsets() -> + [offset(D) || D <- directions()]. + + +offset('N') -> { 0, -1}; +offset('NE') -> { 1, -1}; +offset('E') -> { 1, 0}; +offset('SE') -> { 1, 1}; +offset('S') -> { 0, 1}; +offset('SW') -> {-1, 1}; +offset('W') -> {-1, 0}; +offset('NW') -> {-1, -1}. + + +directions() -> + ['N', 'NE', 'E', 'SE', 'S', 'SW', 'W', 'NW']. + + +init_board(X, Y) -> + array:map(fun(_, _) -> init_row(X) end, array:new(Y)). + + +init_row(X) -> + array:map(fun(_, _) -> init_cell_state() end, array:new(X)). + + +init_cell_state() -> + crypto:rand_uniform(0, 2). + + +atom_to_integer(Atom) -> + list_to_integer(atom_to_list(Atom)). -- 2.20.1