//============================================================================
//dice1
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>

//----------------------------------------------------------------------------
enum {pos1, pos2, pos3, pos4, pos5, pos6, posEND};
enum {posT, posS, posE, posW, posN, posB};
//----------------------------------------------------------------------------
typedef struct{
    int Dice[posEND];
    //int E;
    //int W;
    //int S;
    //int T;
    //int B;
}TCycoro;
//----------------------------------------------------------------------------
char Cmd[101];
//----------------------------------------------------------------------------
void CyRot(TCycoro *cyc, char dir)
{
    int S, cometop, betop;

    switch(dir){
        case 'N': cometop=posN, betop=posS; break;
        case 'E': cometop=posE, betop=posW; break;
        case 'W': cometop=posW, betop=posE; break;
        case 'S': cometop=posS, betop=posN; break;
        default: return;
    }
    S=cyc->Dice[cometop];
      cyc->Dice[cometop] = cyc->Dice[posT];
      cyc->Dice[posT]    = cyc->Dice[betop];
      cyc->Dice[betop]   = cyc->Dice[posB];
      cyc->Dice[posB]=S;
}
//----------------------------------------------------------------------------
void CyRoll(TCycoro *cyc, char dir)
{
    int S;

    if (dir){//left
      S=cyc->Dice[posN];
        cyc->Dice[posN] = cyc->Dice[posE];
        cyc->Dice[posE] = cyc->Dice[posS];
        cyc->Dice[posS] = cyc->Dice[posW];
        cyc->Dice[posW]=S;
    }else{
      S=cyc->Dice[posN];
        cyc->Dice[posN] = cyc->Dice[posW];
        cyc->Dice[posW] = cyc->Dice[posS];
        cyc->Dice[posS] = cyc->Dice[posE];
        cyc->Dice[posE]=S;
    }
}
//----------------------------------------------------------------------------
int fortop(TCycoro *cyc, int pos)
{
    int i;

    for (i=0; i<posEND; i++)
        if (cyc->Dice[i]==pos)
            break;
    if (i==posEND)
        return 0;
    switch(i){
        case posN: CyRot(cyc, 'S'); break;
        case posE: CyRot(cyc, 'W'); break;
        case posW: CyRot(cyc, 'E'); break;
        case posS: CyRot(cyc, 'N'); break;
        case posB: CyRot(cyc, 'S'); CyRot(cyc, 'S'); break;
    }
    return 1;
}
//----------------------------------------------------------------------------
int topval(TCycoro *cyc)
{
    int i,j,k,l,S,value[posEND],cmp[posEND];

    memcpy(&value, &cyc->Dice, sizeof(value));
    /*for (k=0, l=posEND; k<posEND-1; k++, l--)
    for (i=0,j=1; j<l; i++, j++){
        if (value[i]>value[j]){
            S=value[i];
            value[i]=value[j];
            value[j]=S;
        }
	}*/
    //for (i=0; i<posEND; i++)
    //    printf("%d: %d, %d\n", i, cyc->Dice[i], value[i]);
    memset(&cmp, 0, sizeof(cmp));
    for (i=0; i<posEND; i++)
    for (j=0; j<posEND; j++){
        if (value[i]==value[j])
            cmp[i]++;
    }
    //for (i=0; i<posEND; i++)
    //    printf("%d: val %d, %d\n", i, value[i], cmp[i]);
    for (i=0; i<posEND; i++)
        if (cmp[i]==1)
            return value[i];
    return *value;
}
//----------------------------------------------------------------------------
void prndice(TCycoro *cyc, char dir)
{
    printf("dir:%c, N=%d, E=%d, W=%d, S=%d, T=%d, B=%d\n", dir,
            cyc->Dice[posN], cyc->Dice[posE], cyc->Dice[posW],
            cyc->Dice[posS], cyc->Dice[posT], cyc->Dice[posB]);
}
//----------------------------------------------------------------------------
int rgtside(int t, int f)
{
    switch(t){
        case pos1:
            switch(f){
                case pos2: return pos3;
                case pos3: return pos5;
                case pos5: return pos4;
                case pos4: return pos2;
            }
            break;
        case pos2:
            switch(f){
                case pos1: return pos4;
                case pos3: return pos1;
                case pos4: return pos6;
                case pos6: return pos3;
            }
            break;
        case pos3:
            switch(f){
                case pos1: return pos2;
                case pos2: return pos6;
                case pos5: return pos1;
                case pos6: return pos5;
            }
            break;
        case pos4:
            switch(f){
                case pos1: return pos5;
                case pos2: return pos1;
                case pos5: return pos6;
                case pos6: return pos2;
            }
            break;
        case pos5:
            switch(f){
                case pos1: return pos3;
                case pos3: return pos6;
                case pos4: return pos1;
                case pos6: return pos4;
            }
            break;
        case pos6:
            switch(f){
                case pos2: return pos4;
                case pos3: return pos2;
                case pos4: return pos5;
                case pos5: return pos3;
            }
            break;
    }
    return -1;
}
//----------------------------------------------------------------------------
void rotato(int *ary)
{
    int i,n;

    for (i=0, n=*ary; i<posEND-1; i++)
        ary[i]=ary[i+1];
    ary[i]=n;
}
//----------------------------------------------------------------------------
void dice1(void)
{
    int i,cyval[posEND]; TCycoro Cyc; 

    for (i=0; i<posEND; i++)
        Cyc.Dice[i]=i;
    for (i=0; i<posEND; i++)
        scanf("%d", &cyval[i]);
    scanf("%s",Cmd);
    for (i=0; Cmd[i]; i++){
        CyRot(&Cyc, Cmd[i]);
        //printf("dir: %c, top: %d(%d)\n", Cmd[i], cyval[Cyc.T], Cyc.T+1);
        //prndice(&Cyc, Cmd[i]);
    }
    printf("%d\n", cyval[Cyc.Dice[posT]]);
}
//----------------------------------------------------------------------------
int dice2()
{
    int i,n,t,f,rgt, *top,*frn, cyval[posEND];

    for (i=0; i<posEND; i++)
        scanf("%d", &cyval[i]);
    scanf("%d",&n);
    top=malloc(n*sizeof(int));
    frn=malloc(n*sizeof(int));
    for (i=0; i<n; i++)
	    scanf("%d %d", &top[i], &frn[i]);
    //for (i=0; i<n; i++)
	//    printf("%d:%d %d\n", i, top[i], frn[i]);
    for (i=0; i<n; i++){
        for (t=0; cyval[t]!=top[i]; t++);
        for (f=0; cyval[f]!=frn[i]; f++);
        rgt=rgtside(t, f);
        //printf("t:%d, f:%d, %d\n", t, f, cyval[rgt]);
        printf("%d\n", cyval[rgt]);
    }
    free(top);
    free(frn);
    //printf("%d\n", rgt);
    return 0;
}
//----------------------------------------------------------------------------
int CycCmp(TCycoro *Cy1, TCycoro *Cy2, int top)
{
    int i;

    if (!fortop(Cy2, top))
        return 0;
    for (i=0; i<4; i++){
        if (!memcmp(Cy1, Cy2, sizeof(TCycoro)))
            return 1;
        CyRoll(Cy2, 0);
    }
    return 0;
}
//----------------------------------------------------------------------------
void dice3(void)
{
    int i,res; TCycoro Cyc1,Cyc2;

    for (i=res=0; i<posEND; i++)
        scanf("%d", &Cyc1.Dice[i]);
    for (i=0; i<posEND; i++)
        scanf("%d", &Cyc2.Dice[i]);
    i=topval(&Cyc1);
    fortop(&Cyc1, i);
    //printf("Top value %d\n",i);
    if (fortop(&Cyc2, i)){
        //prndice(&Cyc1, '1');
        for (i=0; i<4; i++){
            //prndice(&Cyc2, '2');
            if (!memcmp(&Cyc1, &Cyc2, sizeof(TCycoro)))
                res=1;
            CyRoll(&Cyc2, 0);
        }
    }
    printf("%s\n", (res)?"Yes":"No");
}
//----------------------------------------------------------------------------
void dice4()
{
    int i,j,n,top,res; TCycoro *Cyc;

    scanf("%d",&n);
    Cyc=malloc(n*sizeof(TCycoro));
    for (i=0; i<n; i++)
    for (j=0; j<posEND; j++)
        scanf("%d", &Cyc[i].Dice[j]);
    for (i=res=0; i<n-1; i++){
        top=topval(&Cyc[i]);
    	fortop(&Cyc[i], top);
        for (j=i+1; j<n; j++){
            if (CycCmp(&Cyc[i], &Cyc[j], top))
                res++;
        }
    }
    printf("%s\n", (!res)?"Yes":"No");
}
//----------------------------------------------------------------------------
int main()
{
    dice4();
    return 0;
}
//----------------------------------------------------------------------------

Measured memory_bytes: 600