object AbcBlocks extends App {
protected class Block(face1: Char, face2: Char) {
def isFacedWith(that: Char) = { that == face1 || that == face2 }
override def toString() = face1.toString + face2
}
protected object Block {
def apply(faces: String) = new Block(faces.head, faces.last)
}
type word = Seq[Block]
private val blocks = List(Block("BO"), Block("XK"), Block("DQ"), Block("CP"), Block("NA"),
Block("GT"), Block("RE"), Block("TG"), Block("QD"), Block("FS"),
Block("JW"), Block("HU"), Block("VI"), Block("AN"), Block("OB"),
Block("ER"), Block("FS"), Block("LY"), Block("PC"), Block("ZM"))
private def isMakeable(word: String, blocks: word) = {
def getTheBlocks(word: String, blocks: word) = {
def inner(word: String, toCompare: word, rest: word, accu: word): word = {
if (word.isEmpty || rest.isEmpty || toCompare.isEmpty) accu
else if (toCompare.head.isFacedWith(word.head)) {
val restant = rest diff List(toCompare.head)
inner(word.tail, restant, restant, accu :+ toCompare.head)
} else inner(word, toCompare.tail, rest, accu)
}
inner(word, blocks, blocks, Nil)
}
word.lengthCompare(getTheBlocks(word, blocks).size) == 0
}
val words = List("A", "BARK", "BOOK", "TREAT", "COMMON", "SQUAD", "CONFUSED", "ANBOCPDQERSFTGUVWXLZ")
// Automatic tests
assert(isMakeable(words(0), blocks))
assert(isMakeable(words(1), blocks))
assert(!isMakeable(words(2), blocks)) // BOOK not
assert(isMakeable(words(3), blocks))
assert(!isMakeable(words(4), blocks)) // COMMON not
assert(isMakeable(words(5), blocks))
assert(isMakeable(words(6), blocks))
assert(isMakeable(words(7), blocks))
//words(7).mkString.permutations.foreach(s => assert(isMakeable(s, blocks)))
words.foreach(w => println(s"$w can${if (isMakeable(w, blocks)) " " else "not "}be made."))
}