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."))
}