Problem: There is a dice with one letter of the alphabet (a ~ z, A ~ Z) drawn on each side.


<image>


Consider combining eight such dice to make a 2 x 2 x 2 cube.


<image>


There are conditions on how to combine the dice, and the facing faces of each dice must have the same alphabet, one in lowercase and the other in uppercase. For example, a surface marked a can be touched by a face marked A. However, the orientation of the characters when touching them does not matter.


<image>


According to this rule, input the information of 8 dice and create a program to judge whether or not you can make a cube. If you can make a cube, output YES (half-width uppercase letters), and if you cannot make it, output NO (half-width uppercase letters).

The letters on each side of the dice will be represented as c1 to c6 as shown in the following figure. Also, assume that the same letter is never drawn multiple times on a single dice (uppercase and lowercase letters of the same alphabet are not the case).


<image>



Input

A sequence of multiple datasets is given as input. The end of the input is indicated by a single line of zeros. Each dataset is given in the following format:


s1
s2
::
s8


The i-line gives the information si of the i-th dice. si is a string of length 6 and the jth character corresponds to each side cj of the dice.

The number of datasets does not exceed 50.

Output

The judgment result (half-width uppercase letters) is output to one line for each data set.

Example

Input

zabZNq
BCxmAi
ZcbBCj
aizXCm
QgmABC
JHzMop
ImoXGz
MZTOhp
zabZnQ
BCxmAi
ZcbBCj
aizXCm
QgmABC
JHzMop
ImoXGz
MZTOhp
abcdef
ABDCFE
FBDCAE
abcdef
BEACDF
bfcaed
fabcde
DEABCF
UnivOf
AizuaH
zTXZYW
piglIt
GRULNP
higGtH
uAzIXZ
FizmKZ
UnivOf
AizuaH
piglIt
higGtH
GRULNP
uAzIXZ
FizmKZ
ZTXzYW
0


Output

YES
NO
YES
YES
NO

Solution (in CPP):

Solution:
#include <stdio.h>
#include <cmath>
#include <algorithm>
#include <cfloat>
#include <stack>
#include <queue>
#include <vector>
#include <string>
#include <iostream>
#include <set>
#include <map>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;

class Dice{
public:



	void setPos(int num){

		for(int i = 0; i < 6; i++)work[i] = words[i];

		switch(num){
		case 0:
			setWords(work[4],work[0],work[2],work[3],work[5],work[1]);
			break;
		case 1:
			setWords(work[5],work[4],work[2],work[3],work[1],work[0]);
			break;
		case 2:
			setWords(work[1],work[5],work[2],work[3],work[0],work[4]);
			break;
		case 3:
			setWords(work[0],work[1],work[2],work[3],work[4],work[5]);
			break;
		case 4:
			setWords(work[2],work[1],work[5],work[0],work[4],work[3]);
			break;
		case 5:
			setWords(work[4],work[2],work[5],work[0],work[3],work[1]);
			break;
		case 6:
			setWords(work[3],work[4],work[5],work[0],work[1],work[2]);
			break;
		case 7:
			setWords(work[1],work[3],work[5],work[0],work[2],work[4]);
			break;
		case 8:
			setWords(work[5],work[3],work[4],work[1],work[2],work[0]);
			break;
		case 9:
			setWords(work[2],work[5],work[4],work[1],work[0],work[3]);
			break;
		case 10:
			setWords(work[0],work[2],work[4],work[1],work[3],work[5]);
			break;
		case 11:
			setWords(work[3],work[0],work[4],work[1],work[5],work[2]);
			break;
		case 12:
			setWords(work[1],work[0],work[3],work[2],work[5],work[4]);
			break;
		case 13:
			setWords(work[5],work[1],work[3],work[2],work[4],work[0]);
			break;
		case 14:
			setWords(work[4],work[5],work[3],work[2],work[0],work[1]);
			break;
		case 15:
			setWords(work[0],work[4],work[3],work[2],work[1],work[5]);
			break;
		case 16:
			setWords(work[2],work[4],work[0],work[5],work[1],work[3]);
			break;
		case 17:
			setWords(work[1],work[2],work[0],work[5],work[3],work[4]);
			break;
		case 18:
			setWords(work[3],work[1],work[0],work[5],work[4],work[2]);
			break;
		case 19:
			setWords(work[4],work[3],work[0],work[5],work[2],work[1]);
			break;
		case 20:
			setWords(work[0],work[3],work[1],work[4],work[2],work[5]);
			break;
		case 21:
			setWords(work[2],work[0],work[1],work[4],work[5],work[3]);
			break;
		case 22:
			setWords(work[5],work[2],work[1],work[4],work[3],work[0]);
			break;
		case 23:
			setWords(work[3],work[5],work[1],work[4],work[0],work[2]);
			break;
		}
	}


	char getTop(){
		return words[0];
	}

	char getEast(){
		return words[2];
	}

	char getNorth(){
		return words[1];
	}

	char getWest(){
		return words[3];
	}

	char getBottom(){
		return words[5];
	}

	char getSouth(){
		return words[4];
	}

	void setWords(char w0,char w1,char w2,char w3,char w4,char w5){
		words[0] = w0;
		words[1] = w1;
		words[2] = w2;
		words[3] = w3;
		words[4] = w4;
		words[5] = w5;
	}

	void setFirst(char c1,char c2,char c3,char c4,char c5,char c6){
		words[0] = c1;
		words[1] = c5;
		words[2] = c3;
		words[3] = c4;
		words[4] = c2;
		words[5] = c6;
	}

	void set(Dice arg){
		for(int i = 0; i < 6; i++){
			words[i] = arg.words[i];
		}
	}

	char words[6];
	char work[6];
};

struct Puzzle{
	Dice dice[2][2][2];
	int num;
};

char buf[8][7];
int calc_array[5040][7];
int array_index = 0;

bool clearFLG;


void copyPuzzle(Puzzle& to, Puzzle from){

	for(int h = 0; h < 2; h++){
		for(int row = 0; row < 2; row++){
			for(int col = 0; col < 2; col++){
				to.dice[h][row][col].set(from.dice[h][row][col]);
			}
		}
	}
}

bool is_adj(char left,char right){

	if(left > right){
		swap(left,right);
	}

	return left+32 == right;
}

void puzzle_calc(Puzzle puzzle){

	if(puzzle.num == 8){
		clearFLG = true;
		return;
	}

	switch(puzzle.num){
	case 1:

		for(int i = 0; i <= 23; i++){

			Dice tmp_dice;
			tmp_dice.set(puzzle.dice[1][0][0]);
			tmp_dice.setPos(i);

			if(is_adj(puzzle.dice[1][1][0].getNorth(),tmp_dice.getSouth()) == false)continue;

			Puzzle new_puzzle;
			copyPuzzle(new_puzzle,puzzle);

			new_puzzle.dice[1][0][0].setPos(i);

			new_puzzle.num = puzzle.num+1;
			puzzle_calc(new_puzzle);
		}
		break;
	case 2:
		for(int i = 0; i <= 23; i++){
			Dice tmp_dice;
			tmp_dice.set(puzzle.dice[1][0][1]);
			tmp_dice.setPos(i);

			if(is_adj(puzzle.dice[1][0][0].getEast(),tmp_dice.getWest()) == false)continue;

			Puzzle new_puzzle;
			copyPuzzle(new_puzzle,puzzle);

			new_puzzle.dice[1][0][1].setPos(i);

			new_puzzle.num = puzzle.num+1;
			puzzle_calc(new_puzzle);
		}
		break;
	case 3:
		for(int i = 0; i <= 23; i++){
			Dice tmp_dice;
			tmp_dice.set(puzzle.dice[1][1][1]);
			tmp_dice.setPos(i);

			if(is_adj(puzzle.dice[1][0][1].getSouth(),tmp_dice.getNorth()) == false ||
					is_adj(puzzle.dice[1][1][0].getEast(),tmp_dice.getWest()) == false)continue;

			Puzzle new_puzzle;
			copyPuzzle(new_puzzle,puzzle);

			new_puzzle.dice[1][1][1].setPos(i);

			new_puzzle.num = puzzle.num+1;
			puzzle_calc(new_puzzle);
		}
		break;
	case 4:
		for(int i = 0; i <= 23; i++){

			Dice tmp_dice;
			tmp_dice.set(puzzle.dice[0][1][0]);
			tmp_dice.setPos(i);

			if(is_adj(puzzle.dice[1][1][0].getBottom(),tmp_dice.getTop()) == false)continue;

			Puzzle new_puzzle;
			copyPuzzle(new_puzzle,puzzle);

			new_puzzle.dice[0][1][0].setPos(i);

			new_puzzle.num = puzzle.num+1;
			puzzle_calc(new_puzzle);
		}
		break;
	case 5:
		for(int i = 0; i <= 23; i++){

			Dice tmp_dice;
			tmp_dice.set(puzzle.dice[0][0][0]);
			tmp_dice.setPos(i);

			if(is_adj(puzzle.dice[1][0][0].getBottom(),tmp_dice.getTop()) == false ||
					is_adj(puzzle.dice[0][1][0].getNorth(),tmp_dice.getSouth()) == false)continue;

			Puzzle new_puzzle;
			copyPuzzle(new_puzzle,puzzle);

			new_puzzle.dice[0][0][0].setPos(i);

			new_puzzle.num = puzzle.num+1;
			puzzle_calc(new_puzzle);
		}
		break;
	case 6:
		for(int i = 0; i <= 23; i++){

			Dice tmp_dice;
			tmp_dice.set(puzzle.dice[0][0][1]);
			tmp_dice.setPos(i);

			if(is_adj(puzzle.dice[1][0][1].getBottom(),tmp_dice.getTop()) == false ||
					is_adj(puzzle.dice[0][0][0].getEast(),tmp_dice.getWest()) == false)continue;

			Puzzle new_puzzle;
			copyPuzzle(new_puzzle,puzzle);

			new_puzzle.dice[0][0][1].setPos(i);

			new_puzzle.num = puzzle.num+1;
			puzzle_calc(new_puzzle);
		}
		break;
	case 7:
		for(int i = 0; i <= 23; i++){

			Dice tmp_dice;
			tmp_dice.set(puzzle.dice[0][1][1]);
			tmp_dice.setPos(i);

			if(is_adj(puzzle.dice[1][1][1].getBottom(),tmp_dice.getTop()) == false ||
					is_adj(puzzle.dice[0][1][0].getEast(),tmp_dice.getWest()) == false ||
					is_adj(puzzle.dice[0][0][1].getSouth(),tmp_dice.getNorth()) == false)continue;

			Puzzle new_puzzle;
			copyPuzzle(new_puzzle,puzzle);

			new_puzzle.dice[0][1][1].setPos(i);

			new_puzzle.num = puzzle.num+1;
			puzzle_calc(new_puzzle);
		}
		break;
	}
}

