Skip to content

Instantly share code, notes, and snippets.

@oschrenk
Last active April 18, 2020 18:26
Show Gist options
  • Save oschrenk/f8a40783c5db1d6eb28afffa7808e302 to your computer and use it in GitHub Desktop.
Save oschrenk/f8a40783c5db1d6eb28afffa7808e302 to your computer and use it in GitHub Desktop.
Game of Life
case class GameOfLife private(width: Int, height: Int, cells: Set[Point]) {
private def neighbors(p: Point): Set[Point] = {
(for {
x <- Math.max(1, p.x - 1).to(Math.min(this.width, p.x + 1))
y <- Math.max(1, p.y - 1).to(Math.min(this.height,p.y + 1))
} yield Point(x, y)).toSet - p
}
def changeSet: (Set[Point], Set[Point], Set[Point]) = {
this.cells.map(neighbors)
.foldLeft(Map.empty[Point, Int]) { case (allNeighbors, neighborSet) =>
neighborSet.foldLeft(allNeighbors) { case (currentNeighbors, neighbor) =>
currentNeighbors + (neighbor -> (currentNeighbors.getOrElse(neighbor, 0) + 1))
}
}
.foldLeft((Set.empty[Point], Set.empty[Point], Set.empty[Point])) {
case (s@(survivors, dying, born), (k, v)) =>
(this.cells.contains(k), v) match {
case (true, 2) => (survivors + k, dying, born)
case (true, 3) => (survivors + k, dying, born)
case (true, _) => (survivors, dying + k, born)
case (false, 3) => (survivors, dying, born + k)
case (false, _) => s
}
}
}
def tick(): World = {
val (survivors, _, born) = changeSet
GameOfLife(this.width, this.height, survivors ++ born)
}
}
object GameOfLife {
def seed[A](width: Int, height: Int, points: Set[Point]): World = {
GameOfLife(width, height, points)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment