#include <bits/stdc++.h>
using namespace std;

#define MAX 402

struct st{
	int a;
	int b;
	int c;
	int d;
	int id;
	st(int a_, int b_, int c_, int d_,int id_){
		a = a_;
		b = b_;
		c = c_;
		d = d_;
		id = id_;
	}
	void flip(){
		int A = a;
		a = b;
		b = c;
		c = d;
		d = A;
	}
	long long int outt(){
		long long int R = LLONG_MAX;
		for (int i = 0; i < 4; i++){
			long long int f = 1000 + a;
			f *= 1000;
			f += b;
			f *= 1000;
			f += c;
			f *= 1000;
			f += d;
			R = min(R, f);
			flip();
		}
		return R;
	}
	int get_circle(){
		if (a == b&&b == c&&c == d){
			return 4;
		}
		if (a == c&&b==d){
			return 2;
		}
		return 1;
	}
};

int n;

vector<st> v;

vector<st> vv;

bool same(st &a, st &b){
	return (a.a == b.a) && (a.b == b.b) && (a.c == b.c) && (a.d == b.d);
}


map<pair<long long int,pair<long long int,pair<long long int,long long int> > > , long long int> mp;

pair<long long int, pair<long long int, pair<long long int, long long int> > > MAKE2(long long int a=-1, long long int b=-1, long long int c=-1, long long int d=-1){
	pair<long long int, pair<long long int, pair<long long int, long long int> > > r;
	r.first = a;
	r.second.first = b;
	r.second.second.first = c;
	r.second.second.second = d;
	return r;
}
void ins(st a,int c){
	vector<long long int> V;
	for (int i = 0; i < 4; i++){
		V.push_back(a.outt());
		a.flip();
	}
	for (int i = 0; i < V.size(); i++){
		mp[MAKE2(V[i])]+=c;
		for (int j = 0; j < V.size(); j++){
			mp[MAKE2(V[i],V[j])]+=c;
			for (int k = 0; k < V.size(); k++){
				mp[MAKE2(V[i],V[j],V[k])]+=c;
				for (int kk = 0; kk < V.size(); kk++){
					mp[MAKE2(V[i],V[j],V[k],V[kk])]+=c;
				}
			}
		}
	}
}
map<long long int, int> mpp[5];

int main(){
	cin >> n;
	for (int i = 0; i < n; i++){
		int a, b, c, d;
		scanf("%d%d%d%d", &a, &b, &c, &d);
		v.push_back(st(a, b, c, d,i));
		st tmp = v.back();
		for (int j = 0; j < 4; j++){
			vv.push_back(tmp);
			tmp.flip();
		}
		//ins(tmp, 1);
		mpp[tmp.get_circle()][tmp.outt()]++;
	}
	long long int ans = 0;
	for (int i = 0; i < v.size(); i++){
		mpp[v[i].get_circle()][v[i].outt()]--;
		for (int j = 0; j < vv.size(); j++){
			if (v[i].id >= vv[j].id)continue;
				int used_id_up = v[i].id;
				int used_id_dw = vv[j].id;
				mpp[v[used_id_dw].get_circle()][v[used_id_dw].outt()]--;
				//ins(v[used_id_dw], -1);
				int ar[] = { v[i].d, v[i].c, v[i].b, v[i].a };
				int ar2[] = { vv[j].a, vv[j].b, vv[j].c, vv[j].d };
				long long int cnt = 1;
				vector<long long int> V;
				for (int jj = 0; jj < 4; jj++){
					 st f(ar[jj], ar[(jj + 1) % 4], ar2[(jj + 1) % 4], ar2[jj], 1);
					 int cy = f.get_circle();
					 long long int id = f.outt();
					 if (mpp[cy].count(id)){
						 cnt *=(long long int)(cy)*mpp[cy][id];
						 mpp[cy][id]--;
					 }
					 else{
						 cnt = 0;
					 }
				}
				for (int jj = 0; jj < 4; jj++){
					st f(ar[jj], ar[(jj + 1) % 4], ar2[(jj + 1) % 4], ar2[jj], 1);
					int cy = f.get_circle();
					long long int id = f.outt();
					if (mpp[cy].count(id)){
						mpp[cy][id]++;
					}
				}
				/*for (int ii = 0; ii < (1 << 4); ii++){
					long long int way = 1;
					long long int DD[] = { -1, -1, -1, -1 };
					int DD_siz = 0;
					for (int jj = 0; jj < 4; jj++){
						if ((ii>> jj) & 1){
							DD[DD_siz]=(st(ar[jj], ar[(jj + 1) % 4], ar2[(jj + 1) % 4], ar2[jj], 1).outt());
							DD_siz++;
						}
						else{
							way *= mp[MAKE2(st(ar[jj], ar[(jj + 1) % 4], ar2[(jj + 1) % 4], ar2[jj], 1).outt())];
						}
					}
					if (DD_siz == 1)continue;
					if (DD_siz)way *= mp[MAKE2(DD[0],DD[1],DD[2],DD[3])];
					if (way){
						puts("H");
					}
					if (ii == 0){
						cnt += way;
						continue;
					}
					if (DD_siz % 2==0){
						cnt -= way;
					}
					else{
						cnt += way;
					}
				}*/
				ans += cnt;
				//ins(v[used_id_dw], 1);
				mpp[v[used_id_dw].get_circle()][v[used_id_dw].outt()]++;
		}
	}
	printf("%lld\n", ans);
	return 0;
}

Measured memory_bytes: 384