Created
April 25, 2017 16:42
-
-
Save ezhulenev/db594992e5f68f435fdc5970e97f02db to your computer and use it in GitHub Desktop.
Instant Insanity in Scala
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
object InstantInsanity extends App { | |
type Cube = Seq[Char] | |
val cubes: Seq[Cube] = Seq("BGWGBR", "WGBWRR", "GWRBRR", "BRGGWW").map(_.toSeq) | |
// Rotate a cube 90 degrees over its Z-axis, leaving up and down in place. | |
def rot: Cube => Cube = { case Seq(u, f, r, b, l, d) => Seq(u, r, b, l, f, d) } | |
// Twist a cube around the axis running from the upper-front-right | |
// corner to the back-left-down corner. | |
def twist: Cube => Cube = { case Seq(u, f, r, b, l, d) => Seq(f, r, u, l, d, b) } | |
// Exchange up and down, front and left, back and right. | |
def flip: Cube => Cube = { case Seq(u, f, r, b, l, d) => Seq(d, l, b, r, f, u) } | |
// Compute all 24 ways to orient a cube. | |
def orientations: Cube => Seq[Cube] = { c: Cube => | |
for { | |
c1 <- Seq(c, rot(c), rot(rot(c)), rot(rot(rot(c)))) | |
c2 <- Seq(c1, twist(c1), twist(twist(c1))) | |
c3 <- Seq(c2, flip(c2)) | |
} yield c3 | |
} | |
// Compute which faces of a cube are visible when placed in a pile. | |
def visible: Cube => Seq[Char] = { case Seq(u, f, r, b, l, d) => Seq(f, r, b, l) } | |
// Two cubes are compatible if they have different colours on every | |
// visible face. | |
def compatible: (Cube, Cube) => Boolean = { | |
case (c1, c2) => visible(c1).zip(visible(c2)).forall { case (v1, v2) => v1 != v2 } | |
} | |
// Determine whether a cube can be added to pile of cubes, without | |
// invalidating the solution. | |
def allowed: (Cube, Seq[Cube]) => Boolean = { | |
case (c, cs) => cs.forall(compatible(_, c)) | |
} | |
// Return a list of all ways of orienting each cube such that no side of | |
// the pile has two faces the same. | |
def solutions: Seq[Cube] => Seq[Seq[Cube]] = { | |
case Nil => Seq(Nil) | |
case c :: cs => for { | |
_cs <- solutions(cs) | |
_c <- orientations(c) | |
if allowed(_c, _cs) | |
} yield _c +: _cs | |
} | |
solutions(cubes) | |
.map(_.map(_.mkString(""))) | |
.map(ss => "[" + ss.mkString(", ") + "]") | |
.foreach(println) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment