k47.cz
mastodon twitter RSS
bandcamp explorer

Conway's game of life

18. 9. 2012 (před 10 lety) — k47 (CC by)

Conwayova hra života napsaná ve Scale

import collection.immutable.BitSet

case class Matrix(w: Int, h: Int, bitmap: BitSet) {
  def reset(cells: Seq[(Int, Int)]): Matrix =
    copy(bitmap = BitSet() ++ (cells map (pos _).tupled))

  def pos(x: Int, y: Int): Int = x + y * w

  def at(x: Int, y: Int): Boolean = bitmap(pos(x, y))

  def liveNeighbours(x: Int, y: Int): Int =
    (for {
      δx <- -1 to 1
      δy <- -1 to 1
      if !(δx == 0 && δy == 0) // exclude self
      if at(x + δx, y + δy)
    } yield 1).size

  def cellSurvive(x: Int, y: Int): Boolean =
    (at(x, y), liveNeighbours(x, y)) match {
      case (true,  2 | 3) => true
      case (false, 3)     => true
      case _              => false
    }

  def nextStep: Matrix =
    reset(for {
      x <- 0 until w
      y <- 0 until h
      if cellSurvive(x, y)
    } yield (x, y))

  def rows = 0 until (w * h) map bitmap grouped w
}

def draw(m: Matrix) =
  for (row <- m.rows) {
    //println(row map { if (_) "X" else " " } mkString)
    for (e <- row) print(if (e) "X" else " ")
    println("|")
  }


def matrixFromPoints(w: Int, h: Int)(cells: (Int, Int)*) = Matrix(w, h, BitSet()).reset(cells)
def matrixFromSchema(schema: Seq[String]) = {
  val w = schema map (_.size) min
  val h = schema.size
  val points = for {
    x <- 0 until w
    y <- 0 until h
    if schema(y)(x) == 'X'
  } yield (x, y)
  matrixFromPoints(w, h)(points: _*)
}

def padding(schema: Seq[String], padding: Int) = {
  val w = schema map (_.size) min
  def line(len: Int) = "." * len
  def linePadding = Seq.fill(padding)(line(w + 2 * padding))
  linePadding ++ (schema map { l => line(padding) + l + line(padding) }) ++ linePadding
}


val schema = Seq(
  "................",
  "................",
  "................",
  ".....X...XXX....",
  ".....XXX..X.....",
  "......X.........",
  "................",
  "................"
)

var g = matrixFromSchema(padding(schema, 30))
for (gen <- 0 to 1000) {
  g = g.nextStep
  draw(g)
  println()
}
píše k47, ascii@k47.cz