// cross-linked sudoku solver
// another fine solution by misof
#include <algorithm>

#include <iostream>
#include <sstream>
#include <string>
#include <vector>
#include <queue>
#include <set>
#include <map>

#include <cstdio>
#include <cstdlib>
#include <cctype>
#include <cmath>
#include <cassert>
using namespace std;

#define REP(i,n) for(__typeof(n) i=0;i<(n);++i)
#define FOR(i,a,b) for(__typeof(b) i=(a);i<=(b);++i)
#define FORD(i,a,b) for(__typeof(a) i=(a);i>=(b);--i)
#define CLEAR(t) memset((t),0,sizeof(t))
#define SIZE(t) int((t).size())
template <class T> inline int BITCNT(T x) { int res=0; while (x) { res++; x&=x-1; } return res; }

#define MAX_BOARDS 4
#define MAX_TWINS 5
#define ENCODE(b,r,c,val) (((((((b)<<4)|(r))<<4)|(c))<<10)|(1<<(val)))

int boards;                      // number of boards in the input
int filledSquares;               // number of already filled squares
int IMAGE[MAX_BOARDS][9][9];     // already placed numbers
int allowed[MAX_BOARDS][9][9];   // bit-encoded sets of allowed numbers
int twinCount[MAX_BOARDS][9][9]; // how many squares share the same color?
int twins[MAX_BOARDS][9][9][MAX_TWINS][3]; // what are their coordinates?

inline void tryToErase(int b, int r, int c, int value, vector<int> &changes) { // {{{
  if (IMAGE[b][r][c]) return;
  int mask = 1<<value;
  if ((allowed[b][r][c] & mask) == 0) return;
  allowed[b][r][c] ^= mask;
  changes.push_back( ENCODE(b,r,c,value) );
} // }}}
vector<int> spreadInfo(int b, int r, int c) { // {{{
  assert(IMAGE[b][r][c]);
  
  vector<int> changes;
  int value = IMAGE[b][r][c];
  // erase from the row and column
  REP(i,9) tryToErase(b,r,i,value,changes);
  REP(i,9) tryToErase(b,i,c,value,changes);
  // erase from the 3x3 square
  int rr = (r/3)*3, cc = (c/3)*3;
  REP(i,3) REP(j,3) tryToErase(b,rr+i,cc+j,value,changes);
  // erase everything else from the twins
  REP(t,twinCount[b][r][c]) {
    int tb = twins[b][r][c][t][0];
    int tr = twins[b][r][c][t][1];
    int tc = twins[b][r][c][t][2];
    FOR(k,1,9) if (k!=value) tryToErase(tb,tr,tc,k,changes);
  }
  return changes;
} // }}}
void undo(const vector<int> &changes) { // {{{
  FORD(i,SIZE(changes)-1,0) {
    int E = changes[i];
    int b,r,c,m;
    m = E & 1023; E >>= 10;
    c = E & 15; E >>= 4;
    r = E & 15; E >>= 4;
    b = E;
    allowed[b][r][c] |= m;
  }
} // }}}
void load() { // {{{
  filledSquares = 0;
  cin >> boards;
  REP(b,boards) REP(r,9) REP(c,9) { cin >> IMAGE[b][r][c]; if (IMAGE[b][r][c]) filledSquares++; }
  int equalPairsCount;
  if (!(cin >> equalPairsCount)) return;
  REP(p,equalPairsCount) {
    int aa[3],bb[3];
    REP(i,3) cin >> aa[i]; REP(i,3) cin >> bb[i];

    int t1 = twinCount[aa[0]][aa[1]][aa[2]];
    REP(i,3) twins[aa[0]][aa[1]][aa[2]][t1][i] = bb[i];
    twinCount[aa[0]][aa[1]][aa[2]]++;

    int t2 = twinCount[bb[0]][bb[1]][bb[2]];
    REP(i,3) twins[bb[0]][bb[1]][bb[2]][t2][i] = aa[i];
    twinCount[bb[0]][bb[1]][bb[2]]++;
  }
} // }}}
void init() { // {{{
  CLEAR(allowed);
  REP(b,boards) REP(r,9) REP(c,9) if (!IMAGE[b][r][c]) FOR(k,1,9) allowed[b][r][c] |= 1<<k;
  REP(b,boards) REP(r,9) REP(c,9) if (IMAGE[b][r][c]) spreadInfo(b,r,c);
} // }}}
void print() { // {{{
  REP(b,boards) REP(r,9) REP(c,9) {
    int T = twinCount[b][r][c];
    REP(t,T) {
      int x = twins[b][r][c][t][0];
      int y = twins[b][r][c][t][1];
      int z = twins[b][r][c][t][2];
      assert(IMAGE[b][r][c]==IMAGE[x][y][z]);
    }
  }
  REP(b,boards) {
    REP(r,9) {
      REP(c,9) cout << IMAGE[b][r][c] << " ";
      cout << endl;
    }
    cout << endl;
  }
} // }}}
void solve() { // {{{
  if (filledSquares == boards*9*9) { print(); exit(0); }
  // if there is an impossible square, we are in a dead end
  REP(b,boards) REP(r,9) REP(c,9) if (!IMAGE[b][r][c]) if (!allowed[b][r][c]) return;
  // find the best square to query
  int best = 10, bb=0, br=0, bc=0;
  REP(b,boards) REP(r,9) REP(c,9) if (!IMAGE[b][r][c]) {
    int toto = BITCNT(allowed[b][r][c]);
    if (toto < best) { best=toto; bb=b; br=r; bc=c; }
  }
  // try all allowed values
  FOR(k,1,9) if (allowed[bb][br][bc] & (1<<k)) {
    IMAGE[bb][br][bc] = k;
    filledSquares++;
    vector<int> changes = spreadInfo(bb,br,bc); 

    solve();

    undo(changes);
    filledSquares--;
    IMAGE[bb][br][bc] = 0;
  }
} // }}}

int main() {
  load();
  init();
  solve();
}
// vim: fdm=marker:commentstring=\ \"\ %s:nowrap:autoread
