There are several colored cubes. All of them are of the same size but they may be colored differently. Each face of these cubes has a single color. Colors of distinct faces of a cube may or may not be the same.

Two cubes are said to be identically colored if some suitable rotations of one of the cubes give identical looks to both of the cubes. For example, two cubes shown in Figure 2 are identically colored. A set of cubes is said to be identically colored if every pair of them are identically colored.

A cube and its mirror image are not necessarily identically colored. For example, two cubes shown in Figure 3 are not identically colored.

You can make a given set of cubes identically colored by repainting some of the faces, whatever colors the faces may have. In Figure 4, repainting four faces makes the three cubes identically colored and repainting fewer faces will never do.

Your task is to write a program to calculate the minimum number of faces that needs to be repainted for a given set of cubes to become identically colored.



Input

The input is a sequence of datasets. A dataset consists of a header and a body appearing in this order. A header is a line containing one positive integer n and the body following it consists of n lines. You can assume that 1 ≤ n ≤ 4. Each line in a body contains six color names separated by a space. A color name consists of a word or words connected with a hyphen (-). A word consists of one or more lowercase letters. You can assume that a color name is at most 24-characters long including hyphens.

A dataset corresponds to a set of colored cubes. The integer n corresponds to the number of cubes. Each line of the body corresponds to a cube and describes the colors of its faces. Color names in a line is ordered in accordance with the numbering of faces shown in Figure 5. A line


color1 color2 color3 color4 color5 color6


corresponds to a cube colored as shown in Figure 6.

The end of the input is indicated by a line containing a single zero. It is not a dataset nor a part of a dataset.

<image>
<image>
<image>

Output

For each dataset, output a line containing the minimum number of faces that need to be repainted to make the set of cubes identically colored.

Example

Input

3
scarlet green blue yellow magenta cyan
blue pink green magenta cyan lemon
purple red blue yellow cyan green
2
red green blue yellow magenta cyan
cyan green blue yellow magenta red
2
red green gray gray magenta cyan
cyan green gray gray magenta red
2
red green blue yellow magenta cyan
magenta red blue yellow cyan green
3
red green blue yellow magenta cyan
cyan green blue yellow magenta red
magenta red blue yellow cyan green
3
blue green green green green blue
green blue blue green green green
green green green green green sea-green
3
red yellow red yellow red yellow
red red yellow yellow red yellow
red red red red red red
4
violet violet salmon salmon salmon salmon
violet salmon salmon salmon salmon violet
violet violet salmon salmon violet violet
violet violet violet violet salmon salmon
1
red green blue yellow magenta cyan
4
magenta pink red scarlet vermilion wine-red
aquamarine blue cyan indigo sky-blue turquoise-blue
blond cream chrome-yellow lemon olive yellow
chrome-green emerald-green green olive vilidian sky-blue
0


Output

4
2
0
0
2
3
4
4
0
16
#include <bits/stdc++.h>
#include <unordered_map>
using namespace std;

using VS = vector<string>;    using LL = long long;
using VI = vector<int>;       using VVI = vector<VI>;
using PII = pair<int, int>;   using PLL = pair<LL, LL>;
using VL = vector<LL>;        using VVL = vector<VL>;

#define ALL(a)  begin((a)),end((a))
#define RALL(a) (a).rbegin(), (a).rend()
#define SZ(a) int((a).size())
#define SORT(c) sort(ALL((c)))
#define RSORT(c) sort(RALL((c)))
#define UNIQ(c) (c).erase(unique(ALL((c))), end((c)))
#define FOR(i, s, e) for (int(i) = (s); (i) < (e); (i)++)
#define FORR(i, s, e) for (int(i) = (s); (i) > (e); (i)--)
#define debug(x) cerr << #x << ": " << x << endl
const int INF = 1e9;                          const LL LINF = 1e16;
int DX[8] = { 0, 0, 1, -1, 1, 1, -1, -1 };    int DY[8] = { 1, -1, 0, 0, 1, -1, 1, -1 };

/* -----  2018/06/20  Problem: AOJ 2703 / Link: http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=2703  ----- */
/* ------問題------



-----問題ここまで----- */
/* -----解説等-----



----解説ここまで---- */


using uLL = unsigned long long;

const uLL MOD = 1e9;
//BEGIN CUT HERE
struct Dice {
	int s[6];
	void roll(char c) {
		//the view from above
		// N
		//W E
		// S
		//s[0]:top
		//s[1]:south
		//s[2]:east
		//s[3]:west
		//s[4]:north
		//s[5]:bottom
		int b;
		if (c == 'E') {
			b = s[0];
			s[0] = s[3];
			s[3] = s[5];
			s[5] = s[2];
			s[2] = b;
		}
		if (c == 'W') {
			b = s[0];
			s[0] = s[2];
			s[2] = s[5];
			s[5] = s[3];
			s[3] = b;
		}
		if (c == 'N') {
			b = s[0];
			s[0] = s[1];
			s[1] = s[5];
			s[5] = s[4];
			s[4] = b;
		}
		if (c == 'S') {
			b = s[0];
			s[0] = s[4];
			s[4] = s[5];
			s[5] = s[1];
			s[1] = b;
		}

		// migi neji 
		if (c == 'R') {
			b = s[1];
			s[1] = s[2];
			s[2] = s[4];
			s[4] = s[3];
			s[3] = b;
		}

		if (c == 'L') {
			b = s[1];
			s[1] = s[3];
			s[3] = s[4];
			s[4] = s[2];
			s[2] = b;
		}

	}
	int top() {
		return s[0];
	}
	int bottom() {
		return s[5];
	}
	uLL hash() {
		uLL res = 1;
		for (int i = 0; i < 6; i++) res = res * (MOD)+s[i];
		return res;
	}
	void print() {
		cout << "Dice num: ";
		FOR(i, 0, 6) {
			cout << s[i] << " ";
		}
		cout << "Hash: " << this->hash() << endl;
		cout << endl;
	}
};
vector<Dice> makeDices(Dice d) {
	vector<Dice> res;
	for (int i = 0; i < 6; i++) {
		Dice t(d);
		if (i == 1) t.roll('N');
		if (i == 2) t.roll('S');
		if (i == 3) t.roll('S'), t.roll('S');
		if (i == 4) t.roll('L');
		if (i == 5) t.roll('R');
		for (int k = 0; k < 4; k++) {
			res.push_back(t);
			t.roll('E');
		}
	}
	return res;
}
//END CUT HERE

void solve_AOJ_ITP1_11_A() {
	int N = 6;
	Dice D;
	FOR(i, 0, N) {
		int val; cin >> val;
		D.s[i] = val;
	}
	string s; cin >> s;
	FOR(i, 0, SZ(s)) {
		D.roll(s[i]);
	}
	cout << D.top() << endl;
}

void solve_AOJ_ITP1_11_B() {
	Dice D;
	int N = 6;
	FOR(i, 0, N) {
		int val; cin >> val;
		D.s[i] = val;
	}
	vector<Dice> dices = makeDices(D);
	int Q; cin >> Q;
	FOR(i, 0, Q) {
		int TOP, FRONT;
		cin >> TOP >> FRONT;
		FOR(i, 0, SZ(dices)) { //24個
			if (dices[i].top() == TOP && dices[i].s[1] == FRONT) {
				cout << dices[i].s[2] << endl;
				break;
			}
		}
	}
}

void solve_AOJ_ITP1_11_C() {
	Dice d[2];
	FOR(k, 0, 2) {
		FOR(i, 0, 6) {
			int val; cin >> val;
			d[k].s[i] = val;
		}
	}
	uLL hashval = d[0].hash();
	vector<Dice>dices = makeDices(d[1]);
	FOR(i, 0, SZ(dices)) {
		if (hashval == dices[i].hash()) {
			cout << "Yes" << endl;
			return;
		}
	}
	cout << "No" << endl;
}
void solve_AOJ_ITP1_11_D() {
	int N; cin >> N;
	vector<Dice>d(N);
	FOR(k, 0, N) {
		FOR(i, 0, 6) {
			int val; cin >> val;
			d[k].s[i] = val;
		}
	}
	set<uLL>Se;
	Se.insert(d[0].hash());
	FOR(i, 1, N) {
		vector<Dice>dices = makeDices(d[i]);
		int flag = 0;
		FOR(j, 0, SZ(dices)) {
			flag |= (Se.count(dices[j].hash()));
		}
		if (flag) {
			cout << "No" << endl;
			return;
		}
		Se.insert(dices[i].hash());

	}
	cout << "Yes" << endl;
}

void solve_AOJ_0502() {
	int Q;
	while (cin >> Q, Q) {
		Dice d; FOR(i, 0, 6)d.s[i] = i + 1;
		int ans = 1;
		FOR(kim, 0, Q) {
			string s; cin >> s;
			d.roll(s[0]);
			ans += d.top();
		}
		cout << ans << endl;
	}


}

using PII = pair<int, int>;
map<char, char>changeC;
inline  int  mhash(const PII &a) {
	return (a.first + 1200) * 2400 + a.second + 1200;
}
void solve_AOJ_2703() { // えーサイコロ関係なくないですか？ないですね
	const string ORIG = "EWNS";
	const string TO = "RLBF";
	FOR(i, 0, 4) {
		changeC[TO[i]] = ORIG[i];
	}
	int N;
	while (cin >> N, N) {
		vector<map<PII, int>>Map(N);
		int x, y;
		Dice dice;
		FOR(i, 0, N) {
			cin >> x >> y;
			cin >> dice.s[3] >> dice.s[2] >> dice.s[1] >> dice.s[4] >> dice.s[5] >> dice.s[0];
			string s; cin >> s;
			Map[i][PII(y, x)] = dice.bottom();
			FOR(j, 0, SZ(s)) {
				dice.roll(changeC[s[j]]);
				// R,L,B,F
				if (s[j] == 'R')x++;
				if (s[j] == 'L')x--;
				if (s[j] == 'B')y++;
				if (s[j] == 'F')y--;
				// y x の移動
				Map[i][PII(y, x)] = dice.bottom();
			}
		}

		vector<int>bitdp(1 << N, 0);
		FOR(state, 0, 1 << N) {
			unordered_map<int, bool>used; // orderedだと結構遅かった
			FOR(i, 0, N) {
				if (state & 1 << i) {
					for (auto it : Map[i]) {
						used[mhash(it.first)] = 1;
					}
				}
			}
			// 記録した
			FOR(i, 0, N) {
				if (state & 1 << i)continue;
				int addv = 0;

				for (auto it : Map[i]) {
					if (!used.count(mhash(it.first))) {
						addv += it.second;
					}
				}
				bitdp[state | (1 << i)] = max(bitdp[state | (1 << i)], bitdp[state] + addv);
			}
		}
		cout << bitdp[(1 << N) - 1] << endl;

	}
}

void solve_AOJ_1181() {
	int N;
	Dice BaseDi;
	FOR(i, 0, 6)BaseDi.s[i] = i + 1;
	vector<Dice>dices = makeDices(BaseDi);
	while (cin >> N, N) {
		VVI masu(210, VI(210, 0));
		vector<VVI>valset(210, VVI(210, VI()));
		FOR(okaduki, 0, N) {
			int tp, fr; cin >> tp >> fr;
			int X = 100, Y = 100;
			Dice d;
			FOR(i, 0, SZ(dices)) {
				if (dices[i].top() == tp&&dices[i].s[1] == fr) {
					d = dices[i];
					break;
				}
			}
			while (1) {
				masu[Y][X]++;
				// 落ちる方向を決める
				// 大きな方に転がり落ちる
				int dy[] = { -1, 1, 0, 0, -1, };
				int dx[] = { -1, 0, 1, -1, 0, };
				int dir = -1;
				FOR(num, 4, 6 + 1) {
					if (d.top() != num && d.bottom() != num) { //面があれ
						FOR(i, 1, 4 + 1) {
							if (d.s[i] == num) {
								if (masu[Y][X] > masu[Y + dy[i]][X + dx[i]] + 1) {
									dir = i;
								}
							}
						}
					}
				}
				if (dir == -1) {
					valset[Y][X].push_back(d.top());
					break;
				}
				masu[Y][X]--;
				string TO = "$SEWN";
				Y += dy[dir]; X += dx[dir];
				d.roll(TO[dir]);
			}
		}
		VI a(7, 0);
		FOR(i, 0, 210) {
			FOR(j, 0, 210) {
				if (!SZ(valset[i][j]))continue;
				int val = valset[i][j].back();
				a[val]++;
			}
		}
		FOR(i, 1, 6 + 1) {
			cout << a[i] << " \n"[i == 6];
		}

	}

}

vector<Dice>dices;
int tops[3][3], fronts[3][3];
vector<int> ans;
Dice putdice[3][3][3];
void dfs(int state) {
	if (state == 27) {
		int ret = 0;
		FOR(i, 0, 3) {// 右の右をとる s[2]
			FOR(j, 0, 3) {
				ret += putdice[i][2][j].s[2];
			}
		}

		ans.push_back(ret);
	}
	else {
		int X = (state / 3) % 3;
		int Y = state % 3;
		int Z = state / 9;
		FOR(i, 0, 24) { // put dices to putdice
			// ダメなもの top .front がちゃう
			if (Z == 0 && tops[X][Y] && tops[X][Y] != dices[i].top())continue;
			if (X == 2 && fronts[Z][Y] && fronts[Z][Y] != dices[i].s[1])continue;
			// ダメなもの 7じゃない
			if (X&& putdice[X - 1][Y][Z].s[4] + dices[i].s[1] != 7)continue; // 奥
			if (Y&& putdice[X][Y - 1][Z].s[2] + dices[i].s[3] != 7)continue; // 左
			if (Z&& putdice[X][Y][Z - 1].s[5] + dices[i].s[0] != 7)continue; // 上

			putdice[X][Y][Z] = dices[i];
			dfs(state + 1);
		}


	}

}


// 24^27なきもちになるけど前処理すればだいたい決まるので解析しなくても投げる気持ちが固まる
// パラメータの管理壊れる
void solve_AOJ_1253() {
	// 条件を見たすように配置したときの右面の種類
	Dice Base;
	FOR(i, 0, 6)Base.s[i] = i + 1;
	dices = makeDices(Base);

	int Case; cin >> Case;
	FOR(kyo, 0, Case) {
		FOR(i, 0, 3)FOR(j, 0, 3)cin >> tops[i][j];
		FOR(i, 0, 3)FOR(j, 0, 3)cin >> fronts[i][j];
		dfs(0);
		SORT(ans); UNIQ(ans);
		FOR(i, 0, SZ(ans)) {
			cout << ans[i] << " \n"[i == SZ(ans) - 1];
		}
		if (SZ(ans) == 0)cout << 0 << endl;
		ans.clear();
	}




}
Dice resDice[4];
vector<Dice>diceState[4];

void Dfs(int state, const int N, int& ans) {
	if (N == state) {
		int res = 0;
		// あるおきかたについて
		// 一緒になるように最小の塗り分けをする

		FOR(i, 0, 6) { //ある面について
			map<int, int>cnt;
			FOR(k, 0, N) {
				cnt[resDice[k].s[i]]++;
			}
			int mx = 0;
			for (auto it : cnt) {
				mx = max(mx, it.second); // 重複maxが保存すべきもの
			}
			res += N - mx;
		}




		ans = min(ans, res);
		return;
	}
	FOR(i, 0, 24) {
		resDice[state] = diceState[state][i];
		Dfs(state + 1, N, ans);
	}
}

void solve_AOJ_1259() {
	// N diff checkする 全探索 同じにするための塗り替えを最小にする
	int N;
	while (cin >> N, N) {
		if (N == 1) {
			string s; FOR(i, 0, 6)cin >> s;

			cout << 0 << endl;
		}
		else {

			vector<Dice>baseDice(N);
			FOR(i, 0, 4)diceState[i].clear();
			map<string, int>sHash;
			int hp = 1;
			FOR(i, 0, N) {
				FOR(j, 0, 6) {
					string s;  cin >> s;
					if (sHash.find(s) == sHash.end())sHash[s] = hp++;
					baseDice[i].s[j] = sHash[s];
				}
			}
			// 値をいれたので24^(N-1)全部つくる
			FOR(i, 0, N) {
				diceState[i] = makeDices(baseDice[i]);
			}
			int ans = INF;
			resDice[0] = baseDice[0];
			Dfs(1, N, ans);
			cout << ans << endl;
		}
	}


}
 

// R S Vは解けそう

int main() {
	cin.tie(0);
	ios_base::sync_with_stdio(false);

	//solve_AOJ_ITP1_11_A();
	//solve_AOJ_ITP1_11_B();
	//solve_AOJ_ITP1_11_C();
	//solve_AOJ_ITP1_11_D();
	//solve_AOJ_0502();

	//solve_AOJ_1181();
	//solve_AOJ_2703();
	//solve_AOJ_1253();
	solve_AOJ_1259();

	return 0;
}
//
