Last active
October 23, 2016 13:13
-
-
Save clayrat/62f60e698c0434808ce8a0066356d07d to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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