Project

General

Profile

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

magiccube / src / main / java / org / distorted / solvers / SolverSkewbDiamond.java @ db4775f7

1
///////////////////////////////////////////////////////////////////////////////////////////////////
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
import android.content.res.Resources;
13

    
14
import org.distorted.main.R;
15
import org.distorted.objectlib.main.ObjectSignatures;
16
import org.distorted.objectlib.main.TwistyObject;
17
import org.distorted.objectlib.tablebases.ImplementedTablebasesList;
18
import org.distorted.objectlib.tablebases.TablebaseHelpers;
19
import org.distorted.objectlib.tablebases.TablebasesAbstract;
20

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

    
23
public class SolverSkewbDiamond extends SolverTablebase
24
{
25
  private static final int ERROR_CORNER_FR_MISSING = -1;
26
  private static final int ERROR_CORNER_BR_MISSING = -2;
27
  private static final int ERROR_CORNER_BL_MISSING = -3;
28
  private static final int ERROR_CORNER_FL_MISSING = -4;
29
  private static final int ERROR_CORNER_TO_MISSING = -5;
30
  private static final int ERROR_CORNER_BO_MISSING = -6;
31

    
32
  private static final int ERROR_CENTER_0_MISSING = -7;
33
  private static final int ERROR_CENTER_1_MISSING = -8;
34
  private static final int ERROR_CENTER_2_MISSING = -9;
35
  private static final int ERROR_CENTER_3_MISSING = -10;
36
  private static final int ERROR_CENTER_4_MISSING = -11;
37
  private static final int ERROR_CENTER_5_MISSING = -12;
38
  private static final int ERROR_CENTER_6_MISSING = -13;
39
  private static final int ERROR_CENTER_7_MISSING = -14;
40

    
41
  private static final int ERROR_TWO_CORNERS      = -15;
42
  private static final int ERROR_TWO_CENTERS      = -16;
43
  private static final int ERROR_CORNER_TWIST     = -17;
44
  private static final int ERROR_CORNERS_CANNOT   = -18;
45

    
46
  private TablebasesAbstract mSolver;
47
  private final int[] mFaceColors;
48

    
49
  private static final int[] FREE_CENTERS = {0,2,5,7};
50

    
51
///////////////////////////////////////////////////////////////////////////////////////////////////
52

    
53
  public SolverSkewbDiamond(Resources res, TwistyObject object)
54
    {
55
    super(res,object);
56
    mFaceColors = new int[8];
57
    }
58

    
59
///////////////////////////////////////////////////////////////////////////////////////////////////
60

    
61
  private int retCorner(int[][] corners, int c1, int c2)
62
    {
63
    for(int i=0; i<6; i++)
64
      {
65
      int[] cor = corners[i];
66
      int twist = retCornerTwist(cor,c1,c2);
67
      if( twist>=0 ) return i;
68
      }
69

    
70
    return -1;
71
    }
72

    
73
///////////////////////////////////////////////////////////////////////////////////////////////////
74

    
75
  private int[] getCornersPermutation(int[][] corners)
76
    {
77
    int[] perm = new int[6];
78

    
79
    perm[0] = retCorner(corners,mFaceColors[1],mFaceColors[4]);
80
    perm[1] = retCorner(corners,mFaceColors[1],mFaceColors[6]);
81
    perm[2] = retCorner(corners,mFaceColors[3],mFaceColors[6]);
82
    perm[3] = retCorner(corners,mFaceColors[3],mFaceColors[4]);
83
    perm[4] = retCorner(corners,mFaceColors[1],mFaceColors[3]);
84
    perm[5] = retCorner(corners,mFaceColors[4],mFaceColors[6]);
85

    
86
    return perm;
87
    }
88

    
89
///////////////////////////////////////////////////////////////////////////////////////////////////
90

    
91
  private int computeCornerTwist(int[] corner, int color )
92
    {
93
    if( corner[3]==color ) return 0;
94
    if( corner[2]==color ) return 1;
95
    if( corner[1]==color ) return 2;
96
    if( corner[0]==color ) return 3;
97

    
98
    return -1;
99
    }
100

    
101
///////////////////////////////////////////////////////////////////////////////////////////////////
102

    
103
  private int[] getCornersTwist(int[] corners_perm, int[][] corners)
104
    {
105
    int[] twist = new int[6];
106

    
107
    twist[0] = computeCornerTwist( corners[corners_perm[0]], mFaceColors[1] );
108
    twist[1] = computeCornerTwist( corners[corners_perm[1]], mFaceColors[1] );
109
    twist[2] = computeCornerTwist( corners[corners_perm[2]], mFaceColors[3] );
110
    twist[3] = computeCornerTwist( corners[corners_perm[3]], mFaceColors[3] );
111
    twist[4] = computeCornerTwist( corners[corners_perm[4]], mFaceColors[1] );
112
    twist[5] = computeCornerTwist( corners[corners_perm[5]], mFaceColors[4] );
113

    
114
    return twist;
115
    }
116

    
117
///////////////////////////////////////////////////////////////////////////////////////////////////
118

    
119
  private int retCenter(int color, int[] centers)
120
    {
121
    for(int i=0; i<4; i++ )
122
      if( centers[FREE_CENTERS[i]]==color ) return i;
123

    
124
    return -1;
125
    }
126

    
127
///////////////////////////////////////////////////////////////////////////////////////////////////
128

    
129
  private int[] getFreeCentersPermutation(int[] centers)
130
    {
131
    int[] perm = new int[4];
132

    
133
    for(int i=0; i<4; i++ )
134
      perm[i] = retCenter(mFaceColors[FREE_CENTERS[i]],centers);
135

    
136
    return perm;
137
    }
138

    
139
///////////////////////////////////////////////////////////////////////////////////////////////////
140

    
141
  private int getTotalTwist(int[] twist)
142
    {
143
    int total = 0;
144

    
145
    for(int i=0; i<6; i++)
146
      {
147
      int t= twist[i];
148
      if( t==1 || t==3 ) return -1;
149
      if( i<5 && t==2 ) total+=(1<<i);
150
      }
151

    
152
    return total;
153
    }
154

    
155
///////////////////////////////////////////////////////////////////////////////////////////////////
156

    
157
  private int retCornerTwist(int[] corner, int c1, int c2)
158
    {
159
    if( corner[0]==c1 && corner[2]==c2 ) return 1;
160
    if( corner[1]==c1 && corner[3]==c2 ) return 2;
161
    if( corner[2]==c1 && corner[0]==c2 ) return 3;
162
    if( corner[3]==c1 && corner[1]==c2 ) return 0;
163

    
164
    return -1;
165
    }
166

    
167
///////////////////////////////////////////////////////////////////////////////////////////////////
168

    
169
  private int figureOutColor(int[][] corners, int c1, int c2)
170
    {
171
    for(int i=0; i<6; i++)
172
      {
173
      int[] cor = corners[i];
174
      int twist = retCornerTwist(cor,c1,c2);
175
      if( twist>=0 ) return cor[twist];
176
      }
177

    
178
    return -1;
179
    }
180

    
181
///////////////////////////////////////////////////////////////////////////////////////////////////
182
// We only move the UR, UR, DR & DB faces --> those centers are fixed and determine the colors of
183
// the faces.
184

    
185
  private int figureOutFaceColors(int[] output, int[] centers, int[][] corners)
186
    {
187
    output[1] = centers[1];
188
    output[3] = centers[3];
189
    output[4] = centers[4];
190
    output[6] = centers[6];
191

    
192
    int color01 = figureOutColor(corners,output[4],output[1]);
193
    if( color01<0 ) return ERROR_CORNER_FR_MISSING;
194
    int color02 = figureOutColor(corners,output[3],output[4]);
195
    if( color02<0 ) return ERROR_CORNER_FL_MISSING;
196
    int color03 = figureOutColor(corners,output[1],output[3]);
197
    if( color03<0 ) return ERROR_CORNER_TO_MISSING;
198
    if( color01!=color02 || color01!=color03 ) return ERROR_CORNERS_CANNOT;
199
    output[0] = color01;
200

    
201
    int color21 = figureOutColor(corners,output[1],output[6]);
202
    if( color21<0 ) return ERROR_CORNER_BR_MISSING;
203
    int color22 = figureOutColor(corners,output[6],output[3]);
204
    if( color22<0 ) return ERROR_CORNER_BL_MISSING;
205
    int color23 = figureOutColor(corners,output[3],output[1]);
206
    if( color23<0 ) return ERROR_CORNER_TO_MISSING;
207
    if( color21!=color22 || color21!=color23 ) return ERROR_CORNERS_CANNOT;
208
    output[2] = color21;
209

    
210
    int color51 = figureOutColor(corners,output[1],output[4]);
211
    if( color51<0 ) return ERROR_CORNER_FR_MISSING;
212
    int color52 = figureOutColor(corners,output[6],output[1]);
213
    if( color52<0 ) return ERROR_CORNER_BR_MISSING;
214
    int color53 = figureOutColor(corners,output[4],output[6]);
215
    if( color53<0 ) return ERROR_CORNER_BO_MISSING;
216
    if( color51!=color52 || color51!=color53 ) return ERROR_CORNERS_CANNOT;
217
    output[5] = color51;
218

    
219
    int color71 = figureOutColor(corners,output[3],output[6]);
220
    if( color71<0 ) return ERROR_CORNER_BL_MISSING;
221
    int color72 = figureOutColor(corners,output[4],output[3]);
222
    if( color72<0 ) return ERROR_CORNER_FL_MISSING;
223
    int color73 = figureOutColor(corners,output[6],output[4]);
224
    if( color73<0 ) return ERROR_CORNER_BO_MISSING;
225
    if( color71!=color72 || color71!=color73 ) return ERROR_CORNERS_CANNOT;
226
    output[7] = color71;
227

    
228
    return 0;
229
    }
230

    
231
///////////////////////////////////////////////////////////////////////////////////////////////////
232

    
233
  private int checkAllColorsDifferent()
234
    {
235
    for(int i=0; i<8; i++)
236
      {
237
      boolean present = false;
238

    
239
      for(int j=0; j<8; j++)
240
        if( mFaceColors[j]==i )
241
          {
242
          present=true;
243
          break;
244
          }
245

    
246
      if( !present ) return ERROR_CORNERS_CANNOT;
247
      }
248

    
249
    return 0;
250
    }
251

    
252
///////////////////////////////////////////////////////////////////////////////////////////////////
253

    
254
  private int checkAllCentersPresent(int[] centers)
255
    {
256
    for(int i=0; i<8; i++)
257
      {
258
      boolean present = false;
259

    
260
      for(int j=0; j<8; j++)
261
        if( centers[j]==i )
262
          {
263
          present=true;
264
          break;
265
          }
266

    
267
      if( !present )
268
        {
269
        switch(i)
270
          {
271
          case 0: return ERROR_CENTER_0_MISSING;
272
          case 1: return ERROR_CENTER_1_MISSING;
273
          case 2: return ERROR_CENTER_2_MISSING;
274
          case 3: return ERROR_CENTER_3_MISSING;
275
          case 4: return ERROR_CENTER_4_MISSING;
276
          case 5: return ERROR_CENTER_5_MISSING;
277
          case 6: return ERROR_CENTER_6_MISSING;
278
          case 7: return ERROR_CENTER_7_MISSING;
279
          }
280
        }
281
      }
282

    
283
    return 0;
284
    }
285

    
286
///////////////////////////////////////////////////////////////////////////////////////////////////
287

    
288
  private void getCorners(TwistyObject object, int[][] corners)
289
    {
290
    corners[0][0] = object.getCubitFaceStickerIndex( 0,5); // FR
291
    corners[0][1] = object.getCubitFaceStickerIndex( 0,4);
292
    corners[0][2] = object.getCubitFaceStickerIndex( 0,0);
293
    corners[0][3] = object.getCubitFaceStickerIndex( 0,1);
294

    
295
    corners[1][0] = object.getCubitFaceStickerIndex( 1,2); // BR
296
    corners[1][1] = object.getCubitFaceStickerIndex( 1,6);
297
    corners[1][2] = object.getCubitFaceStickerIndex( 1,5);
298
    corners[1][3] = object.getCubitFaceStickerIndex( 1,1);
299

    
300
    corners[2][0] = object.getCubitFaceStickerIndex( 2,7); // BL
301
    corners[2][1] = object.getCubitFaceStickerIndex( 2,6);
302
    corners[2][2] = object.getCubitFaceStickerIndex( 2,2);
303
    corners[2][3] = object.getCubitFaceStickerIndex( 2,3);
304

    
305
    corners[3][0] = object.getCubitFaceStickerIndex( 3,0); // FL
306
    corners[3][1] = object.getCubitFaceStickerIndex( 3,4);
307
    corners[3][2] = object.getCubitFaceStickerIndex( 3,7);
308
    corners[3][3] = object.getCubitFaceStickerIndex( 3,3);
309

    
310
    corners[4][0] = object.getCubitFaceStickerIndex( 4,0); // U
311
    corners[4][1] = object.getCubitFaceStickerIndex( 4,3);
312
    corners[4][2] = object.getCubitFaceStickerIndex( 4,2);
313
    corners[4][3] = object.getCubitFaceStickerIndex( 4,1);
314

    
315
    corners[5][0] = object.getCubitFaceStickerIndex( 5,5); // D
316
    corners[5][1] = object.getCubitFaceStickerIndex( 5,6);
317
    corners[5][2] = object.getCubitFaceStickerIndex( 5,7);
318
    corners[5][3] = object.getCubitFaceStickerIndex( 5,4);
319
    }
320

    
321
///////////////////////////////////////////////////////////////////////////////////////////////////
322

    
323
  private void getCenters(TwistyObject object, int[] centers)
324
    {
325
    centers[0] = object.getCubitFaceStickerIndex( 9,0); // UF
326
    centers[1] = object.getCubitFaceStickerIndex( 6,0); // UR
327
    centers[2] = object.getCubitFaceStickerIndex( 7,0); // UB
328
    centers[3] = object.getCubitFaceStickerIndex( 8,0); // UL
329
    centers[4] = object.getCubitFaceStickerIndex(13,0); // DF
330
    centers[5] = object.getCubitFaceStickerIndex(10,1); // DR
331
    centers[6] = object.getCubitFaceStickerIndex(11,0); // DB
332
    centers[7] = object.getCubitFaceStickerIndex(12,0); // DL
333
    }
334

    
335
///////////////////////////////////////////////////////////////////////////////////////////////////
336

    
337
  public int tablebaseIndex(TwistyObject object)
338
    {
339
    int[][] corners = new int[6][4];
340
    int[] centers = new int[8];
341

    
342
    getCorners(object,corners);
343
    getCenters(object,centers);
344

    
345
    int result1 = checkAllCentersPresent(centers);
346
    if( result1<0 ) return result1;
347

    
348
    int result2 = figureOutFaceColors(mFaceColors,centers,corners);
349
    if( result2<0 ) return result2;
350

    
351
    int result3 = checkAllColorsDifferent();
352
    if( result3<0 ) return result3;
353

    
354
    int[] corners_perm = getCornersPermutation(corners);
355
    boolean even1 = TablebaseHelpers.permutationIsEven(corners_perm);
356
    if( !even1 ) return ERROR_TWO_CORNERS;
357

    
358
    int[] free_centers_perm = getFreeCentersPermutation(centers);
359
    boolean even2 = TablebaseHelpers.permutationIsEven(free_centers_perm);
360
    if( !even2 ) return ERROR_TWO_CENTERS;
361

    
362
    int[] corners_twist = getCornersTwist(corners_perm, corners);
363
/*
364
android.util.Log.e("D", "faces: "+mFaceColors[0]+" "+mFaceColors[1]+" "+mFaceColors[2]+" "
365
+mFaceColors[3]+" "+mFaceColors[4]+" "+mFaceColors[5]+" "+mFaceColors[6]+" "+mFaceColors[7]);
366

    
367
android.util.Log.e("D", "corn perm: "+corners_perm[0]+" "+corners_perm[1]+" "+corners_perm[2]+" "
368
+corners_perm[3]+" "+corners_perm[4]+" "+corners_perm[5]);
369

    
370
android.util.Log.e("D", "corn twist: "+corners_twist[0]+" "+corners_twist[1]+" "+corners_twist[2]+" "
371
+corners_twist[3]+" "+corners_twist[4]+" "+corners_twist[5]);
372
*/
373
    int totalTwist = getTotalTwist(corners_twist);
374
    if( totalTwist<0 ) return ERROR_CORNER_TWIST;
375

    
376
    int corners_perm_num = TablebaseHelpers.computeEvenPermutationNum(corners_perm);
377
    int centers_perm_num = TablebaseHelpers.computeEvenPermutationNum(free_centers_perm);
378

    
379
    return centers_perm_num + 12*(totalTwist + 32*corners_perm_num);
380
    }
381

    
382
///////////////////////////////////////////////////////////////////////////////////////////////////
383

    
384
  private int getColorIndex4(int face)
385
    {
386
    switch(mFaceColors[face])
387
      {
388
      case 0: return R.string.color_violet4;
389
      case 1: return R.string.color_grey4;
390
      case 2: return R.string.color_blue4;
391
      case 3: return R.string.color_red4;
392
      case 4: return R.string.color_orange4;
393
      case 5: return R.string.color_green4;
394
      case 6: return R.string.color_white4;
395
      case 7: return R.string.color_yellow4;
396
      }
397

    
398
    return -1;
399
    }
400

    
401
///////////////////////////////////////////////////////////////////////////////////////////////////
402

    
403
  private int getColorIndex3(int face)
404
    {
405
    switch(mFaceColors[face])
406
      {
407
      case 0: return R.string.color_violet3;
408
      case 1: return R.string.color_grey3;
409
      case 2: return R.string.color_blue3;
410
      case 3: return R.string.color_red3;
411
      case 4: return R.string.color_orange3;
412
      case 5: return R.string.color_green3;
413
      case 6: return R.string.color_white3;
414
      case 7: return R.string.color_yellow3;
415
      }
416

    
417
    return -1;
418
    }
419

    
420
///////////////////////////////////////////////////////////////////////////////////////////////////
421

    
422
  private int getColorIndex2(int face)
423
    {
424
    switch(face)
425
      {
426
      case 0: return R.string.color_violet2;
427
      case 1: return R.string.color_grey2;
428
      case 2: return R.string.color_blue2;
429
      case 3: return R.string.color_red2;
430
      case 4: return R.string.color_orange2;
431
      case 5: return R.string.color_green2;
432
      case 6: return R.string.color_white2;
433
      case 7: return R.string.color_yellow2;
434
      }
435

    
436
    return -1;
437
    }
438

    
439
///////////////////////////////////////////////////////////////////////////////////////////////////
440

    
441
  private String centerError(Resources res, int face)
442
    {
443
    String color = res.getString(getColorIndex2(face));
444
    return res.getString(R.string.solver_generic_missing_center,color);
445
    }
446

    
447
///////////////////////////////////////////////////////////////////////////////////////////////////
448

    
449
  private String cornerError(Resources res, int f1, int f2)
450
    {
451
    String c1 = res.getString(getColorIndex3(f1));
452
    String c2 = res.getString(getColorIndex4(f2));
453
    return res.getString(R.string.solver_generic_missing_corner2,c1,c2);
454
    }
455

    
456
///////////////////////////////////////////////////////////////////////////////////////////////////
457

    
458
  public String error(int index, Resources res)
459
    {
460
    switch(index)
461
      {
462
      case ERROR_CORNER_FR_MISSING: return cornerError(res,1,4);
463
      case ERROR_CORNER_BR_MISSING: return cornerError(res,1,6);
464
      case ERROR_CORNER_BL_MISSING: return cornerError(res,3,6);
465
      case ERROR_CORNER_FL_MISSING: return cornerError(res,3,4);
466
      case ERROR_CORNER_TO_MISSING: return cornerError(res,1,3);
467
      case ERROR_CORNER_BO_MISSING: return cornerError(res,4,6);
468

    
469
      case ERROR_CENTER_0_MISSING : return centerError(res,0);
470
      case ERROR_CENTER_1_MISSING : return centerError(res,1);
471
      case ERROR_CENTER_2_MISSING : return centerError(res,2);
472
      case ERROR_CENTER_3_MISSING : return centerError(res,3);
473
      case ERROR_CENTER_4_MISSING : return centerError(res,4);
474
      case ERROR_CENTER_5_MISSING : return centerError(res,5);
475
      case ERROR_CENTER_6_MISSING : return centerError(res,6);
476
      case ERROR_CENTER_7_MISSING : return centerError(res,7);
477

    
478
      case ERROR_TWO_CORNERS      : return res.getString(R.string.solver_generic_two_corners);
479
      case ERROR_TWO_CENTERS      : return res.getString(R.string.solver_generic_two_centers);
480
      case ERROR_CORNER_TWIST     : return res.getString(R.string.solver_generic_corner_twist);
481
      case ERROR_CORNERS_CANNOT   : return res.getString(R.string.solver_generic_corners_cannot);
482
      }
483

    
484
    return null;
485
    }
486

    
487
///////////////////////////////////////////////////////////////////////////////////////////////////
488

    
489
  public int[][] solution(int index, Resources res)
490
    {
491
    if( mSolver==null )
492
      {
493
      mSolver = ImplementedTablebasesList.createPacked(res, ObjectSignatures.DIAM_2);
494
      }
495

    
496
    return mSolver!=null ? mSolver.solution(index,null) : null;
497
    }
498
}  
499

    
(12-12/13)