Skip to content

Commit

Permalink
[New Exercise]: Conway's Game of Life (#387)
Browse files Browse the repository at this point in the history
New exercise `Conway's Game of Life`
  • Loading branch information
glaxxie authored Jun 17, 2024
1 parent 0452cc4 commit a684b4d
Show file tree
Hide file tree
Showing 8 changed files with 344 additions and 0 deletions.
8 changes: 8 additions & 0 deletions config.json
Original file line number Diff line number Diff line change
Expand Up @@ -1047,6 +1047,14 @@
"prerequisites": [],
"difficulty": 5
},
{
"slug": "game-of-life",
"name": "Conway's Game Of Life",
"uuid": "9a66392e-acde-4c17-a8c6-281498eb635a",
"practices": [],
"prerequisites": [],
"difficulty": 5
},
{
"slug": "rectangles",
"name": "Rectangles",
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
100 changes: 100 additions & 0 deletions exercises/practice/game-of-life/.meta/GameOfLife.example.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
Function Invoke-GameOfLife() {
<#
.SYNOPSIS
Compute the next generation of cells for Conway's Game of Life.
.DESCRIPTION
Given a matrix of integer acting as cells in Conway's Game of Life, compute the next generation.
Each cell has two states : alive (1) or dead (0).
Each cell have eight neighbors, and 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.
.PARAMETER Matrix
A matrix represent the current state of the game.
.EXAMPLE
$matrix = @(
@(1, 1),
@(1, 0)
)
Invok-GameOfLife -Matrix $matrix
Returns:
@(
@(1, 1),
@(1, 1)
)
#Bottom right cell come alive and the other three cells stay alive follow the logic of the rules.
#>
[CmdletBinding()]
Param(
[int[][]] $Matrix
)
if ($Matrix.Count -eq 0) {
return @()
}

$mapValues = @{}
for ($r = 0; $r -lt $Matrix.Count; $r++) {
for ($c = 0; $c -lt $Matrix[$r].Count; $c++) {
$cell = [Cell]::new($r,$c)
Update-Cell $cell $mapValues $Matrix

$neighbors = $Cell.GetNeighbors($Matrix.Count)
foreach ($n in $neighbors) {
Update-Cell $n $mapValues $Matrix
}
$isAlive = $Matrix[$r][$c] -eq 1
$liveNeighbors = ($neighbors | Where-Object {$mapValues[$_.ToString()] -eq 1}).Count
if ($isAlive -and ($liveNeighbors -eq 2 -or $liveNeighbors -eq 3) -or (-not $isAlive -and $liveNeighbors -eq 3)) {
$Matrix[$r][$c] = 1
}else {
$Matrix[$r][$c] = 0
}
}
}
$Matrix
}
class Cell {
[int]$Row
[int]$Column

Cell([int]$row, [int]$col) {
$this.Row = $row
$this.Column = $col
}

[System.Collections.Generic.List[Cell]] GetNeighbors([int]$Limit) {
$neighbors = [System.Collections.Generic.List[Cell]]::new()
foreach ($i in -1..1) {
foreach ($j in -1..1) {
if ($i -eq 0 -and $j -eq 0) {
continue
}
$newR = $this.Row + $i
$newC = $this.Column + $j
if ($newR -ge 0 -and $newR -lt $Limit -and $newC -ge 0 -and $newC -lt $Limit) {
$neighbors.Add([Cell]::new($newR, $newC))
}
}
}
return $neighbors
}

[string]ToString() {
return "$($this.Row):$($this.Column)"
}
}

function Update-Cell {
param (
[Cell]$Cell,
[hashtable]$Map,
[int[][]] $Matrix
)
if (-not $Map.ContainsKey($Cell.ToString())) {
$Map[$Cell.ToString()] = $Matrix[$Cell.Row][$Cell.Column]
}
}
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": [
"glaxxie"
],
"files": {
"solution": [
"GameOfLife.ps1"
],
"test": [
"GameOfLife.tests.ps1"
],
"example": [
".meta/GameOfLife.example.ps1"
]
},
"blurb": "Implement Conway's Game of Life.",
"source": "Wikipedia",
"source_url": "https://en.wikipedia.org/wiki/Conway%27s_Game_of_Life"
}
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"
36 changes: 36 additions & 0 deletions exercises/practice/game-of-life/GameOfLife.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
Function Invoke-GameOfLife() {
<#
.SYNOPSIS
Compute the next generation of cells for Conway's Game of Life.
.DESCRIPTION
Given a matrix of integer acting as cells in Conway's Game of Life, compute the next generation.
Each cell has two states : alive (1) or dead (0).
Each cell have eight neighbors, and 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.
.PARAMETER Matrix
A matrix represent the current state of the game.
.EXAMPLE
$matrix = @(
@(1, 1),
@(1, 0)
)
Invok-GameOfLife -Matrix $matrix
Returns:
@(
@(1, 1),
@(1, 1)
)
#Bottom right cell come alive and the other three cells stay alive follow the logic of the rules.
#>
[CmdletBinding()]
Param(
[int[][]] $Matrix
)
Throw "Please implement this function"
}
127 changes: 127 additions & 0 deletions exercises/practice/game-of-life/GameOfLife.tests.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
BeforeAll {
. "./GameOfLife.ps1"
}

Describe "GameOfLife test cases" {
It "empty matrix" {
$got = Invoke-GameOfLife -Matrix @()
$want = @()

$got | Should -BeExactly $want
}

It "live cells with zero live neighbors die" {
$got = Invoke-GameOfLife -Matrix @(
@(0, 0, 0),
@(0, 1, 0),
@(0, 0, 0)
)
$want = @(
@(0, 0, 0),
@(0, 0, 0),
@(0, 0, 0)
)

$got | Should -BeExactly $want
}

It "live cells with only one live neighbor die" {
$got = Invoke-GameOfLife -Matrix @(
@(0, 0, 0),
@(0, 1, 0),
@(0, 1, 0)
)
$want = @(
@(0, 0, 0),
@(0, 0, 0),
@(0, 0, 0)
)

$got | Should -BeExactly $want
}

It "live cells with two live neighbors stay alive" {
$got = Invoke-GameOfLife -Matrix @(
@(1, 0, 1),
@(1, 0, 1),
@(1, 0, 1)
)
$want = @(
@(0, 0, 0),
@(1, 0, 1),
@(0, 0, 0)
)

$got | Should -BeExactly $want
}

It "live cells with three live neighbors stay alive" {
$got = Invoke-GameOfLife -Matrix @(
@(0, 1, 0),
@(1, 0, 0),
@(1, 1, 0)
)
$want = @(
@(0, 0, 0),
@(1, 0, 0),
@(1, 1, 0)
)

$got | Should -BeExactly $want
}

It "dead cells with three live neighbors become alive" {
$got = Invoke-GameOfLife -Matrix @(
@(1, 1, 0),
@(0, 0, 0),
@(1, 0, 0)
)
$want = @(
@(0, 0, 0),
@(1, 1, 0),
@(0, 0, 0)
)

$got | Should -BeExactly $want
}

It "live cells with four or more neighbors die" {
$got = Invoke-GameOfLife -Matrix @(
@(1, 1, 1),
@(1, 1, 1),
@(1, 1, 1)
)
$want = @(
@(1, 0, 1),
@(0, 0, 0),
@(1, 0, 1)
)

$got | Should -BeExactly $want
}

It "bigger matrix" {
$got = Invoke-GameOfLife -Matrix @(
@(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)
)
$want = @(
@(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)
)

$got | Should -BeExactly $want
}
}

0 comments on commit a684b4d

Please sign in to comment.