Reformatting for consistency.
[cellular-automata.git] / 003 / src / life.erl
index 2e7114c..5f91d26 100644 (file)
@@ -5,31 +5,96 @@
 
 -define(CHAR_DEAD,   32).  % " "
 -define(CHAR_ALIVE, 111).  % "o"
+-define(CHAR_BAR,    45).  % "-"
+
 -define(INTERVAL, 100).
 
 
+-record(state, {x            :: non_neg_integer()
+               ,y            :: non_neg_integer()
+               ,n            :: pos_integer()
+               ,bar          :: nonempty_string()
+               ,board        :: array()
+               ,gen_count    :: pos_integer()
+               ,gen_duration :: non_neg_integer()
+               ,print_time   :: non_neg_integer()
+               }).
+
+
 %% ============================================================================
 %% API
 %% ============================================================================
 
 bang(Args) ->
     [X, Y] = [atom_to_integer(A) || A <- Args],
-    Board = init_board(X, Y),
-    life_loop(Board).
+    {Time, Board} = timer:tc(fun() -> init_board(X, Y) end),
+    State = #state{x            = X
+                  ,y            = Y
+                  ,n            = X * Y
+                  ,bar          = [?CHAR_BAR || _ <- lists:seq(1, X)]
+                  ,board        = Board
+                  ,gen_count    = 1  % Consider inital state to be generation 1
+                  ,gen_duration = Time
+                  ,print_time   = 0  % There was no print time yet
+    },
+    life_loop(State).
 
 
 %% ============================================================================
 %% Internal
 %% ============================================================================
 
-life_loop(Board) ->
-    ok = do_print_board(Board),
+life_loop(
+    #state{x            = X
+          ,y            = Y
+          ,n            = N
+          ,bar          = Bar
+          ,board        = Board
+          ,gen_count    = GenCount
+          ,gen_duration = Time
+          ,print_time   = LastPrintTime
+    }=State) ->
+
+    {PrintTime, ok} = timer:tc(
+        fun() ->
+            do_print_screen(Board, Bar, X, Y, N, GenCount, Time, LastPrintTime)
+        end
+    ),
+
+    {NewTime, NewBoard} = timer:tc(
+        fun() ->
+            next_generation(X, Y, Board)
+        end
+    ),
+
+    NewState = State#state{board        = NewBoard
+                          ,gen_count    = GenCount + 1
+                          ,gen_duration = NewTime
+                          ,print_time   = PrintTime
+    },
+
     timer:sleep(?INTERVAL),
-    life_loop(next_generation(Board)).
+    life_loop(NewState).
+
+
+do_print_screen(Board, Bar, X, Y, N, GenCount, Time, PrintTime) ->
+    ok = do_print_status(Bar, X, Y, N, GenCount, Time, PrintTime),
+    ok = do_print_board(Board).
+
+
+do_print_status(Bar, X, Y, N, GenCount, TimeMic, PrintTimeMic) ->
+    TimeSec = TimeMic / 1000000,
+    PrintTimeSec = PrintTimeMic / 1000000,
+    ok = io:format("~s~n", [Bar]),
+    ok = io:format(
+        "X: ~b Y: ~b CELLS: ~b GENERATION: ~b DURATION: ~f PRINT TIME: ~f~n",
+        [X, Y, N, GenCount, TimeSec, PrintTimeSec]
+    ),
+    ok = io:format("~s~n", [Bar]).
 
 
 do_print_board(Board) ->
-    CharLists = array:to_list(
+    RowStrings = array:to_list(
         array:map(
             fun(_, Row) ->
                 array:to_list(
@@ -46,10 +111,10 @@ do_print_board(Board) ->
     ),
 
     ok = lists:foreach(
-        fun(CharList) ->
-            ok = io:format("~s~n", [CharList])
+        fun(RowString) ->
+            ok = io:format("~s~n", [RowString])
         end,
-        CharLists
+        RowStrings
     ).
 
 
@@ -57,10 +122,7 @@ 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)),
-
+next_generation(W, H, Board) ->
     array:map(
         fun(Y, Row) ->
             array:map(
This page took 0.031398 seconds and 4 git commands to generate.