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<algorithm>
#include<iostream>
#include<string>
#include<set>
using namespace std;
string face[6];
int n;
int main(){
  while(cin >> n, n){
    set<string> ans;
    for(int j = 0;j < n;j++){
      cin >> face[0] >> face[1] >> face[2] >> face[3] >> face[4] >> face[5];
      string p;
      for(int i = 0;i < 4;i++){
	if(face[0] == "Blue")break;
	swap(face[0], face[1]);
	swap(face[1], face[5]);
	swap(face[5], face[4]);
      }
      for(int i = 0;i < 4;i++){
	if(face[0] == "Blue")break;
	swap(face[0], face[2]);
	swap(face[2], face[5]);
	swap(face[5], face[3]);
      }
      for(int i = 1;i < 5;i++){
	if(i == 1)p = face[i];
	p = min(p, face[i]);
      }
      while(face[1] != p){
	swap(face[1], face[4]);
	swap(face[3], face[4]);
	swap(face[2], face[3]);
      }
      string res ="";
      for(int i = 0;i < 6;i++){
	res += face[i][0];
      }
      ans.insert(res);
    }
    cout << n - ans.size() << endl;
  }
  return 0;
}

C++: bool debug=false;
#include <vector>
#include <iostream>
#include <map>
using namespace std;
#define PB push_back
map<string,int> m;
int t=1;
struct cube{
	int s[6];
	void in(){
		string temp;
		for(int i=0;i<6;i++){
			cin>>temp;
			if(m.find(temp)==m.end())s[i]=m[temp]=t++;
			else s[i]=m[temp];
		}
	}
	void out(){
		if(debug){
			for(int i=0;i<6;i++)cout<<s[i]<<" ";
			cout<<endl;
		}
	}
	bool operator ==(const cube &a){for(int i=0;i<6;i++)if(s[i]!=a.s[i])return false;return true;}
};
cube Arotate(cube c){
	cube temp;
	temp.s[0]=c.s[3];
	temp.s[1]=c.s[1];
	temp.s[2]=c.s[0];
	temp.s[3]=c.s[5];
	temp.s[4]=c.s[4];
	temp.s[5]=c.s[2];
	if(debug)temp.out();
	return temp;
}
cube Brotate(cube c){
	cube temp;
	temp.s[0]=c.s[0];
	temp.s[1]=c.s[3];
	temp.s[2]=c.s[1];
	temp.s[3]=c.s[4];
	temp.s[4]=c.s[2];
	temp.s[5]=c.s[5];
	if(debug)temp.out();
	return temp;
}
cube Crotate(cube c){
	cube temp;	
	temp.s[0]=c.s[1];
	temp.s[1]=c.s[5];
	temp.s[2]=c.s[2];
	temp.s[3]=c.s[3];
	temp.s[4]=c.s[0];
	temp.s[5]=c.s[4];
	if(debug)temp.out();
	return temp;
}
void solve(int n){
	bool f;
	vector<cube> v;
	cube temp;
	for(int y=0;y<n;y++){
		temp.in();
		if(v.empty())v.PB(temp);
		else{
			f=true;
			for(int i=0;i<4;i++){
				temp=Arotate(temp);
				for(int j=0;j<4;j++){
					temp=Brotate(temp);
					for(int k=0;k<4;k++){
						temp=Crotate(temp);
						for(cube x:v)if(temp==x)f=false;
					}
				}
			}
			if(f)v.PB(temp);
			if(debug)cout<<"done"<<endl;
		}
	}
	cout<<n-(int)v.size()<<endl;
}
int main(){
	int n;
	while(true){
		cin>>n;
		if(n==0)break;
		solve(n);
	}
}

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

struct Dice {
	vector<int> val;
	Dice(){ val.resize(6); }
	bool operator == (const Dice &t) const {
		return val == t.val;
	}
	bool operator != (const Dice &t) const {
		return val != t.val;
	}
	bool operator < (const Dice &t) const {
		return val < t.val;
	}
	void rotate_right(){
		int tmp = val[1];
		val[1] = val[2];
		val[2] = val[4];
		val[4] = val[3];
		val[3] = tmp;
	}
	void roll_front(){
		int tmp = val[0];
		val[0] = val[1];
		val[1] = val[5];
		val[5] = val[4];
		val[4] = tmp;
	}
	void roll_right(){
		int tmp = val[0];
		val[0] = val[3];
		val[3] = val[5];
		val[5] = val[2];
		val[2] = tmp;
	}
	vector<Dice> all_pattern(){
		vector<Dice> res;
		Dice d = *this;
		for (int i = 0; i < 6; i++){
			for (int j = 0; j < 4; j++){
				res.push_back(d);
				d.rotate_right();
			}
			if (i == 0) d.roll_front();
			else if (i < 5) d.roll_right();
			else d.roll_front();
		}
		return res;
	}
};

struct UnionFind {
	vector<int> parent;
	
	UnionFind(int n){
		parent.resize(n);
		for (int i = 0; i < n; i++){
			parent[i] = i;
		}
	}
	
	int find(int x){
		if (parent[x] == x) return x;
		return parent[x] = find(parent[x]);
	}
	
	bool same(int x, int y){
		return find(x) == find(y);
	}
	
	bool unite(int x, int y){
		x = find(x);
		y = find(y);
		if (x == y) return false;
		parent[x] = y;
	}
};

map<string, int> ctoi;
int n;
vector<Dice> dices;

bool check(const vector<Dice> &A, const vector<Dice> &B)
{
	for (int i = 0; i < A.size(); i++){
		for (int j = 0; j < B.size(); j++){
			if (A[i] == B[j]) return true;
		}
	}
	return false;
}

void solve()
{
	vector<vector<Dice> > pats;
	UnionFind uf(n);
	
	for (int i = 0; i < n; i++){
		pats.push_back(dices[i].all_pattern());
	}
	
	int res = 0;
	
	for (int i = 0; i < n; i++){
		for (int j = i + 1; j < n; j++){
			vector<Dice> &A = pats[i];
			vector<Dice> &B = pats[j];
			if (!uf.same(i, j)){
				if (check(A, B)){
					uf.unite(i, j);
					res++;
					continue;
				};
			}
		}
	}
	
	printf("%d\n", res);
}

int main()
{
	ctoi["Red"] = 0;
	ctoi["Yellow"] = 1;
	ctoi["Blue"] = 2;
	ctoi["Magenta"] = 3;
	ctoi["Green"] = 4;
	ctoi["Cyan"] = 5;
	
	while (scanf("%d", &n), n){
		dices.clear();
		for (int i = 0; i < n; i++){
			Dice d;
			for (int j = 0; j < 6; j++){
				string str;
				cin >> str;
				d.val[j] = ctoi[str];
			}
			dices.push_back(d);
		}
		solve();
	}
	
	return 0;
}