Project

General

Profile

« Previous | Next » 

Revision 3d022d6a

Added by Leszek Koltunski about 1 year ago

minor

View differences:

src/main/java/org/distorted/objectlib/helpers/OperatingSystemInterface.java
56 56
  void remove(String key);
57 57
  void putInt(String key, int value);
58 58
  int getInt(String key, int def);
59

  
60
  ///////////////////////////////////////////
61
  // STRINGS
62
  ///////////////////////////////////////////
63
  String getString(int id);
64
  String getString(int id, String s1);
65
  String getString(int id, String s1, String s2);
66
  String getString(int id, String s1, String s2, String s3);
59 67
  }
src/main/java/org/distorted/objectlib/kociemba/SolverColor.java
1
/*
2
 * Herbert Kociemba
3
 *
4
 * BSD-licensed. See https://opensource.org/licenses/BSD-3-Clause
5
 */
6

  
7
package org.distorted.objectlib.kociemba;
8

  
9
///////////////////////////////////////////////////////////////////////////////////////////////////
10
// Names the colors of the cube facelets
11

  
12
class SolverColor
13
  {
14
  public static final int U=0;
15
  public static final int R=1;
16
  public static final int F=2;
17
  public static final int D=3;
18
  public static final int L=4;
19
  public static final int B=5;
20

  
21
///////////////////////////////////////////////////////////////////////////////////////////////////
22

  
23
  public static String toString(int i)
24
    {
25
    switch(i)
26
      {
27
      case U: return "U";
28
      case R: return "R";
29
      case F: return "F";
30
      case D: return "D";
31
      case L: return "L";
32
      case B: return "B";
33
      default: return "?";
34
      }
35
    }
36

  
37
///////////////////////////////////////////////////////////////////////////////////////////////////
38

  
39
  public static int toInt(String s)
40
    {
41
	  switch(s.charAt(0))
42
      {
43
      case 'U': return U;
44
      case 'R': return R;
45
      case 'F': return F;
46
      case 'D': return D;
47
      case 'L': return L;
48
      case 'B': return B;
49
      default: return -1;
50
      }  
51
    }
52
  }
src/main/java/org/distorted/objectlib/kociemba/SolverCoordCube.java
1
/*
2
 * Herbert Kociemba
3
 *
4
 * BSD-licensed. See https://opensource.org/licenses/BSD-3-Clause
5
 */
6

  
7
package org.distorted.objectlib.kociemba;
8

  
9
import java.io.InputStream;
10

  
11
import org.distorted.objectlib.R;
12
import org.distorted.objectlib.helpers.OperatingSystemInterface;
13

  
14
///////////////////////////////////////////////////////////////////////////////////////////////////
15

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

  
30
	// All coordinates are 0 for a solved cube except for UBtoDF, which is 114
31
	short twist;
32
	short flip;
33
	short parity;
34
	short FRtoBR;
35
	short URFtoDLF;
36
	short URtoUL;
37
	short UBtoDF;
38
	int URtoDF;
39

  
40
	private static final boolean[] init = new boolean[12];
41
	
42
	static 
43
	  {
44
	  for(int i=0; i<12; i++ ) init[i] = false;	
45
	  }
46

  
47
  // Phase 1 move tables
48
  // Move table for the twists of the corners. twist < 2187 in phase 2; twist = 0 in phase 2.
49
	private static final byte[] twistMove = new byte[2*N_TWIST*N_MOVE];
50

  
51
	// Move table for the flips of the edges. flip < 2048 in phase 1; flip = 0 in phase 2.
52
	private static final byte[] flipMove  = new byte[2*N_FLIP*N_MOVE];
53

  
54
  // Parity of the corner permutation. This is the same as the parity for the edge permutation of a valid cube.
55
  // parity has values 0 and 1
56
	static short[][] parityMove = {
57
	                                { 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1 },
58
			                            { 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0 }
59
			                          };
60

  
61
  // Phase 1 and 2 movetable
62
  // Move table for the four UD-slice edges FR, FL, Bl and BR
63
  // FRtoBRMove < 11880 in phase 1; FRtoBRMove < 24 in phase 2; FRtoBRMove = 0 for solved cube
64
	private static final byte[] FRtoBR_Move = new byte[2*N_FRtoBR*N_MOVE];
65

  
66
	// Phase 1 and 2 movetable
67
	// Move table for permutation of six corners. The positions of the DBL and DRB corners are determined by the parity.
68
	// URFtoDLF < 20160 in phase 1; URFtoDLF < 20160 in phase 2; URFtoDLF = 0 for solved cube.
69
	private static final byte[] URFtoDLF_Move = new byte[2*N_URFtoDLF*N_MOVE];
70

  
71
	// Move table for the permutation of six U-face and D-face edges in phase2. The positions of the DL and DB edges are
72
	// determined by the parity.
73
	// URtoDF < 665280 in phase 1; URtoDF < 20160 in phase 2; URtoDF = 0 for solved cube.
74
	private static final byte[] URtoDF_Move = new byte[2*N_URtoDF*N_MOVE];
75

  
76
	// Helper move tables to compute URtoDF for the beginning of phase2
77
	// Move table for the three edges UR,UF and UL in phase1.
78
	private static final byte[] URtoUL_Move = new byte[2*N_URtoUL*N_MOVE];
79

  
80
	// Move table for the three edges UB,DR and DF in phase1.
81
	private static final byte[] UBtoDF_Move = new byte[2*N_UBtoDF*N_MOVE];
82

  
83
	// Table to merge the coordinates of the UR,UF,UL and UB,DR,DF edges at the beginning of phase2
84
	private static final byte[] MergeURtoULandUBtoDF = new byte[2*336*336];
85

  
86
	// Pruning tables for the search
87
	// Pruning table for the permutation of the corners and the UD-slice edges in phase2.
88
	// The pruning table entries give a lower estimation for the number of moves to reach the solved cube.
89
	public static byte[] Slice_URFtoDLF_Parity_Prun = new byte[N_SLICE2*N_URFtoDLF*N_PARITY / 2];
90

  
91
	// Pruning table for the permutation of the edges in phase2.
92
	// The pruning table entries give a lower estimation for the number of moves to reach the solved cube.
93
	public static byte[] Slice_URtoDF_Parity_Prun = new byte[N_SLICE2*N_URtoDF*N_PARITY / 2];
94

  
95
	// Pruning table for the twist of the corners and the position (not permutation) of the UD-slice edges in phase1
96
	// The pruning table entries give a lower estimation for the number of moves to reach the H-subgroup.
97
	public static byte[] Slice_Twist_Prun = new byte[N_SLICE1*N_TWIST / 2 + 1];
98

  
99
	// Pruning table for the flip of the edges and the position (not permutation) of the UD-slice edges in phase1
100
	// The pruning table entries give a lower estimation for the number of moves to reach the H-subgroup.
101
	public static byte[] Slice_Flip_Prun = new byte[N_SLICE1*N_FLIP / 2];
102

  
103
  private static final int[] resourceTable = new int[]
104
			{
105
			R.raw.cube3solver_table1,
106
			R.raw.cube3solver_table2,
107
			R.raw.cube3solver_table3,
108
			R.raw.cube3solver_table4,
109
			R.raw.cube3solver_table5,
110
			R.raw.cube3solver_table6,
111
			R.raw.cube3solver_table7,
112
			R.raw.cube3solver_table8,
113
			R.raw.cube3solver_table9,
114
			R.raw.cube3solver_table10,
115
			R.raw.cube3solver_table11,
116
			R.raw.cube3solver_table12
117
			};
