#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
using namespace std;

enum FACE { TOP, BOTTOM, FRONT, BACK, LEFT, RIGHT };
FACE ck[6]={TOP,BOTTOM,FRONT,BACK,LEFT,RIGHT};

class UnionFind
{
public:
	vector<int> data;
	UnionFind(int size):data(size, -1){}
	
	bool unionSet(int x, int y)
	{
		x = root(x); y=root(y);
		if(x != y)
		{
			if(data[y] < data[x]) swap(x, y);
			data[x] += data[y]; data[y] = x;
		}
		return x != y;
	}
	
	int root(int x)
	{
		return data[x] < 0 ? x:data[x]=root(data[x]);
	}
};

class Dice
{
public:
	Dice(string m[6])
	{
		f[TOP]=0; f[FRONT]=1; f[LEFT]=2;
		f[RIGHT]=3; f[BACK]=4; f[BOTTOM]=5;
		
		for(int i=0; i<6; i++)
			val[i]=m[i];
	}
	
	void rotated(FACE a, FACE b, FACE c, FACE d)
	{
		int tmp = f[a];
		f[a]=f[b];
		f[b]=f[c];
		f[c]=f[d];
		f[d]=tmp;
	}
	
	vector<Dice> all_rotate()
	{
		vector<Dice> t;
		for(int i=0; i<6; (i&1?rotateY():rotateX()), i++)
		for(int j=0; j<4; rotateZ(), j++)
			t.push_back(*this);
			
		return t;
	}
	
	void rotateX() { rotated(TOP, BACK, BOTTOM, FRONT); }
	void rotateY() { rotated(TOP, LEFT, BOTTOM, RIGHT); }
	void rotateZ() { rotated(FRONT, RIGHT, BACK, LEFT); }
	
	string GetVal(FACE fe) { return val[f[fe]]; }

	
	int f[6];
	string val[6];
};

bool isequal(vector<Dice>& a, vector<Dice>& b)
{
	for(int k=0; k<a.size(); k++) 
	for(int j=0; j<b.size(); j++)
	{
		bool g=true;
		for(int i=0; i<6; i++)
		{
			if(a[k].GetVal(ck[i])!=b[j].GetVal(ck[i]))
			{
				g=false;
				break;
			}
		}
		if(g) return true;
	}
	
	return false;
}

int main()
{
	int N;
	while(cin >> N, N)
	{
		vector<Dice> d;
		for(int i=0; i<N; i++)
		{
			string s[6];
			for(int j=0; j<6; j++)
				cin >> s[j];
				
			d.push_back(s);
		}
		
		vector<vector<Dice> > face;
		for(int i=0; i<d.size(); i++)
			face.push_back(d[i].all_rotate());
		
		int ans=0;
		UnionFind uf(N);
		
		for(int i=0; i<N; i++)
		for(int j=i+1; j<N; j++)
		{
			if(i==j) continue;
			if(isequal(face[j], face[i]))
			{
				if(uf.unionSet(i,j))
					ans++;
			}
		}
		
		cout << ans << endl;
	}
}