#include<bits/stdc++.h>
#include<unordered_map>
using namespace std;
typedef long long ll;
const int N=405;
struct data{
	int a[4];
	data nxt(){
		return (data){a[1],a[2],a[3],a[0]};
	}
	bool operator == (const data &b) const{
		for(int i=0;i<4;i++){
 			if(a[i]!=b.a[i]){
				return false;
			}
		}
		return true;
	}
}a[N];
namespace std{
	template <>
	struct hash <data>{
		hash<ll> h;
		size_t operator () (data n) const{
			ll res=0;
			for(int i=0;i<4;i++){
				res=res*2333+n.a[i];
			}
			return res;
		}
	};
}
unordered_map<data,int> mp;
int n;
ll ans;
void insert(data x,int v){
	for(int i=0;i<4;i++,x=x.nxt()){
		mp[x]+=v;
	}
}
int main(){
	scanf("%d",&n);
	for(int i=1;i<=n;i++){
		scanf("%d%d%d%d",&a[i].a[0],&a[i].a[1],&a[i].a[2],&a[i].a[3]);
		insert(a[i],1);
	}
	for(int i=1;i<=n;i++){
		insert(a[i],-1);
		for(int j=i+1;j<=n;j++){
			insert(a[j],-1);
			for(int k=0;k<4;k++,a[j]=a[j].nxt()){
				data t1=(data){a[i].a[1],a[i].a[0],a[j].a[0],a[j].a[3]};
				data t2=(data){a[i].a[2],a[i].a[1],a[j].a[3],a[j].a[2]};
				data t3=(data){a[i].a[3],a[i].a[2],a[j].a[2],a[j].a[1]};
				data t4=(data){a[i].a[0],a[i].a[3],a[j].a[1],a[j].a[0]};
				if(!mp[t1]||!mp[t2]||!mp[t3]||!mp[t4]){
					continue;
				}
				ll res=1;
				res*=mp[t1];
				insert(t1,-1);
				res*=mp[t2];
				insert(t2,-1);
				res*=mp[t3];
				insert(t3,-1);
				res*=mp[t4];
				insert(t3,1);
				insert(t2,1);
				insert(t1,1);
				ans+=res;
			}
			insert(a[j],1);
		}
	}
	printf("%lld\n",ans);
	return 0;
}