#pragma comment(linker, "/STACK:16777216")
#define _CRT_SECURE_NO_WARNINGS
#include <string>
#include <vector>
#include <map>
#include <list>
#include <iterator>
#include <set>
#include <queue>
#include <iostream>
#include <sstream>
#include <stack>
#include <deque>
#include <cmath>
#include <memory.h>
#include <cstdlib>
#include <cstdio>
#include <cctype>
#include <algorithm>
#include <utility>
#include <cassert>
#include <complex>
#include <time.h>
using namespace std;

#define FOR(i,a,b) for(int i=(a);i<(b);++i)
#define RFOR(i,b,a) for(int i=(b)-1;i>=(a);--i)
#define FILL(A,val) memset(A,val,sizeof(A))
#define ITER(it,a) for(__typeof(a.begin()) it=a.begin();it!=a.end();++it)
#define DBG1(a) cerr<<#a<<"="<<(a)<<"\n"
#define DBG2(a,b) cerr<<#a<<"="<<(a)<<", "<<#b<<"="<<(b)<<"\n"

#define ALL(V) V.begin(),V.end()
#define SZ(V) (int)V.size()
#define PB push_back
#define MP make_pair

typedef unsigned long long LL;
typedef unsigned long long ULL;
typedef vector<int> VI;
typedef pair<int, int> PII;

const double PI = acos(-1.0);
const int INF = 1000 * 1000 * 1000 + 7;
const LL LINF = 1LL * INF * INF;

map<vector<int>, int> M;
map<pair<int, int>, set<pair<int, int> > > M2;

void print(vector<int> a)
{
	FOR(i, 0, SZ(a))
	{
		cout << a[i] << ' ';
	}
	cout << endl;
}

void add(vector<int> a, int sign)
{
	FOR(i, 0, 4)
	{
		M[a] += sign;
		a.PB(a[0]);
		a.erase(a.begin());
	}
}

int main() 
{
	//freopen("in.txt", "r", stdin);
	//ios::sync_with_stdio(0);cin.tie(0);

	int n;
	cin >> n;
	FOR(i, 0, n)
	{
		vector<int> a(4);
		FOR(j, 0, 4)
		{
			cin >> a[j];
		//	a[j] = rand() % 10;
		//	a[j] = 0;
		}

		FOR(j, 0, 4)
		{
		//	print(a);
			M[a]++;
			a.PB(a[0]);
			a.erase(a.begin());
		}

		FOR(j, 0, 4)
		{
		//	print(a);
			M2[MP(a[0], a[1])].insert(MP(a[2], a[3]));
			a.PB(a[0]);
			a.erase(a.begin());
		}
	//	cout << endl;
	}

//	return 0;

	LL res = 0;
	
	for (map<vector<int>, int>::iterator it = M.begin(); it != M.end(); it++)
	{
		vector<int> a = it->first;
		pair<int, int> up = MP(a[1], a[0]);
		pair<int, int> down = MP(a[3], a[2]);
		
		if (!M2.count(up) || !M2.count(down)) continue;

		set<pair<int, int> > &U = M2[up];
		set<pair<int, int> > &D = M2[down];

		for (set<pair<int, int> > ::iterator it1 = U.begin(); it1 != U.end(); it1++)
		{
			for (set<pair<int, int> > ::iterator it2 = D.begin(); it2 != D.end(); it2++)
			{
				LL u, d, l, r, b, f;
				f = M[a];
				vector<int> UP = { up.first, up.second, it1->first, it1->second };
				if (!M.count(UP)) continue;
				vector<int> DOWN = { down.first, down.second, it2->first, it2->second };
				if (!M.count(DOWN)) continue;
				vector<int> LEFT = { a[0], a[3], it2->second, it1->first };
				if (!M.count(LEFT)) continue;
				vector<int> RIGHT = { a[1], it1->second, it2->first, a[2] };
				if (!M.count(RIGHT)) continue;
				vector<int> BACK = { it2->first,it1->second,it1->first, it2->second };
				if (!M.count(BACK)) continue;
				add(a, -1);
				u = M[UP];
				add(UP, -1);
				d = M[DOWN];
				add(DOWN, -1);
				l = M[LEFT];
				add(LEFT, -1);
				r = M[RIGHT];
				add(RIGHT, -1);
				b = M[BACK];
				add(BACK, -1);

				add(a, 1);
				add(UP, 1);
				add(DOWN, 1);
				add(LEFT, 1);
				add(RIGHT, 1);
				add(BACK, 1);

			/*	print(a);
				print(UP);
				print(DOWN);
				print(LEFT);
				print(RIGHT);
				print(BACK);*/
//				return 0;

				LL c = u*d*l*r*b*f;

			//	cout << u << ' ' << d << ' ' << l << ' ' << r << ' ' << b << ' ' << f << endl;
				
				res += c;
			//	cout << c << endl << endl;
			}
		}

	}

	cout << res / 24 << endl;

	return 0;
}

Measured memory_bytes: 640