#include <stdio.h>
#define  MAX  62
#define  SYMM  ".:/-ox+*c"
#define  DIFFER  40000

char  list[DIFFER][2*MAX+2];
int   set, anz, n, no, x[2*MAX], y[2*MAX], grid[MAX][MAX];
char  buffer[2*MAX+2], *sym_class;
FILE  *fp;
#define   VERT  128
#define   HORI   64
#define   ROTA   32
#define   LEFT   16
#define   RIGH    8
#define   SIDE    4
#define   MAIN    2
#define   IDEN    1


main(argc,argv)
int  argc;
char  *argv[];
{
register  h, i, j, k, m, code;
   if (!(fp = (argc > 1 ? fopen(argv[1],"r") : stdin)))
   fprintf(stderr,"can't open %s\n",argv[1]),  exit(-1);
   for (no=m=0, set=1; fgets(buffer,2*MAX+2,fp) ; set++)
   {  n = 0;
      for (anz=1;buffer[anz];anz++)
      {  if (buffer[anz]=='\n')  break;
         if (anz==2*MAX)
			fprintf(stderr,"too manny points in set %u\n",set),  exit(-1);
		 if (buffer[anz] <= '9')
            x[anz-1] = buffer[anz] - '0';
		 else if (buffer[anz] >= 'A' && buffer[anz] <= 'Z')
            x[anz-1] = buffer[anz] - 'A' + 10;
		 else if (buffer[anz] >= 'a' && buffer[anz] <= 'z')
            x[anz-1] = buffer[anz] - 'a' + 36;
         else
            fprintf(stderr,"code error in set %u\n", set),  exit(-1);
         if (x[anz-1] > n)  n = x[anz-1];
         y[anz-1] = (anz-1)/2;
      }
	  anz--;
	  n++;
	  if (2*n != anz)
		 fprintf(stderr,"set=%d  n=%d  anz=%d\n", set, n, anz),  exit (-1);
	  for (h=1;h<=8;h++)
	  {  
		 for (i=0;i<n;i++)
		 for (j=0;j<n;j++)
		    grid[i][j] = 0;
		 for (k=0;k<anz;k++)
            grid[ y[k] ][ x[k] ] = 1; 
         if (buffer[0]==SYMM[8] && (n&1) /* else o could be coded as c undiscovered! */ )
         {  for (i=0;i<n;i++)
              if (grid[i][i])
                 grid[n-1-i][i]=1;
            else if (grid[n-1-i][i])
                 grid[i][i]=1;
         }
         if (code=sym_test())  break;
		 for (k=0;k<anz;k++)
		    if (h==4 || h==8)
            {  i=x[k];  x[k]=y[k];  y[k]= i;  }
		    else
            {  i=x[k];  x[k]=y[k];  y[k]= n-1-i;  }
	  }
	  if (h>8)
		 return  fprintf(stderr,"error in sym_test of set %u: %s\n",set,buffer);
	  else if (h!=1)
      {  m++;
	     k=1;
		 if ((n&1) && (code&(LEFT|RIGH)) && !(code&(SIDE|MAIN|VERT|HORI)))
			for (i=0;i<n;i++)
			   grid[i][n-1-i]=0;
	     for (i=0;i<n;i++)
	     for (j=0;j<n;j++)
		    if (grid[i][j])
			   buffer[k++] = (j<10  ? '0'+j : (j<36 ? 'A'+j-10 : 'a'+j-36) );
		 buffer[k++]='\n';
         buffer[k]='\0';
#ifdef  MARK
		 printf("!");
#endif
      }
	  if (SYMM[symmetry_found(code)]!=buffer[0])
		 fprintf(stderr,"error in symmetry of set %u: Is %s\n",set,sym_class);
      for (h=0;h<anz;h++)
		 list[no][h] = buffer[h];
      list[no][h]='\0';
	  for (k=0;k<no;k++)
	  {
         for (h=0;h<anz && list[k][h];h++)
		    if (list[k][h] != buffer[h])  break;
         if (h==anz && !list[k][h])
		 {  no--;
#ifdef  MARK
            printf("=");
#else
		    fprintf(stderr,"MATCH:  %d set  with  %d diff. set: %c\n",set,k+1,buffer[0]);
#endif
         }
      }
      if (++no == DIFFER)
		 fprintf(stderr,"list overflow\n"), exit(-2);
      fprintf(stdout,"%s",buffer);
   }
   fclose(fp);
   fprintf(stderr,"%u sets checked. Of these"
				  " are %u multiple"
				  " and %u has been normalized"
				  "\n",set-1,set-1-no,m);
   return(0);
}



int sym_test()
{
register   h, i, j, k, r, s, ii, jj, code;
   code = VERT | HORI | ROTA | LEFT | RIGH | SIDE | MAIN | IDEN ;
   for (k=1+(n&1);k<=n;k+=2)
   {
      i = j = n/2;
      i -= k/2;
      r = -k/2;
      s = 0;
      if (!(n&1))
      {
         i--;  j--;
         if (!r)  s = k/2;
      }
      ii = n-1-i;
      jj = n-1-j;
      for (h=4*k;h;h--)
      {
         if (grid[i][j])
         {
            if ((code&VERT) && !grid[ii][j])   code &= ~VERT;
            if ((code&HORI) && !grid[i][jj])   code &= ~HORI;
            if ((code&ROTA) && !grid[ii][jj])  code &= ~ROTA;
            if ((code&LEFT) && !grid[j][ii])   code &= ~LEFT;
            if ((code&RIGH) && !grid[jj][i])   code &= ~RIGH;
            if ((code&SIDE) && !grid[jj][ii])  code &= ~SIDE;
            if ((code&MAIN) && !grid[j][i])    code &= ~MAIN;
            if (code==IDEN)  return  IDEN;
         }
         else
         {
            if ((code&VERT) && grid[ii][j])   return  0;
            if ((code&HORI) && grid[i][jj])   return  0;
            if ((code&ROTA) && grid[ii][jj])  return  0;
            if ((code&LEFT) && grid[j][ii])   return  0;
            if ((code&RIGH) && grid[jj][i])   return  0;
            if ((code&SIDE) && grid[jj][ii])  return  0;
            if ((code&MAIN) && grid[j][i])    return  0;
         }
         if (r>0)       {  j++;  r--;  jj--;  if (!r)  s = -k;  }
         else if (r<0)  {  j--;  r++;  jj++;  if (!r)  s = k;  }
         if (s>0)       {  i++;  s--;  ii--;  if (!s)  r = k;  }
         else if (s<0)  {  i--;  s++;  ii++;  if (!s)  r = -k;  }
      }
   }
   return  code;
}


symmetry_found(code)
int  code;
{
register   i, j;
int  vert, hori, rot2, left, right, haupt, neben;
   vert  = code&VERT;
   hori  = code&HORI;
   rot2  = code&ROTA;
   left  = code&LEFT;
   right = code&RIGH;
   neben = code&SIDE;
   haupt = code&MAIN;
   if (vert && hori && rot2 && left && right)  sym_class="full",  j=7;
   else if (vert && hori && !left && !right)  sym_class="ort2",  j=6;
   else if (!vert && !hori && neben && haupt)  sym_class="dia2",  j=5;
   else if (left && right && (n&1))  sym_class="rct4",  j=8;
   else if (left && right)  sym_class="rot4",  j=4;
   else if (vert || hori)  sym_class="ort1",  j=3;
   else if (haupt || neben)  sym_class="dia1",  j=2;
   else if (rot2)  sym_class="rot2",  j=1;
   else  sym_class="iden",  j=0;
   return  j;
}

