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 <iostream>
#include <string>
#define rep2(x,from,to) for(int x=(from);(x)<(to);(x)++)
#define rep(x,to) rep2(x,0,to)
using namespace std;
string color[6] =  {"Cyan", "Yellow", "Red", "Magenta", "Green", "Blue"};
int* south(int c[6]) {
	int buf = c[0];
	c[0] = c[1];
	c[1] = c[5];
	c[5] = c[4];
	c[4] = buf;
	return c;
}
int* east(int c[6]) {
	int buf = c[0];
	c[0] = c[2];
	c[2] = c[5];
	c[5] = c[3];
	c[3] = buf;
	return c;
}
int* round(int c[6]) {
	int buf = c[1];
	c[1] = c[2];
	c[2] = c[4];
	c[4] = c[3];
	c[3] = buf;
	return c;
}
bool check(int d1[6], int d2[6]) {
	rep(i,6) {
		if(i%2)d1 = south(d1);
		else d1 = east(d1);
		rep(j,4) {	
			d1 = round(d1);
			bool f = 1;
			rep(k,6) {
				if(d1[k] != d2[k]) {
					f = 0;
					break;
				}
			}	
			if(f) return true;
		}
	}
	return false;
}
int main(){
	int n, d[30][6] = {};
	string s;
	while(cin >> n, n) {
		rep(i,n) {
			rep(j,6) {
				cin >> s;
				rep(k,6) {
					if(color[k] == s) d[i][j] = k;
				}
			}
		}
		int a[30] = {};
		rep(i,n) {
			rep2(j,i+1,n) {
				if(check(d[i],d[j])) {
					a[i]++, a[j]++;
				}
			}
		}
		int ret = 0;
		rep(i,30) {
			if(a[i]) ret++;
		}
		if(ret) ret--;
		cout << ret << endl;
	}
	return 0;
}

C++: #include <iostream>
#include <cstdio>
#include <vector>
#include <algorithm>
#include <complex>
#include <cstring>
#include <cstdlib>
#include <string>
#include <cmath>
#include <queue>
#include <map>
#include <set>
using namespace std;

#define REP(i,n) for(int i=0;i<(int)n;++i)
#define FOR(i,c) for(__typeof((c).begin())i=(c).begin();i!=(c).end();++i)
#define ALL(c) (c).begin(), (c).end()
const int INF = 1<<30;

struct UnionFind {
  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;
  }
  bool findSet(int x, int y) {
    return root(x) == root(y);
  }
  int root(int x) {
    return data[x] < 0 ? x : data[x] = root(data[x]);
  }
  int size(int x) {
    return -data[root(x)];
  }
};

bool eq(string *s1, string *s2) {
  REP(k,4) {
    bool f = true;
    REP(i,4) {
      if (s1[i] != s2[(i+k)%4])
        f = false;
    }
    if (f)
      return true;
  }
  return false;
}

int main() {
  int hoge[6][4] = {{1,3,4,2},{0,2,5,3},{0,4,5,1}
                    ,{0,1,5,4},{0,3,5,2},{1,2,4,3}};
  int n;
  while(cin >> n, n) {
    string side[n][4];
    REP(iii,n) {
      string s[6];
      int p;
      REP(i,6) {
        cin >> s[i];
        if (s[i] == "Red")
          p = i;
      }
      REP(i,4) {
        side[iii][i] = s[hoge[p][i]];
//        cout << side[iii][i] << " ";
      }
      //    cout << endl;
    }
    UnionFind u(n);
    REP(i,n-1) {
      for (int j=i+1; j<n; ++j) {
        if (eq(side[i], side[j])) {
          u.unionSet(i,j);
        }
      }
    }
    set<int> se;
    REP(i,n) {
      se.insert(u.root(i));
    }
    cout << n-se.size() << endl;
  }
}

C++: #include<iostream>
#include<string>

using namespace std;

int main()
{
	while(true)
	{
		int n = 0;
		string color[31][6];

		cin >> n;

		if(n == 0)
		{
			return false;
		}

		for(int i = 0; i < n; i++)
		{
			for(int j = 0; j < 6; j++)
			{
				cin >> color[i][j];
			}
		}

		int count = 0;

		for(int i = 0; i < n; i++)
		{
			for(int j = i; j < n; j++)
			{
				if(i != j)
				{
					bool flag = true;

					for(int k = 0; k < 6; k++)
					{
						if(color[i][k] != color[j][k])
						{
							flag = false;
						}
					}

					if(flag)
					{
						count++;
					}
				}
			}
		}

		cout << count << endl;	
	}
}

C++: #include<iostream>
#include<string>
#include<vector>

#define REP(i, b, n) for(int i = b; i<(int)n; i++)
#define rep(i, n) REP(i, 0, n)

using namespace std;

enum{TOP=0,FRONT,RIGHT,LEFT,BACK,BOTTOM}; 
#define rotate_swap(x,a,b,c,d) swap(x.m[a],x.m[b]);swap(x.m[b],x.m[c]);swap(x.m[c],x.m[d]);
  
const int dy[] = {-1, 0, 1, 0};
const int dx[] = {0, 1, 0, -1};
 
class Dice{
public:
  int y, x;
  string m[6];
  Dice(){
    y = x = 0;
  }
  bool operator<(const Dice &a)const{
    rep(i,6)if (m[i] != a.m[i])return m[i] < a.m[i];
    return false;
  }
  bool operator==(const Dice &a)const{
    rep(i,6)if (m[i] != a.m[i])return false;
    return true;
  }
};
 
void rotate_r(Dice &x){
  x.x++;
  rotate_swap(x,TOP,LEFT,BOTTOM,RIGHT);
}
  
void rotate_l(Dice &x){
  x.x--;
  rotate_swap(x,TOP,RIGHT,BOTTOM,LEFT);
}
  
void rotate_f(Dice &x){
  x.y--;
  rotate_swap(x,TOP,BACK,BOTTOM,FRONT);
}
  
void rotate_b(Dice &x){
  x.y++;
  rotate_swap(x,TOP,FRONT,BOTTOM,BACK);
}
  
void rotate_cw(Dice &x){
  rotate_swap(x,BACK,LEFT,FRONT,RIGHT);
}
  
void rotate_ccw(Dice &x){
  rotate_swap(x,BACK,RIGHT,FRONT,LEFT);
}
  
vector<Dice> generate_all(Dice x){
  vector<Dice> res;
  rep(i,6){
    rep(j,4){
      res.push_back(x);
      rotate_cw(x);
    }
    if (i%2 == 0)rotate_r(x);
    else rotate_f(x);
  }
  return res;
}

int main() {
  while (true) {
    int n;
    cin >> n; 
    if (n == 0) break;
    vector<vector<Dice> > v;
    rep (i, n) {
      Dice dice;
      cin >> dice.m[TOP];
      cin >> dice.m[FRONT];
      cin >> dice.m[RIGHT];
      cin >> dice.m[LEFT];
      cin >> dice.m[BACK];
      cin >> dice.m[BOTTOM];
      v.push_back(generate_all(dice));
    }
    int res = 0;
    rep (i, n) rep (j, i) {
      rep (ii, 24) rep (jj, 24) {
	if (v[i][ii] == v[j][jj]) {
	  ++res;
	  goto next;
	}
      }
    next:;
    }
    cout << res << endl;
  }
  return 0;
}

C++: #include<iostream>
using namespace std;

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

string rot1( string s ){
	string res = s;
	res[0] = s[1];
	res[1] = s[5];
	res[5] = s[4];
	res[4] = s[0];
	return res;
}

string rot2( string s ){
	string res = s;
	res[0] = s[2];
	res[2] = s[5];
	res[5] = s[3];
	res[3] = s[0];
	return res;
}

string rot3( string s ){
	string res = s;
	res[1] = s[2];
	res[2] = s[4];
	res[4] = s[3];
	res[3] = s[1];
	return res;
}

int main(){
	int n;
	while( cin >> n, n ){
		string obj[30];
		rep(i,n){
			rep(j,6){
				string in;
				cin >> in;
				obj[i] += in[0];
			}
		}
		int cnt = 0;
		rep(i,n){
			if( obj[i] == "" ) continue;
			for(int j=i+1; j<n; j++){
				if( obj[j] == "" ) continue;
				bool found = false;
				rep(k,6){
					rep(l,4){
						if( obj[i] == obj[j] ){
							found = true;
						}
						obj[j] = rot3(obj[j]);
					}
					if(k%2)	obj[j] = rot1(obj[j]);
					else	obj[j] = rot2(obj[j]);
				}
				if(found){
					cnt++;
					obj[j] = "";
				}
			}
		}
		cout << cnt << endl;
	}
	return 0;
}