#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
typedef pair<ll, ll> P;

#define EACH(i,a) for (auto& i : a)
#define FOR(i,a,b) for (ll i=(a);i<(b);i++)
#define RFOR(i,a,b) for (ll i=(b)-1;i>=(a);i--)
#define REP(i,n) for (ll i=0;i<(n);i++)
#define RREP(i,n) for (ll i=(n)-1;i>=0;i--)
#define debug(x) cout<<#x<<": "<<x<<endl
#define pb push_back
#define ALL(a) (a).begin(),(a).end()

const ll linf = 1e18;
const int inf = 1e9;
const double eps = 1e-12;
const double pi = acos(-1);

template<typename T>
istream& operator>>(istream& is, vector<T>& vec) {
    EACH(x,vec) is >> x;
    return is;
}
template<typename T>
ostream& operator<<(ostream& os, vector<T>& vec) {
    REP(i,vec.size()) {
        if (i) os << " ";
        os << vec[i];
    }
    return os;
}
template<typename T>
ostream& operator<<(ostream& os, vector< vector<T> >& vec) {
    REP(i,vec.size()) {
        if (i) os << endl;
        os << vec[i];
    }
    return os;
}

class Tile {
private:
    vector<ll> h, c;
public:
    Tile(const vector<ll>& c) : c(c), h(0) {
        REP(i, 4) {
            h.pb( hash(i) );
        }
    }
    ll hash(int d = 4) const {
        if (d < h.size()) return h[d];
        if (d == 4) {
            ll res = linf;
            REP(i, 4) {
                res = min(res, hash(i));
            }
            return res;
        }
        else {
            ll res = 0;
            REP(i, 4) {
                res = res * 1000 + c[(i+d)%4];
            }
            return res;
        }
    }
    ll pattern() const {
        if ( hash(0) == hash(1) ) return 4;
        if ( hash(0) == hash(2) ) return 2;
        return 1;
    }
    ll color(int idx) const {
        return c[(idx%c.size()+c.size())%c.size()];
    }
};
bool operator==(const Tile& t1, const Tile& t2) {
    return t1.hash() == t2.hash();
}
bool operator<(const Tile& t1, const Tile& t2) {
    return t1.hash() < t2.hash();
}

ll comb(ll n, ll r) {
    if (r > n) return 0;
    ll res = 1;
    REP(i, r) {
        res *= (n-i);
    }
    FOR(i, 1, r+1) {
        res /= i;
    }
    return res;
}
ll power(ll x, ll n) {
    ll res = 1;
    REP(i, n) res *= x;
    return res;
}
ll fact(ll n) {
    ll res = 1;
    FOR(i, 1, n+1) res *= i;
    return res;
}
int main() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(0);
    ll n; cin >> n;
    vector<Tile> T;
    REP(i, n) {
        vector<ll> v(4); cin >> v;
        T.pb( Tile(v) );
    }
    map<Tile, ll> m;
    REP(i, n) m[T[i]]++;
    ll ans = 0;
    REP(i, n) REP(j, n) REP(ofs, 4) {
        if (i == j) continue;
        const Tile& t1 = T[i];
        const Tile& t2 = T[j];
        map<Tile, int> need;
        REP(k, 4) {
            need[ Tile({t1.color(ofs+k+1), t1.color(ofs+k), t2.color(-k+1), t2.color(-k)}) ]++;
        }
        --m[t1];
        --m[t2];
        ll da = 1;
        EACH(p, need) {
            if (m.count(p.first) > 0) {
                // cout << m[p.first] << " " << p.second << " " << comb(m[p.first], p.second) << endl;
                da *= comb(m[p.first], p.second) * power(p.first.pattern(), p.second) * fact(p.second);
            }
            else {
                da = 0;
            }
        }
        // if (da > 0) cout << i << " " << j << endl;
        ++m[t1];
        ++m[t2];
        ans += da;
    }
    assert(ans % 6 == 0);
    ans /= 6;
    cout << ans << endl;
}


Measured memory_bytes: 384