Project

General

Profile

Download (24 KB) Statistics
| Branch: | Revision:

distorted-objectlib / src / main / java / org / distorted / objectlib / scrambling / ScrambleStateBandaged3x3.java @ 113597af

1
///////////////////////////////////////////////////////////////////////////////////////////////////
2
// Copyright 2022 Leszek Koltunski                                                               //
3
//                                                                                               //
4
// This file is part of Magic Cube.                                                              //
5
//                                                                                               //
6
// Magic Cube is free software: you can redistribute it and/or modify                            //
7
// it under the terms of the GNU General Public License as published by                          //
8
// the Free Software Foundation, either version 2 of the License, or                             //
9
// (at your option) any later version.                                                           //
10
//                                                                                               //
11
// Magic Cube is distributed in the hope that it will be useful,                                 //
12
// but WITHOUT ANY WARRANTY; without even the implied warranty of                                //
13
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the                                 //
14
// GNU General Public License for more details.                                                  //
15
//                                                                                               //
16
// You should have received a copy of the GNU General Public License                             //
17
// along with Magic Cube.  If not, see <http://www.gnu.org/licenses/>.                           //
18
///////////////////////////////////////////////////////////////////////////////////////////////////
19

    
20
package org.distorted.objectlib.scrambling;
21

    
22
import java.util.ArrayList;
23

    
24
///////////////////////////////////////////////////////////////////////////////////////////////////
25
// Producer of the ScrambleStateGraph for any bandaged 3x3x3.
26

    
27
public class ScrambleStateBandaged3x3
28
{
29
  private static final long INVALID_MOVE = -1;
30
  private static final int NUM_MOVES = 27;
31
  private static final int NUM_ISOMETRIES = 24;
32

    
33
  private static final int AXIS_X = 0;
34
  private static final int AXIS_Y = 1;
35
  private static final int AXIS_Z = 2;
36

    
37
  private static final int LAYER_L = 0;
38
  private static final int LAYER_M = 1;
39
  private static final int LAYER_R = 2;
40

    
41
  private long mID;
42
  private final long[] mIsometries;
43
  private final long[] mMoves;
44

    
45
///////////////////////////////////////////////////////////////////////////////////////////////////
46

    
47
  public ScrambleStateBandaged3x3(long id)
48
    {
49
    mID = id;
50
    mIsometries = createIsometries(mID);
51
    mMoves = createMoves(mID);
52
    }
53

    
54
///////////////////////////////////////////////////////////////////////////////////////////////////
55

    
56
  public static void computeGraph(long id)
57
    {
58
    ScrambleStateBandaged3x3 bsg = new ScrambleStateBandaged3x3(id);
59
    ArrayList<ScrambleStateBandaged3x3> graph = new ArrayList<>();
60
    graph.add(bsg);
61

    
62
    insertChildren(graph,id);
63
    pruneGraph(graph,id);
64
    remapGraph(graph);
65

    
66
    int num = graph.size();
67
    android.util.Log.e("D", "\n"+num+" states\n");
68

    
69
    for(int i=0; i<num; i++)
70
      {
71
      bsg = graph.get(i);
72
      android.util.Log.e("D", formatMoves(bsg));
73
      }
74
    }
75

    
76
///////////////////////////////////////////////////////////////////////////////////////////////////
77

    
78
  private static void insertChildren(ArrayList<ScrambleStateBandaged3x3> list, long id)
79
    {
80
    ScrambleStateBandaged3x3 bsg = findState(list,id);
81

    
82
android.util.Log.e("D", "inserting children of "+id);
83

    
84
    if( bsg==null )
85
      {
86
      android.util.Log.e("D", "error: "+id+" doesn't exist");
87
      return;
88
      }
89

    
90
    for(int i=0; i<NUM_MOVES; i++)
91
      {
92
      long move = bsg.getMove(i);
93

    
94
      if( move!=INVALID_MOVE )
95
        {
96
        ScrambleStateBandaged3x3 tmp = findState(list,move);
97

    
98
        if( tmp==null )
99
          {
100
          tmp = new ScrambleStateBandaged3x3(move);
101
          list.add(tmp);
102
          insertChildren(list,move);
103
          }
104
        else if( tmp.mID != move )
105
          {
106
          android.util.Log.e("D", "id "+id+" move: "+move+" leads to already existing "+tmp.mID);
107
          bsg.setMove(i,tmp.mID);
108
          }
109
        }
110
      }
111
    }
112

    
113
///////////////////////////////////////////////////////////////////////////////////////////////////
114

    
115
  private static void pruneGraph(ArrayList<ScrambleStateBandaged3x3> list, long id)
116
    {
117
    int num = list.size();
118
    boolean pruned = false;
119
    ScrambleStateBandaged3x3 bsg;
120

    
121
    for(int i=0; i<num; i++)
122
      {
123
      bsg = list.get(i);
124

    
125
      if( bsg.numAxis()<2 )
126
        {
127
        long prunedID = bsg.getID();
128

    
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;
137
        }
138
      }
139

    
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);
155
    }
156

    
157
///////////////////////////////////////////////////////////////////////////////////////////////////
158

    
159
  private static void remapGraph(ArrayList<ScrambleStateBandaged3x3> list)
160
    {
161
    long id;
162
    int num = list.size();
163
    ScrambleStateBandaged3x3 bsg;
164

    
165
    for(int i=0; i<num; i++ )
166
      {
167
      bsg = list.get(i);
168
      id = bsg.getID();
169
      bsg.setID(i);
170
      remapID(list,id,i);
171
      }
172
    }
173

    
174
///////////////////////////////////////////////////////////////////////////////////////////////////
175

    
176
  private static void remapID(ArrayList<ScrambleStateBandaged3x3> list, long id, long newId)
177
    {
178
    ScrambleStateBandaged3x3 bsg;
179
    int size = list.size();
180

    
181
    for(int i=0; i<size; i++)
182
      {
183
      bsg = list.get(i);
184

    
185
      for(int j=0; j<NUM_MOVES; j++)
186
        {
187
        if( bsg.getMove(j)==id ) bsg.setMove(j,newId);
188
        }
189
      }
190
    }
191

    
192
///////////////////////////////////////////////////////////////////////////////////////////////////
193

    
194
  private static boolean isAnIsometry(ScrambleStateBandaged3x3 bsg, long id)
195
    {
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;
199
    }
200

    
201
///////////////////////////////////////////////////////////////////////////////////////////////////
202

    
203
  private static ScrambleStateBandaged3x3 findState(ArrayList<ScrambleStateBandaged3x3> list, long id)
204
    {
205
    ScrambleStateBandaged3x3 bsg;
206
    int num = list.size();
207

    
208
    for(int i=0; i<num; i++)
209
      {
210
      bsg= list.get(i);
211
      if( isAnIsometry(bsg,id) ) return bsg;
212
      }
213

    
214
    return null;
215
    }
216

    
217
///////////////////////////////////////////////////////////////////////////////////////////////////
218

    
219
  private static String formatMoves(ScrambleStateBandaged3x3 bsg)
220
    {
221
    String x = getTable(bsg, 0);
222
    String y = getTable(bsg, 9);
223
    String z = getTable(bsg,18);
224

    
225
    return "    new ScrambleStateGraph( new int[][] { "+x+", "+y+", "+z+" } ),";
226
    }
227

    
228
///////////////////////////////////////////////////////////////////////////////////////////////////
229

    
230
  private static String getTable(ScrambleStateBandaged3x3 sc, int index)
231
    {
232
    long m0 = sc.getMove(index  );
233
    long m1 = sc.getMove(index+1);
234
    long m2 = sc.getMove(index+2);
235
    long m3 = sc.getMove(index+3);
236
    long m4 = sc.getMove(index+4);
237
    long m5 = sc.getMove(index+5);
238
    long m6 = sc.getMove(index+6);
239
    long m7 = sc.getMove(index+7);
240
    long m8 = sc.getMove(index+8);
241

    
242
    String ret = "";
243

    
244
    if( m0!=INVALID_MOVE ) ret += formatRet(ret,0, 1,m0);
245
    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);
248
    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);
251
    if( m7!=INVALID_MOVE ) ret += formatRet(ret,2, 2,m7);
252
    if( m8!=INVALID_MOVE ) ret += formatRet(ret,2,-1,m8);
253

    
254
    return formatL("{" + ret + "}");
255
    }
256

    
257
///////////////////////////////////////////////////////////////////////////////////////////////////
258

    
259
  private static String formatRet(String str, int row, int angle, long id)
