#include <fstream.h>
#include <iostream.h>
#include <assert.h>

#define MAXGSIZE 25
#define DEBUGMODE false

char printgrid[6*MAXGSIZE][12*MAXGSIZE];
char tokengrid[MAXGSIZE][MAXGSIZE][2][2];
int countgrid[MAXGSIZE][MAXGSIZE][2][2];
int gridhei;
int gridwid;
char piecetoken;

void printsol (void) {
  int spaces = gridhei*6-1;
  for (int lcv1=0;lcv1<gridhei*6;lcv1++) {
    for (int lcv2=0;lcv2<spaces;lcv2++) 
      cout << ' ';
    spaces--;
    for (int lcv2=0;lcv2<gridwid*12;lcv2++)
      cout << printgrid[lcv1][lcv2];
    cout << '\n';
  } 
}

void fillgrid (void) {
  int checker; char let;
  for (int lcv1=0;lcv1<gridhei;lcv1++)
  for (int lcv2=0;lcv2<gridwid;lcv2++) 
  for (int lcv3=0;lcv3<2;lcv3++) {
    if (tokengrid[lcv1][lcv2][0][lcv3] != ' ') {
      let = tokengrid[lcv1][lcv2][0][lcv3];
      checker = countgrid[lcv1][lcv2][0][lcv3];
      if (checker%2 == 1) {
        printgrid[6*lcv1+3][12*lcv2+5] = let;
        printgrid[6*lcv1+3][12*lcv2+6] = let;
        printgrid[6*lcv1+4][12*lcv2+5] = let;
        printgrid[6*lcv1+4][12*lcv2+6] = let;
        printgrid[6*lcv1+4][12*lcv2+7] = let;
        printgrid[6*lcv1+4][12*lcv2+8] = let;
        //printgrid[6*lcv1+5][12*lcv2+9] = let;
        printgrid[6*lcv1+5][12*lcv2+10] = let;
      }
      checker /= 2;
      if (checker%2 == 1) {
        printgrid[6*lcv1+1][12*lcv2+2] = let;
        printgrid[6*lcv1+2][12*lcv2+3] = let;
        printgrid[6*lcv1+2][12*lcv2+4] = let;
        printgrid[6*lcv1+3][12*lcv2+4] = let;
      }
      checker /= 2;
      if (checker%2 == 1) {
        printgrid[6*lcv1+0][12*lcv2+0] = let;
        printgrid[6*lcv1+1][12*lcv2+0] = let;
        printgrid[6*lcv1+1][12*lcv2+1] = let;
        printgrid[6*lcv1+2][12*lcv2+0] = let;
        printgrid[6*lcv1+2][12*lcv2+1] = let;
        printgrid[6*lcv1+2][12*lcv2+2] = let;
        printgrid[6*lcv1+3][12*lcv2+2] = let;
        printgrid[6*lcv1+3][12*lcv2+3] = let;
      }
      checker /= 2;
      if (checker%2 == 1) {
        //printgrid[6*lcv1+3][12*lcv2+0] = let;
        printgrid[6*lcv1+3][12*lcv2+1] = let;
        printgrid[6*lcv1+4][12*lcv2+0] = let;
        printgrid[6*lcv1+4][12*lcv2+1] = let;
        printgrid[6*lcv1+4][12*lcv2+2] = let;
        printgrid[6*lcv1+4][12*lcv2+3] = let;
        printgrid[6*lcv1+5][12*lcv2+0] = let;
        //printgrid[6*lcv1+5][12*lcv2+1] = let;
      }
      checker /= 2;
      if (checker%2 == 1) {
        //printgrid[6*lcv1+4][12*lcv2+4] = let;
        printgrid[6*lcv1+5][12*lcv2+2] = let;
        printgrid[6*lcv1+5][12*lcv2+3] = let;
        printgrid[6*lcv1+5][12*lcv2+4] = let;
        printgrid[6*lcv1+5][12*lcv2+5] = let;
      }
      checker /= 2;
      if (checker%2 == 1) {
        printgrid[6*lcv1+5][12*lcv2+6] = let;
        printgrid[6*lcv1+5][12*lcv2+7] = let;
        printgrid[6*lcv1+5][12*lcv2+8] = let;
      }
    }
    if (tokengrid[lcv1][lcv2][1][lcv3] != ' ') {
      let = tokengrid[lcv1][lcv2][1][lcv3];
      checker = countgrid[lcv1][lcv2][1][lcv3];
      if (checker%2 == 1) {
        printgrid[6*lcv1+0][12*lcv2+10] = let;
        //printgrid[6*lcv1+0][12*lcv2+11] = let;
        printgrid[6*lcv1+1][12*lcv2+8] = let;
        printgrid[6*lcv1+1][12*lcv2+9] = let;
        printgrid[6*lcv1+1][12*lcv2+10] = let;
        printgrid[6*lcv1+1][12*lcv2+11] = let;
        printgrid[6*lcv1+2][12*lcv2+10] = let;
        printgrid[6*lcv1+2][12*lcv2+11] = let;
      }
      checker /= 2;
      if (checker%2 == 1) {
        printgrid[6*lcv1+0][12*lcv2+7] = let;
        printgrid[6*lcv1+0][12*lcv2+8] = let;
        printgrid[6*lcv1+0][12*lcv2+9] = let;
      }
      checker /= 2;
      if (checker%2 == 1) {
        printgrid[6*lcv1+0][12*lcv2+3] = let;
        printgrid[6*lcv1+0][12*lcv2+4] = let;
        printgrid[6*lcv1+0][12*lcv2+5] = let;
        printgrid[6*lcv1+0][12*lcv2+6] = let;
        //printgrid[6*lcv1+1][12*lcv2+7] = let;
      }
      checker /= 2;
      if (checker%2 == 1) {
        //printgrid[6*lcv1+0][12*lcv2+1] = let;
        printgrid[6*lcv1+0][12*lcv2+2] = let;
        printgrid[6*lcv1+1][12*lcv2+3] = let;
        printgrid[6*lcv1+1][12*lcv2+4] = let;
        printgrid[6*lcv1+1][12*lcv2+5] = let;
        printgrid[6*lcv1+1][12*lcv2+6] = let;
        //printgrid[6*lcv1+2][12*lcv2+5] = let;
        printgrid[6*lcv1+2][12*lcv2+6] = let;
      }
      checker /= 2;
      if (checker%2 == 1) {
        printgrid[6*lcv1+2][12*lcv2+7] = let;
        printgrid[6*lcv1+2][12*lcv2+8] = let;
        printgrid[6*lcv1+3][12*lcv2+7] = let;
        printgrid[6*lcv1+3][12*lcv2+8] = let;
        printgrid[6*lcv1+3][12*lcv2+9] = let;
        printgrid[6*lcv1+4][12*lcv2+9] = let;
        printgrid[6*lcv1+4][12*lcv2+10] = let;
        //printgrid[6*lcv1+5][12*lcv2+11] = let;
      }
      checker /= 2;
      if (checker%2 == 1) {
        printgrid[6*lcv1+2][12*lcv2+9] = let;
        printgrid[6*lcv1+3][12*lcv2+10] = let;
        printgrid[6*lcv1+3][12*lcv2+11] = let;
        printgrid[6*lcv1+4][12*lcv2+11] = let;
      }
    }
  }
}

