Project

General

Profile

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

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

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 org.distorted.objectlib.R;
13
import org.distorted.objectlib.helpers.OperatingSystemInterface;
14

    
15
///////////////////////////////////////////////////////////////////////////////////////////////////
16

    
17
public class TBDino4 extends TBDino
18
{
19
  private static final int[][] SAME = {{0,3,7},{1,2,5},{4,8,9},{6,10,11}};
20
  private static final int SOLVED1 =  6237;  // partition 011021302233
21
  private static final int SOLVED2 = 10837;  // partition 001102133223
22

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

    
25
  public TBDino4()
26
    {
27
    super();
28
    }
29

    
30
///////////////////////////////////////////////////////////////////////////////////////////////////
31

    
32
  public TBDino4(OperatingSystemInterface os)
33
    {
34
    super(os, new int[] {R.raw.din4_3_pruning2,R.raw.din4_3_pruning3}, new int[] {R.raw.din4_3_pruning7});
35
    }
36

    
37
///////////////////////////////////////////////////////////////////////////////////////////////////
38
// specifically for the tablebase
39
///////////////////////////////////////////////////////////////////////////////////////////////////
40
// two solved positions: original and mirrored (left face swapped with right)
41

    
42
  @Override
43
  int[] getSolvedIndices()
44
    {
45
    return new int[] {SOLVED1,SOLVED2};
46
    }
47

    
48
///////////////////////////////////////////////////////////////////////////////////////////////////
49
// ditto
50

    
51
  @Override
52
  boolean isSolved(int index)
53
    {
54
    return index==SOLVED1 || index==SOLVED2;
55
    }
56

    
57

    
58
///////////////////////////////////////////////////////////////////////////////////////////////////
59
// Because there are two solved positions [where the second one is the first one rotated by 90 deg
60
// around (0,1,0)] scrambling does not work - because when we randomize an index and solve it,
61
// about half the time we actually solve it to the second solved position. And then the first move
62
// of the randomised scramble sequence does not scramble anything!
63
// If we detect that the first move does not scramble anything [i.e. its layer is 1] - reverse the
64
// whole sequence, i.e. do layer 1<-->4.
65

    
66
  @Override
67
  void postScramble(int[][] scramble, int num)
68
    {
69
    if( num>0 )
70
      {
71
      if( scramble[0][1]==1 )
72
        {
73
        for(int i=0; i<num; i++)
74
          {
75
          int[] s = scramble[i];
76
          s[1] = (s[1]==1 ? 4:1);
77
          }
78
        }
79
      }
80
    }
81

    
82
///////////////////////////////////////////////////////////////////////////////////////////////////
83
// 15408 really (see https://www.jaapsch.net/puzzles/dinocube.htm)
84
// Here 15400 because we equal positions where colors are simply swapped (those are the same with
85
// respect to distance to the 2 solved positions) so there are (11 choose 2)*(8 choose 2)*(5 choose 2)
86
// = 55*28*10 = 15400 possibilities.
87
// We do not pack those tightly, some positions in the same orbit (by Burnside lemma) have 3 different
88
// indices.
89

    
90
  int getSize()
91
    {
92
    return 15400;
93
    }
94

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

    
97
  int getMinScramble()
98
    {
99
    return 6;
100
    }
101

    
102
///////////////////////////////////////////////////////////////////////////////////////////////////
103

    
104
  int[] getMidPruningLevels()
105
    {
106
    return new int[] {2,3};
107
    }
108

    
109
///////////////////////////////////////////////////////////////////////////////////////////////////
110

    
111
  int[] getHighPruningLevels()
112
    {
113
    return new int[] {7};
114
    }
115

    
116
///////////////////////////////////////////////////////////////////////////////////////////////////
117

    
118
  int getGodsNumber()
119
    {
120
    return 7;
121
    }
122

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

    
125
  private static int computeIndex(int[] partition, int section, int size)
126
    {
127
    int index0=0;
128

    
129
    for(;index0<12; index0++)
130
      if(partition[index0]==section ) break;
131

    
132
    int index1=index0+1;
133
    int D1 = 0;
134

    
135
    for(;index1<12; index1++)
136
      {
137
      int val = partition[index1];
138
      if(val >section ) D1++;
139
      if(val==section ) break;
140
      }
141

    
142
    int index2=index1+1;
143
    int D2 = 0;
144

    
145
    for(;index2<12; index2++)
146
      {
147
      int val = partition[index2];
148
      if(val >section ) D2++;
149
      if(val==section ) break;
150
      }
151

    
152
    return D1*size - (D1+1)*D1/2 + D2;
153
    }
154

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

    
157
  public static int indexFromPartition(int[] partition)
158
    {
159
    int index0 = computeIndex(partition,0,11);
160
    int index1 = computeIndex(partition,1,8);
161
    int index2 = computeIndex(partition,2,5);
162

    
163
    return index0 + 55*(index1 + 28*index2);
164
    }
165

    
166
///////////////////////////////////////////////////////////////////////////////////////////////////
167

    
168
  private static void fillPart(int[] part, int index, int section, int size)
169
    {
170
    int index0=0;
171

    
172
    for(; index0<10; index0++)
173
      if( part[index0]<0 )
174
        {
175
        part[index0] = section;
176
        break;
177
        }
178

    
179
    int index1 = index0+1;
180
    int diff = size-1;
181

    
182
    for(; index1<11; index1++)
183
      if( part[index1]<0 )
184
        {
185
        if( index<diff )
186
          {
187
          part[index1] = section;
188
          break;
189
          }
190
        else { index-=diff; diff--; }
191
        }
192

    
193
    int index2 = index1+1;
194

    
195
    for(; index2<12; index2++)
196
      {
197
      if( part[index2]<0 ) index--;
198
      if( index<0 )
199
        {
200
        part[index2] = section;
201
        break;
202
        }
203
      }
204
    }
205

    
206
///////////////////////////////////////////////////////////////////////////////////////////////////
207

    
208
  private static int[] partitionFromIndex(int index)
209
    {
210
    int index0 = (index%55);
211
    index /= 55;
212
    int index1 = (index%28);
213
    int index2 = (index/28);
214

    
215
    int[] part = new int[12];
216
    for(int i=0; i<12; i++) part[i] = -1;
217

    
218
    fillPart(part,index0,0,11);
219
    fillPart(part,index1,1,8);
220
    fillPart(part,index2,2,5);
221

    
222
    for(int i=0; i<12; i++)
223
      if( part[i]<0 ) part[i] = 3;
224

    
225
    return part;
226
    }
227

    
228
///////////////////////////////////////////////////////////////////////////////////////////////////
229

    
230
  private static void fillPerm(int[] perm, int[] part, int section)
231
    {
232
    int num=0;
233
    int[] same = SAME[section];
234

    
235
    for(int i=0; i<12; i++)
236
      if( part[i]==section )
237
        perm[same[num++]] = i;
238
    }
239

    
240
///////////////////////////////////////////////////////////////////////////////////////////////////
241

    
242
  private static int[] quatsFromPartition(int[] partition)
243
    {
244
    int[] perm = new int[12];
245
    fillPerm(perm,partition,0);
246
    fillPerm(perm,partition,1);
247
    fillPerm(perm,partition,2);
248
    fillPerm(perm,partition,3);
249

    
250
    return TBDino.getQuatsFromPerm(perm);
251
    }
252

    
253
///////////////////////////////////////////////////////////////////////////////////////////////////
254

    
255
  private static int[] partitionFromQuats(int[] quats)
256
    {
257
    int[] perm = TBDino.getPermFromQuats(quats);
258
    int[] part = new int[12];
259

    
260
    for(int i=0; i<4; i++)
261
      {
262
      int[] index = SAME[i];
263
      part[perm[index[0]]] = part[perm[index[1]]] = part[perm[index[2]]] = (-i-1);
264
      }
265

    
266
    int newVal=0;
267

    
268
    for(int i=0; i<12; i++)
269
      {
270
      int val = part[i];
271

    
272
      if( val<0 )
273
        {
274
        for(int j=i; j<12; j++)
275
          if( part[j]==val ) part[j] = newVal;
276

    
277
        newVal++;
278
        }
279
      }
280

    
281
    return part;
282
    }
283

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

    
286
  int[] getQuats(int index)
287
    {
288
    int[] partition = partitionFromIndex(index);
289
    return quatsFromPartition(partition);
290
    }
291

    
292
///////////////////////////////////////////////////////////////////////////////////////////////////
293

    
294
  int getIndex(int[] quats)
295
    {
296
    normalizeQuats(quats);
297
    int[] partition = partitionFromQuats(quats);
298
    return indexFromPartition(partition);
299
    }
300
}  
301

    
(7-7/19)