#include<iostream>
#include<cctype>
#include<algorithm>
#include<cstdio>
#include<cstdlib>
#include<vector>
#include<map>
#include<queue>
#include<set>
#include<stack>
#include<cctype>
#include<cstring>
#include<utility>
const int inf=0x7fffffff;
typedef long long int ll;
using namespace std;
const int N=100+5;
char s[100+10];
char ans[][10]={
	"No\n",
	"Yes\n"
};
struct DICE{
	int u,s,e,w,n,d;
	DICE (int u=0,int s=0,int e=0,int w=0,int n=0,int d=0):u(u),s(s),e(e),w(w),n(n),d(d){}
	DICE fW(){
		DICE tmp;
		tmp.s=this->s;
		tmp.n=this->n;
		tmp.e=this->d;
		tmp.w=this->u;
		tmp.u=this->e;
		tmp.d=this->w;
		return tmp;
	}
	DICE fS(){
		DICE tmp;
		tmp.s=this->u;
		tmp.n=this->d;
		tmp.e=this->e;
		tmp.w=this->w;
		tmp.d=this->s;
		tmp.u=this->n;
		return tmp;
	}
	DICE fE(){
		DICE tmp;
		tmp.s=this->s;
		tmp.n=this->n;
		tmp.e=this->u;
		tmp.w=this->d;
		tmp.d=this->e;
		tmp.u=this->w;
		return tmp;
	}
	DICE fN(){
		DICE tmp;
		tmp.s=this->d;
		tmp.n=this->u;
		tmp.e=this->e;
		tmp.w=this->w;
		tmp.d=this->n;
		tmp.u=this->s;
		return tmp;
	}
	int right(int t,int f){
		if(t==this->u)
		{
			if(f==this->s)return this->e;
			else if(f==this->e)return this->n;
			else if(f==this->n)return this->w;
			else if(f==this->w)return this->s;
			else return -1;
		}
		else if(t==this->s){
			DICE tmp=(*this).fN();
			return tmp.right(t,f);
		}
		else if(t==this->e){
			DICE tmp=(*this).fW();
			return tmp.right(t,f);
		}
		else if(t==this->n){
			DICE tmp=(*this).fS();
			return tmp.right(t,f);
		}
		else if(t==this->w){
			DICE tmp=(*this).fE();
			return tmp.right(t,f);
		}
		else if(t==this->d){
			DICE tmp=(*this).fE().fE();
			return tmp.right(t,f);
		}
		else return -1;
		}
};
DICE A[N];
bool check(DICE x,DICE y){
	int ax[]={
		x.s,x.e,x.n,x.w
	};
	int ay[]={
		y.s,y.e,y.n,y.w
	};
	if(x.u==y.u){
		if(x.d==y.d){
			int cnt=0;
			while(cnt<=4){
				while(ax[cnt]!=ay[0]&&cnt<=4)
					cnt++;
				int i=0;
				while(ax[(i+cnt)%4]==ay[i]&&i<=4)
					i++;
				if(i==4)return 1;
				cnt++;
			}
			
		}
	}
	return 0;
}
bool sovle(DICE x,DICE y){
	if(check(x,y))return 1;
	if(check(x.fE(),y))return 1;
	if(check(x.fW(),y))return 1;
	if(check(x.fN(),y))return 1;
	if(check(x.fS(),y))return 1;
	if(check(x.fS().fS(),y))return 1;
	return 0;
}
int main()
{
//#ifdef DEBUG
//	freopen("in", "r", stdin);
////	freopen("out", "w", stdout);
//#endif
	int n;scanf("%d", &n);
	int t=0;
	int a[6];
	bool flag=1;
	for(int i=0;i<6;i++){
		scanf("%d", &a[i]);
	}
	A[0]=DICE(a[0],a[1],a[2],a[3],a[4],a[5]);
	t++;
	while(t<n){
	for(int i=0;i<6;i++){
		scanf("%d", &a[i]);
	}
	A[t]=DICE (a[0],a[1],a[2],a[3],a[4],a[5]);
	for(int i=0;i<t;i++)
	{
		if(sovle(A[i],A[t])){flag=0;
//			cout<<i<<' '<<t<<endl;
		}
	}
	t++;
	}
	printf("%s", ans[flag]);
//	printf("%s", ans[solve(dice,dice2)]);
//	DICE I
//	scanf("%s", s);
//	int len=strlen(s);
//	for(int i=0;i<len;i++){
//		switch(s[i]){
//			case'S':dice=dice.fS();break;
//			case'E':dice=dice.fE();break;
//			case'W':dice=dice.fW();break;
//			case'N':dice=dice.fN();break;
//		}
//	}
//	printf("%d\n", dice.u);
//
	return 0;
}
//aoj1_11_a.cc

