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<algorithm>
#include<set>
#include<vector>
#include<cstdio>

#define REP(i,s,n) for(int i=s;i<n;i++)
#define rep(i,n) REP(i,0,n)
#define inf (1<<29)

using namespace std;

enum FACE { TOP, BOTTOM, FRONT, BACK, LEFT, RIGHT };
template <class T>
class dice {
public:
  dice() {
    id[TOP] = 0; id[FRONT] = 1; id[LEFT] = 2;
    id[RIGHT] = 3; id[BACK] = 4; id[BOTTOM] = 5;
  }
  T& operator[] (FACE f) { return var[id[f]]; }
  const T& operator[] (FACE f) const { return var[id[f]]; }
  bool operator==(const dice<T>& b) const {
    const dice<T> &a = *this;
    return a[TOP] == b[TOP] && a[BOTTOM] == b[BOTTOM] &&
      a[FRONT] == b[FRONT] && a[BACK] == b[BACK] &&
      a[LEFT] == b[LEFT] && a[RIGHT] == b[RIGHT];
  }
  void roll_x() { roll(TOP, BACK, BOTTOM, FRONT); }
  void roll_y() { roll(TOP, LEFT, BOTTOM, RIGHT); }
  void roll_z() { roll(FRONT, RIGHT, BACK, LEFT); }
  vector<dice> all_rolls() {
    vector<dice> ret;
    for (int k = 0; k < 6; (k&1?roll_y():roll_x()),++k)
      for (int i = 0; i < 4; roll_z(), ++i)
        ret.push_back(*this);
    return ret;
  }
  bool equivalent_to(const dice& di) {
    for (int k = 0; k < 6; (k&1?roll_y():roll_x()),++k)
      for (int i = 0; i < 4; roll_z(), ++i)
        if (*this == di) return true;
    return false;
  }
private:
  void roll(FACE a, FACE b, FACE c, FACE d) {
    T tmp = id[a];
    id[a] = id[b]; id[b] = id[c];
    id[c] = id[d]; id[d] = tmp;
  }
  T var[6];
  int id[6];
};

FACE face[] = {TOP,FRONT,RIGHT,LEFT,BACK,BOTTOM};

class UnionFind
{
public:
  int par[40];

  void init(int n){ rep(i,n)par[i] = i; }

  int find(int x)
  {
    if(x == par[x])return x;
    return par[x] = find(par[x]);
  }

  void unit(int x,int y)
  {
    x = find(x), y = find(y);
    if(x != y)par[x] = y;
    find(x),find(y);
  }

};

int main()
{
  int n;
  while(cin >> n,n)
    {
      dice<char> dices[n];
      string fc;
      rep(i,n)rep(j,6)
	{
	  cin >> fc;
	  dices[i][face[j]] = fc[0];
	}
      

      UnionFind uf;
      uf.init(n);
      rep(i,n)REP(j,i+1,n)
	if(dices[i].equivalent_to(dices[j]))uf.unit(i,j);

      set<int> ans;
      rep(i,n)ans.insert(uf.find(i));

      cout << n - ans.size() << endl;

    }
  return 0;
}

C++: #include <stdio.h>

int translate(char Head){
	switch(Head){
	case 'R':return 0;
	case 'Y':return 1;
	case 'B':return 2;
	case 'M':return 3;
	case 'G':return 4;
	case 'C':return 5;
	}
	return -1; //must not reach here
}

class Dice{
public:
	Dice(){
		num_of_data = 0;
	};

	void roll(char dst){
		switch(dst){
		case 'E':
			setNumber(number[3],number[1],number[0],number[5],number[4],number[2]);
			break;
		case 'N':
			setNumber(number[1],number[5],number[2],number[3],number[0],number[4]);
			break;
		case 'S':
			setNumber(number[4],number[0],number[2],number[3],number[5],number[1]);
			break;
		case 'W':
			setNumber(number[2],number[1],number[5],number[0],number[4],number[3]);
			break;
		}
	};

	bool isNewPattern(int inputed[]){
		char order[25] = "NNNNWNNNWNNNENNNENNNWNNN";

		for(int i = 0; i < num_of_data; i++){
			for(int k = 0; k < 6; k++)number[k] = data_bank[i][k];
			for(int k = 0; k < 24; k++){
				roll(order[k]);
				for(int j = 0; j < 6; j++){
					if(inputed[j] != number[j])
						break;
					if(j == 5)
						return false;
				}
			}
		}
		return true;
	}

	void init(){
		num_of_data = 0;
	}

	int getNumOfData(){
		return num_of_data;
	}

	void addData(int table[6]){
		data_bank[num_of_data][0] = table[0];
		data_bank[num_of_data][1] = table[1];
		data_bank[num_of_data][2] = table[2];
		data_bank[num_of_data][3] = table[3];
		data_bank[num_of_data][4] = table[4];
		data_bank[num_of_data][5] = table[5];
		num_of_data++;
	}

private:

	void setNumber(int n0,int n1,int n2,int n3,int n4,int n5){
		number[0] = n0;
		number[1] = n1;
		number[2] = n2;
		number[3] = n3;
		number[4] = n4;
		number[5] = n5;
	}
private:
	int number[6];
	int data_bank[30][6];
	int num_of_data;
};

int main(){
	int n,tmp[6];
	char c1[10],c2[10],c3[10],c4[10],c5[10],c6[10];
	Dice dice;

	while(true){
		scanf("%d",&n);
		if(n == 0)break;

		dice.init();

		for(int i = 0; i < n; i++){
			scanf("%s %s %s %s %s %s",c1,c2,c3,c4,c5,c6);
			tmp[0] = translate(c1[0]);
			tmp[1] = translate(c2[0]);
			tmp[2] = translate(c3[0]);
			tmp[3] = translate(c4[0]);
			tmp[4] = translate(c5[0]);
			tmp[5] = translate(c6[0]);

			if(dice.isNewPattern(tmp)){
				dice.addData(tmp);
			}
		}
		printf("%d\n",n-dice.getNumOfData());

	}
}

C++: #include <cstdio>
#include <cstring>
#include <algorithm>
#include <string>
#include <cmath>
#include <stack>
#include <vector>
#include <map>
#include <set>
#include <queue>
#include <list>
#include <iostream>
#include <sstream>
#include <climits>
#include <cfloat>
#include <complex>

using namespace std;

int main()
{
	char* color = "RYBMGC";
	int n;
	while (scanf("%d", &n), n)
	{
		int ans = 0;

		set<int> used;
		while (n--)
		{
			int c[6];
			char buf[16];
			int fixed;
			for (int i = 0; i < 6; ++i)
			{
				scanf(" %s", buf);
				int j;
				for (j = 0; color[j] != *buf; ++j)
					;
				c[i] = j;
				if (j == 0)
					fixed = i;
			}
			int r[][4] = { 
				{ 1, 2, 4, 3 },
				{ 5, 2, 0, 3 },
				{ 0, 1, 5, 4 },
				{ 0, 4, 5, 1 },
				{ 0, 2, 5, 3 },
				{ 2, 1, 3, 4 }
			};
			int rota[4];
			for (int i = 0; i < 4; ++i)
				rota[i] = r[fixed][i];

			bool u = false;
			for (int i = 0; i < 3; ++i)
			{
				int s = 0;
				for (int j = 0; j < 4; ++j)
					s = s*10 + rota[(i+j) % 4];
				if (used.count(s))
				{
					++ans;
					break;
				}
				else
					used.insert(s);
			}
		}
		printf("%d\n", ans);
	}

	return 0;
}