118

  
119
  private static final byte[][] tableOfTables = new byte[][]
120
			{
121
			twistMove,
122
			flipMove,
123
			FRtoBR_Move,
124
			URFtoDLF_Move,
125
			URtoDF_Move,
126
			URtoUL_Move,
127
			UBtoDF_Move,
128
			MergeURtoULandUBtoDF,
129
			Slice_URFtoDLF_Parity_Prun,
130
			Slice_URtoDF_Parity_Prun,
131
			Slice_Twist_Prun,
132
			Slice_Flip_Prun
133
			};
134

  
135
///////////////////////////////////////////////////////////////////////////////////////////////////
136
// Generate a CoordCube from a CubieCube
137

  
138
	SolverCoordCube(SolverCubieCube c)
139
	  {
140
		twist    = c.getTwist();
141
		flip     = c.getFlip();
142
		parity   = c.cornerParity();
143
		FRtoBR   = c.getFRtoBR();
144
		URFtoDLF = c.getURFtoDLF();
145
		URtoUL   = c.getURtoUL();
146
		UBtoDF   = c.getUBtoDF();
147
		URtoDF   = c.getURtoDF();// only needed in phase2
148
	  }
149

  
150
///////////////////////////////////////////////////////////////////////////////////////////////////
151

  
152
	static byte getPruning(byte[] table, int index)
153
	  {
154
	  byte ret = table[index/2];
155
	  return (byte) ( ((index&1)==0) ? (ret&0x0f) : ((ret&0xf0)>>>4) );
156
	  }
157

  
158
///////////////////////////////////////////////////////////////////////////////////////////////////
159

  
160
	public static short getTwistMove(int a,int b)
161
	  {
162
	  return getTable(a,b,twistMove,N_MOVE);
163
	  }
164

  
165
///////////////////////////////////////////////////////////////////////////////////////////////////
166

  
167
	public static short getFlipMove(int a,int b)
168
	  {
169
	  return getTable(a,b,flipMove,N_MOVE);
170
	  }
171

  
172
///////////////////////////////////////////////////////////////////////////////////////////////////
173

  
174
	public static short getFRtoBR_Move(int a,int b)
175
	  {
176
	  return getTable(a,b,FRtoBR_Move,N_MOVE);
177
	  }
178

  
179
///////////////////////////////////////////////////////////////////////////////////////////////////
180

  
181
	public static short getURFtoDLF_Move(int a,int b)
182
	  {
183
	  return getTable(a,b,URFtoDLF_Move,N_MOVE);
184
	  }
185

  
186
///////////////////////////////////////////////////////////////////////////////////////////////////
187

  
188
	public static short getURtoDF_Move(int a,int b)
189
	  {
190
	  return getTable(a,b,URtoDF_Move,N_MOVE);
191
	  }
192

  
193
///////////////////////////////////////////////////////////////////////////////////////////////////
194

  
195
	public static short getURtoUL_Move(int a,int b)
196
	  {
197
	  return getTable(a,b,URtoUL_Move,N_MOVE);
198
	  }
199

  
200
///////////////////////////////////////////////////////////////////////////////////////////////////
201

  
202
	public static short getUBtoDF_Move(int a,int b)
203
	  {
204
	  return getTable(a,b,UBtoDF_Move,N_MOVE);
205
	  }
206

  
207
///////////////////////////////////////////////////////////////////////////////////////////////////
208

  
209
	public static short getMergeURtoULandUBtoDF(int a,int b)
210
	  {
211
	  return getTable(a,b,MergeURtoULandUBtoDF,336);
212
	  }
213

  
214
///////////////////////////////////////////////////////////////////////////////////////////////////
215

  
216
	private static short getTable(int a,int b, byte[] table, int size)
217
	  {
218
		short upperS = table[2*(a*size+b)];
219
		short lowerS = table[2*(a*size+b)+1];
220

  
221
		if( upperS<0 ) upperS+=256;
222
		if( lowerS<0 ) lowerS+=256;
223

  
224
		return  (short)( (upperS<<8) + lowerS );
225
	  }
226

  
227
///////////////////////////////////////////////////////////////////////////////////////////////////
228

  
229
	public static void initialize(OperatingSystemInterface os, int index)
230
		{
231
		if( !init[index] )
232
		  {
233
		  try
234
		    {
235
		    byte[] table = tableOfTables[index];
236
			  InputStream is = os.openLocalFile(resourceTable[index]);
237
		    is.read( table, 0, table.length);
238
		    }
239
		  catch(Exception ioe)
240
		    {
241
		    System.out.println("error reading table"+index);
242
		    }
243

  
244
		  init[index]=true;
245
		  }
246
		}
247
}
src/main/java/org/distorted/objectlib/kociemba/SolverCorner.java
1
/*
2
 * Herbert Kociemba
3
 *
4
 * BSD-licensed. See https://opensource.org/licenses/BSD-3-Clause
5
 */
6

  
7
package org.distorted.objectlib.kociemba;
8

  
9
///////////////////////////////////////////////////////////////////////////////////////////////////
10
//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
11

  
12
class SolverCorner
13
  {
14
  public static final int URF =0;
15
  public static final int UFL =1;
16
  public static final int ULB =2;
17
  public static final int UBR =3;
18
  public static final int DFR =4;
19
  public static final int DLF =5;
20
  public static final int DBL =6;
21
  public static final int DRB =7;
22
  }
src/main/java/org/distorted/objectlib/kociemba/SolverCubieCube.java
1
/*
2
 * Herbert Kociemba
3
 *
4
 * BSD-licensed. See https://opensource.org/licenses/BSD-3-Clause
5
 */
6

  
7
package org.distorted.objectlib.kociemba;
8

  
9
///////////////////////////////////////////////////////////////////////////////////////////////////
10

  
11
class SolverCubieCube
12
  {
13
  private static final int[][] cnk     = new int[12][7];
14
  private static final int[] tmpEdge6  = new int[6];
15
  private static final int[] tmpEdge4  = new int[4];
16
  private static final int[] tmpEdge3  = new int[3];
17
  private static final int[] tmpCorner6= new int[6];
18

  
19
  // corner permutation
20
  int[] cp = { SolverCorner.URF, SolverCorner.UFL, SolverCorner.ULB, SolverCorner.UBR, SolverCorner.DFR, SolverCorner.DLF, SolverCorner.DBL, SolverCorner.DRB };
21

  
22
  // corner orientation
23
  byte[] co = { 0, 0, 0, 0, 0, 0, 0, 0 };
24

  
25
  // edge permutation
26
  int[] ep = { SolverEdge.UR, SolverEdge.UF, SolverEdge.UL, SolverEdge.UB, SolverEdge.DR, SolverEdge.DF, SolverEdge.DL, SolverEdge.DB, SolverEdge.FR, SolverEdge.FL, SolverEdge.BL, SolverEdge.BR };
27

  
28
  // edge orientation
29
  byte[] eo = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
30

  
31
  // Moves on the cubie level
32
  private static final int[]  cpU = { SolverCorner.UBR, SolverCorner.URF, SolverCorner.UFL, SolverCorner.ULB, SolverCorner.DFR, SolverCorner.DLF, SolverCorner.DBL, SolverCorner.DRB };
33
  private static final byte[] coU = { 0, 0, 0, 0, 0, 0, 0, 0 };
34
  private static final int[]  epU = { SolverEdge.UB, SolverEdge.UR, SolverEdge.UF, SolverEdge.UL, SolverEdge.DR, SolverEdge.DF, SolverEdge.DL, SolverEdge.DB, SolverEdge.FR, SolverEdge.FL, SolverEdge.BL, SolverEdge.BR };
35
  private static final byte[] eoU = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
36

  
37
  private static final int[]  cpR = { SolverCorner.DFR, SolverCorner.UFL, SolverCorner.ULB, SolverCorner.URF, SolverCorner.DRB, SolverCorner.DLF, SolverCorner.DBL, SolverCorner.UBR };
38
  private static final byte[] coR = { 2, 0, 0, 1, 1, 0, 0, 2 };
39
  private static final int[]  epR = { SolverEdge.FR, SolverEdge.UF, SolverEdge.UL, SolverEdge.UB, SolverEdge.BR, SolverEdge.DF, SolverEdge.DL, SolverEdge.DB, SolverEdge.DR, SolverEdge.FL, SolverEdge.BL, SolverEdge.UR };
40
  private static final byte[] eoR = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
41

  
42
  private static final int[]  cpF = { SolverCorner.UFL, SolverCorner.DLF, SolverCorner.ULB, SolverCorner.UBR, SolverCorner.URF, SolverCorner.DFR, SolverCorner.DBL, SolverCorner.DRB };
43
  private static final byte[] coF = { 1, 2, 0, 0, 2, 1, 0, 0 };
44
  private static final int[]  epF = { SolverEdge.UR, SolverEdge.FL, SolverEdge.UL, SolverEdge.UB, SolverEdge.DR, SolverEdge.FR, SolverEdge.DL, SolverEdge.DB, SolverEdge.UF, SolverEdge.DF, SolverEdge.BL, SolverEdge.BR };
45
  private static final byte[] eoF = { 0, 1, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0 };
46

  
47
  private static final int[]  cpD = { SolverCorner.URF, SolverCorner.UFL, SolverCorner.ULB, SolverCorner.UBR, SolverCorner.DLF, SolverCorner.DBL, SolverCorner.DRB, SolverCorner.DFR };
48
  private static final byte[] coD = { 0, 0, 0, 0, 0, 0, 0, 0 };
49
  private static final int[]  epD = { SolverEdge.UR, SolverEdge.UF, SolverEdge.UL, SolverEdge.UB, SolverEdge.DF, SolverEdge.DL, SolverEdge.DB, SolverEdge.DR, SolverEdge.FR, SolverEdge.FL, SolverEdge.BL, SolverEdge.BR };
50
  private static final byte[] eoD = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
51

  
52
  private static final int[]  cpL = { SolverCorner.URF, SolverCorner.ULB, SolverCorner.DBL, SolverCorner.UBR, SolverCorner.DFR, SolverCorner.UFL, SolverCorner.DLF, SolverCorner.DRB };
53
  private static final byte[] coL = { 0, 1, 2, 0, 0, 2, 1, 0 };
54
  private static final int[]  epL = { SolverEdge.UR, SolverEdge.UF, SolverEdge.BL, SolverEdge.UB, SolverEdge.DR, SolverEdge.DF, SolverEdge.FL, SolverEdge.DB, SolverEdge.FR, SolverEdge.UL, SolverEdge.DL, SolverEdge.BR };
55
  private static final byte[] eoL = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
56

  
57
  private static final int[]  cpB = { SolverCorner.URF, SolverCorner.UFL, SolverCorner.UBR, SolverCorner.DRB, SolverCorner.DFR, SolverCorner.DLF, SolverCorner.ULB, SolverCorner.DBL };
58
  private static final byte[] coB = { 0, 0, 1, 2, 0, 0, 2, 1 };
59
  private static final int[]  epB = { SolverEdge.UR, SolverEdge.UF, SolverEdge.UL, SolverEdge.BR, SolverEdge.DR, SolverEdge.DF, SolverEdge.DL, SolverEdge.BL, SolverEdge.FR, SolverEdge.FL, SolverEdge.UB, SolverEdge.DB };
60
  private static final byte[] eoB = { 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 1 };
61

  
62
  // this CubieCube array represents the 6 basic cube moves
63
  static SolverCubieCube[] moveCube = new SolverCubieCube[6];
64

  
65
  static
66
    {
67
    moveCube[0] = new SolverCubieCube();
68
    moveCube[0].cp = cpU;
69
    moveCube[0].co = coU;
70
    moveCube[0].ep = epU;
71
    moveCube[0].eo = eoU;
72

  
73
    moveCube[1] = new SolverCubieCube();
74
    moveCube[1].cp = cpR;
75
    moveCube[1].co = coR;
76
    moveCube[1].ep = epR;
77
    moveCube[1].eo = eoR;
78

  
79
    moveCube[2] = new SolverCubieCube();
80
    moveCube[2].cp = cpF;
81
    moveCube[2].co = coF;
82
    moveCube[2].ep = epF;
83
    moveCube[2].eo = eoF;
84

  
85
    moveCube[3] = new SolverCubieCube();
86
    moveCube[3].cp = cpD;
87
    moveCube[3].co = coD;
88
    moveCube[3].ep = epD;
89
    moveCube[3].eo = eoD;
90

  
91
    moveCube[4] = new SolverCubieCube();
92
    moveCube[4].cp = cpL;
93
    moveCube[4].co = coL;
94
    moveCube[4].ep = epL;
95
    moveCube[4].eo = eoL;
96

  
97
    moveCube[5] = new SolverCubieCube();
98
    moveCube[5].cp = cpB;
99
    moveCube[5].co = coB;
100
    moveCube[5].ep = epB;
101
    moveCube[5].eo = eoB;
102
    }
103

  
104
  static
105
    {
106
    for(int n=0; n<12; n++)
107
      for(int k=0; k<7; k++)
108
	      cnk[n][k] = -1;
109
    }
110

  
111
///////////////////////////////////////////////////////////////////////////////////////////////////
112

  
113
  SolverCubieCube()
114
    {
115
    }
116

  
117
///////////////////////////////////////////////////////////////////////////////////////////////////
118
// n choose k
119

  
120
  static int Cnk(int n, int k)
121
    {
122
    if( cnk[n][k]<0 )
123
      {
124
      int i, j, s;
125

  
126
      if (k > n  ) { cnk[n][k]=0; return 0; }
127
      if (k > n/2) k = n-k;
128
		  
129
      for(s=1, i=n, j=1; i!=n-k; i--, j++)
130
        {
131
	      s *= i;
132
	      s /= j;
133
        }
134
      cnk[n][k]= s;
135
      }
136
		
137
    return cnk[n][k];
138
    }
139

  
140
///////////////////////////////////////////////////////////////////////////////////////////////////
141
// Left rotation of all array elements between 0 and r
142

  
143
  static void rotateLeft(int[] arr, int r)
144
    {
145
    int tmp = arr[0];
146
    for (int i=0; i<r; i++) arr[i] = arr[i + 1];
147
    arr[r] = tmp;
148
    }
149

  
150
///////////////////////////////////////////////////////////////////////////////////////////////////
151
// Right rotation of all array elements between l and r
152

  
153
  static void rotateRight(int[] arr, int r)
154
    {
155
    int tmp = arr[r];
156
    for (int i = r; i > 0; i--) arr[i] = arr[i - 1];
157
    arr[0] = tmp;
158
    }
159

  
160
///////////////////////////////////////////////////////////////////////////////////////////////////
161
// return cube in facelet representation
162

  
163
  SolverFaceCube toFaceCube()
164
    {
165
    SolverFaceCube fcRet = new SolverFaceCube();
166

  
167
    for(int c = SolverCorner.URF; c<= SolverCorner.DRB; c++)
168
      {
169
      int j = cp[c];   // corner cubie with index j is at corner position with index i
170
      byte ori = co[c];// orientation of this cubie
171

  
172
      for( int n=0; n<3; n++)
173
        fcRet.f[SolverFaceCube.cornerFacelet[c][(n + ori) % 3]] = SolverFaceCube.cornerColor[j][n];
174
      }
175

  
176
    for(int e = SolverEdge.UR; e<= SolverEdge.BR; e++)
177
      {
178
      int j = ep[e];   // edge cubie with index j is at edge position with index i
179
      byte ori = eo[e];// orientation of this cubie
180

  
181
      for( int n=0; n<2; n++)
182
	      fcRet.f[SolverFaceCube.edgeFacelet[e][(n + ori) % 2]] = SolverFaceCube.edgeColor[j][n];
183
      }
184

  
185
    return fcRet;
186
    }
187

  
188
///////////////////////////////////////////////////////////////////////////////////////////////////
189
// return the twist of the 8 corners. 0 <= twist < 3^7
190

  
191
  short getTwist()
192
    {
193
    short ret = 0;
194

  
195
    for(int i = SolverCorner.URF; i< SolverCorner.DRB; i++)
196
      ret = (short) (3*ret+co[i]);
197

  
198
    return ret;
199
    }
200

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

  
203
  void setTwist(short twist)
204
    {
205
    int twistParity = 0;
206

  
207
    for (int i = SolverCorner.DRB-1; i>= SolverCorner.URF; i--)
208
      {
209
      twistParity += co[i] = (byte) (twist%3);
210
      twist /= 3;
211
      }
212
    co[SolverCorner.DRB] = (byte) ((3 - twistParity % 3) % 3);
213
    }
214

  
215
///////////////////////////////////////////////////////////////////////////////////////////////////
216
// return the flip of the 12 edges. 0<= flip < 2^11
217

  
218
  short getFlip()
219
    {
220
    short ret = 0;
221

  
222
    for (int i = SolverEdge.UR; i< SolverEdge.BR; i++)
223
      ret = (short) (2 * ret + eo[i]);
224

  
225
    return ret;
226
    }
227

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

  
230
  void setFlip(short flip)
231
    {
232
    int flipParity = 0;
233

  
234
    for (int i = SolverEdge.BR-1; i>= SolverEdge.UR; i--)
235
      {
236
      flipParity += eo[i] = (byte) (flip % 2);
237
      flip /= 2;
238
      }
239
    eo[SolverEdge.BR] = (byte) ((2 - flipParity % 2) % 2);
240
    }
241

  
242
///////////////////////////////////////////////////////////////////////////////////////////////////
243
// Parity of the corner permutation
244

  
245
  short cornerParity()
246
    {
247
    int s = 0;
248

  
249
    for (int i = SolverCorner.DRB; i>= SolverCorner.URF+1; i--)
250
      for (int j = i - 1; j >= SolverCorner.URF; j--)
251
        if (cp[j] > cp[i]) s++;
252

  
253
    return (short) (s%2);
254
    }
255

  
256
///////////////////////////////////////////////////////////////////////////////////////////////////
257
// Parity of the edges permutation. Parity of corners and edges are the same if the cube is solvable.
258

  
259
  short edgeParity()
260
    {
261
    int s = 0;
262

  
263
    for (int i = SolverEdge.BR; i >= SolverEdge.UR+1; i--)
264
      for (int j = i - 1; j >= SolverEdge.UR; j--)
265
        if (ep[j] > ep[i]) s++;
266

  
267
    return (short) (s%2);
268
    }
269

  
270
///////////////////////////////////////////////////////////////////////////////////////////////////
271
// permutation of the UD-slice edges FR,FL,BL and BR
272

  
273
  short getFRtoBR()
274
    {
275
    int a = 0, x = 0;
276

  
277
    // compute the index a < (12 choose 4) and the permutation array perm.
278
    for(int j = SolverEdge.BR; j >= SolverEdge.UR; j--)
279
      if (SolverEdge.FR <= ep[j] && ep[j] <= SolverEdge.BR)
280
        {
281
        a += Cnk(11-j, x+1);
282
	      tmpEdge4[3-x++] = ep[j];
283
	      }
284

  
285
    int b = 0;
286
    for( int j=3; j>0; j--) // compute the index b < 4! for the permutation in perm
287
      {
288
      int k = 0;
289
      while (tmpEdge4[j] != j+8)
290
        {
291
	      rotateLeft(tmpEdge4,j);
292
	      k++;
293
        }
294
      b = (j+1)*b + k;
295
      }
296

  
297
    return (short) (24*a+b);
298
    }
299

  
300
///////////////////////////////////////////////////////////////////////////////////////////////////
301
// Permutation of all corners except DBL and DRB
302

  
303
  short getURFtoDLF()
304
    {
305
    int a = 0, x = 0;
306

  
307
    // compute the index a < (8 choose 6) and the corner permutation.
308
    for(int j = SolverCorner.URF; j<= SolverCorner.DRB; j++)
309
      if( cp[j] <= SolverCorner.DLF )
310
        {
311
	      a += Cnk(j, x+1);
312
	      tmpCorner6[x++] = cp[j];
313
	      }
314

  
315
    int b = 0;
316

  
317
    for( int j=5; j>0; j--) // compute the index b < 6! for the permutation in corner6
318
      {
319
      int k = 0;
320

  
321
      while (tmpCorner6[j] != j)
322
        {
323
	      rotateLeft(tmpCorner6,j);
324
	      k++;
325
	      }
326
      b = (j+1)*b + k;
327
      }
328

  
329
    return (short) (720*a+b);
330
    }
331

  
332
///////////////////////////////////////////////////////////////////////////////////////////////////
333
// Permutation of the six edges UR,UF,UL,UB,DR,DF.
334

  
335
  int getURtoDF()
336
    {
337
    int a = 0, x = 0;
338
    // compute the index a < (12 choose 6) and the edge permutation.
339

  
340
    for(int j = SolverEdge.UR; j<= SolverEdge.BR; j++)
341
      if (ep[j] <= SolverEdge.DF)
342
        {
343
	      a += Cnk(j, x+1);
344
	      tmpEdge6[x++] = ep[j];
345
	      }
346

  
347
    int b = 0;
348

  
349
    for (int j=5; j>0; j--)// compute the index b < 6! for the permutation in edge6
350
      {
351
      int k = 0;
352

  
353
      while (tmpEdge6[j] != j)
354
        {
355
	      rotateLeft(tmpEdge6,j);
356
	      k++;
357
	      }
358
      b = (j+1)*b + k;
359
      }
360
    return 720*a+b;
361
    }
362

  
363
///////////////////////////////////////////////////////////////////////////////////////////////////
364
// Permutation of the three edges UR,UF,UL
365

  
366
  short getURtoUL()
367
    {
368
    int a=0, x=0;
369

  
370
    // compute the index a < (12 choose 3) and the edge permutation.
371
    for(int j = SolverEdge.UR; j<= SolverEdge.BR; j++)
372
      if (ep[j] <= SolverEdge.UL)
373
        {
374
	      a += Cnk(j, x + 1);
375
	      tmpEdge3[x++] = ep[j];
376
	      }
377

  
378
    int b=0;
379

  
380
    for( int j=2; j>0; j--)// compute the index b < 3! for the permutation in edge3
381
      {
382
      int k = 0;
383
      while (tmpEdge3[j] != j)
384
        {
385
	      rotateLeft(tmpEdge3,j);
386
	      k++;
387
	      }
388
      b = (j+1)*b+k;
389
      }
390
	
391
    return (short) (6*a+b);
392
    }
393

  
394
///////////////////////////////////////////////////////////////////////////////////////////////////
395
// Permutation of the three edges UB,DR,DF
396

  
397
  short getUBtoDF()
398
    {
399
    int a=0, x=0;
400
    // compute the index a < (12 choose 3) and the edge permutation.
401

  
402
    for(int j = SolverEdge.UR; j<= SolverEdge.BR; j++)
403
      if (SolverEdge.UB <= ep[j] && ep[j] <= SolverEdge.DF)
404
        {
405
	      a += Cnk(j, x+1);
406
	      tmpEdge3[x++] = ep[j];
407
	      }
408

  
409
    int b=0;
410

  
411
    for (int j=2; j>0; j--) // compute the index b < 3! for the permutation in edge3
412
      {
413
      int k=0;
414

  
415
      while (tmpEdge3[j] != SolverEdge.UB + j)
416
        {
417
	      rotateLeft(tmpEdge3,j);
418
	      k++;
419
	      }
420
      b = (j+1)*b+k;
421
      }
422

  
423
    return (short) (6*a+b);
424
    }
425

  
426
///////////////////////////////////////////////////////////////////////////////////////////////////
427

  
428
  void setURFtoDLB(int idx)
429
    {
430
    int[] perm = { SolverCorner.URF, SolverCorner.UFL, SolverCorner.ULB, SolverCorner.UBR, SolverCorner.DFR, SolverCorner.DLF, SolverCorner.DBL, SolverCorner.DRB };
431
    int k;
432

  
433
    for( int j=1; j<8; j++)
434
      {
435
      k = idx % (j+1);
436
      idx /= j+1;
437
      while (k-- > 0) rotateRight(perm,j);
438
      }
439

  
440
    int x=7;// set corners
441

  
442
    for( int j=7; j>=0; j--) cp[j] = perm[x--];
443
    }
444

  
445
///////////////////////////////////////////////////////////////////////////////////////////////////
446

  
447
  void setURtoBR(int idx)
448
    {
449
    int[] perm = { SolverEdge.UR, SolverEdge.UF, SolverEdge.UL, SolverEdge.UB, SolverEdge.DR, SolverEdge.DF, SolverEdge.DL, SolverEdge.DB, SolverEdge.FR, SolverEdge.FL, SolverEdge.BL, SolverEdge.BR };
450
    int k;
451

  
452
    for( int j=1; j<12; j++)
453
      {
454
      k = idx % (j+1);
455
      idx /= j+1;
456

  
457
      while (k-- > 0) rotateRight(perm,j);
458
      }
459

  
460
    int x=11;// set edges
461

  
462
    for( int j=11; j>=0; j--) ep[j] = perm[x--];
463
    }
464

  
465
///////////////////////////////////////////////////////////////////////////////////////////////////
466
// Check a cubie cube for solvability. Return the error code.
467
// 0: Cube is solvable
468
// -2: Not all 12 edges exist exactly once
469
// -3: Flip error: One edge has to be flipped
470
// -4: Not all corners exist exactly once
471
// -5: Twist error: One corner has to be twisted
472
// -6: Parity error: Two corners ore two edges have to be exchanged
473

  
474
  int verify()
475
    {
476
    int sum = 0;
477
    int[] edgeCount = new int[12];
478

  
479
    for (int e = SolverEdge.UR; e <= SolverEdge.BR; e++) edgeCount[ep[e]]++;
480

  
481
    for( int i=0; i<12; i++)
482
      if (edgeCount[i] != 1) return -2;
483

  
484
    for( int i=0; i<12; i++) sum += eo[i];
485

  
486
    if( (sum%2) != 0) return -3;
487

  
488
    int[] cornerCount = new int[8];
489

  
490
    for(int c = SolverCorner.URF; c<= SolverCorner.DRB; c++) cornerCount[cp[c]]++;
491

  
492
    for (int i = 0; i < 8; i++)
493
      if (cornerCount[i] != 1) return -4;// missing corners
494

  
495
    sum = 0;
496

  
497
    for( int i=0; i<8; i++) sum += co[i];
498

  
499
    if( (sum%3) != 0) return -5;// twisted corner
500

  
501
    if( (edgeParity()^cornerParity()) != 0) return -6;// parity error
502

  
503
    return 0;// cube ok
504
    }
505
}
src/main/java/org/distorted/objectlib/kociemba/SolverEdge.java
1
/*
2
 * Herbert Kociemba
3
 *
4
 * BSD-licensed. See https://opensource.org/licenses/BSD-3-Clause
5
 */
6

  
7
package org.distorted.objectlib.kociemba;
8

  
9
///////////////////////////////////////////////////////////////////////////////////////////////////
10

  
11
class SolverEdge
12
  {
13
  public static final int UR=0;
14
  public static final int UF=1;
15
  public static final int UL=2;
16
  public static final int UB=3;
17
  public static final int DR=4;
18
  public static final int DF=5;
19
  public static final int DL=6;
20
  public static final int DB=7;
21
  public static final int FR=8;
22
  public static final int FL=9;
23
  public static final int BL=10;
24
  public static final int BR=11;
25
  }
src/main/java/org/distorted/objectlib/kociemba/SolverFaceCube.java
1
/*
2
 * Herbert Kociemba
3
 *
4
 * BSD-licensed. See https://opensource.org/licenses/BSD-3-Clause
5
 */
6

  
7
package org.distorted.objectlib.kociemba;
8

  
9
///////////////////////////////////////////////////////////////////////////////////////////////////
10

  
11
class SolverFaceCube
12
{
13
	public int[] f = new int[54];
14

  
15
	// Map the corner positions to facelet positions. cornerFacelet[URF.ordinal()][0] e.g. gives the position of the
16
	// facelet in the URF corner position, which defines the orientation.
17
	// cornerFacelet[URF.ordinal()][1] and cornerFacelet[URF.ordinal()][2] give the position of the other two facelets
18
	// of the URF corner (clockwise).
19
	final static int[][] cornerFacelet =
20
          { { SolverFacelet.U9, SolverFacelet.R1, SolverFacelet.F3 }, { SolverFacelet.U7, SolverFacelet.F1, SolverFacelet.L3 },
21
            { SolverFacelet.U1, SolverFacelet.L1, SolverFacelet.B3 }, { SolverFacelet.U3, SolverFacelet.B1, SolverFacelet.R3 },
22
	          { SolverFacelet.D3, SolverFacelet.F9, SolverFacelet.R7 }, { SolverFacelet.D1, SolverFacelet.L9, SolverFacelet.F7 },
23
            { SolverFacelet.D7, SolverFacelet.B9, SolverFacelet.L7 }, { SolverFacelet.D9, SolverFacelet.R9, SolverFacelet.B7 } };
24

  
25
	// Map the edge positions to facelet positions. edgeFacelet[UR.ordinal()][0] e.g. gives the position of the facelet in
26
	// the UR edge position, which defines the orientation.
27
	// edgeFacelet[UR.ordinal()][1] gives the position of the other facelet
28
	final static int[][] edgeFacelet =
29
          { { SolverFacelet.U6, SolverFacelet.R2 }, { SolverFacelet.U8, SolverFacelet.F2 }, { SolverFacelet.U4, SolverFacelet.L2 },
30
            { SolverFacelet.U2, SolverFacelet.B2 }, { SolverFacelet.D6, SolverFacelet.R8 }, { SolverFacelet.D2, SolverFacelet.F8 },
31
	          { SolverFacelet.D4, SolverFacelet.L8 }, { SolverFacelet.D8, SolverFacelet.B8 }, { SolverFacelet.F6, SolverFacelet.R4 },
32
            { SolverFacelet.F4, SolverFacelet.L6 }, { SolverFacelet.B6, SolverFacelet.L4 }, { SolverFacelet.B4, SolverFacelet.R6 } };
33

  
34
	// Map the corner positions to facelet colors.
35
	final static int[][] cornerColor =
36
          { { SolverColor.U, SolverColor.R, SolverColor.F }, { SolverColor.U, SolverColor.F, SolverColor.L },
37
            { SolverColor.U, SolverColor.L, SolverColor.B }, { SolverColor.U, SolverColor.B, SolverColor.R },
38
            { SolverColor.D, SolverColor.F, SolverColor.R }, { SolverColor.D, SolverColor.L, SolverColor.F },
39
	          { SolverColor.D, SolverColor.B, SolverColor.L }, { SolverColor.D, SolverColor.R, SolverColor.B } };
40

  
41
	// Map the edge positions to facelet colors.
42
	final static int[][] edgeColor =
43
          { { SolverColor.U, SolverColor.R }, { SolverColor.U, SolverColor.F }, { SolverColor.U, SolverColor.L },
44
            { SolverColor.U, SolverColor.B }, { SolverColor.D, SolverColor.R }, { SolverColor.D, SolverColor.F },
45
            { SolverColor.D, SolverColor.L }, { SolverColor.D, SolverColor.B }, { SolverColor.F, SolverColor.R },
46
            { SolverColor.F, SolverColor.L }, { SolverColor.B, SolverColor.L }, { SolverColor.B, SolverColor.R } };
47

  
48
///////////////////////////////////////////////////////////////////////////////////////////////////
49

  
50
	SolverFaceCube()
51
    {
52
	  String s = "UUUUUUUUURRRRRRRRRFFFFFFFFFDDDDDDDDDLLLLLLLLLBBBBBBBBB";
53

  
54
    for( int i=0; i<54; i++)
55
	    f[i] = SolverColor.toInt(s.substring(i, i + 1));
56
	  }
57

  
58
///////////////////////////////////////////////////////////////////////////////////////////////////
59
// Construct a facelet cube from a string
60

  
61
	SolverFaceCube(String cubeString)
62
    {
63
	  for( int i=0; i<cubeString.length(); i++)
64
	    f[i] = SolverColor.toInt(cubeString.substring(i, i + 1));
65
	  }
66

  
67
///////////////////////////////////////////////////////////////////////////////////////////////////
68
// Gives string representation of a facelet cube
69

  
70
	String to_String()
71
    {
72
	  String s = "";
73

  
74
	  for (int i = 0; i < 54; i++)
75
	    s += SolverColor.toString(f[i]);
76

  
77
    return s;
78
	  }
79

  
80
///////////////////////////////////////////////////////////////////////////////////////////////////
81
// Gives CubieCube representation of a faceletcube
82

  
83
	SolverCubieCube toCubieCube()
84
    {
85
	  byte ori;
86
	  SolverCubieCube ccRet = new SolverCubieCube();
87
		
88
    for( int i=0; i< 8; i++) ccRet.cp[i] = SolverCorner.URF; // invalidate corners
89
	  for( int i=0; i<12; i++) ccRet.ep[i] = SolverEdge.UR;    // and edges
90

  
91
	  int col1, col2;
92

  
93
	  for(int i = SolverCorner.URF; i<= SolverCorner.DRB; i++)
94
      {
95
	    // get the colors of the cubie at corner i, starting with U/D
96
	    for (ori = 0; ori < 3; ori++)
97
	      if (f[cornerFacelet[i][ori]] == SolverColor.U || f[cornerFacelet[i][ori]] == SolverColor.D)
98
		      break;
99

  
100
	    col1 = f[cornerFacelet[i][(ori+1)%3]];
101
	    col2 = f[cornerFacelet[i][(ori+2)%3]];
102

  
103
	    for(int j = SolverCorner.URF; j<= SolverCorner.DRB; j++)
104
        {
105
	      if( col1==cornerColor[j][1] && col2==cornerColor[j][2])
106
          {
107
		      // in cornerposition i we have cornercubie j
108
		      ccRet.cp[i] = j;
109
		      ccRet.co[i] = (byte) (ori % 3);
110
		      break;
111
		      }
112
	      }
113
	    }
114

  
115
    for(int i = SolverEdge.UR; i<= SolverEdge.BR; i++)
116
      {
117
	    for(int j = SolverEdge.UR; j<= SolverEdge.BR; j++)
118
        {
119
        if( f[edgeFacelet[i][0]]==edgeColor[j][0] && f[edgeFacelet[i][1]]==edgeColor[j][1])
120
          {
121
		      ccRet.ep[i] = j;
122
		      ccRet.eo[i] = 0;
123
		      break;
124
		      }
125
        if( f[edgeFacelet[i][0]]==edgeColor[j][1] && f[edgeFacelet[i][1]]==edgeColor[j][0])
126
          {
127
		      ccRet.ep[i] = j;
128
		      ccRet.eo[i] = 1;
129
		      break;
130
          }
131
	      }
132
	    }
133

  
134
	return ccRet;
135
	}
136
}
src/main/java/org/distorted/objectlib/kociemba/SolverFacelet.java
1
/*
2
 * Herbert Kociemba
3
 *
4
 * BSD-licensed. See https://opensource.org/licenses/BSD-3-Clause
5
 */
6

  
7
package org.distorted.objectlib.kociemba;
8

  
9
/**
10
 * <pre>
11
 * The names of the facelet positions of the cube
12
 *             |************|
13
 *             |*U1**U2**U3*|
14
 *             |************|
15
 *             |*U4**U5**U6*|
16
 *             |************|
17
 *             |*U7**U8**U9*|
18
 *             |************|
19
 * ************|************|************|************|
20
 * *L1**L2**L3*|*F1**F2**F3*|*R1**R2**F3*|*B1**B2**B3*|
21
 * ************|************|************|************|
22
 * *L4**L5**L6*|*F4**F5**F6*|*R4**R5**R6*|*B4**B5**B6*|
23
 * ************|************|************|************|
24
 * *L7**L8**L9*|*F7**F8**F9*|*R7**R8**R9*|*B7**B8**B9*|
25
 * ************|************|************|************|
26
 *             |************|
27
 *             |*D1**D2**D3*|
28
 *             |************|
29
 *             |*D4**D5**D6*|
30
 *             |************|
31
 *             |*D7**D8**D9*|
32
 *             |************|
33
 * </pre>
34
 * 
35
 *A cube definition string "UBL..." means for example: In position U1 we have the U-color, in position U2 we have the
36
 * B-color, in position U3 we have the L color etc. according to the order U1, U2, U3, U4, U5, U6, U7, U8, U9, R1, R2,
37
 * R3, R4, R5, R6, R7, R8, R9, F1, F2, F3, F4, F5, F6, F7, F8, F9, D1, D2, D3, D4, D5, D6, D7, D8, D9, L1, L2, L3, L4,
38
 * L5, L6, L7, L8, L9, B1, B2, B3, B4, B5, B6, B7, B8, B9 of the enum constants.
39
 */
