Skip to content

Instantly share code, notes, and snippets.

@fteychene
Created April 30, 2020 07:51
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 fteychene/097b836b5f7cb9669190dd7734c03b56 to your computer and use it in GitHub Desktop.
Save fteychene/097b836b5f7cb9669190dd7734c03b56 to your computer and use it in GitHub Desktop.
GameOfLife TypeDD and Sequence test
package mtpcraft.tdd.kata
import kotlin.random.Random
sealed class Cell {
companion object
}
object Dead : Cell()
object Living : Cell()
sealed class Neighbors {
object Two : Neighbors()
object Three : Neighbors()
object LessThanTwo : Neighbors()
object MoreTHanThree : Neighbors()
}
data class GridCell(val living: Cell, val x: Int, val y: Int)
typealias Grid = Sequence<GridCell>
typealias AnalyzableCells = Pair<Cell, Neighbors>
fun evolve(analyzableCell: AnalyzableCells): Cell = analyzableCell.let { (focus, neighbours) ->
when (neighbours) {
Neighbors.Three -> Living
Neighbors.Two -> focus
Neighbors.LessThanTwo -> Dead
Neighbors.MoreTHanThree -> Dead
}
}
fun isAdjacent(focus: GridCell, other: GridCell): Boolean =
other.x in focus.x - 1..focus.x + 1 &&
other.y in focus.y - 1..focus.y + 1
fun neighbors(cells: Sequence<Cell>): Neighbors =
when (cells.filter { it is Living }.toList().size) {
in 0..1 -> Neighbors.LessThanTwo
2 -> Neighbors.Two
3 -> Neighbors.Three
else -> Neighbors.MoreTHanThree
}
fun adjacentCells(grid: Grid): Sequence<Pair<GridCell, Neighbors>> =
grid.map { focus ->
// Slow
focus to neighbors(grid.filter { it != focus && isAdjacent(focus, it) }.map { it.living }.take(9))
}
fun nextGeneration(grid: Grid): Grid =
adjacentCells(grid).map { (gridCell, neighbors) -> gridCell.copy(living = evolve(gridCell.living to neighbors)) }
fun main() {
// Could also use
val startingGrid = random(200, 200)
// val startingGrid = from(
// """
// | | O | O | O | O | O | O | O | O | O | | | | | | O | O | | O | O | O | | | | | | O | | O |
// | O | | | | | | | | | | O | | | | O | O | | O | O | | | O | O | O | O | O | O | O | O | O
// | O | | | | O | O | O | | | | O | | O | O | O | O | | | | | O | O | O | O | | | | | | O
// O | | O | | | | O | | | O | | | | O | | O | O | | O | | O | O | O | | | | | | O | | O
// O | | | | | | | | | O | | | | O | | | O | | | | O | | O | | | | | | | | O
// O | | | | O | | O | O | | | | | | O | | O | | | | | O | | | | | | | | | | O
// | | | | O | | | | | O | | O | | | | O | | | | | | | | | | | | O | O | O |
// O | | | | | | | | | | O | | | | | | | | O | | | | | | O | O | O | | O | |
// O | O | | | | | | | O | O | O | O | | | O | | O | | O | O | O | | O | | | | | O | | O |
// | | | | | | | | | | O | | O | | | | | O | | O | | | | | | | | O | O | |
// O | O | | | | | | | O | | O | | O | | O | | | O | O | | O | | | O | | | | | O | |
// O | O | | O | | | | | O | | O | | O | | O | | | | | O | O | O | | | O | | O | | | |
// | | O | O | O | | O | O | | O | | | O | | | | | O | | O | | | O | | | | | | O | O |
// | O | O | | | | | | | | O | O | O | O | | | | | | O | O | O | | | | O | | O | | O | O
// O | | O | O | | | | O | | | | | O | | O | | | | | | | | | | | O | | O | | O | O
// O | | | | | O | | | | | | | | | | | | | | | | O | O | O | | O | | | | O | O
// | O | O | O | | O | | O | | | | | O | | | O | | O | | | | | | | O | O | | O | | O |
// | O | | | | | | | | | | | O | O | | O | | | | | | O | | O | O | | | | O | O |
// | O | | | | | O | O | O | O | O | | O | | | | | O | | | | | O | | O | | O | | O | |
// O | | | | | | | | O | | | | O | | | | | | | | | | | O | O | | O | | | O |
// O | | | | O | | O | O | O | O | | | O | | | | | | | | | | | | | | | | O | O |
// | | O | O | O | O | | | | | O | O | O | | | | | | O | | | | | | O | O | O | O | O | |
// | | O | O | | | | | | | | | O | | | | | | | | | | | | O | O | | | | | O
// O | | | | O | | | | | | O | | | | | | | | | | | | | O | | | O | | | | O
// O | | | | | | | O | O | | O | | | | | | | | | | | | | | | | | O | | |
// | | O | | | | O | O | | | | | O | | O | | | | | | | O | | | | | | O | | | O
// | | | | O | | O | O | | | | | O | O | O | | O | | | | | | | | | O | | O | O | | O
// | | | O | | O | O | | | | | | | O | | O | | | | | O | O | | | | | | | | | O
// | | O | | O | O | | | | | | | | | | | | | O | | O | | | O | O | | | | | |
// O | | | | O | | | | | | | | | | | | | | O | O | O | O | | O | | | | | | O | O
// | O | O | | O | O | | O | O | | O | | O | | | | | | | | O | O | O | | | O | | O | O | |
// """.trimIndent()
// )
val generations = generateSequence(startingGrid, { nextGeneration(it) }).drop(1)
generations.take(10)
.forEachIndexed { generationId, grid ->
println("Generation $generationId")
println(displayGrid(grid))
println()
}
}
// Utils functions
fun Cell.Companion.random(): Cell =
if (Random.nextBoolean()) Living
else Dead
fun random(xBound: Int, yBound: Int): Grid =
(0..xBound)
.flatMap { x -> (0..yBound)
.map { y -> GridCell(living = Cell.random(), x= x, y= y) } }
.asSequence()
fun from(grid: String): Grid =
grid
.split("\n")
.mapIndexed { y, line ->
line.split("|")
.mapIndexed { x, cell ->
when (cell.trim()) {
"O" -> GridCell(Living, x = x, y = y)
else -> GridCell(Dead, x = x, y = y)
}
}
}
.flatten()
.asSequence()
fun displayCell(cell: GridCell): String =
when (cell.living) {
Dead -> " "
Living -> "O"
}
fun displayGrid(grid: Grid): String =
grid.groupBy { it.y }
.map { it.key to it.value.sortedBy { cell -> cell.x } }
.sortedBy { it.first }
.joinToString("\n") { (_, cells) -> cells.map(::displayCell).joinToString(" | ") }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment