Skip to content

Instantly share code, notes, and snippets.

@clayrat
Last active October 23, 2016 13:13
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save clayrat/62f60e698c0434808ce8a0066356d07d to your computer and use it in GitHub Desktop.
Save clayrat/62f60e698c0434808ce8a0066356d07d to your computer and use it in GitHub Desktop.
package ca
import scalaz.{Comonad, NonEmptyList, Zipper}
import Zipper._
case class Board[A](p: Zipper[Zipper[A]]) {
def up = Board(p.previous.get)
def down = Board(p.next.get)
def left = Board(p.map(_.previous.get))
def right = Board(p.map(_.next.get))
def vertical = zipper(Stream.iterate(this)(_.up).tail, this, Stream.iterate(this)(_.down).tail)
def horizontal = zipper(Stream.iterate(this)(_.left).tail, this, Stream.iterate(this)(_.right).tail)
def slice(u: Int, d: Int, l: Int, r: Int): Vector[Vector[A]] =
(p.lefts.take(u).reverse ++ p.focus #:: p.rights.take(d)).map(i =>
(i.lefts.take(l).reverse ++ i.focus #:: i.rights.take(r)).toVector
).toVector
}
object boardComonad extends Comonad[Board] {
def map[A, B](x: Board[A])(f: A => B) = Board(x.p.map(_.map(f)))
def copoint[A](x: Board[A]) = x.p.focus.focus
override def cojoin[A](x: Board[A]): Board[Board[A]] = Board(x.vertical.map(_.horizontal))
def cobind[A, B](fa: Board[A])(fab: Board[A] => B) = map(cojoin(fa))(fab)
}
object comzip {
import boardComonad._
def neighbours(p: Board[Boolean]): Int =
List(p.left, p.right, p.up, p.down, p.left.up, p.left.down, p.right.up, p.right.down)
.map(copoint).count(identity)
def conway(p: Board[Boolean]): Boolean = neighbours(p) match {
case 2 => copoint(p)
case 3 => true
case _ => false
}
def runBoard[A](init: Board[A], rule: Board[A] => A) =
Stream.iterate(init)(cobind(_)(rule))
def main(args: Array[String]) {
def middleZipper[A](empty: A)(as: NonEmptyList[A]) = {
val emptyS = Stream continually empty
zipper(emptyS, as.head, as.tail.toStream ++ emptyS).move(as.size / 2).get
}
val glider = Board(
middleZipper(zipperInstance.point(false))(
NonEmptyList(
NonEmptyList(false, true, false),
NonEmptyList(false, false, true),
NonEmptyList(true, true, true)
).map(middleZipper(false))
)
)
println(
runBoard(glider, conway).map(
map(_)(if (_) 'X' else '.')
.slice(10, 10, 10, 10)
.map(_.mkString).mkString("\n")
).take(5).mkString("\n\n")
)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment