Go: package main

import (
	"bufio"
	"os"
	"strconv"
	"strings"
		"reflect"
	"fmt"
)

var scanner = bufio.NewScanner(os.Stdin)

func main() {
	// 上面の色を固定してから、左右方向に回転して一致するものがあるかを調べる
	round := [][]int{
		{1,2,3,4,5,6}, {1,3,5,2,4,6}, {1,4,2,5,3,6}, {1,5,4,3,2,6}, // c1を上面に固定して回転
		{2,6,3,4,1,5}, {2,3,1,6,4,5}, {2,1,4,3,6,5}, {2,4,6,1,3,5}, // c2を上面に固定して回転
		{3,1,2,5,6,4}, {3,2,6,1,5,4}, {3,5,1,6,2,4}, {3,6,5,2,1,4}, // c3を上面に固定して回転
		{4,1,5,2,6,3}, {4,2,1,6,5,3}, {4,5,6,1,2,3}, {4,6,2,5,1,3}, // c4を上面に固定して回転
		{5,1,3,4,6,2}, {5,3,6,1,4,2}, {5,4,1,6,3,2}, {5,6,4,3,1,2}, // c5を上面に固定して回転
		{6,2,4,3,5,1}, {6,3,2,5,4,1}, {6,5,3,4,2,1}, {6,4,5,2,3,1}, // c6を上面に固定して回転

	}
	for scanner.Scan() {
		n, _ := strconv.Atoi(scanner.Text())
		if n == 0 {
			break
		}
		cubes := make([][]string, n)
		for i := 0; i < n; i++ {
			scanner.Scan()
			cubes[i] = strings.Split(scanner.Text(), " ")
		}
		check := func(a, b int) bool {
			tmp := make([]string, 6)
			for i := 0; i < 24; i++ {
				for j := 0; j < 6; j++ {
					tmp[j] = cubes[b][round[i][j]-1]
				}
				if reflect.DeepEqual(tmp, cubes[a]) {
					return true
				}
			}
			return false
		}
		tbl := make([]int, n)
		// 全ての組み合わせを調べる
		for i := 0; i < n; i++ {
			if tbl[i] == 1 {
				continue
			}
			for j := i+1; j < n; j++ {
				if check(i, j) {
					tbl[j] = 1
				}
			}
		}
		fmt.Println(sum(tbl))
	}
}

func sum(a []int) int {
	ret := 0
	for _, v := range a {
		ret += v
	}
	return ret
}

C++: #include <bits/stdc++.h>
using namespace std;

//define
#define int long long
#define UNIQUE(v) v.erase(unique(all(v)), v.end());
#define ZIP(v) sort(all(v)),UNIQUE(v)
#define ADD(a, b) a = (a + b) % mod
#define SUB(a, b) a = (a+mod-b)%mod
#define MUL(a, b) a = (a * b) % mod
#define repi(i,m,n) for(int i = m;i < n;i++)
#define drep(i,n,m) for(int i = n;i >= m;i--)
#define rep(i,n) repi(i,0,n)
#define rrep(i,n) repi(i,1,n+1)
#define chmin(x,y) x = min(x,y)
#define chmax(x,y) x = max(x,y)
#define all(v) v.begin(),v.end()
#define rall(v) v.rbegin(), v.rend()
#define dmp(x,y) make_pair(x,y)
#define pb(x) push_back(x)
#define fi first
#define se second

//template
template <typename T, typename U>
ostream &operator<<(ostream &os, const pair<T, U> &p){
  os << p.first << " " << p.second;return os;
}
template <typename T>
ostream &operator<<(ostream &os, const vector<T> &v){
  for (auto it = v.begin();it != v.end();++it){
    if (it != v.begin())os << " ";os << *it;
  }return os;
}
template<typename T, int SIZE>
int array_length(const T (&)[SIZE]){return SIZE;}
template<typename T, int N>
void print(const T (&a)[N], int s = N, int t = -1, bool f = true){
	if(t == -1){rep(i,s){if(i)cout << " ";cout << a[i];}}
	else repi(i,s,t){if(i!=s)cout << " ";cout << a[i];}
	if(f)cout << "\n";
}
template<typename T, int N1, int N2>
void print(const T (&a)[N1][N2], int h = N1, int w = N2){
	rep(i,h){rep(j,w){cout << a[i][j] << " \n"[j==w-1];}}
}

//typedef
typedef pair<int,int> P;
typedef pair<int, P> PP;
typedef pair<P, int> Pi;
typedef vector<int> vi;
typedef deque<int> dq;
const int inf = 1e9+7;
const int INF = 1e18+7;




class UnionFind{
public:
	vector<int> ran, par;
	void init(int n){
		for(int i = 0;i < n;i++){
			par.push_back(i);
			ran.push_back(0);
		}
	}
	
	int find(int x){
		if(par[x] == x)return x;
		return par[x] = find(par[x]);
	}
	
	void unite(int x, int y){
		x = find(par[x]);
		y = find(par[y]);
		if(x == y)return;
		if(ran[x] < ran[y]){
			par[x] = y;
		}else{
			par[y] = x;
			if(par[x] == par[y])ran[x]++;
		}
	}
	
	bool same(int x, int y){
		return find(par[x]) == find(par[y]);
	}
};

template <typename T>class Box;
template <typename T>ostream& operator<<(ostream &, const Box<T> &);
template<typename T>class Box{
public:
	T top;
  T back, left, right, head;
  T bottom;
	T a[6];
	void init(T TOP, T BACK, T LEFT, T RIGHT, T HEAD, T BOTTOM){
		top = TOP;back = BACK;left = LEFT;
		right = RIGHT;head = HEAD;bottom = BOTTOM;
		a[0] = top;a[1] = back;a[2] = left;
		a[3] = right;a[4] = head;a[5] = bottom;
	}
	friend ostream &operator<<<T>(ostream &os, const Box &B);
	bool operator==(const Box& b) const {
		return(top    == b.top   &&
					 back   == b.back  &&
					 left   == b.left  &&
					 right  == b.right &&
					 head   == b.head  &&
					 bottom == b.bottom);
	}
	void rotate(T &d1, T &d2, T &d3, T &d4){
		T tmp = d1;
		d1 = d2;d2 = d3;d3 = d4;
		d4 = tmp;
	}
	void rotate_forward(){rotate(top, head, bottom, back);}
	void rotate_right(){rotate(top, left, bottom, right);}
	void rotate_spin(){rotate(head, right, back, left);}
	friend ostream & operator<< <>(ostream &, const Box<T> & B);
};
template <typename T>
ostream & operator<<(ostream & os, const Box<T> & B){
	os <<  "  " 				<< B.back   << endl;
	os << B.left << " " << B.bottom << " " << B.right << " " << B.top << endl;
	os <<  "  " 				<< B.head   << endl;
	return os;
}

bool same(Box<string> a, Box<string> b){
	rep(i,4){
		a.rotate_forward();
		rep(j,4){
			a.rotate_right();
			rep(k,4){
				a.rotate_spin();
				if(a == b)return true;
			}
		}
	}
	return false;
}

signed main(){
	while(1){
		int n;
		scanf("%lld", &n);
		if(n == 0)break;
		Box<string> B[n];
		UnionFind uf;uf.init(n);
		rep(i,n){
			string str[6];
			rep(j,6)cin >> str[j];
			B[i].init(str[5], str[4], str[3], str[2], str[1], str[0]);
		}
		int ans = 0;
		rep(i,n)rep(j,n){
			if(same(B[i], B[j]))uf.unite(i, j);
		}
		rep(i,n)ans += (uf.find(i) == i);
		printf("%lld\n", n-ans);
	}
	return 0;
}

C++: #include <algorithm>
#include <cctype>
#include <climits>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <functional>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <string>
#include <vector>

using namespace std;

#define reps(i,f,n) for(int i=f; i<int(n); ++i)
#define rep(i,n) reps(i,0,n)

typedef long long ll;
typedef vector<int> vi;
typedef vector<vi> vvi;
typedef pair<int, int> pii;

const int INF = 1001001001;

struct Dice
{
	int data[6];
	void roll(int a, int b, int c, int d)
	{
		int tmp = data[d];
		data[d] = data[c];
		data[c] = data[b];
		data[b] = data[a];
		data[a] = tmp;
	}
	void rotateX(){
		roll(0, 4, 5, 1);
	}
	void rotateY(){
		roll(0, 2, 5, 3);
	}
	void rotateZ(){
		roll(1, 2, 4, 3);
	}
	int hash()
	{
		int ret = INF;
		rep(i, 6){
			rep(j, 4){
				int h = 0;
				rep(k, 6)
					h = h*6 + data[k];
				ret = min(ret, h);
				rotateX();
			}
			i%2 ? rotateY() : rotateZ();
		}
		return ret;
	}
};

int main()
{
	const char* colors[] = {"Cyan", "Yellow", "Red", "Magenta", "Green", "Blue"};
	map<string, int> dict;
	rep(i, 6)
		dict[colors[i]] = i;
	
	int n;
	while(scanf("%d", &n), n){
		int hash[30];
		rep(i, n){
			Dice dice;
			rep(j, 6){
				char str[128];
				scanf("%s", str);
				dice.data[j] = dict[str];
			}
			hash[i] = dice.hash();
		}
		sort(hash, hash+n);
		printf("%d\n", n - (unique(hash, hash+n)-hash));
	}
	return 0;
}