Project

General

Profile

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

distorted-objectlib / src / main / java / org / distorted / objectlib / tablebases / TBSkewb.java @ 8a489ebd

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 TBSkewb extends TablebasesAbstract
22
{
23
  public static final int[] FIXED= {0,3,5,6};
24
  public static final int[] FREE = {1,2,4,7};
25

    
26
  private static final int[][] freeIndex = { {1,3,2},{0,2,3},{3,1,0},{2,0,1} };
27

    
28
  private static final int[][][] centerQuats =
29
    {
30
        { {0,10},{9,11},{1,7},{4,6},{2,5},{3,8} },
31
        { {9,11},{0,10},{4,6},{1,7},{3,8},{2,5} },
32
        { {2,8},{3,5},{0,11},{9,10},{1,4},{6,7} },
33
        { {3,5},{2,8},{9,10},{0,11},{6,7},{1,4} },
34
        { {1,6},{4,7},{2,3},{5,8},{0,9},{10,11} },
35
        { {4,7},{1,6},{5,8},{2,3},{10,11},{0,9} }
36
    };
37

    
38
  // [1][] are the 3 quats the 1st 'fixed' corner will have when 'fakeTwisted' (which in case of
39
  // the fixed corners is the same as the final twist) with respectively twist 0,1,2.
40

    
41
  private static final int[][] fixedQuats = { {0,1,2},{0,7,8},{0,6,5},{0,4,3} };
42

    
43
  // [1][2][] are the 3 quats the 1st free corner, when permuted to the location of the 2nd corner,
44
  // will have when it is 'fakeTwisted' with fakeTwist 0,1,2.
45
  // fakeTwist is an intermediate twist which needs yet to be translated to the final twist of the
46
  // corners (which needs to sum up to something divisible by 3).
47

    
48
  private static final int[][][] freeQuats=
49
    {
50
        { {0,3,4},{9,8,1},{6,11,2},{7,10,5} },
51
        { {9,2,7},{0,5,6},{1,10,3},{4,11,8} },
52
        { {5,1,11},{2,4,10},{0,8,7},{9,3,6} },
53
        { {8,6,10},{3,7,11},{9,5,4},{0,2,1} }
54
    };
55

    
56
///////////////////////////////////////////////////////////////////////////////////////////////////
57

    
58
  public TBSkewb()
59
    {
60
    super();
61
    }
62

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

    
65
  public TBSkewb(Resources res)
66
    {
67
    super(res, R.raw.skew_2_tablebase);
68
    }
69

    
70
///////////////////////////////////////////////////////////////////////////////////////////////////
71

    
72
  int[][] getBasicAngles()
73
    {
74
    int[] tmp = {3,3};
75
    return new int[][] { tmp,tmp,tmp,tmp };
76
    }
77

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

    
80
  Static3D[] getRotationAxis()
81
    {
82
    return new Static3D[]
83
         {
84
           new Static3D( SQ3/3, SQ3/3, SQ3/3),
85
           new Static3D( SQ3/3, SQ3/3,-SQ3/3),
86
           new Static3D( SQ3/3,-SQ3/3, SQ3/3),
87
           new Static3D( SQ3/3,-SQ3/3,-SQ3/3)
88
         };
89
    }
90

    
91
///////////////////////////////////////////////////////////////////////////////////////////////////
92

    
93
  float[][] getPosition()
94
    {
95
    return new float[][]
96
         {
97
             { 1, 1, 1 },
98
             { 1, 1,-1 },
99
             { 1,-1, 1 },
100
             { 1,-1,-1 },
101
             {-1, 1, 1 },
102
             {-1, 1,-1 },
103
             {-1,-1, 1 },
104
             {-1,-1,-1 },
105

    
106
             { 0, 0, 1 },
107
             { 0, 0,-1 },
108
             { 0, 1, 0 },
109
             { 0,-1, 0 },
110
             { 1, 0, 0 },
111
             {-1, 0, 0 }
112
         };
113
    }
114

    
115
///////////////////////////////////////////////////////////////////////////////////////////////////
116

    
117
  float[][] getCuts()
118
    {
119
    float[] cut = {0};
120
    return new float[][] { cut,cut,cut,cut };
121
    }
122

    
123
///////////////////////////////////////////////////////////////////////////////////////////////////
124

    
125
  boolean[][] getRotatable()
126
    {
127
    boolean[] t1 = new boolean[] {false,true};
128
    boolean[] t2 = new boolean[] {true,false};
129
    return new boolean[][] { t1,t2,t2,t1 };
130
    }
131

    
132
///////////////////////////////////////////////////////////////////////////////////////////////////
133
// specifically for the tablebase
134
///////////////////////////////////////////////////////////////////////////////////////////////////
135

    
136
  int getSize()
137
    {
138
    return 3149280;  // see https://www.jaapsch.net/puzzles/skewb.htm
139
    }
140

    
141
///////////////////////////////////////////////////////////////////////////////////////////////////
142

    
143
  int getMinScramble()
144
    {
145
    return 9;
146
    }
147

    
148
///////////////////////////////////////////////////////////////////////////////////////////////////
149

    
150
  public static int computeLocation(int index, int quat)
151
    {
152
    for(int i=0; i<4; i++)
153
      {
154
      int[] q = freeQuats[index][i];
155
      if( quat==q[0] || quat==q[1] || quat==q[2] ) return i;
156
      }
157

    
158
    android.util.Log.e("D", "error in computeLocation, quat="+quat);
159
    return -1;
160
    }
161

    
162
///////////////////////////////////////////////////////////////////////////////////////////////////
163

    
164
  private static int retFixed(int index, int quat)
165
    {
166
    int[] qs = fixedQuats[index];
167

    
168
    if( quat==qs[0]) return 0;
169
    if( quat==qs[1]) return 1;
170
    if( quat==qs[2]) return 2;
171

    
172
    android.util.Log.e("D", "error in retFixed, index="+index+" quat="+quat);
173
    return -1;
174
    }
175

    
176
///////////////////////////////////////////////////////////////////////////////////////////////////
177

    
178
  private static int retFree(int index, int quat)
179
    {
180
    int[][] qs = freeQuats[index];
181

    
182
    for(int i=0; i<4; i++)
183
      {
184
      if( quat==qs[i][0]) return 0;
185
      if( quat==qs[i][1]) return 1;
186
      if( quat==qs[i][2]) return 2;
187
      }
188

    
189
    android.util.Log.e("D", "error in retFree, index="+index+" quat="+quat);
190
    return -1;
191
    }
192

    
193
///////////////////////////////////////////////////////////////////////////////////////////////////
194
// In case of the four 'fixed' corners (0,3,5,6) which do not change their location,
195
// the twist is natural: 0 in the init positions and increasing 1 mod 3 on each CW turn.
196
//
197
// In case of the four 'free' corners their twist is relative to the position of the 'free'
198
// tetrahedron. And so, for example the twist of free corner 1 (whose 0th face is orange) is equal
199
// to 0 if free corner 7 is on the same face like 0th face of corner 1 (which is the case in init
200
// position); then once free corners 2,4,7 permute CW, twist of corner 1 increases by 1 mod 3.
201

    
202
  public static void computeCornerTwists(int[] twists, int[] quats)
203
    {
204
    for(int i=0; i<4; i++) twists[FIXED[i]] = retFixed(i,quats[FIXED[i]]);
205
    for(int i=0; i<4; i++) twists[FREE[i]]  = retFree(i,quats[FREE[i]]);
206
    }
207

    
208
///////////////////////////////////////////////////////////////////////////////////////////////////
209

    
210
  public static void fillInQuats(int[] quats, int[] perm, int[] twist)
211
    {
212
    for(int i=0; i<4; i++)
213
      {
214
      int fixed = FIXED[i];
215
      int free  = FREE[i];
216
      int twFi  = twist[fixed];
217
      int twFr  = twist[free];
218
      int pe    = perm[i];
219

    
220
      quats[fixed] = fixedQuats[i][twFi];
221
      quats[free ] = freeQuats[i][pe][twFr];
222
      }
223
    }
224

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

    
227
  private int[] computeCenterPerm(int[] quats)
228
    {
229
    int[] output = new int[6];
230

    
231
    for(int i=0; i<6; i++)
232
      {
233
      output[i] = -1;
234
      int[][] c = centerQuats[i];
235
      int q = quats[8+i];
236

    
237
      for(int j=0; j<6; j++)
238
        if( c[j][0]==q || c[j][1]==q )
239
          {
240
          output[i] = j;
241
          break;
242
          }
243
      }
244

    
245
    return output;
246
    }
247

    
248
///////////////////////////////////////////////////////////////////////////////////////////////////
249

    
250
  private void fillCenterQuats(int[] quats, int[] perm)
251
    {
252
    for(int i=0; i<6; i++) quats[8+i] = centerQuats[i][perm[i]][0];
253
    }
254

    
255
///////////////////////////////////////////////////////////////////////////////////////////////////
256

    
257
  private void fillUpToEvenPerm(int[] perm)
258
    {
259
    int min, max;
260

    
261
         if( perm[0]!=0 && perm[1]!=0 ) min=0;
262
    else if( perm[0]!=1 && perm[1]!=1 ) min=1;
263
    else                                min=2;
264

    
265
         if( perm[0]!=3 && perm[1]!=3 ) max=3;
266
    else if( perm[0]!=2 && perm[1]!=2 ) max=2;
267
    else                                max=1;
268

    
269
    int diff = perm[1]-perm[0];
270

    
271
    if( diff==-2 || diff==1 || diff==3 ) { perm[2]=min; perm[3]=max; }
272
    else                                 { perm[2]=max; perm[3]=min; }
273
    }
274

    
275
///////////////////////////////////////////////////////////////////////////////////////////////////
276

    
277
  public int[] getQuats(int index)
278
    {
279
    int[] permFree = new int[4];
280
    int center_perm_num = (index%360);
281
    index /= 360;
282
    int totalTwist = (index%2187);
283
    permFree[0] = (index/2187);
284

    
285
    int[] quats = new int[14];
286
    int[] center_perm = new int[6];
287
    int[] twist = new int[8];
288

    
289
    TablebaseHelpers.getEvenPermutationFromNum(center_perm, center_perm_num);
290
    fillCenterQuats(quats,center_perm);
291

    
292
    for(int i=0; i<7; i++)
293
      {
294
      twist[i] = (totalTwist%3);
295
      totalTwist /= 3;
296
      }
297

    
298
    int total = twist[FREE[0]]+twist[FREE[1]]+twist[FREE[2]];
299
    twist[7] = ((6-total)%3);
300
    int sumFixedTwists = twist[FIXED[0]]+twist[FIXED[1]]+twist[FIXED[2]]+twist[FIXED[3]];
301
    permFree[1] = freeIndex[permFree[0]][sumFixedTwists%3];
302
    fillUpToEvenPerm(permFree);
303
    fillInQuats(quats,permFree,twist);
304

    
305
    return quats;
306
    }
307

    
308
///////////////////////////////////////////////////////////////////////////////////////////////////
309

    
310
  public int getIndex(int[] quats)
311
    {
312
    int[] center_perm = computeCenterPerm(quats);
313
    int center_perm_num = TablebaseHelpers.computeEvenPermutationNum(center_perm);
314
    int[] twist = new int[8];
315
    computeCornerTwists(twist,quats);
316
    int totalTwist = twist[0]+ 3*(twist[1]+ 3*(twist[2]+ 3*(twist[3]+ 3*(twist[4]+ 3*(twist[5]+ 3*twist[6])))));
317
    int locationOfFree0 = computeLocation(0,quats[1]);
318

    
319
    return center_perm_num+ 360*(totalTwist + 2187*locationOfFree0);
320
    }
321
}  
322

    
(9-9/14)