#include #include #include #define NPC 11 #define MAXSOLNS 4096 unsigned int pcshapes[NPC] #define PC(a,b,c,d,e,f,g,h,i,j,k,l) \ ( ((a)?(1U<<24):0) | \ ((b)?(1U<<23):0) | \ ((c)?(1U<<22):0) | \ ((d)?(1U<<21):0) | \ ((e)?(1U<<19):0) | \ ((f)?(1U<<18):0) | \ ((g)?(1U<<17):0) | \ ((h)?(1U<<16):0) | \ ((i)?(1U<<14):0) | \ ((j)?(1U<<13):0) | \ ((k)?(1U<<12):0) | \ ((l)?(1U<<11):0) ) #define _ 0 #define X 1 = { PC( X,X,X,_, _,X,_,_, _,X,_,_ ), PC( X,_,X,_, X,X,X,_, _,_,_,_ ), PC( X,_,_,_, X,_,_,_, X,X,X,_ ), PC( X,_,_,_, X,X,_,_, _,X,X,_ ), PC( _,X,_,_, X,X,X,_, _,X,_,_ ), PC( _,X,_,_, X,X,X,X, _,_,_,_ ), PC( X,X,_,_, _,X,_,_, _,X,X,_ ), PC( _,X,X,_, X,X,_,_, _,X,_,_ ), PC( X,X,X,X, X,_,_,_, _,_,_,_ ), PC( X,X,_,_, X,X,_,_, X,_,_,_ ), PC( _,X,X,X, X,X,_,_, _,_,_,_ ) }; #undef X #undef _ #undef PC typedef struct pc PC; typedef struct place PLACE; struct pc { int nforms; unsigned int *forms; int *nx; int *ny; } ; struct place { int pc; int form; int x; int y; } ; static PC pcs[NPC]; static unsigned int *formv; static int *nxyv; static PLACE placement[5]; static char pform[25]; static char solns[MAXSOLNS][25]; static int nsolns; static char usolns[MAXSOLNS][25]; static int nusolns; #define COL(n) (0x1084210>>(n)) #define ROW(n) (0x1f00000>>((n)*5)) static unsigned int lrcorner(unsigned int v) { while ((v & COL(4)) == 0) v >>= 1; while ((v & ROW(4)) == 0) v >>= 5; return(v); } static unsigned int flipx(unsigned int v) { return(lrcorner( ((v & COL(0)) >> 4) | ((v & COL(1)) >> 2) | (v & COL(2)) | ((v & COL(3)) << 2) | ((v & COL(4)) << 4) )); } static unsigned int flipy(unsigned int v) { return(lrcorner( ((v & ROW(0)) >> (4*5)) | ((v & ROW(1)) >> (2*5)) | (v & ROW(2)) | ((v & ROW(3)) << (2*5)) | ((v & ROW(4)) << (4*5)) )); } static unsigned int transpose(unsigned int v) { return(lrcorner( ((v & ( (ROW(0) & COL(4)) )) >> 16) | ((v & ( (ROW(0) & COL(3)) | (ROW(1) & COL(4)) )) >> 12) | ((v & ( (ROW(0) & COL(2)) | (ROW(1) & COL(3)) | (ROW(2) & COL(4)) )) >> 8) | ((v & ( (ROW(0) & COL(1)) | (ROW(1) & COL(2)) | (ROW(2) & COL(3)) | (ROW(3) & COL(4)) )) >> 4) | (v & ( (ROW(0) & COL(0)) | (ROW(1) & COL(1)) | (ROW(2) & COL(2)) | (ROW(3) & COL(3)) | (ROW(4) & COL(4)) )) | ((v & ( (ROW(1) & COL(0)) | (ROW(2) & COL(1)) | (ROW(3) & COL(2)) | (ROW(4) & COL(3)) )) << 4) | ((v & ( (ROW(2) & COL(0)) | (ROW(3) & COL(1)) | (ROW(4) & COL(2)) )) << 8) | ((v & ( (ROW(3) & COL(0)) | (ROW(4) & COL(1)) )) << 12) | ((v & ( (ROW(4) & COL(0)) )) << 16) )); } static int formnx(unsigned int v) { if (v & COL(0)) abort(); if (v & COL(1)) return(2); if (v & COL(2)) return(3); if (v & COL(3)) return(4); abort(); } static int formny(unsigned int v) { if (v & ROW(0)) abort(); if (v & ROW(1)) return(2); if (v & ROW(2)) return(3); if (v & ROW(3)) return(4); abort(); } static void setup(void) { int i; int j; PC *p; unsigned int forms[8]; int nforms; unsigned int v; int formx; int nxyx; static void addform(unsigned int v) { int i; for (i=nforms-1;i>=0;i--) if (v == forms[i]) return; forms[nforms++] = v; } formv = malloc(8*NPC*sizeof(*formv)); nxyv = malloc(8*NPC*2*sizeof(*nxyv)); formx = 0; nxyx = 0; for (i=0;informs = nforms; p->forms = formv + formx; formx += nforms; for (j=nforms-1;j>=0;j--) p->forms[j] = forms[j]; p->nx = nxyv + nxyx; nxyx += nforms; p->ny = nxyv + nxyx; nxyx += nforms; for (j=nforms-1;j>=0;j--) { p->nx[j] = formnx(p->forms[j]); p->ny[j] = formny(p->forms[j]); } } memset(&pform[0],'?',25); nsolns = 0; nusolns = 0; } static void setpform(unsigned int mask, char ch) { int i; for (i=24;i>=0;i--) if ((mask >> i) & 1) pform[i] = ch; } static void dumptext(char *) __attribute__((__unused__)); static void dumptext(char *pf) { printf(" _________\n" "|%c%c%c%c%c%c%c%c%c|\n" "|%c%c%c%c%c%c%c%c%c|\n" "|%c%c%c%c%c%c%c%c%c|\n" "|%c%c%c%c%c%c%c%c%c|\n" "|_%c_%c_%c_%c_|\n", #define H(x) (pf[(x)]==pf[(x)-5])?' ':'_' #define V(x) (pf[(x)]!=pf[(x)-1]) ? '|' : \ ( (pf[(x)]==pf[(x)-5]) || \ (pf[(x)]==pf[(x)-6]) ) ? ' ' : '_' #define L(x) (pf[(x)]!=pf[(x)-1]) ? '|' : '_' H(24), V(24), H(23), V(23), H(22), V(22), H(21), V(21), H(20), H(19), V(19), H(18), V(18), H(17), V(17), H(16), V(16), H(15), H(14), V(14), H(13), V(13), H(12), V(12), H(11), V(11), H(10), H( 9), V( 9), H( 8), V( 8), H( 7), V( 7), H( 6), V( 6), H( 5), L( 4), L( 3), L( 2), L( 1) ); #undef H #undef V #undef L } #define MAP(name,xrv,yrv) static int map_x_##name(int x __attribute__((\ __unused__)), int y __attribute__((__unused__))){ return(xrv); }\ static int map_y_##name(int x __attribute__((__unused__)), int y\ __attribute__((__unused__))){ return(yrv); } MAP(nil,x,y) MAP(x,4-x,y) MAP(y,x,4-y) MAP(xy,4-x,4-y) MAP(t,y,x) MAP(tx,5-y,x) MAP(ty,y,5-x) MAP(txy,5-y,5-x) #undef MAP static int solnmatch(char *s, int (*fx)(int, int), int (*fy)(int, int)) { int x; int y; int i; int j; int sv; int map[5]; map[0] = -1; map[1] = -1; map[2] = -1; map[3] = -1; map[4] = -1; x = 0; y = 0; for (i=0;i<25;i++) { sv = s[i]; j = (*fx)(x,y) + (5 * (*fy)(x,y)); if (map[sv] < 0) { map[sv] = pform[j]; } else if (map[sv] != pform[j]) { return(0); } x ++; if (x >= 5) { x = 0; y ++; } } return(1); } static void place(unsigned int cur, int inx) { unsigned int lbc; int px; PC *p; int f; int x; int y; unsigned int fm; unsigned long long int key; if (inx > 4) { key = 0; for (x=0;x<25;x++) { if (pform[x] == '?') abort(); key = (key * 5) + pform[x]; } if (nsolns >= MAXSOLNS) abort(); bcopy(&pform[0],&solns[nsolns][0],25); nsolns ++; for (x=nusolns-1;x>=0;x--) { #define TRY(n) do { \ if (solnmatch(&usolns[x][0],&map_x_##n,&map_y_##n)) \ { return; \ } \ } while (0) TRY(nil); TRY(x); TRY(y); TRY(xy); TRY(t); TRY(tx); TRY(ty); TRY(txy); #undef TRY } if (nusolns >= MAXSOLNS) abort(); bcopy(&pform[0],&usolns[nusolns][0],25); nusolns ++; return; } lbc = (cur+1) & ~cur; for (px=NPC-1;px>=0;px--) { p = &pcs[px]; for (f=p->nforms-1;f>=0;f--) { for (y=p->ny[f]-1;y>=0;y--) { for (x=p->nx[f]-1;x>=0;x--) { fm = p->forms[f] << (x+(y*5)); if (! (fm & lbc)) continue; if (fm & cur) continue; placement[inx] = (PLACE){ .pc = px, .form = f, .x = x, .y = y }; setpform(fm,"\0\1\2\3\4"[inx]); place(cur|fm,inx+1); setpform(fm,'?'); } } } } } static void dump(void) { int i; printf("%d %d\n",nusolns,nsolns); for (i=0;i