15 |
15 |
import org.distorted.objectlib.main.ObjectSignatures;
|
16 |
16 |
import org.distorted.objectlib.main.TwistyObject;
|
17 |
17 |
import org.distorted.objectlib.tablebases.ImplementedTablebasesList;
|
|
18 |
import org.distorted.objectlib.tablebases.TablebaseHelpers;
|
18 |
19 |
import org.distorted.objectlib.tablebases.TablebasesAbstract;
|
19 |
20 |
|
20 |
21 |
///////////////////////////////////////////////////////////////////////////////////////////////////
|
... | ... | |
42 |
43 |
private static final int ERROR_TWO_CENTERS = -17;
|
43 |
44 |
private static final int ERROR_TWO_CORNERS = -18;
|
44 |
45 |
|
|
46 |
private static final int ERROR_IMPOSSIBLE = -19;
|
|
47 |
|
45 |
48 |
private TablebasesAbstract mSolver;
|
46 |
|
private int[] mFaceColors;
|
|
49 |
private final int[] mFaceColors;
|
47 |
50 |
|
48 |
51 |
///////////////////////////////////////////////////////////////////////////////////////////////////
|
49 |
52 |
|
50 |
53 |
public SolverSkewb(Resources res, TwistyObject object)
|
51 |
54 |
{
|
52 |
55 |
super(res,object);
|
|
56 |
mFaceColors = new int[6];
|
53 |
57 |
}
|
54 |
58 |
|
55 |
59 |
///////////////////////////////////////////////////////////////////////////////////////////////////
|
56 |
60 |
|
57 |
61 |
private void getCorners(TwistyObject object, int[][] corners)
|
58 |
62 |
{
|
|
63 |
for(int i=0; i<8; i++)
|
|
64 |
for(int j=0; j<3; j++)
|
|
65 |
corners[i][j] = object.getCubitFaceStickerIndex(i,j);
|
|
66 |
}
|
|
67 |
|
|
68 |
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
69 |
|
|
70 |
private void getCenters(TwistyObject object, int[] centers)
|
|
71 |
{
|
|
72 |
int[] map = {12,13,10,11,8,9};
|
59 |
73 |
|
|
74 |
for(int i=0; i<6; i++)
|
|
75 |
centers[i] = object.getCubitFaceStickerIndex(map[i],0) - 6;
|
60 |
76 |
}
|
61 |
77 |
|
62 |
78 |
///////////////////////////////////////////////////////////////////////////////////////////////////
|
63 |
79 |
|
64 |
|
private int checkAllCornersPresent(int[][] corners)
|
|
80 |
private int commonCornerColor(int[] c1, int[] c2)
|
|
81 |
{
|
|
82 |
int theSame = 0;
|
|
83 |
int index = 0;
|
|
84 |
|
|
85 |
for(int i=0; i<3; i++)
|
|
86 |
for(int j=0; j<3; j++)
|
|
87 |
if( c1[i]==c2[j] )
|
|
88 |
{
|
|
89 |
index = i;
|
|
90 |
theSame++;
|
|
91 |
}
|
|
92 |
|
|
93 |
return theSame==1 ? c1[index] : ERROR_CORNERS_CANNOT;
|
|
94 |
}
|
|
95 |
|
|
96 |
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
97 |
|
|
98 |
private int computeFaceColors(int[][] corners, int[] output)
|
65 |
99 |
{
|
|
100 |
final int[][] map = { {0,3},{5,6},{0,5},{6,3},{0,6},{3,5} };
|
|
101 |
|
|
102 |
for(int i=0; i<6; i++)
|
|
103 |
{
|
|
104 |
int c1 = map[i][0];
|
|
105 |
int c2 = map[i][1];
|
|
106 |
output[i] = commonCornerColor(corners[c1],corners[c2]);
|
|
107 |
if( output[i]<0 ) return ERROR_CORNERS_CANNOT;
|
|
108 |
}
|
|
109 |
|
66 |
110 |
return 0;
|
67 |
111 |
}
|
68 |
112 |
|
69 |
113 |
///////////////////////////////////////////////////////////////////////////////////////////////////
|
70 |
114 |
|
71 |
|
private int[] computeFaceColors(int[][] corners)
|
|
115 |
private boolean cornerIs(int[] corner, int c0, int c1, int c2)
|
72 |
116 |
{
|
73 |
|
return null;
|
|
117 |
return ( (corner[0]==c0 && corner[1]==c1 && corner[2]==c2 ) ||
|
|
118 |
(corner[1]==c0 && corner[2]==c1 && corner[0]==c2 ) ||
|
|
119 |
(corner[2]==c0 && corner[0]==c1 && corner[1]==c2 ) );
|
74 |
120 |
}
|
75 |
121 |
|
76 |
122 |
///////////////////////////////////////////////////////////////////////////////////////////////////
|
77 |
123 |
|
78 |
|
private void getCenters(TwistyObject object, int[] centers)
|
|
124 |
private int checkAllCornersPresent(int[][] corners)
|
79 |
125 |
{
|
|
126 |
boolean[] present = new boolean[8];
|
|
127 |
|
|
128 |
for(int i=0; i<8; i++)
|
|
129 |
{
|
|
130 |
if( cornerIs(corners[i],4,2,0) ) present[0]=true;
|
|
131 |
if( cornerIs(corners[i],2,5,0) ) present[1]=true;
|
|
132 |
if( cornerIs(corners[i],3,4,0) ) present[2]=true;
|
|
133 |
if( cornerIs(corners[i],5,3,0) ) present[3]=true;
|
|
134 |
if( cornerIs(corners[i],1,2,4) ) present[4]=true;
|
|
135 |
if( cornerIs(corners[i],5,2,1) ) present[5]=true;
|
|
136 |
if( cornerIs(corners[i],4,3,1) ) present[6]=true;
|
|
137 |
if( cornerIs(corners[i],1,3,5) ) present[7]=true;
|
|
138 |
}
|
|
139 |
|
|
140 |
if( !present[0] ) return ERROR_CORNER_024_MISSING;
|
|
141 |
if( !present[1] ) return ERROR_CORNER_025_MISSING;
|
|
142 |
if( !present[2] ) return ERROR_CORNER_034_MISSING;
|
|
143 |
if( !present[3] ) return ERROR_CORNER_035_MISSING;
|
|
144 |
if( !present[4] ) return ERROR_CORNER_124_MISSING;
|
|
145 |
if( !present[5] ) return ERROR_CORNER_125_MISSING;
|
|
146 |
if( !present[6] ) return ERROR_CORNER_134_MISSING;
|
|
147 |
if( !present[7] ) return ERROR_CORNER_135_MISSING;
|
80 |
148 |
|
|
149 |
return 0;
|
81 |
150 |
}
|
82 |
151 |
|
83 |
152 |
///////////////////////////////////////////////////////////////////////////////////////////////////
|
84 |
153 |
|
85 |
154 |
private int checkAllCentersPresent(int[] centers)
|
86 |
155 |
{
|
|
156 |
boolean[] present = new boolean[6];
|
|
157 |
for(int i=0; i<6; i++) present[centers[i]]= true;
|
|
158 |
|
|
159 |
if( !present[0] ) return ERROR_CENTER_4_MISSING;
|
|
160 |
if( !present[1] ) return ERROR_CENTER_5_MISSING;
|
|
161 |
if( !present[2] ) return ERROR_CENTER_2_MISSING;
|
|
162 |
if( !present[3] ) return ERROR_CENTER_3_MISSING;
|
|
163 |
if( !present[4] ) return ERROR_CENTER_0_MISSING;
|
|
164 |
if( !present[5] ) return ERROR_CENTER_1_MISSING;
|
|
165 |
|
|
166 |
return 0;
|
|
167 |
}
|
|
168 |
|
|
169 |
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
170 |
// free corners: 1,2,4,7
|
|
171 |
|
|
172 |
private int retCornerPermutation(int[] perm, int[][] corners)
|
|
173 |
{
|
|
174 |
int[] map = {1,2,4,7};
|
|
175 |
|
|
176 |
perm[0] = 0;
|
|
177 |
perm[1] = -1;
|
|
178 |
perm[2] = -1;
|
|
179 |
perm[3] = 3;
|
|
180 |
perm[4] = -1;
|
|
181 |
perm[5] = 5;
|
|
182 |
perm[6] = 6;
|
|
183 |
perm[7] = -1;
|
|
184 |
|
|
185 |
for(int i=0; i<4; i++)
|
|
186 |
{
|
|
187 |
int index = map[i];
|
|
188 |
int[] cor = corners[index];
|
|
189 |
|
|
190 |
if( cornerIs(cor,2,5,0) ) perm[1] = index;
|
|
191 |
if( cornerIs(cor,3,4,0) ) perm[2] = index;
|
|
192 |
if( cornerIs(cor,1,2,4) ) perm[4] = index;
|
|
193 |
if( cornerIs(cor,1,3,5) ) perm[7] = index;
|
|
194 |
}
|
|
195 |
|
|
196 |
if( perm[1]==-1 ) return ERROR_CORNER_025_MISSING;
|
|
197 |
if( perm[2]==-1 ) return ERROR_CORNER_034_MISSING;
|
|
198 |
if( perm[4]==-1 ) return ERROR_CORNER_124_MISSING;
|
|
199 |
if( perm[7]==-1 ) return ERROR_CORNER_135_MISSING;
|
|
200 |
|
87 |
201 |
return 0;
|
88 |
202 |
}
|
89 |
203 |
|
|
204 |
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
205 |
|
|
206 |
private void fillCornerTwists(int[] output, int[][] corners, int[] perm)
|
|
207 |
{
|
|
208 |
final int[] map = { 4,2,3,5,1,5,4,1 };
|
|
209 |
|
|
210 |
for(int i=0; i<8; i++)
|
|
211 |
{
|
|
212 |
int color = mFaceColors[map[i]];
|
|
213 |
int[] c = corners[perm[i]];
|
|
214 |
|
|
215 |
if( c[0]==color ) output[i] = 0;
|
|
216 |
else if( c[1]==color ) output[i] = 1;
|
|
217 |
else output[i] = 2;
|
|
218 |
}
|
|
219 |
}
|
|
220 |
|
|
221 |
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
222 |
|
|
223 |
private int computeCenterTwist(int p1, int p2)
|
|
224 |
{
|
|
225 |
if( p1==1 )
|
|
226 |
{
|
|
227 |
switch(p2)
|
|
228 |
{
|
|
229 |
case 2: return 2;
|
|
230 |
case 4: return 1;
|
|
231 |
case 7: return 0;
|
|
232 |
}
|
|
233 |
}
|
|
234 |
if( p1==2 )
|
|
235 |
{
|
|
236 |
switch(p2)
|
|
237 |
{
|
|
238 |
case 1: return 2;
|
|
239 |
case 4: return 0;
|
|
240 |
case 7: return 1;
|
|
241 |
}
|
|
242 |
}
|
|
243 |
if( p1==4 )
|
|
244 |
{
|
|
245 |
switch(p2)
|
|
246 |
{
|
|
247 |
case 1: return 1;
|
|
248 |
case 2: return 0;
|
|
249 |
case 7: return 2;
|
|
250 |
}
|
|
251 |
}
|
|
252 |
if( p1==7 )
|
|
253 |
{
|
|
254 |
switch(p2)
|
|
255 |
{
|
|
256 |
case 1: return 0;
|
|
257 |
case 2: return 1;
|
|
258 |
case 4: return 2;
|
|
259 |
}
|
|
260 |
}
|
|
261 |
|
|
262 |
return ERROR_IMPOSSIBLE;
|
|
263 |
}
|
|
264 |
|
|
265 |
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
266 |
|
|
267 |
private int positionOfFirstCorner(int[] perm, int[] twist)
|
|
268 |
{
|
|
269 |
int total_fixed_twist = twist[0]+twist[3]+twist[5]+twist[6];
|
|
270 |
|
|
271 |
int twist_42 = computeCenterTwist(perm[4],perm[2]);
|
|
272 |
int twist_21 = computeCenterTwist(perm[2],perm[1]);
|
|
273 |
|
|
274 |
if( twist_42<0 || twist_21<0 ) return ERROR_IMPOSSIBLE;
|
|
275 |
|
|
276 |
|
|
277 |
android.util.Log.e("D", "twist42 "+twist_42+" twist21 "+twist_21+" total: "+total_fixed_twist);
|
|
278 |
|
|
279 |
if( (twist_21-twist_42+1)%3 != 0 ) return ERROR_TWO_CORNERS;
|
|
280 |
if( (total_fixed_twist-twist_42)%3 !=0 ) return ERROR_CORNER_TWISTED;
|
|
281 |
|
|
282 |
switch(perm[1])
|
|
283 |
{
|
|
284 |
case 1: return 0;
|
|
285 |
case 2: return 1;
|
|
286 |
case 4: return 2;
|
|
287 |
case 7: return 3;
|
|
288 |
}
|
|
289 |
|
|
290 |
return ERROR_IMPOSSIBLE;
|
|
291 |
}
|
|
292 |
|
90 |
293 |
///////////////////////////////////////////////////////////////////////////////////////////////////
|
91 |
294 |
|
92 |
295 |
public int tablebaseIndex(TwistyObject object)
|
93 |
296 |
{
|
94 |
|
int[][] corners = new int[6][3];
|
95 |
|
int[] centers = new int[6];
|
96 |
|
int[] corner_twist= new int[6];
|
|
297 |
int[][] corners= new int[8][3];
|
|
298 |
int[] centers = new int[6];
|
|
299 |
int[] twist = new int[8];
|
|
300 |
int[] perm = new int[8];
|
97 |
301 |
|
98 |
302 |
getCorners(object,corners);
|
99 |
303 |
|
100 |
|
int result1 = checkAllCornersPresent(corners);
|
|
304 |
int result1 = computeFaceColors(corners,mFaceColors);
|
101 |
305 |
if( result1<0 ) return result1;
|
102 |
306 |
|
103 |
|
mFaceColors = computeFaceColors(corners);
|
|
307 |
int result2 = checkAllCornersPresent(corners);
|
|
308 |
if( result2<0 ) return result2;
|
104 |
309 |
|
105 |
310 |
getCenters(object,centers);
|
106 |
|
int result2 = checkAllCentersPresent(centers);
|
107 |
|
if( result2<0 ) return result2;
|
|
311 |
int result3 = checkAllCentersPresent(centers);
|
|
312 |
if( result3<0 ) return result3;
|
|
313 |
/*
|
|
314 |
for(int i=0; i<8; i++)
|
|
315 |
for(int j=0; j<3; j++) android.util.Log.e("D", "corner "+i+" face "+j+" : "+corners[i][j]);
|
108 |
316 |
|
109 |
|
// TODO...
|
|
317 |
for(int i=0; i<6; i++) android.util.Log.e("D", "center "+i+" : "+centers[i]);
|
|
318 |
for(int i=0; i<6; i++) android.util.Log.e("D", "face "+i+" : "+mFaceColors[i]);
|
|
319 |
*/
|
|
320 |
if( !TablebaseHelpers.permutationIsEven(centers) ) return ERROR_TWO_CENTERS;
|
|
321 |
int center_perm_num = TablebaseHelpers.computeEvenPermutationNum(centers);
|
110 |
322 |
|
111 |
|
return 0;
|
|
323 |
int result4 = retCornerPermutation(perm,corners);
|
|
324 |
if( result4<0 ) return result4;
|
|
325 |
|
|
326 |
fillCornerTwists(twist,corners,perm);
|
|
327 |
|
|
328 |
for(int i=0; i<8; i++) android.util.Log.e("D", "perm "+i+" : "+perm[i]);
|
|
329 |
for(int i=0; i<8; i++) android.util.Log.e("D", "twist "+i+" : "+twist[i]);
|
|
330 |
|
|
331 |
int totalTwist = 0;
|
|
332 |
for(int i=0; i<8; i++) totalTwist += twist[i];
|
|
333 |
|
|
334 |
android.util.Log.e("D", "total twist "+totalTwist);
|
|
335 |
|
|
336 |
if( (totalTwist%3)!=0 ) return ERROR_CORNER_TWISTED;
|
|
337 |
|
|
338 |
int total = twist[0]+ 3*(twist[1]+ 3*(twist[2]+ 3*(twist[3]+ 3*(twist[4]+ 3*(twist[5]+ 3*twist[6])))));
|
|
339 |
|
|
340 |
int corner1 = positionOfFirstCorner(perm,twist);
|
|
341 |
if( corner1<0 ) return ERROR_TWO_CORNERS;
|
|
342 |
|
|
343 |
android.util.Log.e("D", "corner1: "+corner1+" center perm: "+center_perm_num+" twist: "+total);
|
|
344 |
|
|
345 |
return corner1 + 4*(center_perm_num + 360*total);
|
112 |
346 |
}
|
113 |
347 |
|
114 |
348 |
///////////////////////////////////////////////////////////////////////////////////////////////////
|
Progess with Skewb solver.