260
    {
261
    String ret = str.length()!=0 ? ",":"";
262

    
263
    ret += row;
264
    ret += angle<0 ? "," : ", ";
265
    ret += angle;
266

    
267
         if( id< 10 ) ret += (",  "+id);
268
    else if( id<100 ) ret += (", " +id);
269
    else              ret += (","  +id);
270

    
271
    return ret;
272
    }
273

    
274
///////////////////////////////////////////////////////////////////////////////////////////////////
275

    
276
  private static final int LENGTH = 28;
277

    
278
  private static String formatL(String input)
279
    {
280
    int len = input.length();
281
    String ret = input;
282
    for(int i=0 ;i<LENGTH-len; i++) ret += " ";
283
    return ret;
284
    }
285

    
286
///////////////////////////////////////////////////////////////////////////////////////////////////
287

    
288
  private long getID()
289
    {
290
    return mID;
291
    }
292

    
293
///////////////////////////////////////////////////////////////////////////////////////////////////
294

    
295
  private void setID(long id)
296
    {
297
    mID = id;
298
    }
299

    
300
///////////////////////////////////////////////////////////////////////////////////////////////////
301

    
302
  private long getMove(int index)
303
    {
304
    return (index>=0 && index<NUM_MOVES) ? mMoves[index] : INVALID_MOVE;
305
    }
306

    
307
///////////////////////////////////////////////////////////////////////////////////////////////////
308

    
309
  private int numAxis()
310
    {
311
    int num = 0;
312

    
313
    if( mMoves[ 0]!=INVALID_MOVE || mMoves[ 1]!=INVALID_MOVE || mMoves[ 2]!=INVALID_MOVE ||
314
        mMoves[ 3]!=INVALID_MOVE || mMoves[ 4]!=INVALID_MOVE || mMoves[ 5]!=INVALID_MOVE ||
315
        mMoves[ 6]!=INVALID_MOVE || mMoves[ 7]!=INVALID_MOVE || mMoves[ 8]!=INVALID_MOVE   ) num++;
316

    
317
    if( mMoves[ 9]!=INVALID_MOVE || mMoves[10]!=INVALID_MOVE || mMoves[11]!=INVALID_MOVE ||
318
        mMoves[12]!=INVALID_MOVE || mMoves[13]!=INVALID_MOVE || mMoves[14]!=INVALID_MOVE ||
319
        mMoves[15]!=INVALID_MOVE || mMoves[16]!=INVALID_MOVE || mMoves[17]!=INVALID_MOVE   ) num++;
320

    
321
    if( mMoves[18]!=INVALID_MOVE || mMoves[19]!=INVALID_MOVE || mMoves[20]!=INVALID_MOVE ||
322
        mMoves[21]!=INVALID_MOVE || mMoves[22]!=INVALID_MOVE || mMoves[23]!=INVALID_MOVE ||
323
        mMoves[24]!=INVALID_MOVE || mMoves[25]!=INVALID_MOVE || mMoves[26]!=INVALID_MOVE   ) num++;
324

    
325
    return num;
326
    }
327

    
328
///////////////////////////////////////////////////////////////////////////////////////////////////
329

    
330
  private void setMove(int index, long newMove)
331
    {
332
    if( index>=0 && index<NUM_MOVES ) mMoves[index] = newMove;
333
    }
334

    
335
///////////////////////////////////////////////////////////////////////////////////////////////////
336

    
337
  private static long[] createMoves(long id)
338
    {
339
    long[] ret = new long[NUM_MOVES];
340
    int index = 0;
341

    
342
    for(int axis=0; axis<3; axis++)
343
      for(int layer=0; layer<3; layer++)
344
        {
345
        long x1 = turn(id,axis,layer);
346

    
347
        if( x1!=INVALID_MOVE )
348
          {
349
          long x2 = turn(x1,axis,layer);
350
          long x3 = turn(x2,axis,layer);
351

    
352
          ret[index  ] = x1;
353
          ret[index+1] = x2;
354
          ret[index+2] = x3;
355
          }
356
        else
357
          {
358
          ret[index  ] = INVALID_MOVE;
359
          ret[index+1] = INVALID_MOVE;
360
          ret[index+2] = INVALID_MOVE;
361
          }
362

    
363
        index+=3;
364
        }
365

    
366
    return ret;
367
    }
368

    
369
///////////////////////////////////////////////////////////////////////////////////////////////////
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
471

    
472
  private static long turn(long id, int axis, int layer)
473
    {
474
    switch(axis)
475
      {
476
      case AXIS_X: switch(layer)
477
                     {
478
                     case LAYER_L: if( getBit(id, 1)==1 || getBit(id, 6)==1 || getBit(id,11)==1 ||
479
                                       getBit(id,22)==1 || getBit(id,27)==1 || getBit(id,32)==1 ||
480
                                       getBit(id,43)==1 || getBit(id,48)==1 || getBit(id,53)==1  ) return INVALID_MOVE;
481

    
482
                                   long x1 = cycle(id,9,14,46,41);
483
                                   long x2 = cycle(x1,4,35,51,20);
484
                                   return    cycle(x2,17,25,38,30);
485

    
486
                     case LAYER_M: if( getBit(id, 1)==1 || getBit(id, 6)==1 || getBit(id,11)==1 ||
487
                                       getBit(id,22)==1 || getBit(id,27)==1 || getBit(id,32)==1 ||
488
                                       getBit(id,43)==1 || getBit(id,48)==1 || getBit(id,53)==1 ||
489
                                       getBit(id, 0)==1 || getBit(id, 5)==1 || getBit(id,10)==1 ||
490
                                       getBit(id,21)==1 || getBit(id,26)==1 || getBit(id,31)==1 ||
491
                                       getBit(id,42)==1 || getBit(id,47)==1 || getBit(id,52)==1  ) return INVALID_MOVE;
492

    
493
                                   long x4 = cycle(id,8,13,45,40);
494
                                   long x5 = cycle(x4,3,34,50,19);
495
                                   return    cycle(x5,16,24,37,29);
496

    
497
                     case LAYER_R: if( getBit(id, 0)==1 || getBit(id, 5)==1 || getBit(id,10)==1 ||
498
                                       getBit(id,21)==1 || getBit(id,26)==1 || getBit(id,31)==1 ||
499
                                       getBit(id,42)==1 || getBit(id,47)==1 || getBit(id,52)==1  ) return INVALID_MOVE;
500

    
501
                                   long x7 = cycle(id,7,12,44,39);
502
                                   long x8 = cycle(x7,2,33,49,18);
503
                                   return    cycle(x8,15,23,36,28);
504
                     }
505

    
506
      case AXIS_Y: switch(layer)
507
                     {
508
                     case LAYER_L: if( getBit(id,12)==1 || getBit(id,13)==1 || getBit(id,14)==1 ||
509
                                       getBit(id,15)==1 || getBit(id,16)==1 || getBit(id,17)==1 ||
510
                                       getBit(id,18)==1 || getBit(id,19)==1 || getBit(id,20)==1  ) return INVALID_MOVE;
511

    
512
                                   long y1 = cycle(id,1,9,10,2);
513
                                   long y2 = cycle(y1,0,4,11,7);
514
                                   return    cycle(y2,3,6,8,5);
515

    
516
                     case LAYER_M: if( getBit(id,12)==1 || getBit(id,13)==1 || getBit(id,14)==1 ||
517
                                       getBit(id,15)==1 || getBit(id,16)==1 || getBit(id,17)==1 ||
518
                                       getBit(id,18)==1 || getBit(id,19)==1 || getBit(id,20)==1 ||
519
                                       getBit(id,33)==1 || getBit(id,34)==1 || getBit(id,35)==1 ||
520
                                       getBit(id,36)==1 || getBit(id,37)==1 || getBit(id,38)==1 ||
521
                                       getBit(id,39)==1 || getBit(id,40)==1 || getBit(id,41)==1  ) return INVALID_MOVE;
522

    
523
                                   long y4 = cycle(id,21,25,32,28);
524
                                   long y5 = cycle(y4,22,30,31,23);
525
                                   return    cycle(y5,24,27,29,26);
526

    
527
                     case LAYER_R: if( getBit(id,33)==1 || getBit(id,34)==1 || getBit(id,35)==1 ||
528
                                       getBit(id,36)==1 || getBit(id,37)==1 || getBit(id,38)==1 ||
529
                                       getBit(id,39)==1 || getBit(id,40)==1 || getBit(id,41)==1  ) return INVALID_MOVE;
530

    
531
                                   long y7 = cycle(id,42,46,53,49);
532
                                   long y8 = cycle(y7,43,51,52,44);
533
                                   return    cycle(y8,45,48,50,47);
534
                     }
535

    
536
      case AXIS_Z: switch(layer)
537
                     {
538
                     case LAYER_L: if( getBit(id, 7)==1 || getBit(id, 8)==1 || getBit(id, 9)==1 ||
539
                                       getBit(id,28)==1 || getBit(id,29)==1 || getBit(id,30)==1 ||
540
                                       getBit(id,49)==1 || getBit(id,50)==1 || getBit(id,51)==1  ) return INVALID_MOVE;
541

    
542
                                   long z1 = cycle(id,10,20,53,39);
543
                                   long z2 = cycle(z1,11,41,52,18);
544
                                   return    cycle(z2,19,32,40,31);
545

    
546
                     case LAYER_M: if( getBit(id, 7)==1 || getBit(id, 8)==1 || getBit(id, 9)==1 ||
547
                                       getBit(id,28)==1 || getBit(id,29)==1 || getBit(id,30)==1 ||
548
                                       getBit(id,49)==1 || getBit(id,50)==1 || getBit(id,51)==1 ||
549
                                       getBit(id, 2)==1 || getBit(id, 3)==1 || getBit(id, 4)==1 ||
550
                                       getBit(id,23)==1 || getBit(id,24)==1 || getBit(id,25)==1 ||
551
                                       getBit(id,44)==1 || getBit(id,45)==1 || getBit(id,46)==1  ) return INVALID_MOVE;
552

    
553
                                   long z4 = cycle(id,5,17,48,36);
554
                                   long z5 = cycle(z4,6,38,47,15);
555
                                   return    cycle(z5,16,27,37,26);
556

    
557
                     case LAYER_R: if( getBit(id, 2)==1 || getBit(id, 3)==1 || getBit(id, 4)==1 ||
558
                                       getBit(id,23)==1 || getBit(id,24)==1 || getBit(id,25)==1 ||
559
                                       getBit(id,44)==1 || getBit(id,45)==1 || getBit(id,46)==1  ) return INVALID_MOVE;
560

    
561
                                   long z7 = cycle(id,0,14,43,33);
562
                                   long z8 = cycle(z7,1,35,42,12);
563
                                   return    cycle(z8,13,22,34,21);
564
                     }
565
      }
566

    
567
    return 0;
568
    }
569

    
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
///////////////////////////////////////////////////////////////////////////////////////////////////
632
// bit b1 in place of b2 etc.
633

    
634
  private static long cycle(long id, int b1, int b2, int b3, int b4)
635
    {
636
    long bit1 = getBit(id,b1);
637
    long bit2 = getBit(id,b2);
638
    long bit3 = getBit(id,b3);
639
    long bit4 = getBit(id,b4);
640

    
641
    long i1 = setBit(id,b2,bit1);
642
    long i2 = setBit(i1,b3,bit2);
643
    long i3 = setBit(i2,b4,bit3);
644
    return    setBit(i3,b1,bit4);
645
    }
646

    
647

    
648
///////////////////////////////////////////////////////////////////////////////////////////////////
649
// bit b1 in place of b2 etc.
650

    
651
  private static long cyclePriv(long id, int b1, int b2, int b3, int b4)
652
    {
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;
669
    }
670

    
671

    
672
///////////////////////////////////////////////////////////////////////////////////////////////////
673

    
674
  private static long setBitPriv(long id, int bit, long value)
675
    {
676
    long old = getBit(id,bit);
677

    
678
    if( old!=value )
679
      {
680
      long diff = (1L<<bit);
681
      id += (value==0 ? -diff : diff);
682
      }
683

    
684
android.util.Log.e("D", "setBit: id: "+id+" bit="+bit+" value="+value+" old="+old+" ret="+id);
685

    
686
    return id;
687
    }
688
///////////////////////////////////////////////////////////////////////////////////////////////////
689

    
690
  private static long getBit(long id, int bit)
691
    {
692
    return (id>>bit)&0x1;
693
    }
694

    
695
///////////////////////////////////////////////////////////////////////////////////////////////////
696

    
697
  private static long setBit(long id, int bit, long value)
698
    {
699
    long old = getBit(id,bit);
700

    
701
    if( old!=value )
702
      {
703
      long diff = (1L<<bit);
704
      id += (value==0 ? -diff : diff);
705
      }
706

    
707
    return id;
708
    }
709
}
(3-3/5)