Skip to content

Commit 4ca3d0b

Browse files
committed
Added Game of Life exercise.
1 parent 851f0be commit 4ca3d0b

File tree

10 files changed

+328
-0
lines changed

10 files changed

+328
-0
lines changed

config.json

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -479,6 +479,14 @@
479479
"practices": [],
480480
"prerequisites": [],
481481
"difficulty": 7
482+
},
483+
{
484+
"slug": "game-of-life",
485+
"name": "Conway's Game of Life",
486+
"uuid": "d22b3d88-b1ca-41b1-b00a-0d1ed45de2de",
487+
"practices": [],
488+
"prerequisites": [],
489+
"difficulty": 7
482490
}
483491
]
484492
},
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+
"SimaDovakin"
4+
],
5+
"files": {
6+
"solution": [
7+
"gameOfLife.u"
8+
],
9+
"test": [
10+
"gameOfLife.test.u"
11+
],
12+
"example": [
13+
".meta/examples/gameOfLife.example.u"
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: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
gameOfLife.directions : [(Int, Int)]
2+
gameOfLife.directions =
3+
use base.Int range
4+
5+
Each.toList do
6+
row = range -1 +2 |> each
7+
col = range -1 +2 |> each
8+
(row, col) !== (+0, +0) |> guard
9+
(row, col)
10+
11+
gameOfLife.countAliveNeighbours : Nat -> Nat -> [[Nat]] -> Nat
12+
gameOfLife.countAliveNeighbours row col matrix =
13+
rows = List.size matrix |> Nat.toInt
14+
cols =
15+
List.head matrix
16+
|> Optional.getOrElse []
17+
|> List.size
18+
|> Nat.toInt
19+
accumulateCells acc position =
20+
(r, c) = position
21+
if Int.inRange +0 rows r && Int.inRange +0 cols c then
22+
matrix
23+
|> List.at (Int.abs r)
24+
|> Optional.getOrElse []
25+
|> List.at (Int.abs c)
26+
|> Optional.getOrElse 0
27+
|> (+) acc
28+
else
29+
acc
30+
positions =
31+
List.map
32+
(cases (dr, dc) -> (Nat.toInt row + dr, Nat.toInt col + dc))
33+
directions
34+
foldLeft
35+
accumulateCells
36+
0
37+
positions
38+
39+
gameOfLife.tick : [[Nat]] -> [[Nat]]
40+
gameOfLife.tick matrix =
41+
Each.toList do
42+
rows = List.size matrix
43+
cols =
44+
matrix
45+
|> List.head
46+
|> getOrElse []
47+
|> List.size
48+
row = Each.range 0 rows
49+
Each.toList do
50+
col = Each.range 0 cols
51+
52+
cell =
53+
matrix
54+
|> List.at row
55+
|> getOrElse []
56+
|> List.at col
57+
|> getOrElse 0
58+
aliveNeighboursCount = countAliveNeighbours row col matrix
59+
match (cell, aliveNeighboursCount) with
60+
(1, aliveNeighbours) | aliveNeighbours === 2 || aliveNeighbours === 3 -> 1
61+
(0, 3) -> 1
62+
_ -> 0
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
[
2+
{
3+
"name": "empty matrix",
4+
"test_code": "verify do\n labeled \"empty matrix\" do\n expected = []\n actual = tick []\n label \"expected\" expected\n label \"actual\" actual\n ensureEqual expected actual"
5+
},
6+
{
7+
"name": "live cells with zero live neighbors die",
8+
"test_code": "verify do\n labeled \"live cells with zero live neighbors die\" do\n expected = [\n [0, 0, 0],\n [0, 0, 0],\n [0, 0, 0]\n ]\n actual = tick [\n [0, 0, 0],\n [0, 1, 0],\n [0, 0, 0]\n ]\n label \"expected\" expected\n label \"actual\" actual\n ensureEqual expected actual"
9+
},
10+
{
11+
"name": "live cells with only one live neighbor die",
12+
"test_code": "verify do\n labeled \"live cells with only one live neighbor die\" do\n expected = [\n [0, 0, 0],\n [0, 0, 0],\n [0, 0, 0]\n ]\n actual = tick [\n [0, 0, 0],\n [0, 1, 0],\n [0, 1, 0]\n ]\n label \"expected\" expected\n label \"actual\" actual\n ensureEqual expected actual"
13+
},
14+
{
15+
"name": "live cells with two live neighbors stay alive",
16+
"test_code": "verify do\n labeled \"live cells with two live neighbors stay alive\" do\n expected = [\n [0, 0, 0],\n [1, 0, 1],\n [0, 0, 0]\n ]\n actual = tick [\n [1, 0, 1],\n [1, 0, 1],\n [1, 0, 1]\n ]\n label \"expected\" expected\n label \"actual\" actual\n ensureEqual expected actual"
17+
},
18+
{
19+
"name": "live cells with three live neighbors stay alive",
20+
"test_code": "verify do\n labeled \"live cells with three live neighbors stay alive\" do\n expected = [\n [0, 0, 0],\n [1, 0, 0],\n [1, 1, 0]\n ]\n actual = tick [\n [0, 1, 0],\n [1, 0, 0],\n [1, 1, 0]\n ]\n label \"expected\" expected\n label \"actual\" actual\n ensureEqual expected actual"
21+
},
22+
{
23+
"name": "dead cells with three live neighbors become alive",
24+
"test_code": "verify do\n labeled \"dead cells with three live neighbors become alive\" do\n expected = [\n [0, 0, 0],\n [1, 1, 0],\n [0, 0, 0]\n ]\n actual = tick [\n [1, 1, 0],\n [0, 0, 0],\n [1, 0, 0]\n ]\n label \"expected\" expected\n label \"actual\" actual\n ensureEqual expected actual"
25+
},
26+
{
27+
"name": "live cells with four or more neighbors die",
28+
"test_code": "verify do\n labeled \"live cells with four or more neighbors die\" do\n expected = [\n [1, 0, 1],\n [0, 0, 0],\n [1, 0, 1]\n ]\n actual = tick [\n [1, 1, 1],\n [1, 1, 1],\n [1, 1, 1]\n ]\n label \"expected\" expected\n label \"actual\" actual\n ensureEqual expected actual"
29+
},
30+
{
31+
"name": "bigger matrix",
32+
"test_code": "verify do\n labeled \"bigger matrix\" do\n expected = [\n [1, 1, 0, 1, 1, 0, 0, 0],\n [0, 0, 0, 0, 0, 1, 1, 0],\n [1, 0, 1, 1, 1, 1, 0, 1],\n [1, 0, 0, 0, 0, 0, 0, 1],\n [1, 1, 0, 0, 1, 0, 0, 1],\n [1, 1, 0, 1, 0, 0, 0, 1],\n [1, 0, 0, 0, 0, 0, 0, 0],\n [0, 0, 0, 0, 0, 0, 1, 1]\n ]\n actual = tick [\n [1, 1, 0, 1, 1, 0, 0, 0],\n [1, 0, 1, 1, 0, 0, 0, 0],\n [1, 1, 1, 0, 0, 1, 1, 1],\n [0, 0, 0, 0, 0, 1, 1, 0],\n [1, 0, 0, 0, 1, 1, 0, 0],\n [1, 1, 0, 0, 0, 1, 1, 1],\n [0, 0, 1, 0, 1, 0, 0, 1],\n [1, 0, 0, 0, 0, 0, 1, 1]\n ]\n label \"expected\" expected\n label \"actual\" actual\n ensureEqual expected actual"
33+
}
34+
]
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# Testing transcript
2+
3+
```ucm
4+
scratch/main> load ./gameOfLife.u
5+
scratch/main> add
6+
scratch/main> load ./gameOfLife.test.u
7+
scratch/main> add
8+
scratch/main> move.term gameOfLife.tests tests
9+
```
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: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
gameOfLife.tick.tests.ex1 = verify do
2+
labeled "empty matrix" do
3+
expected = []
4+
actual = tick []
5+
label "expected" expected
6+
label "actual" actual
7+
ensureEqual expected actual
8+
9+
gameOfLife.tick.tests.ex2 = verify do
10+
labeled "live cells with zero live neighbors die" do
11+
expected = [
12+
[0, 0, 0],
13+
[0, 0, 0],
14+
[0, 0, 0]
15+
]
16+
actual = tick [
17+
[0, 0, 0],
18+
[0, 1, 0],
19+
[0, 0, 0]
20+
]
21+
label "expected" expected
22+
label "actual" actual
23+
ensureEqual expected actual
24+
25+
gameOfLife.tick.tests.ex3 = verify do
26+
labeled "live cells with only one live neighbor die" do
27+
expected = [
28+
[0, 0, 0],
29+
[0, 0, 0],
30+
[0, 0, 0]
31+
]
32+
actual = tick [
33+
[0, 0, 0],
34+
[0, 1, 0],
35+
[0, 1, 0]
36+
]
37+
label "expected" expected
38+
label "actual" actual
39+
ensureEqual expected actual
40+
41+
gameOfLife.tick.tests.ex4 = verify do
42+
labeled "live cells with two live neighbors stay alive" do
43+
expected = [
44+
[0, 0, 0],
45+
[1, 0, 1],
46+
[0, 0, 0]
47+
]
48+
actual = tick [
49+
[1, 0, 1],
50+
[1, 0, 1],
51+
[1, 0, 1]
52+
]
53+
label "expected" expected
54+
label "actual" actual
55+
ensureEqual expected actual
56+
57+
gameOfLife.tick.tests.ex5 = verify do
58+
labeled "live cells with three live neighbors stay alive" do
59+
expected = [
60+
[0, 0, 0],
61+
[1, 0, 0],
62+
[1, 1, 0]
63+
]
64+
actual = tick [
65+
[0, 1, 0],
66+
[1, 0, 0],
67+
[1, 1, 0]
68+
]
69+
label "expected" expected
70+
label "actual" actual
71+
ensureEqual expected actual
72+
73+
gameOfLife.tick.tests.ex6 = verify do
74+
labeled "dead cells with three live neighbors become alive" do
75+
expected = [
76+
[0, 0, 0],
77+
[1, 1, 0],
78+
[0, 0, 0]
79+
]
80+
actual = tick [
81+
[1, 1, 0],
82+
[0, 0, 0],
83+
[1, 0, 0]
84+
]
85+
label "expected" expected
86+
label "actual" actual
87+
ensureEqual expected actual
88+
89+
gameOfLife.tick.tests.ex7 = verify do
90+
labeled "live cells with four or more neighbors die" do
91+
expected = [
92+
[1, 0, 1],
93+
[0, 0, 0],
94+
[1, 0, 1]
95+
]
96+
actual = tick [
97+
[1, 1, 1],
98+
[1, 1, 1],
99+
[1, 1, 1]
100+
]
101+
label "expected" expected
102+
label "actual" actual
103+
ensureEqual expected actual
104+
105+
gameOfLife.tick.tests.ex8 = verify do
106+
labeled "bigger matrix" do
107+
expected = [
108+
[1, 1, 0, 1, 1, 0, 0, 0],
109+
[0, 0, 0, 0, 0, 1, 1, 0],
110+
[1, 0, 1, 1, 1, 1, 0, 1],
111+
[1, 0, 0, 0, 0, 0, 0, 1],
112+
[1, 1, 0, 0, 1, 0, 0, 1],
113+
[1, 1, 0, 1, 0, 0, 0, 1],
114+
[1, 0, 0, 0, 0, 0, 0, 0],
115+
[0, 0, 0, 0, 0, 0, 1, 1]
116+
]
117+
actual = tick [
118+
[1, 1, 0, 1, 1, 0, 0, 0],
119+
[1, 0, 1, 1, 0, 0, 0, 0],
120+
[1, 1, 1, 0, 0, 1, 1, 1],
121+
[0, 0, 0, 0, 0, 1, 1, 0],
122+
[1, 0, 0, 0, 1, 1, 0, 0],
123+
[1, 1, 0, 0, 0, 1, 1, 1],
124+
[0, 0, 1, 0, 1, 0, 0, 1],
125+
[1, 0, 0, 0, 0, 0, 1, 1]
126+
]
127+
label "expected" expected
128+
label "actual" actual
129+
ensureEqual expected actual
130+
131+
test> gameOfLife.tests = join [
132+
gameOfLife.tick.tests.ex1,
133+
gameOfLife.tick.tests.ex2,
134+
gameOfLife.tick.tests.ex3,
135+
gameOfLife.tick.tests.ex4,
136+
gameOfLife.tick.tests.ex5,
137+
gameOfLife.tick.tests.ex6,
138+
gameOfLife.tick.tests.ex7,
139+
gameOfLife.tick.tests.ex8,
140+
]
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
gameOfLife.tick : [[Nat]] -> [[Nat]]
2+
gameOfLife.tick matrix = todo "implement tick"

0 commit comments

Comments
 (0)