1
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
2
|
// Copyright 2023 Leszek Koltunski //
|
3
|
// //
|
4
|
// This file is part of Magic Cube. //
|
5
|
// //
|
6
|
// Magic Cube is proprietary software licensed under an EULA which you should have received //
|
7
|
// along with the code. If not, check https://distorted.org/magic/License-Magic-Cube.html //
|
8
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
9
|
|
10
|
package org.distorted.objectlib.tablebases;
|
11
|
|
12
|
import org.distorted.library.helpers.QuatHelper;
|
13
|
import org.distorted.library.type.Static3D;
|
14
|
import org.distorted.library.type.Static4D;
|
15
|
import org.distorted.objectlib.R;
|
16
|
import org.distorted.objectlib.helpers.OperatingSystemInterface;
|
17
|
import org.distorted.objectlib.helpers.QuatGroupGenerator;
|
18
|
import org.distorted.objectlib.objects.TwistySkewb;
|
19
|
|
20
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
21
|
|
22
|
public class TBSkewb extends TablebasesPruning
|
23
|
{
|
24
|
public static final int[] FIXED= {0,3,5,6};
|
25
|
public static final int[] FREE = {1,2,4,7};
|
26
|
|
27
|
private static final int[][] freeIndex = { {1,3,2},{0,2,3},{3,1,0},{2,0,1} };
|
28
|
|
29
|
// [1][] are the 3 quats the 1st 'fixed' corner will have when twisted with respectively twist 0,1,2.
|
30
|
private static final int[][] fixedQuats = { {0,1,2},{0,7,8},{0,6,5},{0,4,3} };
|
31
|
|
32
|
private static int[][] tetradPerm, divideTable, multiplyTable, locationTable;
|
33
|
|
34
|
// centerQuats[0][1] are the two quats the 0th center might have when rotated to the position of
|
35
|
// the 1st center.
|
36
|
// Warning! Order of the centers follows the order from TwistySkewb, i.e. +z,-z,+y,-y,+x,-x
|
37
|
private static final int[][][] centerQuats =
|
38
|
{
|
39
|
{ {0,10},{9,11},{1,7},{4,6},{2,5},{3,8} },
|
40
|
{ {9,11},{0,10},{4,6},{1,7},{3,8},{2,5} },
|
41
|
{ {2,8},{3,5},{0,11},{9,10},{1,4},{6,7} },
|
42
|
{ {3,5},{2,8},{9,10},{0,11},{6,7},{1,4} },
|
43
|
{ {1,6},{4,7},{2,3},{5,8},{0,9},{10,11} },
|
44
|
{ {4,7},{1,6},{5,8},{2,3},{10,11},{0,9} }
|
45
|
};
|
46
|
|
47
|
private static Static4D[] mQuats;
|
48
|
private static final Static3D[] ROT_AXIS = TwistySkewb.ROT_AXIS;
|
49
|
private static final int[][] BASIC_ANGLES = { {3,3},{3,3},{3,3},{3,3} };
|
50
|
|
51
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
52
|
|
53
|
public TBSkewb()
|
54
|
{
|
55
|
super();
|
56
|
}
|
57
|
|
58
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
59
|
|
60
|
public TBSkewb(OperatingSystemInterface os)
|
61
|
{
|
62
|
super(os,new int[] {R.raw.skew_2_pruning4,R.raw.skew_2_pruning5},new int[]{R.raw.skew_2_pruning11});
|
63
|
}
|
64
|
|
65
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
66
|
|
67
|
int[][] getBasicAngles()
|
68
|
{
|
69
|
return BASIC_ANGLES;
|
70
|
}
|
71
|
|
72
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
73
|
|
74
|
Static3D[] getRotationAxis()
|
75
|
{
|
76
|
return ROT_AXIS;
|
77
|
}
|
78
|
|
79
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
80
|
|
81
|
float[][] getPosition()
|
82
|
{
|
83
|
return new float[][]
|
84
|
{
|
85
|
{ 1, 1, 1 },
|
86
|
{ 1, 1,-1 },
|
87
|
{ 1,-1, 1 },
|
88
|
{ 1,-1,-1 },
|
89
|
{-1, 1, 1 },
|
90
|
{-1, 1,-1 },
|
91
|
{-1,-1, 1 },
|
92
|
{-1,-1,-1 },
|
93
|
|
94
|
{ 0, 0, 1 },
|
95
|
{ 0, 0,-1 },
|
96
|
{ 0, 1, 0 },
|
97
|
{ 0,-1, 0 },
|
98
|
{ 1, 0, 0 },
|
99
|
{-1, 0, 0 }
|
100
|
};
|
101
|
}
|
102
|
|
103
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
104
|
|
105
|
float[][] getCuts()
|
106
|
{
|
107
|
float[] cut = {0};
|
108
|
return new float[][] { cut,cut,cut,cut };
|
109
|
}
|
110
|
|
111
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
112
|
|
113
|
boolean[][] getRotatable()
|
114
|
{
|
115
|
boolean[] t1 = new boolean[] {false,true};
|
116
|
boolean[] t2 = new boolean[] {true,false};
|
117
|
return new boolean[][] { t1,t2,t2,t1 };
|
118
|
}
|
119
|
|
120
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
121
|
// specifically for the tablebase
|
122
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
123
|
|
124
|
int getSize()
|
125
|
{
|
126
|
return 3149280; // see https://www.jaapsch.net/puzzles/skewb.htm
|
127
|
}
|
128
|
|
129
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
130
|
|
131
|
int getMinScramble()
|
132
|
{
|
133
|
return 9;
|
134
|
}
|
135
|
|
136
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
137
|
|
138
|
int[] getMidPruningLevels()
|
139
|
{
|
140
|
return new int[] {4,5};
|
141
|
}
|
142
|
|
143
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
144
|
|
145
|
int[] getHighPruningLevels()
|
146
|
{
|
147
|
return new int[] {11};
|
148
|
}
|
149
|
|
150
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
151
|
|
152
|
int getGodsNumber()
|
153
|
{
|
154
|
return 11;
|
155
|
}
|
156
|
|
157
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
158
|
|
159
|
boolean moveCanProceed(int lastA, int lastR, int currA, int currR)
|
160
|
{
|
161
|
return lastA!=currA;
|
162
|
}
|
163
|
|
164
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
165
|
|
166
|
private static int figureOutLocation(float[] loc, float[][] vectors)
|
167
|
{
|
168
|
float minDiff = Float.MAX_VALUE;
|
169
|
int index = -1;
|
170
|
|
171
|
for(int i=0; i<4; i++)
|
172
|
{
|
173
|
float[] v = vectors[i];
|
174
|
float dx = v[0]-loc[0];
|
175
|
float dy = v[1]-loc[1];
|
176
|
float dz = v[2]-loc[2];
|
177
|
float diff = dx*dx + dy*dy + dz*dz;
|
178
|
|
179
|
if( diff<minDiff )
|
180
|
{
|
181
|
minDiff = diff;
|
182
|
index = i;
|
183
|
}
|
184
|
}
|
185
|
|
186
|
return index;
|
187
|
}
|
188
|
|
189
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
190
|
|
191
|
private static void generateLocation()
|
192
|
{
|
193
|
locationTable = new int[4][12];
|
194
|
|
195
|
if( mQuats==null )
|
196
|
mQuats = QuatGroupGenerator.computeGroup(ROT_AXIS,BASIC_ANGLES);
|
197
|
|
198
|
float[][] vectors = new float[][]
|
199
|
{
|
200
|
{ 1, 1,-1, 0},
|
201
|
{ 1,-1, 1, 0},
|
202
|
{-1, 1, 1, 0},
|
203
|
{-1,-1,-1, 0}
|
204
|
};
|
205
|
|
206
|
float[] output = new float[4];
|
207
|
|
208
|
for(int i=0; i<4; i++)
|
209
|
{
|
210
|
float[] v = vectors[i];
|
211
|
|
212
|
for(int q=0; q<12; q++)
|
213
|
{
|
214
|
Static4D quat = mQuats[q];
|
215
|
QuatHelper.rotateVectorByQuat(output,v[0],v[1],v[2],v[3],quat);
|
216
|
int loc = figureOutLocation(output,vectors);
|
217
|
locationTable[i][q] = loc;
|
218
|
}
|
219
|
}
|
220
|
}
|
221
|
|
222
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
223
|
|
224
|
public static int computeLocation(int index, int quat)
|
225
|
{
|
226
|
if( locationTable==null ) generateLocation();
|
227
|
return locationTable[index][quat];
|
228
|
}
|
229
|
|
230
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
231
|
|
232
|
private static int fixedQuatToTwist(int index, int quat)
|
233
|
{
|
234
|
int[] qs = fixedQuats[index];
|
235
|
|
236
|
if( quat==qs[0]) return 0;
|
237
|
if( quat==qs[1]) return 1;
|
238
|
if( quat==qs[2]) return 2;
|
239
|
|
240
|
android.util.Log.e("D", "error in fixedQuatToTwist, index="+index+" quat="+quat);
|
241
|
return -1;
|
242
|
}
|
243
|
|
244
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
245
|
|
246
|
private static int fixedTwistToQuat(int index, int twist)
|
247
|
{
|
248
|
return fixedQuats[index][twist];
|
249
|
}
|
250
|
|
251
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
252
|
|
253
|
private static int figureOutTetrad(int q0, int q1, int q2, int q3)
|
254
|
{
|
255
|
int[] quats = fixedQuats[3];
|
256
|
|
257
|
int s00 = divideFromRight(q0,quats[0]);
|
258
|
int s01 = divideFromRight(q0,quats[1]);
|
259
|
int s02 = divideFromRight(q0,quats[2]);
|
260
|
|
261
|
quats = fixedQuats[1];
|
262
|
|
263
|
int s10 = divideFromRight(q2,quats[0]);
|
264
|
int s11 = divideFromRight(q2,quats[1]);
|
265
|
int s12 = divideFromRight(q2,quats[2]);
|
266
|
|
267
|
quats = fixedQuats[2];
|
268
|
|
269
|
int s20 = divideFromRight(q1,quats[0]);
|
270
|
|
271
|
if( s20==s00 || s20==s01 || s20==s02 )
|
272
|
return ( s20==s10 || s20==s11 || s20==s12 ) ? s20 : -1;
|
273
|
|
274
|
int s21 = divideFromRight(q1,quats[1]);
|
275
|
|
276
|
if( s21==s00 || s21==s01 || s21==s02 )
|
277
|
return ( s21==s10 || s21==s11 || s21==s12 ) ? s21 : -1;
|
278
|
|
279
|
int s22 = divideFromRight(q1,quats[2]);
|
280
|
|
281
|
if( s22==s00 || s22==s01 || s22==s02 )
|
282
|
return ( s22==s10 || s22==s11 || s22==s12 ) ? s22 : -1;
|
283
|
|
284
|
return -1;
|
285
|
}
|
286
|
|
287
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
288
|
|
289
|
private static void generateDivideTable()
|
290
|
{
|
291
|
divideTable = new int[12][12];
|
292
|
|
293
|
for(int i=0; i<12; i++)
|
294
|
for(int j=0; j<12; j++)
|
295
|
{
|
296
|
int res = multiplyQuat(i,j);
|
297
|
divideTable[res][j] = i;
|
298
|
}
|
299
|
}
|
300
|
|
301
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
302
|
// double cover!
|
303
|
|
304
|
private static int findQuat(Static4D quat)
|
305
|
{
|
306
|
float minDiff = Float.MAX_VALUE;
|
307
|
int bestindex = -1;
|
308
|
float dx,dy,dz,dw,diff;
|
309
|
|
310
|
float x= quat.get0();
|
311
|
float y= quat.get1();
|
312
|
float z= quat.get2();
|
313
|
float w= quat.get3();
|
314
|
|
315
|
for(int i=0; i<12; i++)
|
316
|
{
|
317
|
Static4D q = mQuats[i];
|
318
|
dx = x-q.get0();
|
319
|
dy = y-q.get1();
|
320
|
dz = z-q.get2();
|
321
|
dw = w-q.get3();
|
322
|
|
323
|
diff = dx*dx + dy*dy + dz*dz + dw*dw;
|
324
|
|
325
|
if( diff<minDiff )
|
326
|
{
|
327
|
minDiff = diff;
|
328
|
bestindex = i;
|
329
|
}
|
330
|
|
331
|
dx = x+q.get0();
|
332
|
dy = y+q.get1();
|
333
|
dz = z+q.get2();
|
334
|
dw = w+q.get3();
|
335
|
|
336
|
diff = dx*dx + dy*dy + dz*dz + dw*dw;
|
337
|
|
338
|
if( diff<minDiff )
|
339
|
{
|
340
|
minDiff = diff;
|
341
|
bestindex = i;
|
342
|
}
|
343
|
}
|
344
|
|
345
|
return bestindex;
|
346
|
}
|
347
|
|
348
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
349
|
|
350
|
private static void generateMultiplyTable()
|
351
|
{
|
352
|
multiplyTable = new int[12][12];
|
353
|
|
354
|
if( mQuats==null )
|
355
|
mQuats = QuatGroupGenerator.computeGroup(ROT_AXIS,BASIC_ANGLES);
|
356
|
|
357
|
for(int i=0; i<12; i++)
|
358
|
{
|
359
|
Static4D q0 = mQuats[i];
|
360
|
|
361
|
for(int j=0; j<12; j++)
|
362
|
{
|
363
|
Static4D q1 = mQuats[j];
|
364
|
Static4D res= QuatHelper.quatMultiply(q0,q1);
|
365
|
int index = findQuat(res);
|
366
|
multiplyTable[i][j] = index;
|
367
|
}
|
368
|
}
|
369
|
}
|
370
|
|
371
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
372
|
|
373
|
private static void generateTetradPerm()
|
374
|
{
|
375
|
tetradPerm = new int[4][4];
|
376
|
|
377
|
for(int i=0; i<4; i++)
|
378
|
for(int j=0; j<4; j++) tetradPerm[i][j] = -1;
|
379
|
|
380
|
for(int q=0; q<12; q++)
|
381
|
{
|
382
|
int loc0 = computeLocation(0,q);
|
383
|
int loc1 = computeLocation(1,q);
|
384
|
tetradPerm[loc0][loc1] = q;
|
385
|
}
|
386
|
}
|
387
|
|
388
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
389
|
|
390
|
public static int figureOutTetrad(int[] perm)
|
391
|
{
|
392
|
if( tetradPerm==null ) generateTetradPerm();
|
393
|
return tetradPerm[perm[0]][perm[1]];
|
394
|
}
|
395
|
|
396
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
397
|
// return (r^-1) * q
|
398
|
|
399
|
private static int divideFromLeft(int q, int r)
|
400
|
{
|
401
|
if( divideTable==null ) generateDivideTable();
|
402
|
return multiplyTable[divideTable[0][r]][q];
|
403
|
}
|
404
|
|
405
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
406
|
// return q * (r^-1)
|
407
|
|
408
|
private static int divideFromRight(int q, int r)
|
409
|
{
|
410
|
if( divideTable==null ) generateDivideTable();
|
411
|
return divideTable[q][r];
|
412
|
}
|
413
|
|
414
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
415
|
|
416
|
private static int multiplyQuat(int q, int r)
|
417
|
{
|
418
|
if( multiplyTable==null ) generateMultiplyTable();
|
419
|
return multiplyTable[q][r];
|
420
|
}
|
421
|
|
422
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
423
|
// In case of the four 'fixed' corners (0,3,5,6) which do not change their location,
|
424
|
// the twist is natural: 0 in the init positions and increasing 1 mod 3 on each CW turn.
|
425
|
//
|
426
|
// In case of the four 'free' corners their twist is relative to the position of the 'free'
|
427
|
// tetrahedron. And so, for example the twist of free corner 1 (whose 0th face is orange) is equal
|
428
|
// to 0 if free corner 7 is on the same face like 0th face of corner 1 (which is the case in init
|
429
|
// position); then once free corners 2,4,7 permute CW, twist of corner 1 increases by 1 mod 3.
|
430
|
//
|
431
|
// Way to figure out the 'free' twists: notice their final quat must be a product of initial
|
432
|
// 'in place' quat and a common quat which rotates the tetrad of all 4 'free' corners.
|
433
|
// Figure out the tetrad quat and divide free quats by it, then do the same like with fixed corners.
|
434
|
|
435
|
public static void computeCornerTwists(int[] twists, int[] quats)
|
436
|
{
|
437
|
for(int i=0; i<4; i++) twists[FIXED[i]] = fixedQuatToTwist(i,quats[FIXED[i]]);
|
438
|
|
439
|
int free0 = quats[FREE[0]];
|
440
|
int free1 = quats[FREE[1]];
|
441
|
int free2 = quats[FREE[2]];
|
442
|
int free3 = quats[FREE[3]];
|
443
|
|
444
|
int tetradQuat = figureOutTetrad(free0,free1,free2,free3);
|
445
|
|
446
|
if( tetradQuat>=0 )
|
447
|
{
|
448
|
int quat0 = divideFromLeft(free0, tetradQuat);
|
449
|
int quat1 = divideFromLeft(free1, tetradQuat);
|
450
|
int quat2 = divideFromLeft(free2, tetradQuat);
|
451
|
int quat3 = divideFromLeft(free3, tetradQuat);
|
452
|
|
453
|
twists[FREE[0]] = fixedQuatToTwist(3, quat0);
|
454
|
twists[FREE[1]] = fixedQuatToTwist(2, quat1);
|
455
|
twists[FREE[2]] = fixedQuatToTwist(1, quat2);
|
456
|
twists[FREE[3]] = fixedQuatToTwist(0, quat3);
|
457
|
}
|
458
|
else
|
459
|
{
|
460
|
android.util.Log.e("D", "ERROR in computeCornerTwists: "+free0+" "+free1+" "+free2+" "+free3);
|
461
|
}
|
462
|
}
|
463
|
|
464
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
465
|
|
466
|
public static void fillInQuats(int[] quats, int[] perm, int[] twist)
|
467
|
{
|
468
|
for(int i=0; i<4; i++)
|
469
|
{
|
470
|
int fixed = FIXED[i];
|
471
|
int twFi = twist[fixed];
|
472
|
quats[fixed] = fixedQuats[i][twFi];
|
473
|
}
|
474
|
|
475
|
int q0 = fixedTwistToQuat(3,twist[FREE[0]]);
|
476
|
int q1 = fixedTwistToQuat(2,twist[FREE[1]]);
|
477
|
int q2 = fixedTwistToQuat(1,twist[FREE[2]]);
|
478
|
int q3 = fixedTwistToQuat(0,twist[FREE[3]]);
|
479
|
|
480
|
int tetradQuat = figureOutTetrad(perm);
|
481
|
|
482
|
quats[FREE[0]] = multiplyQuat(tetradQuat,q0);
|
483
|
quats[FREE[1]] = multiplyQuat(tetradQuat,q1);
|
484
|
quats[FREE[2]] = multiplyQuat(tetradQuat,q2);
|
485
|
quats[FREE[3]] = multiplyQuat(tetradQuat,q3);
|
486
|
}
|
487
|
|
488
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
489
|
|
490
|
private int[] computeCenterPerm(int[] quats)
|
491
|
{
|
492
|
int[] output = new int[6];
|
493
|
|
494
|
for(int i=0; i<6; i++)
|
495
|
{
|
496
|
output[i] = -1;
|
497
|
int[][] c = centerQuats[i];
|
498
|
int q = quats[8+i];
|
499
|
|
500
|
for(int j=0; j<6; j++)
|
501
|
if( c[j][0]==q || c[j][1]==q )
|
502
|
{
|
503
|
output[i] = j;
|
504
|
break;
|
505
|
}
|
506
|
}
|
507
|
|
508
|
return output;
|
509
|
}
|
510
|
|
511
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
512
|
|
513
|
private void fillCenterQuats(int[] quats, int[] perm)
|
514
|
{
|
515
|
for(int i=0; i<6; i++) quats[8+i] = centerQuats[i][perm[i]][0];
|
516
|
}
|
517
|
|
518
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
519
|
|
520
|
private void fillUpToEvenPerm(int[] perm)
|
521
|
{
|
522
|
int min, max;
|
523
|
|
524
|
if( perm[0]!=0 && perm[1]!=0 ) min=0;
|
525
|
else if( perm[0]!=1 && perm[1]!=1 ) min=1;
|
526
|
else min=2;
|
527
|
|
528
|
if( perm[0]!=3 && perm[1]!=3 ) max=3;
|
529
|
else if( perm[0]!=2 && perm[1]!=2 ) max=2;
|
530
|
else max=1;
|
531
|
|
532
|
int diff = perm[1]-perm[0];
|
533
|
|
534
|
if( diff==-2 || diff==1 || diff==3 ) { perm[2]=min; perm[3]=max; }
|
535
|
else { perm[2]=max; perm[3]=min; }
|
536
|
}
|
537
|
|
538
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
539
|
|
540
|
public static int permFree1(int permFree0, int sumFixedTwists)
|
541
|
{
|
542
|
return freeIndex[permFree0][sumFixedTwists%3];
|
543
|
}
|
544
|
|
545
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
546
|
|
547
|
int[] getQuats(int index)
|
548
|
{
|
549
|
int[] permFree = new int[4];
|
550
|
int center_perm_num = (index%360);
|
551
|
index /= 360;
|
552
|
int totalTwist = (index%2187);
|
553
|
permFree[0] = (index/2187);
|
554
|
|
555
|
int[] quats = new int[14];
|
556
|
int[] center_perm = new int[6];
|
557
|
int[] twist = new int[8];
|
558
|
|
559
|
TablebaseHelpers.getEvenPermutationFromNum(center_perm, center_perm_num);
|
560
|
fillCenterQuats(quats,center_perm);
|
561
|
|
562
|
int total = 0;
|
563
|
|
564
|
for(int i=0; i<7; i++)
|
565
|
{
|
566
|
twist[i] = (totalTwist%3);
|
567
|
totalTwist /= 3;
|
568
|
total += twist[i];
|
569
|
}
|
570
|
|
571
|
twist[7] = ((24-total)%3);
|
572
|
int sumFixedTwists = twist[FIXED[0]]+twist[FIXED[1]]+twist[FIXED[2]]+twist[FIXED[3]];
|
573
|
|
574
|
permFree[1] = permFree1(permFree[0],sumFixedTwists);
|
575
|
fillUpToEvenPerm(permFree);
|
576
|
fillInQuats(quats,permFree,twist);
|
577
|
|
578
|
return quats;
|
579
|
}
|
580
|
|
581
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
582
|
|
583
|
int getIndex(int[] quats)
|
584
|
{
|
585
|
int[] center_perm = computeCenterPerm(quats);
|
586
|
int center_perm_num = TablebaseHelpers.computeEvenPermutationNum(center_perm);
|
587
|
int[] twist = new int[8];
|
588
|
computeCornerTwists(twist,quats);
|
589
|
int totalTwist = twist[0]+ 3*(twist[1]+ 3*(twist[2]+ 3*(twist[3]+ 3*(twist[4]+ 3*(twist[5]+ 3*twist[6])))));
|
590
|
int locationOfFree0 = computeLocation(0,quats[1]);
|
591
|
|
592
|
return center_perm_num+ 360*(totalTwist + 2187*locationOfFree0);
|
593
|
}
|
594
|
}
|
595
|
|