Skip to content

Instantly share code, notes, and snippets.

@jedws
Created September 2, 2011 00:44
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jedws/1187685 to your computer and use it in GitHub Desktop.
Save jedws/1187685 to your computer and use it in GitHub Desktop.
functional version of conway's life
/**
* A functional Conway's game of life.
*/
package object conway {
type Coord[A] = (Int, Int) => A
type Calculator = Coord[Coord[Boolean] => Boolean]
type Size = Int
val nextCell: Boolean => Int => Boolean =
old => mates =>
if (mates > 3) false
else if (mates == 3) true
else (old && mates == 2)
val wrapper: Size => Int => Int =
size => i =>
if (i < 0) size + i
else if (i >= size) i % size
else i
/** Function for working out the next generation's value for a board */
val next: Size => Calculator = size => {
val wrap = wrapper(size)
(a, b) => {
val (x, y) = (wrap(a), wrap(b))
val (l, r, u, d) = (wrap(x - 1), wrap(x + 1), wrap(y - 1), wrap(y + 1))
val mates = List((l, u), (l, y), (l, d), (x, u), (x, d), (r, u), (r, y), (r, d))
c => nextCell { c(x, y) } { mates filter { c.tupled } size }
}
}
implicit def asCoord[A](as: Array[Array[A]]): Coord[A] = (x, y) => as(x)(y)
val calculator: Size => Calculator = s => Array.tabulate(s, s) { next(s) }
val memo: Size => Coord[Boolean] => Coord[Boolean] = s => c => Array.tabulate(s, s) { c }
val generate: Calculator => Coord[Boolean] => Coord[Boolean] = c => old => (x, y) => c(x, y)(old)
val stream: Size => Coord[Boolean] => Stream[Coord[Boolean]] = size => init => {
val next = generate(calculator(size)) andThen memo(size)
def loop(old: Coord[Boolean]): Stream[Coord[Boolean]] = old #:: loop(next(old))
loop(init)
}
val render: Size => Coord[Boolean] => String = size => c => {
val sb = new StringBuilder((size * size) + size, "")
for (x <- 0 until size) {
for (y <- 0 until size) sb.append(if (c(x, y)) "•" else " ")
sb.append("\n")
}
sb toString
}
val debug: Coord[Boolean] = (x, y) => { println("x: " + x + " y: " + y); ((x + y) & 1) == 0 }
}
package conway {
class Board(size: Size) extends Coord[Boolean] {
val board = Array.ofDim[Boolean](size, size)
def apply(x: Int) = (y: Int) => board(x)(y)
}
object Board {
import util.Random._
def random(s: Size) = asCoord(Array.tabulate(s, s) { (_, _) => nextBoolean })
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment