// Slower C++ solution:
#include<bits/stdc++.h>

using namespace std;

typedef long long ll;

#define rep(i, n) for(int i = 0; i < (n); i++)

#define rep1(i, n) for(int i = 1; i <= (n); i++)

#define co(x) cout << (x) << "\n"

#define cosp(x) cout << (x) << " "

#define ce(x) cerr << (x) << "\n"

#define cesp(x) cerr << (x) << " "

#define pb push_back

#define mp make_pair

#define Would

#define you

#define please



typedef tuple<int, int, int, int> TP;

TP narabi(int a, int b, int c, int d) {

	TP kari[4];

	kari[0] = tie(a, b, c, d);

	kari[1] = tie(b, c, d, a);

	kari[2] = tie(c, d, a, b);

	kari[3] = tie(d, a, b, c);

	sort(kari, kari + 4);

	return kari[0];

}



int main() {

	cin.tie(0);

	ios::sync_with_stdio(false);





	int N;

	cin >> N;

	TP C[400];

	map<TP, int> MP;

	rep(i, N) {

		int a, b, c, d;

		cin >> a >> b >> c >> d;

		C[i] = narabi(a, b, c, d);

		MP[C[i]]++;

	}



	ll kotae = 0;

	rep(i, N) rep(j, N) if (i != j) {

		MP[C[i]]--;

		MP[C[j]]--;



		int a, b, c, d, e, f, g, h;

		a = get<0>(C[i]);

		b = get<1>(C[i]);

		c = get<2>(C[i]);

		d = get<3>(C[i]);

		e = get<0>(C[j]);

		f = get<1>(C[j]);

		g = get<2>(C[j]);

		h = get<3>(C[j]);



		rep(x, 4) {

			TP D[4];

			D[0] = narabi(a, d, f, e);

			D[1] = narabi(a, e, h, b);

			D[2] = narabi(b, h, g, c);

			D[3] = narabi(c, g, f, d);

			ll kari = 1;

			rep(k, 4) {

				kari *= MP[D[k]]--;

				if (get<0>(D[k]) == get<2>(D[k]) && get<1>(D[k]) == get<3>(D[k])) {

					kari *= 2;

					if (get<1>(D[k]) == get<2>(D[k])) kari *= 2;

				}

				if (kari < 0) kari = 0;

			}

			rep(k, 4) MP[D[k]]++;

			kotae += kari;



			int tmp = e;

			e = f;

			f = g;

			g = h;

			h = tmp;

		}



		MP[C[i]]++;

		MP[C[j]]++;

	}

	co(kotae / 6);



	Would you please return 0;

}

// Faster C++ solution for the same problem (measured speedup: 1.125915105839458x):
#include<bits/stdc++.h>

using namespace std;

typedef long long ll;

#define rep(i, n) for(int i = 0; i < (n); i++)

#define rep1(i, n) for(int i = 1; i <= (n); i++)

#define co(x) cout << (x) << "\n"

#define cosp(x) cout << (x) << " "

#define ce(x) cerr << (x) << "\n"

#define cesp(x) cerr << (x) << " "

#define pb push_back

#define mp make_pair

#define Would

#define you

#define please



typedef tuple<int, int, int, int> TP;

TP narabi(int a, int b, int c, int d) {

	TP kari[4];

	kari[0] = tie(a, b, c, d);

	kari[1] = tie(b, c, d, a);

	kari[2] = tie(c, d, a, b);

	kari[3] = tie(d, a, b, c);

	return *min_element(kari, kari + 4);

}



int main() {

	cin.tie(0);

	ios::sync_with_stdio(false);





	int N;

	cin >> N;

	TP C[400];

	int cnum[1000] = {};

	rep(i, N) {

		int a, b, c, d;

		cin >> a >> b >> c >> d;

		C[i] = narabi(a, b, c, d);

		cnum[a]++;

		cnum[b]++;

		cnum[c]++;

		cnum[d]++;

	}



	sort(C, C + N);

	int kazu[400] = {};

	rep(i, N) {

		int k = i;

		while (k + 1 < N && C[k + 1] == C[i]) k++;

		kazu[i] = k - i + 1;

		i = k;

	}



	ll kotae = 0;

	rep(i, N) {

		int inum = lower_bound(C, C + N, C[i]) - C;

		kazu[inum]--;

		rep(j, N) if (i != j) {



			int a, b, c, d, e, f, g, h;

			a = get<0>(C[i]);

			b = get<1>(C[i]);

			c = get<2>(C[i]);

			d = get<3>(C[i]);

			e = get<0>(C[j]);

			f = get<1>(C[j]);

			g = get<2>(C[j]);

			h = get<3>(C[j]);

			if (cnum[a] <= 2) continue;

			if (cnum[b] <= 2) continue;

			if (cnum[c] <= 2) continue;

			if (cnum[d] <= 2) continue;

			if (cnum[e] <= 2) continue;

			if (cnum[f] <= 2) continue;

			if (cnum[g] <= 2) continue;

			if (cnum[h] <= 2) continue;



			int bairitu = kazu[inum] + 1;

			int jnum = lower_bound(C, C + N, C[j]) - C;

			bairitu *= kazu[jnum]--;



			rep(x, 4) {

				TP D[4];

				D[0] = narabi(a, d, f, e);

				D[1] = narabi(a, e, h, b);

				D[2] = narabi(b, h, g, c);

				D[3] = narabi(c, g, f, d);

				TP* itr[4];

				rep(k, 4) itr[k] = lower_bound(C, C + N, D[k]);

				ll kari = bairitu;

				rep(k, 4) {

					if (itr[k] != C + N && *(itr[k]) == D[k]) {

						kari *= kazu[itr[k] - C]--;

						if (get<0>(D[k]) == get<2>(D[k]) && get<1>(D[k]) == get<3>(D[k])) {

							kari *= 2;

							if (get<1>(D[k]) == get<2>(D[k])) kari *= 2;

						}

					}

					else {

						kari = 0;

						break;

					}

				}

				rep(k, 4) {

					if (itr[k] != C + N && *itr[k] == D[k]) {

						kazu[itr[k] - C]++;

					}

					else break;

				}

				kotae += kari;



				int tmp = e;

				e = f;

				f = g;

				g = h;

				h = tmp;

			}

			j += kazu[jnum]++;

		}

		i += kazu[inum]++;

	}

	co(kotae / 6);



	Would you please return 0;

}