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

using namespace std;

int quarkdata[][6] = {
  {0,1,0,1,0,2},
  {0,3,5,1,3,1},
  {0,0,0,6,3,1},
  {0,0,7,0,9,3},
  {0,6,0,3,0,1},
  {0,0,0,10,1,1},
  {0,0,11,11,0,2},
  {0,6,1,0,6,1},
  {0,0,0,1,5,1},
  {0,0,1,0,1,5},
  {0,0,0,6,4,1},
  {0,0,7,0,9,3},
  {0,10,0,3,10,4},
  {0,0,4,9,0,8},
  {0,0,6,5,0,6},
  {0,2,3,9,2,7},
  {0,0,3,1,0,6},
  {0,0,12,11,0,2},
  {1,9,10,1,9,10},
  {0,0,0,2,12,11},
  {0,0,10,0,12,11},
  {0,9,0,9,0,10},
  {0,0,3,4,0,2},
  {0,0,12,11,0,10},
  {0,0,0,12,12,10},
  {0,0,5,6,0,6},
  {0,1,0,1,0,2},
  {8,1,6,8,1,6},
  {0,0,2,7,0,8},
  {0,1,0,1,0,5},
  {0,0,1,0,1,10},
  {0,0,0,6,2,6},
  {0,0,1,0,1,5},
  {0,0,7,0,0,7},
  {0,0,1,0,0,1},
  {0,0,1,0,5,1},
  {10,2,1,10,2,1},
};

int order[] = {
  24, 17, 25, 32, 31, 23, 16, 9, 10, 18,
  26, 33, 40, 39, 38, 30, 22, 15, 8, 1,
  2, 3, 11, 19, 27, 34, 41, 48, 47, 46,
  45, 37, 29, 21, 14, 7, 0,
};

int placed[37];  // -1 == unplaced.
int placement[49];

bool in_range(int cell) {
  if (cell < 0) return false;
  if (cell >= 49) return false;
  return true;
}

int get_edge(int piecenum, int edge) {
  assert(placed[piecenum] != -1);
  return quarkdata[piecenum][(edge+placed[piecenum])%6];  
}

char value(int row, int col) {
  if ((row%2==0)&&(col%2==0)) return '+';
  if ((row%2==1)&&(col%2==1)) return ' ';
  int cell = row/2*7+(col/2+row/2-3)/2;
  if (((row+col)%4 == 1) && (row%2 == 1)) {
    return ' ';
  } 
  if (((row+col)%4 == 1) && (row%2 == 0)) {
    if (in_range(cell) && placement[cell] != -1) {
      return('0'+get_edge(placement[cell],1));
    } else if (in_range(cell-7) && placement[cell-7] != -1) {
      return('0'+get_edge(placement[cell-7],4));
    } else {
      return ' ';
    }
  }
  if (((row+col)%4 == 3) && (row%2 == 0)) {
    if (in_range(cell) && placement[cell] != -1) {
      return('0'+get_edge(placement[cell],0));
    } else if (in_range(cell-8) && placement[cell-8] != -1) {
      return('0'+get_edge(placement[cell-8],3));
    } else {
      return ' ';
    }
  }
  if (((row+col)%4 == 3) && (row%2 == 1)) {
    if (in_range(cell) && placement[cell] != -1) {
      return('0'+get_edge(placement[cell],5));
    } else if (in_range(cell-1) && placement[cell-1] != -1) {
      return('0'+get_edge(placement[cell-1],2));
    } else {
      return ' ';
    }
  }
  return ' ';
}

void printerr() {
  for (int row=0;row<15;row++) {
    for (int col=0;col<29;col++) {
      cerr << value(row,col);
    }
    cerr << "\n";
  } 
}

void print() {
  for (int row=0;row<15;row++) {
    for (int col=0;col<29;col++) {
      cout << value(row,col);
    }
    cout << "\n";
  } 
}

bool valid(int level) {
  int my_pos = order[level];
  for (int other = 0; other < level; other++) {
    int other_pos = order[other];
    if (other_pos + 8 == my_pos) {
      if (get_edge(placement[other_pos],3) !=
          get_edge(placement[my_pos],0)) return false;
    } else if (other_pos + 7 == my_pos) {
      if (get_edge(placement[other_pos],4) !=
          get_edge(placement[my_pos],1)) return false;
    } else if (other_pos + 1 == my_pos) {
      if (get_edge(placement[other_pos],2) !=
          get_edge(placement[my_pos],5)) return false;
    } else if (other_pos - 1 == my_pos) {
      if (get_edge(placement[other_pos],5) !=
          get_edge(placement[my_pos],2)) return false;
    } else if (other_pos - 7 == my_pos) {
      if (get_edge(placement[other_pos],1) !=
          get_edge(placement[my_pos],4)) return false;
    } else if (other_pos - 8 == my_pos) {
      if (get_edge(placement[other_pos],0) !=
          get_edge(placement[my_pos],3)) return false;
    }
  }
  return true;
}

int numsols = 0;
int iters = 0;

void recurse(int level) {
  iters++;
  if (iters > 1000000) {
    cerr << numsols << " level " << level << "\n";
    printerr();
  }
  if (level == 0) {
    int piecenum = 0;
    int orientation = 0;
    placed[piecenum] = orientation;
    placement[order[level]] = piecenum;
    recurse(1);
  } else if (level == 37) {
    numsols++;
    print();
  } else {
    for (int piecenum = 0; piecenum < 37; ++piecenum) {
      if (placed[piecenum] != -1) continue;
      placement[order[level]] = piecenum;
      for (int orientation = 0; orientation < 6; ++orientation) {
        placed[piecenum] = orientation;
        if (valid(level)) {
          recurse(level+1);
        }
      } 
      placement[order[level]] = -1;
      placed[piecenum] = -1;
    }
  }
};

int main() {
  for (int i=0; i<37; ++i) {
    placed[i] = -1;
  }
  for (int i=0; i<49; ++i) {
    placement[i] = -1;
  }
  recurse(0);
}
