#include <bits/stdc++.h>

#define forn(i, n) for (int i = 0; i < int(n); i++)
#define nfor(i, n) for (int i = int(n) - 1; i >= 0; i--)
#define fore(i, l, r) for (int i = int(l); i < int(r); i++)
#define correct(x, y, n, m) (0 <= (x) && (x) < (n) && 0 <= (y) && (y) < (m))
#define all(a) (a).begin(), (a).end()
#define sz(a) int((a).size())
#define pb(a) push_back(a)
#define mp(x, y) make_pair((x), (y))
#define x first
#define y second

using namespace std;

typedef long long li;
typedef long double ld;
typedef pair<int, int> pt;

template<typename X> inline X abs(const X& a) { return a < 0? -a: a; }
template<typename X> inline X sqr(const X& a) { return a * a; }

template<typename A, typename B> inline ostream& operator<< (ostream& out, const pair<A, B>& p) { return out << "(" << p.x << ", " << p.y << ")"; }
template<typename T> inline ostream& operator<< (ostream& out, const vector<T>& a) { out << "["; forn(i, sz(a)) { if (i) out << ','; out << ' ' << a[i]; } return out << " ]"; } 
template<typename T> inline ostream& operator<< (ostream& out, const set<T>& a) { return out << vector<T>(all(a)); }
template<typename X, typename Y> inline ostream& operator<< (ostream& out, const map<X, Y>& a) { return out << vector<pair<X, Y>>(all(a)); }
template<typename T> inline ostream& operator<< (ostream& out, pair<T*, int> a) { return out << vector<T>(a.x, a.x + a.y); }

inline ld gett() { return ld(clock()) / CLOCKS_PER_SEC; }

const int INF = int(1e9);
const li INF64 = li(1e18);
const ld EPS = 1e-9, PI = 3.1415926535897932384626433832795;

#ifdef SU1
#define LOG
#endif

int n;
const int N = 500;
int c[N][4];

bool read() {
	if (!(cin >> n))
		return false;
	forn(i, n)
		forn(j, 4)
			assert(cin >> c[i][j]);
	return true;
}

vector <int> rotate(vector <int> v) {
	vector <int> res = v;
	forn(i, sz(v))
		res[(i + 1) % sz(v)] = v[i];
	return res;
}

int deg(vector <int> v) {
	int res = 0;
	vector <int> x = v;
	forn(i, 4) {
		if (x == v)
			res++;
		x = rotate(x);
	}
	return res;
}

bool same(vector <int> v, vector <int> u) {
	vector <int> x = v;
	forn(i, 4) {
		if (x == u)
			return true;
		x = rotate(x);
	}
	return false;
}

vector <int> mv(int a, int b, int c, int d) {
	vector <int> res(4);
	res[0] = a;
	res[1] = b;
	res[2] = c;
	res[3] = d;
	return res;
}

map <li, int> cnt;

void inccnt(vector <int> x, int delta) {
	li v = 0;
	for (auto c: x)
		v = v * 1000 + c;
	cnt[v] += delta;
}

int getcnt(vector <int> x) {
	li v = 0;
	for (auto c: x)
		v = v * 1000 + c;
	if (!cnt.count(v))
		return 0;
	return cnt[v];
}

void inccnt(int i, int delta) {
	vector <int> x = vector <int> (c[i], c[i] + 4);
	forn(_, 4) {
		x = rotate(x);
		inccnt(x, delta);
	}
}

vector <int> vs[4];

void solve() {
	cnt.clear();
	forn(i, n)
		inccnt(i, +1);

	li res = 0;
	forn(i, n) {
		vector <int> ci = vector <int> (c[i], c[i] + 4);
		inccnt(i, -1);
/*		cerr << "-----" << endl;
		for (auto x: cnt)
			cerr << x.y << endl;
		cerr << "-----" << endl;*/
		fore(j, i + 1, n) {
			inccnt(j, -1);
			vector <int> cj = vector <int> (c[j], c[j] + 4);
			forn(_, 4) {
				cj = rotate(cj);
				vs[0] = mv(ci[0], cj[1], cj[0], ci[1]);
				vs[1] = mv(ci[0], ci[3], cj[2], cj[1]);
				vs[2] = mv(ci[1], cj[0], cj[3], ci[2]);
				vs[3] = mv(ci[3], ci[2], cj[3], cj[2]);
				li ans = 1;
				forn(k, 4) {
					li cur = getcnt(vs[k]);
					int d = deg(vs[k]);
					forn(t, k) {
						if (same(vs[t], vs[k]))
							cur -= d;
					}
					if (cur > 0)
						ans *= cur;
					else
						ans = 0;
				}
/*				if (ans)
					cerr << i << " " << j << " " << _ << " " << ans << endl;*/
				res += ans;
			}
			inccnt(j, +1);
		}
	}
	cout << res << endl;
}

int main() {
#ifdef SU1
    assert(freopen("input.txt", "rt", stdin));
    //assert(freopen("output.txt", "wt", stdout));
#endif
    
    cout << setprecision(10) << fixed;
    cerr << setprecision(5) << fixed;

    while (read()) {
		ld stime = gett();
		solve();
		cerr << "Time: " << gett() - stime << endl;
		//break;
	}
	
    return 0;
}


Measured memory_bytes: 512