Project

General

Profile

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

distorted-objectlib / src / main / java / org / distorted / objectlib / tablebases / TablebaseHelpers.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 java.util.Random;
13

    
14
///////////////////////////////////////////////////////////////////////////////////////////////////
15

    
16
public class TablebaseHelpers
17
{
18

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

    
21
  public static void displayTable(int[] table, String marker)
22
    {
23
    StringBuilder sb = new StringBuilder();
24

    
25
    for( int t : table )
26
      {
27
      sb.append(' ');
28
      sb.append(t);
29
      }
30

    
31
    android.util.Log.e("D", marker+" : "+sb);
32
    }
33

    
34
///////////////////////////////////////////////////////////////////////////////////////////////////
35

    
36
  private static String print(int[][] move)
37
    {
38
    StringBuilder sb = new StringBuilder();
39

    
40
    if( move==null )
41
      {
42
      return ("move NULL!!");
43
      }
44

    
45
    for (int[] ints : move)
46
      {
47
      sb.append(' ');
48
      sb.append('(');
49
      sb.append(ints[0]);
50
      sb.append(' ');
51
      sb.append(ints[1]);
52
      sb.append(' ');
53
      sb.append(ints[2]);
54
      sb.append(')');
55
      }
56

    
57
    return sb.toString();
58
    }
59

    
60
///////////////////////////////////////////////////////////////////////////////////////////////////
61

    
62
  public static void test(TablebasesAbstract tb)
63
    {
64
    int size = tb.getSize();
65

    
66
    for(int i=0; i<size; i++)
67
      {
68
      boolean success = tb.test(i);
69

    
70
      if( (!success && i>0) || (success && i==0) )
71
        {
72
        android.util.Log.e("D", "--------> FAILED: "+i);
73
        break;
74
        }
75

    
76
      if( (i%1000)==0 )   android.util.Log.e("D", "trying "+i);
77
      }
78
    }
79

    
80
///////////////////////////////////////////////////////////////////////////////////////////////////
81

    
82
  private final static int MAX_PERM=12;  // biggest N for which N! is still less than 2^32
83
  private final static int[] avail = new int[MAX_PERM];
84
  private final static int[] pos   = new int[MAX_PERM];
85
  private final static int[] fact  = new int[MAX_PERM];
86

    
87
  static
88
    {
89
    fact[0] = 1;
90
    for(int i=1; i<MAX_PERM; i++) fact[i] = fact[i-1]*i;
91
    }
92

    
93
///////////////////////////////////////////////////////////////////////////////////////////////////
94

    
95
  public static void getPermutationFromNum(int[] buffer,int permSize, int permNum)
96
    {
97
    avail[0] = pos[0] = 0;
98
    for(int i=1; i<permSize; i++) avail[i] = pos[i] = permSize-i;
99

    
100
    for(int i=0; i<permSize-1; i++)
101
      {
102
      int m = fact[permSize-1-i];
103
      int k = permNum/m;
104
      permNum %= m;
105
      buffer[i] = avail[k];
106
      int y = avail[permSize-1-i];
107
      pos[y] = k;
108
      avail[k] = y;
109
      }
110

    
111
    buffer[permSize-1] = avail[0];
112
    }
113

    
114
///////////////////////////////////////////////////////////////////////////////////////////////////
115
// Enumeration of permutations in linear time.
116
// 1) notice that 'avail' and 'pos' are always inverses: avail[m]=n iff pos[n]=m
117
// 2) notice that that implies that after the i-th execution of the loop, avail[0 ... n-1-i]
118
//    contains the n-i elements of the permutation we haven't scanned yet
119
//    ( that is because this is true initially, and during each loop, we remove avail[k] from
120
//      this list - but k = pos[buffer[i]] implies buffer[i] = avail[k] so we are really removing
121
//      buffer[i] - i.e. exactly the permutation element we have just scanned! )
122
// 3) each 'k' is a digit of the permutation in a strange ( n-1,n-2,...,2 ) notation where the most
123
//    significant digit can be one of the {0...,n-1}, the next most significant - one of the {0,...,n-2},
124
//    etc.
125
// 4) the ret = ret*(permSize-i) + k is a transform from this ( n-1,n-2,...,2 ) notation to an index.
126
//
127
// 'avail' is initially set to {0,n-1,n-2,...,2,1} because that implies that an 'empty' permutation
128
//  gets mapped to index=0.
129

    
130
  public static int computePermutationNum(int[] buffer)
131
    {
132
    int permSize = buffer.length;
133
    avail[0] = pos[0] = 0;
134
    for(int i=1; i<permSize; i++) avail[i] = pos[i] = permSize-i;
135

    
136
    int ret = 0;
137

    
138
    for(int i=0; i<permSize-1; i++)
139
      {
140
      int k = pos[buffer[i]];
141
      ret = ret*(permSize-i) + k;
142
      int y = avail[permSize-1-i];
143
      pos[y] = k;
144
      avail[k] = y;
145
      }
146

    
147
    return ret;
148
    }
149

    
150
///////////////////////////////////////////////////////////////////////////////////////////////////
151

    
152
  public static int computeEvenPermutationNum(int[] buffer)
153
    {
154
    int index = computePermutationNum(buffer);
155
    return index/2;
156
    }
157

    
158
///////////////////////////////////////////////////////////////////////////////////////////////////
159

    
160
  public static void getEvenPermutationFromNum(int[] buffer, int permNum)
161
    {
162
    getPermutationFromNum(buffer, buffer.length, 2*permNum);
163
    boolean even = permutationIsEven(buffer);
164
    if( !even ) getPermutationFromNum(buffer, buffer.length, 2*permNum+1 );
165
    }
166

    
167
///////////////////////////////////////////////////////////////////////////////////////////////////
168

    
169
  private static int swaps(int val, int[] buffer, int len)
170
    {
171
    int ret = 0;
172

    
173
    for(int i=0; i<len; i++)
174
      {
175
           if( buffer[i] >val ) ret++;
176
      else if( buffer[i]==val ) return ret;
177
      }
178

    
179
    return -1;
180
    }
181

    
182
///////////////////////////////////////////////////////////////////////////////////////////////////
183

    
184
  public static boolean permutationIsEven(int[] buffer)
185
    {
186
    int len = buffer.length;
187
    int numOfSwaps = 0;
188
    for(int i=0; i<len-1; i++) numOfSwaps += swaps(i,buffer,len);
189
    return (numOfSwaps%2==0);
190
    }
191

    
192
///////////////////////////////////////////////////////////////////////////////////////////////////
193

    
194
  public static void invertPermutation(int[] perm, int[] output)
195
    {
196
    int len = perm.length;
197
    for(int i=0; i<len; i++) output[i] = -1;
198
    for(int i=0; i<len; i++) output[perm[i]] = i;
199
    }
200
}
(17-17/19)