Project

General

Profile

Download (22.1 KB) Statistics
| Branch: | Tag: | Revision:

magiccube / src / main / java / org / distorted / solvers / cube3 / CoordCube.java @ b95ceafc

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]==true ) return;
82
		
83
		CubieCube a = new CubieCube();
84
		for (short i = 0; i < N_TWIST; i++) {
85
			a.setTwist(i);
86
			for (int j = 0; j < 6; j++) {
87
				for (int k = 0; k < 3; k++) {
88
					a.cornerMultiply(CubieCube.moveCube[j]);
89
					twistMove[i][3 * j + k] = a.getTwist();
90
				}
91
				a.cornerMultiply(CubieCube.moveCube[j]);// 4. faceturn restores
92
				// a
93
			}
94
		}
95
		
96
		init[0]=true;
97
		*/
98
		if( init[0]==false )
99
		  {
100
          try
101
		    {
102
        	InputStream is = res.openRawResource(com.threedcell.rubik.R.raw.table1); 
103
		    is.read( twistMove, 0, 2*N_TWIST*N_MOVE);
104
		    }
105
		  catch(Exception ioe)
106
		    {
107
		    System.out.println("error reading table1");
108
                    return false;
109
		    }
110
		
111
		  init[0]=true;
112
		  }
113

    
114
                return true;
115
	}
116

    
117
	public static short getTwistMove(int a,int b)
118
	{
119
		short upperS = twistMove[2*(a*N_MOVE+b)];
120
		short lowerS = twistMove[2*(a*N_MOVE+b)+1];
121
		
122
		if( upperS<0 ) upperS+=256;
123
		if( lowerS<0 ) lowerS+=256;
124
		
125
		return  (short)( (upperS<<8) + lowerS );
126
	}
127
	
128
	// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
129
	// Move table for the flips of the edges
130
	// flip < 2048 in phase 1
131
	// flip = 0 in phase 2.
132
	private static byte[] flipMove = new byte[2*N_FLIP*N_MOVE];
133
	
134
	public static boolean initialize2(Resources res)
135
	{/*
136
		if( init[1]==true ) return;
137
	
138
		CubieCube a = new CubieCube();
139
		for (short i = 0; i < N_FLIP; i++) {
140
			a.setFlip(i);
141
			for (int j = 0; j < 6; j++) {
142
				for (int k = 0; k < 3; k++) {
143
					a.edgeMultiply(CubieCube.moveCube[j]);
144
					flipMove[i][3 * j + k] = a.getFlip();
145
				}
146
				a.edgeMultiply(CubieCube.moveCube[j]);
147
				// a
148
			}
149
		}
150
		
151
		init[1]=true;
152
		*/
153
		if( init[1]==false )
154
		  {
155
		  try
156
		    {
157
			InputStream is = res.openRawResource(com.threedcell.rubik.R.raw.table2); 
158
		    is.read( flipMove, 0, 2*N_FLIP*N_MOVE);
159
		    }
160
		  catch(Exception ioe)
161
		    {
162
		    System.out.println("error reading table2");
163
                    return false;
164
		    }
165
		
166
		  init[1]=true;
167
		  }
168

    
169
                return true;
170
	}
171
	
172
	public static short getFlipMove(int a,int b)
173
	{
174
		short upperS = flipMove[2*(a*N_MOVE+b)];
175
		short lowerS = flipMove[2*(a*N_MOVE+b)+1];
176
		
177
		if( upperS<0 ) upperS+=256;
178
		if( lowerS<0 ) lowerS+=256;
179
		
180
		return  (short)( (upperS<<8) + lowerS );
181
	}
182
	
183
	// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
184
	// Parity of the corner permutation. This is the same as the parity for the edge permutation of a valid cube.
185
	// parity has values 0 and 1
186
	static short[][] parityMove = { { 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1 },
187
			{ 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0 } };
188

    
189
	// ***********************************Phase 1 and 2 movetable********************************************************
190

    
191
	// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
192
	// Move table for the four UD-slice edges FR, FL, Bl and BR
193
	// FRtoBRMove < 11880 in phase 1
194
	// FRtoBRMove < 24 in phase 2
195
	// FRtoBRMove = 0 for solved cube
196
	private static byte[] FRtoBR_Move = new byte[2*N_FRtoBR*N_MOVE];
197
	
198
	public static boolean initialize3(Resources res)
199
	{/*
200
		if( init[2]==true ) return;
201
		
202
		CubieCube a = new CubieCube();
203
		for (short i = 0; i < N_FRtoBR; i++) {
204
			a.setFRtoBR(i);
205
			for (int j = 0; j < 6; j++) {
206
				for (int k = 0; k < 3; k++) {
207
					a.edgeMultiply(CubieCube.moveCube[j]);
208
					FRtoBR_Move[i][3 * j + k] = a.getFRtoBR();
209
				}
210
				a.edgeMultiply(CubieCube.moveCube[j]);
211
			}
212
		}
213
		
214
		init[2]=true;
215
		*/
216
		
217
		if( init[2]==false )
218
		  {
219
		  try
220
		    {
221
			InputStream is = res.openRawResource(com.threedcell.rubik.R.raw.table3); 
222
		    is.read( FRtoBR_Move, 0, 2*N_FRtoBR*N_MOVE);
223
		    }
224
		  catch(Exception ioe)
225
		    {
226
		    System.out.println("error reading table3");
227
                    return true;
228
		    }
229
		
230
		  init[2]=true;
231
		  }
232

    
233
                return false;
234
	}
235

    
236
	public static short getFRtoBR_Move(int a,int b)
237
	{
238
		short upperS = FRtoBR_Move[2*(a*N_MOVE+b)];
239
		short lowerS = FRtoBR_Move[2*(a*N_MOVE+b)+1];
240
		
241
		if( upperS<0 ) upperS+=256;
242
		if( lowerS<0 ) lowerS+=256;
243
		
244
		return  (short)( (upperS<<8) + lowerS );
245
	}
246
	
247
	// *******************************************Phase 1 and 2 movetable************************************************
248

    
249
	// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
250
	// Move table for permutation of six corners. The positions of the DBL and DRB corners are determined by the parity.
251
	// URFtoDLF < 20160 in phase 1
252
	// URFtoDLF < 20160 in phase 2
253
	// URFtoDLF = 0 for solved cube.
254
	private static byte[] URFtoDLF_Move = new byte[2*N_URFtoDLF*N_MOVE];
255
	
256
	public static boolean initialize4(Resources res)
257
	{/*
258
		if( init[3]==true ) return;
259
	
260
		CubieCube a = new CubieCube();
261
		for (short i = 0; i < N_URFtoDLF; i++) {
262
			a.setURFtoDLF(i);
263
			for (int j = 0; j < 6; j++) {
264
				for (int k = 0; k < 3; k++) {
265
					a.cornerMultiply(CubieCube.moveCube[j]);
266
					URFtoDLF_Move[i][3 * j + k] = a.getURFtoDLF();
267
				}
268
				a.cornerMultiply(CubieCube.moveCube[j]);
269
			}
270
		}
271
		
272
		init[3]=true;
273
		*/
274
		if( init[3]==false )
275
		  {
276
		  try
277
		    {
278
			InputStream is = res.openRawResource(com.threedcell.rubik.R.raw.table4); 
279
		    is.read( URFtoDLF_Move, 0, 2*N_URFtoDLF*N_MOVE);
280
		    }
281
		  catch(Exception ioe)
282
		    {
283
		    System.out.println("error reading table4");
284
                    return false;
285
		    }
286
		
287
		  init[3]=true;
288
		  }
289

    
290
                return true;
291
	}
292
	
293
	public static short getURFtoDLF_Move(int a,int b)
294
	{
295
		short upperS = URFtoDLF_Move[2*(a*N_MOVE+b)];
296
		short lowerS = URFtoDLF_Move[2*(a*N_MOVE+b)+1];
297
		
298
		if( upperS<0 ) upperS+=256;
299
		if( lowerS<0 ) lowerS+=256;
300
		
301
		return  (short)( (upperS<<8) + lowerS );
302
	}
303
	// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
304
	// Move table for the permutation of six U-face and D-face edges in phase2. The positions of the DL and DB edges are
305
	// determined by the parity.
306
	// URtoDF < 665280 in phase 1
307
	// URtoDF < 20160 in phase 2
308
	// URtoDF = 0 for solved cube.
309
	private static byte[] URtoDF_Move = new byte[2*N_URtoDF*N_MOVE];
310
	
311
	public static boolean initialize5(Resources res)
312
	{/*
313
		if( init[4]==true ) return;
314
		
315
		CubieCube a = new CubieCube();
316
		for (short i = 0; i < N_URtoDF; i++) {
317
			a.setURtoDF(i);
318
			for (int j = 0; j < 6; j++) {
319
				for (int k = 0; k < 3; k++) {
320
					a.edgeMultiply(CubieCube.moveCube[j]);
321
					URtoDF_Move[i][3 * j + k] = (short) a.getURtoDF();
322
					// Table values are only valid for phase 2 moves!
323
					// For phase 1 moves, casting to short is not possible.
324
				}
325
				a.edgeMultiply(CubieCube.moveCube[j]);
326
			}
327
		}
328
		
329
		init[4]=true;
330
		*/
331
		if( init[4]==false )
332
		  {
333
		  try
334
		    {
335
			InputStream is = res.openRawResource(com.threedcell.rubik.R.raw.table5); 
336
		    is.read( URtoDF_Move, 0, 2*N_URtoDF*N_MOVE);
337
		    }
338
		  catch(Exception ioe)
339
		    {
340
		    System.out.println("error reading table5");
341
                    return false;
342
		    }
343
		
344
		  init[4]=true;
345
		  }
346

    
347
                return true;
348
	}
349
	
350
	public static short getURtoDF_Move(int a,int b)
351
	{
352
		short upperS = URtoDF_Move[2*(a*N_MOVE+b)];
353
		short lowerS = URtoDF_Move[2*(a*N_MOVE+b)+1];
354
		
355
		if( upperS<0 ) upperS+=256;
356
		if( lowerS<0 ) lowerS+=256;
357
		
358
		return  (short)( (upperS<<8) + lowerS );
359
	}
360
	// **************************helper move tables to compute URtoDF for the beginning of phase2************************
361

    
362
	// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
363
	// Move table for the three edges UR,UF and UL in phase1.
364
	private static byte[] URtoUL_Move = new byte[2*N_URtoUL*N_MOVE];
365
	
366
	public static boolean initialize6(Resources res)
367
	{/*
368
		if( init[5]==true ) return;
369
		
370
		CubieCube a = new CubieCube();
371
		for (short i = 0; i < N_URtoUL; i++) {
372
			a.setURtoUL(i);
373
			for (int j = 0; j < 6; j++) {
374
				for (int k = 0; k < 3; k++) {
375
					a.edgeMultiply(CubieCube.moveCube[j]);
376
					URtoUL_Move[i][3 * j + k] = a.getURtoUL();
377
				}
378
				a.edgeMultiply(CubieCube.moveCube[j]);
379
			}
380
		}
381
		
382
		init[5]=true;
383
		*/
384
		if( init[5]==false )
385
		  {
386
		  try
387
		    {
388
			InputStream is = res.openRawResource(com.threedcell.rubik.R.raw.table6); 
389
		    is.read( URtoUL_Move, 0, 2*N_URtoUL*N_MOVE);
390
		    }
391
		  catch(Exception ioe)
392
		    {
393
		    System.out.println("error reading table6");
394
                    return false;
395
		    }
396
		
397
		  init[5]=true;
398
		  }
399

    
400
                return true;
401
	}
402

    
403
	public static short getURtoUL_Move(int a,int b)
404
	{
405
		short upperS = URtoUL_Move[2*(a*N_MOVE+b)];
406
		short lowerS = URtoUL_Move[2*(a*N_MOVE+b)+1];
407
		
408
		if( upperS<0 ) upperS+=256;
409
		if( lowerS<0 ) lowerS+=256;
410
		
411
		return  (short)( (upperS<<8) + lowerS );
412
	}
413
	
414
	// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
415
	// Move table for the three edges UB,DR and DF in phase1.
416
	private static byte[] UBtoDF_Move = new byte[2*N_UBtoDF*N_MOVE];
417
	
418
	public static boolean initialize7(Resources res)
419
	{/*
420
		if( init[6]==true ) return;
421
		
422
		CubieCube a = new CubieCube();
423
		for (short i = 0; i < N_UBtoDF; i++) {
424
			a.setUBtoDF(i);
425
			for (int j = 0; j < 6; j++) {
426
				for (int k = 0; k < 3; k++) {
427
					a.edgeMultiply(CubieCube.moveCube[j]);
428
					UBtoDF_Move[i][3 * j + k] = a.getUBtoDF();
429
				}
430
				a.edgeMultiply(CubieCube.moveCube[j]);
431
			}
432
		}
433
		
434
		init[6]=true;
435
		*/
436
		if( init[6]==false )
437
		  {
438
		  try
439
		    {
440
			InputStream is = res.openRawResource(com.threedcell.rubik.R.raw.table7); 
441
		    is.read( UBtoDF_Move, 0, 2*N_UBtoDF*N_MOVE);
442
		    }
443
		  catch(Exception ioe)
444
		    {
445
		    System.out.println("error reading table7");
446
                    return false;
447
		    }
448
		
449
		  init[6]=true;
450
		  }
451

    
452
                return true;
453
	}
454
	
455
	public static short getUBtoDF_Move(int a,int b)
456
	{
457
		short upperS = UBtoDF_Move[2*(a*N_MOVE+b)];
458
		short lowerS = UBtoDF_Move[2*(a*N_MOVE+b)+1];
459
		
460
		if( upperS<0 ) upperS+=256;
461
		if( lowerS<0 ) lowerS+=256;
462
		
463
		return  (short)( (upperS<<8) + lowerS );
464
	}
465
	
466
	// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
467
	// Table to merge the coordinates of the UR,UF,UL and UB,DR,DF edges at the beginning of phase2
468
	private static byte[] MergeURtoULandUBtoDF = new byte[2*336*336];
469
	
470
	public static boolean initialize8(Resources res)
471
	{/*
472
		if( init[7]==true ) return;
473
		
474
		// for i, j <336 the six edges UR,UF,UL,UB,DR,DF are not in the
475
		// UD-slice and the index is <20160
476
		for (short uRtoUL = 0; uRtoUL < 336; uRtoUL++) {
477
			for (short uBtoDF = 0; uBtoDF < 336; uBtoDF++) {
478
				MergeURtoULandUBtoDF[uRtoUL][uBtoDF] = (short) CubieCube.getURtoDF(uRtoUL, uBtoDF);
479
			}
480
		}
481
		
482
		init[7]=true;
483
		*/
484
		if( init[7]==false )
485
		  {
486
		  try
487
		    {
488
			InputStream is = res.openRawResource(com.threedcell.rubik.R.raw.table8); 
489
		    is.read( MergeURtoULandUBtoDF, 0, 2*336*336);
490
		    }
491
		  catch(Exception ioe)
492
		    {
493
		    System.out.println("error reading table8");
494
                    return false;
495
		    }
496
		
497
		  init[7]=true;
498
		  }
499

    
500
                return true;
501
	}
502
	
503
	public static short getMergeURtoULandUBtoDF(int a,int b)
504
	{
505
		short upperS = MergeURtoULandUBtoDF[2*(a*336+b)];
506
		short lowerS = MergeURtoULandUBtoDF[2*(a*336+b)+1];
507
		
508
		if( upperS<0 ) upperS+=256;
509
		if( lowerS<0 ) lowerS+=256;
510
		
511
		return  (short)( (upperS<<8) + lowerS );
512
	}
513
	// ****************************************Pruning tables for the search*********************************************
514

    
515
	// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
516
	// Pruning table for the permutation of the corners and the UD-slice edges in phase2.
517
	// The pruning table entries give a lower estimation for the number of moves to reach the solved cube.
518
	public static byte[] Slice_URFtoDLF_Parity_Prun = new byte[N_SLICE2 * N_URFtoDLF * N_PARITY / 2];
519
	
520
	public static boolean initialize9(Resources res)
521
	{
522
		
523
		/*
524
		for (int i = 0; i < N_SLICE2 * N_URFtoDLF * N_PARITY / 2; i++)
525
			Slice_URFtoDLF_Parity_Prun[i] = -1;
526
		int depth = 0;
527
		setPruning(Slice_URFtoDLF_Parity_Prun, 0, (byte) 0);
528
		int done = 1;
529
		while (done != N_SLICE2 * N_URFtoDLF * N_PARITY) {
530
			for (int i = 0; i < N_SLICE2 * N_URFtoDLF * N_PARITY; i++) {
531
				int parity = i % 2;
532
				int URFtoDLF = (i / 2) / N_SLICE2;
533
				int slice = (i / 2) % N_SLICE2;
534
				if (getPruning(Slice_URFtoDLF_Parity_Prun, i) == depth) {
535
					for (int j = 0; j < 18; j++) {
536
						switch (j) {
537
						case 3:
538
						case 5:
539
						case 6:
540
						case 8:
541
						case 12:
542
						case 14:
543
						case 15:
544
						case 17:
545
							continue;
546
						default:
547
							int newSlice = FRtoBR_Move[slice][j];
548
							int newURFtoDLF = URFtoDLF_Move[URFtoDLF][j];
549
							int newParity = parityMove[parity][j];
550
							if (getPruning(Slice_URFtoDLF_Parity_Prun, (N_SLICE2 * newURFtoDLF + newSlice) * 2 + newParity) == 0x0f) {
551
								setPruning(Slice_URFtoDLF_Parity_Prun, (N_SLICE2 * newURFtoDLF + newSlice) * 2 + newParity,
552
										(byte) (depth + 1));
553
								done++;
554
							}
555
						}
556
					}
557
				}
558
			}
559
			depth++;
560
		}
561
		*/
562
		
563
		if( init[8]==false )
564
		  {
565
		  try
566
		    {
567
			InputStream is = res.openRawResource(com.threedcell.rubik.R.raw.table9); 
568
		    is.read( Slice_URFtoDLF_Parity_Prun, 0, N_SLICE2 * N_URFtoDLF * N_PARITY / 2);
569
		    }
570
		  catch(Exception ioe)
571
		    {
572
		    System.out.println("error reading table9");
573
                    return false;
574
		    }
575
		
576
		  init[8]=true;
577
		  }
578

    
579
                return true;
580
	}
581

    
582
	// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
583
	// Pruning table for the permutation of the edges in phase2.
584
	// The pruning table entries give a lower estimation for the number of moves to reach the solved cube.
585
	public static byte[] Slice_URtoDF_Parity_Prun = new byte[N_SLICE2 * N_URtoDF * N_PARITY / 2];
586
	
587
	public static boolean initialize10(Resources res)
588
	{/*
589
		if( init[9]==true ) return;
590
		
591
		for (int i = 0; i < N_SLICE2 * N_URtoDF * N_PARITY / 2; i++)
592
			Slice_URtoDF_Parity_Prun[i] = -1;
593
		int depth = 0;
594
		setPruning(Slice_URtoDF_Parity_Prun, 0, (byte) 0);
595
		int done = 1;
596
		while (done != N_SLICE2 * N_URtoDF * N_PARITY) {
597
			for (int i = 0; i < N_SLICE2 * N_URtoDF * N_PARITY; i++) {
598
				int parity = i % 2;
599
				int URtoDF = (i / 2) / N_SLICE2;
600
				int slice = (i / 2) % N_SLICE2;
601
				if (getPruning(Slice_URtoDF_Parity_Prun, i) == depth) {
602
					for (int j = 0; j < 18; j++) {
603
						switch (j) {
604
						case 3:
605
						case 5:
606
						case 6:
607
						case 8:
608
						case 12:
609
						case 14:
610
						case 15:
611
						case 17:
612
							continue;
613
						default:
614
							int newSlice = FRtoBR_Move[slice][j];
615
							int newURtoDF = URtoDF_Move[URtoDF][j];
616
							int newParity = parityMove[parity][j];
617
							if (getPruning(Slice_URtoDF_Parity_Prun, (N_SLICE2 * newURtoDF + newSlice) * 2 + newParity) == 0x0f) {
618
								setPruning(Slice_URtoDF_Parity_Prun, (N_SLICE2 * newURtoDF + newSlice) * 2 + newParity,
619
										(byte) (depth + 1));
620
								done++;
621
							}
622
						}
623
					}
624
				}
625
			}
626
			depth++;
627
		}
628
		
629
		init[9]=true;
630
		*/
631
		
632
		if( init[9]==false )
633
		  {
634
		  try
635
		    {
636
			InputStream is = res.openRawResource(com.threedcell.rubik.R.raw.table10); 
637
		    is.read( Slice_URtoDF_Parity_Prun, 0, N_SLICE2 * N_URtoDF * N_PARITY / 2);
638
		    }
639
		  catch(Exception ioe)
640
		    {
641
		    System.out.println("error reading table10");
642
                    return false;
643
		    }
644
		
645
		  init[9]=true;
646
		  }
647

    
648
                return true;
649
	}
650

    
651
	// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
652
	// Pruning table for the twist of the corners and the position (not permutation) of the UD-slice edges in phase1
653
	// The pruning table entries give a lower estimation for the number of moves to reach the H-subgroup.
654
	public static byte[] Slice_Twist_Prun = new byte[N_SLICE1 * N_TWIST / 2 + 1];
655
	
656
	public static boolean initialize11(Resources res)
657
	{/*
658
		if( init[10]==true ) return;
659
		
660
		for (int i = 0; i < N_SLICE1 * N_TWIST / 2 + 1; i++)
661
			Slice_Twist_Prun[i] = -1;
662
		int depth = 0;
663
		setPruning(Slice_Twist_Prun, 0, (byte) 0);
664
		int done = 1;
665
		while (done != N_SLICE1 * N_TWIST) {
666
			for (int i = 0; i < N_SLICE1 * N_TWIST; i++) {
667
				int twist = i / N_SLICE1, slice = i % N_SLICE1;
668
				if (getPruning(Slice_Twist_Prun, i) == depth) {
669
					for (int j = 0; j < 18; j++) {
670
						int newSlice = FRtoBR_Move[slice * 24][j] / 24;
671
						int newTwist = twistMove[twist][j];
672
						if (getPruning(Slice_Twist_Prun, N_SLICE1 * newTwist + newSlice) == 0x0f) {
673
							setPruning(Slice_Twist_Prun, N_SLICE1 * newTwist + newSlice, (byte) (depth + 1));
674
							done++;
675
						}
676
					}
677
				}
678
			}
679
			depth++;
680
		}
681
		
682
		init[10]=true;
683
		*/
684
		if( init[10]==false )
685
		  {
686
		  try
687
		    {
688
			InputStream is = res.openRawResource(com.threedcell.rubik.R.raw.table11); 
689
		    is.read( Slice_Twist_Prun, 0, N_SLICE1 * N_TWIST / 2 + 1);
690
		    }
691
		  catch(Exception ioe)
692
		    {
693
		    System.out.println("error reading table11");
694
                    return false;
695
		    }
696
		
697
		  init[10]=true;
698
		  }
699

    
700
                return true;
701
	}
702

    
703
	// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
704
	// Pruning table for the flip of the edges and the position (not permutation) of the UD-slice edges in phase1
705
	// The pruning table entries give a lower estimation for the number of moves to reach the H-subgroup.
706
	public static byte[] Slice_Flip_Prun = new byte[N_SLICE1 * N_FLIP / 2];
707
	
708
	public static boolean initialize12(Resources res)
709
	{/*
710
		if( init[11]==true ) return;
711
		
712
		for (int i = 0; i < N_SLICE1 * N_FLIP / 2; i++)
713
			Slice_Flip_Prun[i] = -1;
714
		int depth = 0;
715
		setPruning(Slice_Flip_Prun, 0, (byte) 0);
716
		int done = 1;
717
		while (done != N_SLICE1 * N_FLIP) {
718
			for (int i = 0; i < N_SLICE1 * N_FLIP; i++) {
719
				int flip = i / N_SLICE1, slice = i % N_SLICE1;
720
				if (getPruning(Slice_Flip_Prun, i) == depth) {
721
					for (int j = 0; j < 18; j++) {
722
						int newSlice = FRtoBR_Move[slice * 24][j] / 24;
723
						int newFlip = flipMove[flip][j];
724
						if (getPruning(Slice_Flip_Prun, N_SLICE1 * newFlip + newSlice) == 0x0f) {
725
							setPruning(Slice_Flip_Prun, N_SLICE1 * newFlip + newSlice, (byte) (depth + 1));
726
							done++;
727
						}
728
					}
729
				}
730
			}
731
			depth++;
732
		}
733
		
734
		init[11]=true;
735
		*/
736
		if( init[11]==false )
737
		  {
738
		  try
739
		    {
740
			InputStream is = res.openRawResource(com.threedcell.rubik.R.raw.table12); 
741
		    is.read( Slice_Flip_Prun, 0, N_SLICE1 * N_FLIP / 2);
742
		    }
743
		  catch(Exception ioe)
744
		    {
745
		    System.out.println("error reading table12");
746
                    return false;
747
		    }
748
		
749
		  init[11]=true;
750
		  }
751

    
752
                return true;
753
	}
754

    
755
	// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
756
	// Set pruning value in table. Two values are stored in one byte.
757
	static void setPruning(byte[] table, int index, byte value) {
758
		if ((index & 1) == 0)
759
			table[index / 2] &= 0xf0 | value;
760
		else
761
			table[index / 2] &= 0x0f | (value << 4);
762
	}
763

    
764
	// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
765
	// Extract pruning value
766
	static byte getPruning(byte[] table, int index) {
767
		if ((index & 1) == 0)
768
			return (byte) (table[index / 2] & 0x0f);
769
		else
770
			return (byte) ((table[index / 2] & 0xf0) >>> 4);
771
	}
772
}
(2-2/9)