Last week I had the pleasure of attending Software Craftsmanship 2010 at the magnificent Bletchley Park mansion on a gloriously sunny autumn’s day.
One of the great sessions I attended was Michael Hunger’s:
Using the Game Of Life to code, discuss language, paradigms and approaches
Michael used a video of Jon Conway himself to explain the rules; which he followed up by showing a very interesting implementation using APL. Afterwards we all paired up to try implementations in various languages. After about half an hour my pair came up with the following F# implementation.
Initialise a board as a 2D Array:
let width, height = 12,12
let board = Array2D.init width height (fun x y -> 0)
Computing the next generation of life requires finding the neighbours of a specified cell:
let computeNeighbours x y (board:int[,]) =
let getValue (x,y) =
let x = (x + width) % width
let y = (y + height) % height
board.[x,y]
[
-1,-1;0,-1;1,-1;
-1,0; 1,0;
-1,1 ;0,1;1,1;
]
|> Seq.map (fun (dx,dy) -> x+dx,y+dy)
|> Seq.map getValue
|> Seq.sum
To compute the next generation the current board is mapped to a new one, computing life by matching the result of the compute neighbours function to the rules of life:
let doGeneration board =
board
|> Array2D.mapi (fun x y n ->
match n, computeNeighbours x y board with
| _, 3 -> 1
| n, 2 -> n
| _, _ -> 0
)
The board is shown to both the console and Visual Studio output window:
let show (board:int[,]) =
for y = 0 to height-1 do
for x = 0 to width-1 do
let v = if board.[x,y] = 0 then '0' else '1'
Console.Write v
Debug.Write v
Console.WriteLine ()
Debug.WriteLine ""
Console.WriteLine(String('-',width))
Debug.WriteLine(String('-',width))
Finally the board is set up and a number of generations are run:
do [7,7;8,7;9,7;9,6;8,5]
|> List.iter (fun (x,y) -> board.[x,y] <- 1)
do let mutable current = board
for i = 1 to 10 do
show current
current <- doGeneration current
done
A visually prettier implementations was achieved using JavaScript and HTML during the exercise. So just for fun I tried running the F# code inside WebSharper (which converts F# code directly to JavaScript). A few minor changes required:
- The 2D Array for the board was replaced with a Jagged Array
- The output was converted to HTML
- The loop changed to an Asynchronous Workflow
You can see the WebSharper version running here: http://trelford.com/life
Coincidentally Adam Granicz of Intellifactory, who was very recently awarded an F# MVP, will be giving a talk about his WebSharper product this Tuesday October 12th; along with Can Erten on Backtracking, for the Functional Londoner’s Meetup Group at Skills Matter!
GameOfLife.fs (1.36 kb)
GameOfLifeWebSharper.fs (2.55 kb)