Problem:
Cube Surface Puzzle

Given a set of six pieces, “Cube Surface Puzzle” is to construct a hollow cube with filled surface.
Pieces of a puzzle is made of a number of small unit cubes laid grid-aligned on a plane.
For a puzzle constructing a cube of its side length n,
unit cubes are on either of the following two areas.

Core (blue): A square area with its side length n−2.
Unit cubes fill up this area.

Fringe (red): The area of width 1 unit forming the outer fringe of the core.
Each unit square in this area may be empty or with a unit cube on it.

Each piece is connected with faces of its unit cubes.
Pieces can be arbitrarily rotated and either side of the pieces can
be inside or outside of the constructed cube.
The unit cubes on the core area should come in the centers of the
faces of the constructed cube.

Consider that we have six pieces in Fig. E-1 (The first dataset of Sample Input).
Then, we can construct a cube as shown in Fig. E-2.

Fig. E-1 Pieces from the first dataset of Sample Input

Fig. E-2 Constructing a cube

Mr. Hadrian Hex has collected a number of cube surface puzzles.
One day, those pieces were mixed together and he
cannot find yet from which six pieces he can construct a cube.
Your task is to write a program to help Mr. Hex, which judges whether we can construct a cube for a given set of pieces.

Input

The input consists of at most 200 datasets, each in the following format.

n

x1,1x1,2 … x1,n

x2,1x2,2 … x2,n

…

x6n,1x6n,2 … x6n,n

The first line contains an integer n denoting the length of one side of the cube to be constructed (3 ≤ n ≤ 9, n is odd).
The following 6n lines give the six pieces.
Each piece is described in n lines.
Each of the lines corresponds to one grid row and each of the characters in
the line, either ‘X’ or ‘.’, indicates whether or not a unit cube is on
the corresponding unit square: ‘X’ means a unit cube is on the column and ‘.’ means none is there.

The core area of each piece is centered in the data for the piece.

The end of the input is indicated by a line containing a zero.

Output

For each dataset, output “Yes” if we can construct a cube, or “No” if we cannot.

Sample Input

5
..XX.
.XXX.
XXXXX
XXXXX
X....
....X
XXXXX
.XXX.
.XXX.
.....
..XXX
XXXX.
.XXXX
.XXXX
...X.
...X.
.XXXX
XXXX.
XXXX.
.X.X.
XXX.X
.XXXX
XXXXX
.XXXX
.XXXX
XX...
.XXXX
XXXXX
XXXXX
XX...
5
..XX.
.XXX.
XXXXX
XXXX.
X....
....X
XXXXX
.XXX.
.XXX.
.....
.XXXX
XXXX.
.XXXX
.XXXX
...X.
...X.
.XXXX
XXXX.
XXXX.
.X.X.
XXX.X
.XXXX
XXXXX
.XXXX
.XXXX
XX...
XXXXX
XXXXX
.XXXX
XX...
0

Output for the Sample Input

Yes
No

Solution in Scala (judge verdict: Accepted)

import scala.annotation.tailrec
import scala.reflect.ClassTag


object Main extends App {
  import scala.io.StdIn._
  solve()
  @tailrec def solve(): Unit = {
    val n = readInt()
    if (n == 0) return
    val cube = new Cube(n)
    val faces = Array.tabulate(6) { _ ⇒
      Face(Array.tabulate(n) { _ ⇒ readLine.trim })
    }
    cube.setFace(faces.head)
    println(if(faces.tail.permutations.exists(f ⇒ canMake(cube, f, 0))) "Yes" else "No")
    solve()
  }
  def canMake(cube: Cube, faces: Array[Face], position: Int): Boolean = {
    if (position == faces.length) true
    else {
      (0 until 4).foldLeft((false: Boolean, faces(position))) {
        case ((true, f), _) ⇒ (true, f)
        case ((false, f), _) if cube.setFace(f) ⇒
          if (canMake(cube, faces, position + 1)) (true, f)
          else {
            cube.revert()
            (false, f.rotateRight)
          }
        case ((_, f), _) ⇒ (false, f.rotateRight)
      }._1 || (0 until 4).foldLeft((false: Boolean, faces(position).flip)) {
        case ((true, f), _) ⇒ (true, f)
        case ((false, f), _) if cube.setFace(f) ⇒
          if (canMake(cube, faces, position + 1)) (true, f)
          else {
            cube.revert()
            (false, f.rotateRight)
          }
        case ((_, f), _) ⇒ (false, f.rotateRight)
      }._1
    }
  }

}
object Face {
  def apply(state: Array[String]): Face = new Face(Array2D(state.map{_.map{_ == 'X'}.toArray}))
}
class Face(val state: Array2D[Boolean]) {
  def up(x: Int) = state(0, x)
  def right(x: Int) = state.lastOf(x)
  def bottom(x: Int) = state(state.height - 1, x)
  def left(x: Int) = state.headOf(x)
  def rotateRight: Face = new Face(state.rotateRight)
  def flip: Face = new Face(state.flip)
}
class Cube(size: Int) {
  private val state: Array2D[Boolean] = Array2D.fill(size * 4, size){false}
  private var history: List[Face] = Nil
  private var last = 0

