patternMinor
Conway's Game of Life in F#
Viewed 0 times
lifegameconway
Problem
Since I'm learning F# along with functional programming, I managed to implement the rules for Conway's Game of Life. I'm not sure if I can improve some of its parts, though. For example, the
neighbours function does an ugly range testing, but I can't think of anything simpler.module Game
open System
type Cell =
| Alive
| Dead
let amount_neighbours (board: Cell[,]) (pos: int * int) =
let range (n: int) (limit: int) =
let min = if n (limit - 2) then (limit - 1) else n + 1
[min .. max]
let x_range = range (fst pos) (Array2D.length1 board)
let y_range = range (snd pos) (Array2D.length2 board)
List.sum [for x in x_range ->
List.sum [for y in y_range -> if board.[x, y] = Alive && (x, y) <> pos then 1 else 0]]
let lifecycle (board: Cell[,]) =
Array2D.init (Array2D.length1 board) (Array2D.length2 board) (fun i j ->
let neighbours = amount_neighbours board (i, j)
match neighbours with
| 2 -> board.[i, j]
| 3 -> Alive
| _ -> Dead)
let rec process_game (board: Cell[,]) (n: int) =
match n with
| x when x > 0 ->
printfn "Iteration"
printfn "%A" board
process_game (lifecycle board) (n - 1)
| _ -> 0
[]
let main args =
let board = Array2D.init 5 5 (fun i j -> if i = 2 && j > 0 && j < 4 then Alive else Dead)
ignore (process_game board 4)
0Solution
I thought it would make sense if you created a function
But I'm not sure it's actually much better than your version:
alive, which would take care of bounds checking for you. And also simplify the the final expression by using a single sequence expression instead of two like you do.But I'm not sure it's actually much better than your version:
let amount_neighbours (board: Cell[,]) (pos: int * int) =
let alive board pos =
let (x, y) = pos
if x = Array2D.length1 board ||
y = Array2D.length2 board then
false
else
board.[x, y] = Alive
let vicinity x = seq { x - 1 .. x + 1 }
seq {
for x in vicinity (fst pos) do
for y in vicinity (snd pos) do
if (x, y) <> pos && alive board (x, y) then
yield true
} |> Seq.lengthCode Snippets
let amount_neighbours (board: Cell[,]) (pos: int * int) =
let alive board pos =
let (x, y) = pos
if x < 0 || x >= Array2D.length1 board ||
y < 0 || y >= Array2D.length2 board then
false
else
board.[x, y] = Alive
let vicinity x = seq { x - 1 .. x + 1 }
seq {
for x in vicinity (fst pos) do
for y in vicinity (snd pos) do
if (x, y) <> pos && alive board (x, y) then
yield true
} |> Seq.lengthContext
StackExchange Code Review Q#17723, answer score: 3
Revisions (0)
No revisions yet.