# include<bits/stdc++.h>
using namespace std;
# define lowbit(x) ((x)&(-x))
# define pi acos(-1.0)
# define eps 1e-8
# define MOD 1000000007
# define INF 1000000000
# define mem(a,b) memset(a,b,sizeof(a))
# define FOR(i,a,n) for(register int i=a; i<=n; ++i)
# define FDR(i,a,n) for(register int i=a; i>=n; --i)
# define AU(i,x)    for(auto i=x.begin(); i!=x.end(); ++i)
# define ALL(A) A.begin(),A.end()
# define bug puts("H");
# define lch p<<1,l,mid
# define rch p<<1|1,mid+1,r
# define mp make_pair
# define pb push_back
typedef pair<int,int> PII;
typedef vector<int> VI;
# pragma comment(linker, "/STACK:1024000000,1024000000")
typedef long long LL;
inline char nc(){
    static char buf[1000000],*p1=buf,*p2=buf;
    return p1==p2&&(p2=(p1=buf)+fread(buf,1,1000000,stdin),p1==p2)?EOF:*p1++;
}
inline int Scan(){
    char ch=nc();int sum=0, f=1;
    if (ch=='-') f=-1, ch=nc();
    while(!(ch>='0'&&ch<='9'))ch=nc();
    while(ch>='0'&&ch<='9')sum=sum*10+ch-48,ch=nc();
    return sum*f;
}
int ps4[4][2]={0,1,0,-1,1,0,-1,0};
int ps8[8][2]={0,1,0,-1,1,0,-1,0,1,1,1,-1,-1,-1,-1,1};
inline int min(int a,int b,int c) {return min(a,min(b,c));}
inline int max(int a,int b,int c) {return max(a,max(b,c));}
inline int min(int a,int b,int c,int d){return min(min(a,b,c),d);}
inline int max(int a,int b,int c,int d){return max(max(a,b,c),d);}
//struct Edge{int p, next, w;}edge[maxn];
//inline add_edge(int u, int v, int w){edge[cnt]=Edge{v,head[u],w}; head[u]=cnt++;}
const int N=405;
///Code begin..................................................................

struct Node{int a[5];}node[N];
unordered_map<LL,int>vis;
Node tmp, b[5];
int F[5];
LL ans=0;

LL _hash(Node a){
    LL tmp=0;
    FOR(i,0,3) tmp*=1000, tmp+=a.a[i];
    return tmp;
}
Node Swap(Node a){
    Node b;
    FOR(i,0,3) b.a[i]=a.a[3-i];
    return b;
}
int find(int x){return F[x]<0?x:F[x]=find(F[x]);}
int Check(Node c1, Node c2){
    int cnt=0;
    FOR(i,0,3) {
        if (c1.a[0]==c2.a[i]&&c1.a[1]==c2.a[(i+1)%4]&&c1.a[2]==c2.a[(i+2)%4]&&c1.a[3]==c2.a[(i+3)%4])
            ++cnt;
    }
    return cnt;
}
LL Cal(int x){
    mem(F,-1);
    FOR(i,0,3) FOR(j,i+1,3) {
        if (Check(b[i],b[j])) {
            int u=find(i), v=find(j);
            if (u!=v) F[u]+=F[v], F[v]=u;
        }
    }
    LL tmp=1;
    FOR(i,0,3) {
        if (F[i]>0) continue;
        int m=vis[_hash(b[i])]-Check(node[x],b[i]), n=Check(b[i],b[i]);
        LL now=1;
        FOR(j,1,-F[i]) {
            if (m<0) {now=0; break;}
            now*=m;
            m-=n;
        }
        tmp*=now;
    }
    return tmp;
}
int main ()
{
    int n;
    scanf("%d",&n);
    FOR(i,1,n) {
        scanf("%d%d%d%d",&node[i].a[0],&node[i].a[1],&node[i].a[2],&node[i].a[3]);
        node[i]=Swap(node[i]);
        FOR(j,1,i-1) FOR(k,0,3) {
            FOR(l,0,3) tmp.a[l]=node[j].a[(l+k)%4];
            FOR(l,0,3) {
                b[l].a[0]=node[i].a[l]; b[l].a[1]=node[i].a[(l+1)%4];
                b[l].a[3]=tmp.a[l]; b[l].a[2]=tmp.a[(l+1)%4];
            }
            ans+=Cal(j);
        }
        node[i]=Swap(node[i]);
        FOR(j,0,3) {
            FOR(k,0,3) tmp.a[k]=node[i].a[(k+j)%4];
            ++vis[_hash(tmp)];
        }
    }
    printf("%lld\n",ans);
    return 0;
}

Measured memory_bytes: 58256