  override def toString: String = state.toString
  def setFace(face: Face): Boolean = {
    val res = last match {
      case 0 ⇒
        for ((x, y) ← face.state.indices) state(x, y) = face.state(x, y)
        true
      case 3 ⇒
        val res = (1 until size - 1).forall(x ⇒ state(3 * size - 1, x) != face.up(x) && state(0, x) != face.bottom(x)) && !(state.headOf(3 * size - 1) && face.up(0)) && !(state.lastOf(3 * size - 1) && face.up(size - 1))&& !(state.headOf(0) && face.bottom(0)) && !(state.lastOf(0) && face.bottom(size - 1))
        if (res) {
          (0 until size).foreach{x ⇒
            state(3 * size, x) = face.up(x)
            state(3 * size + x, 0) = face.left(x)
            state(3 * size + x, state.width - 1) = face.right(x)
            state(3 * size + size - 1, x) = face.bottom(x)
          }
        }
        res
      case 4 ⇒
        var r = face
        (0 until 4).forall{i ⇒
          r = r.rotateRight
          (1 until size - 1).forall(x ⇒ state.lastOf(i * size + x) != r.left(x)) && List(state.lastOf(i * size), state.lastOf((i * size + state.height - 1) % state.height), r.left(0)).count(b ⇒ b) == 1
        }
      case 5 ⇒
        var r = face
        (0 until 4).reverse.forall{i ⇒
          r = r.rotateRight
          (1 until size - 1).forall(x ⇒ state.headOf(i * size + x) != r.right(x)) && List(state.headOf(i * size), state.headOf((i * size + state.height - 1) % state.height), r.right(0)).count(b ⇒ b) == 1
        }
      case i ⇒
        val res = (1 until size - 1).forall(x ⇒ state(i * size - 1, x) != face.up(x)) && !(state.headOf(i * size - 1) && face.up(0)) && !(state.lastOf(i * size - 1) && face.up(size - 1))
        if (res) {
          (0 until size).foreach{x ⇒
            state(i * size, x) = face.up(x)
            state(i * size + x, 0) = face.left(x)
            state(i * size + x, state.width - 1) = face.right(x)
            state(i * size + size - 1, x) = face.bottom(x)
          }
        }
        res
    }
    if (res) {
      last += 1
      history ::= face
    }
    res
  }
  def revert(): Unit = {
    last -= 1
    val face = history.head
    history = history.tail
    last match {
      case 0 ⇒ for ((x, y) ← face.state.indices) state(x, y) = false
      case 4 | 5 ⇒
      case i ⇒
        (0 until size).foreach{x ⇒
          state(i * size, x) = false
          state(i * size + x, 0) = false
          state(i * size + x, state.width - 1) = false
          state(i * size + size - 1, x) = false
        }
    }
  }
}
object Array2D {
  def fill[T: ClassTag](x: Int, y: Int)(generator: ⇒ T): Array2D[T] = {
    new Pure(Array.fill(x, y)(generator))
  }
  def apply[T](array: Array[Array[T]]): Array2D[T] = new Pure[T](array)
}
sealed trait Array2D[T] {
  def apply(x: Int, y: Int): T
  def update(x: Int, y: Int, value: T): Unit
  def height: Int
  def width: Int
  def rotateRight: Array2D[T] = new Rotate[T](this)
  def flip: Array2D[T] = new Flip[T](this)
  def lastOf(x: Int) = apply(x, width - 1)
  def headOf(x: Int) = apply(x, 0)
  def indices: Iterable[(Int, Int)] = (0 until height).flatMap{x ⇒ (0 until width).map{y ⇒ (x, y)}}

  override def toString: String = {
    (0 until height).map{x ⇒ (0 until width).map{y ⇒ apply(x, y)}.mkString(",")}.mkString("\n")
  }
}
class Pure[T](private val array: Array[Array[T]]) extends Array2D[T] {
  override def apply(x: Int, y: Int): T = array(x)(y)
  override def update(x: Int, y: Int, value: T): Unit = array(x)(y) = value
  override def height: Int = array.length
  override def width: Int = array.head.length
}
class Flip[T](private val array: Array2D[T]) extends Array2D[T] {
  override def apply(x: Int, y: Int): T = array(height - x - 1, y)
  override def update(x: Int, y: Int, value: T): Unit = array(height - x - 1, y) = value
  override def height: Int = array.height
  override def width: Int = array.width
}
class Rotate[T](private val array: Array2D[T]) extends Array2D[T] {
  override def apply(x: Int, y: Int): T = array(width - y - 1, x)
  override def update(x: Int, y: Int, value: T): Unit = array(width - y - 1, x) = value
  override def height: Int = array.width
  override def width: Int = array.height
}