#include <bits/stdc++.h>
//#include <boost/functional/hash.hpp>
//example: unordered_set< pair<int,int>,boost::hash< std::pair<int, int> > > used;
//priority_queue< pair<int,pair<int,int> >, vector<pair<int,pair<int,int>>>, greater<pair<int,pair<int,int> > > > pqueue;    //cost, vertex(行き先)
using namespace std;

#define module 1000000007
#define mp make_pair
#define all(v) (v).begin(),(v).end()

template<class T, class U>
inline void chmin(T &t, U f) { if (t > f)t = f; }

template<class T, class U>
inline void chmax(T &t, U f) { if (t < f)t = f; }

typedef pair<int, int> P;
typedef long long LL;
#define int long long
const int INF = INT_MAX / 2;    //int_max->2*e+9
const int MAXN = 100001;

/*struct edge {
    edge(int to, int cost) : to(to), cost(cost) {}
    int to, cost;
};
vector<edge> graph[MAXN];*/

int dx[4] = {-1, 0, 1, 0};
int dy[4] = {0, -1, 0, 1};

//-----Template---------
/*//pure
LL compress(vector<int>& v){ //10^3*4->10^12
    LL r=0;
    for (int i = 0; i < v.size(); ++i) {
        r=r*1000+v[i];
    }
    return r;
}


vector<int> getMinVector(vector<int> v){
    vector<vector<int>> tmpVecs;
    tmpVecs.push_back(v);
    for (int i = 1; i < 4; ++i) {
        rotate(v.begin(),v.begin()+1,v.end());  //begin to end, begin+1が先頭に来るように左に回す
        //右に回すときには rotate(v.rbegin(),v.rbegin()+1,v.rend()) とrbeginを使う
        tmpVecs.push_back(v);
    }
    sort(all(tmpVecs));
    *//*sort(tmpVecs.begin(),tmpVecs.end(),[](vector<int> a,vector<int> b){
        if(a.size()==0)return true;
        for (int i = 0; i < a.size(); ++i) {
            if(a[i]!=b[i]){
                return a[i]<b[i];
            }
        }
        return true;
    });*//*
    return tmpVecs[0];
}
//pure
int getWay(vector<int>& v){
    int wayNum=1;
    if(v[0] == v[1] && v[1]==v[2] && v[2]==v[3]){
        wayNum=4;
    }else if(v[0]==v[2] && v[1]==v[3]){
        wayNum=2;
    }
    return wayNum;
}

int getWay2(vector<int> v){
    set<vector<int>> s;
    for (int i = 0; i < 4; ++i) {
        s.insert(v);
        rotate(v.begin(),v.begin()+1,v.end());
    }
    return 4/s.size();
}

int n, counter;
//string tile[401];
vector<vector<int>> tile(401);
unordered_map<LL,int> cnt;
unordered_map<LL,int> way;*/

vector<int> rig(vector<int> v){
    vector<vector<int>> r(4);
    for (int i = 0; i < 4; ++i) {
        r[i]=v;
        rotate(r[i].begin(),r[i].begin()+i,r[i].end());
    }
    sort(all(r));
    return r[0];
}

LL en(vector<int> v){
    LL r=0;
    for (int i = 0; i < v.size(); ++i) {
        r=r*1000+v[i];
    }
    return r;
}

int n;
vector<int>C[400];
signed main(){
    cin>>n;
    map<LL,int>cnt;
    map<LL,int>way;
    for (int i = 0; i < n; ++i) {
        C[i].resize(4);
        for (int j = 0; j < 4; ++j) {
            cin>>C[i][j];
        }
        C[i]=rig(C[i]);
        cnt[en(C[i])]++;

        vector<int> v=C[i];
        set<vector<int>>s;
        for (int k = 0; k <4 ; ++k) {
            s.insert(v);
            rotate(v.begin(),v.begin()+1,v.end());
        }
        way[en(C[i])]=4/s.size();
    }

    LL ans=0;
    for (int i = 0; i < n; ++i) {
        cnt[en(C[i])]--;
        vector<int> X=C[i];
        for (int j = i+1; j < n; ++j) {
            vector<int> Y=C[j];
            cnt[en(C[j])]--;
            reverse(all(Y));

            for (int ii = 0; ii < 4; ++ii) {
                vector<LL> wanna(4);
                for(int k=0;k<4;k++){
                    vector<int> v(4);
                    v[0]=X[(k+1)%4];
                    v[1]=X[k];
                    v[2]=Y[k];
                    v[3]=Y[(k+1)%4];
                    v=rig(v);
                    wanna[k]=en(v);
                }
                sort(all(wanna));
                vector<pair<int,int>> want;
                for(int k=0;k<4;k++){
                    if(want.size()==0||want.back().first!=wanna[k]){
                        want.push_back(mp(wanna[k],1));
                    }
                    else{
                        want[want.size()-1].second++;
                    }
                }

                LL tmp=1;
                for(int k=0;k<want.size();k++){
                    int e=want[k].first;
                    int f=want[k].second;
                    if(cnt.find(e)==cnt.end()){
                        tmp=0;
                        continue;
                    }
                    LL hoge=cnt[e];
                    LL piyo=way[e];
                    for(int l=0;l<f;l++)
                        tmp*=(hoge-l)*piyo;
                }
                ans+=tmp;
                rotate(Y.begin(),Y.begin()+1,Y.end());
            }
            cnt[en(C[j])]++;
        }
    }
    cout<<ans<<endl;
    return 0;
}

Measured memory_bytes: 384