4
\$\begingroup\$

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 < 1 then 0 else n - 1
 let max = 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
[<EntryPoint>]
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)
 0
Ethan Bierlein
15.9k4 gold badges60 silver badges146 bronze badges
asked Oct 19, 2012 at 15:57
\$\endgroup\$

1 Answer 1

3
\$\begingroup\$

I thought it would make sense if you created a function 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 < 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.length
answered Oct 20, 2012 at 13:11
\$\endgroup\$
1
  • \$\begingroup\$ Well, this is a good improvement IMO. I'll vote up as soon as I can! Thanks. \$\endgroup\$ Commented Oct 20, 2012 at 19:00

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.