//https://qiita.com/Nabetani/items/1f41e38cb92654ede6d8
//http://gi.ics.nara-wu.ac.jp/~takasu/lecture/programming/H26-gengo1-9.pdf
//https://qiita.com/shun-shun123/items/69af670f0332fa424f6e
//1個前の正面データを保有していたら、次が上面なのか補足可能
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
//#define rep(i, n) for (int i = 0; i < (int)(n); i++)
using std::cin;
using std::cout;
using std::endl;
using std::string;
using std::vector;

/*サイコロのクラス設計
メンバー変数　上面の情報、各面が保有する数、各方向の面;
メンバー関数　数字割り当て、投げ、
*/

//vectorのfindはあるかどうかをイテレータで返すのみ。ポインタがめんどい。
//auto n_array = std::find(Counterclockwise_[m].begin(), Counterclockwise_[m].end(), n);
int index_search(vector<vector<int>> array, int m, int n) //m:上面の目の配列,n:S方向の目 const⇒&にすると引き渡し
{
    int index;
    for (int i = 0; i < 4; i++)
    {
        if (array[m][i] == n)
        {
            index = i;
            return index;
        }
    }
    return -1;
}

//値⇔ラベル変換
int label_search(int array[], int m)
{
    int label;
    for (int i = 0; i < 6; i++)
    {
        if (array[i] == m)
        {
            label = i + 1; //ラベルに対応
            return label;
        }
    }
    return -1;
}

class Dice
{
private:
public:
    int face[6]; //各面のポイント[0:1面,1:2面...]

    int BUsur, //BeforeUpper_1回前の上面の数_後で名前変える
        Usur,  //上面の数、
        Nsur,  //各方向の面の数[0:current,1:previous]
        Ssur,
        Esur,
        Wsur,
        Bsur; //Bottomsur

    string order; //INPUTの2行目

    //問題文はメスサイコロ
    //上面が1~6のときに、周囲の数値を反時計周りに取得してきたもの
    vector<vector<int>> Counterclockwise_;

    Dice(); //(int)にすると怒られ
    void Allocate_num();
    void Infor_upsur(int);
    void Infor_sur();   //これいる？
    void D_throw();     //throwだと何か反応
    void Rsur_search(); //投げた後の右側面を探知_B用
    //void D_consistecy(); //ダイスの同一性チェック_C,D用
};

Dice::Dice() //;を付けない
    : face{0},
      BUsur(1),
      Usur(1),
      Nsur(5),
      Ssur(2),
      Esur(3),
      Wsur(4),
      Bsur(6),

      Counterclockwise_{{2, 3, 5, 4}, //1 S-E-N-Wの順
                        {6, 3, 1, 4}, //2
                        {5, 1, 2, 6}, //3
                        {6, 2, 1, 5}, //4
                        {4, 1, 3, 6}, //5
                        {4, 5, 3, 2}} //6
{
}

//各面の数値割り当て
void Dice::Allocate_num()
{
    for (int i = 0; i < 6; i++)
    {
        //i=0:Up,1:S,2:E,3:W,4:N,5:Bottom    ITP1_11_A の図の値から -1したものに対応
        cin >> face[i]; //input 1行目読み込み
    }
}

//上面の数値を出力
void Dice::Infor_upsur(int x)
{
    if (x == 0)
        cout << face[Usur - 1] << endl;
    else if (x == 1)
        cout << face[BUsur - 1] << endl;
}

//暇あったら作る
void Dice::Infor_sur()
{
}

//投げた後,各面の情報を保有
void Dice::D_throw()
{
    int n = 0;
    cin >> order;

    //最後の文字がnullではない.
    while (order[n] != '\0') //cin>>order && order[n] != '\0'にしてしまうとnullのstringが来るまで読み込み続ける
    {
        BUsur = Usur; //Upper情報の更新
        if (order[n] == 'N')
        {
            //前:後[U:S ,S:B, B:N, N:BU] EとWは保持
            Usur = Ssur;
            Ssur = Bsur;
            Bsur = Nsur;
            Nsur = BUsur;
        }
        else if (order[n] == 'S')
        {
            //前:後[U:N, N:B, B:S, S:BU] E,Wは保持
            Usur = Nsur;
            Nsur = Bsur;
            Bsur = Ssur;
            Ssur = BUsur;
        }
        else if (order[n] == 'E')
        {
            //[U:W, W:B, B:E, E:BU] N,Sは保持
            Usur = Wsur;
            Wsur = Bsur;
            Bsur = Esur;
            Esur = BUsur;
        }
        else if (order[n] == 'W')
        {
            //[U:E, E:B, B:W, W,BU]
            Usur = Esur;
            Esur = Bsur;
            Bsur = Wsur;
            Wsur = BUsur;
        }

        n++;
    }
}

//投げた後の情報のみで、右側面の数値を特定する
void Dice::Rsur_search()
{
    int q;                    //質問数
    int face_S, face_E, m, n; //m:上面,n:側面
    cin >> q;
    int Rsur[q];

    for (int i = 0; i < q; i++)
        Rsur[i] = 0; //Rsur[q] = {0}; だと怒られるかも

    //右側面のラベル導出
    for (int i = 0; i < q; i++)
    {
        cin >> face_S >> face_E;
        //自作関数：値をlabelに変換
        m = label_search(face, face_S);
        n = label_search(face, face_E);
        //自作関数: 配列値=n の時,そのインデックスを持ってくる。ここでは南方向の目のindex
        int n_array = index_search(Counterclockwise_, m - 1, n);

        if (n_array == 3)
            Rsur[i] = Counterclockwise_[m - 1][0];
        else
            Rsur[i] = Counterclockwise_[m - 1][n_array + 1]; //nに対して右隣のindexに格納されているものが答え
    }

    for (int i = 0; i < q; i++)
    {
        //i=0:Up,1:S,2:E,3:W,4:N,5:Bottom    ITP1_11_A の図の値から -1したものに対応
        //呼び出すのは右側面に対応するラベル(ITP1_11_Aを参照)ではなく、face[]
        int ind = Rsur[i] - 1;
        cout << face[ind] << endl;
    }
}

//ダイスの同一性チェック_C,D用
//https://www.sirochro.com/note/cpp-class-object-delivery/
//https://brain.cc.kogakuin.ac.jp/~kanamaru/lecture/C++2/06/06-02.html
/*ポインタでの引き渡し
void D_consistecy(Dice *a, Dice *b) 
{
    cout << a-> face[1];
}
*/

//はじめのプログラムでは、数字の重複を考えていなかったため修正
//突貫工事なので修正したい
int D_consistency(Dice a, Dice b)
{
    //Upper_label_search labelの数を増やさないと行けない
    int upper_label_array[6];
    int cnt = 0;

    for (int i = 0; i < 6; i++)
    {
        if (a.face[0] == b.face[i]) //aの上面に対応する数値が bのどのラベルに位置しているか
        {
            upper_label_array[cnt] = i + 1; //上面のlabelを返す
            cnt++;
        }
    }

    for (int i = 0; i < cnt; i++)
    {
        int label_number_sum = 21; //メッチャ苦し紛れ,底面のlabel値を特定するのに利用
        int upper_label = upper_label_array[i];
        //cout << "上面のラベル:" << upper_label << endl;
        label_number_sum -= upper_label;

        for (int j = 0; j < 4; j++)
        {
            //Around_label_search
            int around_label = a.Counterclockwise_[upper_label - 1][j]; //a. b.どちらでもいい
            //cout << "回りのラベル:" << around_label << endl;

            if (a.face[1] == b.face[around_label - 1]) //ダイスaのlabel2に相当する箇所を検索 , 4 5 3 2
            {
                //cout << "a.face:" << a.face[1] << "b.face:" << b.face[around_label -1]<< endl;
                label_number_sum -= around_label;
                //cout << "labelnumbersum:" << label_number_sum << endl;

                //上面の周囲の値をチェック
                for (int k = 1; k < 4; k++)
                {
                    if (j + k >= 4)
                        around_label = a.Counterclockwise_[upper_label - 1][j + k - 4];
                    else
                        around_label = a.Counterclockwise_[upper_label - 1][j + k];

                    label_number_sum -= around_label;
                    //cout << "around_label" << around_label << endl;
                    //cout << "a.face:" << a.face[a.Counterclockwise_[0][k]-1] << "   b.face:" << b.face[around_label -1] <<endl;
                    //cout << "labelnumbersum:" << label_number_sum << endl;

                    if (a.face[a.Counterclockwise_[0][k] - 1] == b.face[around_label - 1])
                    {
                        if (k == 3 && a.face[5] == b.face[label_number_sum - 1])
                        {
                            //cout << "Yes" << endl;
                            return 0;
                        }
                    }
                    else
                    {
                        break;
                    }
                }
            }
        }
    }

    //cout << "No" << endl;
    return -1;
}

int D_consistency_array(Dice a[],int n)
{
    for (int i = 0; i < n; i++)
        a[i].Allocate_num();

    for (int i = 0; i < n - 1; i++)
    {
        for (int j = i + 1; j < n; j++)
        {
            if (D_consistency(a[i], a[j]) == 0)
            {
                cout << "No" << endl;
                return 0; //-1にするとAOJ側でエラー
            }
        }
    }

    cout << "Yes" << endl;
    return 0;
}

//Allocate_num,error
/*
10_A.cc: In function ‘int main()’:
10_A.cc:49:11: error: request for member ‘Allocate_num’ in ‘first’, which is of non-class type ‘Dice()’
     first.Allocate_num();
*/
//https://blog.amagi.dev/entry/20121130/cpp_create_instance

int main()
{
    int n;
    cin >> n;
    Dice D[n + 1]; //first()にするとエラー

    D_consistency_array(D, n);
}


Measured memory_bytes: 3244