#include <iostream>
#include <vector>
#include <string.h>
using namespace std;

//debugFlag
bool g_bDebugFlag = false;

enum{
	NONE = 0,
	SMALL = 1,
	MEDIUM = 2,
	LARGE = 3,
};

enum{
	FLAG_SMALL = 1 << 0,
	FLAG_MEDIUM = 1 << 1,
	FLAG_LARGE = 1 << 2,
};

int smallDrop[] = {
	0, 1, 0,
	1, 1, 1,
	0, 1, 0
};

int mediumDrop[] = {
	1, 1, 1,
	1, 1, 1,
	1, 1, 1,
};

int largeDrop[] = {
	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,
};

struct Result
{
	Result() : x( 0 ), y( 0 ), size( 0 ){}
	Result( const int _x, const int _y, const int _size ) : x( _x ), y( _y ), size( _size ){}
	int x;
	int y;
	int size;
};

class Drop
{
public:
	Drop( const int size ) : m_size( size )
	{
		switch( size ){
			case SMALL:		//小
				m_patternSize = 3;
				m_pattern = smallDrop;
				break;
			case MEDIUM:	//中
				m_patternSize = 3;
				m_pattern = mediumDrop;
				break;
			case LARGE:		//大
				m_patternSize = 5;
				m_pattern = largeDrop;
				break;
		}
	}
	~Drop()
	{
	}

	int m_size;
	int m_patternSize;
	int* m_pattern;
};

class Cloth
{
public:
	Cloth( const int dropCount ) : m_depthMax( 0 ), m_dropCount( dropCount )
	{
		memset( m_map, 0, sizeof(m_map) );
	}
	~Cloth()
	{
	}
	void input( const int d, const int x, const int y )
	{
		m_map[ y ][ x ] = d;
		if( d > m_depthMax ){
			m_depthMax = d;
		}
	}
	vector<Result> analyze()
	{
		vector<Result> r;
		return rec( m_dropCount, r );
	}
	void outputStain()
	{
		if( !g_bDebugFlag ){
			return;
		}

		for( int i = 0; i < 10; ++i ){
			for( int j = 0; j < 10; ++j ){
				cout << m_map[ i ][ j ] << " ";
			}
			cout << endl;
		}
		cout << endl;
	}

