17 #define SIZE_TOT (SIZE_EDGE*SIZE_EDGE)
19 typedef unsigned char num;
20 typedef unsigned int pos;
21 typedef num field[SIZE_TOT];
23 #define INVALID_POS ((pos)-1)
25 #define RC_ENTRY(x,y) ((y)*SIZE_EDGE+(x))
28 #define STATES_TOT (362880)
29 #define FILENAME_23 "Nokia61_23.cache"
30 #define ROUNDCYCLE_TOT (sizeof(roundcycle)/sizeof(*roundcycle))
31 static const unsigned char roundcycle[]={
38 #error "STATES_TOT not known!"
50 pos states_touched=0,states_retouched=0,states_done=0;
54 static const num ascending[25]={0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24};
56 static int check_field(const field fld)
58 unsigned char used[SIZE_TOT];
61 memset(used,0,sizeof(used));
62 for (i=0;i<SIZE_TOT;i++) {
63 if (fld[i]>=SIZE_TOT || used[fld[i]])
70 #define assert_field(fld) assert(check_field(fld))
72 static void dump_field(const field fld)
76 for (y=0;y<SIZE_EDGE;y++) {
78 for (x=0;x<SIZE_EDGE;x++)
79 printf(" %2u",fld[y*SIZE_EDGE+x]+1);
84 static pos field_to_pos(const field fld)
86 num points[SIZE_TOT],remains;
90 puts("field_to_pos(");
95 memcpy(points,ascending,sizeof(points));
96 for (remains=SIZE_TOT;remains;remains--) {
99 n=(num *)memchr(points,n,remains)-points;
102 memmove(points+n,points+n+1,remains-n-1);
112 static void pos_to_field(field fld,pos p)
114 num points[SIZE_TOT],expanded[SIZE_TOT],remains;
115 #if defined(DEBUG) || !defined(NDEBUG)
123 printf("pos_to_field(%u)=\n",p);
126 for (remains=1;remains<=SIZE_TOT;remains++) {
130 expanded[SIZE_TOT-remains]=n;
132 memcpy(points,ascending,sizeof(points));
133 for (remains=SIZE_TOT;remains;remains--) {
134 num n=expanded[SIZE_TOT-remains];
138 memmove(points+n,points+n+1,remains-n-1);
142 dump_field(fld_orig);
146 assert(p_orig==field_to_pos(fld_orig));
149 static void mark(pos p,pos parent,pos depth)
153 assert(p>=0 && p<STATES_TOT);
155 if (!(state->parent==INVALID_POS || state->depth>depth))
161 state->parent=parent;
163 if (state->todo_next==INVALID_POS) {
165 todo_tail=&state->todo_next;
177 static void progress_dump(void)
180 printf("TOUCHED=%6u (RETOUCHED %6u), DONE=%6u, KNOWN TODO=%6u, UNTOUCHED=%6u, MAXDEPTH=%6u\n",
181 states_touched,states_retouched,states_done,states_touched-states_done,STATES_TOT-states_touched,maxdepth);
186 static void states_progress(void)
188 static unsigned period=0;
189 static time_t time_last=0;
192 if (period++<PROGRESS)
195 if (time(&time_new)<5+time_last)
202 static void cycle(void)
206 while ((p=todo)!=INVALID_POS) {
207 struct state *state=states+p;
209 unsigned char y,x,cyc;
213 printf("START: %u\n",p);
215 for (y=0;y<=SIZE_EDGE-SIZE_ROT;y++)
216 for (x=0;x<=SIZE_EDGE-SIZE_ROT;x++)
217 for (cyc=0;cyc<ROUNDCYCLE_TOT;cyc++) {
221 base=fld+y*SIZE_EDGE+x;
222 for (cyci=0;cyci<ROUNDCYCLE_TOT-1;cyci++) {
223 swap=base[roundcycle[cyci]];
224 base[roundcycle[cyci]]=base[roundcycle[cyci+1]];
225 base[roundcycle[cyci+1]]=swap;
230 mark(field_to_pos(fld),p,state->depth+1);
232 todo=state->todo_next;
233 state->todo_next=INVALID_POS;
241 static void final(void)
251 fputs("Depth distribution:",stdout);
252 maxes=malloc(sizeof(*maxes)*(maxdepth+1));
253 memset(maxes,0,sizeof(maxes));
254 for (p=0;p<STATES_TOT;p++)
255 maxes[states[p].depth]++;
256 for (maxi=0;maxi<=maxdepth;maxi++)
257 printf(" %d(=%d)",maxi,maxes[maxi]);
266 static struct item_23 {
269 #define STATES_23_SIZEOF (sizeof(*states_23)*STATES_TOT)
271 static int read_23(void)
275 unsigned char eof_mark;
277 if (!(f=fopen(FILENAME_23,"rb")))
279 if (!(states_23=malloc(STATES_23_SIZEOF))) {
284 if (fread(states_23,1,STATES_23_SIZEOF,f)!=STATES_23_SIZEOF) {
289 if (fread(&eof_mark,1,1,f))
291 for (p=0;p<STATES_TOT;p++) {
293 states[p].parent=(states_23[p].a[0]<<16)
294 | (states_23[p].a[1]<< 8)
295 | (states_23[p].a[2]<< 0);
300 printf("Cache read from \"%s\".\n",FILENAME_23);
305 static void write_23(void)
310 if (!(f=fopen(FILENAME_23,"wb"))) {
313 printf("Failed to write cache to \"%s\"!\n",FILENAME_23);
317 if (!(states_23=malloc(STATES_23_SIZEOF))) {
323 for (p=0;p<STATES_TOT;p++) {
324 states_23[p].a[0]=(states[p].parent>>16);
325 states_23[p].a[1]=(states[p].parent>> 8);
326 states_23[p].a[2]=(states[p].parent>> 0);
328 if (fwrite(states_23,1,STATES_23_SIZEOF,f)!=STATES_23_SIZEOF) {
337 printf("Cache written to \"%s\".\n",FILENAME_23);
341 #endif /* SIZE_EDGE==3 */
343 static void input(void)
352 for (y=0;y<SIZE_EDGE;y++) {
353 printf("Enter line #%d/%d: ",y+1,SIZE_EDGE); fflush(stdout);
354 for (x=0;x<SIZE_EDGE;x++) {
355 if (1!=scanf("%d",&i)) {
358 puts("Error reading input, restarting!");
361 fld[y*SIZE_EDGE+x]=i-1;
364 if (!check_field(fld)) {
365 puts("Field not valid!");
372 printf("STATE %6u: DEPTH=%6u, PARENT=%6u\n",p,state->depth,state->parent);
377 } while (state!=states+0);
388 memset(states,-1,sizeof(states));
397 return(EXIT_SUCCESS);