#include<cstdio>
#include<algorithm>
#include<vector>
#include<string>
#include<iostream>
#include<queue>
#include<map>
#include<set>
#include<complex>
#include<stack>
#include<cmath>
  
using namespace std;
  
#define reps(i,f,n) for(int i=f;i<n;i++)
#define repc(i,n) for(char i=0;i<n;i++)
#define rep(i,n) reps(i,0,n)

#define pb push_back

#define X real()
#define Y imag()

const int N = 10;

class P{
	public:
	int x,y,kind;
	P(int x,int y,int kind):x(x),y(y),kind(kind){}
};


class B{
	public:
	char board[N][N];
	B(){rep(i,N)rep(j,N)board[i][j]=0;}
	
	B copy(){
		B b;
		rep(i,N)rep(j,N)b.board[i][j]=board[i][j];
		return b;
	}
};

char color[3][5][5]={
	{
		{0,0,0,0,0},
		{0,0,1,0,0},
		{0,1,1,1,0},
		{0,0,1,0,0},
		{0,0,0,0,0},
	},
	{
		{0,0,0,0,0},
		{0,1,1,1,0},
		{0,1,1,1,0},
		{0,1,1,1,0},
		{0,0,0,0,0},
	},
	{
		{0,0,1,0,0},
		{0,1,1,1,0},
		{1,1,1,1,1},
		{0,1,1,1,0},
		{0,0,1,0,0},
	}
};

bool canput(B& b, P p){
	
	char a = 5;
	char c = 2;
	char d = 0;
	
	if(p.kind!=2){
		a=3;
		c=1;
		d=1;
	}
	
	bool flg = true;
	repc(dy,a){
		repc(dx,a){
			char nx = p.x+dx-c;
			char ny = p.y+dy-c;
			
			if(nx<0 || ny<0 || nx>=N || ny>=N)continue;
			
			if(color[p.kind][dy+d][dx+d]==1 && b.board[ny][nx]==0)flg=false;
		}
	}
	
	return flg;
}

void put(B& b, P p,int rev=1){
	
	char a = 5;
	char c = 2;
	char d = 0;
	
	if(p.kind!=2){
		a=3;
		d=1;
		c=1;
	}
	repc(dy,a){
		repc(dx,a){
			char nx = p.x+dx-c;
			char ny = p.y+dy-c;
			
			if(nx<0 || ny<0 || nx>=N || ny>=N)continue;
			
			if(color[p.kind][dy+d][dx+d]==1){
				b.board[ny][nx]-=rev;
			}
		}
	}
}

vector<P> getcand(B& b){
	vector<P> ret;
	rep(y,N){
		rep(x,N){
			rep(k,3){
				if(canput(b, P(x,y,k))){
					ret.pb(P(x,y,k));
				}
			}
		}
	}
	return ret;
}

bool canuse(B& b, P p){
	put(b,p);
	
	
	vector<P> cand2 = getcand(b);
	bool ok = true;
	
	rep(i,N)rep(j,N)if(b.board[i][j]<0)ok=false;
	rep(i,cand2.size())put(b, cand2[i]);
	
	rep(i,N){
		rep(j,N){
			if(b.board[i][j]>0)ok=false;
		}
	}
	
	rep(i,cand2.size())put(b, cand2[i], -1);
	
	put(b,p,-1);
	
	return ok;
}


int deccand(vector<P>& cand, B b,int p=0){
	int mini = 0;
	rep(i,cand.size()){
		if(!canuse(b, cand[i])){
			cand.erase(cand.begin()+i);
			i--;
			if(i+mini<p)mini++;
		}
	}	
	return mini;
}
vector<P> answ;

int n;
bool saiki(B& b, vector<P>& cand, int depth, vector<P>& hoge){
	
	{
		int bsum = 0;
		int rsum = 0;
		rep(i,N)rep(j,N)bsum += b.board[i][j];
		
		reps(i,depth,cand.size()){
			if(cand[i].kind==0)rsum += 5;
			if(cand[i].kind==1)rsum += 9;
			if(cand[i].kind==2)rsum += 13;
		}
		
		if(rsum<bsum)return false;
	}
	
	
	
	///return 
	if(depth==cand.size()){
		if(hoge.size()!=n)return false;
		
		bool ok = true;
		rep(i,N){
			rep(j,N){
				if(b.board[i][j]!=0)ok=false;
			}
		}
		
		if(ok)answ = hoge;
		
		return ok;
	}
	
	bool next1 = saiki(b, cand, depth+1, hoge);
	if(next1)return true;
	
	
	if(hoge.size()==n)return false;
	
	bool next2;
	
	
	if(!canuse(b,cand[depth]))return false;
	
	put(b, cand[depth]);
	
	
	int m = 0;
	vector<P> copy;
	bool dodec = hoge.size()<1;
	hoge.push_back(cand[depth]);
	
	if(dodec){
		//make copy
		copy = cand;
		
		//dec cand
		m = deccand(cand, b, depth);
	}
	next2 = saiki(b, cand, depth+1-m, hoge);
	if(dodec){
		//return copy
		cand = copy;
	}
	
	hoge.pop_back();
	
	put(b, cand[depth], -1);
	
	return next2;
}

int main(){
	
	B b;
	
	cin>>n;
	
	
	rep(i,N)rep(j,N){
		cin>>b.board[i][j];
		b.board[i][j]-='0';
	}
	
	
	vector<P> cand = getcand(b);
	deccand(cand, b);
	vector<P> aaa;
	saiki(b, cand, 0, aaa);
	
	rep(i,answ.size()){
		printf("%d %d %d\n",answ[i].x,answ[i].y,answ[i].kind+1);
	}
}