Skip to content

Instantly share code, notes, and snippets.

@dsolovay
Last active August 29, 2015 14:01
Show Gist options
  • Save dsolovay/7cdc89a732dfd297957f to your computer and use it in GitHub Desktop.
Save dsolovay/7cdc89a732dfd297957f to your computer and use it in GitHub Desktop.
Simple Life implementation in F#
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