	vector<Result> rec( const int count, vector<Result> res )
	{
		if( count == 0 ){
			outputStain();
			if( isWhite() ){
				return res;
			}
			return vector<Result>();
		}

		Result r;
		if( removeMediumDrop( &r ) ){
			removeStain( r.x - 1, r.y - 1, MEDIUM );
			res.push_back( r );
			return rec( count - 1, res );
		}
		for( int y = 0; y < 10; ++y ){
			for( int x = 0; x < 10; ++x ){
				int sizeFlags  = match( x, y );
				if( sizeFlags > 0 ){
					int size[ 3 ];
					size[ 0 ] = sizeFlags & FLAG_LARGE ? LARGE : 0;
					size[ 1 ] = sizeFlags & FLAG_SMALL ? SMALL : 0;
					size[ 2 ] = sizeFlags & FLAG_MEDIUM ? MEDIUM : 0;
					for( int i = 0; i < 3; ++i ){
						if( size[ i ] == 0 ) continue;

						removeStain( x, y, size[ i ] );
						if( isPossiblePattern( x, y, size[ i ] ) ){
							res.push_back( Result( x + ( size[ i ] == LARGE ? 2 : 1 ), y + ( size[ i ] == LARGE ? 2 : 1 ), size[ i ] ) );
							vector<Result> ret = rec( count - 1, res );
							if( ret.size() == m_dropCount ){
								return ret;
							}
							res.pop_back();
						}
						dye( x, y, size[ i ] );
					}
				}
			}
		}
		return vector<Result>();
	}
	int match( const int x, const int y )
	{
		Drop large( LARGE );
		bool mismatchL = false;
		for( int i = 0; i < large.m_patternSize; ++i ){
			for( int j = 0; j < large.m_patternSize; ++j ){
				if( ( large.m_pattern[ i * large.m_patternSize + j ] > 0 && m_map[ y + i ][ x + j ] <= 0 ) ){
					mismatchL = true;
					break;
				}
			}
			if( mismatchL ){
				break;
			}
		}

		Drop medium( MEDIUM );
		Drop small( SMALL );
		bool mismatchM = false;
		bool mismatchS = false;
		for( int i = 0; i < small.m_patternSize; ++i ){
			for( int j = 0; j < small.m_patternSize; ++j ){
				int X = x + j;
				int Y = y + i;
				int index = i * small.m_patternSize + j;
				if( ( small.m_pattern[ index ] > 0 && m_map[ Y ][ X ] <= 0 ) ){
					mismatchS = true;
				}
				if( ( medium.m_pattern[ index ] > 0 && m_map[ Y ][ X ] <= 0 ) ){
					mismatchM = true;
				}
				if( mismatchS && mismatchM ){
					break;
				}
			}
			if( mismatchS && mismatchM ){
				break;
			}
		}

		return 0x0
			| ( mismatchL ? 0 : FLAG_LARGE )
			| ( mismatchM ? 0 : FLAG_MEDIUM )
			| ( mismatchS ? 0 : FLAG_SMALL );
	}
	bool removeMediumDrop( Result* r )
	{
		static int pattern[][ 9 ] = {
			{ 0, 0, 0, 0, 1, 1, 0, 1, 1, },
			{ 0, 0, 0, 1, 1, 0, 1, 1, 0, },
			{ 0, 1, 1, 0, 1, 1, 0, 0, 0, },
			{ 1, 1, 0, 1, 1, 0, 0, 0, 0, },
		};

		for( int k = 0; k < 4; ++k ){
			for( int y = 0; y < 7; ++y ){
				for( int x = 0; x < 7; ++x ){
					bool mismatch = false;
					for( int i = 0; i < 3; ++i ){
						for( int j = 0; j < 3; ++j ){
							if( ( pattern[ k ][ i * 3 + j ] > 0 && m_map[ y + i ][ x + j ] <= 0 )
								|| ( pattern[ k ][ i * 3 + j ] == 0 && m_map[ y + i ][ x + j ] > 0 ) ){
								mismatch = true;
								break;
							}
						}
						if( mismatch ) break;
					}
					if( !mismatch ){
						int retX, retY;
						switch( k ){
							case 0: retX = x + 2; retY = y + 2; break;
							case 1: retX = x;     retY = y + 2; break;
							case 2: retX = x + 2; retY = y;     break;
							case 3: retX = x;     retY = y;     break;
						}
						r->size = MEDIUM;
						r->x = retX;
						r->y = retY;
						return true;
					}
				}
			}
		}
		return false;
	}
	void removeStain( const int x, const int y, const int size )
	{
		Drop drop( size );
		for( int i = 0; i < drop.m_patternSize; ++i ){
			for( int j = 0; j < drop.m_patternSize; ++j ){
				if( drop.m_pattern[ i * drop.m_patternSize + j ] ){
					--m_map[ y + i ][ x + j ];
					if( m_map[ y + i ][ x + j ] < 0 ){
						__debugbreak();
					}
				}
			}
		}
		outputStain();
	}
	void dye( const int x, const int y, const int size ){
		Drop drop( size );
		for( int i = 0; i < drop.m_patternSize; ++i ){
			for( int j = 0; j < drop.m_patternSize; ++j ){
				if( drop.m_pattern[ i * drop.m_patternSize + j ] ){
					++m_map[ y + i ][ x + j ];
				}
			}
		}
		outputStain();
	}
	bool isWhite()
	{
		for( int y = 0; y < 10; ++y ){
			for( int x = 0; x < 10; ++x ){
				if( m_map[ y ][ x ] ){
					return false;
				}
			}
		}
		return true;
	}
	bool isPossiblePattern( const int ox, const int oy, const int size )
	{
		static int pattern[][ 9 ] = {
			{ 1, 1, 1, 0, 1, 0, 0, 0, 0, },
			{ 0, 0, 1, 0, 1, 1, 0, 0, 1, },
			{ 0, 0, 0, 0, 1, 0, 1, 1, 1, },
			{ 1, 0, 0, 1, 1, 0, 1, 0, 0, },
			{ 0, 1, 0, 1, 1, 1, 0, 1, 0, },
		};

		int patternSize = Drop( size ).m_patternSize + 4;

		for( int y = ( oy - 2 < 0 ? 0 : oy - 2 ); y < oy - 2 + patternSize; ++y ){
			for( int x = ( ox - 2 < 0 ? 0 : ox - 2 ); x < ox - 2 + patternSize; ++x ){
				if( m_map[ y + 1 ][ x + 1 ] == 0 ){
					continue;
				}
				bool possible = false;
				for( int k = 0; k < 5; ++k ){
					bool impossible = false;
					for( int i = 0; i < 3; ++i ){
						for( int j = 0; j < 3; ++j ){
							if( pattern[ k ][ i * 3 + j ] > 0 && m_map[ y + i ][ x + j ] <= 0 ){
								impossible = true;
								break;
							}
						}
						if( impossible ) break;
					}
					if( !impossible ){
						possible = true;
						break;
					}
				}
				if( !possible ){
					return false;
				}
			}
		}
		return true;
	}

private:
	int m_map[ 10 + 4 ][ 10 + 4 ];
	int m_depthMax;
	int m_dropCount;
};

int main()
{
	int n;
	while( cin >> n ){
		Cloth cloth( n );
		for( int y = 0; y < 10; ++y ){
			for( int x = 0; x < 10; ++x ){
				int d;
				cin >> d;
				cloth.input( d, x, y );
			}
		}

		cloth.outputStain();

		vector<Result> result = cloth.analyze();
		for( int i = 0; i < result.size(); ++i ){
			Result r = result[ i ];
			cout << r.x << " " << r.y << " " << r.size << endl;
		}
	}

	return 0;
}