Project

General

Profile

Download (9.99 KB) Statistics
| Branch: | Revision:

distorted-objectlib / src / main / java / org / distorted / objectlib / tablebases / TBDino4.java @ d6e2cf37

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.objectlib.tablebases;
11

    
12
import static org.distorted.objectlib.main.TwistyObject.SQ3;
13

    
14
import android.content.res.Resources;
15

    
16
import org.distorted.library.type.Static3D;
17
import org.distorted.objectlib.R;
18

    
19
///////////////////////////////////////////////////////////////////////////////////////////////////
20

    
21
public class TBDino4 extends TablebasesAbstract
22
{
23
  private static final int[][] SAME = {{0,3,7},{1,2,5},{4,8,9},{6,10,11}};
24
  private static final int SOLVED1 =  6237;  // part 011021302233
25
  private static final int SOLVED2 = 10837;  // part 001102133223
26
  private int[][] mAngles;
27

    
28
///////////////////////////////////////////////////////////////////////////////////////////////////
29

    
30
  public TBDino4()
31
    {
32
    super();
33
    }
34

    
35
///////////////////////////////////////////////////////////////////////////////////////////////////
36

    
37
  public TBDino4(Resources res)
38
    {
39
    super(res, R.raw.din4_3_tablebase);
40
    }
41

    
42
///////////////////////////////////////////////////////////////////////////////////////////////////
43

    
44
  int[][] getBasicAngles()
45
    {
46
    if( mAngles==null )
47
      {
48
      int[] tmp = {3,3,3};
49
      mAngles = new int[][] { tmp,tmp,tmp,tmp };
50
      }
51

    
52
    return mAngles;
53
    }
54

    
55
///////////////////////////////////////////////////////////////////////////////////////////////////
56

    
57
  Static3D[] getRotationAxis()
58
    {
59
    return new Static3D[]
60
         {
61
           new Static3D( SQ3/3, SQ3/3, SQ3/3),
62
           new Static3D( SQ3/3, SQ3/3,-SQ3/3),
63
           new Static3D( SQ3/3,-SQ3/3, SQ3/3),
64
           new Static3D( SQ3/3,-SQ3/3,-SQ3/3)
65
         };
66
    }
67

    
68
///////////////////////////////////////////////////////////////////////////////////////////////////
69

    
70
  float[][] getPosition()
71
    {
72
    return new float[][]
73
         {
74
             { 0.0f, 1.5f, 1.5f },
75
             { 1.5f, 0.0f, 1.5f },
76
             { 0.0f,-1.5f, 1.5f },
77
             {-1.5f, 0.0f, 1.5f },
78
             { 1.5f, 1.5f, 0.0f },
79
             { 1.5f,-1.5f, 0.0f },
80
             {-1.5f,-1.5f, 0.0f },
81
             {-1.5f, 1.5f, 0.0f },
82
             { 0.0f, 1.5f,-1.5f },
83
             { 1.5f, 0.0f,-1.5f },
84
             { 0.0f,-1.5f,-1.5f },
85
             {-1.5f, 0.0f,-1.5f }
86
         };
87
    }
88

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

    
91
  float[][] getCuts()
92
    {
93
    float[] cut = new float[] { -SQ3/3, SQ3/3 };
94
    return new float[][] { cut,cut,cut,cut };
95
    }
96

    
97
///////////////////////////////////////////////////////////////////////////////////////////////////
98
// exclude the middle layer
99

    
100
  boolean[][] getRotatable()
101
    {
102
    boolean[] tmp = {true,false,true};
103
    return new boolean[][] { tmp,tmp,tmp,tmp };
104
    }
105

    
106
///////////////////////////////////////////////////////////////////////////////////////////////////
107
// specifically for the tablebase
108
///////////////////////////////////////////////////////////////////////////////////////////////////
109
// two solved positions: original and mirrored (left face swapped with right)
110

    
111
  @Override
112
  int[] getSolvedIndices()
113
    {
114
    return new int[] {SOLVED1,SOLVED2};
115
    }
116

    
117
///////////////////////////////////////////////////////////////////////////////////////////////////
118
// ditto
119

    
120
  @Override
121
  boolean isSolved(int index)
122
    {
123
    return index==SOLVED1 || index==SOLVED2;
124
    }
125

    
126
///////////////////////////////////////////////////////////////////////////////////////////////////
127
// we can never really move the top-front edge, because if we do so, we would also rotate the
128
// rotation axis themselves! (see getIndex() where the cubit quats are normalized so that quat[0]
129
// - i.e. the front-top edge - is always 0).
130
// That's why map the moves (0,2,X) to (0,0&1,-X) and (3,0,X) to (3,1&2,-X)
131

    
132
  @Override
133
  int[] newMove(int axis, int layer, int angle)
134
    {
135
    if( axis==0 && layer==2 ) return new int[] { axis, 3, angle==1 ? 1:-1};
136
    if( axis==3 && layer==0 ) return new int[] { axis, 6, angle==1 ? 1:-1};
137

    
138
    int maxAngle = mAngles[axis][layer];
139
    angle = maxAngle-angle;
140
    if( angle> 0.5f*maxAngle ) angle -= maxAngle;
141
    return new int[] { axis, (1<<layer), angle };
142
    }
143

    
144
///////////////////////////////////////////////////////////////////////////////////////////////////
145

    
146
  @Override
147
  void convertMoves(int[][] moves)
148
    {
149
    for(int[] move : moves )
150
      {
151
      int[] newMove = newMove(move[0],move[1],move[2]);
152

    
153
      move[0] = newMove[0];
154
      move[1] = newMove[1];
155
      move[2] = newMove[2];
156
      }
157
    }
158

    
159
///////////////////////////////////////////////////////////////////////////////////////////////////
160
// 15408 really (see https://www.jaapsch.net/puzzles/dinocube.htm)
161
// Here 15400 because we equal positions where colors are simply swapped (those are the same with
162
// respect to distance to the 2 solved positions) so there are (11 choose 2)*(8 choose 2)*(5 choose 2)
163
// = 55*28*10 = 15400 possibilities.
164
// We do not pack those tightly, some positions in the same orbit (by Burnside lemma) have 3 different
165
// indices.
166

    
167
  int getSize()
168
    {
169
    return 15400;
170
    }
171

    
172
///////////////////////////////////////////////////////////////////////////////////////////////////
173

    
174
  int getMinScramble()
175
    {
176
    return 5;
177
    }
178

    
179
///////////////////////////////////////////////////////////////////////////////////////////////////
180

    
181
  private static int computeIndex(int[] partition, int section, int size)
182
    {
183
    int index0=0;
184

    
185
    for(;index0<12; index0++)
186
      if(partition[index0]==section ) break;
187

    
188
    int index1=index0+1;
189
    int D1 = 0;
190

    
191
    for(;index1<12; index1++)
192
      {
193
      int val = partition[index1];
194
      if(val >section ) D1++;
195
      if(val==section ) break;
196
      }
197

    
198
    int index2=index1+1;
199
    int D2 = 0;
200

    
201
    for(;index2<12; index2++)
202
      {
203
      int val = partition[index2];
204
      if(val >section ) D2++;
205
      if(val==section ) break;
206
      }
207

    
208
    return D1*size - (D1+1)*D1/2 + D2;
209
    }
210

    
211
///////////////////////////////////////////////////////////////////////////////////////////////////
212

    
213
  public static int indexFromPartition(int[] partition)
214
    {
215
    int index0 = computeIndex(partition,0,11);
216
    int index1 = computeIndex(partition,1,8);
217
    int index2 = computeIndex(partition,2,5);
218

    
219
    return index0 + 55*(index1 + 28*index2);
220
    }
221

    
222
///////////////////////////////////////////////////////////////////////////////////////////////////
223

    
224
  private static void fillPart(int[] part, int index, int section, int size)
225
    {
226
    int index0=0;
227

    
228
    for(; index0<10; index0++)
229
      if( part[index0]<0 )
230
        {
231
        part[index0] = section;
232
        break;
233
        }
234

    
235
    int index1 = index0+1;
236
    int diff = size-1;
237

    
238
    for(; index1<11; index1++)
239
      if( part[index1]<0 )
240
        {
241
        if( index<diff )
242
          {
243
          part[index1] = section;
244
          break;
245
          }
246
        else { index-=diff; diff--; }
247
        }
248

    
249
    int index2 = index1+1;
250

    
251
    for(; index2<12; index2++)
252
      {
253
      if( part[index2]<0 ) index--;
254
      if( index<0 )
255
        {
256
        part[index2] = section;
257
        break;
258
        }
259
      }
260
    }
261

    
262
///////////////////////////////////////////////////////////////////////////////////////////////////
263

    
264
  private static int[] partitionFromIndex(int index)
265
    {
266
    int index0 = (index%55);
267
    index /= 55;
268
    int index1 = (index%28);
269
    int index2 = (index/28);
270

    
271
    int[] part = new int[12];
272
    for(int i=0; i<12; i++) part[i] = -1;
273

    
274
    fillPart(part,index0,0,11);
275
    fillPart(part,index1,1,8);
276
    fillPart(part,index2,2,5);
277

    
278
    for(int i=0; i<12; i++)
279
      if( part[i]<0 ) part[i] = 3;
280

    
281
    return part;
282
    }
283

    
284
///////////////////////////////////////////////////////////////////////////////////////////////////
285

    
286
  private static void fillPerm(int[] perm, int[] part, int section)
287
    {
288
    int num=0;
289
    int[] same = SAME[section];
290

    
291
    for(int i=0; i<12; i++)
292
      if( part[i]==section )
293
        perm[same[num++]] = i;
294
    }
295

    
296
///////////////////////////////////////////////////////////////////////////////////////////////////
297

    
298
  private static int[] quatsFromPartition(int[] partition)
299
    {
300
    int[] perm = new int[12];
301
    fillPerm(perm,partition,0);
302
    fillPerm(perm,partition,1);
303
    fillPerm(perm,partition,2);
304
    fillPerm(perm,partition,3);
305

    
306
    return TBDino6.getQuatsFromPerm(perm);
307
    }
308

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

    
311
  private static int[] partitionFromQuats(int[] quats)
312
    {
313
    int[] perm = new int[12];
314
    System.arraycopy(quats, 0, perm, 0, 12);
315
    TBDino6.getPermFromQuats(perm);
316

    
317
    int[] part = new int[12];
318

    
319
    for(int i=0; i<4; i++)
320
      {
321
      int[] index = SAME[i];
322
      part[perm[index[0]]] = part[perm[index[1]]] = part[perm[index[2]]] = (-i-1);
323
      }
324

    
325
    int newVal=0;
326

    
327
    for(int i=0; i<12; i++)
328
      {
329
      int val = part[i];
330

    
331
      if( val<0 )
332
        {
333
        for(int j=i; j<12; j++)
334
          if( part[j]==val ) part[j] = newVal;
335

    
336
        newVal++;
337
        }
338
      }
339

    
340
    return part;
341
    }
342

    
343
///////////////////////////////////////////////////////////////////////////////////////////////////
344

    
345
  int[] getQuats(int index)
346
    {
347
    int[] partition = partitionFromIndex(index);
348
    return quatsFromPartition(partition);
349
    }
350

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

    
353
  int getIndex(int[] quats)
354
    {
355
    int[] partition = partitionFromQuats(quats);
356
    return indexFromPartition(partition);
357
    }
358
}  
359

    
(5-5/16)