Project

General

Profile

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

magiccube / src / main / java / org / distorted / solvers / SolverTablebaseDINO6.java @ f4b24b79

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.TwistyObject;
17
import org.distorted.objectlib.tablebases.TBDino6;
18
import org.distorted.objectlib.tablebases.TablebaseHelpers;
19

    
20
///////////////////////////////////////////////////////////////////////////////////////////////////
21

    
22
public class SolverTablebaseDINO6 extends SolverTablebase
23
{
24
  private static final int ERROR_EDGE_MISSING        = -1;
25
  private static final int ERROR_EDGE_CANNOT         = -2;
26
  private static final int ERROR_EDGE_TWISTED        = -3;
27
  private static final int ERROR_EDGE_MONOCHROMATIC  = -4;
28
  private static final int ERROR_EDGE_TWICE          = -5;
29
  private static final int ERROR_TWO_EDGES           = -6;
30

    
31
  int[][] EDGE_MAP = {
32
                      {4,2},{0,4},{4,3},{1,4},
33
                      {2,0},{3,0},{3,1},{2,1},
34
                      {5,2},{0,5},{5,3},{1,5}
35
                     };
36

    
37
  private final int[] mFaceColors;
38
  private int mErrorColor1, mErrorColor2;
39

    
40
///////////////////////////////////////////////////////////////////////////////////////////////////
41

    
42
  public SolverTablebaseDINO6(OperatingSystemInterface os, Resources res, TwistyObject object)
43
    {
44
    super(os,res,object);
45
    mFaceColors = new int[6];
46
    }
47

    
48
///////////////////////////////////////////////////////////////////////////////////////////////////
49

    
50
  private void getEdges(TwistyObject object, int[][] edges)
51
    {
52
    for(int i=0; i<12; i++)
53
      {
54
      edges[i][0] = object.getCubitFaceStickerIndex(i,0);
55
      edges[i][1] = object.getCubitFaceStickerIndex(i,1);
56
      }
57
    }
58

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

    
61
  private int computeOpposite(int color, int[][] edges)
62
    {
63
    int[] buffer = new int[6];
64
    for(int i=0; i<6; i++) buffer[i] = 0;
65

    
66
    for(int i=0; i<12; i++)
67
      {
68
      int e0 = edges[i][0];
69
      int e1 = edges[i][1];
70

    
71
      if( e0==color && e1==color)
72
        {
73
        mErrorColor1 = color;
74
        return ERROR_EDGE_MONOCHROMATIC;
75
        }
76

    
77
      if( e0==color )
78
        {
79
        buffer[e1]++;
80

    
81
        if( buffer[e1]>1 )
82
          {
83
          mErrorColor1 = color;
84
          mErrorColor2 = e1;
85
          return ERROR_EDGE_TWICE;
86
          }
87
        }
88

    
89
      if( e1==color )
90
        {
91
        buffer[e0]++;
92

    
93
        if( buffer[e0]>1 )
94
          {
95
          mErrorColor1 = color;
96
          mErrorColor2 = e0;
97
          return ERROR_EDGE_TWICE;
98
          }
99
        }
100
      }
101

    
102
    int total = 0;
103

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

    
115
    if( total==4 )
116
      for(int i=0; i<6; i++)
117
        if( buffer[i]==0 && i!=color ) return i;
118

    
119
    return ERROR_EDGE_CANNOT;
120
    }
121

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

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

    
136
    int total = 0;
137
    for(int i=0; i<6; i++)
138
      if( buffer[i] ) total++;
139

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

    
157
      return 0;
158
      }
159

    
160
    return ERROR_EDGE_CANNOT;
161
    }
162

    
163
///////////////////////////////////////////////////////////////////////////////////////////////////
164

    
165
  private int figureOutFaceColors(int[][] edges)
166
    {
167
    boolean[] present = new boolean[6];
168

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

    
171
    for(int i=0; i<12; i++)
172
      {
173
      int[] edge = edges[i];
174
      int c0 = edge[0];
175
      int c1 = edge[1];
176

    
177
      if( c0>=0 && c0<6 ) present[c0] = true;
178
      if( c1>=0 && c1<6 ) present[c1] = true;
179
      }
180

    
181
    for(int i=0; i<6; i++)
182
      if( !present[i] )
183
        {
184
        mErrorColor1 = i;
185
        mErrorColor2 = (i<4 ? i+2 : i-2 );
186
        return ERROR_EDGE_MISSING;
187
        }
188

    
189
    if( edges[0][0]==edges[0][1] ) return ERROR_EDGE_CANNOT;
190

    
191
    mFaceColors[4] = edges[0][0];
192
    mFaceColors[2] = edges[0][1];
193
    mFaceColors[5] = computeOpposite(mFaceColors[4], edges);
194
    if( mFaceColors[5]<0 ) return mFaceColors[5];
195

    
196
    mFaceColors[3] = computeOpposite(mFaceColors[2], edges);
197
    if( mFaceColors[3]<0 ) return mFaceColors[3];
198

    
199
    int success = fillUpRemainingFaceColors(present);
200
    if( success<0 ) return success;
201

    
202
    return 0;
203
    }
204

    
205
///////////////////////////////////////////////////////////////////////////////////////////////////
206

    
207
  private boolean notPresent(int face0, int face1, int[][] edges)
208
    {
209
    int c0=mFaceColors[face0];
210
    int c1=mFaceColors[face1];
211

    
212
    for(int i=0; i<12; i++)
213
      {
214
      int[] edge = edges[i];
215
      if( edge[0]==c0 && edge[1]==c1 ) return false;
216
      if( edge[0]==c1 && edge[1]==c0 ) return false;
217
      }
218
    return true;
219
    }
220

    
221
///////////////////////////////////////////////////////////////////////////////////////////////////
222

    
223
  public int checkAllPresent(int[][] edges)
224
    {
225
    for(int i=0; i<12; i++)
226
      {
227
      int[] map = EDGE_MAP[i];
228
      int m1 = map[0];
229
      int m2 = map[1];
230

    
231
      if( notPresent(m1,m2,edges) )
232
        {
233
        mErrorColor1 = mFaceColors[m1];
234
        mErrorColor2 = mFaceColors[m2];
235
        return ERROR_EDGE_MISSING;
236
        }
237
      }
238

    
239
    return 0;
240
    }
241

    
242
///////////////////////////////////////////////////////////////////////////////////////////////////
243

    
244
  private boolean wrongTwist(int face0, int face1, int[][] edges)
245
    {
246
    int c0=mFaceColors[face0];
247
    int c1=mFaceColors[face1];
248

    
249
    for(int i=0; i<12; i++)
250
      {
251
      int[] edge = edges[i];
252
      if( edge[1]==c0 && edge[0]==c1 ) return true;
253
      }
254
    return false;
255
    }
256

    
257
///////////////////////////////////////////////////////////////////////////////////////////////////
258

    
259
  public int checkTwist(int[][] edges)
260
    {
261
    for(int i=0; i<12; i++)
262
      {
263
      int[] map = EDGE_MAP[i];
264
      int m1 = map[0];
265
      int m2 = map[1];
266

    
267
      if( wrongTwist(m1,m2,edges) )
268
        {
269
        mErrorColor1 = mFaceColors[m1];
270
        mErrorColor2 = mFaceColors[m2];
271
        return ERROR_EDGE_TWISTED;
272
        }
273
      }
274

    
275
    return 0;
276
    }
277

    
278
///////////////////////////////////////////////////////////////////////////////////////////////////
279

    
280
  private int getPerm(int face0, int face1, int[][] edges)
281
    {
282
    int c0=mFaceColors[face0];
283
    int c1=mFaceColors[face1];
284

    
285
    for(int i=0; i<12; i++)
286
      {
287
      int[] edge = edges[i];
288
      if( edge[0]==c0 && edge[1]==c1 ) return i;
289
      }
290

    
291
    return -1;
292
    }
293

    
294
///////////////////////////////////////////////////////////////////////////////////////////////////
295

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

    
306
    return 0;
307
    }
308

    
309
///////////////////////////////////////////////////////////////////////////////////////////////////
310

    
311
  public int tablebaseIndex(TwistyObject object)
312
    {
313
    int[][] edges = new int[12][2];
314
    getEdges(object,edges);
315

    
316
    int result1 = figureOutFaceColors(edges);
317
    if( result1<0 ) return result1;
318

    
319
    int result2 = checkAllPresent(edges);
320
    if( result2<0 ) return result2;
321

    
322
    int result3 = checkTwist(edges);
323
    if( result3<0 ) return result3;
324

    
325
    int[] perm = new int[12];
326
    int result4 = computePermutation(edges,perm);
327
    if( result4<0 ) return result4;
328

    
329
    if( !TablebaseHelpers.permutationIsEven(perm) ) return ERROR_TWO_EDGES;
330

    
331
    return TBDino6.getIndexFromPerm(perm);
332
    }
333

    
334
///////////////////////////////////////////////////////////////////////////////////////////////////
335

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

    
348
    return -1;
349
    }
350

    
351
///////////////////////////////////////////////////////////////////////////////////////////////////
352

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

    
365
    return -1;
366
    }
367

    
368
///////////////////////////////////////////////////////////////////////////////////////////////////
369

    
370
  private String edgeMissingError(Resources res, int color0, int color1)
371
    {
372
    int j0 = getColorIndex3(color0);
373
    int j1 = getColorIndex6(color1);
374

    
375
    String c0 = res.getString(j0);
376
    String c1 = res.getString(j1);
377

    
378
    return res.getString(R.string.solver_generic_missing_edge,c0,c1);
379
    }
380

    
381
///////////////////////////////////////////////////////////////////////////////////////////////////
382

    
383
  private String edgeTwistedError(Resources res, int color0, int color1)
384
    {
385
    int j0 = getColorIndex3(color0);
386
    int j1 = getColorIndex6(color1);
387

    
388
    String c0 = res.getString(j0);
389
    String c1 = res.getString(j1);
390

    
391
    return res.getString(R.string.solver_generic_twisted_edge,c0,c1);
392
    }
393

    
394
///////////////////////////////////////////////////////////////////////////////////////////////////
395

    
396
  private String edgeMonoError(Resources res, int color)
397
    {
398
    int j0 = getColorIndex3(color);
399
    int j1 = getColorIndex6(color);
400
    String c0 = res.getString(j0);
401
    String c1 = res.getString(j1);
402

    
403
    return res.getString(R.string.solver_generic_edge_mono,c0,c1);
404
    }
405

    
406
///////////////////////////////////////////////////////////////////////////////////////////////////
407

    
408
  private String edgeTwiceError(Resources res, int color0, int color1)
409
    {
410
    int j0 = getColorIndex3(color0);
411
    int j1 = getColorIndex6(color1);
412
    String c0 = res.getString(j0);
413
    String c1 = res.getString(j1);
414

    
415
    return res.getString(R.string.solver_generic_edge_twice,c0,c1);
416
    }
417

    
418
///////////////////////////////////////////////////////////////////////////////////////////////////
419

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

    
432
    return null;
433
    }
434
}  
435

    
(8-8/17)