#include <iostream>
#include <vector>
#include <map>
#include <algorithm>
using namespace std;


template<class T> inline bool chmax(T& a, T b) { if (a < b) { a = b; return 1; } return 0; }
template<class T> inline bool chmin(T& a, T b) { if (a > b) { a = b; return 1; } return 0; }

template<class T> vector<T> make_vec(size_t a) { return vector<T>(a); }
template<class T, class... Ts> auto make_vec(size_t a, Ts... ts) {
  return vector<decltype(make_vec<T>(ts...))>(a, make_vec<T>(ts...));
}
template<class T, class V>
typename enable_if<is_class<T>::value == 0>::type fill(T &t, const V &v) {
    t = v;
}
template<class T, class V>
typename enable_if<is_class<T>::value != 0>::type fill(T &t, const V &v){
    for (auto &e : t) fill(e, v);
}

#define COUT(x) cout << #x << " = " << (x) << " (L" << __LINE__ << ")" << endl
template<class T1, class T2> ostream& operator << (ostream &s, pair<T1,T2> P)
{ return s << '<' << P.first << ", " << P.second << '>'; }
template<class T> ostream& operator << (ostream &s, vector<T> P)
{ for (int i = 0; i < P.size(); ++i) { if (i > 0) { s << " "; } s << P[i]; } return s; }
template<class T> ostream& operator << (ostream &s, vector<vector<T> > P)
{ for (int i = 0; i < P.size(); ++i) { s << endl << P[i]; } return s << endl; }

#define EACH(i, s) for (__typeof__((s).begin()) i = (s).begin(); i != (s).end(); ++i)
template<class T1, class T2> ostream& operator << (ostream &s, map<T1,T2> P)
{ EACH(it, P) { s << "<" << it->first << "->" << it->second << "> "; } return s << endl; }



int N;
vector<vector<int> > C;
map<vector<int>, long long> ma;

void use(vector<int> v) {
    for (int it = 0; it < 4; ++it) {
        vector<int> col(4);
        for (int j = 0; j < 4; ++j) {
            col[j] = v[(it+j)%4];
        }
        ma[col]--;
    }
}

void add(vector<int> v) {
    for (int it = 0; it < 4; ++it) {
        vector<int> col(4);
        for (int j = 0; j < 4; ++j) {
            col[j] = v[(it+j)%4];
        }
        ma[col]++;
    }
}

int main() {
    while (cin >> N) {
        C.assign(N, vector<int>(4));
        for (int i = 0; i < N; ++i) 
            for (int j = 0; j < 4; ++j)
                cin >> C[i][j];

        ma.clear();
        for (int i = 0; i < N; ++i) add(C[i]);

        long long res = 0;
        for (int i = 0; i < N; ++i) {
            use(C[i]);
            for (int j = 0; j < N; ++j) {
                if (j == i) continue;
                use(C[j]);

                for (int dir = 0; dir < 4; ++dir) {
                    auto ue = C[i];
                    vector<int> shita(4);
                    for (int k = 0; k < 4; ++k) shita[k] = C[j][(dir + k) % 4];
                    reverse(shita.begin(), shita.end());

                    //cout << i << ", " << j << ", " << dir <<  ": " << C[i] << ", " << C[j] << " ;; " << shita << endl;

                    long long tmp = 1;
                    vector<bool> isadd(4, 0);
                    for (int it = 0; it < 4; ++it) {
                        vector<int> col(4);
                        col[1] = ue[it%4];
                        col[0] = ue[(it+1)%4];
                        col[2] = shita[it%4];
                        col[3] = shita[(it+1)%4];
                        if (!ma.count(col)) tmp = 0;
                        else tmp *= ma[col], use(col), isadd[it] = true;


                        if (i == 0 && j == 4 && dir == 2) {
                            //cout << it << ": " << col << endl;
                        }
                    }
                    for (int it = 0; it < 4; ++it) {
                        vector<int> col(4);
                        col[1] = ue[it%4];
                        col[0] = ue[(it+1)%4];
                        col[2] = shita[it%4];
                        col[3] = shita[(it+1)%4];
                        if (isadd[it]) add(col);
                    }
                    
                    res += tmp;
                }
                add(C[j]);
            }
            add(C[i]);
        }
        cout << res / 6 << endl;
    }
}


Measured memory_bytes: 384