Skip to content

Instantly share code, notes, and snippets.

@rockymadden
Forked from jedws/conwaydef.scala
Created March 14, 2014 21:43
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 rockymadden/9557606 to your computer and use it in GitHub Desktop.
Save rockymadden/9557606 to your computer and use it in GitHub Desktop.
/**
* A functional Conway's game of life.
*/
package object conwaydef {
type Coord[A] = (Int, Int) => A
type Calculator = Coord[Coord[Boolean] => Boolean]
type Size = Int
def nextCell(old: Boolean)(mates: Int) = if (mates > 3) false else if (mates == 3) true else (old && mates == 2)
def wrapper(size: Size)(i: Int) = 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 */
def next(size: Size) = {
val wrap = wrapper(size) _
(a: Int, b: Int) => {
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: Coord[Boolean]) => nextCell { c(x, y) } { mates filter { c.tupled } size }
}
}
implicit def asCoord[A](as: Array[Array[A]]): Coord[A] = (x, y) => as(x)(y)
def calculator(s: Size): Calculator = Array.tabulate(s, s) { next(s) }
def memo(s: Size)(c: Coord[Boolean]): Coord[Boolean] = Array.tabulate(s, s) { c }
def generate(c: Calculator)(old: Coord[Boolean]): Coord[Boolean] = (x, y) => c(x, y)(old)
def stream(size: Size) = {
val next = generate(calculator(size)) _ andThen memo(size)
def recurse(c: Coord[Boolean]) : Stream[Coord[Boolean]] = c #:: recurse(next(c))
recurse _
}
def render(size: Size, c: Coord[Boolean]): String = {
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
}
def debug(x: Int, y: Int) = { println("x: " + x + " y: " + y); ((x + y) & 1) == 0 }
}
package conwaydef {
class Board(size: Size) extends Coord[Boolean] {
val array = Array.ofDim[Boolean](size, size)
def apply(x: Int, y: Int) = array(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