import std.stdio;
import std.conv, std.array, std.algorithm, std.string;
import std.math, std.random, std.range, std.datetime;
import std.bigint;

int[string] cset;
int[][] cs;

void main(){
	int n = readln.chomp.to!int;
	
	foreach(i; 0 .. n){
		int[] x = readln.chomp.split.map!(to!int).array;
		cset[x.toKey] += 1;
		}
	
	debug cset.writeln;
	
	cset.rehash;
	
	
	BigInt ans = 0;
	foreach(a; cset.keys){
		int[] x = a.split.map!(to!int).array;
		foreach(b; cset.keys){
			int[] y = b.split.map!(to!int).array;
			ans += fn(x, y);
			if(b.weight < 4){
				y = y[1 .. $] ~ y[0];
				ans += fn(x, y);
				if(b.weight < 2){
					y = y[1 .. $] ~ y[0];
					ans += fn(x, y);
					y = y[1 .. $] ~ y[0];
					ans += fn(x, y);
					}
				}
			}
		}
	
	ans /= 6;
	ans.writeln;
	
	}

string toKey(int[] x){
	while(x[0] > x[1] || x[0] > x[2] || x[0] > x[3]) x = x[1 .. $] ~ x[0];
	if(x[0] == x[3]) x = x[3] ~ x[0 .. 3];
	if(x[0] == x[3]) x = x[3] ~ x[0 .. 3];
	if(x[0] == x[3]) x = x[3] ~ x[0 .. 3];
	if(x[0] == x[2] && x[1] > x[3]) x = x[2 .. 4] ~ x[0 .. 2];
	
	return x.map!(to!string).join(" ");
	}

int weight(string k){
	int[] x = k.split.map!(to!int).array;
	if(x[0] == x[2] && x[1] == x[3]){
		if(x[0] == x[1]) return 4; else return 2;
		}
	else return 1;
	}

BigInt fn(int[] x, int[] y){
	string[] ks = [
		x.toKey,
		y.toKey,
		[x[0], y[0], y[3], x[1]].toKey,
		[x[1], y[3], y[2], x[2]].toKey,
		[x[2], y[2], y[1], x[3]].toKey,
		[x[3], y[1], y[0], x[0]].toKey
		];
	foreach(k; ks) if(!(k in cset)) return BigInt(0);
	
	BigInt[] ns = ks.map!(k => BigInt(cset[k])).array;
	
	foreach(i, k; ks) foreach(ii, kk; ks){
		if(k == kk) if(i < ii){
			ns[ii] -= 1;
			if(ns[ii] <= 0) return BigInt(0);
			}
		}
	
	BigInt ans = 1;
	foreach(i, k; ks) ans *= ns[i] * k.weight;
	ans /= ks[0].weight;
	
	debug if(ans > 0){
		writeln(x, " ", y);
		writeln(ks);
		writeln(ns, " ", ans);
		}
	
	return ans;
	
	}