#include<bits/stdc++.h>
#define LL long long
#define ull unsigned long long
#define ULL ull
#define mp make_pair
#define pii pair<int,int>
#define piii pair<int, pii >
#define pll pair <ll,ll>
#define pb push_back
#define big 20160116
#define INF 2147483647
#define pq priority_queue
#define rank rk124232
#define y1 y20160116
#define y0 y20160110
#define _ 0
using namespace std;
#ifndef MY
	#define putchar IO::_putchar
	#define getchar IO::_getchar
#endif
namespace IO
{
    const int sz=1<<15;
    char inbuf[sz],outbuf[sz];
    char *pinbuf=inbuf+sz;
    char *poutbuf=outbuf;
    inline char _getchar()
    {
        if (pinbuf==inbuf+sz)fread(inbuf,1,sz,stdin),pinbuf=inbuf;
        return *(pinbuf++);
    }
    inline void _putchar(char x)
    {
        if (poutbuf==outbuf+sz)fwrite(outbuf,1,sz,stdout),poutbuf=outbuf;
        *(poutbuf++)=x;
    }
    inline void flush()
    {
        if (poutbuf!=outbuf)fwrite(outbuf,1,poutbuf-outbuf,stdout),poutbuf=outbuf;
    }
}
inline int read()
{
    int x=0,p=1;
	char c=getchar();
    while (c<'0' || c>'9'){
    	if (c=='-') p=-1;
    	c=getchar();
	}
    while (c>='0' && c<='9') x=x*10+c-48,c=getchar();
    return x*p;
}
namespace Mymath{
	LL qp(LL x,LL p,LL mod){
		LL ans=1;
		while (p){
			if (p&1) ans=ans*x%mod;
			x=x*x%mod;
			p>>=1;
		}
		return ans;
	}
	LL inv(LL x,LL mod){
		return qp(x,mod-2,mod);
	}
	LL C(LL N,LL K,LL fact[],LL mod){
		return fact[N]*inv(fact[K],mod)%mod*inv(fact[N-K],mod)%mod;
	}
	template <typename Tp> Tp gcd(Tp A,Tp B){
		if (B==0) return A;
		return gcd(B,A%B);
	}
	template <typename Tp> Tp lcm(Tp A,Tp B){
		return A*B/gcd(A,B);
	}
};
namespace fwt{
	using namespace Mymath;
	void FWT(int a[],int n,LL mod)
	{
	    for(int d=1;d<n;d<<=1)
	        for(int m=d<<1,i=0;i<n;i+=m)
	            for(int j=0;j<d;j++)
	            {
	                int x=a[i+j],y=a[i+j+d];
	                a[i+j]=(x+y)%mod,a[i+j+d]=(x-y+mod)%mod;
	                //xor:a[i+j]=x+y,a[i+j+d]=x-y;
	                //and:a[i+j]=x+y;
	                //or:a[i+j+d]=x+y;
	            }
	}

