Revision d12d901a
Added by Leszek Koltunski over 2 years ago
src/main/java/org/distorted/objectlib/scrambling/ScrambleStateBandaged3x3.java | ||
---|---|---|
28 | 28 |
{ |
29 | 29 |
private static final long INVALID_MOVE = -1; |
30 | 30 |
private static final int NUM_MOVES = 27; |
31 |
private static final int NUM_ISOMETRIES = 24; |
|
32 | 31 |
|
33 | 32 |
private static final int AXIS_X = 0; |
34 | 33 |
private static final int AXIS_Y = 1; |
... | ... | |
39 | 38 |
private static final int LAYER_R = 2; |
40 | 39 |
|
41 | 40 |
private long mID; |
42 |
private final long[] mIsometries;
|
|
41 |
private int mDistance;
|
|
43 | 42 |
private final long[] mMoves; |
44 | 43 |
|
45 | 44 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
46 | 45 |
|
47 | 46 |
public ScrambleStateBandaged3x3(long id) |
48 | 47 |
{ |
48 |
mDistance = -1; |
|
49 | 49 |
mID = id; |
50 |
mIsometries = createIsometries(mID); |
|
51 | 50 |
mMoves = createMoves(mID); |
52 | 51 |
} |
53 | 52 |
|
... | ... | |
60 | 59 |
graph.add(bsg); |
61 | 60 |
|
62 | 61 |
insertChildren(graph,id); |
63 |
pruneGraph(graph,id); |
|
62 |
pruneGraph(graph,id,false); |
|
63 |
computeDistance(graph,id,0); |
|
64 |
removeDisconnectedParts(graph); |
|
64 | 65 |
remapGraph(graph); |
65 | 66 |
|
66 | 67 |
int num = graph.size(); |
... | ... | |
79 | 80 |
{ |
80 | 81 |
ScrambleStateBandaged3x3 bsg = findState(list,id); |
81 | 82 |
|
82 |
android.util.Log.e("D", "inserting children of "+id); |
|
83 |
|
|
84 | 83 |
if( bsg==null ) |
85 | 84 |
{ |
86 | 85 |
android.util.Log.e("D", "error: "+id+" doesn't exist"); |
... | ... | |
103 | 102 |
} |
104 | 103 |
else if( tmp.mID != move ) |
105 | 104 |
{ |
106 |
android.util.Log.e("D", "id "+id+" move: "+move+" leads to already existing "+tmp.mID); |
|
107 | 105 |
bsg.setMove(i,tmp.mID); |
108 | 106 |
} |
109 | 107 |
} |
... | ... | |
112 | 110 |
|
113 | 111 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
114 | 112 |
|
115 |
private static void pruneGraph(ArrayList<ScrambleStateBandaged3x3> list, long id) |
|
113 |
private static void pruneGraph(ArrayList<ScrambleStateBandaged3x3> list, long id, boolean startingPrunedAlready)
|
|
116 | 114 |
{ |
117 | 115 |
int num = list.size(); |
118 | 116 |
boolean pruned = false; |
... | ... | |
125 | 123 |
if( bsg.numAxis()<2 ) |
126 | 124 |
{ |
127 | 125 |
long prunedID = bsg.getID(); |
126 |
if( id!=prunedID || !startingPrunedAlready ) |
|
127 |
{ |
|
128 |
startingPrunedAlready = true; |
|
129 |
remapID(list,prunedID,INVALID_MOVE); |
|
130 |
} |
|
128 | 131 |
|
129 |
android.util.Log.e("D", "pruning id "+prunedID+" axis: "+bsg.numAxis() ); |
|
130 |
bsg.printMoves(); |
|
131 |
|
|
132 |
if( id!=prunedID ) list.remove(i); // do not remove the starting point, even if |
|
133 |
// it does have only 1 axis |
|
134 |
pruned = true; |
|
135 |
remapID(list,prunedID,INVALID_MOVE); |
|
136 |
break; |
|
132 |
// do not remove the starting point, even if it does have only 1 axis |
|
133 |
if( id!=prunedID ) |
|
134 |
{ |
|
135 |
list.remove(i); |
|
136 |
pruned = true; |
|
137 |
break; |
|
138 |
} |
|
137 | 139 |
} |
138 | 140 |
} |
139 | 141 |
|
140 |
if( pruned ) pruneGraph(list,id); |
|
141 |
} |
|
142 |
|
|
143 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
144 |
|
|
145 |
private void printMoves() |
|
146 |
{ |
|
147 |
String moves = ""; |
|
148 |
|
|
149 |
for(int i=0; i<NUM_MOVES; i++) |
|
150 |
{ |
|
151 |
moves += (" " + mMoves[i]); |
|
152 |
} |
|
153 |
|
|
154 |
android.util.Log.e("D", moves); |
|
142 |
if( pruned ) pruneGraph(list,id,startingPrunedAlready); |
|
155 | 143 |
} |
156 | 144 |
|
157 | 145 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
... | ... | |
191 | 179 |
|
192 | 180 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
193 | 181 |
|
194 |
private static boolean isAnIsometry(ScrambleStateBandaged3x3 bsg, long id)
|
|
182 |
private static void computeDistance(ArrayList<ScrambleStateBandaged3x3> list, long id, int distance)
|
|
195 | 183 |
{ |
196 |
if( bsg.mID==id ) return true; |
|
197 |
for(int i=0; i<NUM_ISOMETRIES-1; i++) if ( bsg.mIsometries[i]==id ) return true; |
|
198 |
return false; |
|
184 |
ScrambleStateBandaged3x3 state = findState(list,id); |
|
185 |
|
|
186 |
if( state==null ) |
|
187 |
{ |
|
188 |
android.util.Log.e("D", "error: "+id+" doesn't exist"); |
|
189 |
return; |
|
190 |
} |
|
191 |
|
|
192 |
if( state.mDistance<0 ) |
|
193 |
{ |
|
194 |
state.mDistance = distance; |
|
195 |
|
|
196 |
for(int i=0; i<NUM_MOVES; i++) |
|
197 |
{ |
|
198 |
long move = state.getMove(i); |
|
199 |
|
|
200 |
if( move!=INVALID_MOVE ) |
|
201 |
{ |
|
202 |
computeDistance(list,move,distance+1); |
|
203 |
} |
|
204 |
} |
|
205 |
} |
|
206 |
} |
|
207 |
|
|
208 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
209 |
|
|
210 |
private static void removeDisconnectedParts(ArrayList<ScrambleStateBandaged3x3> list) |
|
211 |
{ |
|
212 |
int num = list.size(); |
|
213 |
ScrambleStateBandaged3x3 bsg; |
|
214 |
|
|
215 |
for(int i=0; i<num; i++) |
|
216 |
{ |
|
217 |
bsg = list.get(i); |
|
218 |
|
|
219 |
if( bsg.mDistance<0 ) |
|
220 |
{ |
|
221 |
list.remove(i); |
|
222 |
i--; |
|
223 |
num--; |
|
224 |
} |
|
225 |
} |
|
199 | 226 |
} |
200 | 227 |
|
201 | 228 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
... | ... | |
208 | 235 |
for(int i=0; i<num; i++) |
209 | 236 |
{ |
210 | 237 |
bsg= list.get(i); |
211 |
if( isAnIsometry(bsg,id) ) return bsg;
|
|
238 |
if( bsg.mID==id ) return bsg;
|
|
212 | 239 |
} |
213 | 240 |
|
214 | 241 |
return null; |
... | ... | |
222 | 249 |
String y = getTable(bsg, 9); |
223 | 250 |
String z = getTable(bsg,18); |
224 | 251 |
|
225 |
return " new ScrambleStateGraph( new int[][] { "+x+", "+y+", "+z+" } ),";
|
|
252 |
return " new ScrambleState( new int[][] { "+x+", "+y+", "+z+" } ),"; |
|
226 | 253 |
} |
227 | 254 |
|
228 | 255 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
... | ... | |
241 | 268 |
|
242 | 269 |
String ret = ""; |
243 | 270 |
|
244 |
if( m0!=INVALID_MOVE ) ret += formatRet(ret,0, 1,m0);
|
|
271 |
if( m0!=INVALID_MOVE ) ret += formatRet(ret,0,-1,m0);
|
|
245 | 272 |
if( m1!=INVALID_MOVE ) ret += formatRet(ret,0, 2,m1); |
246 |
if( m2!=INVALID_MOVE ) ret += formatRet(ret,0,-1,m2);
|
|
247 |
if( m3!=INVALID_MOVE ) ret += formatRet(ret,1, 1,m3);
|
|
273 |
if( m2!=INVALID_MOVE ) ret += formatRet(ret,0, 1,m2);
|
|
274 |
if( m3!=INVALID_MOVE ) ret += formatRet(ret,1,-1,m3);
|
|
248 | 275 |
if( m4!=INVALID_MOVE ) ret += formatRet(ret,1, 2,m4); |
249 |
if( m5!=INVALID_MOVE ) ret += formatRet(ret,1,-1,m5);
|
|
250 |
if( m6!=INVALID_MOVE ) ret += formatRet(ret,2, 1,m6);
|
|
276 |
if( m5!=INVALID_MOVE ) ret += formatRet(ret,1, 1,m5);
|
|
277 |
if( m6!=INVALID_MOVE ) ret += formatRet(ret,2,-1,m6);
|
|
251 | 278 |
if( m7!=INVALID_MOVE ) ret += formatRet(ret,2, 2,m7); |
252 |
if( m8!=INVALID_MOVE ) ret += formatRet(ret,2,-1,m8);
|
|
279 |
if( m8!=INVALID_MOVE ) ret += formatRet(ret,2, 1,m8);
|
|
253 | 280 |
|
254 | 281 |
return formatL("{" + ret + "}"); |
255 | 282 |
} |
... | ... | |
367 | 394 |
} |
368 | 395 |
|
369 | 396 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
370 |
|
|
371 |
private static long[] createIsometries(long id) |
|
372 |
{ |
|
373 |
long[] ret = new long[NUM_ISOMETRIES-1]; |
|
374 |
|
|
375 |
ret[ 0] = turnWhole( id,AXIS_X); |
|
376 |
ret[ 1] = turnWhole(ret[ 0],AXIS_X); |
|
377 |
ret[ 2] = turnWhole(ret[ 1],AXIS_X); |
|
378 |
ret[ 3] = turnWhole(ret[ 2],AXIS_Y); |
|
379 |
ret[ 4] = turnWhole(ret[ 3],AXIS_Y); |
|
380 |
ret[ 5] = turnWhole(ret[ 4],AXIS_Y); |
|
381 |
ret[ 6] = turnWhole(ret[ 5],AXIS_Z); |
|
382 |
ret[ 7] = turnWhole(ret[ 6],AXIS_Z); |
|
383 |
ret[ 8] = turnWhole(ret[ 7],AXIS_Z); |
|
384 |
ret[ 9] = turnWhole(ret[ 8],AXIS_X); |
|
385 |
ret[10] = turnWhole(ret[ 9],AXIS_X); |
|
386 |
ret[11] = turnWhole(ret[10],AXIS_X); |
|
387 |
ret[12] = turnWhole(ret[11],AXIS_Y); |
|
388 |
ret[13] = turnWhole(ret[12],AXIS_Y); |
|
389 |
ret[14] = turnWhole(ret[13],AXIS_Y); |
|
390 |
ret[15] = turnWhole(ret[ 5],AXIS_X); |
|
391 |
ret[16] = turnWhole(ret[15],AXIS_Y); |
|
392 |
ret[17] = turnWhole(ret[16],AXIS_Y); |
|
393 |
ret[18] = turnWhole(ret[ 4],AXIS_X); |
|
394 |
ret[19] = turnWhole(ret[18],AXIS_X); |
|
395 |
ret[20] = turnWhole(ret[19],AXIS_X); |
|
396 |
ret[21] = turnWhole(ret[ 3],AXIS_Z); |
|
397 |
ret[22] = turnWhole(ret[21],AXIS_Z); |
|
398 |
/* |
|
399 |
String iso = "isometries of "+id+" :"; |
|
400 |
|
|
401 |
for(int i=0; i<NUM_ISOMETRIES-1; i++) |
|
402 |
{ |
|
403 |
iso += (" " + ret[i]); |
|
404 |
} |
|
405 |
|
|
406 |
android.util.Log.e("D", iso); |
|
407 |
*/ |
|
408 |
/* |
|
409 |
long t = turnWhole(1,AXIS_X); |
|
410 |
|
|
411 |
android.util.Log.e("D", "1 turned along X: "+t); |
|
412 |
*/ |
|
413 |
return ret; |
|
414 |
} |
|
415 |
|
|
416 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
417 |
// 0 : DF,DRF |
|
418 |
// 1 : DF,DLF |
|
419 |
// 2 : DR,DRF |
|
420 |
// 3 : D,DF |
|
421 |
// 4 : DL,DLF |
|
422 |
// 5 : D,DR |
|
423 |
// 6 : D,DL |
|
424 |
// 7 : DR,DRB |
|
425 |
// 8 : D,DB |
|
426 |
// 9 : DL,DLB |
|
427 |
//10 : DB,DRB |
|
428 |
//11 : DB,DLB |
|
429 |
//12 : FR,DRF |
|
430 |
//13 : F,DF |
|
431 |
//14 : FL,DLF |
|
432 |
//15 : R,DR |
|
433 |
//16 : D,CORE |
|
434 |
//17 : L,DL |
|
435 |
//18 : BR,DRB |
|
436 |
//19 : B,DB |
|
437 |
//20 : BL,DLB |
|
438 |
//21 : F,FR |
|
439 |
//22 : F,FL |
|
440 |
//23 : R,FR |
|
441 |
//24 : F,CORE |
|
442 |
//25 : L,FL |
|
443 |
//26 : R,CORE |
|
444 |
//27 : L,CORE |
|
445 |
//28 : R,BR |
|
446 |
//29 : B,CORE |
|
447 |
//30 : L,BL |
|
448 |
//31 : B,BR |
|
449 |
//32 : B,BL |
|
450 |
//33 : FR,URF |
|
451 |
//34 : F,UF |
|
452 |
//35 : FL,ULF |
|
453 |
//36 : R,UR |
|
454 |
//37 : U,CORE |
|
455 |
//38 : L,UL |
|
456 |
//39 : BR,URB |
|
457 |
//40 : B,UB |
|
458 |
//41 : BL,ULB |
|
459 |
//42 : UF,URF |
|
460 |
//43 : UF,ULF |
|
461 |
//44 : UR,URF |
|
462 |
//45 : U,UF |
|
463 |
//46 : UL,ULF |
|
464 |
//47 : U,UR |
|
465 |
//48 : U,UL |
|
466 |
//49 : UR,URB |
|
467 |
//50 : U,UB |
|
468 |
//51 : UL,ULB |
|
469 |
//52 : UB,URB |
|
470 |
//53 : UB,ULB |
|
397 |
// Definition of the id: it's an 'Andreas signature' of a bandaged cube. |
|
398 |
// https://twistypuzzles.com/forum/viewtopic.php?t=24452&sid=f3b4ac0c611c4713e4d7840f1aabbb0b&start=350 |
|
471 | 399 |
|
472 | 400 |
private static long turn(long id, int axis, int layer) |
473 | 401 |
{ |
... | ... | |
567 | 495 |
return 0; |
568 | 496 |
} |
569 | 497 |
|
570 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
571 |
|
|
572 |
private static long turnWhole(long id, int axis) |
|
573 |
{ |
|
574 |
switch(axis) |
|
575 |
{ |
|
576 |
case AXIS_X: long x1 = cycle(id,9,14,46,41); // |
|
577 |
long x2 = cycle(x1,4,35,51,20); // left layer |
|
578 |
long x3 = cycle(x2,17,25,38,30);// |
|
579 |
|
|
580 |
long x4 = cycle(x3,8,13,45,40); // |
|
581 |
long x5 = cycle(x4,3,34,50,19); // mid layer |
|
582 |
long x6 = cycle(x5,16,24,37,29);// |
|
583 |
|
|
584 |
long x7 = cycle(x6,7,12,44,39); // |
|
585 |
long x8 = cycle(x7,2,33,49,18); // right layer |
|
586 |
long x9 = cycle(x8,15,23,36,28);// |
|
587 |
|
|
588 |
long x10= cycle(x9,1,43,53,11); // |
|
589 |
long x11= cycle(x10,6,22,48,32);// left lock |
|
590 |
long x12= cycle(x11,0,42,52,10);// |
|
591 |
return cycle(x12,5,21,47,31);// right lock |
|
592 |
|
|
593 |
case AXIS_Y: long y1 = cycle(id,1,9,10,2); // |
|
594 |
long y2 = cycle(y1,0,4,11,7); // bottom layer |
|
595 |
long y3 = cycle(y2,3,6,8,5); // |
|
596 |
|
|
597 |
long y4 = cycle(y3,21,25,32,28);// |
|
598 |
long y5 = cycle(y4,22,30,31,23);// mid layer |
|
599 |
long y6 = cycle(y5,24,27,29,26);// |
|
600 |
|
|
601 |
long y7 = cycle(y6,42,46,53,49);// |
|
602 |
long y8 = cycle(y7,43,51,52,44);// top layer |
|
603 |
long y9 = cycle(y8,45,48,50,47);// |
|
604 |
|
|
605 |
long y10= cycle(y9,12,14,20,18); // |
|
606 |
long y11= cycle(y10,13,17,19,15);// bottom lock |
|
607 |
long y12= cycle(y11,33,35,41,39);// |
|
608 |
return cycle(y12,34,38,40,36);// top lock |
|
609 |
|
|
610 |
case AXIS_Z: long z1 = cycle(id,10,20,53,39);// |
|
611 |
long z2 = cycle(z1,11,41,52,18);// back layer |
|
612 |
long z3 = cycle(z2,19,32,40,31);// |
|
613 |
|
|
614 |
long z4 = cycle(z3,5,17,48,36); // |
|
615 |
long z5 = cycle(z4,6,38,47,15); // mid layer |
|
616 |
long z6 = cycle(z5,16,27,37,26);// |
|
617 |
|
|
618 |
long z7 = cycle(z6,0,14,43,33); // |
|
619 |
long z8 = cycle(z7,1,35,42,12); // front layer |
|
620 |
long z9 = cycle(z8,13,22,34,21);// |
|
621 |
|
|
622 |
long z10= cycle(z9,7,9,51,49); // |
|
623 |
long z11= cycle(z10,8,30,50,28);// back lock |
|
624 |
long z12= cycle(z11,2,4,46,44); // |
|
625 |
return cycle(z12,3,25,45,23);// front lock |
|
626 |
} |
|
627 |
|
|
628 |
return 0; |
|
629 |
} |
|
630 |
|
|
631 | 498 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
632 | 499 |
// bit b1 in place of b2 etc. |
633 | 500 |
|
... | ... | |
644 | 511 |
return setBit(i3,b1,bit4); |
645 | 512 |
} |
646 | 513 |
|
647 |
|
|
648 | 514 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
649 |
// bit b1 in place of b2 etc. |
|
650 | 515 |
|
651 |
private static long cyclePriv(long id, int b1, int b2, int b3, int b4)
|
|
516 |
private static long getBit(long id, int bit)
|
|
652 | 517 |
{ |
653 |
long bit1 = getBit(id,b1); |
|
654 |
long bit2 = getBit(id,b2); |
|
655 |
long bit3 = getBit(id,b3); |
|
656 |
long bit4 = getBit(id,b4); |
|
657 |
|
|
658 |
android.util.Log.e("D", "bit1="+bit1+" bit2="+bit2+" bit3="+bit3+" bit4="+bit4); |
|
659 |
|
|
660 |
long i1 = setBitPriv(id,b2,bit1); |
|
661 |
long i2 = setBitPriv(i1,b3,bit2); |
|
662 |
long i3 = setBitPriv(i2,b4,bit3); |
|
663 |
long i4 = setBitPriv(i3,b1,bit4); |
|
664 |
|
|
665 |
|
|
666 |
android.util.Log.e("D", "i1="+i1+" i2="+i2+" i3="+i3+" i4="+i4); |
|
667 |
|
|
668 |
return i4; |
|
518 |
return (id>>bit)&0x1; |
|
669 | 519 |
} |
670 | 520 |
|
671 |
|
|
672 | 521 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
673 | 522 |
|
674 |
private static long setBitPriv(long id, int bit, long value)
|
|
523 |
private static long setBit(long id, int bit, long value) |
|
675 | 524 |
{ |
676 | 525 |
long old = getBit(id,bit); |
677 | 526 |
|
... | ... | |
681 | 530 |
id += (value==0 ? -diff : diff); |
682 | 531 |
} |
683 | 532 |
|
684 |
android.util.Log.e("D", "setBit: id: "+id+" bit="+bit+" value="+value+" old="+old+" ret="+id); |
|
685 |
|
|
686 | 533 |
return id; |
687 | 534 |
} |
688 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
689 | 535 |
|
690 |
private static long getBit(long id, int bit) |
|
536 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
537 |
/* |
|
538 |
private void printMoves() |
|
691 | 539 |
{ |
692 |
return (id>>bit)&0x1; |
|
540 |
String moves = ""; |
|
541 |
|
|
542 |
for(int i=0; i<NUM_MOVES; i++) |
|
543 |
{ |
|
544 |
moves += (" " + mMoves[i]); |
|
545 |
} |
|
546 |
|
|
547 |
android.util.Log.e("D", moves); |
|
693 | 548 |
} |
694 | 549 |
|
695 | 550 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
696 | 551 |
|
697 |
private static long setBit(long id, int bit, long value)
|
|
552 |
private static String printBits(long id)
|
|
698 | 553 |
{ |
699 |
long old = getBit(id,bit); |
|
554 |
String ret = "["; |
|
555 |
boolean first = true; |
|
700 | 556 |
|
701 |
if( old!=value )
|
|
557 |
for(int i=0; i<64; i++)
|
|
702 | 558 |
{ |
703 |
long diff = (1L<<bit); |
|
704 |
id += (value==0 ? -diff : diff); |
|
559 |
if( ( (id>>i)&0x1)==1 ) |
|
560 |
{ |
|
561 |
String num = (i<10 ? " "+i : ""+i); |
|
562 |
|
|
563 |
if( first ) { ret += num; first=false; } |
|
564 |
else ret += (","+num); |
|
565 |
} |
|
705 | 566 |
} |
706 | 567 |
|
707 |
return id;
|
|
568 |
return ret + "]";
|
|
708 | 569 |
} |
570 |
*/ |
|
709 | 571 |
} |
Also available in: Unified diff
Generalized ScrambleState generator: finished. Remove the specialized 'Evil' generator.