40

  
41
///////////////////////////////////////////////////////////////////////////////////////////////////
42

  
43
class SolverFacelet
44
  {
45
  public static int U1 = 0;
46
  public static int U2 = 1;
47
  public static int U3 = 2;
48
  public static int U4 = 3;
49
  public static int U5 = 4;
50
  public static int U6 = 5;
51
  public static int U7 = 6;
52
  public static int U8 = 7;
53
  public static int U9 = 8;
54

  
55
  public static int R1 = 9;
56
  public static int R2 = 10;
57
  public static int R3 = 11;
58
  public static int R4 = 12;
59
  public static int R5 = 13;
60
  public static int R6 = 14;
61
  public static int R7 = 15;
62
  public static int R8 = 16;
63
  public static int R9 = 17;
64

  
65
  public static int F1 = 18;
66
  public static int F2 = 19;
67
  public static int F3 = 20;
68
  public static int F4 = 21;
69
  public static int F5 = 22;
70
  public static int F6 = 23;
71
  public static int F7 = 24;
72
  public static int F8 = 25;
73
  public static int F9 = 26;
74

  
75
  public static int D1 = 27;
76
  public static int D2 = 28;
77
  public static int D3 = 29;
78
  public static int D4 = 30;
79
  public static int D5 = 31;
80
  public static int D6 = 32;
81
  public static int D7 = 33;
82
  public static int D8 = 34;
83
  public static int D9 = 35;
84

  
85
  public static int L1 = 36;
86
  public static int L2 = 37;
87
  public static int L3 = 38;
88
  public static int L4 = 39;
89
  public static int L5 = 40;
90
  public static int L6 = 41;
91
  public static int L7 = 42;
92
  public static int L8 = 43;
93
  public static int L9 = 44;
94

  
95
  public static int B1 = 45;
96
  public static int B2 = 46;
97
  public static int B3 = 47;
98
  public static int B4 = 48;
99
  public static int B5 = 49;
100
  public static int B6 = 50;
101
  public static int B7 = 51;
102
  public static int B8 = 52;
103
  public static int B9 = 53;
104
  }
src/main/java/org/distorted/objectlib/kociemba/SolverSearch.java
1
/*
2
 * Herbert Kociemba
3
 *
4
 * BSD-licensed. See https://opensource.org/licenses/BSD-3-Clause
5
 */
6

  
7
package org.distorted.objectlib.kociemba;
8

  
9
import org.distorted.objectlib.helpers.OperatingSystemInterface;
10

  
11
///////////////////////////////////////////////////////////////////////////////////////////////////
12

  
13
public class SolverSearch
14
{
15
	static int mNumMoves = 0;
16
	
17
	static int[] ax      = new int[31]; // The axis of the move
18
	static int[] po      = new int[31]; // The power of the move
19

  
20
	static int[] flip    = new int[31]; // phase1 coordinates
21
	static int[] twist   = new int[31];
22
	static int[] slice   = new int[31];
23

  
24
	static int[] parity  = new int[31]; // phase2 coordinates
25
	static int[] URFtoDLF= new int[31];
26
	static int[] FRtoBR  = new int[31];
27
	static int[] URtoUL  = new int[31];
28
	static int[] UBtoDF  = new int[31];
29
	static int[] URtoDF  = new int[31];
30

  
31
	static int[] minDistPhase1 = new int[31]; // IDA * distance to goal estimations
32
	static int[] minDistPhase2 = new int[31];
33

  
34
///////////////////////////////////////////////////////////////////////////////////////////////////
35

  
36
	static String solutionToString(int length) 
37
	  {
38
		StringBuilder s = new StringBuilder();
39
		
40
		for( int i=0; i<length; i++)
41
		  {
42
			switch(ax[i])
43
			  {
44
			  case 0: switch(po[i])
45
			            {
46
			            case 1: s.append(" 548"); break;
47
			            case 2: s.append(" 804"); break;
48
			            case 3: s.append(" 292"); break;
49
			            }
50
				        break;
51
			  case 1: switch(po[i])
52
	                {
53
	                case 1: s.append(" 516"); break;
54
	                case 2: s.append(" 772"); break;
55
	                case 3: s.append(" 260"); break;
56
	                }
57
				        break;
58
		  	case 2: switch(po[i])
59
                  {
60
                  case 1: s.append(" 580"); break;
61
                  case 2: s.append(" 836"); break;
62
                  case 3: s.append(" 324"); break;
63
                  }
64
				        break;
65
		  	case 3: switch(po[i])
66
                  {
67
                  case 1: s.append(" 289"); break;
68
                  case 2: s.append(" 033"); break;
69
                  case 3: s.append(" 545"); break;
70
                  }
71
				        break;
72
			  case 4: switch(po[i])
73
                  {
74
                  case 1: s.append(" 257"); break;
75
                  case 2: s.append(" 001"); break;
76
                  case 3: s.append(" 513"); break;
77
                  }
78
				        break;
79
			  case 5: switch(po[i])
80
                  {
81
                  case 1: s.append(" 321"); break;
82
                  case 2: s.append(" 065"); break;
83
                  case 3: s.append(" 577"); break;
84
                  }
85
				        break;
86
			  }
87
		  }
88
		return s.toString();
89
	}
90

  
91
///////////////////////////////////////////////////////////////////////////////////////////////////
92

  
93
	public static void prepare(OperatingSystemInterface os)
94
	  {
95
	  SolverCoordCube.initialize(os,0);
96
    SolverCoordCube.initialize(os,1);
97
		SolverCoordCube.initialize(os,2);
98
		SolverCoordCube.initialize(os,3);
99
		SolverCoordCube.initialize(os,4);
100
		SolverCoordCube.initialize(os,5);
101
		SolverCoordCube.initialize(os,6);
102
		SolverCoordCube.initialize(os,7);
103
		SolverCoordCube.initialize(os,8);
104
		SolverCoordCube.initialize(os,9);
105
		SolverCoordCube.initialize(os,10);
106
		SolverCoordCube.initialize(os,11);
107
	  }
108

  
109
///////////////////////////////////////////////////////////////////////////////////////////////////
110
/**
111
 * Computes the solver string for a given cube.
112
 *
113
 * @param facelets
114
 *          is the cube definition string, see {@link SolverFacelet} for the format.
115
 *
116
 * @param maxDepth
117
 *          defines the maximal allowed maneuver length. For random cubes, a maxDepth of 21 usually
118
 *          will return a solution in less than 0.5 seconds. With a maxDepth of 20 it takes a few
119
 *          seconds on average to find a solution, but it may take much longer for specific cubes.
120
 *
121
 *@param timeOut
122
 *          defines the maximum computing time of the method in seconds. If it does not return with
123
 *          a solution, it returns with an error code.
124
 * @return The solution string or an error code:
125
 *         Error 1: There is not exactly one facelet of each color
126
 *         Error 2: Not all 12 edges exist exactly once
127
 *         Error 3: Flip error: One edge has to be flipped
128
 *         Error 4: Not all corners exist exactly once
129
 *         Error 5: Twist error: One corner has to be twisted
130
 *         Error 6: Parity error: Two corners or two edges have to be exchanged
131
 *         Error 7: No solution exists for the given maxDepth
132
 *         Error 8: Timeout, no solution within given time
133
 */
134

  
135
	public static String solution(String facelets, int maxDepth, long timeOut) 
136
	  {
137
		int s;
138
		int[] count = new int[6];
139

  
140
		try
141
		  {
142
			for( int i=0; i<54; i++)
143
				count[SolverColor.toInt(facelets.substring(i,i+1))]++;
144
		  }
145
		catch (Exception e)
146
		  {
147
		  android.util.Log.d("error", "1");
148
			return "Error 1";
149
		  }
150

  
151
		for( int i=0; i<6; i++)
152
			if (count[i] != 9)
153
			  {
154
			  android.util.Log.d("error", "2");
155
				return "Error 1";
156
				}
157

  
158
		SolverFaceCube fc = new SolverFaceCube(facelets);
159
		SolverCubieCube cc = fc.toCubieCube();
160
		if ((s = cc.verify()) != 0)
161
		  {
162
		  android.util.Log.d("error", "3");
163
			return "Error " + Math.abs(s);
164
			}
165

  
166
		SolverCoordCube c = new SolverCoordCube(cc);
167

  
168
		po[0] = 0;
169
		ax[0] = 0;
170
		flip[0] = c.flip;
171
		twist[0] = c.twist;
172
		parity[0] = c.parity;
173
		slice[0] = c.FRtoBR / 24;
174
		URFtoDLF[0] = c.URFtoDLF;
175
		FRtoBR[0] = c.FRtoBR;
176
		URtoUL[0] = c.URtoUL;
177
		UBtoDF[0] = c.UBtoDF;
178

  
179
		minDistPhase1[1] = 1;// else failure for depth=1, n=0
180
		int mv, n=0;
181
		boolean busy = false;
182
		int depthPhase1 = 1;
183

  
184
		long tStart = System.currentTimeMillis();
185

  
186
		do
187
		  {
188
			do
189
			  {
190
				if( (depthPhase1-n > minDistPhase1[n+1]) && !busy)
191
				  {
192
					if (ax[n]==0 || ax[n]==3)// Initialize next move
193
						ax[++n] = 1;
194
					else
195
						ax[++n] = 0;
196
					po[n] = 1;
197
				  }
198
				else if (++po[n] > 3)
199
				  {
200
					do
201
					  { // increment axis
202
						if (++ax[n] > 5)
203
						  {
204
							if (System.currentTimeMillis() - tStart > timeOut << 10)
205
								return "Error 8";
206

  
207
							if (n==0)
208
							  {
209
								if (depthPhase1 >= maxDepth)
210
									return "Error 7";
211
								else
212
								  {
213
									depthPhase1++;
214
									ax[n] = 0;
215
									po[n] = 1;
216
									busy = false;
217
									break;
218
								  }
219
							  }
220
							else
221
							  {
222
								n--;
223
								busy = true;
224
								break;
225
							  }
226
						  }
227
						else
228
						  {
229
							po[n] = 1;
230
							busy = false;
231
						  }
232
					  }
233
					while (n != 0 && (ax[n - 1] == ax[n] || ax[n - 1] - 3 == ax[n]));
234
				  }
235
				else
236
					busy = false;
237
			  }
238
			while (busy);
239

  
240
			// compute new coordinates and new minDistPhase1. If minDistPhase1 =0, the H subgroup is reached
241
			mv = 3*ax[n]+po[n]-1;
242
			flip [n+1] = SolverCoordCube.getFlipMove(flip[n],mv);
243
			twist[n+1] = SolverCoordCube.getTwistMove(twist[n],mv);
244
			slice[n+1] = SolverCoordCube.getFRtoBR_Move(slice[n] * 24,mv) / 24;
245
			minDistPhase1[n+1] = Math.max(SolverCoordCube.getPruning(SolverCoordCube.Slice_Flip_Prun, SolverCoordCube.N_SLICE1 * flip[n+1]
246
					+ slice[n+1]), SolverCoordCube.getPruning(SolverCoordCube.Slice_Twist_Prun, SolverCoordCube.N_SLICE1 * twist[n+1]
247
					+ slice[n+1]));
248

  
249
			if (minDistPhase1[n+1]==0 && n >= depthPhase1 - 5)
250
			  {
251
				minDistPhase1[n+1] = 10;// instead of 10 any value >5 is possible
252
				if (n==depthPhase1-1 && (s = totalDepth(depthPhase1, maxDepth)) >= 0)
253
				  {
254
					if (s==depthPhase1 || (ax[depthPhase1-1] != ax[depthPhase1] && ax[depthPhase1-1] != ax[depthPhase1]+3))
255
					  {
256
						mNumMoves = s;
257
						return solutionToString(s);
258
					  }
259
				  }
260
			  }
261
		  }
262
		while (true);
263
	  }
264

  
265
///////////////////////////////////////////////////////////////////////////////////////////////////
266
// Apply phase2 of algorithm and return the combined phase1 and phase2 depth. In phase2, only the moves
267
// U,D,R2,F2,L2 and B2 are allowed.
268

  
269
	static int totalDepth(int depthPhase1, int maxDepth)
270
	  {
271
		int mv, d1, d2;
272
		int maxDepthPhase2 = Math.min(10,maxDepth-depthPhase1);// Allow only max 10 moves in phase2
273
		for( int i=0; i<depthPhase1; i++)
274
		  {
275
			mv = 3*ax[i]+po[i]-1;
276
			URFtoDLF[i+1] = SolverCoordCube.getURFtoDLF_Move(URFtoDLF[i],mv);
277
			FRtoBR  [i+1] = SolverCoordCube.getFRtoBR_Move(FRtoBR[i],mv);
278
			parity  [i+1] = SolverCoordCube.parityMove[parity[i]][mv];
279
		  }
280

  
281
		if( (d1 = SolverCoordCube.getPruning(SolverCoordCube.Slice_URFtoDLF_Parity_Prun,
282
				(SolverCoordCube.N_SLICE2 * URFtoDLF[depthPhase1] + FRtoBR[depthPhase1]) * 2 + parity[depthPhase1])) > maxDepthPhase2)
283
			return -1;
284

  
285
		for( int i=0; i<depthPhase1; i++)
286
		  {
287
			mv = 3 * ax[i] + po[i] - 1;
288
			URtoUL[i + 1] = SolverCoordCube.getURtoUL_Move(URtoUL[i],mv);
289
			UBtoDF[i + 1] = SolverCoordCube.getUBtoDF_Move(UBtoDF[i],mv);
290
		  }
291

  
292
		URtoDF[depthPhase1] = SolverCoordCube.getMergeURtoULandUBtoDF(URtoUL[depthPhase1],UBtoDF[depthPhase1]);
293

  
294
		if ((d2 = SolverCoordCube.getPruning(SolverCoordCube.Slice_URtoDF_Parity_Prun,
295
				(SolverCoordCube.N_SLICE2 * URtoDF[depthPhase1] + FRtoBR[depthPhase1]) * 2 + parity[depthPhase1])) > maxDepthPhase2)
296
			return -1;
297

  
298
		if ((minDistPhase2[depthPhase1] = Math.max(d1, d2)) == 0)// already solved
299
			return depthPhase1;
300

  
301
		// now set up search
302
		int depthPhase2 = 1;
303
		int n = depthPhase1;
304
		boolean busy = false;
305
		po[depthPhase1] = 0;
306
		ax[depthPhase1] = 0;
307
		minDistPhase2[n + 1] = 1; // else failure for depthPhase2=1, n=0
308
		// end initialization
309

  
310
		do
311
		  {
312
			do
313
			  {
314
				if ((depthPhase1 + depthPhase2 - n > minDistPhase2[n + 1]) && !busy)
315
				  {
316
					if (ax[n] == 0 || ax[n] == 3)// Initialize next move
317
					  {
318
						ax[++n] = 1;
319
						po[n] = 2;
320
					  }
321
					else
322
					  {
323
						ax[++n] = 0;
324
						po[n] = 1;
325
					  }
326
				  }
327
				else if ((ax[n] == 0 || ax[n] == 3) ? (++po[n] > 3) : ((po[n] = po[n] + 2) > 3))
328
				  {
329
					do
330
					  {
331
						if (++ax[n] > 5)
332
						  {
333
							if (n == depthPhase1)
334
							  {
... This diff was truncated because it exceeds the maximum size that can be displayed.

Also available in: Unified diff