/*
*/

#pragma comment(linker, "/STACK:16777216")
#define _CRT_SECURE_NO_WARNINGS

#include <fstream>
#include <iostream>
#include <string>
#include <complex>
#include <math.h>
#include <set>
#include <vector>
#include <map>
#include <queue>
#include <stdio.h>
#include <stack>
#include <algorithm>
#include <list>
#include <ctime>
#include <memory.h>
#include <assert.h>

#define y0 sdkfaslhagaklsldk
#define y1 aasdfasdfasdf
#define yn askfhwqriuperikldjk
#define j1 assdgsdgasghsf
#define tm sdfjahlfasfh
#define lr asgasgash
#define norm asdfasdgasdgsd
#define have adsgagshdshfhds

#define eps 1e-9
#define M_PI 3.141592653589793
#define bs 1000000007
#define bsize 350

using namespace std;

const int INF = 1e9;
const int N = 2220;

int n;
int ar[N][6];
long long dp[N][16];

long long ans;

int ar1[100], ar2[100];
int matches[1000];

vector<int> cube_list[1050], lists[10];
int pattern[1050];

vector<int> get_rotation(vector<int> v, int ps)
{
	vector<int> res = v;
	for (int i = 0; i < v.size(); i++)
	{
		res[i] = v[(i + ps) % v.size()];
	}
	return res;
}

int good_rotations(vector<int> v)
{
	int res = 0;
	for (int i = 0; i < 4; i++)
	{
		vector<int> v2 = get_rotation(v, i);
		if (v2 == v)
			++res;
	}
	return res;
}
bool better(vector<int> a, vector<int> b)
{
	for (int i = 0; i < a.size(); i++)
	{
		if (a[i] != b[i])
			return a[i] < b[i];
	}
	return false;
}

vector<int> normalize(vector<int> v)
{
	vector<int> res = v;
	for (int i = 0; i < 4; i++)
	{
		vector<int> here = get_rotation(v, i);
		if (better(here, res))
			res = here;
	}
	return res;
}

int maps[N], maps2[N];
set<vector<int> > v_list;
map<vector<int>, int> mapp;
int cnt[1 << 20];

int get_id(vector<int> v,int flag)
{
	if (v_list.find(v) == v_list.end())
	{
		if (flag == 1)
		{
			return 0;
		}
		v_list.insert(v);
		mapp[v] = v_list.size();
	}
	return mapp[v];
}

long long run_solver(int id_front, int id_back, int rot_back)
{
	for (int i = 0; i < 4; i++)
	{
		ar1[i] = ar[id_front][i];
	}

	ar2[0] = ar[id_back][(0+rot_back)%4];
	ar2[1] = ar[id_back][(3+rot_back)%4];
	ar2[2] = ar[id_back][(2+rot_back)%4];
	ar2[3] = ar[id_back][(1+rot_back)%4];

	for (int i = 0; i < 4; i++)
	{
		lists[i].clear();
	}
	for (int q = 0; q < 4; q++)
	{
		int i = q;
		lists[i].push_back(ar2[q]);
		lists[i].push_back(ar2[(q + 1) % 4]);
		lists[i].push_back(ar1[(q + 1) % 4]);
		lists[i].push_back(ar1[q]);
	}
	for (int i = 0; i < 4; i++)
	{
		lists[i] = normalize(lists[i]);
	}

	for (int i = 0; i < 4; i++)
	{
		pattern[i] = i;
	}

	for (int i = 0; i < 4; i++)
	{
		if (pattern[i] != i)
			continue;
		for (int j = i + 1; j < 4; j++)
		{
			if (lists[i]==lists[j])
				pattern[j] = i;
		}
	}

	for (int i = 0; i < 4; i++)
	{
		maps2[i] = get_id(lists[i],1);
	}

	/*for (int i = 0; i < 4; i++)
	{
		cnt[i] = 0;
	}

	for (int i = id_front+1; i <= n; i++)
	{
		if (i == id_back)
			continue;
		for (int j = 0; j < 4; j++)
		{
			if (pattern[j] != j)
				continue;
			if (maps[i] == maps2[j])
				++cnt[j];
		}
	}
	*/
	long long res = 1;

	for (int i = 0; i < 4; i++)
	{
		int here = pattern[i];
		if (cnt[maps2[here]] == 0)
			res = 0;
		res *= cnt[maps2[here]];
		//cout << cnt[here] << "%" << good_rotations(lists[i]) << endl;
		cnt[maps2[here]]--;
		res *= good_rotations(lists[i]);
	}

	for (int i = 0; i < 4; i++)
	{
		int here = pattern[i];
		cnt[maps2[here]]++;
	}

//	cout << res << endl;
	return res;
}

int main(){
	//freopen("fabro.in","r",stdin);
	//freopen("fabro.out","w",stdout);
	//freopen("F:/in.txt", "r", stdin);
	//freopen("F:/output.txt", "w", stdout);
	ios_base::sync_with_stdio(0);
	//cin.tie(0);

	cin >> n;
	for (int i = 1; i <= n; i++)
	{
		for (int j = 0; j < 4; j++)
		{
			cin >> ar[i][j];
//			ar[i][j] = rand() % 1000;
		}
		vector<int> v;
		for (int j = 0; j < 4; j++)
		{
			v.push_back(ar[i][j]);
		}
		v = normalize(v);
		for (int j = 0; j < 4; j++)
		{
			ar[i][j] = v[j];
		}
		cube_list[i] = v;
		maps[i] = get_id(v,0);
	}

	for (int i = 1; i <= n; i++)
	{
		cnt[maps[i]]++;
	}

	for (int F = 1; F <= n; F++)
	{
		cnt[maps[F]]--;

		for (int B = F + 1; B <= n; B++)
		{
			if (F == B)
				continue;
			cnt[maps[B]]--;
			for (int brot = 0; brot < 4; brot++)
			{
				ans+=run_solver(F, B, brot);
			}
			cnt[maps[B]]++;
		}
	}

	cout << ans << endl;

	cin.get(); cin.get();
	return 0;
}

Measured memory_bytes: 384