// Solution to 2010 MCPC Problem F: Top This
// Started 2/13/2013
// Finished on 5/7/2014

import java.util.*;

public class f {

	public final static int SIZE = 6;

	public static char[][] bestGrid;
	public static boolean foundSol;

	public static void main(String[] args) {

		Scanner stdin = new Scanner(System.in);
		int numCases = stdin.nextInt();

		// Go through each case.
		for (int loop=1; loop<=numCases; loop++) {
			String s1 = stdin.next();
			String s2 = stdin.next();
			System.out.println(loop);
			bestGrid = new char[SIZE][SIZE];
			solve(s1, s2);
		}
	}

	// Beginning board.
	public static void init(char[][] g) {
		for (int i=0; i<g.length; i++)
			Arrays.fill(g[i], '.');
	}

	public static void solve(String a, String b) {

		// Set up grids.
		char[][] grid1 = new char[SIZE][SIZE];
		char[][] grid2 = new char[SIZE][SIZE];
		init(grid1);
		init(grid2);

		// Set up pieces.
		piece[] sol1 = new piece[a.length()];
		for (int i=0; i<sol1.length; i++)
			sol1[i] = new piece(a.charAt(i));
		piece[] sol2 = new piece[b.length()];
		for (int i=0; i<sol2.length; i++)
			sol2[i] = new piece(b.charAt(i));

		// Do it!
		foundSol = false;
		generate(grid1, grid2, 0, 0, sol1, sol2);

		// Print results.
		if (foundSol)
			print(bestGrid);
		else
			System.out.println("No solution");
	}

	// Prints board.
	public static void print(char[][] grid) {
		for (int i=0; i<grid.length; i++)
			System.out.println(new String(grid[i]));
	}

	// Returns true iff g1 and g2 are identical.
	public static boolean equal(char[][] g1, char[][] g2) {
		for (int i=0; i<g1.length; i++)
			for (int j=0; j<g1[0].length; j++)
				if (g1[i][j] != g2[i][j])
					return false;
		return true;
	}

	// Returns true iff g2 has no piece placed in a location g1 doesn't have a piece.
	public static boolean noconflict(char[][] g1, char[][] g2) {
		for (int i=0; i<g1.length; i++)
			for (int j=0; j<g1[0].length; j++)
				if (g1[i][j] == '.' && g2[i][j] == '#')
					return false;
		return true;
	}

	// makes g1 equal to the current value of g2.
	public static void setGrid(char[][] g1, char[][] g2) {
		for (int i=0; i<g1.length; i++)
			for (int j=0; j<g1[0].length; j++)
				g1[i][j] = g2[i][j];
	}

	// Returns true iff g1 is lexicographically before g2, by their definition.
	public static boolean better(char[][] g1, char[][] g2) {
		for (int i=0; i<g1.length; i++) {
			for (int j=0; j<g1[0].length; j++) {
				if (g1[i][j] == '#' && g2[i][j] == '.') return true;
				else if (g1[i][j] == '.' && g2[i][j] == '#') return false;
			}
		}
		return false;
	}

	public static boolean place(char[][] g, int loc, piece p) {

		// Extract location.
		int x = loc/SIZE;
		int y = loc%SIZE;

		// Go through each piece looking for out of bounds and placement conflict.
		for (int i=0; i<p.offset.length; i++) {
			int newx = x + p.offset[i][0];
			int newy = y + p.offset[i][1];
			if (newx < 0 || newx >= SIZE || newy < 0 || newy >= SIZE) return false;
			if (g[newx][newy] == '#') return false;
		}

		// Place piece.
		for (int i=0; i<p.offset.length; i++) {
			int newx = x + p.offset[i][0];
			int newy = y + p.offset[i][1];
			g[newx][newy] = '#';
		}
		return true;
	}

	public static void unplace(char[][] g, int loc, piece p) {

		// Extract location.
		int x = loc/SIZE;
		int y = loc%SIZE;

		// Place no piece here!
		for (int i=0; i<p.offset.length; i++) {
			int newx = x + p.offset[i][0];
			int newy = y + p.offset[i][1];
			g[newx][newy] = '.';
		}
	}