void clearall (void) {
  gridhei = 0;
  gridwid = 0;
  for (int lcv1=0;lcv1<MAXGSIZE;lcv1++)
  for (int lcv2=0;lcv2<MAXGSIZE;lcv2++) {
    tokengrid[lcv1][lcv2][0][0] = ' ';
    tokengrid[lcv1][lcv2][0][1] = ' ';
    tokengrid[lcv1][lcv2][1][0] = ' ';
    tokengrid[lcv1][lcv2][1][1] = ' ';
  }
  for (int lcv1=0;lcv1<6*MAXGSIZE;lcv1++)
  for (int lcv2=0;lcv2<10*MAXGSIZE;lcv2++) {
    printgrid[lcv1][lcv2] = ' ';
  }
}

void getpiece (ifstream & in) {
  int piecenum, row, col, ori;
  int rownum, colnum, t1, t2;

  in.get(); in.get(); in.get(); in.get(); in.get(); in.get();
  in >> piecenum;
  in.get(); in.get(); in.get(); in.get(); in.get(); in.get();
  in >> row;
  in.get(); in.get(); in.get(); in.get(); in.get(); in.get();
  in >> col;
  in.get(); in.get(); in.get(); in.get(); in.get(); in.get();
  in >> ori;
  in >> ws;

  rownum = row-1;
  while ((in.peek()!='P') && (in.peek()!= 'T') && (in.peek()!= 'S')) {
    rownum++;
    in >> ws;
    colnum = col-1;
    while ((int)(in.peek())!=10) {
      colnum++;
      in >> t1 >> t2;
      in.get();
      if (t1 == 9) {
        tokengrid[rownum][colnum][0][0] = piecetoken;
        tokengrid[rownum][colnum][0][1] = piecetoken;
        countgrid[rownum][colnum][0][0] = 4*7;
        countgrid[rownum][colnum][0][1] = 5*7;
        if (gridhei < rownum) gridhei = rownum;
        if (gridwid < colnum) gridwid = colnum;
      } else if (t1 == 0) {
      } else if (tokengrid[rownum][colnum][0][0] == ' ') {
        tokengrid[rownum][colnum][0][0] = piecetoken;
        countgrid[rownum][colnum][0][0] = t1*7;
        if (gridhei < rownum) gridhei = rownum;
        if (gridwid < colnum) gridwid = colnum;
      } else {
        tokengrid[rownum][colnum][0][1] = piecetoken;
        countgrid[rownum][colnum][0][1] = t1*7;
        if (gridhei < rownum) gridhei = rownum;
        if (gridwid < colnum) gridwid = colnum;
      }

      if (t2 == 9) {
        tokengrid[rownum][colnum][1][0] = piecetoken;
        tokengrid[rownum][colnum][1][1] = piecetoken;
        countgrid[rownum][colnum][1][0] = 4*7;
        countgrid[rownum][colnum][1][1] = 5*7;
        if (gridhei < rownum) gridhei = rownum;
        if (gridwid < colnum) gridwid = colnum;
      } else if (t2 == 0) {
      } else if (tokengrid[rownum][colnum][1][0] == ' ') {
        tokengrid[rownum][colnum][1][0] = piecetoken;
        countgrid[rownum][colnum][1][0] = t2*7;
        if (gridhei < rownum) gridhei = rownum;
        if (gridwid < colnum) gridwid = colnum;
      } else {
        tokengrid[rownum][colnum][1][1] = piecetoken;
        countgrid[rownum][colnum][1][1] = t2*7;
        if (gridhei < rownum) gridhei = rownum;
        if (gridwid < colnum) gridwid = colnum;
      }

    }
    in.get();
  }
  
}

void main (int argc, char * argv []) {
  ifstream gd;
  int solnum=0;

  gd.open(argv[1],ios::in);
  while (gd.peek() != EOF) {
    while ((gd.peek() != EOF) && (gd.peek() != '!')) gd.get();
    if (gd.peek() == '!') {
      solnum++;
      piecetoken='A';
      piecetoken--;
      cout << "Solution number " << solnum << ":\n";
      clearall();
      while (gd.peek() != 'P') gd.get();
      while (gd.peek() == 'P') {
        piecetoken++;
        getpiece(gd);
      }
      gridhei++;
      gridwid++;
      fillgrid();
      printsol();
    }
  }
  gd.close();
  
  cout << solnum << " total solutions.\n";
}
