package cs.sq12phase; class Square { int edgeperm; //number encoding the edge permutation 0-40319 int cornperm; //number encoding the corner permutation 0-40319 boolean topEdgeFirst; //true if top layer starts with edge left of seam boolean botEdgeFirst; //true if bottom layer starts with edge right of seam int ml; //shape of middle layer (+/-1, or 0 if ignored) static byte[] SquarePrun = new byte[40320 * 2]; //pruning table; #twists to solve corner|edge permutation static char[] TwistMove = new char[40320]; //transition table for twists static char[] TopMove = new char[40320]; //transition table for top layer turns static char[] BottomMove = new char[40320]; //transition table for bottom layer turns private static int[] fact = {1, 1, 2, 6, 24, 120, 720, 5040}; static void set8Perm(byte[] arr, int idx) { int val = 0x76543210; for (int i=0; i<7; i++) { int p = fact[7-i]; int v = idx / p; idx -= v*p; v <<= 2; arr[i] = (byte) ((val >> v) & 07); int m = (1 << v) - 1; val = (val & m) + ((val >> 4) & ~m); } arr[7] = (byte)val; } static char get8Perm(byte[] arr) { int idx = 0; int val = 0x76543210; for (int i=0; i<7; i++) { int v = arr[i] << 2; idx = (8 - i) * idx + ((val >> v) & 07); val -= 0x11111110 << v; } return (char)idx; } static int[][] Cnk = new int[12][12]; static int get8Comb(byte[] arr) { int idx = 0, r = 4; for (int i=0; i<8; i++) { if (arr[i] >= 4) { idx += Cnk[7-i][r--]; } } return idx; } static boolean inited = false; static void init() { if (inited) { return; } for (int i=0; i<12; i++) { Cnk[i][0] = 1; Cnk[i][i] = 1; for (int j=1; j<i; j++) { Cnk[i][j] = Cnk[i-1][j-1] + Cnk[i-1][j]; } } byte[] pos = new byte[8]; byte temp; for(int i=0;i<40320;i++){ //twist set8Perm(pos, i); temp=pos[2];pos[2]=pos[4];pos[4]=temp; temp=pos[3];pos[3]=pos[5];pos[5]=temp; TwistMove[i]=get8Perm(pos); //top layer turn set8Perm(pos, i); temp=pos[0]; pos[0]=pos[1]; pos[1]=pos[2]; pos[2]=pos[3]; pos[3]=temp; TopMove[i]=get8Perm(pos); //bottom layer turn set8Perm(pos, i); temp=pos[4]; pos[4]=pos[5]; pos[5]=pos[6]; pos[6]=pos[7]; pos[7]=temp; BottomMove[i]=get8Perm(pos); } for (int i=0; i<40320*2; i++) { SquarePrun[i] = -1; } SquarePrun[0] = 0; int depth = 0; int done = 1; while (done < 40320 * 2) { boolean inv = depth >= 11; int find = inv ? -1 : depth; int check = inv ? depth : -1; ++depth; OUT: for (int i=0; i<40320*2; i++) { if (SquarePrun[i] == find) { int idx = i >> 1; int ml = i & 1; //try twist int idxx = TwistMove[idx]<<1 | (1-ml); if(SquarePrun[idxx] == check) { ++done; SquarePrun[inv ? i : idxx] = (byte) (depth); if (inv) { continue OUT; } } //try turning top layer idxx = idx; for(int m=0; m<4; m++) { idxx = TopMove[idxx]; if(SquarePrun[idxx<<1|ml] == check){ ++done; SquarePrun[inv ? i : (idxx<<1|ml)] = (byte) (depth); if (inv) { continue OUT; } } } assert idxx == idx; //try turning bottom layer for(int m=0; m<4; m++) { idxx = BottomMove[idxx]; if(SquarePrun[idxx<<1|ml] == check){ ++done; SquarePrun[inv ? i : (idxx<<1|ml)] = (byte) (depth); if (inv) { continue OUT; } } } } } System.out.print(depth); System.out.print('\t'); System.out.println(done); } inited = true; } }