Project

General

Profile

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

magiccube / src / main / java / org / distorted / solvers / SolverDino6.java @ master

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.metadata.ListObjects;
17
import org.distorted.objectlib.main.TwistyObject;
18
import org.distorted.objectlib.tablebases.ImplementedTablebasesList;
19
import org.distorted.objectlib.tablebases.TBDino6;
20
import org.distorted.objectlib.tablebases.TablebaseHelpers;
21
import org.distorted.objectlib.tablebases.TablebasesAbstract;
22

    
23
///////////////////////////////////////////////////////////////////////////////////////////////////
24

    
25
public class SolverDino6 extends SolverTablebase
26
{
27
  private static final int ERROR_EDGE_MISSING        = -1;
28
  private static final int ERROR_EDGE_CANNOT         = -2;
29
  private static final int ERROR_EDGE_TWISTED        = -3;
30
  private static final int ERROR_EDGE_MONOCHROMATIC  = -4;
31
  private static final int ERROR_EDGE_TWICE          = -5;
32
  private static final int ERROR_TWO_EDGES           = -6;
33

    
34
  int[][] EDGE_MAP = {
35
                      {4,2},{0,4},{4,3},{1,4},
36
                      {2,0},{3,0},{3,1},{2,1},
37
                      {5,2},{0,5},{5,3},{1,5}
38
                     };
39

    
40
  private TablebasesAbstract mSolver;
41
  private final int[] mFaceColors;
42
  private int mErrorColor1, mErrorColor2;
43

    
44
///////////////////////////////////////////////////////////////////////////////////////////////////
45

    
46
  public SolverDino6(OperatingSystemInterface os, Resources res, TwistyObject object)
47
    {
48
    super(os,res,object);
49
    mFaceColors = new int[6];
50
    }
51

    
52
///////////////////////////////////////////////////////////////////////////////////////////////////
53

    
54
  private void getEdges(TwistyObject object, int[][] edges)
55
    {
56
    for(int i=0; i<12; i++)
57
      {
58
      edges[i][0] = object.getCubitFaceStickerIndex(i,0);
59
      edges[i][1] = object.getCubitFaceStickerIndex(i,1);
60
      }
61
    }
62

    
63
///////////////////////////////////////////////////////////////////////////////////////////////////
64

    
65
  private int computeOpposite(int color, int[][] edges)
66
    {
67
    int[] buffer = new int[6];
68
    for(int i=0; i<6; i++) buffer[i] = 0;
69

    
70
    for(int i=0; i<12; i++)
71
      {
72
      int e0 = edges[i][0];
73
      int e1 = edges[i][1];
74

    
75
      if( e0==color && e1==color)
76
        {
77
        mErrorColor1 = color;
78
        return ERROR_EDGE_MONOCHROMATIC;
79
        }
80

    
81
      if( e0==color )
82
        {
83
        buffer[e1]++;
84

    
85
        if( buffer[e1]>1 )
86
          {
87
          mErrorColor1 = color;
88
          mErrorColor2 = e1;
89
          return ERROR_EDGE_TWICE;
90
          }
91
        }
92

    
93
      if( e1==color )
94
        {
95
        buffer[e0]++;
96

    
97
        if( buffer[e0]>1 )
98
          {
99
          mErrorColor1 = color;
100
          mErrorColor2 = e0;
101
          return ERROR_EDGE_TWICE;
102
          }
103
        }
104
      }
105

    
106
    int total = 0;
107

    
108
    for(int i=0; i<6; i++)
109
      if( buffer[i]==1 )
110
        {
111
        if( i!=color) total++;
112
        else
113
          {
114
          mErrorColor1 = i;
115
          return ERROR_EDGE_MONOCHROMATIC;
116
          }
117
        }
118

    
119
    if( total==4 )
120
      for(int i=0; i<6; i++)
121
        if( buffer[i]==0 && i!=color ) return i;
122

    
123
    return ERROR_EDGE_CANNOT;
124
    }
125

    
126
///////////////////////////////////////////////////////////////////////////////////////////////////
127

    
128
  private int fillUpRemainingFaceColors(boolean[] buffer)
129
    {
130
    for(int i=0; i<6; i++)
131
      {
132
      buffer[i] = false;
133
      }
134
    for(int i=0; i<6; i++)
135
      {
136
      int color = mFaceColors[i];
137
      if( color>=0 ) buffer[color] = true;
138
      }
139

    
140
    int total = 0;
141
    for(int i=0; i<6; i++)
142
      if( buffer[i] ) total++;
143

    
144
    if( total==4 )
145
      {
146
      for(int i=0; i<6; i++)
147
        if( !buffer[i] )
148
          {
149
          buffer[i]=true;
150
          mFaceColors[0] = i;
151
          break;
152
          }
153
      for(int i=0; i<6; i++)
154
        if( !buffer[i] )
155
          {
156
          buffer[i]=true;
157
          mFaceColors[1] = i;
158
          break;
159
          }
160

    
161
      return 0;
162
      }
163

    
164
    return ERROR_EDGE_CANNOT;
165
    }
166

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

    
169
  private int figureOutFaceColors(int[][] edges)
170
    {
171
    boolean[] present = new boolean[6];
172

    
173
    for(int i=0; i<6; i++) mFaceColors[i] = -1;
174

    
175
    for(int i=0; i<12; i++)
176
      {
177
      int[] edge = edges[i];
178
      int c0 = edge[0];
179
      int c1 = edge[1];
180

    
181
      if( c0>=0 && c0<6 ) present[c0] = true;
182
      if( c1>=0 && c1<6 ) present[c1] = true;
183
      }
184

    
185
    for(int i=0; i<6; i++)
186
      if( !present[i] )
187
        {
188
        mErrorColor1 = i;
189
        mErrorColor2 = (i<4 ? i+2 : i-2 );
190
        return ERROR_EDGE_MISSING;
191
        }
192

    
193
    if( edges[0][0]==edges[0][1] ) return ERROR_EDGE_CANNOT;
194

    
195
    mFaceColors[4] = edges[0][0];
196
    mFaceColors[2] = edges[0][1];
197
    mFaceColors[5] = computeOpposite(mFaceColors[4], edges);
198
    if( mFaceColors[5]<0 ) return mFaceColors[5];
199

    
200
    mFaceColors[3] = computeOpposite(mFaceColors[2], edges);
201
    if( mFaceColors[3]<0 ) return mFaceColors[3];
202

    
203
    int success = fillUpRemainingFaceColors(present);
204
    if( success<0 ) return success;
205

    
206
    return 0;
207
    }
208

    
209
///////////////////////////////////////////////////////////////////////////////////////////////////
210

    
211
  private boolean notPresent(int face0, int face1, int[][] edges)
212
    {
213
    int c0=mFaceColors[face0];
214
    int c1=mFaceColors[face1];
215

    
216
    for(int i=0; i<12; i++)
217
      {
218
      int[] edge = edges[i];
219
      if( edge[0]==c0 && edge[1]==c1 ) return false;
220
      if( edge[0]==c1 && edge[1]==c0 ) return false;
221
      }
222
    return true;
223
    }
224

    
225
///////////////////////////////////////////////////////////////////////////////////////////////////
226

    
227
  public int checkAllPresent(int[][] edges)
228
    {
229
    for(int i=0; i<12; i++)
230
      {
231
      int[] map = EDGE_MAP[i];
232
      int m1 = map[0];
233
      int m2 = map[1];
234

    
235
      if( notPresent(m1,m2,edges) )
236
        {
237
        mErrorColor1 = mFaceColors[m1];
238
        mErrorColor2 = mFaceColors[m2];
239
        return ERROR_EDGE_MISSING;
240
        }
241
      }
242

    
243
    return 0;
244
    }
245

    
246
///////////////////////////////////////////////////////////////////////////////////////////////////
247

    
248
  private boolean wrongTwist(int face0, int face1, int[][] edges)
249
    {
250
    int c0=mFaceColors[face0];
251
    int c1=mFaceColors[face1];
252

    
253
    for(int i=0; i<12; i++)
254
      {
255
      int[] edge = edges[i];
256
      if( edge[1]==c0 && edge[0]==c1 ) return true;
257
      }
258
    return false;
259
    }
260

    
261
///////////////////////////////////////////////////////////////////////////////////////////////////
262

    
263
  public int checkTwist(int[][] edges)
264
    {
265
    for(int i=0; i<12; i++)
266
      {
267
      int[] map = EDGE_MAP[i];
268
      int m1 = map[0];
269
      int m2 = map[1];
270

    
271
      if( wrongTwist(m1,m2,edges) )
272
        {
273
        mErrorColor1 = mFaceColors[m1];
274
        mErrorColor2 = mFaceColors[m2];
275
        return ERROR_EDGE_TWISTED;
276
        }
277
      }
278

    
279
    return 0;
280
    }
281

    
282
///////////////////////////////////////////////////////////////////////////////////////////////////
283

    
284
  private int getPerm(int face0, int face1, int[][] edges)
285
    {
286
    int c0=mFaceColors[face0];
287
    int c1=mFaceColors[face1];
288

    
289
    for(int i=0; i<12; i++)
290
      {
291
      int[] edge = edges[i];
292
      if( edge[0]==c0 && edge[1]==c1 ) return i;
293
      }
294

    
295
    return -1;
296
    }
297

    
298
///////////////////////////////////////////////////////////////////////////////////////////////////
299

    
300
  private int computePermutation(int[][] edges, int[] perm)
301
    {
302
    for(int i=0; i<12; i++)
303
      {
304
      int[] map = EDGE_MAP[i];
305
      int m1 = map[0];
306
      int m2 = map[1];
307
      perm[i] = getPerm(m1,m2,edges);
308
      }
309

    
310
    return 0;
311
    }
312

    
313
///////////////////////////////////////////////////////////////////////////////////////////////////
314

    
315
  public int tablebaseIndex(TwistyObject object)
316
    {
317
    int[][] edges = new int[12][2];
318
    getEdges(object,edges);
319

    
320
    int result1 = figureOutFaceColors(edges);
321
    if( result1<0 ) return result1;
322

    
323
    int result2 = checkAllPresent(edges);
324
    if( result2<0 ) return result2;
325

    
326
    int result3 = checkTwist(edges);
327
    if( result3<0 ) return result3;
328

    
329
    int[] perm = new int[12];
330
    int result4 = computePermutation(edges,perm);
331
    if( result4<0 ) return result4;
332

    
333
    if( !TablebaseHelpers.permutationIsEven(perm) ) return ERROR_TWO_EDGES;
334

    
335
    return TBDino6.getIndexFromPerm(perm);
336
    }
337

    
338
///////////////////////////////////////////////////////////////////////////////////////////////////
339

    
340
  private int getColorIndex3(int color)
341
    {
342
    switch(color)
343
      {
344
      case 0: return R.string.color_yellow3;
345
      case 1: return R.string.color_white3;
346
      case 2: return R.string.color_blue3;
347
      case 3: return R.string.color_green3;
348
      case 4: return R.string.color_red3;
349
      case 5: return R.string.color_orange3;
350
      }
351

    
352
    return -1;
353
    }
354

    
355
///////////////////////////////////////////////////////////////////////////////////////////////////
356

    
357
  private int getColorIndex6(int color)
358
    {
359
    switch(color)
360
      {
361
      case 0: return R.string.color_yellow6;
362
      case 1: return R.string.color_white6;
363
      case 2: return R.string.color_blue6;
364
      case 3: return R.string.color_green6;
365
      case 4: return R.string.color_red6;
366
      case 5: return R.string.color_orange6;
367
      }
368

    
369
    return -1;
370
    }
371

    
372
///////////////////////////////////////////////////////////////////////////////////////////////////
373

    
374
  private String edgeMissingError(Resources res, int color0, int color1)
375
    {
376
    int j0 = getColorIndex3(color0);
377
    int j1 = getColorIndex6(color1);
378

    
379
    String c0 = res.getString(j0);
380
    String c1 = res.getString(j1);
381

    
382
    return res.getString(R.string.solver_generic_missing_edge,c0,c1);
383
    }
384

    
385
///////////////////////////////////////////////////////////////////////////////////////////////////
386

    
387
  private String edgeTwistedError(Resources res, int color0, int color1)
388
    {
389
    int j0 = getColorIndex3(color0);
390
    int j1 = getColorIndex6(color1);
391

    
392
    String c0 = res.getString(j0);
393
    String c1 = res.getString(j1);
394

    
395
    return res.getString(R.string.solver_generic_twisted_edge,c0,c1);
396
    }
397

    
398
///////////////////////////////////////////////////////////////////////////////////////////////////
399

    
400
  private String edgeMonoError(Resources res, int color)
401
    {
402
    int j0 = getColorIndex3(color);
403
    int j1 = getColorIndex6(color);
404
    String c0 = res.getString(j0);
405
    String c1 = res.getString(j1);
406

    
407
    return res.getString(R.string.solver_generic_edge_mono,c0,c1);
408
    }
409

    
410
///////////////////////////////////////////////////////////////////////////////////////////////////
411

    
412
  private String edgeTwiceError(Resources res, int color0, int color1)
413
    {
414
    int j0 = getColorIndex3(color0);
415
    int j1 = getColorIndex6(color1);
416
    String c0 = res.getString(j0);
417
    String c1 = res.getString(j1);
418

    
419
    return res.getString(R.string.solver_generic_edge_twice,c0,c1);
420
    }
421

    
422
///////////////////////////////////////////////////////////////////////////////////////////////////
423

    
424
  public String error(int index, Resources res)
425
    {
426
    switch(index)
427
      {
428
      case ERROR_EDGE_MISSING      : return edgeMissingError(res,mErrorColor1,mErrorColor2);
429
      case ERROR_EDGE_TWISTED      : return edgeTwistedError(res,mErrorColor1,mErrorColor2);
430
      case ERROR_EDGE_MONOCHROMATIC: return edgeMonoError(res,mErrorColor1);
431
      case ERROR_EDGE_TWICE        : return edgeTwiceError(res,mErrorColor1,mErrorColor2);
432
      case ERROR_EDGE_CANNOT       : return res.getString(R.string.solver_generic_edges_cannot);
433
      case ERROR_TWO_EDGES         : return res.getString(R.string.solver_generic_two_edges);
434
      }
435

    
436
    return null;
437
    }
438

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

    
441
  public int[][] solution(int index, OperatingSystemInterface os)
442
    {
443
    if( mSolver==null )
444
      {
445
      mSolver = ImplementedTablebasesList.createPacked(os, ListObjects.DINO_3.name() );
446
      }
447

    
448
    return mSolver!=null ? mSolver.solution(index,null,os) : null;
449
    }
450
}  
451

    
(7-7/16)