Last active
August 29, 2015 14:01
-
-
Save dsolovay/7cdc89a732dfd297957f to your computer and use it in GitHub Desktop.
Simple Life implementation in F#
This file contains hidden or 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
let rec MakeRow (length: int) (value: int) = | |
if length=0 then [] | |
else value :: MakeRow (length - 1) value | |
let rec MakeGrid (n: int) (rowMaker) = | |
if n=0 then [] | |
else rowMaker :: MakeGrid (n - 1) rowMaker | |
let MakeLifeGrid x = MakeGrid x (MakeRow x 0) | |
let LifeGrid = MakeLifeGrid 10 | |
let rec PrintGrid (grid: int list list)= | |
let rec PrintRow (row: int list) = | |
match row with | |
| [] -> printfn "" | |
| x::xs -> printf "%A" x | |
PrintRow xs | |
match grid with | |
| [] -> printfn "" | |
| x::xs -> PrintRow x | |
PrintGrid xs | |
let rec SetCellInRow pos newValue (theRow: int list) = | |
if pos<=0 then failwith "pos must be >= 1" | |
elif pos = 1 then newValue :: List.tail theRow | |
else List.head theRow :: SetCellInRow (pos-1) newValue (List.tail theRow) | |
let rec SetCell row col newValue (grid : int list list) = | |
if row <= 0 || col <= 0 then failwith "row and col must be >= 0" | |
elif row=1 then SetCellInRow col newValue (List.head grid) :: (List.tail grid) | |
else (List.head grid) :: SetCell (row - 1) col newValue (List.tail grid) | |
let rec ReadCell row col (grid: int list list) = | |
let rec ReadRowCell col (theRow: int list) = | |
if col < 1 then failwith "col must be >=1" | |
elif col=1 then List.head theRow | |
else ReadRowCell (col - 1) (List.tail theRow) | |
if row<1 then failwith "row must be >=1" | |
elif row=1 then ReadRowCell col (List.head grid) | |
else ReadCell (row-1) col (List.tail grid) | |
let ReadCellSafe row col (grid: int list list) = | |
if row < 1 || row > (List.length grid) || | |
col < 1 || col > (List.length (List.head grid)) | |
then 0 | |
else ReadCell row col grid | |
let NeighborCount row col grid = | |
ReadCellSafe (row-1) (col-1) grid + | |
ReadCellSafe (row-1) (col) grid + | |
ReadCellSafe (row-1) (col+1) grid + | |
ReadCellSafe (row) (col-1) grid + | |
ReadCellSafe (row) (col+1) grid + | |
ReadCellSafe (row+1) (col-1) grid + | |
ReadCellSafe (row+1) (col) grid + | |
ReadCellSafe (row+1) (col+1) grid | |
let SetLife row col (grid: int list list) = | |
match (NeighborCount row col grid) with | |
| 2 -> ReadCell row col grid | |
| 3 -> 1 | |
| _ -> 0 | |
let rec RunGeneration row col (grid: int list list) = | |
let rec RunGenerationOnRow row col = | |
if col > (List.length (List.head grid)) then [] | |
else SetLife row col grid :: RunGenerationOnRow row (col+1) | |
if row > (List.length grid) then [] | |
else RunGenerationOnRow row col :: RunGeneration (row+1) col grid | |
let rec SetupGrid (lifeCells: (int * int) list) (grid: int list list) = | |
if List.length lifeCells = 0 then grid | |
else | |
match (List.head lifeCells) with | |
| (row, col) -> SetupGrid (List.tail lifeCells) (SetCell row col 1 grid) | |
let rec RunGame turns currentTurn (grid: int list list) = | |
printfn "Generation %A" currentTurn | |
PrintGrid grid | |
if currentTurn = turns then printfn "Game over." | |
else | |
let newGrid = RunGeneration 1 1 grid | |
RunGame turns (currentTurn+1) newGrid | |
let beacon1 = [(2,5);(3,5); (4,5)] | |
let glider = [(4,2);(4,3);(4,4);(3,4);(2,3)] | |
RunGame 20 0 (SetupGrid glider (MakeLifeGrid 15)) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment