Skip to content

Commit 0310e6a

Browse files
committed
Add game-of-life
1 parent 5b24234 commit 0310e6a

File tree

10 files changed

+314
-0
lines changed

10 files changed

+314
-0
lines changed

config.json

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -636,6 +636,14 @@
636636
"dates"
637637
]
638638
},
639+
{
640+
"slug": "game-of-life",
641+
"name": "Conway's Game of Life",
642+
"uuid": "14c7124a-7dbc-4f7c-a852-84413f195053",
643+
"practices": [],
644+
"prerequisites": [],
645+
"difficulty": 5
646+
},
639647
{
640648
"slug": "grade-school",
641649
"name": "Grade School",
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# Instructions
2+
3+
After each generation, the cells interact with their eight neighbors, which are cells adjacent horizontally, vertically, or diagonally.
4+
5+
The following rules are applied to each cell:
6+
7+
- Any live cell with two or three live neighbors lives on.
8+
- Any dead cell with exactly three live neighbors becomes a live cell.
9+
- All other cells die or stay dead.
10+
11+
Given a matrix of 1s and 0s (corresponding to live and dead cells), apply the rules to each cell, and return the next generation.
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# Introduction
2+
3+
[Conway's Game of Life][game-of-life] is a fascinating cellular automaton created by the British mathematician John Horton Conway in 1970.
4+
5+
The game consists of a two-dimensional grid of cells that can either be "alive" or "dead."
6+
7+
After each generation, the cells interact with their eight neighbors via a set of rules, which define the new generation.
8+
9+
[game-of-life]: https://en.wikipedia.org/wiki/Conway%27s_Game_of_Life
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
{
2+
"authors": [
3+
"BNAndras"
4+
],
5+
"files": {
6+
"solution": [
7+
"src/game_of_life.erl"
8+
],
9+
"test": [
10+
"test/game_of_life_tests.erl"
11+
],
12+
"example": [
13+
".meta/example.erl"
14+
]
15+
},
16+
"blurb": "Implement Conway's Game of Life.",
17+
"source": "Wikipedia",
18+
"source_url": "https://en.wikipedia.org/wiki/Conway%27s_Game_of_Life"
19+
}
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
-module(example).
2+
3+
-export([tick/1]).
4+
5+
tick([]) -> [];
6+
tick(Matrix) ->
7+
Rows = length(Matrix),
8+
Cols = length(hd(Matrix)),
9+
RowIndices = lists:seq(0, Rows - 1),
10+
ColIndices = lists:seq(0, Cols - 1),
11+
lists:map(
12+
fun(R) ->
13+
lists:map(
14+
fun(C) -> next_tick(Matrix, R, C, Rows, Cols) end,
15+
ColIndices
16+
)
17+
end,
18+
RowIndices
19+
).
20+
21+
next_tick(Matrix, Row, Col, Rows, Cols) ->
22+
CurrentCell = get_cell(Matrix, Row, Col),
23+
LiveNeighbors = count_live_neighbors(Matrix, Row, Col, Rows, Cols),
24+
update_cell(CurrentCell, LiveNeighbors).
25+
26+
get_cell(Matrix, Row, Col) ->
27+
lists:nth(Col + 1, lists:nth(Row + 1, Matrix)).
28+
29+
update_cell(1, LiveNeighbors) when LiveNeighbors =:= 2 orelse LiveNeighbors =:= 3 -> 1;
30+
update_cell(0, 3) -> 1;
31+
update_cell(_, _) -> 0.
32+
33+
count_live_neighbors(Matrix, Row, Col, Rows, Cols) ->
34+
Neighbors = [
35+
{Row - 1, Col - 1}, {Row - 1, Col}, {Row - 1, Col + 1},
36+
{Row, Col - 1}, {Row, Col + 1},
37+
{Row + 1, Col - 1}, {Row + 1, Col}, {Row + 1, Col + 1}
38+
],
39+
lists:foldl(
40+
fun({NRow, NCol}, Acc) ->
41+
case NRow >= 0 andalso NRow < Rows andalso NCol >= 0 andalso NCol < Cols of
42+
true ->
43+
Acc + get_cell(Matrix, NRow, NCol);
44+
false ->
45+
Acc
46+
end
47+
end,
48+
0,
49+
Neighbors
50+
).
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
# This is an auto-generated file.
2+
#
3+
# Regenerating this file via `configlet sync` will:
4+
# - Recreate every `description` key/value pair
5+
# - Recreate every `reimplements` key/value pair, where they exist in problem-specifications
6+
# - Remove any `include = true` key/value pair (an omitted `include` key implies inclusion)
7+
# - Preserve any other key/value pair
8+
#
9+
# As user-added comments (using the # character) will be removed when this file
10+
# is regenerated, comments can be added via a `comment` key.
11+
12+
[ae86ea7d-bd07-4357-90b3-ac7d256bd5c5]
13+
description = "empty matrix"
14+
15+
[4ea5ccb7-7b73-4281-954a-bed1b0f139a5]
16+
description = "live cells with zero live neighbors die"
17+
18+
[df245adc-14ff-4f9c-b2ae-f465ef5321b2]
19+
description = "live cells with only one live neighbor die"
20+
21+
[2a713b56-283c-48c8-adae-1d21306c80ae]
22+
description = "live cells with two live neighbors stay alive"
23+
24+
[86d5c5a5-ab7b-41a1-8907-c9b3fc5e9dae]
25+
description = "live cells with three live neighbors stay alive"
26+
27+
[015f60ac-39d8-4c6c-8328-57f334fc9f89]
28+
description = "dead cells with three live neighbors become alive"
29+
30+
[2ee69c00-9d41-4b8b-89da-5832e735ccf1]
31+
description = "live cells with four or more neighbors die"
32+
33+
[a79b42be-ed6c-4e27-9206-43da08697ef6]
34+
description = "bigger matrix"
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
%% Erlang compiler options
2+
{erl_opts, [debug_info, warnings_as_errors]}.
3+
4+
{deps, [{erl_exercism, "0.1.2"}]}.
5+
6+
{dialyzer, [
7+
{warnings, [underspecs, no_return]},
8+
{get_warnings, true},
9+
{plt_apps, top_level_deps}, % top_level_deps | all_deps
10+
{plt_extra_apps, []},
11+
{plt_location, local}, % local | "/my/file/name"
12+
{plt_prefix, "rebar3"},
13+
{base_plt_apps, [stdlib, kernel, crypto]},
14+
{base_plt_location, global}, % global | "/my/file/name"
15+
{base_plt_prefix, "rebar3"}
16+
]}.
17+
18+
%% eunit:test(Tests)
19+
{eunit_tests, []}.
20+
%% Options for eunit:test(Tests, Opts)
21+
{eunit_opts, [verbose]}.
22+
23+
%% == xref ==
24+
25+
{xref_warnings, true}.
26+
27+
%% xref checks to run
28+
{xref_checks, [undefined_function_calls, undefined_functions,
29+
locals_not_used, exports_not_used,
30+
deprecated_function_calls, deprecated_functions]}.
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{application, game_of_life,
2+
[{description, "exercism.org - game-of-life"},
3+
{vsn, "0.0.1"},
4+
{modules, []},
5+
{registered, []},
6+
{applications, [kernel,
7+
stdlib]},
8+
{env, []}
9+
]}.
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
-module(game_of_life).
2+
3+
-export([tick/1]).
4+
5+
6+
tick(_Matrix) -> undefined.
Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
-module(game_of_life_tests).
2+
3+
-include_lib("erl_exercism/include/exercism.hrl").
4+
-include_lib("eunit/include/eunit.hrl").
5+
6+
7+
8+
9+
'1_empty_matrix_test_'() ->
10+
{"empty matrix",
11+
fun() ->
12+
Matrix = [],
13+
Expected = [],
14+
?assertEqual(Expected, game_of_life:tick(Matrix))
15+
end}.
16+
17+
'2_live_cells_with_zero_live_neighbors_die_test_'() ->
18+
{"live cells with zero live neighbors die",
19+
fun() ->
20+
Matrix = [
21+
[0, 0, 0],
22+
[0, 1, 0],
23+
[0, 0, 0]
24+
],
25+
Expected = [
26+
[0, 0, 0],
27+
[0, 0, 0],
28+
[0, 0, 0]
29+
],
30+
?assertEqual(Expected, game_of_life:tick(Matrix))
31+
end}.
32+
33+
'3_live_cells_with_only_one_live_neighbor_die_test_'() ->
34+
{"live cells with only one live neighbor die",
35+
fun() ->
36+
Matrix = [
37+
[0, 0, 0],
38+
[0, 1, 0],
39+
[0, 1, 0]
40+
],
41+
Expected = [
42+
[0, 0, 0],
43+
[0, 0, 0],
44+
[0, 0, 0]
45+
],
46+
?assertEqual(Expected, game_of_life:tick(Matrix))
47+
end}.
48+
49+
'4_live_cells_with_two_live_neighbors_stay_alive_test_'() ->
50+
{"live cells with two live neighbors stay alive",
51+
fun() ->
52+
Matrix = [
53+
[1, 0, 1],
54+
[1, 0, 1],
55+
[1, 0, 1]
56+
],
57+
Expected = [
58+
[0, 0, 0],
59+
[1, 0, 1],
60+
[0, 0, 0]
61+
],
62+
?assertEqual(Expected, game_of_life:tick(Matrix))
63+
end}.
64+
65+
'5_live_cells_with_three_live_neighbors_stay_alive_test_'() ->
66+
{"live cells with three live neighbors stay alive",
67+
fun() ->
68+
Matrix = [
69+
[0, 1, 0],
70+
[1, 0, 0],
71+
[1, 1, 0]
72+
],
73+
Expected = [
74+
[0, 0, 0],
75+
[1, 0, 0],
76+
[1, 1, 0]
77+
],
78+
?assertEqual(Expected, game_of_life:tick(Matrix))
79+
end}.
80+
81+
'6_dead_cells_with_three_live_neighbors_become_alive_test_'() ->
82+
{"dead cells with three live neighbors become alive",
83+
fun() ->
84+
Matrix = [
85+
[1, 1, 0],
86+
[0, 0, 0],
87+
[1, 0, 0]
88+
],
89+
Expected = [
90+
[0, 0, 0],
91+
[1, 1, 0],
92+
[0, 0, 0]
93+
],
94+
?assertEqual(Expected, game_of_life:tick(Matrix))
95+
end}.
96+
97+
'7_live_cells_with_four_or_more_neighbors_die_test_'() ->
98+
{"live cells with four or more neighbors die",
99+
fun() ->
100+
Matrix = [
101+
[1, 1, 1],
102+
[1, 1, 1],
103+
[1, 1, 1]
104+
],
105+
Expected = [
106+
[1, 0, 1],
107+
[0, 0, 0],
108+
[1, 0, 1]
109+
],
110+
?assertEqual(Expected, game_of_life:tick(Matrix))
111+
end}.
112+
113+
'8_bigger_matrix_test_'() ->
114+
{"bigger matrix",
115+
fun() ->
116+
Matrix = [
117+
[1, 1, 0, 1, 1, 0, 0, 0],
118+
[1, 0, 1, 1, 0, 0, 0, 0],
119+
[1, 1, 1, 0, 0, 1, 1, 1],
120+
[0, 0, 0, 0, 0, 1, 1, 0],
121+
[1, 0, 0, 0, 1, 1, 0, 0],
122+
[1, 1, 0, 0, 0, 1, 1, 1],
123+
[0, 0, 1, 0, 1, 0, 0, 1],
124+
[1, 0, 0, 0, 0, 0, 1, 1]
125+
],
126+
Expected = [
127+
[1, 1, 0, 1, 1, 0, 0, 0],
128+
[0, 0, 0, 0, 0, 1, 1, 0],
129+
[1, 0, 1, 1, 1, 1, 0, 1],
130+
[1, 0, 0, 0, 0, 0, 0, 1],
131+
[1, 1, 0, 0, 1, 0, 0, 1],
132+
[1, 1, 0, 1, 0, 0, 0, 1],
133+
[1, 0, 0, 0, 0, 0, 0, 0],
134+
[0, 0, 0, 0, 0, 0, 1, 1]
135+
],
136+
?assertEqual(Expected,
137+
game_of_life:tick(Matrix))
138+
end}.

0 commit comments

Comments
 (0)