// Sudominoku, MCPC 2011 Problem D   Alternate Java version by Andy Harrington

/* basic recursive solution with backtracking, complicated by the fact that
   you must keep track of both numbers on the board and dominoes used.
   To avoid many near misses with small one-cell holes, the main iteration
   is filling the board left to right and down.
   The inner loop is trying different dominoes.
*/

import java.util.*;
import java.io.*;
import static java.lang.Math.*;

public class sudominoku {
    static int N;
    static int[] rowHas,     // *Has short for arrays rowHas, colHas, blockHas
                 colHas;     //   ints are bitfields for used 1-9: n-> 1<<(n-1),
    static int[][] blockHas, //   one set for each row, col, 3x3 block
                   board;    // 9x9 with numbers 1-9 and 0 for unfilled
    static boolean[][] used; // used[small][big] true if use domino small+big
    static String sol;       // solution string
//    static long tries;       //JUDGE data
//    static Scanner keyb = new Scanner(System.in);  // pause in debugging seq
    
    static boolean addNum(int n, int r, int c) {//if can add, true; update *Has
        int bit = << (n-1);  // *Has arrays use bitfield for used numbers
        if (board[r][c==  && (bit & blockHas[r/3][c/3]) == &&
            (bit & rowHas[r]) == && (bit & colHas[c]) == 0) { //num not used
            rowHas[r+= bit;
            colHas[c+= bit;
            blockHas[r/3][c/3+= bit;
            board[r][c= n;
            return true;
        }
        return false;
    }

    static void subNum(int r, int c) {//backtrack placement
        int n = board[r][c];
//        if (n==0) {  // DEBUG
//            pr("Removing nothing");
//            return;
//        }
        int bit = << (n-1);
        rowHas[r-= bit;
        colHas[c-= bit;
        blockHas[r/3][c/3-= bit;
        board[r][c0;
    }

    /** assume legal first end at r0,c0; try second number n at r,c */
    static void addSecond(int r0, int c0, int r, int c, int n) {
        if (c == || r == 9return;
        if (addNum(n, r, c)) {
            nextLoc(r0, c0);
            subNum(r, c)// backtrack before next test
        }
    }

    static void pinFirstEnd(int r, int c, int n1, int n2) {
//        tries++;  //DEBUG
        if (addNum(n1, r, c)) {
            addSecond(r, c, r, c+1, n2);
            addSecond(r, c, r+1, c, n2);
            subNum(r, c)// backtrack before next test
        }
    }

    /** tries everything with pieces at next open place after r,c */
    static void nextLoc(int r, int c) {
        if (ONE_SOL && sol.length() 0return//force stop after solution
        do //left to right, then down to next row
            c++;
            if (c == 9) {
                c = 0;
                r++;
            }
            if (r == 9) {
               sol += bStr()// allows for many sudominoku solutions 
               return//Two different domino arrangements may give same sudoku
            }
        while (board[r][c0)// skip occupied spots
//        pr(String.format("Try (%d, %d)%n%s", r, c, bStr()));
//        if (DEBUG)keyb.nextLine(); // watch steps unfold
        for (int small = 1; small < 9; small++// try unused dominos
            for (int big = small+1; big <= 9; big++) {
                if (used[small][big]) continue;
                used[small][bigtrue;
                pinFirstEnd(r, c, small, big);
                pinFirstEnd(r, c, big, small);
                used[small][bigfalse// backtrack before next test
            }
    }

    static String bStr() { // string for board; allow incomplete with '_'
        String s = "", nl = String.format("%n");
        for (int[] row : board)  {
            for (int n : row)
                s += ((n== 0"_" ""+n);
            s += nl;
        }
        return s;
    }

    static void addInput(int n, String loc) { // parameters like 5, "B7"
        if (!addNum(n, loc.charAt(0)-'A', loc.charAt(1'1')) //put on board
            pr("Double used spot! " + loc);  //DEBUG
    }

    public static void main(String[] argsthrows Exception {
        Scanner in = new Scanner(new File("sudominoku.in"));
        N = in.nextInt();
        int dataSetN = 1;
        while (N > 0) {
            board = new int[9][9];
            used = new boolean[10][10]//ignore 0 indices
            rowHas = new int[9]; colHas = new int[9];
            blockHas  = new int[3][3];
            sol = "";
//            tries = 0;
            for (int i = 0; i < N; i++) {
                int n1 = in.nextInt();
                addInput(n1, in.next());
                int n2 = in.nextInt();
                addInput(n2, in.next());
                used[min(n1, n2)][max(n1, n2)] true;
            }
            for (int i = 1; i <= 9; i++
                addInput(i, in.next());
//            pr("init:\n"+bStr());
            nextLoc(0, -1);
            System.out.println("Puzzle " + dataSetN);
            System.out.print(sol);
//            pr("Tries: " + tries);
            dataSetN++;
            N = in.nextInt();
        }
    }

    // only judge checks follow /////////////////////////

    static String inSet(int t) { // expand bitset as string
        String s= "";
        for (int n = 1; n <= 9; n++)
           s += (((t&(1<<(n-1)))
                  == 0"_" (""+n));
        return s;
    }
    
    static boolean DEBUG = false;
    static boolean ONE_SOL = true;  // for longer check make false
    
    static void prp(String msg) { // debug message
        if (DEBUGSystem.err.print(msg);
    }
    
    static void pr(String msg) {// debug message with newline
        prp(msg+"\n");
    }
}