Skip to content

Instantly share code, notes, and snippets.

@groz
Last active September 23, 2015 22:39
Show Gist options
  • Save groz/41b1b8dfce081edc1dd7 to your computer and use it in GitHub Desktop.
Save groz/41b1b8dfce081edc1dd7 to your computer and use it in GitHub Desktop.
Conway's Game of Life in Scala
package gameoflife
final case class Cell(x: Long, y: Long)
// Actual solution
object Life {
def proximity(c: Cell): Set[Cell] =
(for {
x <- -1 to 1
y <- -1 to 1
} yield Cell(c.x + x, c.y + y)).toSet
def aliveNeighbours(field: Set[Cell], cell: Cell): Long =
(proximity(cell) - cell).count(field.contains)
def advance(field: Set[Cell]): Set[Cell] = {
val deadHull =
(for {
aliveCell <- field
cell <- proximity(aliveCell)
} yield cell) -- field
val cameAlive = deadHull.filter(aliveNeighbours(field, _) == 3)
val stillAlive = field.filter { c =>
val nAlive = aliveNeighbours(field, c)
nAlive == 2 || nAlive == 3
}
cameAlive ++ stillAlive
}
def play(initialState: Set[Cell], nTurns: Int, render: Set[Cell] => Unit): Set[Cell] =
(1 to nTurns).foldLeft(initialState) { (state, i) =>
render(state)
advance(state)
}
}
// Driver application
object MainApp extends App {
import scala.io.Source
val defaultInput =
"""
|(0, 1)
|(1, 2)
|(2, 0)
|(2, 1)
|(2, 2)
|(-2000000000000, -2000000000000)
|(-2000000000001, -2000000000001)
""".stripMargin
def parseField(input: String): Set[Cell] =
for {
line <- input.split("""[\r\n]+""").toSet
if line.trim.nonEmpty
stripped = line.stripPrefix("(").stripSuffix(")")
Array(x, y) = stripped.split(',').map(_.trim.toLong)
} yield Cell(x, y)
val fieldString = args match {
case Array(filename) => Source.fromFile(filename).mkString
case _ => defaultInput
}
Life.play(parseField(fieldString), 10, field => println(field))
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment