#include <iostream>
#include <cstring>
using namespace std;
inline void swap(int &a, int &b) { int t=a; a=b; b=t; }
// 程序中使用横向棋盘,5行7列,水平移动变竖直移动,竖直移动变水平运动。
int n;
int map[7][6][9];
int a[6],b[6],c[6]; // 每一步的变化,a是棋盘倒放之后的行,b是列
// 方块下落
void fall(int depth)
{
for (int i=1; i<=5; i++)
{
int m=map[depth][i];
// 在第i行中,寻找第一个0,然后再寻找非0,接下来移动。不过不一定正确……
int j=1,k=0;
while (m[j]) j++;
if (j==8) continue;
k=j+1;
while (m[k]==0 && k<8) k++;
while (k<8) swap(m[j++],m[k++]);
}
}
// 检查是否可以消除方块。如果可以,就消除方块。
bool mark[6][8]; // 消除方块时用
bool check(int depth)
{
bool changed=false;
memset(mark,0,sizeof(mark));
// 检查是否可以消除
// 水平方向
for (int i=1; i<=5; i++)
for (int delta=7; delta>=3; delta--) // 连通的方块数
for (int j=1; j<=8-delta; j++)
{
int a=map[depth][i][j];
for (int k=j+1; k<=j+delta-1; k++)
if (map[depth][i][k]!=a)
{
a=0;
break;
}
if (a) for (int k=j; k<=j+delta-1; k++) mark[i][k]=true;
}
// 竖直方向
for (int j=1; j<=7; j++)
for (int delta=5; delta>=3; delta--)
for (int i=1; i<=6-delta; i++)
{
int a=map[depth][i][j];
for (int k=i+1; k<=i+delta-1; k++)
if (map[depth][k][j]!=a)
{
a=0;
break;
}
if (a) for (int k=i; k<=i+delta-1; k++) mark[k][j]=true;
}
// 消除
for (int i=1; i<=5; i++)
for (int j=1; j<=7; j++)
if (mark[i][j]) map[depth][i][j]=0, changed=true;
return changed;
}
// 进行搜索,如果有解则返回true,否则返回false。
bool DFS(int depth)
{
if (depth>n)
{
for (int i=1; i<=5; i++)
if (map[n+1][i][1]) return false;
return true;
}
for (int i=1; i<=5; i++)
for (int j=1; j<=7; j++)
{
/
移动一种方块。分四种情况:
① 方块本身就是0,那么直接跳过;
② 在左边界,只能向右移动;
③ 在右边界,只能向左移动。如果左边有方块,那么可以忽略这一步,
因为那个方块右移和这个方块左移效果相同,但字典序更小。
也就是说,在右边界时,如果左边为空,则向左移动,否则不移动。
④ 不在边界,如果左边为空,就既向左又向右(特殊考虑,因为要多一段代码);
如果左边不为空,那么不管右边是什么都向右移动。
*/
if (map[depth][i][j]0) continue;
a[depth]=i;
b[depth]=j;
int &dir=c[depth]; // 移动方向
if (i<5) // 第②种情况+第④种情况的第一部分
dir=1;
else if (i5 && map[depth][4][j]==0) // 第③种情况
dir=-1;
else
continue;
memcpy(map[depth+1], map[depth], sizeof(map[depth]));
swap(map[depth+1][i][j], map[depth+1][i+dir][j]);
// 下落与消除方块
do
{
fall(depth+1);
} while (check(depth+1));
// 继续搜索
if (DFS(depth+1)) return true;
if (i>1 && i<5 && map[depth][i-1][j]==0) // 第④种情况的第二部分
{
a[depth]=i;
b[depth]=j;
dir=-1;
memcpy(map[depth+1], map[depth], sizeof(map[depth]));
swap(map[depth+1][i][j], map[depth+1][i+dir][j]);
// 和上面一样
do
{
fall(depth+1);
} while (check(depth+1));
if (DFS(depth+1)) return true;
}
}
return false;
}
int main()
{
memset(map,0,sizeof(map));
cin>>n;
for (int i=1; i<=5; i++)
{
int temp, j=1;
do
{
cin>>temp;
map[1][i][j++]=temp;
} while (temp);
}
if (DFS(1))
for (int i=1; i<=n; i++)
cout<<(a[i]-1)<<" "<<(b[i]-1)<<" "<<c[i]<<endl;
else
cout<<"-1"<<endl;
return 0;
}