#include <stdio.h>
#define   MLEN     128
#define   MAX       62
#define   SYMM     ".:/-xo+*c"
#define   symbols  ".,:;!?#$%&@*+=-_<>()[]{}|/\\^'`~\""

char line[MLEN],  buffer[2*MAX+2];
int  n, anz, x[2*MAX], y[2*MAX], grid[MAX][MAX];


main(argc,argv)
int  argc;
char  *argv[];
{
   register  h, i, j, k, flag, lno, m, pflag;
   int  zei, set;
   FILE  *fp;
   k=1;
   do {
	  if (argc <= 1)
	     fp = stdin;
	  else
      {  for (i=0;*(argv[k]+i);i++) ;
         if (*(argv[k]+i-1)=='Z' && *(argv[k]+i-2)=='.'  ||
             *(argv[k]+i-1)=='z' && *(argv[k]+i-2)=='g' && *(argv[k]+i-3)=='.'
             ||  !(fp = fopen(argv[k],"r")) )
         {  char   command[MLEN];
            sprintf(command,"zcat %s",argv[k]);
            if (!(fp = popen(command,"r")))
               return  fprintf(stderr,"can't open %s\n",argv[k]), -1;
            else
               pflag = 1;
         } 
         else
            pflag = 0;
	  }
      lno = 0;
      for (set=0;;set++)
      {
         while ( fgets(line, MLEN, fp) )
         {  lno++;
            flag = 0;
            for (i=0;;i++)
               if (line[i] == ' ')
                  continue;
               else if (line[i] == '.' || line[i]  == 'o')
                  flag = 1;
               else if ((line[i]=='\n' || line[i]=='\0') &&  flag)
                  goto over;
               else
                  break;
         }
         fprintf(stderr,"%s:%4d solutions coded\n",argv[k],set);
         break;
         over:
         n=j=0;
         do {
            for (h=0;h<i;h++)
            {  if (line[h] == ' ' || line[h] == '.')
                  continue;
               else if (line[h] != 'o')
                  return  fprintf(stderr,"illegal character in line %d\n", lno), -2;
               else if (h-1&1)
                  return  fprintf(stderr,"parity error in line %d\n",lno),  -2;
               else
               {  if (n+n+2 <= j)
                     return  fprintf(stderr,"more than 2 in line %d\n",lno), -3;
                  y[j] = zei = (h-1)/2;
				  x[j] = n;
				  j++;
                  buffer[j] = (zei<10?zei+'0':(zei<36?zei-10+'A':zei-36+'a') );
               }
            }
            n++;
            if (n+n != j)
               return  fprintf(stderr,"not exact two in line %d\n",lno), -3;
            if (i==j)  break;
            fgets(line, MLEN, fp);
			lno++;
         } while (1);
		 anz = j;
		 buffer[++j]='\n';
         m = 0;
         for(i=0;i<anz;i++)
            for(j=i+1;j<anz;j++)
               for(h=j+1;h<anz;h++)
                  m += ((x[j]-x[i])*(y[h]-y[i]))==((x[h]-x[i])*(y[j]-y[i]));
         if (m)  fprintf(stderr,"\n%d violating tripel in set %d\n",m,set+1);
         switch( symmetry_check() )
         {  case   1:  buffer[0]=SYMM[0];  break;
            case   3:  buffer[0]=SYMM[2];  break;
            case   9:  buffer[0]=SYMM[3];  break;
            case  17:  buffer[0]=SYMM[1];  break;
            case  33:  buffer[0]=SYMM[2];  break;
            case  51:  buffer[0]=SYMM[4];  break;
            case  85:  buffer[0]=(n&1?SYMM[8]:SYMM[5]);  break;
            case 119:  buffer[0]=(n&1?SYMM[4]:'?');  break;
            case 129:  buffer[0]=SYMM[3];  break;
            case 153:  buffer[0]=SYMM[6];  break;
            case 255:  buffer[0]=SYMM[7];  break;
            default:   buffer[0]='?';
         }
		 fwrite(buffer+0,1,anz+2,stdout);
      }
	  if (argc <= 1)
		 ;
      else if (pflag)
         pclose(fp);
      else
         fclose(fp);
   } while (++k<argc);
}


symmetry_check()
{
  int  i, j, k, a, b, c, s, sym, sym_all;
  for(i=0;i<n;i++)
     for(j=0;j<n;j++)
        grid[i][j] =0;
  for(k=0;k<anz;k++)
     grid[x[k]][y[k]] = 1;
  sym_all = ~0;
  for(k=0;k<anz;k++)
  {
     sym = 0;
     a = x[k];
     b = y[k];
     for(s=0;s<4;s++)
     {  sym <<=1;
        c = n-1-a;
        sym += grid[c][b];
        sym<<=1;
        sym += grid[b][c];
        a = b,   b = c;
     }
	 if ((n&1) && (x[k]==y[k] || x[k] == n-1-y[k]))
		sym |= 68;
     sym_all &= sym ;
  }
  return  sym_all;
}

