Project

General

Profile

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

magiccube / src / main / java / org / distorted / solvers / SolverCuboid323.java @ 673c1a11

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.helpers.OperatingSystemInterface;
16
import org.distorted.objectlib.main.ObjectSignatures;
17
import org.distorted.objectlib.main.TwistyObject;
18
import org.distorted.objectlib.tablebases.ImplementedTablebasesList;
19
import org.distorted.objectlib.tablebases.TablebaseHelpers;
20
import org.distorted.objectlib.tablebases.TablebasesAbstract;
21

    
22
///////////////////////////////////////////////////////////////////////////////////////////////////
23

    
24
public class SolverCuboid323 extends SolverTablebase
25
{
26
  private static final int ERROR_CORNER_MISSING = -1;
27
  private static final int ERROR_EDGE_MISSING   = -2;
28
  private static final int ERROR_CORNERS_CANNOT = -3;
29
  private static final int ERROR_EDGE_TWISTED   = -4;
30
  private static final int ERROR_CORNER_TWISTED = -5;
31

    
32
  TablebasesAbstract mSolver;
33
  private final int[] mFaceColors;
34
  private int mErrorColor1, mErrorColor2, mErrorColor3;
35
  private boolean mUpper;
36

    
37
///////////////////////////////////////////////////////////////////////////////////////////////////
38
// if mUpper==true, then the edge3 is the 'half-fixed' front edge. Remove it from the permutation.
39
// Otherwise edge1 is the one; remove it.
40

    
41
  private int[] correctEdgePerm(int[] perm)
42
    {
43
    int val;
44
    int[] ret = new int[7];
45

    
46
    if( mUpper )
47
      {
48
      ret[0] = perm[0];
49
      ret[1] = perm[1];
50
      ret[2] = perm[2];
51
      ret[3] = perm[4];
52
      ret[4] = perm[5];
53
      ret[5] = perm[6];
54
      ret[6] = perm[7];
55

    
56
      val = perm[3];
57
      }
58
    else
59
      {
60
      ret[0] = perm[0];
61
      ret[1] = perm[2];
62
      ret[2] = perm[3];
63
      ret[3] = perm[4];
64
      ret[4] = perm[5];
65
      ret[5] = perm[6];
66
      ret[6] = perm[7];
67

    
68
      val = perm[1];
69
      }
70

    
71
    for(int i=0; i<7; i++)
72
      if( ret[i]>val ) ret[i]--;
73

    
74
    return ret;
75
    }
76

    
77
///////////////////////////////////////////////////////////////////////////////////////////////////
78
// 0 or 1, depending on if the 'half-fixed' front edge is in its place or not.
79
// if the 'half-fixed' edge is the upped front one ( i.e. mUpper==true) than it can be in its
80
// place or not; if mUpper==false it always must be in its place.
81

    
82
  private boolean isFrontEdgeInItsPlace(int[][] edges)
83
    {
84
    return (!mUpper || edges[3][1]==mFaceColors[2]);
85
    }
86

    
87
///////////////////////////////////////////////////////////////////////////////////////////////////
88

    
89
  public SolverCuboid323(OperatingSystemInterface os, Resources res, TwistyObject object)
90
    {
91
    super(os,res,object);
92
    mFaceColors = new int[6];
93
    }
94

    
95
////////////////////////////////////////////////////////////////////////////////////////
96

    
97
  private int findCorner(int[][] corners, int c1, int c2)
98
    {
99
    for(int i=0; i<8; i++)
100
      {
101
      int[] c = corners[i];
102

    
103
      if( c[0]==c1 && c[1]==c2 ) return c[2];
104
      if( c[1]==c1 && c[2]==c2 ) return c[0];
105
      if( c[2]==c1 && c[0]==c2 ) return c[1];
106
      }
107

    
108
    return ERROR_CORNERS_CANNOT;
109
    }
110

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

    
113
  private int missingColor()
114
    {
115
    boolean[] present = new boolean[6];
116
    for(int i=0; i<5; i++) present[mFaceColors[i]] = true;
117

    
118
    int indexFalse = -1;
119

    
120
    for(int i=0; i<6; i++)
121
      if( !present[i] )
122
        {
123
        if( indexFalse<0 ) indexFalse=i;
124
        else return ERROR_CORNERS_CANNOT;
125
        }
126

    
127
    return indexFalse;
128
    }
129

    
130
////////////////////////////////////////////////////////////////////////////////////////
131

    
132
  private int edgePresent(int[][] edges, int f0, int f1)
133
    {
134
    int c0 = mFaceColors[f0];
135
    int c1 = mFaceColors[f1];
136

    
137
    for(int i=0; i<8; i++ )
138
      {
139
      int[] edge = edges[i];
140

    
141
      if( edge[0]==c0 && edge[1]==c1 ) return i;
142
      if( edge[0]==c1 && edge[1]==c0 )
143
        {
144
        mErrorColor1 = c0;
145
        mErrorColor2 = c1;
146
        return ERROR_EDGE_TWISTED;
147
        }
148
      }
149

    
150
    mErrorColor1 = c0;
151
    mErrorColor2 = c1;
152
    return ERROR_EDGE_MISSING;
153
    }
154

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

    
157
  private int cornerPresent(int[][] corners, int f0, int f1, int f2)
158
    {
159
    int c0 = mFaceColors[f0];
160
    int c1 = mFaceColors[f1];
161
    int c2 = mFaceColors[f2];
162

    
163
    for(int i=0; i<8; i++)
164
      {
165
      int[] corner = corners[i];
166

    
167
      if(  corner[0]==c0 && corner[1]==c1 && corner[2]==c2 ) return i;
168
      if( (corner[0]==c1 && corner[1]==c2 && corner[2]==c0 ) ||
169
          (corner[0]==c2 && corner[1]==c0 && corner[2]==c1 )  )
170
        {
171
        mErrorColor1 = c0;
172
        mErrorColor2 = c1;
173
        mErrorColor3 = c2;
174
        return ERROR_CORNER_TWISTED;
175
        }
176
      }
177

    
178
    mErrorColor1 = c0;
179
    mErrorColor2 = c1;
180
    mErrorColor3 = c2;
181
    return ERROR_CORNER_MISSING;
182
    }
183

    
184
////////////////////////////////////////////////////////////////////////////////////////
185

    
186
  private int retEdgePermutation(int[] output, int[][] edges)
187
    {
188
    int[][] e = { {5,3}, {4,3}, {5,2}, {4,2}, {1,3}, {1,2}, {0,3}, {0,2} };
189

    
190
    for(int i=0; i<8; i++)
191
      {
192
      int[] ee = e[i];
193
      output[i] = edgePresent(edges,ee[0],ee[1]);
194
      if( output[i]<0 ) return output[i];
195
      }
196

    
197
    return 0;
198
    }
199

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

    
202
  private int retCornerPermutation(int[] output, int[][] corners)
203
    {
204
    int[][] c = { {5,1,3}, {1,4,3}, {1,5,2}, {4,1,2}, {0,5,3}, {4,0,3}, {5,0,2}, {0,4,2} };
205

    
206
    for(int i=0; i<8; i++)
207
      {
208
      int[] cc = c[i];
209
      output[i] = cornerPresent(corners,cc[0],cc[1],cc[2]);
210
      if( output[i]<0 ) return output[i];
211
      }
212

    
213
    return 0;
214
    }
215

    
216
////////////////////////////////////////////////////////////////////////////////////////
217

    
218
  private int computeFaceColors(int[][] corners, int[][] edges, int[] centers)
219
    {
220
    mFaceColors[2] = centers[0];
221
    mFaceColors[3] = centers[1];
222

    
223
    if( edges[1][1]==mFaceColors[2] )
224
      {
225
      mUpper = true;
226
      mFaceColors[4] = edges[1][0];
227
      }
228
    else if( edges[3][1]==mFaceColors[2] )
229
      {
230
      mUpper = true;
231
      mFaceColors[4] = edges[3][0];
232
      }
233
    else
234
      {
235
      mUpper = false;
236
      mFaceColors[4] = edges[3][0];
237
      }
238

    
239
    mFaceColors[0] = findCorner(corners,mFaceColors[4],mFaceColors[2]);
240
    if( mFaceColors[0]<0 ) return mFaceColors[0];
241

    
242
    mFaceColors[1] = findCorner(corners,mFaceColors[2],mFaceColors[4]);
243
    if( mFaceColors[1]<0 ) return mFaceColors[1];
244

    
245
    mFaceColors[5] = missingColor();
246
    if( mFaceColors[5]<0 ) return mFaceColors[5];
247

    
248
    return 0;
249
    }
250

    
251
///////////////////////////////////////////////////////////////////////////////////////////////////
252

    
253
  private void getCorners(TwistyObject object, int[][] corners)
254
    {
255
    corners[0][0] = object.getCubitFaceStickerIndex(0,5);
256
    corners[0][1] = object.getCubitFaceStickerIndex(0,1);
257
    corners[0][2] = object.getCubitFaceStickerIndex(0,3);
258

    
259
    corners[1][0] = object.getCubitFaceStickerIndex(1,3);
260
    corners[1][1] = object.getCubitFaceStickerIndex(1,5);
261
    corners[1][2] = object.getCubitFaceStickerIndex(1,1);
262

    
263
    corners[2][0] = object.getCubitFaceStickerIndex(2,5);
264
    corners[2][1] = object.getCubitFaceStickerIndex(2,1);
265
    corners[2][2] = object.getCubitFaceStickerIndex(2,3);
266

    
267
    corners[3][0] = object.getCubitFaceStickerIndex(3,5);
268
    corners[3][1] = object.getCubitFaceStickerIndex(3,1);
269
    corners[3][2] = object.getCubitFaceStickerIndex(3,3);
270

    
271
    corners[4][0] = object.getCubitFaceStickerIndex(4,1);
272
    corners[4][1] = object.getCubitFaceStickerIndex(4,3);
273
    corners[4][2] = object.getCubitFaceStickerIndex(4,5);
274

    
275
    corners[5][0] = object.getCubitFaceStickerIndex(5,5);
276
    corners[5][1] = object.getCubitFaceStickerIndex(5,1);
277
    corners[5][2] = object.getCubitFaceStickerIndex(5,3);
278

    
279
    corners[6][0] = object.getCubitFaceStickerIndex(6,5);
280
    corners[6][1] = object.getCubitFaceStickerIndex(6,1);
281
    corners[6][2] = object.getCubitFaceStickerIndex(6,3);
282

    
283
    corners[7][0] = object.getCubitFaceStickerIndex(7,1);
284
    corners[7][1] = object.getCubitFaceStickerIndex(7,3);
285
    corners[7][2] = object.getCubitFaceStickerIndex(7,5);
286
    }
287

    
288
///////////////////////////////////////////////////////////////////////////////////////////////////
289

    
290
  private void getEdges(TwistyObject object, int[][] edges)
291
    {
292
    edges[0][0] = object.getCubitFaceStickerIndex(8,5);
293
    edges[0][1] = object.getCubitFaceStickerIndex(8,3);
294
    edges[1][0] = object.getCubitFaceStickerIndex(9,3);
295
    edges[1][1] = object.getCubitFaceStickerIndex(9,5);
296
    edges[2][0] = object.getCubitFaceStickerIndex(10,3);
297
    edges[2][1] = object.getCubitFaceStickerIndex(10,5);
298
    edges[3][0] = object.getCubitFaceStickerIndex(11,5);
299
    edges[3][1] = object.getCubitFaceStickerIndex(11,3);
300
    edges[4][0] = object.getCubitFaceStickerIndex(12,3);
301
    edges[4][1] = object.getCubitFaceStickerIndex(12,5);
302
    edges[5][0] = object.getCubitFaceStickerIndex(13,5);
303
    edges[5][1] = object.getCubitFaceStickerIndex(13,3);
304
    edges[6][0] = object.getCubitFaceStickerIndex(14,3);
305
    edges[6][1] = object.getCubitFaceStickerIndex(14,5);
306
    edges[7][0] = object.getCubitFaceStickerIndex(15,5);
307
    edges[7][1] = object.getCubitFaceStickerIndex(15,3);
308
    }
309

    
310
///////////////////////////////////////////////////////////////////////////////////////////////////
311

    
312
  private void getCenters(TwistyObject object, int[] centers)
313
    {
314
    centers[0] = object.getCubitFaceStickerIndex(16,4);
315
    centers[1] = object.getCubitFaceStickerIndex(17,4);
316
    }
317

    
318
///////////////////////////////////////////////////////////////////////////////////////////////////
319

    
320
  public int tablebaseIndex(TwistyObject object)
321
    {
322
    int[][] corners= new int[8][3];
323
    int[][] edges  = new int[8][2];
324
    int[] centers  = new int[2];
325

    
326
    getCorners(object,corners);
327
    getEdges(object,edges);
328
    getCenters(object,centers);
329

    
330
for(int i=0; i<8; i++) android.util.Log.e("D", "corner: "+i+" : "+corners[i][0]+" "+corners[i][1]+" "+corners[i][2]);
331
for(int i=0; i<8; i++) android.util.Log.e("D", "edge: "+i+" : "+edges[i][0]+" "+edges[i][1]);
332

    
333
    int result0 = computeFaceColors(corners, edges, centers);
334
    if( result0<0 ) return result0;
335

    
336
    int[] corner_perm = new int[8];
337
    int result1 = retCornerPermutation(corner_perm,corners);
338
    if( result1<0 ) return result1;
339

    
340
android.util.Log.e("D", "upper: "+mUpper);
341
for(int i=0; i<6; i++) android.util.Log.e("D", "face color: "+mFaceColors[i]);
342

    
343
    int[] edge_perm = new int[8];
344
    int result2 = retEdgePermutation(edge_perm,edges);
345
    if( result2<0 ) return result2;
346

    
347
    TablebaseHelpers.displayTable(corner_perm, "CORNER PERM");
348
    TablebaseHelpers.displayTable(edge_perm, "EDGE PERM");
349

    
350
    int[] edge_perm2 = correctEdgePerm(edge_perm); // edge1 (lower) or edge3 (upper) is fixed!
351

    
352
    int corner_perm_num = TablebaseHelpers.computePermutationNum(corner_perm);
353
    int edge_perm_num = TablebaseHelpers.computePermutationNum(edge_perm2);
354
    boolean inPlace = isFrontEdgeInItsPlace(edges);
355

    
356
android.util.Log.e("D", "corner_perm_num: "+corner_perm_num+" edge_perm_num: "+edge_perm_num+" inPlace: "+inPlace);
357

    
358
    return corner_perm_num + 20160*( (inPlace?0:1) + 2*edge_perm_num);
359
    }
360

    
361
///////////////////////////////////////////////////////////////////////////////////////////////////
362

    
363
  private int getColorIndex4(int color)
364
    {
365
    switch(color)
366
      {
367
      case 0: return R.string.color_yellow4;
368
      case 1: return R.string.color_white4;
369
      case 2: return R.string.color_blue4;
370
      case 3: return R.string.color_green4;
371
      case 4: return R.string.color_red4;
372
      case 5: return R.string.color_orange4;
373
      }
374

    
375
    return -1;
376
    }
377

    
378
///////////////////////////////////////////////////////////////////////////////////////////////////
379

    
380
  private int getColorIndex3(int color)
381
    {
382
    switch(color)
383
      {
384
      case 0: return R.string.color_yellow3;
385
      case 1: return R.string.color_white3;
386
      case 2: return R.string.color_blue3;
387
      case 3: return R.string.color_green3;
388
      case 4: return R.string.color_red3;
389
      case 5: return R.string.color_orange3;
390
      }
391

    
392
    return -1;
393
    }
394

    
395
///////////////////////////////////////////////////////////////////////////////////////////////////
396

    
397
  private int getColorIndex5(int color)
398
    {
399
    switch(color)
400
      {
401
      case 0: return R.string.color_yellow5;
402
      case 1: return R.string.color_white5;
403
      case 2: return R.string.color_blue5;
404
      case 3: return R.string.color_green5;
405
      case 4: return R.string.color_red5;
406
      case 5: return R.string.color_orange5;
407
      }
408

    
409
    return -1;
410
    }
411

    
412
///////////////////////////////////////////////////////////////////////////////////////////////////
413

    
414
  private int getColorIndex6(int color)
415
    {
416
    switch(color)
417
      {
418
      case 0: return R.string.color_yellow6;
419
      case 1: return R.string.color_white6;
420
      case 2: return R.string.color_blue6;
421
      case 3: return R.string.color_green6;
422
      case 4: return R.string.color_red6;
423
      case 5: return R.string.color_orange6;
424
      }
425

    
426
    return -1;
427
    }
428

    
429
///////////////////////////////////////////////////////////////////////////////////////////////////
430

    
431
  private String edgeTwistedError(Resources res, int color0, int color1)
432
    {
433
    int j0 = getColorIndex3(color0);
434
    int j1 = getColorIndex6(color1);
435

    
436
    String c0 = res.getString(j0);
437
    String c1 = res.getString(j1);
438

    
439
    return res.getString(R.string.solver_generic_twisted_edge,c0,c1);
440
    }
441

    
442
///////////////////////////////////////////////////////////////////////////////////////////////////
443

    
444
  private String cornerTwistedError(Resources res, int color0, int color1, int color2)
445
    {
446
    int j0 = getColorIndex3(color0);
447
    int j1 = getColorIndex3(color1);
448
    int j2 = getColorIndex5(color2);
449

    
450
    String c0 = res.getString(j0);
451
    String c1 = res.getString(j1);
452
    String c2 = res.getString(j2);
453

    
454
    return res.getString(R.string.solver_generic_twisted_corner,c0,c1,c2);
455
    }
456

    
457
///////////////////////////////////////////////////////////////////////////////////////////////////
458

    
459
  private String edgeMissingError(Resources res, int color0, int color1)
460
    {
461
    int j0 = getColorIndex3(color0);
462
    int j1 = getColorIndex6(color1);
463

    
464
    String c0 = res.getString(j0);
465
    String c1 = res.getString(j1);
466

    
467
    return res.getString(R.string.solver_generic_missing_edge,c0,c1);
468
    }
469

    
470
///////////////////////////////////////////////////////////////////////////////////////////////////
471

    
472
  private String cornerMissingError(Resources res, int color0, int color1, int color2)
473
    {
474
    int j0 = getColorIndex3(color0);
475
    int j1 = getColorIndex3(color1);
476
    int j2 = getColorIndex4(color2);
477

    
478
    String c0 = res.getString(j0);
479
    String c1 = res.getString(j1);
480
    String c2 = res.getString(j2);
481

    
482
    return res.getString(R.string.solver_generic_missing_corner,c0,c1,c2);
483
    }
484

    
485
///////////////////////////////////////////////////////////////////////////////////////////////////
486

    
487
  public String error(int index, Resources res)
488
    {
489
    switch(index)
490
      {
491
      case ERROR_CORNER_MISSING : return cornerMissingError(res,mErrorColor1,mErrorColor2,mErrorColor3);
492
      case ERROR_EDGE_MISSING   : return edgeMissingError(res,mErrorColor1,mErrorColor2);
493
      case ERROR_CORNERS_CANNOT : return res.getString(R.string.solver_generic_corners_cannot);
494
      case ERROR_EDGE_TWISTED   : return edgeTwistedError(res,mErrorColor1,mErrorColor2);
495
      case ERROR_CORNER_TWISTED : return cornerTwistedError(res,mErrorColor1,mErrorColor2,mErrorColor3);
496
      }
497

    
498
    return null;
499
    }
500

    
501
///////////////////////////////////////////////////////////////////////////////////////////////////
502

    
503
  public int[][] solution(int index, OperatingSystemInterface os)
504
    {
505
    if( mSolver==null )
506
      {
507
      mSolver = ImplementedTablebasesList.createUnpacked(ObjectSignatures.CU_323);
508
      if( mSolver!=null ) mSolver.createTablebase(2);
509
      }
510

    
511
    return mSolver!=null ? mSolver.solution(index,null,os) : null;
512
    }
513
}  
514

    
(5-5/16)