#pragma region include
#include <iostream>
#include <iomanip>
#include <stdio.h>

#include <sstream>
#include <algorithm>
#include <cmath>
#include <complex>

#include <string>
#include <cstring>
#include <vector>
#include <tuple>
#include <bitset>

#include <queue>
#include <complex>
#include <set>
#include <map>
#include <stack>
#include <list>

#include <fstream>
#include <random>
//#include <time.h>
#include <ctime>
#pragma endregion //#include
/////////
#define REP(i, x, n) for(int i = x; i < n; ++i)
#define rep(i,n) REP(i,0,n)
/////////
#pragma region typedef
typedef long long LL;
typedef long double LD;
typedef unsigned long long ULL;
#pragma endregion //typedef
////定数
const int INF = (int)1e9;
const LL MOD = (LL)1e9+7;
const LL LINF = (LL)1e18;
const double PI = acos(-1.0);
const double EPS = 1e-9;
/////////
using namespace::std;

void solve(){
	int N;
	cin >> N;
	vector<vector<int> > pane(N,vector<int>(4));
	for(int i=0;i<N;++i){
		vector<int> temp(4),res(4);
		for(int j=0;j<4;++j){
			cin >> temp[j];
		}
		res = temp;
		for(int j=0;j<3;++j){
			rotate(temp.begin(),temp.begin()+1,temp.end());
			res = min(res,temp);
		}
		pane[i] = res;
	}
	map<vector<int>,int> pMap;
	for(int i=0;i<N;++i){
		pMap[ pane[i] ]++;
	}
	/*
		  5---4
		 /|  /|
		0-6-1 7 ←6が裏
		|/  |/
		3---2
	*/
	vector< vector<int> > men(6,vector<int>(4));
	men[0][0]=0;men[0][1]=1;men[0][2]=2;men[0][3]=3;
	men[1][0]=1;men[1][1]=0;men[1][2]=5;men[1][3]=4;
	men[2][0]=2;men[2][1]=1;men[2][2]=4;men[2][3]=7;
	men[3][0]=3;men[3][1]=2;men[3][2]=7;men[3][3]=6;
	men[4][0]=0;men[4][1]=3;men[4][2]=6;men[4][3]=5;
	men[5][0]=4;men[5][1]=5;men[5][2]=6;men[5][3]=7;
	//0,5面を決定して[1,4]面を探す
	
	map<vector<int>,LL> Bmap;
	vector<int> pos(8);
	LL ans = 0;
	for(int A=0;A<=N-6;++A){
		for(int i=0;i<4;++i){
			pos[i] = pane[A][i];
		}
		pMap[ pane[A] ]--;//減らす
		for(int B=A+1;B<N;++B){
			vector<int> temp = pane[B];
			for(int d=0;d<4;++d){//Bの回転
				/*if( Bmap[ temp ] ){
					ans += Bmap[ temp ];
					rotate(temp.begin(),temp.begin()+1,temp.end());
					continue;
				}*/
				LL resABD = 1;//A,Bと回転での通り数
				for(int i=0;i<4;++i){
					pos[i+4] = temp[i];
				}
				//8頂点の色が決まった
				
				multiset<vector<int> > inSet;//
				inSet.insert( pane[B] );
				//4枚決める
				for(int i=0;i<4;++i){
					vector<int> ter(4);//探す面
					LL mul = 1;//対称の場合
					for(int j=0;j<4;++j){
						ter[j] = pos[ men[i+1][j] ];
					}
					{//小さい値の並びを代表とする
						vector<int> temp = ter;
						for(int k=0;k<3;++k){
							rotate(temp.begin(),temp.begin()+1,temp.end());
							if( ter == temp ){
								mul++;
							}else if( temp < ter ){
								ter = temp;
								mul = 1;
							}
						}
					}
					LL res = pMap[ ter ];
					LL sub = inSet.count( ter );//既に配置しているかチェック
					res -= sub;
					if( res <= 0 ){
						resABD = 0;//配置できなかった
						break;
					}else{
						resABD *= (res*mul);
					}
					inSet.insert( ter );
				}

				Bmap[ temp ] = resABD;
				ans += resABD;
				//次のための回転
				rotate(temp.begin(),temp.begin()+1,temp.end());
			}
		}
	}
	cout << ans << endl;
}

#pragma region main
signed main(void){
	std::cin.tie(0);
	std::ios::sync_with_stdio(false);
	std::cout << std::fixed;//小数を10進数表示
	cout << setprecision(16);//小数点以下の桁数を指定//coutとcerrで別	
	
	solve();
}
#pragma endregion //main()


Measured memory_bytes: 35456