Revision bdcb662f
Added by Leszek Koltunski about 1 year ago
src/main/java/org/distorted/objectlib/tablebases/PruningTable.java | ||
---|---|---|
327 | 327 |
|
328 | 328 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
329 | 329 |
|
330 |
boolean belongs(int number)
|
|
330 |
boolean contains(int number)
|
|
331 | 331 |
{ |
332 | 332 |
int bucket = (number>>mNumBits); |
333 | 333 |
int offset1 = getBucketOffset(bucket); |
src/main/java/org/distorted/objectlib/tablebases/TBCube2.java | ||
---|---|---|
11 | 11 |
|
12 | 12 |
import android.content.res.Resources; |
13 | 13 |
|
14 |
import org.distorted.library.main.QuatHelper; |
|
15 | 14 |
import org.distorted.library.type.Static3D; |
16 |
import org.distorted.library.type.Static4D; |
|
17 | 15 |
import org.distorted.objectlib.R; |
18 | 16 |
|
19 | 17 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
20 | 18 |
|
21 | 19 |
public class TBCube2 extends TablebasesPruning |
22 | 20 |
{ |
23 |
private static final int[][] P = |
|
24 |
{ |
|
25 |
{ 2,-1,-1}, |
|
26 |
{ 2,-1, 1}, |
|
27 |
{ 2, 1,-1}, |
|
28 |
{ 2, 1, 1}, |
|
29 |
{-2,-1,-1}, |
|
30 |
{-2,-1, 1}, |
|
31 |
{-2, 1,-1}, |
|
32 |
{-2, 1, 1}, |
|
33 |
|
|
34 |
{-1, 2,-1}, |
|
35 |
{ 1, 2,-1}, |
|
36 |
{-1, 2, 1}, |
|
37 |
{ 1, 2, 1}, |
|
38 |
{-1,-2,-1}, |
|
39 |
{ 1,-2,-1}, |
|
40 |
{-1,-2, 1}, |
|
41 |
{ 1,-2, 1}, |
|
42 |
|
|
43 |
{-1,-1, 2}, |
|
44 |
{ 1,-1, 2}, |
|
45 |
{-1, 1, 2}, |
|
46 |
{ 1, 1, 2}, |
|
47 |
{-1,-1,-2}, |
|
48 |
{ 1,-1,-2}, |
|
49 |
{-1, 1,-2}, |
|
50 |
{ 1, 1,-2}, |
|
51 |
}; |
|
52 |
|
|
53 |
private static final int[][] PT = |
|
54 |
{ |
|
55 |
{4,0},{5,0},{6,0},{7,0}, |
|
56 |
{0,0},{1,0},{2,0},{3,0}, |
|
57 |
{2,2},{6,1},{3,1},{7,2}, |
|
58 |
{0,1},{4,2},{1,2},{5,1}, |
|
59 |
{1,1},{5,2},{3,2},{7,1}, |
|
60 |
{0,2},{4,1},{2,1},{6,2} |
|
61 |
}; |
|
62 |
|
|
63 |
private int[][][] mQuatsMap; |
|
21 |
private final int[][][] mQuatsMap = |
|
22 |
{ |
|
23 |
{ { 0,21,13}, { 1, 6,18}, { 3,17, 7}, { 2,12,22}, {14, 4, 9}, { 5,10,15}, { 8,20,23}, {11,16,19} }, |
|
24 |
{ { 3,18, 4}, { 0,22,10}, { 2,13,20}, { 1, 7,16}, { 5,23,21}, {11, 9, 6}, {14,19,17}, { 8,15,12} }, |
|
25 |
{ { 1, 9,17}, { 2,15,21}, { 0,23,12}, { 3,19, 6}, { 8,13,10}, {14,18,16}, {11, 7, 4}, { 5,22,20} }, |
|
26 |
{ { 2,10,23}, { 3,16, 9}, { 1, 4,19}, { 0,20,15}, {11,17,18}, { 8,21,22}, { 5,12,13}, {14, 6, 7} }, |
|
27 |
{ {14, 7, 6}, { 5,13,12}, { 8,22,21}, {11,18,17}, { 0,15,20}, { 1,19, 4}, { 3, 9,16}, { 2,23,10} }, |
|
28 |
{ { 5,20,22}, {11, 4, 7}, {14,16,18}, { 8,10,13}, { 3, 6,19}, { 0,12,23}, { 2,21,15}, { 1,17, 9} }, |
|
29 |
{ { 8,12,15}, {14,17,19}, {11, 6, 9}, { 5,21,23}, { 1,16, 7}, { 2,20,13}, { 0,10,22}, { 3, 4,18} }, |
|
30 |
{ {11,19,16}, { 8,23,20}, { 5,15,10}, {14, 9, 4}, { 2,22,12}, { 3, 7,17}, { 1,18, 6}, { 0,13,21} }, |
|
31 |
}; |
|
64 | 32 |
|
65 | 33 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
66 | 34 |
|
... | ... | |
167 | 135 |
|
168 | 136 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
169 | 137 |
|
170 |
private int[] getPermTwist(float[] point) |
|
171 |
{ |
|
172 |
float ERR = 0.01f; |
|
173 |
|
|
174 |
for(int i=0; i<24; i++) |
|
175 |
{ |
|
176 |
float dx = point[0]-P[i][0]; |
|
177 |
float dy = point[1]-P[i][1]; |
|
178 |
float dz = point[2]-P[i][2]; |
|
179 |
|
|
180 |
if( dx*dx + dy*dy + dz*dz < ERR ) return PT[i]; |
|
181 |
} |
|
182 |
|
|
183 |
return null; |
|
184 |
} |
|
185 |
|
|
186 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
187 |
|
|
188 |
private void fillOutMap(float[] buffer, int[][] map, float[] point, Static4D quat, int quatIndex) |
|
138 |
boolean moveCanProceed(int lastA, int lastR, int currA, int currR) |
|
189 | 139 |
{ |
190 |
QuatHelper.rotateVectorByQuat(buffer,point[0],point[1],point[2],1,quat); |
|
191 |
int[] pt = getPermTwist(buffer); |
|
192 |
map[pt[0]][pt[1]] = quatIndex; |
|
193 |
} |
|
194 |
|
|
195 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
196 |
|
|
197 |
private void computeMap() |
|
198 |
{ |
|
199 |
final float[][] POINTS = |
|
200 |
{ |
|
201 |
{-2,-1,-1}, |
|
202 |
{-2,-1, 1}, |
|
203 |
{-2, 1,-1}, |
|
204 |
{-2, 1, 1}, |
|
205 |
{ 2,-1,-1}, |
|
206 |
{ 2,-1, 1}, |
|
207 |
{ 2, 1,-1}, |
|
208 |
{ 2, 1, 1}, |
|
209 |
}; |
|
210 |
|
|
211 |
mQuatsMap = new int[8][8][3]; |
|
212 |
Static4D[] quats = getQuats(); |
|
213 |
float[] buffer = new float[4]; |
|
214 |
|
|
215 |
for(int c=0; c<8; c++) |
|
216 |
for(int q=0; q<24; q++) |
|
217 |
fillOutMap(buffer,mQuatsMap[c],POINTS[c],quats[q],q); |
|
140 |
return lastA!=currA; |
|
218 | 141 |
} |
219 | 142 |
|
220 | 143 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
... | ... | |
303 | 226 |
|
304 | 227 |
public int[] getQuats(int index) |
305 | 228 |
{ |
306 |
if( mQuatsMap==null ) computeMap(); |
|
307 |
|
|
308 | 229 |
int twistNum = index%729; |
309 | 230 |
int permuNum = index/729; |
310 | 231 |
|
... | ... | |
335 | 256 |
|
336 | 257 |
public int getIndex(int[] quats) |
337 | 258 |
{ |
338 |
if( mQuatsMap==null ) computeMap(); |
|
339 |
|
|
340 | 259 |
int[] twist = new int[8]; |
341 | 260 |
int[] perm8 = new int[8]; |
342 | 261 |
|
... | ... | |
346 | 265 |
int twistNum = twist[0] + 3*(twist[2] + 3*(twist[3] + 3*(twist[4] + 3*(twist[5] + 3*twist[6])))); |
347 | 266 |
int permNum = TablebaseHelpers.computePermutationNum(perm7); |
348 | 267 |
|
268 |
if( permNum<0 ) |
|
269 |
{ |
|
270 |
android.util.Log.e("D", " permNum="+permNum ); |
|
271 |
|
|
272 |
StringBuilder sb2 = new StringBuilder(); |
|
273 |
for(int i=0; i<8; i++) { sb2.append(' '); sb2.append(perm8[i]); } |
|
274 |
android.util.Log.e("D", " perm8="+sb2 ); |
|
275 |
|
|
276 |
StringBuilder sb3 = new StringBuilder(); |
|
277 |
for(int i=0; i<8; i++) { sb3.append(' '); sb3.append(quats[i]); } |
|
278 |
android.util.Log.e("D", " quats="+sb3 ); |
|
279 |
} |
|
280 |
|
|
349 | 281 |
return twistNum + 729*permNum; |
350 | 282 |
} |
351 | 283 |
} |
src/main/java/org/distorted/objectlib/tablebases/TablebasesAbstract.java | ||
---|---|---|
29 | 29 |
private final Static3D[] mAxis; |
30 | 30 |
private final int mSize, mMinScramble; |
31 | 31 |
private final int[][] mAngles; |
32 |
private final int mNumAxis; |
|
33 | 32 |
private final int[] mNumLayers; |
34 | 33 |
private final int mNumQuats; |
35 | 34 |
private final Static4D[] mQuats; |
36 |
private final int[][] mRotRow; |
|
37 |
private final int mNumCubits; |
|
38 |
private final float[][] mPosition; |
|
39 | 35 |
private final float[][] mCuts; |
40 | 36 |
private final int[] mNumCuts; |
41 |
private final boolean[][] mRotatable; |
|
42 |
private final int mScalingFactor; |
|
43 | 37 |
|
44 | 38 |
private int[][] mQuatMult; |
45 | 39 |
private boolean mInitialized; |
46 | 40 |
|
47 | 41 |
Tablebase mTablebase; |
42 |
final int mScalingFactor; |
|
43 |
final int mNumAxis; |
|
44 |
final float[][] mPosition; |
|
45 |
final int[][] mRotRow; |
|
46 |
final int mNumCubits; |
|
47 |
final boolean[][] mRotatable; |
|
48 | 48 |
|
49 | 49 |
private static final float[] mTmp = new float[4]; |
50 | 50 |
|
... | ... | |
127 | 127 |
|
128 | 128 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
129 | 129 |
|
130 |
private int computeRow(float[] pos, int quat, int axisIndex)
|
|
130 |
int computeRow(float[] pos, int quat, int axisIndex) |
|
131 | 131 |
{ |
132 | 132 |
int ret=0; |
133 | 133 |
int len = pos.length/3; |
... | ... | |
205 | 205 |
|
206 | 206 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
207 | 207 |
|
208 |
private int getMultQuat(int index1, int index2)
|
|
208 |
int getMultQuat(int index1, int index2) |
|
209 | 209 |
{ |
210 | 210 |
if( mQuatMult==null ) |
211 | 211 |
{ |
... | ... | |
323 | 323 |
return new byte[][] { data }; |
324 | 324 |
} |
325 | 325 |
|
326 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
327 |
|
|
328 |
void convertMoves(int[][] moves) |
|
329 |
{ |
|
330 |
for(int[] move : moves ) |
|
331 |
{ |
|
332 |
int axis = move[0]; |
|
333 |
int layer= move[1]; |
|
334 |
int angle= move[2]; |
|
335 |
|
|
336 |
int maxAngle = mAngles[axis][layer]; |
|
337 |
angle = maxAngle-angle; |
|
338 |
if( angle> 0.5f*maxAngle ) angle -= maxAngle; |
|
339 |
|
|
340 |
move[1] = (1<<layer); |
|
341 |
move[2] = angle; |
|
342 |
} |
|
343 |
} |
|
344 |
|
|
326 | 345 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
327 | 346 |
|
328 | 347 |
private void addMove(ArrayList<int[]> moves, int axis, int layer, int angle) |
... | ... | |
347 | 366 |
|
348 | 367 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
349 | 368 |
|
350 |
private void getNextAxisLayerAngleQuat(int[] data)
|
|
369 |
void getNextAxisLayerAngleQuat(int[] data) |
|
351 | 370 |
{ |
352 | 371 |
int axis = data[0]; |
353 | 372 |
int layer= data[1]; |
... | ... | |
377 | 396 |
return moves; |
378 | 397 |
} |
379 | 398 |
|
380 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
381 |
|
|
382 |
Static4D[] getQuats() |
|
383 |
{ |
|
384 |
return mQuats; |
|
385 |
} |
|
386 |
|
|
387 | 399 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
388 | 400 |
|
389 | 401 |
public int[][] solution(int index, int[] extra) |
... | ... | |
558 | 570 |
|
559 | 571 |
for(int i=0; i<size; i++) |
560 | 572 |
{ |
561 |
if (table.belongs(i))
|
|
573 |
if (table.contains(i))
|
|
562 | 574 |
{ |
563 | 575 |
if ((num % 10) == 0) sb.append("\n"); |
564 | 576 |
num++; |
src/main/java/org/distorted/objectlib/tablebases/TablebasesPruning.java | ||
---|---|---|
19 | 19 |
|
20 | 20 |
public abstract class TablebasesPruning extends TablebasesAbstract |
21 | 21 |
{ |
22 |
private final int mGodsNumber; |
|
23 |
|
|
22 | 24 |
private boolean mInitialized; |
23 | 25 |
private PruningTable[] mHighTables; |
24 | 26 |
private PruningTable[] mMidTables; |
25 |
private int mGodsNumber, mLowestHigh, mHighestMid, mLowestMid;
|
|
27 |
private int mLowestHigh, mHighestMid, mLowestMid; |
|
26 | 28 |
|
27 | 29 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
28 | 30 |
|
29 | 31 |
abstract int[] getMidPruningLevels(); |
30 | 32 |
abstract int[] getHighPruningLevels(); |
31 | 33 |
abstract int getGodsNumber(); |
34 |
abstract boolean moveCanProceed(int lastA, int lastL, int currA, int currL); |
|
32 | 35 |
|
33 | 36 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
34 | 37 |
|
... | ... | |
83 | 86 |
|
84 | 87 |
for(int i=0; i<mid ; i++) mMidTables[i] = createPruningTable(res,midIDs[i] ); |
85 | 88 |
for(int i=0; i<high; i++) mHighTables[i]= createPruningTable(res,highIDs[i]); |
89 |
|
|
90 |
computeLowHigh(); |
|
86 | 91 |
} |
87 | 92 |
|
88 | 93 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
... | ... | |
118 | 123 |
for(int i=0; i<numHighLevels; i++) |
119 | 124 |
mHighTables[i] = new PruningTable(mTablebase,highLevels[i]); |
120 | 125 |
|
126 |
computeLowHigh(); |
|
127 |
|
|
121 | 128 |
mInitialized = true; |
122 | 129 |
} |
123 | 130 |
|
... | ... | |
133 | 140 |
|
134 | 141 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
135 | 142 |
|
136 |
public int[][] solution(int index, int[] extra) |
|
143 |
private void computeLowHigh() |
|
144 |
{ |
|
145 |
mLowestHigh = mGodsNumber+1; |
|
146 |
int numHigh = mHighTables==null ? 0 : mHighTables.length; |
|
147 |
|
|
148 |
for( int i=0; i<numHigh; i++ ) |
|
149 |
{ |
|
150 |
int level = mHighTables[i].getLevel(); |
|
151 |
if( i==0 || level<mLowestHigh ) mLowestHigh=level; |
|
152 |
} |
|
153 |
|
|
154 |
mLowestMid = 0; |
|
155 |
mHighestMid= 0; |
|
156 |
int numMid = mMidTables==null ? 0 : mMidTables.length; |
|
157 |
|
|
158 |
for( int i=0; i<numMid; i++ ) |
|
159 |
{ |
|
160 |
int level = mMidTables[i].getLevel(); |
|
161 |
if( i==0 || level<mLowestMid ) mLowestMid =level; |
|
162 |
if( i==0 || level>mHighestMid ) mHighestMid=level; |
|
163 |
} |
|
164 |
} |
|
165 |
|
|
166 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
167 |
|
|
168 |
public int traverseDownTable(int index, PruningTable[] tables, int tableIndex, int lastA, int lastR, int[] move, int[] tmpQuats) |
|
169 |
{ |
|
170 |
int[] quats = getQuats(index); |
|
171 |
int numQuats = quats.length; |
|
172 |
|
|
173 |
move[0]=0; |
|
174 |
move[1]=0; |
|
175 |
move[2]=1; |
|
176 |
move[3]=1; |
|
177 |
|
|
178 |
for(int ax=0; ax<mNumAxis; ax++) |
|
179 |
for(int cubit=0; cubit<mNumCubits; cubit++) |
|
180 |
mRotRow[cubit][ax] = computeRow(mPosition[cubit],quats[cubit],ax); |
|
181 |
|
|
182 |
for(int s=0; s<mScalingFactor; s++) |
|
183 |
{ |
|
184 |
int ax = move[0]; |
|
185 |
int layer = move[1]; |
|
186 |
int quat = move[3]; |
|
187 |
|
|
188 |
if( mRotatable[ax][layer] && moveCanProceed(lastA,lastR,move[0],move[1]) ) |
|
189 |
{ |
|
190 |
int bitLayer = (1<<layer); |
|
191 |
System.arraycopy(quats, 0, tmpQuats, 0, numQuats); |
|
192 |
|
|
193 |
for(int cubit=0; cubit<mNumCubits; cubit++) |
|
194 |
if( mRotRow[cubit][ax]==bitLayer ) |
|
195 |
{ |
|
196 |
int currQuat = tmpQuats[cubit]; |
|
197 |
int newQuat = getMultQuat(quat,currQuat); |
|
198 |
tmpQuats[cubit] = newQuat; |
|
199 |
} |
|
200 |
|
|
201 |
int childIndex = getIndex(tmpQuats); |
|
202 |
|
|
203 |
if( tableIndex>0 ) |
|
204 |
{ |
|
205 |
if( tables[tableIndex-1].contains(childIndex) ) return childIndex; |
|
206 |
} |
|
207 |
else if( !tables[0].contains(childIndex) ) |
|
208 |
{ |
|
209 |
if( tables.length<=1 || !tables[1].contains(childIndex) ) return childIndex; |
|
210 |
} |
|
211 |
} |
|
212 |
|
|
213 |
getNextAxisLayerAngleQuat(move); |
|
214 |
} |
|
215 |
|
|
216 |
return -1; |
|
217 |
} |
|
218 |
|
|
219 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
220 |
|
|
221 |
private int traversePruningBlock(int[][] moves, PruningTable[] tables, int tableIndex, int index, int lastA, int lastR) |
|
137 | 222 |
{ |
223 |
int movesIndex = 1; |
|
224 |
int[] move = moves[movesIndex]; |
|
225 |
int[] tmpQuats = new int[4]; |
|
226 |
|
|
227 |
do |
|
228 |
{ |
|
229 |
index = traverseDownTable(index,tables,tableIndex,lastA,lastR,move,tmpQuats); |
|
230 |
lastA = move[0]; |
|
231 |
lastR = move[1]; |
|
232 |
tableIndex--; |
|
233 |
movesIndex++; |
|
234 |
move = moves[movesIndex]; |
|
235 |
} |
|
236 |
while( tableIndex>=0 ); |
|
237 |
|
|
238 |
return index; |
|
239 |
} |
|
240 |
|
|
241 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
242 |
// ret: [0][] --> (new index,new depth,?,?) ; [1...N-1][] --> moves. (or null if index not in High) |
|
243 |
|
|
244 |
private int[][] traverseBlock(int index, PruningTable[] tables, int lastA, int lastR) |
|
245 |
{ |
|
246 |
int num = (tables==null) ? 0 : tables.length; |
|
247 |
int tableIndex = -1; |
|
248 |
|
|
249 |
for( int i=0; i<num; i++ ) |
|
250 |
if( tables[i].contains(index) ) |
|
251 |
{ |
|
252 |
tableIndex = i; |
|
253 |
break; |
|
254 |
} |
|
255 |
|
|
256 |
if( tableIndex<0 ) return null; |
|
257 |
|
|
258 |
int[][] ret = new int[tableIndex+2][4]; |
|
259 |
ret[0][1] = tables[0].getLevel()-1; |
|
260 |
ret[0][0] = traversePruningBlock(ret,tables,tableIndex,index,lastA, lastR); |
|
261 |
|
|
262 |
return ret; |
|
263 |
} |
|
264 |
|
|
265 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
266 |
|
|
267 |
private int midTablesContain(int index) |
|
268 |
{ |
|
269 |
int num = mMidTables.length; |
|
270 |
|
|
271 |
for( int i=0; i<num; i++ ) |
|
272 |
if( mMidTables[i].contains(index) ) |
|
273 |
return i; |
|
274 |
|
|
275 |
return -1; |
|
276 |
} |
|
277 |
|
|
278 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
279 |
|
|
280 |
private boolean jumpMidZeroRecursive(int index, int jump, int depth, int lastA, int lastR, int[][] solution) |
|
281 |
{ |
|
282 |
int[] quats = getQuats(index); |
|
283 |
int numQuats = quats.length; |
|
284 |
int[] move = solution[depth]; |
|
285 |
int[] tmp = new int[mNumCubits]; |
|
286 |
|
|
287 |
move[0]=0; |
|
288 |
move[1]=0; |
|
289 |
move[2]=1; |
|
290 |
move[3]=1; |
|
291 |
|
|
292 |
for(int ax=0; ax<mNumAxis; ax++) |
|
293 |
for(int cubit=0; cubit<mNumCubits; cubit++) |
|
294 |
mRotRow[cubit][ax] = computeRow(mPosition[cubit],quats[cubit],ax); |
|
295 |
|
|
296 |
for(int s=0; s<mScalingFactor; s++) |
|
297 |
{ |
|
298 |
int ax = move[0]; |
|
299 |
int layer = move[1]; |
|
300 |
int quat = move[3]; |
|
301 |
|
|
302 |
if( mRotatable[ax][layer] && moveCanProceed(lastA,lastR,ax,layer) ) |
|
303 |
{ |
|
304 |
int bitLayer = (1<<layer); |
|
305 |
System.arraycopy(quats, 0, tmp, 0, numQuats); |
|
306 |
|
|
307 |
for(int cubit=0; cubit<mNumCubits; cubit++) |
|
308 |
if( mRotRow[cubit][ax]==bitLayer ) |
|
309 |
{ |
|
310 |
int currQuat = tmp[cubit]; |
|
311 |
int newQuat = getMultQuat(quat,currQuat); |
|
312 |
tmp[cubit] = newQuat; |
|
313 |
} |
|
314 |
|
|
315 |
int childIndex = getIndex(tmp); |
|
316 |
|
|
317 |
if( childIndex==0 ) |
|
318 |
{ |
|
319 |
solution[0][0] = childIndex; |
|
320 |
solution[0][1] = 0; |
|
321 |
return true; |
|
322 |
} |
|
323 |
|
|
324 |
int containingTable = midTablesContain(childIndex); |
|
325 |
|
|
326 |
if( containingTable>=0 ) |
|
327 |
{ |
|
328 |
solution[0][0] = childIndex; |
|
329 |
solution[0][1] = mMidTables[containingTable].getLevel(); |
|
330 |
return true; |
|
331 |
} |
|
332 |
|
|
333 |
if( jump>1 && jumpMidZeroRecursive(childIndex, jump-1, depth+1, ax, layer, solution) ) |
|
334 |
{ |
|
335 |
return true; |
|
336 |
} |
|
337 |
} |
|
338 |
|
|
339 |
getNextAxisLayerAngleQuat(move); |
|
340 |
} |
|
341 |
|
|
342 |
return false; |
|
343 |
} |
|
344 |
|
|
345 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
346 |
// ret: [0][] --> (?,old depth,?,?) ; [1...N-1][] --> moves. |
|
347 |
|
|
348 |
private int[][] jumpToMidOrZero(int index, int maxJump, int lastA, int lastR) |
|
349 |
{ |
|
350 |
int[][] solution = new int[maxJump+1][4]; |
|
351 |
|
|
352 |
for(int i=1; i<maxJump; i++) |
|
353 |
if( jumpMidZeroRecursive(index,i,1,lastA,lastR,solution) ) |
|
354 |
return solution; |
|
355 |
|
|
356 |
return null; |
|
357 |
} |
|
358 |
|
|
359 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
360 |
|
|
361 |
private boolean jumpZeroRecursive(int index, int jump, int depth, int lastA, int lastR, int[][] solution) |
|
362 |
{ |
|
363 |
int[] quats = getQuats(index); |
|
364 |
int numQuats = quats.length; |
|
365 |
int[] move = solution[depth]; |
|
366 |
int[] tmp = new int[mNumCubits]; |
|
367 |
|
|
368 |
android.util.Log.e("D", "trying 0rec: index="+index); |
|
369 |
|
|
370 |
move[0]=0; |
|
371 |
move[1]=0; |
|
372 |
move[2]=1; |
|
373 |
move[3]=1; |
|
374 |
|
|
375 |
for(int ax=0; ax<mNumAxis; ax++) |
|
376 |
for(int cubit=0; cubit<mNumCubits; cubit++) |
|
377 |
mRotRow[cubit][ax] = computeRow(mPosition[cubit],quats[cubit],ax); |
|
378 |
|
|
379 |
for(int s=0; s<mScalingFactor; s++) |
|
380 |
{ |
|
381 |
int ax = move[0]; |
|
382 |
int layer = move[1]; |
|
383 |
int quat = move[3]; |
|
384 |
|
|
385 |
if( mRotatable[ax][layer] && moveCanProceed(lastA,lastR,move[0],move[1]) ) |
|
386 |
{ |
|
387 |
int bitLayer = (1<<layer); |
|
388 |
System.arraycopy(quats, 0, tmp, 0, numQuats); |
|
389 |
|
|
390 |
for(int cubit=0; cubit<mNumCubits; cubit++) |
|
391 |
if( mRotRow[cubit][ax]==bitLayer ) |
|
392 |
{ |
|
393 |
int currQuat = tmp[cubit]; |
|
394 |
int newQuat = getMultQuat(quat,currQuat); |
|
395 |
tmp[cubit] = newQuat; |
|
396 |
} |
|
397 |
|
|
398 |
int childIndex = getIndex(tmp); |
|
399 |
if( childIndex==0 ) |
|
400 |
{ |
|
401 |
android.util.Log.e("D", "END: ax="+ax+" layer="+layer+" angle: "+move[2]); |
|
402 |
return true; |
|
403 |
} |
|
404 |
if( jump>1 && jumpZeroRecursive(childIndex, jump-1, depth+1, ax, layer, solution) ) |
|
405 |
{ |
|
406 |
android.util.Log.e("D", "REC: ax="+ax+" layer="+layer+" angle: "+move[2]); |
|
407 |
return true; |
|
408 |
} |
|
409 |
} |
|
410 |
|
|
411 |
getNextAxisLayerAngleQuat(move); |
|
412 |
} |
|
413 |
|
|
414 |
return false; |
|
415 |
} |
|
416 |
|
|
417 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
418 |
// ret: [0][] --> (?,old depth,?,?) ; [1...N-1][] --> moves. |
|
419 |
|
|
420 |
private int[][] jumpToZero(int index, int maxJump, int lastA, int lastR) |
|
421 |
{ |
|
422 |
int[][] solution = new int[maxJump+1][4]; |
|
423 |
|
|
424 |
for(int i=1; i<maxJump; i++) |
|
425 |
if( jumpZeroRecursive(index,i,1,lastA,lastR,solution) ) |
|
426 |
return solution; |
|
427 |
|
|
138 | 428 |
return null; |
139 | 429 |
} |
430 |
|
|
431 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
432 |
|
|
433 |
private int[][] concatenateMoves(int[][] high, int[][] jump1, int[][] mid, int[][] jump2) |
|
434 |
{ |
|
435 |
int len1 = high ==null ? 0 : high.length-1; |
|
436 |
int len2 = jump1==null ? 0 : jump1[0][1]; |
|
437 |
int len3 = mid ==null ? 0 : mid.length-1; |
|
438 |
int len4 = jump2==null ? 0 : jump2[0][1]; |
|
439 |
|
|
440 |
int[][] moves = new int[len1+len2+len3+len4][]; |
|
441 |
int index = 0; |
|
442 |
|
|
443 |
for(int i=0; i<len1; i++) moves[index++] = high[i+1]; |
|
444 |
for(int i=0; i<len2; i++) moves[index++] = jump1[i+1]; |
|
445 |
for(int i=0; i<len3; i++) moves[index++] = mid[i+1]; |
|
446 |
for(int i=0; i<len4; i++) moves[index++] = jump2[i+1]; |
|
447 |
|
|
448 |
convertMoves(moves); |
|
449 |
|
|
450 |
return moves; |
|
451 |
} |
|
452 |
|
|
453 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
454 |
|
|
455 |
public int[][] solution(int index, int[] extra) |
|
456 |
{ |
|
457 |
if( index==0 ) return null; |
|
458 |
int lastA=-1, lastR=0; |
|
459 |
int[][] highMoves = traverseBlock(index,mHighTables,lastA,lastR); |
|
460 |
|
|
461 |
if( highMoves!=null ) |
|
462 |
{ |
|
463 |
index = highMoves[0][0]; |
|
464 |
int len = highMoves.length; |
|
465 |
lastA = highMoves[len-1][0]; |
|
466 |
lastR = highMoves[len-1][1]; |
|
467 |
} |
|
468 |
|
|
469 |
int maxJump = Math.max(mLowestHigh-1-mHighestMid,mLowestMid/2); |
|
470 |
int[][] jump1Moves = jumpToMidOrZero(index,maxJump,lastA,lastR); |
|
471 |
|
|
472 |
if( jump1Moves!=null ) |
|
473 |
{ |
|
474 |
if( jump1Moves[0][0]==0 ) |
|
475 |
{ |
|
476 |
return concatenateMoves(null,null,null,jump1Moves); |
|
477 |
} |
|
478 |
if( jump1Moves[0][1]==mLowestMid ) |
|
479 |
{ |
|
480 |
int[][] jump2Moves = jumpToZero(index,mLowestMid-1,-1,0); |
|
481 |
if( jump2Moves==null ) throw new RuntimeException("1 error jumping to 0"); |
|
482 |
return concatenateMoves(null,null,null,jump2Moves); |
|
483 |
} |
|
484 |
|
|
485 |
index = jump1Moves[0][0]; |
|
486 |
int len = jump1Moves.length; |
|
487 |
lastA = jump1Moves[len-1][0]; |
|
488 |
lastR = jump1Moves[len-1][1]; |
|
489 |
} |
|
490 |
|
|
491 |
int[][] midMoves = traverseBlock(index,mMidTables,lastA,lastR); |
|
492 |
if( midMoves!=null ) |
|
493 |
{ |
|
494 |
index = midMoves[0][0]; |
|
495 |
int len = midMoves.length; |
|
496 |
lastA = midMoves[len-1][0]; |
|
497 |
lastR = midMoves[len-1][1]; |
|
498 |
} |
|
499 |
else throw new RuntimeException("error traversing mid Tables"); |
|
500 |
|
|
501 |
int[][] jump2Moves = jumpToZero(index,mLowestMid-1,lastA,lastR); |
|
502 |
if( jump2Moves==null ) throw new RuntimeException("2 error jumping to 0"); |
|
503 |
return concatenateMoves(highMoves,jump1Moves,midMoves,jump2Moves); |
|
504 |
} |
|
140 | 505 |
} |
Also available in: Unified diff
Progress with TablebasesPruning