Created
November 17, 2019 09:18
-
-
Save vhalli/b74edf65a8805f7200fc9683a4fa3266 to your computer and use it in GitHub Desktop.
Conway's Game of Life in Elm (For GDCR 2019 at Helpshift)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module Conway exposing (..) | |
import Set exposing (Set) | |
type alias Cell = | |
( Int, Int ) | |
newCell : Int -> Int -> Cell | |
newCell x y = | |
Tuple.pair x y | |
vicinity_of : Cell -> Set Cell | |
vicinity_of cell = | |
Set.fromList | |
[ newCell (Tuple.first cell - 1) (Tuple.second cell - 1) | |
, newCell (Tuple.first cell) (Tuple.second cell - 1) | |
, newCell (Tuple.first cell + 1) (Tuple.second cell - 1) | |
, newCell (Tuple.first cell - 1) (Tuple.second cell) | |
, newCell (Tuple.first cell + 1) (Tuple.second cell) | |
, newCell (Tuple.first cell - 1) (Tuple.second cell + 1) | |
, newCell (Tuple.first cell) (Tuple.second cell + 1) | |
, newCell (Tuple.first cell + 1) (Tuple.second cell + 1) | |
] | |
neighbours_of : Set Cell -> Cell -> Set Cell | |
neighbours_of alive cell = | |
cell | |
|> vicinity_of | |
|> Set.intersect alive | |
survives : Set Cell -> Cell -> Bool | |
survives alive cell = | |
cell | |
|> neighbours_of alive | |
|> Set.size | |
|> (\x -> x == 2 || x == 3) | |
regenerates : Set Cell -> Cell -> Bool | |
regenerates alive dead_cell = | |
dead_cell | |
|> neighbours_of alive | |
|> Set.size | |
|> (==) 3 | |
tick : Set Cell -> Set Cell | |
tick env = | |
let | |
neighbours = | |
Set.foldl (\c s -> Set.union s (vicinity_of c)) Set.empty env | |
dead_cells = | |
Set.diff neighbours env | |
survivors = | |
Set.filter (\c -> survives env c) env | |
second_chance = | |
Set.filter (\c -> regenerates env c) dead_cells | |
in | |
Set.union survivors second_chance |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module ConwayTest exposing (..) | |
import Conway | |
import Expect exposing (..) | |
import Set exposing (Set) | |
import Test exposing (..) | |
suite : Test | |
suite = | |
describe "Conway's Game of Life" | |
[ describe "A Cell" | |
(let | |
cell = | |
Conway.newCell 5 5 | |
alive : Set Conway.Cell | |
alive = | |
Set.fromList | |
[ Conway.newCell 3 6 | |
, Conway.newCell 4 4 | |
, Conway.newCell 6 6 | |
, Conway.newCell 9 9 | |
] | |
in | |
[ test "has a vicinity" <| | |
let | |
expected_vicinity = | |
Set.fromList | |
[ ( 4, 4 ) | |
, ( 5, 4 ) | |
, ( 6, 4 ) | |
, ( 4, 5 ) | |
, ( 6, 5 ) | |
, ( 4, 6 ) | |
, ( 5, 6 ) | |
, ( 6, 6 ) | |
] | |
in | |
\_ -> Expect.equalSets expected_vicinity (Conway.vicinity_of cell) | |
, test "may have neighbours in its vicinity" <| | |
let | |
expected_neighbours = | |
Set.fromList [ Conway.newCell 4 4, Conway.newCell 6 6 ] | |
in | |
\_ -> Expect.equalSets expected_neighbours (Conway.neighbours_of alive cell) | |
, test "with two or three live neighbours, survives" <| | |
\_ -> Expect.true "Expected cell to survive" (Conway.survives alive cell) | |
, test "with no neighbours, to die" <| | |
\_ -> Expect.false "Expected cell to die" (Conway.survives alive (Conway.newCell 0 0)) | |
, test "with more than three neighbours, to die" <| | |
let | |
too_much_bheed = | |
alive | |
|> Set.insert (Conway.newCell 4 6) | |
|> Set.insert (Conway.newCell 5 6) | |
in | |
\_ -> Expect.false "Expected cell to die" (Conway.survives too_much_bheed cell) | |
, test "with three live neighbours, becomes alive" <| | |
let | |
three_neighbours = | |
Set.insert (Conway.newCell 4 6) alive | |
in | |
\_ -> Expect.true "Expected cell to regenerate" (Conway.regenerates three_neighbours cell) | |
] | |
) | |
, describe "After each tick, a set" | |
[ test "with no cells remains unchanged" <| | |
\_ -> Expect.equalSets Set.empty (Conway.tick Set.empty) | |
, test "with a single cell becomes empty" <| | |
let | |
current_state = | |
Set.singleton (Conway.newCell 1 1) | |
in | |
\_ -> Expect.equalSets Set.empty (Conway.tick current_state) | |
, test "with multiple cells follows the rules of the game :)" <| | |
let | |
current_state = | |
Set.fromList | |
[ Conway.newCell 5 5 | |
, Conway.newCell 5 6 | |
, Conway.newCell 5 7 | |
] | |
next_state = | |
Set.fromList | |
[ Conway.newCell 4 6 | |
, Conway.newCell 5 6 | |
, Conway.newCell 6 6 | |
] | |
in | |
\_ -> Expect.equalSets next_state (Conway.tick current_state) | |
] | |
] |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment