Project

General

Profile

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

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

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 SolverSkewb extends SolverTablebase
24
{
25
  private static final int ERROR_CORNER_135_MISSING = -1;
26
  private static final int ERROR_CORNER_134_MISSING = -2;
27
  private static final int ERROR_CORNER_125_MISSING = -3;
28
  private static final int ERROR_CORNER_124_MISSING = -4;
29
  private static final int ERROR_CORNER_035_MISSING = -5;
30
  private static final int ERROR_CORNER_034_MISSING = -6;
31
  private static final int ERROR_CORNER_025_MISSING = -7;
32
  private static final int ERROR_CORNER_024_MISSING = -8;
33

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

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

    
46
  private static final int ERROR_IMPOSSIBLE         = -19;
47

    
48
  private TablebasesAbstract mSolver;
49
  private final int[] mFaceColors;
50

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

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

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

    
61
  private void getCorners(TwistyObject object, int[][] corners)
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};
73

    
74
    for(int i=0; i<6; i++)
75
      centers[i] = object.getCubitFaceStickerIndex(map[i],0) - 6;
76
    }
77

    
78
///////////////////////////////////////////////////////////////////////////////////////////////////
79

    
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)
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

    
110
    return 0;
111
    }
112

    
113
///////////////////////////////////////////////////////////////////////////////////////////////////
114

    
115
  private boolean cornerIs(int[] corner, int c0, int c1, int c2)
116
    {
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 )  );
120
    }
121

    
122
///////////////////////////////////////////////////////////////////////////////////////////////////
123

    
124
  private int checkAllCornersPresent(int[][] corners)
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;
148

    
149
    return 0;
150
    }
151

    
152
///////////////////////////////////////////////////////////////////////////////////////////////////
153

    
154
  private int checkAllCentersPresent(int[] centers)
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

    
201
    return 0;
202
    }
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

    
293
///////////////////////////////////////////////////////////////////////////////////////////////////
294

    
295
  public int tablebaseIndex(TwistyObject object)
296
    {
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];
301

    
302
    getCorners(object,corners);
303

    
304
    int result1 = computeFaceColors(corners,mFaceColors);
305
    if( result1<0 ) return result1;
306

    
307
    int result2 = checkAllCornersPresent(corners);
308
    if( result2<0 ) return result2;
309

    
310
    getCenters(object,centers);
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]);
316

    
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);
322

    
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);
346
    }
347

    
348
///////////////////////////////////////////////////////////////////////////////////////////////////
349

    
350
  private int getColorIndex2(int face)
351
    {
352
    switch(mFaceColors[face])
353
      {
354
      case 0: return R.string.color_yellow2;
355
      case 1: return R.string.color_white2;
356
      case 2: return R.string.color_blue2;
357
      case 3: return R.string.color_green2;
358
      case 4: return R.string.color_red2;
359
      case 5: return R.string.color_orange2;
360
      }
361

    
362
    return -1;
363
    }
364

    
365
///////////////////////////////////////////////////////////////////////////////////////////////////
366

    
367
  private int getColorIndex3(int face)
368
    {
369
    switch(mFaceColors[face])
370
      {
371
      case 0: return R.string.color_yellow3;
372
      case 1: return R.string.color_white3;
373
      case 2: return R.string.color_blue3;
374
      case 3: return R.string.color_green3;
375
      case 4: return R.string.color_red3;
376
      case 5: return R.string.color_orange3;
377
      }
378

    
379
    return -1;
380
    }
381

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

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

    
396
    return -1;
397
    }
398

    
399
///////////////////////////////////////////////////////////////////////////////////////////////////
400

    
401
  private String cornerError(Resources res, int face0, int face1, int face2)
402
    {
403
    int j0 = getColorIndex3(face0);
404
    int j1 = getColorIndex3(face1);
405
    int j2 = getColorIndex4(face2);
406

    
407
    String c0 = res.getString(j0);
408
    String c1 = res.getString(j1);
409
    String c2 = res.getString(j2);
410

    
411
    return res.getString(R.string.solver_generic_missing_corner,c0,c1,c2);
412
    }
413

    
414
///////////////////////////////////////////////////////////////////////////////////////////////////
415

    
416
  private String centerError(Resources res, int face)
417
    {
418
    int color = getColorIndex2(face);
419
    String clr= res.getString(color);
420
    return res.getString(R.string.solver_generic_missing_center,clr);
421
    }
422

    
423
///////////////////////////////////////////////////////////////////////////////////////////////////
424

    
425
  public String error(int index, Resources res)
426
    {
427
    switch(index)
428
      {
429
      case ERROR_CORNER_135_MISSING: return cornerError(res,1,3,5);
430
      case ERROR_CORNER_134_MISSING: return cornerError(res,1,3,4);
431
      case ERROR_CORNER_125_MISSING: return cornerError(res,1,2,5);
432
      case ERROR_CORNER_124_MISSING: return cornerError(res,1,2,4);
433
      case ERROR_CORNER_035_MISSING: return cornerError(res,0,3,5);
434
      case ERROR_CORNER_034_MISSING: return cornerError(res,0,3,4);
435
      case ERROR_CORNER_025_MISSING: return cornerError(res,0,2,5);
436
      case ERROR_CORNER_024_MISSING: return cornerError(res,0,2,4);
437

    
438
      case ERROR_CENTER_0_MISSING  : return centerError(res,0);
439
      case ERROR_CENTER_1_MISSING  : return centerError(res,1);
440
      case ERROR_CENTER_2_MISSING  : return centerError(res,2);
441
      case ERROR_CENTER_3_MISSING  : return centerError(res,3);
442
      case ERROR_CENTER_4_MISSING  : return centerError(res,4);
443
      case ERROR_CENTER_5_MISSING  : return centerError(res,5);
444

    
445
      case ERROR_CORNERS_CANNOT    : return res.getString(R.string.solver_generic_corners_cannot);
446
      case ERROR_CORNER_TWISTED    : return res.getString(R.string.solver_generic_corner_twist);
447
      case ERROR_TWO_CENTERS       : return res.getString(R.string.solver_generic_two_centers);
448
      case ERROR_TWO_CORNERS       : return res.getString(R.string.solver_generic_two_corners);
449
      }
450

    
451
    return null;
452
    }
453

    
454
///////////////////////////////////////////////////////////////////////////////////////////////////
455

    
456
  public int[][] solution(int index, Resources res)
457
    {
458
    if( mSolver==null )
459
      {
460
      mSolver = ImplementedTablebasesList.createUnpacked(ObjectSignatures.SKEW_2);
461

    
462
      if( mSolver!=null )
463
        {
464
        mSolver.createTablebase(-1);
465
        mSolver.pack();
466
        }
467
      }
468

    
469
    return mSolver!=null ? mSolver.solution(index,null) : null;
470
    }
471
}  
472

    
(10-10/12)