	void UFWT(int a[],int n,LL mod)
	{
		LL rev=inv(2,mod);
	    for(int d=1;d<n;d<<=1)
	        for(int m=d<<1,i=0;i<n;i+=m)
	            for(int j=0;j<d;j++)
	            {
	                int x=a[i+j],y=a[i+j+d];
	                a[i+j]=1LL*(x+y)*rev%mod,a[i+j+d]=(1LL*(x-y)*rev%mod+mod)%mod;
	                //xor:a[i+j]=(x+y)/2,a[i+j+d]=(x-y)/2;
	                //and:a[i+j]=x-y;
	                //or:a[i+j+d]=y-x;
	            }
	}
	void solve(int a[],int b[],int n,LL mod)
	{
	    FWT(a,n,mod);
	    FWT(b,n,mod);
	    for(int i=0;i<n;i++) a[i]=1LL*a[i]*b[i]%mod;
	    UFWT(a,n,mod);
	}
};
namespace Maxflow{
	const int Maxn=1005;
	struct edge{
		int to,rev,cap;
		edge(int _to,int _rev,int _cap){
			to=_to,rev=_rev,cap=_cap;
		}
	};
	int src=1002,snk=1003;
	vector<edge> G[Maxn];
	int dist[Maxn],seen[Maxn];
	int n;
	void Clear(){
		for (int i=0;i<Maxn;i++) G[i].clear();
	}
	void bfs(int s){
		for (int i=0;i<Maxn;i++) dist[i]=-1;
		dist[s]=0;
		queue<int> Q;
		Q.push(s);
		while (!Q.empty()){
			int x=Q.front();
			Q.pop();
			for (int i=0;i<G[x].size();i++){
				edge &e=G[x][i];
				if (e.cap && dist[e.to]==-1){
					dist[e.to]=dist[x]+1;
					Q.push(e.to);
				}
			}
		}
	}
	int dfs(int now,int dest,int fl){
		if (now==dest) return fl;
		for (int &i=seen[now];i<G[now].size();i++){
			edge &ed=G[now][i];
			if (ed.cap && dist[ed.to]==dist[now]+1){
				int f=dfs(ed.to,dest,min(fl,ed.cap));
				if (f){
					ed.cap-=f;
					G[ed.to][ed.rev].cap+=f;
					return f;
				}
			}
		}
		return 0;
	}
	int dinic(int s=src,int t=snk){
		int ret=0;
		while (1){
			memset(seen,0,sizeof(seen));
			bfs(s);
			if (dist[t]==-1) return ret;
			int f=dfs(s,t,INF);
			while(f){
				ret+=f;
				f=dfs(s,t,INF);
			}
		}
	}
};
namespace Geometry{
	struct iP{
		LL x,y;
		iP(LL _x,LL _y){
			x=_x,y=_y;
		}
		iP(){
			x=y=0;
		}
		iP operator +(iP p){
			return iP(x+p.x,y+p.y);
		}
		iP operator -(iP p){
			return iP(x-p.x,y-p.y);
		}
		iP operator *(LL k){
			return iP(x*k,y*k);
		}
		LL det(iP p){
			return x*p.y-y*p.x;
		}
		LL dot(iP p){
			return x*p.x+y*p.y;
		}
		LL dist(){
			return x*x+y*y;
		}
		bool operator <(const iP &p)const{
			if (x!=p.x) return x<p.x;
			return y<p.y;
		}
	};
	struct dP{
		double x,y;
		dP(double _x,double _y){
			x=_x,y=_y;
		}
		dP(){
			x=y=0.0;
		}
		dP operator +(dP p){
			return dP(x+p.x,y+p.y);
		}
		dP operator -(dP p){
			return dP(x-p.x,y-p.y);
		}
		dP operator *(double k){
			return dP(x*k,y*k);
		}
		double det(dP p){
			return x*p.y-y*p.x;
		}
		double dot(dP p){
			return x*p.x+y*p.y;
		}
		double dist(){
			return x*x+y*y;
		}
		bool operator <(const dP &p)const{
			if (x!=p.x) return x<p.x;
			return y<p.y;
		}
	};
	vector<iP> convex_hull(iP X[],int l){
		#define sz ret.size()
		vector<iP> ret;
		sort(X+1,X+1+l);
		ret.pb(X[1]);
		for (int i=2;i<=l;i++){
			while (sz>=2 && (ret[sz-2]-X[i]).det(ret[sz-1]-X[i])>=0){
				ret.pop_back();
			}
			ret.pb(X[i]);
		}
		int rs=ret.size()+1;
		for (int i=l-1;i>=1;i--){
			while (sz>=rs && (ret[sz-2]-X[i]).det(ret[sz-1]-X[i])>=0){
				ret.pop_back();
			}
			ret.pb(X[i]);
		}
		return ret;
	}
};
const int Maxn=405;
int c[Maxn][4];
int n;
int now[4][4];
int cc[Maxn][4];
LL V[4];
LL ha[Maxn][4];
LL dp[16],dp2[16];
map<pair<LL,LL>,LL> D;
set<LL> S;
int main(){
	scanf("%d",&n);
	for (int i=1;i<=n;i++){
		for (int j=0;j<4;j++){
			scanf("%d",&c[i][j]);
		}
		for (int st=0;st<4;st++){
			ha[i][st]=0;
			for (int k=0;k<4;k++){
				ha[i][st]*=1000LL;
				ha[i][st]+=c[i][(st+k)%4];
			}
		//	cout<<ha[i][st]<<endl;
		}
		S.insert(ha[i][0]);
	}
	if (S.size()<=50){
		LL ans=0;
	for (int i=1;i<=n;i++){
		for (int j=i+1;j<=n;j++){
			LL dlt=0;
			bool ff=false;
			for (int p1=0;p1<4;p1++){
				for (int p2=0;p2<4;p2++){
					if (D.count(mp(ha[i][p1],ha[j][p2]))){
						ff=true;
						ans+=D[mp(ha[i][p1],ha[j][p2])];
						break;
					}
				}
				if (ff) break;
			}
			if (ff) continue;
			for (int k=0;k<4;k++){
//				bool flag=true;
				now[0][0]=c[j][k];
				now[0][1]=c[j][(k+3)%4];
				now[0][2]=c[i][1];
				now[0][3]=c[i][0];
				
				now[1][0]=c[j][(k+3)%4];
				now[1][1]=c[j][(k+2)%4];
				now[1][2]=c[i][2];
				now[1][3]=c[i][1];
				
				now[2][0]=c[j][(k+2)%4];
				now[2][1]=c[j][(k+1)%4];
				now[2][2]=c[i][3];
				now[2][3]=c[i][2];
				
				now[3][0]=c[j][(k+1)%4];
				now[3][1]=c[j][(k)%4];
				now[3][2]=c[i][0];
				now[3][3]=c[i][3];
				
				for (int l=0;l<4;l++){
					V[l]=0;
					for (int o=0;o<4;o++){
						V[l]=V[l]*1000+now[l][o];
					}
					//if (i==1 && j==5) cout<<k<<' '<<V[l]<<endl;
				//	cout<<V[l]<<endl;
				}
				memset(dp,0,sizeof(dp));
				dp[0]=1;
				for (int l=1;l<=n;l++){
					if (l==i || l==j) continue;
					memset(dp2,0,sizeof(dp2));
					for (int jj=0;jj<4;jj++){
						int cnt=0;
						for (int kk=0;kk<4;kk++){
							if (ha[l][kk]==V[jj]) cnt++;
						}
						
						if (cnt){
						//	cout<<cnt<<endl;
							for (int q=15;q>=0;q--){
								if (q>>jj&1){
									dp2[q]+=dp[q^(1<<jj)]*cnt;
								}
							}
						}
					}
					for (int jj=0;jj<16;jj++) dp[jj]+=dp2[jj];
				}
				//cout<<dp[15]<<endl;
				dlt+=dp[15];
			}
			D[mp(ha[i][0],ha[j][0])]=dlt;
			ans+=dlt;
		}
		}
		printf("%lld\n",ans/3);
	}
	else
	{
		LL ans=0;
		for (int i=1;i<=n;i++){
			for (int j=i+1;j<=n;j++){
				for (int k=0;k<4;k++){
	//				bool flag=true;
					now[0][0]=c[j][k];
					now[0][1]=c[j][(k+3)%4];
					now[0][2]=c[i][1];
					now[0][3]=c[i][0];
					
					now[1][0]=c[j][(k+3)%4];
					now[1][1]=c[j][(k+2)%4];
					now[1][2]=c[i][2];
					now[1][3]=c[i][1];
					
					now[2][0]=c[j][(k+2)%4];
					now[2][1]=c[j][(k+1)%4];
					now[2][2]=c[i][3];
					now[2][3]=c[i][2];
					
					now[3][0]=c[j][(k+1)%4];
					now[3][1]=c[j][(k)%4];
					now[3][2]=c[i][0];
					now[3][3]=c[i][3];
					
					for (int l=0;l<4;l++){
						V[l]=0;
						for (int o=0;o<4;o++){
							V[l]=V[l]*1000+now[l][o];
						}
						//if (i==1 && j==5) cout<<k<<' '<<V[l]<<endl;
					//	cout<<V[l]<<endl;
					}
					memset(dp,0,sizeof(dp));
					dp[0]=1;
					for (int l=i+1;l<=n;l++){
						if (l==i || l==j) continue;
						memset(dp2,0,sizeof(dp2));
						for (int jj=0;jj<4;jj++){
							int cnt=0;
							for (int kk=0;kk<4;kk++){
								if (ha[l][kk]==V[jj]) cnt++;
							}
							
							if (cnt){
							//	cout<<cnt<<endl;
								for (int q=15;q>=0;q--){
									if (q>>jj&1){
										dp2[q]+=dp[q^(1<<jj)]*cnt;
									}
								}
							}
						}
						for (int jj=0;jj<16;jj++) dp[jj]+=dp2[jj];
					}
					//cout<<dp[15]<<endl;
					ans+=dp[15];
				}
			}
		}
		printf("%lld\n",ans);
	}
	
	return ~~(0^_^0);
}


Measured memory_bytes: 384