/*
明知这是一场意外，你要不要来
明知这是一场重伤害，你会不会来
当疯狂慢慢从爱情离开，还有什么你值得感慨
如果风景早已都不存在，我想我谁都不爱
——薛之谦《意外》
*/
#include <bits/stdc++.h>
using namespace std;

#define fo(i,s,t) for(int i = s; i <= t; ++ i)
#define fd(i,s,t) for(int i = s; i >= t; -- i)
#define bf(i,s) for(int i = head[s]; i; i = e[i].next)
#define mp make_pair
#define fi first
#define se second
#define pii pair<int,int>
#define pb push_back
#define VI vector<int>
#define sf scanf
#define pf printf
#define fp freopen
#define SZ(x) ((int)(x).size())
// #define MPS
typedef long long ll;
typedef double db;
typedef unsigned long long ull;
const int inf = 1<<30;
const ll INF = 1ll<<60;
const db Inf = 1e20;
const db eps = 1e-9;

void gmax(int &a,int b){a = (a > b ? a : b);}
void gmin(int &a,int b){a = (a < b ? a : b);}

const int maxn = 405;

map<ll,int> Cnt;
int n;
VI C[maxn];
ll Ans;

ll f(int a,int b,int c,int d) // hash function
{
	return (((a*1000ll + b)*1000) + c)*1000 + d;
}
VI fmr(VI A) // find the minimal representation for a squre
{
	VI ret = A;
	fo(d,1,3)
	{
		fo(i,0,3) 
			if(ret[i] < A[(i+d)%4]) break;
			else if(ret[i] > A[(i+d)%4]) 
			{
				fo(j,0,3) ret[j] = A[(j+d)%4];
				break;
			}
	}
	return ret;
}
int main()
{
	#ifdef MPS
		fp("arc062e.in","r",stdin);
		fp("arc062e.out","w",stdout);
	#endif
	VI tmp;
	sf("%d",&n);
	fo(i,1,n) 
	{
		fo(j,0,3) {int x; sf("%d",&x); C[i].pb(x);}
		tmp = fmr(C[i]);
		Cnt[f(tmp[0],tmp[1],tmp[2],tmp[3])] ++;
	}
	fo(i,1,n)
	{
		tmp.clear(); fo(j,0,3) tmp.pb(C[i][j]); tmp = fmr(tmp);
		Cnt[f(tmp[0],tmp[1],tmp[2],tmp[3])] --;
		fo(j,i+1,n)
		{
			tmp.clear(); fo(k,0,3) tmp.pb(C[j][k]); tmp = fmr(tmp);
			Cnt[f(tmp[0],tmp[1],tmp[2],tmp[3])] --;
			fo(d1,0,3)
			{
				VI tmp;
				vector<ll> cube;
				tmp.clear(); 
				tmp.pb(C[j][1]); tmp.pb(C[i][(4-d1)%4]); tmp.pb(C[i][(3-d1+4)%4]); tmp.pb(C[j][2]);
				tmp = fmr(tmp);
				cube.pb(f(tmp[0],tmp[1],tmp[2],tmp[3]));

				tmp.clear(); 
				tmp.pb(C[j][1]); tmp.pb(C[j][0]); tmp.pb(C[i][(1-d1+4)%4]); tmp.pb(C[i][(4-d1)%4]);
				tmp = fmr(tmp);
				cube.pb(f(tmp[0],tmp[1],tmp[2],tmp[3]));

				tmp.clear(); 
				tmp.pb(C[i][(1-d1+4)%4]); tmp.pb(C[j][0]); tmp.pb(C[j][3]); tmp.pb(C[i][(2-d1+4)%4]);
				tmp = fmr(tmp);
				cube.pb(f(tmp[0],tmp[1],tmp[2],tmp[3]));

				tmp.clear(); 
				tmp.pb(C[j][3]); tmp.pb(C[j][2]); tmp.pb(C[i][(3-d1+4)%4]); tmp.pb(C[i][(2-d1+4)%4]);
				tmp = fmr(tmp);
				cube.pb(f(tmp[0],tmp[1],tmp[2],tmp[3]));

				sort(cube.begin(),cube.end());
				int s = 1; ll cur = 1;
				for(int i = 1; i <= 4; ++ i)
					if(i != 4 && cube[i] == cube[i-1]) {++ s; continue;}
					else
					{
						if(!Cnt.count(cube[i-1])) {cur = 0; break;} 
						int num = Cnt[cube[i-1]]; //we are calculating A(num, s) = num! / (num-s)!
						fo(i,num-s+1,num) cur *= i;
						int bonus = 1, a, b, c, d;
						ll x = cube[i-1];
						a = x/1000000000; x -= a*1000000000ll;
						b = x/1000000; x -= b*1000000ll;
						c = x/1000; x -= c*1000ll;
						d = x;
						if(a == d && b == a && c == b && d == c) ++ bonus;
						if(a == c && b == d && c == a && d == b) ++ bonus;
						if(a == b && b == c && c == d && d == a) ++ bonus;
						fo(i,1,s) cur *= bonus;
						s = 1;
					}
				Ans += cur;
			}
			tmp.clear(); fo(k,0,3) tmp.pb(C[j][k]); tmp = fmr(tmp);
			Cnt[f(tmp[0],tmp[1],tmp[2],tmp[3])] ++;
		}
		tmp.clear(); fo(j,0,3) tmp.pb(C[i][j]); tmp = fmr(tmp);
		Cnt[f(tmp[0],tmp[1],tmp[2],tmp[3])] ++;
	}
	pf("%lld\n",Ans/3);
	return 0;
}

Measured memory_bytes: 256