void func(){

	for(int i = 1; i <= 7; i++){
		scanf("%s",buf[i]);
	}

	clearFLG = false;
	int calc_index = 0;

	while(clearFLG == false && calc_index < 5040){

		Puzzle new_puzzle;
		new_puzzle.dice[1][1][0].setFirst(buf[0][0],buf[0][1],buf[0][2],buf[0][3],buf[0][4],buf[0][5]); //?????????S1?????????(1,1,0)????¨????

		for(int i = 0; i < 7; i++){

			int num = calc_array[calc_index][i];

			switch(i){
			case 0:
				new_puzzle.dice[1][0][0].setFirst(buf[num][0],buf[num][1],buf[num][2],buf[num][3],buf[num][4],buf[num][5]);
				break;
			case 1:
				new_puzzle.dice[1][0][1].setFirst(buf[num][0],buf[num][1],buf[num][2],buf[num][3],buf[num][4],buf[num][5]);
				break;
			case 2:
				new_puzzle.dice[1][1][1].setFirst(buf[num][0],buf[num][1],buf[num][2],buf[num][3],buf[num][4],buf[num][5]);
				break;
			case 3:
				new_puzzle.dice[0][1][0].setFirst(buf[num][0],buf[num][1],buf[num][2],buf[num][3],buf[num][4],buf[num][5]);
				break;
			case 4:
				new_puzzle.dice[0][0][0].setFirst(buf[num][0],buf[num][1],buf[num][2],buf[num][3],buf[num][4],buf[num][5]);
				break;
			case 5:
				new_puzzle.dice[0][0][1].setFirst(buf[num][0],buf[num][1],buf[num][2],buf[num][3],buf[num][4],buf[num][5]);
				break;
			case 6:
				new_puzzle.dice[0][1][1].setFirst(buf[num][0],buf[num][1],buf[num][2],buf[num][3],buf[num][4],buf[num][5]);
				break;
			}
		}

		for(int i = 0; i <= 23; i++){
			Puzzle next_puzzle;
			copyPuzzle(next_puzzle,new_puzzle);
			next_puzzle.dice[1][1][0].setPos(i);
			next_puzzle.num = 1;
			puzzle_calc(next_puzzle);
		}

		calc_index++;
	}

	if(clearFLG){
		printf("YES\n");
	}else{
		printf("NO\n");
	}
}


void recursive(bool check[8],int jyunretsu[7],int num){

	if(num == 7){
		for(int k = 0; k < 7; k++){
			calc_array[array_index][k] = jyunretsu[k];
		}
		array_index++;
		return;
	}

	for(int i = 1; i <= 7; i++){
		if(check[i] == false){
			int next_jyunretsu[7];
			for(int k = 0; k < num; k++)next_jyunretsu[k] = jyunretsu[k];
			next_jyunretsu[num] = i;

			bool next_check[8];
			for(int k = 1; k <= 7; k++)next_check[k] = check[k];
			next_check[i] = true;

			recursive(next_check,next_jyunretsu,num+1);
		}
	}
}

int main(){

	bool check[8];
	for(int i = 1; i <= 7; i++){
		check[i] = false;
	}
	int jyunretsu[7];

	recursive(check,jyunretsu,0);

	while(true){
		scanf("%s",buf[0]);
		if(buf[0][0] == '0')break;

		func();
	}
	return 0;
}