Project

General

Profile

« Previous | Next » 

Revision 358be403

Added by Leszek Koltunski over 2 years ago

Optimize the solver.

View differences:

src/main/java/org/distorted/solvers/SolverMain.java
27 27
import org.distorted.main.R;
28 28
import org.distorted.screens.ScreenList;
29 29
import org.distorted.screens.RubikScreenSolver;
30
import org.distorted.solvers.cube3.RubikSolverSearch;
30 31

  
31 32
///////////////////////////////////////////////////////////////////////////////////////////////////
32 33

  
......
72 73
    {
73 74
    String result;
74 75

  
75
    if( !org.distorted.solvers.cube3.Search.prepare(mRes) )
76
      result= "Error 9";
77
    else
78
      {
79
      String objectPosition = prepareCube3position();
80
      result = org.distorted.solvers.cube3.Search.solution(objectPosition, 24, 20);
81
      }
76
    RubikSolverSearch.prepare(mRes);
77
    String objectPosition = prepareCube3position();
78
    result = RubikSolverSearch.solution(objectPosition, 24, 20);
82 79

  
83 80
    if (result.contains("Error"))
84 81
      {
......
207 204
    return objectString.toString();
208 205
    }
209 206

  
210
///////////////////////////////////////////////////////////////////////////////////////////////////
211

  
212
  private void interruptCube3()
213
    {
214
    org.distorted.solvers.cube3.Search.interrupt();
215
    }
216

  
217 207
///////////////////////////////////////////////////////////////////////////////////////////////////
218 208

  
219 209
  public void start()
src/main/java/org/distorted/solvers/cube3/Color.java
1
package org.distorted.solvers.cube3;
2

  
3
//++++++++++++++++++++++++++++++ Names the colors of the cube facelets ++++++++++++++++++++++++++++++++++++++++++++++++
4

  
5
class Color
6
  {
7
  public static final int U=0;
8
  public static final int R=1;
9
  public static final int F=2;
10
  public static final int D=3;
11
  public static final int L=4;
12
  public static final int B=5;
13

  
14
  public static String toString(int i)
15
    {
16
    switch(i)
17
      {
18
      case U: return "U";
19
      case R: return "R";
20
      case F: return "F";
21
      case D: return "D";
22
      case L: return "L";
23
      case B: return "B";
24
      default: return "?";
25
      }
26
    }
27
  
28
  public static int toInt(String s)
29
    {
30
	switch(s.charAt(0))
31
      {
32
      case 'U': return U;
33
      case 'R': return R;
34
      case 'F': return F;
35
      case 'D': return D;
36
      case 'L': return L;
37
      case 'B': return B;
38
      default: return -1;
39
      }  
40
    }
41
  }
src/main/java/org/distorted/solvers/cube3/CoordCube.java
1
package org.distorted.solvers.cube3;
2

  
3
import android.content.res.Resources;
4
import java.io.InputStream;
5

  
6
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
7
// Representation of the cube on the coordinate level
8
class CoordCube {
9

  
10
	static final short N_TWIST = 2187;// 3^7 possible corner orientations
11
	static final short N_FLIP = 2048;// 2^11 possible edge flips
12
	static final short N_SLICE1 = 495;// 12 choose 4 possible positions of FR,FL,BL,BR edges
13
	static final short N_SLICE2 = 24;// 4! permutations of FR,FL,BL,BR edges in phase2
14
	static final short N_PARITY = 2; // 2 possible corner parities
15
	static final short N_URFtoDLF = 20160;// 8!/(8-6)! permutation of URF,UFL,ULB,UBR,DFR,DLF corners
16
	static final short N_FRtoBR = 11880; // 12!/(12-4)! permutation of FR,FL,BL,BR edges
17
	static final short N_URtoUL = 1320; // 12!/(12-3)! permutation of UR,UF,UL edges
18
	static final short N_UBtoDF = 1320; // 12!/(12-3)! permutation of UB,DR,DF edges
19
	static final short N_URtoDF = 20160; // 8!/(8-6)! permutation of UR,UF,UL,UB,DR,DF edges in phase2
20
	
21
	static final int N_URFtoDLB = 40320;// 8! permutations of the corners
22
	static final int N_URtoBR = 479001600;// 8! permutations of the corners
23
	
24
	static final short N_MOVE = 18;
25

  
26
	// All coordinates are 0 for a solved cube except for UBtoDF, which is 114
27
	short twist;
28
	short flip;
29
	short parity;
30
	short FRtoBR;
31
	short URFtoDLF;
32
	short URtoUL;
33
	short UBtoDF;
34
	int URtoDF;
35

  
36
	private static boolean[] init = new boolean[12];
37
	
38
	static 
39
	  {
40
	  for(int i=0; i<12; i++ ) init[i] = false;	
41
	  }
42
	
43
	// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
44
	// Generate a CoordCube from a CubieCube
45
	CoordCube(CubieCube c) {
46
		twist = c.getTwist();
47
		flip = c.getFlip();
48
		parity = c.cornerParity();
49
		FRtoBR = c.getFRtoBR();
50
		URFtoDLF = c.getURFtoDLF();
51
		URtoUL = c.getURtoUL();
52
		UBtoDF = c.getUBtoDF();
53
		URtoDF = c.getURtoDF();// only needed in phase2
54
	}
55

  
56
	// A move on the coordinate level
57
	// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
58
	void move(int m) {
59
		twist = getTwistMove(twist,m);
60
		flip = getFlipMove(flip,m);
61
		parity = parityMove[parity][m];
62
		FRtoBR = getFRtoBR_Move(FRtoBR,m);
63
		URFtoDLF = getURFtoDLF_Move(URFtoDLF,m);
64
		URtoUL = getURtoUL_Move(URtoUL,m);
65
		UBtoDF = getUBtoDF_Move(UBtoDF,m);
66
		if (URtoUL < 336 && UBtoDF < 336)// updated only if UR,UF,UL,UB,DR,DF
67
			// are not in UD-slice
68
			URtoDF = getMergeURtoULandUBtoDF(URtoUL,UBtoDF);
69
	}
70

  
71
	// ******************************************Phase 1 move tables*****************************************************
72

  
73
	// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
74
	// Move table for the twists of the corners
75
	// twist < 2187 in phase 2.
76
	// twist = 0 in phase 2.
77
	private static byte[] twistMove = new byte[2*N_TWIST*N_MOVE];
78
	
79
	public static boolean initialize1(Resources res)
80
	{
81
		if( !init[0] )
82
		  {
83
          try
84
		    {
85
        	InputStream is = res.openRawResource(org.distorted.main.R.raw.cube3solver_table1);
86
		    is.read( twistMove, 0, 2*N_TWIST*N_MOVE);
87
		    }
88
		  catch(Exception ioe)
89
		    {
90
		    System.out.println("error reading table1");
91
                    return false;
92
		    }
93
		
94
		  init[0]=true;
95
		  }
96

  
97
                return true;
98
	}
99

  
100
	public static short getTwistMove(int a,int b)
101
	{
102
		short upperS = twistMove[2*(a*N_MOVE+b)];
103
		short lowerS = twistMove[2*(a*N_MOVE+b)+1];
104
		
105
		if( upperS<0 ) upperS+=256;
106
		if( lowerS<0 ) lowerS+=256;
107
		
108
		return  (short)( (upperS<<8) + lowerS );
109
	}
110
	
111
	// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
112
	// Move table for the flips of the edges
113
	// flip < 2048 in phase 1
114
	// flip = 0 in phase 2.
115
	private static byte[] flipMove = new byte[2*N_FLIP*N_MOVE];
116
	
117
	public static boolean initialize2(Resources res)
118
	{
119
		if( !init[1] )
120
		  {
121
		  try
122
		    {
123
			InputStream is = res.openRawResource(org.distorted.main.R.raw.cube3solver_table2);
124
		    is.read( flipMove, 0, 2*N_FLIP*N_MOVE);
125
		    }
126
		  catch(Exception ioe)
127
		    {
128
		    System.out.println("error reading table2");
129
                    return false;
130
		    }
131
		
132
		  init[1]=true;
133
		  }
134

  
135
                return true;
136
	}
137
	
138
	public static short getFlipMove(int a,int b)
139
	{
140
		short upperS = flipMove[2*(a*N_MOVE+b)];
141
		short lowerS = flipMove[2*(a*N_MOVE+b)+1];
142
		
143
		if( upperS<0 ) upperS+=256;
144
		if( lowerS<0 ) lowerS+=256;
145
		
146
		return  (short)( (upperS<<8) + lowerS );
147
	}
148
	
149
	// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
150
	// Parity of the corner permutation. This is the same as the parity for the edge permutation of a valid cube.
151
	// parity has values 0 and 1
152
	static short[][] parityMove = { { 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1 },
153
			{ 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0 } };
154

  
155
	// ***********************************Phase 1 and 2 movetable********************************************************
156

  
157
	// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
158
	// Move table for the four UD-slice edges FR, FL, Bl and BR
159
	// FRtoBRMove < 11880 in phase 1
160
	// FRtoBRMove < 24 in phase 2
161
	// FRtoBRMove = 0 for solved cube
162
	private static byte[] FRtoBR_Move = new byte[2*N_FRtoBR*N_MOVE];
163
	
164
	public static boolean initialize3(Resources res)
165
	{
166
		if( !init[2] )
167
		  {
168
		  try
169
		    {
170
			InputStream is = res.openRawResource(org.distorted.main.R.raw.cube3solver_table3);
171
		    is.read( FRtoBR_Move, 0, 2*N_FRtoBR*N_MOVE);
172
		    }
173
		  catch(Exception ioe)
174
		    {
175
		    System.out.println("error reading table3");
176
                    return true;
177
		    }
178
		
179
		  init[2]=true;
180
		  }
181

  
182
                return false;
183
	}
184

  
185
	public static short getFRtoBR_Move(int a,int b)
186
	{
187
		short upperS = FRtoBR_Move[2*(a*N_MOVE+b)];
188
		short lowerS = FRtoBR_Move[2*(a*N_MOVE+b)+1];
189
		
190
		if( upperS<0 ) upperS+=256;
191
		if( lowerS<0 ) lowerS+=256;
192
		
193
		return  (short)( (upperS<<8) + lowerS );
194
	}
195
	
196
	// *******************************************Phase 1 and 2 movetable************************************************
197

  
198
	// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
199
	// Move table for permutation of six corners. The positions of the DBL and DRB corners are determined by the parity.
200
	// URFtoDLF < 20160 in phase 1
201
	// URFtoDLF < 20160 in phase 2
202
	// URFtoDLF = 0 for solved cube.
203
	private static byte[] URFtoDLF_Move = new byte[2*N_URFtoDLF*N_MOVE];
204
	
205
	public static boolean initialize4(Resources res)
206
	{
207
		if( !init[3] )
208
		  {
209
		  try
210
		    {
211
			InputStream is = res.openRawResource(org.distorted.main.R.raw.cube3solver_table4);
212
		    is.read( URFtoDLF_Move, 0, 2*N_URFtoDLF*N_MOVE);
213
		    }
214
		  catch(Exception ioe)
215
		    {
216
		    System.out.println("error reading table4");
217
                    return false;
218
		    }
219
		
220
		  init[3]=true;
221
		  }
222

  
223
                return true;
224
	}
225
	
226
	public static short getURFtoDLF_Move(int a,int b)
227
	{
228
		short upperS = URFtoDLF_Move[2*(a*N_MOVE+b)];
229
		short lowerS = URFtoDLF_Move[2*(a*N_MOVE+b)+1];
230
		
231
		if( upperS<0 ) upperS+=256;
232
		if( lowerS<0 ) lowerS+=256;
233
		
234
		return  (short)( (upperS<<8) + lowerS );
235
	}
236
	// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
237
	// Move table for the permutation of six U-face and D-face edges in phase2. The positions of the DL and DB edges are
238
	// determined by the parity.
239
	// URtoDF < 665280 in phase 1
240
	// URtoDF < 20160 in phase 2
241
	// URtoDF = 0 for solved cube.
242
	private static byte[] URtoDF_Move = new byte[2*N_URtoDF*N_MOVE];
243
	
244
	public static boolean initialize5(Resources res)
245
	{
246
		if( !init[4] )
247
		  {
248
		  try
249
		    {
250
			InputStream is = res.openRawResource(org.distorted.main.R.raw.cube3solver_table5);
251
		    is.read( URtoDF_Move, 0, 2*N_URtoDF*N_MOVE);
252
		    }
253
		  catch(Exception ioe)
254
		    {
255
		    System.out.println("error reading table5");
256
                    return false;
257
		    }
258
		
259
		  init[4]=true;
260
		  }
261

  
262
                return true;
263
	}
264
	
265
	public static short getURtoDF_Move(int a,int b)
266
	{
267
		short upperS = URtoDF_Move[2*(a*N_MOVE+b)];
268
		short lowerS = URtoDF_Move[2*(a*N_MOVE+b)+1];
269
		
270
		if( upperS<0 ) upperS+=256;
271
		if( lowerS<0 ) lowerS+=256;
272
		
273
		return  (short)( (upperS<<8) + lowerS );
274
	}
275
	// **************************helper move tables to compute URtoDF for the beginning of phase2************************
276

  
277
	// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
278
	// Move table for the three edges UR,UF and UL in phase1.
279
	private static byte[] URtoUL_Move = new byte[2*N_URtoUL*N_MOVE];
280
	
281
	public static boolean initialize6(Resources res)
282
	{
283
		if( !init[5] )
284
		  {
285
		  try
286
		    {
287
			InputStream is = res.openRawResource(org.distorted.main.R.raw.cube3solver_table6);
288
		    is.read( URtoUL_Move, 0, 2*N_URtoUL*N_MOVE);
289
		    }
290
		  catch(Exception ioe)
291
		    {
292
		    System.out.println("error reading table6");
293
                    return false;
294
		    }
295
		
296
		  init[5]=true;
297
		  }
298

  
299
                return true;
300
	}
301

  
302
	public static short getURtoUL_Move(int a,int b)
303
	{
304
		short upperS = URtoUL_Move[2*(a*N_MOVE+b)];
305
		short lowerS = URtoUL_Move[2*(a*N_MOVE+b)+1];
306
		
307
		if( upperS<0 ) upperS+=256;
308
		if( lowerS<0 ) lowerS+=256;
309
		
310
		return  (short)( (upperS<<8) + lowerS );
311
	}
312
	
313
	// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
314
	// Move table for the three edges UB,DR and DF in phase1.
315
	private static byte[] UBtoDF_Move = new byte[2*N_UBtoDF*N_MOVE];
316
	
317
	public static boolean initialize7(Resources res)
318
	{
319
		if( !init[6] )
320
		  {
321
		  try
322
		    {
323
			InputStream is = res.openRawResource(org.distorted.main.R.raw.cube3solver_table7);
324
		    is.read( UBtoDF_Move, 0, 2*N_UBtoDF*N_MOVE);
325
		    }
326
		  catch(Exception ioe)
327
		    {
328
		    System.out.println("error reading table7");
329
                    return false;
330
		    }
331
		
332
		  init[6]=true;
333
		  }
334

  
335
                return true;
336
	}
337
	
338
	public static short getUBtoDF_Move(int a,int b)
339
	{
340
		short upperS = UBtoDF_Move[2*(a*N_MOVE+b)];
341
		short lowerS = UBtoDF_Move[2*(a*N_MOVE+b)+1];
342
		
343
		if( upperS<0 ) upperS+=256;
344
		if( lowerS<0 ) lowerS+=256;
345
		
346
		return  (short)( (upperS<<8) + lowerS );
347
	}
348
	
349
	// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
350
	// Table to merge the coordinates of the UR,UF,UL and UB,DR,DF edges at the beginning of phase2
351
	private static byte[] MergeURtoULandUBtoDF = new byte[2*336*336];
352
	
353
	public static boolean initialize8(Resources res)
354
	{
355
		if( !init[7] )
356
		  {
357
		  try
358
		    {
359
			InputStream is = res.openRawResource(org.distorted.main.R.raw.cube3solver_table8);
360
		    is.read( MergeURtoULandUBtoDF, 0, 2*336*336);
361
		    }
362
		  catch(Exception ioe)
363
		    {
364
		    System.out.println("error reading table8");
365
                    return false;
366
		    }
367
		
368
		  init[7]=true;
369
		  }
370

  
371
                return true;
372
	}
373
	
374
	public static short getMergeURtoULandUBtoDF(int a,int b)
375
	{
376
		short upperS = MergeURtoULandUBtoDF[2*(a*336+b)];
377
		short lowerS = MergeURtoULandUBtoDF[2*(a*336+b)+1];
378
		
379
		if( upperS<0 ) upperS+=256;
380
		if( lowerS<0 ) lowerS+=256;
381
		
382
		return  (short)( (upperS<<8) + lowerS );
383
	}
384
	// ****************************************Pruning tables for the search*********************************************
385

  
386
	// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
387
	// Pruning table for the permutation of the corners and the UD-slice edges in phase2.
388
	// The pruning table entries give a lower estimation for the number of moves to reach the solved cube.
389
	public static byte[] Slice_URFtoDLF_Parity_Prun = new byte[N_SLICE2 * N_URFtoDLF * N_PARITY / 2];
390
	
391
	public static boolean initialize9(Resources res)
392
	{
393
		if( !init[8] )
394
		  {
395
		  try
396
		    {
397
			  InputStream is = res.openRawResource(org.distorted.main.R.raw.cube3solver_table9);
398
		    is.read( Slice_URFtoDLF_Parity_Prun, 0, N_SLICE2 * N_URFtoDLF * N_PARITY / 2);
399
		    }
400
		  catch(Exception ioe)
401
		    {
402
		    System.out.println("error reading table9");
403
                    return false;
404
		    }
405
		
406
		  init[8]=true;
407
		  }
408

  
409
    return true;
410
	}
411

  
412
	// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
413
	// Pruning table for the permutation of the edges in phase2.
414
	// The pruning table entries give a lower estimation for the number of moves to reach the solved cube.
415
	public static byte[] Slice_URtoDF_Parity_Prun = new byte[N_SLICE2 * N_URtoDF * N_PARITY / 2];
416
	
417
	public static boolean initialize10(Resources res)
418
	{
419
		if( !init[9] )
420
		  {
421
		  try
422
		    {
423
			InputStream is = res.openRawResource(org.distorted.main.R.raw.cube3solver_table10);
424
		    is.read( Slice_URtoDF_Parity_Prun, 0, N_SLICE2 * N_URtoDF * N_PARITY / 2);
425
		    }
426
		  catch(Exception ioe)
427
		    {
428
		    System.out.println("error reading table10");
429
                    return false;
430
		    }
431
		
432
		  init[9]=true;
433
		  }
434

  
435
                return true;
436
	}
437

  
438
	// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
439
	// Pruning table for the twist of the corners and the position (not permutation) of the UD-slice edges in phase1
440
	// The pruning table entries give a lower estimation for the number of moves to reach the H-subgroup.
441
	public static byte[] Slice_Twist_Prun = new byte[N_SLICE1 * N_TWIST / 2 + 1];
442
	
443
	public static boolean initialize11(Resources res)
444
	{
445
		if( !init[10] )
446
		  {
447
		  try
448
		    {
449
			InputStream is = res.openRawResource(org.distorted.main.R.raw.cube3solver_table11);
450
		    is.read( Slice_Twist_Prun, 0, N_SLICE1 * N_TWIST / 2 + 1);
451
		    }
452
		  catch(Exception ioe)
453
		    {
454
		    System.out.println("error reading table11");
455
                    return false;
456
		    }
457
		
458
		  init[10]=true;
459
		  }
460

  
461
                return true;
462
	}
463

  
464
	// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
465
	// Pruning table for the flip of the edges and the position (not permutation) of the UD-slice edges in phase1
466
	// The pruning table entries give a lower estimation for the number of moves to reach the H-subgroup.
467
	public static byte[] Slice_Flip_Prun = new byte[N_SLICE1 * N_FLIP / 2];
468
	
469
	public static boolean initialize12(Resources res)
470
	{
471
		if( !init[11] )
472
		  {
473
		  try
474
		    {
475
			InputStream is = res.openRawResource(org.distorted.main.R.raw.cube3solver_table12);
476
		    is.read( Slice_Flip_Prun, 0, N_SLICE1 * N_FLIP / 2);
477
		    }
478
		  catch(Exception ioe)
479
		    {
480
		    System.out.println("error reading table12");
481
                    return false;
482
		    }
483
		
484
		  init[11]=true;
485
		  }
486

  
487
                return true;
488
	}
489

  
490
	// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
491
	// Set pruning value in table. Two values are stored in one byte.
492
	static void setPruning(byte[] table, int index, byte value) {
493
		if ((index & 1) == 0)
494
			table[index / 2] &= 0xf0 | value;
495
		else
496
			table[index / 2] &= 0x0f | (value << 4);
497
	}
498

  
499
	// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
500
	// Extract pruning value
501
	static byte getPruning(byte[] table, int index) {
502
		if ((index & 1) == 0)
503
			return (byte) (table[index / 2] & 0x0f);
504
		else
505
			return (byte) ((table[index / 2] & 0xf0) >>> 4);
506
	}
507
}
src/main/java/org/distorted/solvers/cube3/Corner.java
1
package org.distorted.solvers.cube3;
2

  
3
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
4
//The names of the corner positions of the cube. Corner URF e.g., has an U(p), a R(ight) and a F(ront) facelet
5

  
6
class Corner
7
  {
8
  public static final int URF =0;
9
  public static final int UFL =1;
10
  public static final int ULB =2;
11
  public static final int UBR =3;
12
  public static final int DFR =4;
13
  public static final int DLF =5;
14
  public static final int DBL =6;
15
  public static final int DRB =7;
16
  }
src/main/java/org/distorted/solvers/cube3/CubieCube.java
1
package org.distorted.solvers.cube3;
2

  
3
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
4
//Cube on the cubie level
5
class CubieCube
6
  {
7
  private static int[][] cnk = new int[12][7];
8
	
9
  private static byte[] tmpByte12   = new byte[12];
10
  private static byte[] tmpByte8    = new byte[8];
11
	
12
  private static int[] tmpEdge12    = new int[12];
13
  private static int[] tmpEdge6     = new int[6];
14
  private static int[] tmpEdge4     = new int[4];
15
  private static int[] tmpEdge3     = new int[3];
16
	
17
  private static int[] tmpCorner6 = new int[6];
18
  private static int[] tmpCorner8 = new int[8];
19

  
20
  // initialize to Id-Cube
21

  
22
  // corner permutation
23
  int[] cp = { Corner.URF, Corner.UFL, Corner.ULB, Corner.UBR, Corner.DFR, Corner.DLF, Corner.DBL, Corner.DRB };
24

  
25
  // corner orientation
26
  byte[] co = { 0, 0, 0, 0, 0, 0, 0, 0 };
27

  
28
  // edge permutation
29
  int[] ep = { Edge.UR, Edge.UF, Edge.UL, Edge.UB, Edge.DR, Edge.DF, Edge.DL, Edge.DB, Edge.FR, Edge.FL, Edge.BL, Edge.BR };
30

  
31
  // edge orientation
32
  byte[] eo = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
33

  
34
  // ************************************** Moves on the cubie level ***************************************************
35

  
36
  private static int[]  cpU = { Corner.UBR, Corner.URF, Corner.UFL, Corner.ULB, Corner.DFR, Corner.DLF, Corner.DBL, Corner.DRB };
37
  private static byte[] coU = { 0, 0, 0, 0, 0, 0, 0, 0 };
38
  private static int[]  epU = { Edge.UB, Edge.UR, Edge.UF, Edge.UL, Edge.DR, Edge.DF, Edge.DL, Edge.DB, Edge.FR, Edge.FL, Edge.BL, Edge.BR };
39
  private static byte[] eoU = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
40

  
41
  private static int[]  cpR = { Corner.DFR, Corner.UFL, Corner.ULB, Corner.URF, Corner.DRB, Corner.DLF, Corner.DBL, Corner.UBR };
42
  private static byte[] coR = { 2, 0, 0, 1, 1, 0, 0, 2 };
43
  private static int[]  epR = { Edge.FR, Edge.UF, Edge.UL, Edge.UB, Edge.BR, Edge.DF, Edge.DL, Edge.DB, Edge.DR, Edge.FL, Edge.BL, Edge.UR };
44
  private static byte[] eoR = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
45

  
46
  private static int[]  cpF = { Corner.UFL, Corner.DLF, Corner.ULB, Corner.UBR, Corner.URF, Corner.DFR, Corner.DBL, Corner.DRB };
47
  private static byte[] coF = { 1, 2, 0, 0, 2, 1, 0, 0 };
48
  private static int[]  epF = { Edge.UR, Edge.FL, Edge.UL, Edge.UB, Edge.DR, Edge.FR, Edge.DL, Edge.DB, Edge.UF, Edge.DF, Edge.BL, Edge.BR };
49
  private static byte[] eoF = { 0, 1, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0 };
50

  
51
  private static int[]  cpD = { Corner.URF, Corner.UFL, Corner.ULB, Corner.UBR, Corner.DLF, Corner.DBL, Corner.DRB, Corner.DFR };
52
  private static byte[] coD = { 0, 0, 0, 0, 0, 0, 0, 0 };
53
  private static int[]  epD = { Edge.UR, Edge.UF, Edge.UL, Edge.UB, Edge.DF, Edge.DL, Edge.DB, Edge.DR, Edge.FR, Edge.FL, Edge.BL, Edge.BR };
54
  private static byte[] eoD = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
55

  
56
  private static int[]  cpL = { Corner.URF, Corner.ULB, Corner.DBL, Corner.UBR, Corner.DFR, Corner.UFL, Corner.DLF, Corner.DRB };
57
  private static byte[] coL = { 0, 1, 2, 0, 0, 2, 1, 0 };
58
  private static int[]  epL = { Edge.UR, Edge.UF, Edge.BL, Edge.UB, Edge.DR, Edge.DF, Edge.FL, Edge.DB, Edge.FR, Edge.UL, Edge.DL, Edge.BR };
59
  private static byte[] eoL = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
60

  
61
  private static int[]  cpB = { Corner.URF, Corner.UFL, Corner.UBR, Corner.DRB, Corner.DFR, Corner.DLF, Corner.ULB, Corner.DBL };
62
  private static byte[] coB = { 0, 0, 1, 2, 0, 0, 2, 1 };
63
  private static int[]  epB = { Edge.UR, Edge.UF, Edge.UL, Edge.BR, Edge.DR, Edge.DF, Edge.DL, Edge.BL, Edge.FR, Edge.FL, Edge.UB, Edge.DB };
64
  private static byte[] eoB = { 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 1 };
65

  
66
  // this CubieCube array represents the 6 basic cube moves
67
  static CubieCube[] moveCube = new CubieCube[6];
68

  
69
  static
70
    {
71
    moveCube[0] = new CubieCube();
72
    moveCube[0].cp = cpU;
73
    moveCube[0].co = coU;
74
    moveCube[0].ep = epU;
75
    moveCube[0].eo = eoU;
76

  
77
    moveCube[1] = new CubieCube();
78
    moveCube[1].cp = cpR;
79
    moveCube[1].co = coR;
80
    moveCube[1].ep = epR;
81
    moveCube[1].eo = eoR;
82

  
83
    moveCube[2] = new CubieCube();
84
    moveCube[2].cp = cpF;
85
    moveCube[2].co = coF;
86
    moveCube[2].ep = epF;
87
    moveCube[2].eo = eoF;
88

  
89
    moveCube[3] = new CubieCube();
90
    moveCube[3].cp = cpD;
91
    moveCube[3].co = coD;
92
    moveCube[3].ep = epD;
93
    moveCube[3].eo = eoD;
94

  
95
    moveCube[4] = new CubieCube();
96
    moveCube[4].cp = cpL;
97
    moveCube[4].co = coL;
98
    moveCube[4].ep = epL;
99
    moveCube[4].eo = eoL;
100

  
101
    moveCube[5] = new CubieCube();
102
    moveCube[5].cp = cpB;
103
    moveCube[5].co = coB;
104
    moveCube[5].ep = epB;
105
    moveCube[5].eo = eoB;
106
    }
107

  
108
  static
109
    {
110
    for(int n=0; n<12; n++)
111
      for(int k=0; k<7; k++)
112
	cnk[n][k] = -1;
113
    }
114
	
115
  CubieCube() { };
116

  
117
  // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
118
  CubieCube(int[] cp, byte[] co, int[] ep, byte[] eo)
119
    {
120
    this();
121

  
122
    for (int i = 0; i < 8; i++)
123
      {
124
      this.cp[i] = cp[i];
125
      this.co[i] = co[i];
126
      }
127
    for (int i = 0; i < 12; i++)
128
      {
129
      this.ep[i] = ep[i];
130
      this.eo[i] = eo[i];
131
      }
132
    }
133

  
134
  // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
135
  // n choose k
136
  static int Cnk(int n, int k)
137
    {
138
    if( cnk[n][k]<0 )
139
      {
140
      int i, j, s;
141
		
142
      if (n < k) { cnk[n][k]=0; return 0; }
143
      if (k > n / 2) k = n - k;
144
		  
145
      for (s = 1, i = n, j = 1; i != n - k; i--, j++)
146
        {
147
	s *= i;
148
	s /= j;
149
        }
150
      cnk[n][k]= s;
151
      }
152
		
153
    return cnk[n][k];
154
    }
155

  
156
  // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
157
  static void rotateLeft(int[] arr, int l, int r)
158
    // Left rotation of all array elements between l and r
159
    {
160
    int tmp = arr[l];
161
    for (int i = l; i < r; i++) arr[i] = arr[i + 1];
162
    arr[r] = tmp;
163
    }
164

  
165
  // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
166
  static void rotateRight(int[] arr, int l, int r)
167
    // Right rotation of all array elements between l and r
168
    {
169
    int tmp = arr[r];
170
    for (int i = r; i > l; i--) arr[i] = arr[i - 1];
171
    arr[l] = tmp;
172
    }
173

  
174
  // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
175
  // return cube in facelet representation
176
  FaceCube toFaceCube()
177
    {
178
    FaceCube fcRet = new FaceCube();
179

  
180
    for ( int c=Corner.URF; c<=Corner.DRB; c++)
181
      {
182
      int j = cp[c];   // cornercubie with index j is at cornerposition with index i
183
      byte ori = co[c];// Orientation of this cubie
184

  
185
      for (int n = 0; n < 3; n++)
186
        fcRet.f[FaceCube.cornerFacelet[c][(n + ori) % 3]] = FaceCube.cornerColor[j][n];
187
      }
188

  
189
    for ( int e=Edge.UR; e<=Edge.BR; e++)
190
      {
191
      int j = ep[e];   // edgecubie with index j is at edgeposition with index i
192
      byte ori = eo[e];// Orientation of this cubie
193

  
194
      for (int n = 0; n < 2; n++)
195
	fcRet.f[FaceCube.edgeFacelet[e][(n + ori) % 2]] = FaceCube.edgeColor[j][n];
196
      }
197

  
198
    return fcRet;
199
    }
200

  
201
  // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
202
  // Multiply this CubieCube with another cubiecube b, restricted to the corners.<br>
203
  // Because we also describe reflections of the whole cube by permutations, we get a complication with the corners. The
204
  // orientations of mirrored corners are described by the numbers 3, 4 and 5. The composition of the orientations
205
  // cannot
206
  // be computed by addition modulo three in the cyclic group C3 any more. Instead the rules below give an addition in
207
  // the dihedral group D3 with 6 elements.<br>
208
  //
209
  // NOTE: Because we do not use symmetry reductions and hence no mirrored cubes in this simple implementation of the
210
  // Two-Phase-Algorithm, some code is not necessary here.
211
  //
212
  void cornerMultiply(CubieCube b)
213
    {
214
    for ( int corn=Corner.URF; corn<=Corner.DRB; corn++)
215
      {
216
      tmpCorner8[corn] = cp[b.cp[corn]];
217
      byte oriA = co[b.cp[corn]];
218
      byte oriB = b.co[corn];
219
      byte ori = 0;
220
			
221
      if (oriA < 3 && oriB < 3) // if both cubes are regular cubes...
222
        {
223
	ori = (byte) (oriA + oriB); // just do an addition modulo 3 here
224
	if (ori >= 3) ori -= 3;     // the composition is a regular cube
225

  
226
  // +++++++++++++++++++++not used in this implementation +++++++++++++++++++++++++++++++++++
227
	}
228
      else if (oriA < 3 && oriB >= 3) // if cube b is in a mirrored state...
229
        {
230
	ori = (byte) (oriA + oriB);
231
	if (ori >= 6) ori -= 3; // the composition is a mirrored cube
232
	}
233
      else if (oriA >= 3 && oriB < 3) // if cube a is an a mirrored state...
234
	{
235
	ori = (byte) (oriA - oriB);
236
	if (ori < 3) ori += 3; // the composition is a mirrored cube
237
	}
238
      else if (oriA >= 3 && oriB >= 3) // if both cubes are in mirrored states...
239
	{
240
	ori = (byte) (oriA - oriB);
241
	if (ori < 0) ori += 3; // the composition is a regular cube
242
  // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
243
	}
244

  
245
      tmpByte8[corn] = ori;
246
      }
247

  
248
    for ( int c=Corner.URF; c<=Corner.DRB; c++)
249
      {
250
      cp[c] = tmpCorner8[c];
251
      co[c] = tmpByte8[c];
252
      }
253
    }
254

  
255
  // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
256
  // Multiply this CubieCube with another cubiecube b, restricted to the edges.
257
  void edgeMultiply(CubieCube b)
258
    {
259
    for ( int edge=Edge.UR; edge<=Edge.BR; edge++)
260
      {
261
      tmpEdge12[edge] = ep[b.ep[edge]];
262
      tmpByte12[edge] = (byte) ((b.eo[edge] + eo[b.ep[edge]]) % 2);
263
      }
264
		
265
    for ( int e=Edge.UR; e<=Edge.BR; e++)
266
      {
267
      ep[e] = tmpEdge12[e];
268
      eo[e] = tmpByte12[e];
269
      }
270
    }
271

  
272
  // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
273
  // Multiply this CubieCube with another CubieCube b.
274
  void multiply(CubieCube b)
275
    {
276
    cornerMultiply(b);
277
  //edgeMultiply(b);
278
    }
279

  
280
  // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
281
  // Compute the inverse CubieCube
282
  void invCubieCube(CubieCube c)
283
    {
284
    for ( int edge=Edge.UR; edge<=Edge.BR; edge++) c.ep[ep[edge]] = edge;
285
    for ( int edge=Edge.UR; edge<=Edge.BR; edge++) c.eo[edge] = eo[c.ep[edge]];
286

  
287
    for ( int corn=Corner.URF; corn<=Corner.DRB; corn++) c.cp[cp[corn]] = corn;
288
    for ( int corn=Corner.URF; corn<=Corner.DRB; corn++)
289
      {
290
      byte ori = co[c.cp[corn]];
291
      if (ori >= 3)// Just for completeness. We do not invert mirrored cubes in the program.
292
        c.co[corn] = ori;
293
      else
294
        {// the standard case
295
        c.co[corn] = (byte) -ori;
296
        if (c.co[corn] < 0) c.co[corn] += 3;
297
        }
298
      }
299
    }
300

  
301
  // ********************************************* Get and set coordinates *********************************************
302

  
303
  // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
304
  // return the twist of the 8 corners. 0 <= twist < 3^7
305
  short getTwist()
306
    {
307
    short ret = 0;
308

  
309
    for ( int i=Corner.URF; i<Corner.DRB; i++)
310
      ret = (short) (3 * ret + co[i]);
311

  
312
    return ret;
313
    }
314

  
315
  // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
316
  void setTwist(short twist)
317
    {
318
    int twistParity = 0;
319

  
320
    for ( int i=Corner.DRB-1; i>=Corner.URF; i--)
321
      {
322
      twistParity += co[i] = (byte) (twist % 3);
323
      twist /= 3;
324
      }
325
    co[Corner.DRB] = (byte) ((3 - twistParity % 3) % 3);
326
    }
327

  
328
  // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
329
  // return the flip of the 12 edges. 0<= flip < 2^11
330
  short getFlip()
331
    {
332
    short ret = 0;
333

  
334
    for ( int i=Edge.UR; i<Edge.BR; i++)
335
      ret = (short) (2 * ret + eo[i]);
336

  
337
    return ret;
338
    }
339

  
340
  // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
341
  void setFlip(short flip)
342
    {
343
    int flipParity = 0;
344

  
345
    for (int i=Edge.BR-1; i>=Edge.UR; i--)
346
      {
347
      flipParity += eo[i] = (byte) (flip % 2);
348
      flip /= 2;
349
      }
350
    eo[Edge.BR] = (byte) ((2 - flipParity % 2) % 2);
351
    }
352

  
353
  // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
354
  // Parity of the corner permutation
355
  short cornerParity()
356
    {
357
    int s = 0;
358

  
359
    for (int i=Corner.DRB; i>=Corner.URF+1; i--)
360
      for (int j = i - 1; j >= Corner.URF; j--)
361
        if (cp[j] > cp[i]) s++;
362

  
363
    return (short) (s % 2);
364
    }
365

  
366
  // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
367
  // Parity of the edges permutation. Parity of corners and edges are the same if the cube is solvable.
368
  short edgeParity()
369
    {
370
    int s = 0;
371

  
372
    for (int i = Edge.BR; i >= Edge.UR+1; i--)
373
      for (int j = i - 1; j >= Edge.UR; j--)
374
        if (ep[j] > ep[i]) s++;
375

  
376
    return (short) (s % 2);
377
    }
378

  
379
  // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
380
  // permutation of the UD-slice edges FR,FL,BL and BR
381
  short getFRtoBR()
382
    {
383
    int a = 0, x = 0;
384

  
385
    // compute the index a < (12 choose 4) and the permutation array perm.
386
    for (int j = Edge.BR; j >= Edge.UR; j--)
387
      if (Edge.FR <= ep[j] && ep[j] <= Edge.BR)
388
        {
389
        a += Cnk(11 - j, x + 1);
390
	tmpEdge4[3 - x++] = ep[j];
391
	}
392

  
393
    int b = 0;
394
    for (int j = 3; j > 0; j--)// compute the index b < 4! for the permutation in perm
395
      {
396
      int k = 0;
397
      while (tmpEdge4[j] != j + 8)
398
        {
399
	rotateLeft(tmpEdge4, 0, j);
400
	k++;
401
        }
402
      b = (j + 1) * b + k;
403
      }
404

  
405
    return (short) (24 * a + b);
406
    }
407

  
408
  // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
409
  void setFRtoBR(short idx)
410
    {
411
    int x;
412
    int[] sliceEdge = { Edge.FR, Edge.FL, Edge.BL, Edge.BR };
413
    int[] otherEdge = { Edge.UR, Edge.UF, Edge.UL, Edge.UB, Edge.DR, Edge.DF, Edge.DL, Edge.DB };
414
    int b = idx % 24; // Permutation
415
    int a = idx / 24; // Combination
416

  
417
    for ( int e=Edge.UR; e<=Edge.BR; e++) ep[e] = Edge.DB;// Use UR to invalidate all edges
418

  
419
    for (int j = 1, k; j < 4; j++)// generate permutation from index b
420
      {
421
      k = b % (j + 1);
422
      b /= j + 1;
423
      while (k-- > 0) rotateRight(sliceEdge, 0, j);
424
      }
425

  
426
    x = 3;// generate combination and set slice edges
427

  
428
    for (int j = Edge.UR; j <= Edge.BR; j++)
429
      if (a - Cnk(11 - j, x + 1) >= 0)
430
        {
431
	ep[j] = sliceEdge[3 - x];
432
	a -= Cnk(11 - j, x-- + 1);
433
	}
434

  
435
    x = 0; // set the remaining edges UR..DB
436

  
437
    for (int j = Edge.UR; j <= Edge.BR; j++)
438
      if (ep[j] == Edge.DB)
439
	ep[j] = otherEdge[x++];
440

  
441
    }
442

  
443
  // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
444
  // Permutation of all corners except DBL and DRB
445
  short getURFtoDLF()
446
    {
447
    int a = 0, x = 0;
448

  
449
    // compute the index a < (8 choose 6) and the corner permutation.
450
    for (int j = Corner.URF; j <= Corner.DRB; j++)
451
      if (cp[j] <= Corner.DLF)
452
        {
453
	a += Cnk(j, x + 1);
454
	tmpCorner6[x++] = cp[j];
455
	}
456

  
457
    int b = 0;
458

  
459
    for (int j = 5; j > 0; j--)// compute the index b < 6! for the permutation in corner6
460
      {
461
      int k = 0;
462

  
463
      while (tmpCorner6[j] != j)
464
        {
465
	rotateLeft(tmpCorner6, 0, j);
466
	k++;
467
	}
468
      b = (j + 1) * b + k;
469
      }
470

  
471
    return (short) (720 * a + b);
472
    }
473

  
474
  // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
475
  void setURFtoDLF(short idx)
476
    {
477
    int x;
478

  
479
    int[] corner6 = { Corner.URF, Corner.UFL, Corner.ULB, Corner.UBR, Corner.DFR, Corner.DLF };
480
    int[] otherCorner = { Corner.DBL, Corner.DRB };
481
    int b = idx % 720; // Permutation
482
    int a = idx / 720; // Combination
483

  
484
    for ( int c=Corner.URF; c<=Corner.DRB; c++) cp[c] = Corner.DRB;// Use DRB to invalidate all corners
485

  
486
    for (int j = 1, k; j < 6; j++)// generate permutation from index b
487
      {
488
      k = b % (j + 1);
489
      b /= j + 1;
490
      while (k-- > 0) rotateRight(corner6, 0, j);
491
      }
492

  
493
    x = 5;// generate combination and set corners
494

  
495
    for (int j = Corner.DRB; j >= 0; j--)
496
      if (a - Cnk(j, x + 1) >= 0)
497
        {
498
	cp[j] = corner6[x];
499
	a -= Cnk(j, x-- + 1);
500
	}
501

  
502
    x = 0;
503

  
504
    for (int j = Corner.URF; j <= Corner.DRB; j++)
505
      if (cp[j] == Corner.DRB)
506
	cp[j] = otherCorner[x++];
507
    }
508

  
509
  // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
510
  // Permutation of the six edges UR,UF,UL,UB,DR,DF.
511
  int getURtoDF()
512
    {
513
    int a = 0, x = 0;
514
    // compute the index a < (12 choose 6) and the edge permutation.
515

  
516
    for (int j = Edge.UR; j <= Edge.BR; j++)
517
      if (ep[j] <= Edge.DF)
518
        {
519
	a += Cnk(j, x + 1);
520
	tmpEdge6[x++] = ep[j];
521
	}
522

  
523
    int b = 0;
524

  
525
    for (int j = 5; j > 0; j--)// compute the index b < 6! for the permutation in edge6
526
      {
527
      int k = 0;
528

  
529
      while (tmpEdge6[j] != j)
530
        {
531
	rotateLeft(tmpEdge6, 0, j);
532
	k++;
533
	}
534
      b = (j + 1) * b + k;
535
      }
536
    return 720 * a + b;
537
    }
538

  
539
  // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
540
  void setURtoDF(int idx)
541
    {
542
    int x;
543
    int[] edge6 = { Edge.UR, Edge.UF, Edge.UL, Edge.UB, Edge.DR, Edge.DF };
544
    int[] otherEdge = { Edge.DL, Edge.DB, Edge.FR, Edge.FL, Edge.BL, Edge.BR };
545
    int b = idx % 720; // Permutation
546
    int a = idx / 720; // Combination
547

  
548
    for ( int e=Edge.UR; e<=Edge.BR; e++) ep[e] = Edge.BR;// Use BR to invalidate all edges
549

  
550
    for (int j = 1, k; j < 6; j++)// generate permutation from index b
551
      {
552
      k = b % (j + 1);
553
      b /= j + 1;
554
      while (k-- > 0) rotateRight(edge6, 0, j);
555
      }
556

  
557
    x = 5;// generate combination and set edges
558

  
559
    for (int j = Edge.BR; j >= 0; j--)
560
      if (a - Cnk(j, x + 1) >= 0)
561
        {
562
	ep[j] = edge6[x];
563
	a -= Cnk(j, x-- + 1);
564
	}
565

  
566
    x = 0; // set the remaining edges DL..BR
567

  
568
    for (int j = Edge.UR; j <= Edge.BR; j++)
569
      if (ep[j] == Edge.BR)
570
        ep[j] = otherEdge[x++];
571
    }
572

  
573
  // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
574
  // Permutation of the six edges UR,UF,UL,UB,DR,DF
575
  public static int getURtoDF(short idx1, short idx2)
576
    {
577
    CubieCube a = new CubieCube();
578
    CubieCube b = new CubieCube();
579
    a.setURtoUL(idx1);
580
    b.setUBtoDF(idx2);
581

  
582
    for (int i = 0; i < 8; i++)
583
      {
584
      if (a.ep[i] != Edge.BR)
585
        if (b.ep[i] != Edge.BR)// collision
586
          return -1;
587
	else
588
          b.ep[i] = a.ep[i];
589
      }
590

  
591
    return b.getURtoDF();
592
    }
593

  
594
  // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
595
  // Permutation of the three edges UR,UF,UL
596
  short getURtoUL()
597
    {
598
    int a = 0, x = 0;
599
    // compute the index a < (12 choose 3) and the edge permutation.
600
    for (int j = Edge.UR; j <= Edge.BR; j++)
601
      if (ep[j] <= Edge.UL)
602
        {
603
	a += Cnk(j, x + 1);
604
	tmpEdge3[x++] = ep[j];
605
	}
606

  
607
    int b = 0;
608

  
609
    for (int j = 2; j > 0; j--)// compute the index b < 3! for the permutation in edge3
610
      {
611
      int k = 0;
612
      while (tmpEdge3[j] != j)
613
        {
614
	rotateLeft(tmpEdge3, 0, j);
615
	k++;
616
	}
617
      b = (j + 1) * b + k;
618
      }
619
	
620
    return (short) (6 * a + b);
621
    }
622

  
623
  // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
624
  void setURtoUL(short idx)
625
    {
626
    int x;
627
    int[] edge3 = { Edge.UR, Edge.UF, Edge.UL };
628
    int b = idx % 6; // Permutation
629
    int a = idx / 6; // Combination
630

  
631
    for (int e = Edge.UR; e <= Edge.BR; e++) ep[e] = Edge.BR;// Use BR to invalidate all edges
632

  
633
    for (int j = 1, k; j < 3; j++)// generate permutation from index b
634
      {
635
      k = b % (j + 1);
636
      b /= j + 1;
637

  
638
      while (k-- > 0) rotateRight(edge3, 0, j);
639
      }
640

  
641
    x = 2;// generate combination and set edges
642

  
643
    for (int j = Edge.BR; j >= 0; j--)
644
      if (a - Cnk(j, x + 1) >= 0)
645
        {
646
	ep[j] = edge3[x];
647
	a -= Cnk(j, x-- + 1);
648
	}
649
    }
650

  
651
  // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
652
  // Permutation of the three edges UB,DR,DF
653
  short getUBtoDF()
654
    {
655
    int a = 0, x = 0;
656
    // compute the index a < (12 choose 3) and the edge permutation.
657

  
658
    for (int j = Edge.UR; j <= Edge.BR; j++)
659
      if (Edge.UB <= ep[j] && ep[j] <= Edge.DF)
660
        {
661
	a += Cnk(j, x + 1);
662
	tmpEdge3[x++] = ep[j];
663
	}
664

  
665
    int b = 0;
666

  
667
    for (int j = 2; j > 0; j--)// compute the index b < 3! for the permutation in edge3
668
      {
669
      int k = 0;
670

  
671
      while (tmpEdge3[j] != Edge.UB + j)
672
        {
673
	rotateLeft(tmpEdge3, 0, j);
674
	k++;
675
	}
676
      b = (j + 1) * b + k;
677
      }
678

  
679
    return (short) (6 * a + b);
680
    }
681

  
682
  // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
683
  void setUBtoDF(short idx)
684
    {
685
    int x;
686
    int[] edge3 = { Edge.UB, Edge.DR, Edge.DF };
687
    int b = idx % 6; // Permutation
688
    int a = idx / 6; // Combination
689

  
690
    for (int e = Edge.UR; e <= Edge.BR; e++) ep[e] = Edge.BR;// Use BR to invalidate all edges
691

  
692
    for (int j = 1, k; j < 3; j++)// generate permutation from index b
693
      {
694
      k = b % (j + 1);
695
      b /= j + 1;
696

  
697
      while (k-- > 0) rotateRight(edge3, 0, j);
698
      }
699

  
700
    x = 2;// generate combination and set edges
701

  
702
    for (int j = Edge.BR; j >= 0; j--)
703
      if (a - Cnk(j, x + 1) >= 0)
704
        {
705
	ep[j] = edge3[x];
706
	a -= Cnk(j, x-- + 1);
707
	}
708
    }
709

  
710
  // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
711
  int getURFtoDLB()
712
    {
713
    int b = 0;
714

  
715
    for (int i = 0; i < 8; i++) tmpCorner8[i] = cp[i];
716

  
717
    for (int j = 7; j > 0; j--)// compute the index b < 8! for the permutation in perm
718
      {
719
      int k = 0;
720
      while (tmpCorner8[j] != j)
721
        {
722
	rotateLeft(tmpCorner8, 0, j);
723
	k++;
724
	}
725
      b = (j + 1) * b + k;
726
      }
727

  
728
    return b;
729
    }
730

  
731
  // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
732
  void setURFtoDLB(int idx)
733
    {
734
    int[] perm = { Corner.URF, Corner.UFL, Corner.ULB, Corner.UBR, Corner.DFR, Corner.DLF, Corner.DBL, Corner.DRB };
735
    int k;
736

  
737
    for (int j = 1; j < 8; j++)
738
      {
739
      k = idx % (j + 1);
740
      idx /= j + 1;
741
      while (k-- > 0) rotateRight(perm, 0, j);
742
      }
743

  
744
    int x = 7;// set corners
745

  
746
    for (int j = 7; j >= 0; j--) cp[j] = perm[x--];
747
    }
748

  
749
  // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
750
  int getURtoBR()
751
    {
752
    int b = 0;
753

  
754
    for (int i = 0; i < 12; i++) tmpEdge12[i] = ep[i];
755

  
756
    for (int j = 11; j > 0; j--)// compute the index b < 12! for the permutation in perm
757
      {
758
      int k = 0;
759
      
760
      while (tmpEdge12[j] != j)
761
        {
762
 	rotateLeft(tmpEdge12, 0, j);
763
	k++;
764
	}
765
      b = (j + 1) * b + k;
766
      }
767

  
768
    return b;
769
    }
770

  
771
  // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
772
  void setURtoBR(int idx)
773
    {
774
    int[] perm = { Edge.UR, Edge.UF, Edge.UL, Edge.UB, Edge.DR, Edge.DF, Edge.DL, Edge.DB, Edge.FR, Edge.FL, Edge.BL, Edge.BR };
775
    int k;
776

  
777
    for (int j = 1; j < 12; j++)
778
      {
779
      k = idx % (j + 1);
780
      idx /= j + 1;
781

  
782
      while (k-- > 0) rotateRight(perm, 0, j);
783
      }
784

  
785
    int x = 11;// set edges
786

  
787
    for (int j = 11; j >= 0; j--) ep[j] = perm[x--];
788
    }
789

  
790
  // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
791
  // Check a cubiecube for solvability. Return the error code.
792
  // 0: Cube is solvable
793
  // -2: Not all 12 edges exist exactly once
794
  // -3: Flip error: One edge has to be flipped
795
  // -4: Not all corners exist exactly once
796
  // -5: Twist error: One corner has to be twisted
797
  // -6: Parity error: Two corners ore two edges have to be exchanged
798
  int verify()
799
    {
800
    int sum = 0;
801
    int[] edgeCount = new int[12];
802

  
803
    for (int e = Edge.UR; e <= Edge.BR; e++) edgeCount[ep[e]]++;
804

  
805
    for (int i = 0; i < 12; i++)
806
      if (edgeCount[i] != 1)
807
	return -2;
808

  
809
    for (int i = 0; i < 12; i++)
810
      sum += eo[i];
811

  
812
    if (sum % 2 != 0)
813
      return -3;
814

  
815
    int[] cornerCount = new int[8];
816

  
817
    for ( int c=Corner.URF; c<=Corner.DRB; c++) cornerCount[cp[c]]++;
818

  
819
    for (int i = 0; i < 8; i++)
820
      if (cornerCount[i] != 1)
821
        return -4;// missing corners
822

  
823
    sum = 0;
824

  
825
    for (int i = 0; i < 8; i++)
826
      sum += co[i];
827

  
828
    if (sum % 3 != 0)
829
      return -5;// twisted corner
830

  
831
    if ((edgeParity() ^ cornerParity()) != 0)
832
      return -6;// parity error
833

  
834
    return 0;// cube ok
835
    }
836
}
src/main/java/org/distorted/solvers/cube3/Edge.java
1
package org.distorted.solvers.cube3;
2

  
3
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
4
//Then names of the edge positions of the cube. Edge UR e.g., has an U(p) and R(ight) facelet.
5

  
6
class Edge
7
  {
8
  public static final int UR=0;
9
  public static final int UF=1;
10
  public static final int UL=2;
11
  public static final int UB=3;
12
  public static final int DR=4;
13
  public static final int DF=5;
14
  public static final int DL=6;
15
  public static final int DB=7;
16
  public static final int FR=8;
17
  public static final int FL=9;
18
  public static final int BL=10;
19
  public static final int BR=11;
... This diff was truncated because it exceeds the maximum size that can be displayed.

Also available in: Unified diff