	// Solves the problem recursively for grid1 with k1 pieces placed, grid2 with k2 pieces placed and pieces
	// sol1 for grid1 and sol2 for grid2.
	public static void generate(char[][] grid1, char[][] grid2, int k1, int k2, piece[] sol1, piece[] sol2) {

		// We've finished the first grid
		if (k1 == sol1.length) {

			// Add the second one.
			if (k2 == sol2.length) {
				if (equal(grid1, grid2) && (!foundSol || better(grid1, bestGrid))) {
					foundSol = true;
					setGrid(bestGrid, grid1);
				}
			}

			// Go through each location.
			for (int loc=0; loc<SIZE*SIZE; loc++) {

				// Piece can't go here.
				if (grid1[loc/SIZE][loc%SIZE] == '.' ||
					grid2[loc/SIZE][loc%SIZE] == '#') continue;

				// Go through each rotation.
				for (int rot=0; rot<sol2[k2].numRotations; rot++) {

					boolean okay = place(grid2, loc, sol2[k2]);

					if (okay && noconflict(grid1, grid2))
						generate(grid1, grid2, k1, k2+1, sol1, sol2);

					if (okay) unplace(grid2, loc, sol2[k2]);
					sol2[k2].clockRotate();
				}

				// Move back for future use.
				for (int rot=0; rot<sol2[k2].numRotations; rot++)
					sol2[k2].counterRotate();
			}

			return;

		} // end base case...


		// Go through each location for first piece.
		for (int loc=0; loc<SIZE*SIZE; loc++) {

			// Piece can't go here.
			if (grid1[loc/SIZE][loc%SIZE] == '#') continue;

			// Go through each rotation.
			for (int rot=0; rot<sol1[k1].numRotations; rot++) {

				boolean okay = place(grid1, loc, sol1[k1]);

				if (okay) {
					generate(grid1, grid2, k1+1, k2, sol1, sol2);
					unplace(grid1, loc, sol1[k1]);
				}
				sol1[k1].clockRotate();
			}

			// Move back for future use.
			for (int rot=0; rot<sol1[k1].numRotations; rot++)
				sol1[k1].counterRotate();
		}
	}

}

class piece {

	public final static int[][][] TOKENS = { {{0,0},{0,1},{0,2},{0,3}},
								             {{0,0},{0,1},{0,2},{1,0}},
											 {{0,0},{0,1},{0,2},{1,1}},
											 {{0,0},{0,1},{0,2},{1,2}},
											 {{0,0},{0,1},{1,1},{1,2}},
											 {{0,0},{0,1},{1,0},{1,1}},
											 {{0,0},{0,1},{1,-1},{1,0}} };

	public final static int[] ROTATIONS = {2,4,4,4,2,1,2};

	public int[][] offset;
	public int curOrientation;
	public int numRotations;

	// Set up this piece.
	public piece(char c) {
		int number = c - 'A';
		offset = new int[4][2];
		for (int i=0; i<4; i++)
			for (int j=0; j<2; j++)
				offset[i][j] = TOKENS[number][i][j];
		curOrientation = 0;
		numRotations = ROTATIONS[number];
	}

	// Go clockwise.
	public void clockRotate() {
		for (int i=0; i<4; i++) {
			int temp = offset[i][0];
			offset[i][0] = offset[i][1];
			offset[i][1] = -temp;
		}
		curOrientation++;
		adjust();
	}

	// Go counter-clockwise.
	public void counterRotate() {
		for (int i=0; i<4; i++) {
			int temp = offset[i][0];
			offset[i][0] = -offset[i][1];
			offset[i][1] = temp;
		}
		curOrientation--;
		adjust();
	}

	// Move top left to (0,0). Tie goes to top.
	public void adjust() {
		int minx = offset[0][0];
		int miny = offset[0][1];
		for (int i=1; i<4; i++) {
			if (offset[i][0] < minx) {
				minx = offset[i][0];
				miny = offset[i][1];
			}
			else if (offset[i][0] == minx && offset[i][1] < miny) {
				minx = offset[i][0];
				miny = offset[i][1];
			}
		}

		for (int i=0; i<4; i++) {
			offset[i][0] -= minx;
			offset[i][1] -= miny;
		}
	}

}