#include <bits/stdc++.h>

//{{{ uf.hpp
#ifndef INCLUDE_UF_HPP
#define INCLUDE_UF_HPP
#include <vector>
#include <algorithm>
namespace orislib {
namespace ds {
//{{{ UF merge, same, root, size, count
struct UF {
  std::vector<int> data;
  int cnt;
  UF(int n) : data(n, -1), cnt(n) {}
  bool merge(int a, int b){
    a = root(a);
    b = root(b);
    if (a != b){
      cnt--;
      if (data[b] < data[a]) std::swap(a, b);
      data[a] += data[b];
      data[b] = a;
    }
    return a != b;
  }
  bool same(int a, int b){ return root(a) == root(b); }
  int root(int a){ return data[a] >= 0 ? data[a] = root(data[a]) : a; }
  int size(int a){ return -data[root(a)]; }
  int count(){ return cnt; }
};
//}}}
//{{{ UF2d merge, same, size, count
struct UF2d {
  UF uf;
  const int W, H;
  UF2d(int w, int h) : uf(w * h), W(w), H(h) {}
  bool merge(int ax, int ay, int bx, int by){ return uf.merge(ay * W + ax, by * W + bx); }
  bool same(int ax, int ay, int bx, int by){ return uf.same(ay * W + ax, by * W + bx); }
  int size(int x, int y){ return uf.size(y * W + x); }
  int count(){ return uf.count(); }
};
//}}}
}
}
#endif
//}}}

using namespace std;
using namespace orislib::ds;

typedef long long ll;
typedef long double ld;
typedef tuple<int, int> duo;
typedef tuple<int, int, int> tri;
const int dx[] = {0, 0, 0, 1, -1, 1, 1, -1, -1, 2, -2, 0, 0};
const int dy[] = {0, 1, -1, 0, 0, 1, -1, 1, -1, 0, 0, 2, -2};
const int Mod = 1000000000 + 0;
//{{{ templates
#define TT_ template<typename T>inline
#define TTF_ template<typename T,typename F>inline
TT_ T sq(T x){return x*x;}
TT_ T In(){T x;cin>>x;return x;}
TT_ void Out(T&x){cout<<x;}
TT_ void sort(T&v){sort(begin(v),end(v));}
TT_ void revs(T&v){reverse(begin(v),end(v));}
TT_ void uniq(T&v){sort(v);v.erase(unique(begin(v),end(v)),end(v));}
TT_ int ubnd(T&v,typename T::value_type&x){return upper_bound(begin(v),end(v),x)-begin(v);}
TT_ int lbnd(T&v,typename T::value_type&x){return lower_bound(begin(v),end(v),x)-begin(v);}
TTF_ void inpt(T&v,int n,F f){for(v.reserve(n);n--;v.emplace_back(f()));}
TTF_ void show(T&v,F f,string d=" ",string e="\n"){int i=0;for(auto&x:v)i++&&(cout<<d),f(x);cout<<e;}
TT_ typename T::iterator minel(T&v){return min_element(begin(v),end(v));}
TT_ typename T::iterator maxel(T&v){return max_element(begin(v),end(v));}

inline void fast_io(){ios::sync_with_stdio(0);cin.tie(0);}
inline int in(){int x;scanf("%d",&x);return x;}
inline ll pow_mod(ll a,ll k,ll m){ll r=1;for(;k>0;a=a*a%m,k>>=1)if(k&1)r=r*a%m;return r;}
inline ll mod_inv(ll a,ll p){return pow_mod(a,p-2,p);}
//}}} priority_queue queue deque front stringstream max_element min_element insert count make_tuple

struct Zhash {
  Zhash(){
    mt19937 mt;
    for (int i = 0; i < 10; i++){
      for (int j = 0; j < 10; j++){
        for (int s = 0; s < 256; s++){
          rands[i][j][s] = mt();
        }
      }
    }
  }
  int hash(int data[10][10]){
    int h = 0;
    for (int i = 0; i < 10; i++){
      for (int j = 0; j < 10; j++){
        h ^= rands[i][j][data[i][j]];
      }
    }
    return h;
  }
  int rands[10][10][256];
};

const int len[] = {5, 9, 13};

struct Board {
  Board(){
    memset(valid_table, 0, sizeof(valid_table));
    valid_table[0][0] = true;
    for (int t = 1; t <= 12; t++){
      for (int v = 0; v <= 12 * 13; v++){
        if (!valid_table[t - 1][v]) continue;
        valid_table[t][v + 5] = true;
        valid_table[t][v + 9] = true;
        valid_table[t][v + 13] = true;
      }
    }
    memset(cnt, 0, sizeof(cnt));
  }
  void read(){
    N = in();
    tot = 0;
    for (int i = 0; i < 10; i++){
      for (int j = 0; j < 10; j++){
        data[i][j] = in();
        tot += data[i][j];
      }
    }
  }
  bool invalid(int x, int y){
    return x < 0 || x >= 10 || y < 0 || y >= 10;
  }
  bool drop_ink(int x, int y, int t){
    const int l = len[t];
    tot -= l;
    cnt[t]++;
    bool ok = tot >= 0 && valid_table[N - (cnt[0] + cnt[1] + cnt[2])][tot];
    for (int d = 0; d < l; d++){
      int nx = x + dx[d], ny = y + dy[d];
      if (invalid(nx, ny)){
        ok = false;
        continue;
      }
      data[ny][nx]--;
      if (data[ny][nx] < 0) ok = false;
    }
    ans.emplace_back(x, y, t + 1);
    if (ok){
      int h = zhash.hash(data);
      if (vis.count(h)) return false;
      vis.insert(h);
      UF2d uf(10, 10);
      for (int i = 0; i < 10; i++){
        for (int j = 0; j < 10; j++){
          if (data[i][j] <= 0) continue;
          for (int d = 0; d < 5; d++){
            int nx = j + dx[d], ny = i + dy[d];
            if (invalid(nx, ny)) continue;
            if (data[ny][nx] <= 0) continue;
            uf.merge(j, i, nx, ny);
          }
        }
      }
      int mini = 128;
      for (int i = 0; i < 10; i++){
        for (int j = 0; j < 10; j++){
          if (data[i][j] >= 1) mini = min(mini, uf.size(j, i));
        }
      }
      if (mini < 5) return false;
    }
    return ok;
  }
  void undo(int x, int y, int t){
    const int l = len[t];
    tot += l;
    cnt[t]--;
    for (int d = 0; d < l; d++){
      int nx = x + dx[d], ny = y + dy[d];
      if (invalid(nx, ny)) continue;
      data[ny][nx]++;
    }
    ans.pop_back();
  }
  bool solve(){
    if (cnt[0] + cnt[1] + cnt[2] == N) return true;
    for (int t = 0; t < 3; t++){
      for (int i = 0; i < 10; i++){
        for (int j = 0; j < 10; j++){
          bool ok = drop_ink(j, i, t);
          if (ok && solve()) return true;
          undo(j, i, t);
        }
      }
    }
    return false;
  }
  int data[10][10];
  int cnt[3];
  int tot;
  int N;
  bool valid_table[13][13*13+1];
  set<int> vis;
  vector<tri> ans;
  Zhash zhash;
};

int main()
{
  Board b;
  b.read();
  b.solve();
  for (const auto& a : b.ans){
    cout << get<0>(a) << " " << get<1>(a) << " " << get<2>(a) << "\n";
  }
  return 0;
}