Project

General

Profile

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

magiccube / src / main / java / org / distorted / solvers / SolverSkewb.java @ b4f45fdc

1 18354673 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
2
// Copyright 2023 Leszek Koltunski                                                               //
3
//                                                                                               //
4
// This file is part of Magic Cube.                                                              //
5
//                                                                                               //
6
// Magic Cube is proprietary software licensed under an EULA which you should have received      //
7
// along with the code. If not, check https://distorted.org/magic/License-Magic-Cube.html        //
8
///////////////////////////////////////////////////////////////////////////////////////////////////
9
10
package org.distorted.solvers;
11
12 b4f45fdc Leszek Koltunski
import static org.distorted.objectlib.tablebases.TBSkewb.FREE;
13
14 18354673 Leszek Koltunski
import android.content.res.Resources;
15
16
import org.distorted.main.R;
17
import org.distorted.objectlib.main.ObjectSignatures;
18
import org.distorted.objectlib.main.TwistyObject;
19
import org.distorted.objectlib.tablebases.ImplementedTablebasesList;
20 c76be0a6 Leszek Koltunski
import org.distorted.objectlib.tablebases.TBSkewb;
21 cff92952 Leszek Koltunski
import org.distorted.objectlib.tablebases.TablebaseHelpers;
22 18354673 Leszek Koltunski
import org.distorted.objectlib.tablebases.TablebasesAbstract;
23
24
///////////////////////////////////////////////////////////////////////////////////////////////////
25
26
public class SolverSkewb extends SolverTablebase
27
{
28
  private static final int ERROR_CORNER_135_MISSING = -1;
29
  private static final int ERROR_CORNER_134_MISSING = -2;
30
  private static final int ERROR_CORNER_125_MISSING = -3;
31
  private static final int ERROR_CORNER_124_MISSING = -4;
32
  private static final int ERROR_CORNER_035_MISSING = -5;
33
  private static final int ERROR_CORNER_034_MISSING = -6;
34
  private static final int ERROR_CORNER_025_MISSING = -7;
35
  private static final int ERROR_CORNER_024_MISSING = -8;
36
37
  private static final int ERROR_CENTER_0_MISSING   = -9;
38
  private static final int ERROR_CENTER_1_MISSING   = -10;
39
  private static final int ERROR_CENTER_2_MISSING   = -11;
40
  private static final int ERROR_CENTER_3_MISSING   = -12;
41
  private static final int ERROR_CENTER_4_MISSING   = -13;
42
  private static final int ERROR_CENTER_5_MISSING   = -14;
43
44
  private static final int ERROR_CORNERS_CANNOT     = -15;
45
  private static final int ERROR_CORNER_TWISTED     = -16;
46
  private static final int ERROR_TWO_CENTERS        = -17;
47
  private static final int ERROR_TWO_CORNERS        = -18;
48
49
  private TablebasesAbstract mSolver;
50 cff92952 Leszek Koltunski
  private final int[] mFaceColors;
51 18354673 Leszek Koltunski
52
///////////////////////////////////////////////////////////////////////////////////////////////////
53
54
  public SolverSkewb(Resources res, TwistyObject object)
55
    {
56
    super(res,object);
57 cff92952 Leszek Koltunski
    mFaceColors = new int[6];
58 18354673 Leszek Koltunski
    }
59
60
///////////////////////////////////////////////////////////////////////////////////////////////////
61
62
  private void getCorners(TwistyObject object, int[][] corners)
63
    {
64 cff92952 Leszek Koltunski
    for(int i=0; i<8; i++)
65
      for(int j=0; j<3; j++)
66
        corners[i][j] = object.getCubitFaceStickerIndex(i,j);
67
    }
68
69
///////////////////////////////////////////////////////////////////////////////////////////////////
70
71
  private void getCenters(TwistyObject object, int[] centers)
72
    {
73 b4f45fdc Leszek Koltunski
    final int[] face_colors = {4,5,2,3,0,1};
74
    int[] tmp = new int[6];
75 18354673 Leszek Koltunski
76 cff92952 Leszek Koltunski
    for(int i=0; i<6; i++)
77 b4f45fdc Leszek Koltunski
      {
78
      int color = object.getCubitFaceStickerIndex(i+8,0) - 6;
79
      tmp[i] = face_colors[color];
80
      }
81
82
    TablebaseHelpers.invertPermutation(tmp,centers);
83 18354673 Leszek Koltunski
    }
84
85
///////////////////////////////////////////////////////////////////////////////////////////////////
86
87 cff92952 Leszek Koltunski
  private int commonCornerColor(int[] c1, int[] c2)
88 18354673 Leszek Koltunski
    {
89 cff92952 Leszek Koltunski
    int theSame = 0;
90
    int index   = 0;
91
92
    for(int i=0; i<3; i++)
93
      for(int j=0; j<3; j++)
94
        if( c1[i]==c2[j] )
95
          {
96
          index = i;
97
          theSame++;
98
          }
99
100
    return theSame==1 ? c1[index] : ERROR_CORNERS_CANNOT;
101
    }
102
103
///////////////////////////////////////////////////////////////////////////////////////////////////
104
105
  private int computeFaceColors(int[][] corners, int[] output)
106
    {
107
    final int[][] map = { {0,3},{5,6},{0,5},{6,3},{0,6},{3,5} };
108
109
    for(int i=0; i<6; i++)
110
      {
111
      int c1 = map[i][0];
112
      int c2 = map[i][1];
113
      output[i] = commonCornerColor(corners[c1],corners[c2]);
114
      if( output[i]<0 ) return ERROR_CORNERS_CANNOT;
115
      }
116
117 18354673 Leszek Koltunski
    return 0;
118
    }
119
120
///////////////////////////////////////////////////////////////////////////////////////////////////
121
122 cff92952 Leszek Koltunski
  private boolean cornerIs(int[] corner, int c0, int c1, int c2)
123 18354673 Leszek Koltunski
    {
124 cff92952 Leszek Koltunski
    return ( (corner[0]==c0 && corner[1]==c1 && corner[2]==c2 ) ||
125
             (corner[1]==c0 && corner[2]==c1 && corner[0]==c2 ) ||
126
             (corner[2]==c0 && corner[0]==c1 && corner[1]==c2 )  );
127 18354673 Leszek Koltunski
    }
128
129
///////////////////////////////////////////////////////////////////////////////////////////////////
130
131 cff92952 Leszek Koltunski
  private int checkAllCornersPresent(int[][] corners)
132 18354673 Leszek Koltunski
    {
133 cff92952 Leszek Koltunski
    boolean[] present = new boolean[8];
134
135
    for(int i=0; i<8; i++)
136
      {
137
      if( cornerIs(corners[i],4,2,0) ) present[0]=true;
138
      if( cornerIs(corners[i],2,5,0) ) present[1]=true;
139
      if( cornerIs(corners[i],3,4,0) ) present[2]=true;
140
      if( cornerIs(corners[i],5,3,0) ) present[3]=true;
141
      if( cornerIs(corners[i],1,2,4) ) present[4]=true;
142
      if( cornerIs(corners[i],5,2,1) ) present[5]=true;
143
      if( cornerIs(corners[i],4,3,1) ) present[6]=true;
144
      if( cornerIs(corners[i],1,3,5) ) present[7]=true;
145
      }
146
147
    if( !present[0] ) return ERROR_CORNER_024_MISSING;
148
    if( !present[1] ) return ERROR_CORNER_025_MISSING;
149
    if( !present[2] ) return ERROR_CORNER_034_MISSING;
150
    if( !present[3] ) return ERROR_CORNER_035_MISSING;
151
    if( !present[4] ) return ERROR_CORNER_124_MISSING;
152
    if( !present[5] ) return ERROR_CORNER_125_MISSING;
153
    if( !present[6] ) return ERROR_CORNER_134_MISSING;
154
    if( !present[7] ) return ERROR_CORNER_135_MISSING;
155 18354673 Leszek Koltunski
156 cff92952 Leszek Koltunski
    return 0;
157 18354673 Leszek Koltunski
    }
158
159
///////////////////////////////////////////////////////////////////////////////////////////////////
160
161
  private int checkAllCentersPresent(int[] centers)
162
    {
163 cff92952 Leszek Koltunski
    boolean[] present = new boolean[6];
164
    for(int i=0; i<6; i++) present[centers[i]]= true;
165
166
    if( !present[0] ) return ERROR_CENTER_4_MISSING;
167
    if( !present[1] ) return ERROR_CENTER_5_MISSING;
168
    if( !present[2] ) return ERROR_CENTER_2_MISSING;
169
    if( !present[3] ) return ERROR_CENTER_3_MISSING;
170
    if( !present[4] ) return ERROR_CENTER_0_MISSING;
171
    if( !present[5] ) return ERROR_CENTER_1_MISSING;
172
173
    return 0;
174
    }
175
176
///////////////////////////////////////////////////////////////////////////////////////////////////
177
178 14cf0761 Leszek Koltunski
  private int retFreeCornerPermutation(int[] perm, int[][] corners)
179 cff92952 Leszek Koltunski
    {
180 14cf0761 Leszek Koltunski
    perm[0] = -1;
181 cff92952 Leszek Koltunski
    perm[1] = -1;
182
    perm[2] = -1;
183 14cf0761 Leszek Koltunski
    perm[3] = -1;
184 cff92952 Leszek Koltunski
185
    for(int i=0; i<4; i++)
186
      {
187 b4f45fdc Leszek Koltunski
      int[] cor = corners[FREE[i]];
188 cff92952 Leszek Koltunski
189 14cf0761 Leszek Koltunski
      if( cornerIs(cor,2,5,0) ) perm[0] = i;
190
      if( cornerIs(cor,3,4,0) ) perm[1] = i;
191
      if( cornerIs(cor,1,2,4) ) perm[2] = i;
192
      if( cornerIs(cor,1,3,5) ) perm[3] = i;
193 cff92952 Leszek Koltunski
      }
194
195 14cf0761 Leszek Koltunski
    if( perm[0]==-1 ) return ERROR_CORNER_025_MISSING;
196
    if( perm[1]==-1 ) return ERROR_CORNER_034_MISSING;
197
    if( perm[2]==-1 ) return ERROR_CORNER_124_MISSING;
198
    if( perm[3]==-1 ) return ERROR_CORNER_135_MISSING;
199 cff92952 Leszek Koltunski
200 18354673 Leszek Koltunski
    return 0;
201
    }
202
203 14cf0761 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
204 cff92952 Leszek Koltunski
205 14cf0761 Leszek Koltunski
  private int retCornerPerm(int index, int[] perm)
206
    {
207
    switch(index)
208
      {
209
      case 0: return 0;
210 b4f45fdc Leszek Koltunski
      case 1: return FREE[perm[0]];
211
      case 2: return FREE[perm[1]];
212 14cf0761 Leszek Koltunski
      case 3: return 3;
213 b4f45fdc Leszek Koltunski
      case 4: return FREE[perm[2]];
214 14cf0761 Leszek Koltunski
      case 5: return 5;
215
      case 6: return 6;
216 b4f45fdc Leszek Koltunski
      case 7: return FREE[perm[3]];
217 14cf0761 Leszek Koltunski
      }
218 cff92952 Leszek Koltunski
219 14cf0761 Leszek Koltunski
    return -1;
220
    }
221 cff92952 Leszek Koltunski
222 14cf0761 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
223 cff92952 Leszek Koltunski
224 14cf0761 Leszek Koltunski
  private void computeCornerQuats(int[] quats, int[][] corners, int[] perm)
225
    {
226
    final int[] map = { 4,2,3,5,1,5,4,1 };
227 b4f45fdc Leszek Koltunski
    int[] twist = new int[8];
228 cff92952 Leszek Koltunski
229 14cf0761 Leszek Koltunski
    for(int i=0; i<8; i++)
230 cff92952 Leszek Koltunski
      {
231 14cf0761 Leszek Koltunski
      int color = mFaceColors[map[i]];
232
      int[] c = corners[retCornerPerm(i,perm)];
233
234 b4f45fdc Leszek Koltunski
           if( c[0]==color ) twist[i] = 0;
235
      else if( c[1]==color ) twist[i] = 1;
236
      else                   twist[i] = 2;
237 cff92952 Leszek Koltunski
      }
238
239 b4f45fdc Leszek Koltunski
    TBSkewb.fillInQuats(quats,perm,twist);
240 cff92952 Leszek Koltunski
    }
241
242 18354673 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
243
244
  public int tablebaseIndex(TwistyObject object)
245
    {
246 cff92952 Leszek Koltunski
    int[][] corners= new int[8][3];
247
    int[] centers  = new int[6];
248
    int[] twist    = new int[8];
249 14cf0761 Leszek Koltunski
    int[] freePerm = new int[4];
250
    int[] quats    = new int[8];
251 18354673 Leszek Koltunski
252
    getCorners(object,corners);
253
254 cff92952 Leszek Koltunski
    int result1 = computeFaceColors(corners,mFaceColors);
255 18354673 Leszek Koltunski
    if( result1<0 ) return result1;
256
257 cff92952 Leszek Koltunski
    int result2 = checkAllCornersPresent(corners);
258
    if( result2<0 ) return result2;
259 18354673 Leszek Koltunski
260
    getCenters(object,centers);
261 cff92952 Leszek Koltunski
    int result3 = checkAllCentersPresent(centers);
262
    if( result3<0 ) return result3;
263 18354673 Leszek Koltunski
264 cff92952 Leszek Koltunski
    if( !TablebaseHelpers.permutationIsEven(centers) ) return ERROR_TWO_CENTERS;
265
    int center_perm_num = TablebaseHelpers.computeEvenPermutationNum(centers);
266 18354673 Leszek Koltunski
267 14cf0761 Leszek Koltunski
    int result4 = retFreeCornerPermutation(freePerm,corners);
268 cff92952 Leszek Koltunski
    if( result4<0 ) return result4;
269
270 14cf0761 Leszek Koltunski
    computeCornerQuats(quats,corners,freePerm);
271 c76be0a6 Leszek Koltunski
    TBSkewb.computeCornerTwists(twist,quats);
272 b4f45fdc Leszek Koltunski
273
    int total = 0;
274
    for(int i=0; i<4; i++) total += twist[FREE[i]];
275 14cf0761 Leszek Koltunski
    if( (total%3)!=0 ) return ERROR_CORNER_TWISTED;
276
    int totalTwist = twist[0]+ 3*(twist[1]+ 3*(twist[2]+ 3*(twist[3]+ 3*(twist[4]+ 3*(twist[5]+ 3*twist[6])))));
277 cff92952 Leszek Koltunski
278 4fd36883 Leszek Koltunski
    int locationOfFree0 = TBSkewb.computeLocation(0,quats[1]);
279 cff92952 Leszek Koltunski
280 14cf0761 Leszek Koltunski
    return center_perm_num+ 360*(totalTwist + 2187*locationOfFree0);
281 18354673 Leszek Koltunski
    }
282
283
///////////////////////////////////////////////////////////////////////////////////////////////////
284
285
  private int getColorIndex2(int face)
286
    {
287
    switch(mFaceColors[face])
288
      {
289
      case 0: return R.string.color_yellow2;
290
      case 1: return R.string.color_white2;
291
      case 2: return R.string.color_blue2;
292
      case 3: return R.string.color_green2;
293
      case 4: return R.string.color_red2;
294
      case 5: return R.string.color_orange2;
295
      }
296
297
    return -1;
298
    }
299
300
///////////////////////////////////////////////////////////////////////////////////////////////////
301
302
  private int getColorIndex3(int face)
303
    {
304
    switch(mFaceColors[face])
305
      {
306
      case 0: return R.string.color_yellow3;
307
      case 1: return R.string.color_white3;
308
      case 2: return R.string.color_blue3;
309
      case 3: return R.string.color_green3;
310
      case 4: return R.string.color_red3;
311
      case 5: return R.string.color_orange3;
312
      }
313
314
    return -1;
315
    }
316
317
///////////////////////////////////////////////////////////////////////////////////////////////////
318
319
  private int getColorIndex4(int face)
320
    {
321
    switch(mFaceColors[face])
322
      {
323
      case 0: return R.string.color_yellow4;
324
      case 1: return R.string.color_white4;
325
      case 2: return R.string.color_blue4;
326
      case 3: return R.string.color_green4;
327
      case 4: return R.string.color_red4;
328
      case 5: return R.string.color_orange4;
329
      }
330
331
    return -1;
332
    }
333
334
///////////////////////////////////////////////////////////////////////////////////////////////////
335
336
  private String cornerError(Resources res, int face0, int face1, int face2)
337
    {
338
    int j0 = getColorIndex3(face0);
339
    int j1 = getColorIndex3(face1);
340
    int j2 = getColorIndex4(face2);
341
342
    String c0 = res.getString(j0);
343
    String c1 = res.getString(j1);
344
    String c2 = res.getString(j2);
345
346
    return res.getString(R.string.solver_generic_missing_corner,c0,c1,c2);
347
    }
348
349
///////////////////////////////////////////////////////////////////////////////////////////////////
350
351
  private String centerError(Resources res, int face)
352
    {
353
    int color = getColorIndex2(face);
354
    String clr= res.getString(color);
355
    return res.getString(R.string.solver_generic_missing_center,clr);
356
    }
357
358
///////////////////////////////////////////////////////////////////////////////////////////////////
359
360
  public String error(int index, Resources res)
361
    {
362
    switch(index)
363
      {
364
      case ERROR_CORNER_135_MISSING: return cornerError(res,1,3,5);
365
      case ERROR_CORNER_134_MISSING: return cornerError(res,1,3,4);
366
      case ERROR_CORNER_125_MISSING: return cornerError(res,1,2,5);
367
      case ERROR_CORNER_124_MISSING: return cornerError(res,1,2,4);
368
      case ERROR_CORNER_035_MISSING: return cornerError(res,0,3,5);
369
      case ERROR_CORNER_034_MISSING: return cornerError(res,0,3,4);
370
      case ERROR_CORNER_025_MISSING: return cornerError(res,0,2,5);
371
      case ERROR_CORNER_024_MISSING: return cornerError(res,0,2,4);
372
373
      case ERROR_CENTER_0_MISSING  : return centerError(res,0);
374
      case ERROR_CENTER_1_MISSING  : return centerError(res,1);
375
      case ERROR_CENTER_2_MISSING  : return centerError(res,2);
376
      case ERROR_CENTER_3_MISSING  : return centerError(res,3);
377
      case ERROR_CENTER_4_MISSING  : return centerError(res,4);
378
      case ERROR_CENTER_5_MISSING  : return centerError(res,5);
379
380
      case ERROR_CORNERS_CANNOT    : return res.getString(R.string.solver_generic_corners_cannot);
381
      case ERROR_CORNER_TWISTED    : return res.getString(R.string.solver_generic_corner_twist);
382
      case ERROR_TWO_CENTERS       : return res.getString(R.string.solver_generic_two_centers);
383
      case ERROR_TWO_CORNERS       : return res.getString(R.string.solver_generic_two_corners);
384
      }
385
386
    return null;
387
    }
388
389
///////////////////////////////////////////////////////////////////////////////////////////////////
390
391
  public int[][] solution(int index, Resources res)
392
    {
393
    if( mSolver==null )
394
      {
395 4fd36883 Leszek Koltunski
      mSolver = ImplementedTablebasesList.createPacked(res,ObjectSignatures.SKEW_2);
396 18354673 Leszek Koltunski
      }
397
398
    return mSolver!=null ? mSolver.solution(index,null) : null;
399
    }
400
}