//AC
#include<string>
#include<iostream>
using namespace std;


class Dice{
	int dn[6];
	int ori[6];
	int up, front;
	string qu;

public:
	Dice(int d1, int d2, int d3, int d4, int d5, int d6){
		dn[0] = d1;
		dn[1] = d2;
		dn[2] = d3;
		dn[3] = d4;
		dn[4] = d5;
		dn[5] = d6;

		ori[0] = d1;
		ori[1] = d2;
		ori[2] = d3;
		ori[3] = d4;
		ori[4] = d5;
		ori[5] = d6;
	}

	void Result(string m){
		int w;
		qu = m;
		for (int i = 0; i < 6; i++){
			dn[i] = ori[i];
		}

		for (int i = 0; i < qu.size(); i++){
			switch (qu[i]){
			case 'E':
				w = dn[0];
				dn[0] = dn[3];
				dn[3] = dn[5];
				dn[5] = dn[2];
				dn[2] = w;
				break;

			case 'N':
				w = dn[5];
				dn[5] = dn[4];
				dn[4] = dn[0];
				dn[0] = dn[1];
				dn[1] = w;
				break;

			case 'S':
				w = dn[0];
				dn[0] = dn[4];
				dn[4] = dn[5];
				dn[5] = dn[1];
				dn[1] = w;
				break;

			case 'W':
				w = dn[0];
				dn[0] = dn[2];
				dn[2] = dn[5];
				dn[5] = dn[3];
				dn[3] = w;
				break;
			}
		}
	}

	int get0(){
		return dn[0];
	}
	int get1(){
		return dn[1];
	}
	int get2(){
		return dn[2];
	}
	int get3(){
		return dn[3];
	}
	int get4(){
		return dn[4];
	}
	int get5(){
		return dn[5];
	}
};

int main()
{
	int n;
	int count = 0;
	int ndice[100][6];
	string flag = "Yes";
	string quu[23] = { "WSE", "ESW", "WSSE", "SWW", "EN", "WN", "N", "SW", "W", "SSW",
		"NW", "SE", "E", "SSE", "NE", "S", "WS", "ES", "WWS", "WW", "SWS", "SES", "SS" };

	cin >> n;
	for (int i = 0; i < n; i++){          // n個のサイコロの入力
		for (int j = 0; j < 6; j++){
			cin >> ndice[i][j];
		}	
	}

	for (int i = 0; i < n; i++){                // サイコロを比べる
		for (int j = i + 1; j < n; j++){                      // Dice a()にサイコロを登録し、順次比較していく
			Dice a(ndice[j][0], ndice[j][1], ndice[j][2], 
				ndice[j][3], ndice[j][4], ndice[j][5]);

			for (int k = 0; k < 6; k++){            // 転がすこともなく同じサイコロかどうか
				if (ndice[i][k] == ndice[j][k]){
					count = count + 1;
				}
			}
			if (count == 6){     // 6面全てが一致すれば、同じサイコロ
				flag = "No";
			}
			count = 0;

			for (int l = 0; l < 23; l++){     // サイコロが取り得る全ての可能性(面の上下左右)を比較していく
				a.Result(quu[l]);

				ndice[j][0] = a.get0();
				ndice[j][1] = a.get1();
				ndice[j][2] = a.get2();
				ndice[j][3] = a.get3();
				ndice[j][4] = a.get4();
				ndice[j][5] = a.get5();

				for (int k = 0; k < 6; k++){               // 6面全てが一致すれば、同じサイコロ
					if (ndice[i][k] == ndice[j][k]){
						count = count + 1;
					}
				}
				if (count == 6){
					flag = "No";
				}
				count = 0;
			}
		}
	}
	cout << flag << endl;
	
	return 0;
}
