Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions config.json
Original file line number Diff line number Diff line change
Expand Up @@ -479,6 +479,14 @@
"practices": [],
"prerequisites": [],
"difficulty": 7
},
{
"slug": "game-of-life",
"name": "Conway's Game of Life",
"uuid": "d22b3d88-b1ca-41b1-b00a-0d1ed45de2de",
"practices": [],
"prerequisites": [],
"difficulty": 7
}
]
},
Expand Down
11 changes: 11 additions & 0 deletions exercises/practice/game-of-life/.docs/instructions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Instructions

After each generation, the cells interact with their eight neighbors, which are cells adjacent horizontally, vertically, or diagonally.

The following rules are applied to each cell:

- Any live cell with two or three live neighbors lives on.
- Any dead cell with exactly three live neighbors becomes a live cell.
- All other cells die or stay dead.

Given a matrix of 1s and 0s (corresponding to live and dead cells), apply the rules to each cell, and return the next generation.
9 changes: 9 additions & 0 deletions exercises/practice/game-of-life/.docs/introduction.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Introduction

[Conway's Game of Life][game-of-life] is a fascinating cellular automaton created by the British mathematician John Horton Conway in 1970.

The game consists of a two-dimensional grid of cells that can either be "alive" or "dead."

After each generation, the cells interact with their eight neighbors via a set of rules, which define the new generation.

[game-of-life]: https://en.wikipedia.org/wiki/Conway%27s_Game_of_Life
19 changes: 19 additions & 0 deletions exercises/practice/game-of-life/.meta/config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{
"authors": [
"SimaDovakin"
],
"files": {
"solution": [
"gameOfLife.u"
],
"test": [
"gameOfLife.test.u"
],
"example": [
".meta/examples/gameOfLife.example.u"
]
},
"blurb": "Implement Conway's Game of Life.",
"source": "Wikipedia",
"source_url": "https://en.wikipedia.org/wiki/Conway%27s_Game_of_Life"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
gameOfLife.directions : [(Int, Int)]
gameOfLife.directions =
Each.toList do
row = range -1 +2 |> each
col = range -1 +2 |> each
(row, col) !== (+0, +0) |> guard
(row, col)

gameOfLife.countAliveNeighbours : Nat -> Nat -> [[Nat]] -> Nat
gameOfLife.countAliveNeighbours row col matrix =
rows = List.size matrix |> Nat.toInt
cols =
List.head matrix
|> Optional.getOrElse []
|> List.size
|> Nat.toInt
accumulateCells acc position =
(r, c) = position
if Int.inRange +0 rows r && Int.inRange +0 cols c then
matrix
|> List.at (Int.abs r)
|> Optional.getOrElse []
|> List.at (Int.abs c)
|> Optional.getOrElse 0
|> (+) acc
else
acc
positions =
List.map
(cases (dr, dc) -> (Nat.toInt row + dr, Nat.toInt col + dc))
directions
foldLeft
accumulateCells
0
positions

gameOfLife.tick : [[Nat]] -> [[Nat]]
gameOfLife.tick matrix =
Each.toList do
rows = List.size matrix
cols =
matrix
|> List.head
|> getOrElse []
|> List.size
row = Each.range 0 rows
Each.toList do
col = Each.range 0 cols

cell =
matrix
|> List.at row
|> getOrElse []
|> List.at col
|> getOrElse 0
aliveNeighboursCount = countAliveNeighbours row col matrix
match (cell, aliveNeighboursCount) with
(1, aliveNeighbours) | aliveNeighbours === 2 || aliveNeighbours === 3 -> 1
(0, 3) -> 1
_ -> 0
34 changes: 34 additions & 0 deletions exercises/practice/game-of-life/.meta/testAnnotation.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
[
{
"name": "empty matrix",
"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"
},
{
"name": "live cells with zero live neighbors die",
"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"
},
{
"name": "live cells with only one live neighbor die",
"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"
},
{
"name": "live cells with two live neighbors stay alive",
"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"
},
{
"name": "live cells with three live neighbors stay alive",
"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"
},
{
"name": "dead cells with three live neighbors become alive",
"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"
},
{
"name": "live cells with four or more neighbors die",
"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"
},
{
"name": "bigger matrix",
"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"
}
]
9 changes: 9 additions & 0 deletions exercises/practice/game-of-life/.meta/testLoader.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Testing transcript

```ucm
scratch/main> load ./gameOfLife.u
scratch/main> add
scratch/main> load ./gameOfLife.test.u
scratch/main> add
scratch/main> move.term gameOfLife.tests tests
```
34 changes: 34 additions & 0 deletions exercises/practice/game-of-life/.meta/tests.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# This is an auto-generated file.
#
# Regenerating this file via `configlet sync` will:
# - Recreate every `description` key/value pair
# - Recreate every `reimplements` key/value pair, where they exist in problem-specifications
# - Remove any `include = true` key/value pair (an omitted `include` key implies inclusion)
# - Preserve any other key/value pair
#
# As user-added comments (using the # character) will be removed when this file
# is regenerated, comments can be added via a `comment` key.

[ae86ea7d-bd07-4357-90b3-ac7d256bd5c5]
description = "empty matrix"

[4ea5ccb7-7b73-4281-954a-bed1b0f139a5]
description = "live cells with zero live neighbors die"

[df245adc-14ff-4f9c-b2ae-f465ef5321b2]
description = "live cells with only one live neighbor die"

[2a713b56-283c-48c8-adae-1d21306c80ae]
description = "live cells with two live neighbors stay alive"

[86d5c5a5-ab7b-41a1-8907-c9b3fc5e9dae]
description = "live cells with three live neighbors stay alive"

[015f60ac-39d8-4c6c-8328-57f334fc9f89]
description = "dead cells with three live neighbors become alive"

[2ee69c00-9d41-4b8b-89da-5832e735ccf1]
description = "live cells with four or more neighbors die"

[a79b42be-ed6c-4e27-9206-43da08697ef6]
description = "bigger matrix"
140 changes: 140 additions & 0 deletions exercises/practice/game-of-life/gameOfLife.test.u
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
gameOfLife.tick.tests.ex1 = verify do
labeled "empty matrix" do
expected = []
actual = tick []
label "expected" expected
label "actual" actual
ensureEqual expected actual

gameOfLife.tick.tests.ex2 = verify do
labeled "live cells with zero live neighbors die" do
expected = [
[0, 0, 0],
[0, 0, 0],
[0, 0, 0]
]
actual = tick [
[0, 0, 0],
[0, 1, 0],
[0, 0, 0]
]
label "expected" expected
label "actual" actual
ensureEqual expected actual

gameOfLife.tick.tests.ex3 = verify do
labeled "live cells with only one live neighbor die" do
expected = [
[0, 0, 0],
[0, 0, 0],
[0, 0, 0]
]
actual = tick [
[0, 0, 0],
[0, 1, 0],
[0, 1, 0]
]
label "expected" expected
label "actual" actual
ensureEqual expected actual

gameOfLife.tick.tests.ex4 = verify do
labeled "live cells with two live neighbors stay alive" do
expected = [
[0, 0, 0],
[1, 0, 1],
[0, 0, 0]
]
actual = tick [
[1, 0, 1],
[1, 0, 1],
[1, 0, 1]
]
label "expected" expected
label "actual" actual
ensureEqual expected actual

gameOfLife.tick.tests.ex5 = verify do
labeled "live cells with three live neighbors stay alive" do
expected = [
[0, 0, 0],
[1, 0, 0],
[1, 1, 0]
]
actual = tick [
[0, 1, 0],
[1, 0, 0],
[1, 1, 0]
]
label "expected" expected
label "actual" actual
ensureEqual expected actual

gameOfLife.tick.tests.ex6 = verify do
labeled "dead cells with three live neighbors become alive" do
expected = [
[0, 0, 0],
[1, 1, 0],
[0, 0, 0]
]
actual = tick [
[1, 1, 0],
[0, 0, 0],
[1, 0, 0]
]
label "expected" expected
label "actual" actual
ensureEqual expected actual

gameOfLife.tick.tests.ex7 = verify do
labeled "live cells with four or more neighbors die" do
expected = [
[1, 0, 1],
[0, 0, 0],
[1, 0, 1]
]
actual = tick [
[1, 1, 1],
[1, 1, 1],
[1, 1, 1]
]
label "expected" expected
label "actual" actual
ensureEqual expected actual

gameOfLife.tick.tests.ex8 = verify do
labeled "bigger matrix" do
expected = [
[1, 1, 0, 1, 1, 0, 0, 0],
[0, 0, 0, 0, 0, 1, 1, 0],
[1, 0, 1, 1, 1, 1, 0, 1],
[1, 0, 0, 0, 0, 0, 0, 1],
[1, 1, 0, 0, 1, 0, 0, 1],
[1, 1, 0, 1, 0, 0, 0, 1],
[1, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 1, 1]
]
actual = tick [
[1, 1, 0, 1, 1, 0, 0, 0],
[1, 0, 1, 1, 0, 0, 0, 0],
[1, 1, 1, 0, 0, 1, 1, 1],
[0, 0, 0, 0, 0, 1, 1, 0],
[1, 0, 0, 0, 1, 1, 0, 0],
[1, 1, 0, 0, 0, 1, 1, 1],
[0, 0, 1, 0, 1, 0, 0, 1],
[1, 0, 0, 0, 0, 0, 1, 1]
]
label "expected" expected
label "actual" actual
ensureEqual expected actual

test> gameOfLife.tests = join [
gameOfLife.tick.tests.ex1,
gameOfLife.tick.tests.ex2,
gameOfLife.tick.tests.ex3,
gameOfLife.tick.tests.ex4,
gameOfLife.tick.tests.ex5,
gameOfLife.tick.tests.ex6,
gameOfLife.tick.tests.ex7,
gameOfLife.tick.tests.ex8,
]
2 changes: 2 additions & 0 deletions exercises/practice/game-of-life/gameOfLife.u
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
gameOfLife.tick : [[Nat]] -> [[Nat]]
gameOfLife.tick matrix = todo "implement tick"