Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /**
- * 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 })
- }
- }
Add Comment
Please, Sign In to add comment