#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <map>
using namespace std;

typedef long long s64;

struct object
{
	int a, b, c, d;
	object() {}
	object(const int &_a, const int &_b, const int &_c, const int &_d)
		: a(_a), b(_b), c(_c), d(_d) {}

	inline s64 value() const
	{
		return ((s64)a << 30) | (b << 20) | (c << 10) | d;
	}

	inline object rotate() const
	{
		return {b, c, d, a};
	}
};
map<s64, int> all;

inline void add(object cur, int delta)
{
	for (int k = 0; k < 4; ++k)
		all[(cur = cur.rotate()).value()] += delta;
}

inline int query(const object &a)
{
	return all[a.value()];
}

inline bool existed(const object &a)
{
	return all.find(a.value()) != all.end();
}

const int MaxN = 400;

int n;
object f[MaxN + 1];

int main()
{
	cin >> n;
	for (int i = 1; i <= n; ++i)
	{
		cin >> f[i].a >> f[i].b;
		cin >> f[i].c >> f[i].d;
		add(f[i], 1);
	}

	s64 res = 0;
	for (int i = 1; i < n; ++i)
	{
		add(f[i], -1);

		for (int j = i + 1; j <= n; ++j)
		{
			add(f[j], -1);

			object cur = f[j];
			for (int k = 0; k < 4; ++k)
			{
				object f1(cur.b, cur.a, f[i].b, f[i].a);
				object f2(cur.a, cur.d, f[i].c, f[i].b);
				object f3(cur.d, cur.c, f[i].d, f[i].c);
				object f4(cur.c, cur.b, f[i].a, f[i].d);

				if (!existed(f1) || !existed(f2) || !existed(f3) || !existed(f4))
				{
					cur = cur.rotate();
					continue;
				}

				s64 ways = 1;
				ways *= query(f1), add(f1, -1);
				ways *= query(f2), add(f2, -1);
				ways *= query(f3), add(f3, -1);
				ways *= query(f4);

				add(f1, 1), add(f2, 1), add(f3, 1);

				res += ways;

				cur = cur.rotate();
			}

			add(f[j], 1);
		}
	}

	cout << res << endl;

	return 0;
}