diff options
Diffstat (limited to '')
145 files changed, 53517 insertions, 0 deletions
diff --git a/old/2020-unknown-date/cube_backup.c b/old/2020-unknown-date/cube_backup.c new file mode 100644 index 0000000..e049edd --- /dev/null +++ b/old/2020-unknown-date/cube_backup.c | |||
| @@ -0,0 +1,527 @@ | |||
| 1 | #include <stdio.h> | ||
| 2 | #include <string.h> | ||
| 3 | #include "cube.h" | ||
| 4 | |||
| 5 | /* The next few functions are used to convert from the Cube structure | ||
| 6 | * representation to actual arrays of pieces. */ | ||
| 7 | void cube_to_ep_array(Cube cube, int ep[12]); | ||
| 8 | void cube_to_eofb_array(Cube cube, int eo[12]); | ||
| 9 | void cube_to_eorl_array(Cube cube, int eo[12]); | ||
| 10 | void cube_to_eoud_array(Cube cube, int eo[12]); | ||
| 11 | void cube_to_cp_array(Cube cube, int cp[8]); | ||
| 12 | void cube_to_coud_array(Cube cube, int co[8]); | ||
| 13 | void cube_to_cofb_array(Cube cube, int co[8]); | ||
| 14 | void cube_to_corl_array(Cube cube, int co[8]); | ||
| 15 | void cube_to_centerpos_array(Cube cube, int centerpos[6]); | ||
| 16 | Cube ep_array_to_cube(int ep[12]); | ||
| 17 | Cube eofb_array_to_cube(int eo[12]); | ||
| 18 | Cube eorl_array_to_cube(int eo[12]); | ||
| 19 | Cube eoud_array_to_cube(int eo[12]); | ||
| 20 | Cube cp_array_to_cube(int cp[8]); | ||
| 21 | Cube coud_array_to_cube(int co[8]); | ||
| 22 | Cube cofb_array_to_cube(int co[8]); | ||
| 23 | Cube corl_array_to_cube(int co[8]); | ||
| 24 | Cube centerpos_array_to_cube(int centerpos[6]); | ||
| 25 | Cube move_array(Cube cube, void (cube_to_arr)(Cube, int *), | ||
| 26 | Cube (*arr_to_cube)(int *), | ||
| 27 | int *perm, int *orient, int n, int m); | ||
| 28 | |||
| 29 | |||
| 30 | /* Transition tables */ | ||
| 31 | int epose_ttable[NMOVES][factorial12/factorial8]; | ||
| 32 | int eposs_ttable[NMOVES][factorial12/factorial8]; | ||
| 33 | int eposm_ttable[NMOVES][factorial12/factorial8]; | ||
| 34 | int eofb_ttable[NMOVES][pow2to11]; | ||
| 35 | int eorl_ttable[NMOVES][pow2to11]; | ||
| 36 | int eoud_ttable[NMOVES][pow2to11]; | ||
| 37 | int cp_ttable[NMOVES][factorial8]; | ||
| 38 | int coud_ttable[NMOVES][pow3to7]; | ||
| 39 | int cofb_ttable[NMOVES][pow3to7]; | ||
| 40 | int corl_ttable[NMOVES][pow3to7]; | ||
| 41 | int centerpos_ttable[NMOVES][factorial6]; | ||
| 42 | |||
| 43 | char edge_string[12][5] = { | ||
| 44 | "UF", "UL", "UB", "UR", "DF", "DL", "DB", "DR", "FR", "FL", "BL", "BR" | ||
| 45 | }; | ||
| 46 | char corner_string[8][5] = { "UFR", "UFL", "UBL", "UBR", "DFR", "DFL", "DBL", "DBR" }; | ||
| 47 | char center_string[6][5] = { "U", "D", "R", "L", "F", "B" }; | ||
| 48 | char move_string[NMOVES][5] = { | ||
| 49 | "-", | ||
| 50 | "U", "U2", "U\'", "D", "D2", "D\'", "R", "R2", "R\'", | ||
| 51 | "L", "L2", "L\'", "F", "F2", "F\'", "B", "B2", "B\'", | ||
| 52 | "Uw", "Uw2", "Uw\'", "Dw", "Dw2", "Dw\'", "Rw", "Rw2", "Rw\'", | ||
| 53 | "Lw", "Lw2", "Lw\'", "Fw", "Fw2", "Fw\'", "Bw", "Bw2", "Bw\'", | ||
| 54 | "M", "M2", "M\'", "S", "S2", "S\'", "E", "E2", "E\'", | ||
| 55 | "x", "x2", "x\'", "y", "y2", "y\'", "z", "z2", "z\'", | ||
| 56 | }; | ||
| 57 | |||
| 58 | int epe_solved[] = {FR, FL, BL, BR}; | ||
| 59 | int eps_solved[] = {UL, UR, DL, DR}; | ||
| 60 | int epm_solved[] = {UF, UB, DF, DB}; | ||
| 61 | |||
| 62 | /**************************/ | ||
| 63 | /* Internal use functions */ | ||
| 64 | /**************************/ | ||
| 65 | |||
| 66 | int cube_to_ep_array(Cube cube, int ep[12]) { | ||
| 67 | int epe[4], eps[4], epm[4]; | ||
| 68 | index_to_perm(cube.epose % factorial(4), 4, epe); | ||
| 69 | index_to_perm(cube.eposs % factorial(4), 4, eps); | ||
| 70 | index_to_perm(cube.eposm % factorial(4), 4, epm); | ||
| 71 | |||
| 72 | int epose[12], eposs[12], eposm[12]; | ||
| 73 | index_to_subset(cube.epose / factorial(4), 12, 4, epose); | ||
| 74 | index_to_subset(cube.eposs / factorial(4), 12, 4, eposs); | ||
| 75 | index_to_subset(cube.eposm / factorial(4), 12, 4, eposm); | ||
| 76 | for (int i = 0; i < 4; i++) { | ||
| 77 | swap(&eposs[eps_solved[i]], &eposs[i+8]); | ||
| 78 | swap(&eposm[epm_solved[i]], &eposm[i+8]); | ||
| 79 | } | ||
| 80 | |||
| 81 | for (int i = 0, ie = 0, is = 0, im = 0; i < 12; i++) { | ||
| 82 | if (epose[i]) ep[i] = epe_solved[epe[ie++]]; | ||
| 83 | if (eposs[i]) ep[i] = eps_solved[eps[is++]]; | ||
| 84 | if (eposm[i]) ep[i] = epm_solved[epm[im++]]; | ||
| 85 | } | ||
| 86 | } | ||
| 87 | |||
| 88 | void cube_to_eofb_array(Cube cube, int eo[12]) { | ||
| 89 | int_to_sum_zero_array(cube.eofb, 2, 12, eo); | ||
| 90 | } | ||
| 91 | |||
| 92 | void cube_to_eorl_array(Cube cube, int eo[12]) { | ||
| 93 | int_to_sum_zero_array(cube.eorl, 2, 12, eo); | ||
| 94 | } | ||
| 95 | |||
| 96 | void cube_to_eoud_array(Cube cube, int eo[12]) { | ||
| 97 | int_to_sum_zero_array(cube.eoud, 2, 12, eo); | ||
| 98 | } | ||
| 99 | |||
| 100 | void cube_to_cp_array(Cube cube, int cp[8]) { | ||
| 101 | index_to_perm(cube.cp, 8, cp); | ||
| 102 | } | ||
| 103 | |||
| 104 | void cube_to_coud_array(Cube cube, int co[8]) { | ||
| 105 | int_to_sum_zero_array(cube.coud, 3, 8, co); | ||
| 106 | } | ||
| 107 | |||
| 108 | void cube_to_cofb_array(Cube cube, int co[8]) { | ||
| 109 | int_to_sum_zero_array(cube.cofb, 3, 8, co); | ||
| 110 | } | ||
| 111 | |||
| 112 | void cube_to_corl_array(Cube cube, int co[8]) { | ||
| 113 | int_to_sum_zero_array(cube.corl, 3, 8, co); | ||
| 114 | } | ||
| 115 | |||
| 116 | void cube_to_centerpos_array(Cube cube, int centerpos[6]) { | ||
| 117 | index_to_perm(cube.centerpos, 6, centerpos); | ||
| 118 | } | ||
| 119 | |||
| 120 | Cube ep_array_to_cube(int ep[12]) { | ||
| 121 | int epe[4], eps[4], epm[4]; | ||
| 122 | int epose[12] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; | ||
| 123 | int eposs[12] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; | ||
| 124 | int eposm[12] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; | ||
| 125 | for (int i = 0, ie = 0, is = 0, im = 0; i < 12; i++) { | ||
| 126 | for (int j = 0; j < 4; j++) { | ||
| 127 | if (ep[i] == epe_solved[j]) { epe[ie++] = j; epose[i] = 1; } | ||
| 128 | if (ep[i] == eps_solved[j]) { eps[is++] = j; eposs[i] = 1; } | ||
| 129 | if (ep[i] == epm_solved[j]) { epm[im++] = j; eposm[i] = 1; } | ||
| 130 | } | ||
| 131 | } | ||
| 132 | for (int i = 0; i < 4; i++) { | ||
| 133 | swap(&eposs[eps_solved[i]], &eposs[i+8]); | ||
| 134 | swap(&eposm[epm_solved[i]], &eposm[i+8]); | ||
| 135 | } | ||
| 136 | return { .epose = factorial(4) * subset_to_index(epose, 12, 4) | ||
| 137 | + perm_to_index(epe, 4), | ||
| 138 | .eposs = factorial(4) * subset_to_index(eposs, 12, 4) | ||
| 139 | + perm_to_index(eps, 4), | ||
| 140 | .eposm = factorial(4) * subset_to_index(eposm, 12, 4) | ||
| 141 | + perm_to_index(epm, 4) }; | ||
| 142 | } | ||
| 143 | |||
| 144 | Cube eofb_array_to_cube(int eo[12]) { | ||
| 145 | return { .eofb = digit_array_to_int(eo, 11, 2) }; | ||
| 146 | } | ||
| 147 | |||
| 148 | Cube eorl_array_to_cube(int eo[12]) { | ||
| 149 | return { .eorl = digit_array_to_int(eo, 11, 2) }; | ||
| 150 | } | ||
| 151 | |||
| 152 | Cube eoud_array_to_cube(int eo[12]) { | ||
| 153 | return { .eoud = digit_array_to_int(eo, 11, 2) }; | ||
| 154 | } | ||
| 155 | |||
| 156 | Cube cp_array_to_cube(int cp[8]) { | ||
| 157 | return { .cp = perm_to_index(cp, 8) }; | ||
| 158 | } | ||
| 159 | |||
| 160 | Cube coud_array_to_cube(int co[8]) { | ||
| 161 | return { .coud = digit_array_to_int(co, 7, 3) }; | ||
| 162 | } | ||
| 163 | |||
| 164 | Cube cofb_array_to_cube(int co[8]) { | ||
| 165 | return { .cofb = digit_array_to_int(co, 7, 3) }; | ||
| 166 | } | ||
| 167 | |||
| 168 | Cube corl_array_to_cube(int co[8]) { | ||
| 169 | return { .corl = digit_array_to_int(co, 7, 3) }; | ||
| 170 | } | ||
| 171 | |||
| 172 | Cube centerpos_array_to_cube(int centerpos[6]) { | ||
| 173 | return { .centerpos = perm_to_index(centerpos, 6) }; | ||
| 174 | } | ||
| 175 | |||
| 176 | Cube move_array(Cube cube, void (*cube_to_arr)(Cube, int *), | ||
| 177 | void (*arr_to_cube)(int *), | ||
| 178 | int *perm, int *orient, int n, int m) { | ||
| 179 | int arr[n]; | ||
| 180 | cube_to_arr(cube, arr); | ||
| 181 | apply_permutation(perm, arr, n); | ||
| 182 | sum_arrays_mod(arr, orient, n, m); | ||
| 183 | return arr_to_cube(arr); | ||
| 184 | } | ||
| 185 | |||
| 186 | /***********************/ | ||
| 187 | /* Interface functions */ | ||
| 188 | /***********************/ | ||
| 189 | |||
| 190 | Move inverse(Move m) { | ||
| 191 | if (m == NULLMOVE) | ||
| 192 | return m; | ||
| 193 | int mod = (m-1)%3; | ||
| 194 | Move base = m - mod; | ||
| 195 | return base + 2 - mod; | ||
| 196 | } | ||
| 197 | |||
| 198 | void copy_alg(NissMove *src, NissMove *dest) { | ||
| 199 | for (int i = 0; src[i].m != NULLMOVE; i++) | ||
| 200 | dest[i] = src[i]; | ||
| 201 | } | ||
| 202 | |||
| 203 | bool commute(Move m1, Move m2) { | ||
| 204 | return equal(apply_move(m2, apply_move(m1, {0})), | ||
| 205 | apply_move(m1, apply_move(m2, {0}))); | ||
| 206 | } | ||
| 207 | |||
| 208 | bool equal(Cube c1, Cube c2) { | ||
| 209 | return c1.eofb == c2.eofb && c1.epose == c2.epose && | ||
| 210 | c1.eposs == c2.eposs && c1.eposm == c2.eposm && | ||
| 211 | c1.coud == c2.coud && c1.cp == c2.cp && | ||
| 212 | c1.centerpos == c2.centerpos; | ||
| 213 | } | ||
| 214 | |||
| 215 | bool solvable(Cube cube) { | ||
| 216 | /* Since we memorize orientation truncating the last digit, we only need to | ||
| 217 | * check that the permutations have the correct sign. */ | ||
| 218 | /* TODO: add check that every integer is in range */ | ||
| 219 | int ep[12], cp[12], c[6]; | ||
| 220 | /* TODO: change to use cube-specific functions */ | ||
| 221 | cube_to_ep_array(cube, ep); | ||
| 222 | cube_to_cp_array(cube, 8, cp); | ||
| 223 | cube_to_centerpos_array(cube, 6, c); | ||
| 224 | return (perm_sign(ep, 12) ^ perm_sign(c, 6)) == perm_sign(cp, 8); | ||
| 225 | } | ||
| 226 | |||
| 227 | bool is_solved(Cube cube) { | ||
| 228 | return (!cube.eofb && !cube.coud && !cube.cp && | ||
| 229 | !cube.epose && !cube.eposs && !cube.eposm && !cube.centerpos); | ||
| 230 | } | ||
| 231 | |||
| 232 | char *to_string(Cube cube) { | ||
| 233 | int eo[12], co[8], ep[12], cp[8], cenpos[6]; | ||
| 234 | cube_to_eofb_array(cube, eo); | ||
| 235 | cube_to_coud_array(cube, co); | ||
| 236 | cube_to_ep_array(cube, ep); | ||
| 237 | cube_to_cp_array(cube, cp); | ||
| 238 | cube_to_centerpos_array(cube, cenpos); | ||
| 239 | |||
| 240 | static char ret[1000]; | ||
| 241 | |||
| 242 | for (int i = 0; i < 12; i++) { | ||
| 243 | strcat(ret, " "); | ||
| 244 | strcat(ret, edge_string[ep[i]]); | ||
| 245 | strcat(ret, " "); | ||
| 246 | } | ||
| 247 | strcat(ret, "\n"); | ||
| 248 | for (int i = 0; i < 12; i++) { | ||
| 249 | strcat(ret, " "); | ||
| 250 | char num[2] = { [0] = eo[i] + '0', [1] = 0 }; | ||
| 251 | strcat(ret, num); | ||
| 252 | strcat(ret, " "); | ||
| 253 | } | ||
| 254 | strcat(ret, "\n"); | ||
| 255 | for (int i = 0; i < 8; i++) { | ||
| 256 | strcat(ret, corner_string[cp[i]]); | ||
| 257 | strcat(ret, " "); | ||
| 258 | } | ||
| 259 | strcat(ret, "\n"); | ||
| 260 | for (int i = 0; i < 8; i++) { | ||
| 261 | strcat(ret, " "); | ||
| 262 | char num[2] = { [0] = co[i] + '0', [1] = 0 }; | ||
| 263 | strcat(ret, num); | ||
| 264 | strcat(ret, " "); | ||
| 265 | } | ||
| 266 | strcat(ret, "\n"); | ||
| 267 | for (int i = 0; i < 6; i++) { | ||
| 268 | strcat(ret, " "); | ||
| 269 | strcat(ret, center_string[cenpos[i]]); | ||
| 270 | strcat(ret, " "); | ||
| 271 | } | ||
| 272 | strcat(ret, "\n"); | ||
| 273 | |||
| 274 | return ret; | ||
| 275 | } | ||
| 276 | |||
| 277 | void init_ttables() { | ||
| 278 | FILE *ttf; | ||
| 279 | |||
| 280 | if ((ttf = fopen("ttables", "rb")) != NULL) { | ||
| 281 | for (int m = 0; m < NMOVES; m++) { | ||
| 282 | fread(epose_ttable[m], sizeof(int), factorial12/factorial8, ttf); | ||
| 283 | fread(eposs_ttable[m], sizeof(int), factorial12/factorial8, ttf); | ||
| 284 | fread(eposm_ttable[m], sizeof(int), factorial12/factorial8, ttf); | ||
| 285 | fread(eofb_ttable[m], sizeof(int), pow2to11, ttf); | ||
| 286 | fread(eorl_ttable[m], sizeof(int), pow2to11, ttf); | ||
| 287 | fread(eoud_ttable[m], sizeof(int), pow2to11, ttf); | ||
| 288 | fread(cp_ttable[m], sizeof(int), factorial8, ttf); | ||
| 289 | fread(coud_ttable[m], sizeof(int), pow3to7, ttf); | ||
| 290 | fread(corl_ttable[m], sizeof(int), pow3to7, ttf); | ||
| 291 | fread(cofb_ttable[m], sizeof(int), pow3to7, ttf); | ||
| 292 | fread(centerpos_ttable[m], sizeof(int), factorial6, ttf); | ||
| 293 | } | ||
| 294 | fclose(ttf); | ||
| 295 | } else { | ||
| 296 | ttf = fopen("ttables", "wb"); | ||
| 297 | int empty[12] = {0,0,0,0,0,0,0,0,0,0,0,0}; | ||
| 298 | /* For each type of pieces only the effects of U, x and y are described */ | ||
| 299 | int edge_cycle[NMOVES][12] = { | ||
| 300 | [U] = {UR, UF, UL, UB, DF, DL, DB, DR, FR, FL, BL, BR}, | ||
| 301 | [X] = {DF, FL, UF, FR, DB, BL, UB, BR, DR, DL, UL, UR}, | ||
| 302 | [Y] = {UR, UF, UL, UB, DR, DF, DL, DB, BR, FR, FL, BL}, | ||
| 303 | }; | ||
| 304 | int eofb_flipped[NMOVES][12] = { | ||
| 305 | [X] = { [UF] = 1, [UB] = 1, [DF] = 1, [DB] = 1 }, | ||
| 306 | [Y] = { [FR] = 1, [FL] = 1, [BL] = 1, [BR] = 1 }, | ||
| 307 | }; | ||
| 308 | int eorl_flipped[NMOVES][12] = { | ||
| 309 | [X] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, | ||
| 310 | [Y] = { [FR] = 1, [FL] = 1, [BL] = 1, [BR] = 1 }, | ||
| 311 | }; | ||
| 312 | int eoud_flipped[NMOVES][12] = { | ||
| 313 | [U] = { [UF] = 1, [UL] = 1, [UB] = 1, [UR] = 1 }, | ||
| 314 | [X] = { [UF] = 1, [UB] = 1, [DF] = 1, [DB] = 1 }, | ||
| 315 | [Y] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, | ||
| 316 | }; | ||
| 317 | int corner_cycle[NMOVES][8] = { | ||
| 318 | [U] = {UBR, UFR, UFL, UBL, DFR, DFL, DBL, DBR}, | ||
| 319 | [X] = {DFR, DFL, UFL, UFR, DBR, DBL, UBL, UBR}, | ||
| 320 | [Y] = {UBR, UFR, UFL, UBL, DBR, DFR, DFL, DBL}, | ||
| 321 | }; | ||
| 322 | int coud_flipped[NMOVES][8] = { | ||
| 323 | [X] = {[UFR]=2,[UBR]=1,[DBR]=2,[DFR]=1,[UFL]=1,[UBL]=2,[DBL]=1,[DFL]=2}, | ||
| 324 | }; | ||
| 325 | int corl_flipped[NMOVES][8] = { | ||
| 326 | [U] = { [UFR] = 1, [UBR] = 2, [UBL] = 1, [UFL] = 2 }, | ||
| 327 | [Y] = {[UFR]=1,[UBR]=2,[UBL]=1,[UFL]=2,[DFR]=2,[DBR]=1,[DBL]=2,[DFL]=1}, | ||
| 328 | }; | ||
| 329 | int cofb_flipped[NMOVES][8] = { | ||
| 330 | [U] = { [UFR] = 2, [UBR] = 1, [UBL] = 2, [UFL] = 1 }, | ||
| 331 | [X] = {[UFR]=1,[UBR]=2,[DFR]=2,[DBR]=1,[UBL]=2,[UFL]=1,[DBL]=1,[DFL]=2}, | ||
| 332 | [Y] = {[UFR]=2,[UBR]=1,[UBL]=2,[UFL]=1,[DFR]=1,[DBR]=2,[DBL]=1,[DFL]=2}, | ||
| 333 | }; | ||
| 334 | int center_cycle[NMOVES][6] = { | ||
| 335 | [X] = {F_center, B_center, R_center, L_center, D_center, U_center}, | ||
| 336 | [Y] = {U_center, D_center, B_center, F_center, R_center, L_center}, | ||
| 337 | }; | ||
| 338 | |||
| 339 | /* Each move is reduced to a combination of U, x and y using this table */ | ||
| 340 | Move equiv_moves[NMOVES][13] = { | ||
| 341 | [U] = { U, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, | ||
| 342 | [U2] = { U, U, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, | ||
| 343 | [U3] = { U, U, U, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, | ||
| 344 | [D] = { X, X, U, X, X, 0, 0, 0, 0, 0, 0, 0, 0 }, | ||
| 345 | [D2] = { X, X, U, U, X, X, 0, 0, 0, 0, 0, 0, 0 }, | ||
| 346 | [D3] = { X, X, U, U, U, X, X, 0, 0, 0, 0, 0, 0 }, | ||
| 347 | [R] = { Y, X, U, X, X, X, Y, Y, Y, 0, 0, 0, 0 }, | ||
| 348 | [R2] = { Y, X, U, U, X, X, X, Y, Y, Y, 0, 0, 0 }, | ||
| 349 | [R3] = { Y, X, U, U, U, X, X, X, Y, Y, Y, 0, 0 }, | ||
| 350 | [L] = { Y, Y, Y, X, U, X, X, X, Y, 0, 0, 0, 0 }, | ||
| 351 | [L2] = { Y, Y, Y, X, U, U, X, X, X, Y, 0, 0, 0 }, | ||
| 352 | [L3] = { Y, Y, Y, X, U, U, U, X, X, X, Y, 0, 0 }, | ||
| 353 | [F] = { X, U, X, X, X, 0, 0, 0, 0, 0, 0, 0, 0 }, | ||
| 354 | [F2] = { X, U, U, X, X, X, 0, 0, 0, 0, 0, 0, 0 }, | ||
| 355 | [F3] = { X, U, U, U, X, X, X, 0, 0, 0, 0, 0, 0 }, | ||
| 356 | [B] = { X, X, X, U, X, 0, 0, 0, 0, 0, 0, 0, 0 }, | ||
| 357 | [B2] = { X, X, X, U, U, X, 0, 0, 0, 0, 0, 0, 0 }, | ||
| 358 | [B3] = { X, X, X, U, U, U, X, 0, 0, 0, 0, 0, 0 }, | ||
| 359 | |||
| 360 | [Uw] = { X, X, U, X, X, Y, 0, 0, 0, 0, 0, 0, 0 }, | ||
| 361 | [Uw2] = { X, X, U, U, X, X, Y, Y, 0, 0, 0, 0, 0 }, | ||
| 362 | [Uw3] = { X, X, U, U, U, X, X, Y, Y, Y, 0, 0, 0 }, | ||
| 363 | [Dw] = { U, Y, Y, Y, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, | ||
| 364 | [Dw2] = { U, U, Y, Y, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, | ||
| 365 | [Dw3] = { U, U, U, Y, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, | ||
| 366 | [Rw] = { Y, Y, Y, X, U, X, X, X, Y, X, 0, 0, 0 }, | ||
| 367 | [Rw2] = { Y, Y, Y, X, U, U, X, X, X, Y, X, X, 0 }, | ||
| 368 | [Rw3] = { Y, Y, Y, X, U, U, U, Y, X, X, X, Y, 0 }, | ||
| 369 | [Lw] = { Y, X, U, X, X, X, Y, Y, Y, X, X, X, 0 }, | ||
| 370 | [Lw2] = { Y, X, U, U, X, X, X, Y, Y, Y, X, X, 0 }, | ||
| 371 | [Lw3] = { Y, X, U, U, U, X, X, X, Y, Y, Y, X, 0 }, | ||
| 372 | [Fw] = { X, X, X, U, Y, Y, Y, X, 0, 0, 0, 0, 0 }, | ||
| 373 | [Fw2] = { X, X, X, U, U, Y, Y, X, 0, 0, 0, 0, 0 }, | ||
| 374 | [Fw3] = { X, X, X, U, U, U, Y, X, 0, 0, 0, 0, 0 }, | ||
| 375 | [Bw] = { X, U, Y, Y, Y, X, X, X, 0, 0, 0, 0, 0 }, | ||
| 376 | [Bw2] = { X, U, U, Y, Y, X, X, X, 0, 0, 0, 0, 0 }, | ||
| 377 | [Bw3] = { X, U, U, U, Y, X, X, X, 0, 0, 0, 0, 0 }, | ||
| 378 | |||
| 379 | [M] = { Y, X, U, X, X, U, U, U, Y, X, Y, Y, Y }, | ||
| 380 | [M2] = { Y, X, U, U, X, X, U, U, X, X, X, Y, 0 }, | ||
| 381 | [M3] = { Y, X, U, U, U, X, X, U, Y, X, X, X, Y }, | ||
| 382 | [S] = { X, U, U, U, X, X, U, Y, Y, Y, X, 0, 0 }, | ||
| 383 | [S2] = { X, U, U, X, X, U, U, Y, Y, X, 0, 0, 0 }, | ||
| 384 | [S3] = { X, U, X, X, U, U, U, Y, X, 0, 0, 0, 0 }, | ||
| 385 | [E] = { U, X, X, U, U, U, X, X, Y, Y, Y, 0, 0 }, | ||
| 386 | [E2] = { U, U, X, X, U, U, X, X, Y, Y, 0, 0, 0 }, | ||
| 387 | [E3] = { U, U, U, X, X, U, X, X, Y, 0, 0, 0, 0 }, | ||
| 388 | |||
| 389 | [X] = { X, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, | ||
| 390 | [X2] = { X, X, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, | ||
| 391 | [X3] = { X, X, X, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, | ||
| 392 | [Y] = { Y, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, | ||
| 393 | [Y2] = { Y, Y, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, | ||
| 394 | [Y3] = { Y, Y, Y, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, | ||
| 395 | [Z] = { Y, Y, Y, X, Y, 0, 0, 0, 0, 0, 0, 0, 0 }, | ||
| 396 | [Z2] = { Y, Y, X, X, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, | ||
| 397 | [Z3] = { Y, X, Y, Y, Y, 0, 0, 0, 0, 0, 0, 0, 0 }, | ||
| 398 | }; | ||
| 399 | |||
| 400 | /* Generate all move cycles and flips */ | ||
| 401 | for (int i = 0; i < NMOVES; i++) { | ||
| 402 | if (i == U || i == X || i == Y) | ||
| 403 | continue; | ||
| 404 | |||
| 405 | Cube cube = {0}; | ||
| 406 | |||
| 407 | cube_to_ep_array(&cube, edge_cycle[i]); | ||
| 408 | cube_to_eofb_array(&cube, eofb_flipped[i]); | ||
| 409 | cube_to_eorl_array(&cube, eorl_flipped[i]); | ||
| 410 | cube_to_eoud_array(&cube, eoud_flipped[i]); | ||
| 411 | cube_to_cp_array(&cube, corner_cycle[i]); | ||
| 412 | cube_to_coud_array(&cube, coud_flipped[i]); | ||
| 413 | cube_to_cofb_array(&cube, cofb_flipped[i]); | ||
| 414 | cube_to_corl_array(&cube, corl_flipped[i]); | ||
| 415 | cube_to_centerpos_array(&cube, center_cycle[i]); | ||
| 416 | |||
| 417 | for (int j = 0; equiv_moves[i][j]; j++) { | ||
| 418 | int m = equiv_moves[i][j]; | ||
| 419 | |||
| 420 | apply_permutation(edge_cycle[m], edge_cycle[i], 12); | ||
| 421 | apply_permutation(edge_cycle[m], eofb_flipped[i], 12); | ||
| 422 | apply_permutation(edge_cycle[m], eorl_flipped[i], 12); | ||
| 423 | apply_permutation(edge_cycle[m], eoud_flipped[i], 12); | ||
| 424 | |||
| 425 | sum_arrays_mod(eofb_flipped[i], eofb_flipped[m], 12, 2); | ||
| 426 | sum_arrays_mod(eorl_flipped[i], eorl_flipped[m], 12, 2); | ||
| 427 | sum_arrays_mod(eoud_flipped[i], eoud_flipped[m], 12, 2); | ||
| 428 | |||
| 429 | apply_permutation(corner_cycle[m], corner_cycle[i], 8); | ||
| 430 | apply_permutation(corner_cycle[m], coud_flipped[i], 8); | ||
| 431 | apply_permutation(corner_cycle[m], cofb_flipped[i], 8); | ||
| 432 | apply_permutation(corner_cycle[m], corl_flipped[i], 8); | ||
| 433 | |||
| 434 | sum_arrays_mod(coud_flipped[i], coud_flipped[m], 8, 3); | ||
| 435 | sum_arrays_mod(corl_flipped[i], corl_flipped[m], 8, 3); | ||
| 436 | sum_arrays_mod(cofb_flipped[i], cofb_flipped[m], 8, 3); | ||
| 437 | |||
| 438 | apply_permutation(center_cycle[m], center_cycle[i], 6); | ||
| 439 | } | ||
| 440 | } | ||
| 441 | |||
| 442 | /* Initialize transition tables */ | ||
| 443 | for (int m = 0; m < NMOVES; m++) { | ||
| 444 | for (int i = 0; i < factorial12/factorial8; i++) { | ||
| 445 | Cube cube = { .epose = i }; | ||
| 446 | move_array(&cube, cube_to_ep_array, ep_array_to_cube, | ||
| 447 | edge_cycle[m], empty, 12, 1); | ||
| 448 | epose_ttable[m][i] = cube.epose; | ||
| 449 | cube.eposs = i; | ||
| 450 | move_array(&cube, cube_to_ep_array, ep_array_to_cube, | ||
| 451 | edge_cycle[m], empty, 12, 1); | ||
| 452 | eposs_ttable[m][i] = cube.eposs; | ||
| 453 | cube.eposm = i; | ||
| 454 | move_array(&cube, cube_to_ep_array, ep_array_to_cube, | ||
| 455 | edge_cycle[m], empty, 12, 1); | ||
| 456 | eposm_ttable[m][i] = cube.eposm; | ||
| 457 | } | ||
| 458 | for (int i = 0; i < pow2to11; i++ ) { | ||
| 459 | Cube cube = { .eofb = i, .eorl = i, .eoud = i }; | ||
| 460 | move_array(&cube, cube_to_eofb_array, eofb_array_to_cube, | ||
| 461 | edge_cycle[m], eofb_flipped[m], 12, 2); | ||
| 462 | move_array(&cube, cube_to_eorl_array, eorl_array_to_cube, | ||
| 463 | edge_cycle[m], eorl_flipped[m], 12, 2); | ||
| 464 | move_array(&cube, cube_to_eoud_array, eoud_array_to_cube, | ||
| 465 | edge_cycle[m], eoud_flipped[m], 12, 2); | ||
| 466 | eofb_ttable[m][i] = cube.eofb; | ||
| 467 | eorl_ttable[m][i] = cube.eorl; | ||
| 468 | eoud_ttable[m][i] = cube.eoud; | ||
| 469 | } | ||
| 470 | for (int i = 0; i < factorial8; i++) { | ||
| 471 | /* TODO: Maybe do this by hand to optimize? */ | ||
| 472 | Cube cube = { .cp = i }; | ||
| 473 | move_array(&cube, cube_to_cp_array, ep_array_to_cube, | ||
| 474 | corner_cycle[m], empty, 8, 1); | ||
| 475 | cp_ttable[m][i] = cube.cp; | ||
| 476 | } | ||
| 477 | for (int i = 0; i < pow3to7; i++) { | ||
| 478 | Cube cube = { .coud = i, .corl = i, .cofb = i }; | ||
| 479 | move_array(&cube, cube_to_coud_array, coud_array_to_cube, | ||
| 480 | corner_cycle[m], coud_flipped[m], 8, 3); | ||
| 481 | move_array(&cube, cube_to_corl_array, corl_array_to_cube, | ||
| 482 | corner_cycle[m], corl_flipped[m], 8, 3); | ||
| 483 | move_array(&cube, cube_to_cofb_array, cofb_array_to_cube, | ||
| 484 | corner_cycle[m], cofb_flipped[m], 8, 3); | ||
| 485 | coud_ttable[m][i] = cube.coud; | ||
| 486 | corl_ttable[m][i] = cube.corl; | ||
| 487 | cofb_ttable[m][i] = cube.cofb; | ||
| 488 | } | ||
| 489 | for (int i = 0; i < factorial6; i++) { | ||
| 490 | Cube cube = { .centerpos = i }; | ||
| 491 | move_array(&cube, cube_to_centerpos_array, centerpos_array_to_cube, | ||
| 492 | center_cycle[m], empty, 6, 1); | ||
| 493 | centerpos_ttable[m][i] = cube.centerpos; | ||
| 494 | } | ||
| 495 | fwrite(epose_ttable[m], sizeof(int), factorial12/factorial8, ttf); | ||
| 496 | fwrite(eposs_ttable[m], sizeof(int), factorial12/factorial8, ttf); | ||
| 497 | fwrite(eposm_ttable[m], sizeof(int), factorial12/factorial8, ttf); | ||
| 498 | fwrite(eofb_ttable[m], sizeof(int), pow2to11, ttf); | ||
| 499 | fwrite(eorl_ttable[m], sizeof(int), pow2to11, ttf); | ||
| 500 | fwrite(eoud_ttable[m], sizeof(int), pow2to11, ttf); | ||
| 501 | fwrite(cp_ttable[m], sizeof(int), factorial8, ttf); | ||
| 502 | fwrite(coud_ttable[m], sizeof(int), pow3to7, ttf); | ||
| 503 | fwrite(corl_ttable[m], sizeof(int), pow3to7, ttf); | ||
| 504 | fwrite(cofb_ttable[m], sizeof(int), pow3to7, ttf); | ||
| 505 | fwrite(centerpos_ttable[m], sizeof(int), factorial6, ttf); | ||
| 506 | } | ||
| 507 | fclose(ttf); | ||
| 508 | } | ||
| 509 | } | ||
| 510 | |||
| 511 | Cube apply_move(Move m, Cube cube) { | ||
| 512 | Cube moved = cube; | ||
| 513 | |||
| 514 | moved.eofb = eofb_ttable[m][cube.eofb]; | ||
| 515 | moved.eorl = eorl_ttable[m][cube.eorl]; | ||
| 516 | moved.eoud = eoud_ttable[m][cube.eoud]; | ||
| 517 | moved.coud = coud_ttable[m][cube.coud]; | ||
| 518 | moved.cofb = cofb_ttable[m][cube.cofb]; | ||
| 519 | moved.corl = corl_ttable[m][cube.corl]; | ||
| 520 | moved.epose = epose_ttable[m][cube.epose]; | ||
| 521 | moved.eposs = eposs_ttable[m][cube.eposs]; | ||
| 522 | moved.eposm = eposm_ttable[m][cube.eposm]; | ||
| 523 | moved.cp = cp_ttable[m][cube.cp]; | ||
| 524 | moved.centerpos = centerpos_ttable[m][cube.centerpos]; | ||
| 525 | |||
| 526 | return moved; | ||
| 527 | } | ||
diff --git a/old/2020-unknown-date/cubeutils.c b/old/2020-unknown-date/cubeutils.c new file mode 100644 index 0000000..4f0a060 --- /dev/null +++ b/old/2020-unknown-date/cubeutils.c | |||
| @@ -0,0 +1,100 @@ | |||
| 1 | #include <stdio.h> | ||
| 2 | #include "utils.h" | ||
| 3 | #include "pieces.h" | ||
| 4 | #include "cubeutils.h" | ||
| 5 | |||
| 6 | int epe_solved[] = {FR, FL, BL, BR}; | ||
| 7 | int eps_solved[] = {UL, UR, DL, DR}; | ||
| 8 | int epm_solved[] = {UF, UB, DF, DB}; | ||
| 9 | |||
| 10 | void cube_to_ep_array(Cube *cube, int ep[12]) { | ||
| 11 | int epe[4], eps[4], epm[4]; | ||
| 12 | index_to_perm(cube->epose % factorial(4), 4, epe); | ||
| 13 | index_to_perm(cube->eposs % factorial(4), 4, eps); | ||
| 14 | index_to_perm(cube->eposm % factorial(4), 4, epm); | ||
| 15 | |||
| 16 | int epose[12], eposs[12], eposm[12]; | ||
| 17 | index_to_subset(cube->epose / factorial(4), 12, 4, epose); | ||
| 18 | index_to_subset(cube->eposs / factorial(4), 12, 4, eposs); | ||
| 19 | index_to_subset(cube->eposm / factorial(4), 12, 4, eposm); | ||
| 20 | for (int i = 0; i < 4; i++) { | ||
| 21 | swap(&eposs[eps_solved[i]], &eposs[i+8]); | ||
| 22 | swap(&eposm[epm_solved[i]], &eposm[i+8]); | ||
| 23 | } | ||
| 24 | |||
| 25 | for (int i = 0, ie = 0, is = 0, im = 0; i < 12; i++) { | ||
| 26 | if (epose[i]) ep[i] = epe_solved[epe[ie++]]; | ||
| 27 | if (eposs[i]) ep[i] = eps_solved[eps[is++]]; | ||
| 28 | if (eposm[i]) ep[i] = epm_solved[epm[im++]]; | ||
| 29 | } | ||
| 30 | } | ||
| 31 | |||
| 32 | void ep_array_to_epos(int ep[12], Cube *cube) { | ||
| 33 | int epe[4], eps[4], epm[4]; | ||
| 34 | int epose[12] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; | ||
| 35 | int eposs[12] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; | ||
| 36 | int eposm[12] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; | ||
| 37 | for (int i = 0, ie = 0, is = 0, im = 0; i < 12; i++) { | ||
| 38 | for (int j = 0; j < 4; j++) { | ||
| 39 | if (ep[i] == epe_solved[j]) { epe[ie++] = j; epose[i] = 1; } | ||
| 40 | if (ep[i] == eps_solved[j]) { eps[is++] = j; eposs[i] = 1; } | ||
| 41 | if (ep[i] == epm_solved[j]) { epm[im++] = j; eposm[i] = 1; } | ||
| 42 | } | ||
| 43 | } | ||
| 44 | for (int i = 0; i < 4; i++) { | ||
| 45 | swap(&eposs[eps_solved[i]], &eposs[i+8]); | ||
| 46 | swap(&eposm[epm_solved[i]], &eposm[i+8]); | ||
| 47 | } | ||
| 48 | cube->epose = factorial(4) * subset_to_index(epose, 12, 4) | ||
| 49 | + perm_to_index(epe, 4); | ||
| 50 | cube->eposs = factorial(4) * subset_to_index(eposs, 12, 4) | ||
| 51 | + perm_to_index(eps, 4); | ||
| 52 | cube->eposm = factorial(4) * subset_to_index(eposm, 12, 4) | ||
| 53 | + perm_to_index(epm, 4); | ||
| 54 | } | ||
| 55 | |||
| 56 | bool solvable(Cube *cube) { | ||
| 57 | /* Since we memorize orientation truncating the last digit, we only need to | ||
| 58 | * check that the permutations have the correct sign. */ | ||
| 59 | /* TODO: add check that every integer is in range */ | ||
| 60 | int ep[12], cp[12], c[6]; | ||
| 61 | cube_to_ep_array(cube, ep); | ||
| 62 | index_to_perm(cube->cp, 8, cp); | ||
| 63 | index_to_perm(cube->centerpos, 6, c); | ||
| 64 | return (perm_sign(ep, 12) ^ perm_sign(c, 6)) == perm_sign(cp, 8); | ||
| 65 | } | ||
| 66 | |||
| 67 | Cube *solved_cube() { | ||
| 68 | static Cube cube = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; | ||
| 69 | return &cube; | ||
| 70 | } | ||
| 71 | |||
| 72 | bool solved(Cube *cube) { | ||
| 73 | return (cube->eofb == 0 && cube->coud == 0 && cube->cp == 0 && | ||
| 74 | cube->epose == 0 && cube->eposs == 0 && cube->eposm == 0 && | ||
| 75 | cube->centerpos == 0); | ||
| 76 | } | ||
| 77 | |||
| 78 | char *to_string(Cube *cube) { | ||
| 79 | int eo[12], co[8], ep[12], cp[8], cenpos[6]; | ||
| 80 | cube_to_eofb_array(cube->eofb, eo); | ||
| 81 | cube_to_coud_array(cube->coud, co); | ||
| 82 | cube_to_ep_array(cube, ep); | ||
| 83 | cube_to_cp_array(cube->cp, cp); | ||
| 84 | cube_to_centerpos_array(cube->centerpos, cenpos); | ||
| 85 | |||
| 86 | char *ret[1000]; | ||
| 87 | |||
| 88 | for (int i = 0; i < 12; i++) sprintf(ret, " %s ", edge_string[ep[i]]); | ||
| 89 | sprintf(ret, "\n"); | ||
| 90 | for (int i = 0; i < 12; i++) sprintf(ret, " %d ", eo[i]); | ||
| 91 | sprintf(ret, "\n"); | ||
| 92 | for (int i = 0; i < 8; i++) sprintf(ret, "%s ", corner_string[cp[i]]); | ||
| 93 | sprintf(ret, "\n"); | ||
| 94 | for (int i = 0; i < 8; i++) sprintf(ret, " %d ", co[i]); | ||
| 95 | sprintf(ret, "\n"); | ||
| 96 | for (int i = 0; i < 6; i++) sprintf(ret, " %s ", center_string[cenpos[i]]); | ||
| 97 | sprintf(ret, "\n"); | ||
| 98 | |||
| 99 | return ret; | ||
| 100 | } | ||
diff --git a/old/2020-unknown-date/cubeutils.h b/old/2020-unknown-date/cubeutils.h new file mode 100644 index 0000000..b24291c --- /dev/null +++ b/old/2020-unknown-date/cubeutils.h | |||
| @@ -0,0 +1,18 @@ | |||
| 1 | /* Cube-specific utility functions */ | ||
| 2 | |||
| 3 | #ifndef CUBEUTILS_H | ||
| 4 | #define CUBEUTILS_H | ||
| 5 | |||
| 6 | #include <stdbool.h> | ||
| 7 | #include "pieces.h" | ||
| 8 | |||
| 9 | void cube_to_ep_array(Cube *cube, int ep[12]); | ||
| 10 | void ep_array_to_epos(int ep[12], Cube *cube); | ||
| 11 | |||
| 12 | Cube *solved_cube(); | ||
| 13 | bool solvable(Cube *cube); | ||
| 14 | bool solved(Cube *cube); | ||
| 15 | |||
| 16 | void print(Cube *cube); | ||
| 17 | |||
| 18 | #endif | ||
diff --git a/old/2020-unknown-date/moves.c b/old/2020-unknown-date/moves.c new file mode 100644 index 0000000..de293ed --- /dev/null +++ b/old/2020-unknown-date/moves.c | |||
| @@ -0,0 +1,57 @@ | |||
| 1 | #include <stdbool.h> | ||
| 2 | #include "pieces.h" | ||
| 3 | #include "moves.h" | ||
| 4 | #include "utils.h" | ||
| 5 | |||
| 6 | /* Transition tables */ | ||
| 7 | int eofb_ttable[pow2to11][NULLMOVE]; | ||
| 8 | int eorl_ttable[pow2to11][NULLMOVE]; | ||
| 9 | int eoud_ttable[pow2to11][NULLMOVE]; | ||
| 10 | int coud_ttable[pow3to7][NULLMOVE]; | ||
| 11 | int cofb_ttable[pow3to7][NULLMOVE]; | ||
| 12 | int corl_ttable[pow3to7][NULLMOVE]; | ||
| 13 | int epose_ttable[factorial12/factorial8][NULLMOVE]; | ||
| 14 | int eposs_ttable[factorial12/factorial8][NULLMOVE]; | ||
| 15 | int eposm_ttable[factorial12/factorial8][NULLMOVE]; | ||
| 16 | int cp_ttable[factorial8][NULLMOVE]; | ||
| 17 | int centerpos_ttable[factorial6][NULLMOVE]; | ||
| 18 | |||
| 19 | void apply_move_ep(Move m, int a[12]) { | ||
| 20 | int aux[12]; | ||
| 21 | intarrcopy(a, aux, 12); | ||
| 22 | for (int i = 0; i < 12; i++) | ||
| 23 | a[i] = aux[edge_cycle[m][i]]; | ||
| 24 | } | ||
| 25 | |||
| 26 | void apply_move_cp(Move m, int a[8]) { | ||
| 27 | int aux[8]; | ||
| 28 | intarrcopy(a, aux, 8); | ||
| 29 | for (int i = 0; i < 8; i++) | ||
| 30 | a[i] = aux[corner_cycle[m][i]]; | ||
| 31 | } | ||
| 32 | |||
| 33 | void apply_move_centerpos(Move m, int a[6]) { | ||
| 34 | int aux[6]; | ||
| 35 | intarrcopy(a, aux, 6); | ||
| 36 | for (int i = 0; i < 6; i++) | ||
| 37 | a[i] = aux[center_cycle[m][i]]; | ||
| 38 | } | ||
| 39 | |||
| 40 | void init_ttables() { | ||
| 41 | /* TODO */ | ||
| 42 | } | ||
| 43 | |||
| 44 | void apply_move(Move m, Cube *cube) { | ||
| 45 | cube->eofb = eofb_ttable[cube->eofb][m]; | ||
| 46 | cube->eorl = eorl_ttable[cube->eorl][m]; | ||
| 47 | cube->eoud = eoud_ttable[cube->eoud][m]; | ||
| 48 | cube->coud = coud_ttable[cube->coud][m]; | ||
| 49 | cube->cofb = cofb_ttable[cube->cofb][m]; | ||
| 50 | cube->corl = corl_ttable[cube->corl][m]; | ||
| 51 | cube->epose = epose_ttable[cube->epose][m]; | ||
| 52 | cube->eposs = eposs_ttable[cube->eposs][m]; | ||
| 53 | cube->eposm = eposm_ttable[cube->eposm][m]; | ||
| 54 | cube->cp = cp_ttable[cube->cp][m]; | ||
| 55 | cube->centerpos = centerpos_ttable[cube->centerpos][m]; | ||
| 56 | } | ||
| 57 | |||
diff --git a/old/2020-unknown-date/moves.h b/old/2020-unknown-date/moves.h new file mode 100644 index 0000000..605f335 --- /dev/null +++ b/old/2020-unknown-date/moves.h | |||
| @@ -0,0 +1,9 @@ | |||
| 1 | /* Moves and transition tables */ | ||
| 2 | |||
| 3 | #ifndef MOVES_H | ||
| 4 | #define MOVES_H | ||
| 5 | |||
| 6 | void apply_move(Move m, Cube *cube); | ||
| 7 | void init_ttables(); | ||
| 8 | |||
| 9 | #endif | ||
diff --git a/old/2020-unknown-date/pieces.c b/old/2020-unknown-date/pieces.c new file mode 100644 index 0000000..d782c89 --- /dev/null +++ b/old/2020-unknown-date/pieces.c | |||
| @@ -0,0 +1,208 @@ | |||
| 1 | #include "pieces.h" | ||
| 2 | |||
| 3 | char edge_string[12][5] = { | ||
| 4 | "UF", "UL", "UB", "UR", "DF", "DL", "DB", "DR", "FR", "FL", "BL", "BR" | ||
| 5 | }; | ||
| 6 | |||
| 7 | char corner_string[8][5] = { | ||
| 8 | "UFR", "UFL", "UBL", "UBR", "DFR", "DFL", "DBL", "DBR" | ||
| 9 | }; | ||
| 10 | |||
| 11 | char center_string[6][5] = { "U", "D", "R", "L", "F", "B" }; | ||
| 12 | |||
| 13 | char move_string[NULLMOVE+1][5] = { | ||
| 14 | "U", "U2", "U\'", "D", "D2", "D\'", "R", "R2", "R\'", | ||
| 15 | "L", "L2", "L\'", "F", "F2", "F\'", "B", "B2", "B\'", | ||
| 16 | "Uw", "Uw2", "Uw\'", "Dw", "Dw2", "Dw\'", "Rw", "Rw2", "Rw\'", | ||
| 17 | "Lw", "Lw2", "Lw\'", "Fw", "Fw2", "Fw\'", "Bw", "Bw2", "Bw\'", | ||
| 18 | "M", "M2", "M\'", "S", "S2", "S\'", "E", "E2", "E\'", | ||
| 19 | "x", "x2", "x\'", "y", "y2", "y\'", "z", "z2", "z\'", | ||
| 20 | "-" | ||
| 21 | }; | ||
| 22 | |||
| 23 | int edge_cycle[NULLMOVE+1][12] = { | ||
| 24 | [U] = {UR, UF, UL, UB, DF, DL, DB, DR, FR, FL, BL, BR}, | ||
| 25 | [U2] = {UB, UR, UF, UL, DF, DL, DB, DR, FR, FL, BL, BR}, | ||
| 26 | [U3] = {UL, UB, UR, UF, DF, DL, DB, DR, FR, FL, BL, BR}, | ||
| 27 | [D] = {UF, UL, UB, UR, DL, DB, DR, DF, FR, FL, BL, BR}, | ||
| 28 | [D2] = {UF, UL, UB, UR, DB, DR, DF, DL, FR, FL, BL, BR}, | ||
| 29 | [D3] = {UF, UL, UB, UR, DR, DF, DL, DB, FR, FL, BL, BR}, | ||
| 30 | [R] = {UF, UL, UB, FR, DF, DL, DB, BR, DR, FL, BL, UR}, | ||
| 31 | [R2] = {UF, UL, UB, DR, DF, DL, DB, UR, BR, FL, BL, FR}, | ||
| 32 | [R3] = {UF, UL, UB, BR, DF, DL, DB, FR, UR, FL, BL, DR}, | ||
| 33 | [L] = {UF, BL, UB, UR, DF, FL, DB, DR, FR, UL, DL, BR}, | ||
| 34 | [L2] = {UF, DL, UB, UR, DF, UL, DB, DR, FR, BL, FL, BR}, | ||
| 35 | [L3] = {UF, FL, UB, UR, DF, BL, DB, DR, FR, DL, UL, BR}, | ||
| 36 | [F] = {FL, UL, UB, UR, FR, DL, DB, DR, UF, DF, BL, BR}, | ||
| 37 | [F2] = {DF, UL, UB, UR, UF, DL, DB, DR, FL, FR, BL, BR}, | ||
| 38 | [F3] = {FR, UL, UB, UR, FL, DL, DB, DR, DF, UF, BL, BR}, | ||
| 39 | [B] = {UF, UL, BR, UR, DF, DL, BL, DR, FR, FL, UB, DB}, | ||
| 40 | [B2] = {UF, UL, DB, UR, DF, DL, UB, DR, FR, FL, BR, BL}, | ||
| 41 | [B3] = {UF, UL, BL, UR, DF, DL, BR, DR, FR, FL, DB, UB}, | ||
| 42 | |||
| 43 | [Uw] = {UR, UF, UL, UB, DF, DL, DB, DR, BR, FR, FL, BL}, | ||
| 44 | [Uw2] = {UB, UR, UF, UL, DF, DL, DB, DR, BL, BR, FR, FL}, | ||
| 45 | [Uw3] = {UL, UB, UR, UF, DF, DL, DB, DR, FL, BL, BR, FR}, | ||
| 46 | [Dw] = {UF, UL, UB, UR, DL, DB, DR, DF, FL, BL, BR, FR}, | ||
| 47 | [Dw2] = {UF, UL, UB, UR, DB, DR, DF, DL, BL, BR, FR, FL}, | ||
| 48 | [Dw3] = {UF, UL, UB, UR, DR, DF, DL, DB, BR, FR, FL, BL}, | ||
| 49 | [Rw] = {DF, UL, UF, FR, DB, DL, UB, BR, DR, FL, BL, UR}, | ||
| 50 | [Rw2] = {DB, UL, DF, DR, UB, DL, UF, UR, BR, FL, BL, FR}, | ||
| 51 | [Rw3] = {UB, UL, DB, BR, UF, DL, DF, FR, UR, FL, BL, DR}, | ||
| 52 | [Lw] = {UB, BL, DB, UR, UF, FL, DF, DR, FR, UL, DL, BR}, | ||
| 53 | [Lw2] = {DB, DL, DF, UR, UB, UL, UF, DR, FR, BL, FL, BR}, | ||
| 54 | [Lw3] = {DF, FL, UF, UR, DB, BL, UB, DR, FR, DL, UL, BR}, | ||
| 55 | [Fw] = {FL, DL, UB, UL, FR, DR, DB, UR, UF, DF, BL, BR}, | ||
| 56 | [Fw2] = {DF, DR, UB, DL, UF, UR, DB, UL, FL, FR, BL, BR}, | ||
| 57 | [Fw3] = {FR, UR, UB, DR, FL, UL, DB, DL, DF, UF, BL, BR}, | ||
| 58 | [Bw] = {UF, UR, BR, DR, DF, UL, BL, DL, FR, FL, UB, DB}, | ||
| 59 | [Bw2] = {UF, DR, DB, DL, DF, UR, UB, UL, FR, FL, BR, BL}, | ||
| 60 | [Bw3] = {UF, DL, BL, UL, DF, DR, BR, UR, FR, FL, DB, UB}, | ||
| 61 | |||
| 62 | [M] = {UB, UL, DB, UR, UF, DL, DF, DR, FR, FL, BL, BR}, | ||
| 63 | [M2] = {DB, UL, DF, UR, UB, DL, UF, DR, FR, FL, BL, BR}, | ||
| 64 | [M3] = {DF, UL, UF, UR, DB, DL, UB, DR, FR, FL, BL, BR}, | ||
| 65 | [S] = {UF, DL, UB, UL, DF, DR, DB, UR, FR, FL, BL, BR}, | ||
| 66 | [S2] = {UF, DR, UB, DL, DF, UR, DB, UL, FR, FL, BL, BR}, | ||
| 67 | [S3] = {UF, UR, UB, DR, DF, UL, DB, DL, FR, FL, BL, BR}, | ||
| 68 | [E] = {UF, UL, UB, UR, DF, DL, DB, DR, FL, BL, BR, FR}, | ||
| 69 | [E2] = {UF, UL, UB, UR, DF, DL, DB, DR, BL, BR, FR, FL}, | ||
| 70 | [E3] = {UF, UL, UB, UR, DF, DL, DB, DR, BR, FR, FL, BL}, | ||
| 71 | |||
| 72 | [X] = {DF, FL, UF, FR, DB, BL, UB, BR, DR, DL, UL, UR}, | ||
| 73 | [X2] = {DB, DL, DF, DR, UB, UL, UF, UR, BR, BL, FL, FR}, | ||
| 74 | [X3] = {UB, BL, DB, BR, UF, FL, DF, FR, UR, UL, DL, DR}, | ||
| 75 | [Y] = {UR, UF, UL, UB, DR, DF, DL, DB, BR, FR, FL, BL}, | ||
| 76 | [Y2] = {UB, UR, UF, UL, DB, DR, DF, DL, BL, BR, FR, FL}, | ||
| 77 | [Y3] = {UL, UB, UR, UF, DL, DB, DR, DF, FL, BL, BR, FR}, | ||
| 78 | [Z] = {FL, DL, BL, UL, FR, DR, BR, UR, UF, DF, DB, UB}, | ||
| 79 | [Z2] = {DF, DR, DB, DL, UF, UR, UB, UL, FL, FR, BR, BL}, | ||
| 80 | [Z3] = {FR, UR, BR, DR, FL, UL, BL, DL, DF, UF, UB, DB}, | ||
| 81 | |||
| 82 | [NULLMOVE] = {UF, UL, UB, UR, DF, DL, DB, DR, FR, FL, BL, BR}, | ||
| 83 | }; | ||
| 84 | |||
| 85 | int corner_cycle[NULLMOVE+1][8] = { | ||
| 86 | [U] = {UBR, UFR, UFL, UBL, DFR, DFL, DBL, DBR}, | ||
| 87 | [U2] = {UBL, UBR, UFR, UFL, DFR, DFL, DBL, DBR}, | ||
| 88 | [U3] = {UFL, UBL, UBR, UFR, DFR, DFL, DBL, DBR}, | ||
| 89 | [D] = {UFR, UFL, UBL, UBR, DFL, DBL, DBR, DFR}, | ||
| 90 | [D2] = {UFR, UFL, UBL, UBR, DBL, DBR, DFR, DFL}, | ||
| 91 | [D3] = {UFR, UFL, UBL, UBR, DBR, DFR, DFL, DBL}, | ||
| 92 | [R] = {DFR, UFL, UBL, UFR, DBR, DFL, DBL, UBR}, | ||
| 93 | [R2] = {DBR, UFL, UBL, DFR, UBR, DFL, DBL, UFR}, | ||
| 94 | [R3] = {UBR, UFL, UBL, DBR, UFR, DFL, DBL, DFR}, | ||
| 95 | [L] = {UFR, UBL, DBL, UBR, DFR, UFL, DFL, DBR}, | ||
| 96 | [L2] = {UFR, DBL, DFL, UBR, DFR, UBL, UFL, DBR}, | ||
| 97 | [L3] = {UFR, DFL, UFL, UBR, DFR, DBL, UBL, DBR}, | ||
| 98 | [F] = {UFL, DFL, UBL, UBR, UFR, DFR, DBL, DBR}, | ||
| 99 | [F2] = {DFL, DFR, UBL, UBR, UFL, UFR, DBL, DBR}, | ||
| 100 | [F3] = {DFR, UFR, UBL, UBR, DFL, UFL, DBL, DBR}, | ||
| 101 | [B] = {UFR, UFL, UBR, DBR, DFR, DFL, UBL, DBL}, | ||
| 102 | [B2] = {UFR, UFL, DBR, DBL, DFR, DFL, UBR, UBL}, | ||
| 103 | [B3] = {UFR, UFL, DBL, UBL, DFR, DFL, DBR, UBR}, | ||
| 104 | |||
| 105 | [Uw] = {UBR, UFR, UFL, UBL, DFR, DFL, DBL, DBR}, | ||
| 106 | [Uw2] = {UBL, UBR, UFR, UFL, DFR, DFL, DBL, DBR}, | ||
| 107 | [Uw3] = {UFL, UBL, UBR, UFR, DFR, DFL, DBL, DBR}, | ||
| 108 | [Dw] = {UFR, UFL, UBL, UBR, DFL, DBL, DBR, DFR}, | ||
| 109 | [Dw2] = {UFR, UFL, UBL, UBR, DBL, DBR, DFR, DFL}, | ||
| 110 | [Dw3] = {UFR, UFL, UBL, UBR, DBR, DFR, DFL, DBL}, | ||
| 111 | [Rw] = {DFR, UFL, UBL, UFR, DBR, DFL, DBL, UBR}, | ||
| 112 | [Rw2] = {DBR, UFL, UBL, DFR, UBR, DFL, DBL, UFR}, | ||
| 113 | [Rw3] = {UBR, UFL, UBL, DBR, UFR, DFL, DBL, DFR}, | ||
| 114 | [Lw] = {UFR, UBL, DBL, UBR, DFR, UFL, DFL, DBR}, | ||
| 115 | [Lw2] = {UFR, DBL, DFL, UBR, DFR, UBL, UFL, DBR}, | ||
| 116 | [Lw3] = {UFR, DFL, UFL, UBR, DFR, DBL, UBL, DBR}, | ||
| 117 | [Fw] = {UFL, DFL, UBL, UBR, UFR, DFR, DBL, DBR}, | ||
| 118 | [Fw2] = {DFL, DFR, UBL, UBR, UFL, UFR, DBL, DBR}, | ||
| 119 | [Fw3] = {DFR, UFR, UBL, UBR, DFL, UFL, DBL, DBR}, | ||
| 120 | [Bw] = {UFR, UFL, UBR, DBR, DFR, DFL, UBL, DBL}, | ||
| 121 | [Bw2] = {UFR, UFL, DBR, DBL, DFR, DFL, UBR, UBL}, | ||
| 122 | [Bw3] = {UFR, UFL, DBL, UBL, DFR, DFL, DBR, UBR}, | ||
| 123 | |||
| 124 | [M] = {UFR, UFL, UBL, UBR, DFR, DFL, DBL, DBR}, | ||
| 125 | [M2] = {UFR, UFL, UBL, UBR, DFR, DFL, DBL, DBR}, | ||
| 126 | [M3] = {UFR, UFL, UBL, UBR, DFR, DFL, DBL, DBR}, | ||
| 127 | [S] = {UFR, UFL, UBL, UBR, DFR, DFL, DBL, DBR}, | ||
| 128 | [S2] = {UFR, UFL, UBL, UBR, DFR, DFL, DBL, DBR}, | ||
| 129 | [S3] = {UFR, UFL, UBL, UBR, DFR, DFL, DBL, DBR}, | ||
| 130 | [E] = {UFR, UFL, UBL, UBR, DFR, DFL, DBL, DBR}, | ||
| 131 | [E2] = {UFR, UFL, UBL, UBR, DFR, DFL, DBL, DBR}, | ||
| 132 | [E3] = {UFR, UFL, UBL, UBR, DFR, DFL, DBL, DBR}, | ||
| 133 | |||
| 134 | [X] = {DFR, DFL, UFL, UFR, DBR, DBL, UBL, UBR}, | ||
| 135 | [X2] = {DBR, DBL, DFL, DFR, UBR, UBL, UFL, UFR}, | ||
| 136 | [X3] = {UBR, UBL, DBL, DBR, UFR, UFL, DFL, DFR}, | ||
| 137 | [Y] = {UBR, UFR, UFL, UBL, DBR, DFR, DFL, DBL}, | ||
| 138 | [Y2] = {UBL, UBR, UFR, UFL, DBL, DBR, DFR, DFL}, | ||
| 139 | [Y3] = {UFL, UBL, UBR, UFR, DFL, DBL, DBR, DFR}, | ||
| 140 | [Z] = {UFL, DFL, DBL, UBL, UFR, DFR, DBR, UBR}, | ||
| 141 | [Z2] = {DFL, DFR, DBR, DBL, UFL, UFR, UBR, UBL}, | ||
| 142 | [Z3] = {DFR, UFR, UBR, DBR, DFL, UFL, UBL, DBL}, | ||
| 143 | |||
| 144 | [NULLMOVE] = {UFR, UFL, UBL, UBR, DFR, DFL, DBL, DBR}, | ||
| 145 | }; | ||
| 146 | |||
| 147 | int center_cycle[NULLMOVE+1][6] = { | ||
| 148 | [U] = {U_center, D_center, R_center, L_center, F_center, B_center}, | ||
| 149 | [U2] = {U_center, D_center, R_center, L_center, F_center, B_center}, | ||
| 150 | [U3] = {U_center, D_center, R_center, L_center, F_center, B_center}, | ||
| 151 | [D] = {U_center, D_center, R_center, L_center, F_center, B_center}, | ||
| 152 | [D2] = {U_center, D_center, R_center, L_center, F_center, B_center}, | ||
| 153 | [D3] = {U_center, D_center, R_center, L_center, F_center, B_center}, | ||
| 154 | [R] = {U_center, D_center, R_center, L_center, F_center, B_center}, | ||
| 155 | [R2] = {U_center, D_center, R_center, L_center, F_center, B_center}, | ||
| 156 | [R3] = {U_center, D_center, R_center, L_center, F_center, B_center}, | ||
| 157 | [L] = {U_center, D_center, R_center, L_center, F_center, B_center}, | ||
| 158 | [L2] = {U_center, D_center, R_center, L_center, F_center, B_center}, | ||
| 159 | [L3] = {U_center, D_center, R_center, L_center, F_center, B_center}, | ||
| 160 | [F] = {U_center, D_center, R_center, L_center, F_center, B_center}, | ||
| 161 | [F2] = {U_center, D_center, R_center, L_center, F_center, B_center}, | ||
| 162 | [F3] = {U_center, D_center, R_center, L_center, F_center, B_center}, | ||
| 163 | [B] = {U_center, D_center, R_center, L_center, F_center, B_center}, | ||
| 164 | [B2] = {U_center, D_center, R_center, L_center, F_center, B_center}, | ||
| 165 | [B3] = {U_center, D_center, R_center, L_center, F_center, B_center}, | ||
| 166 | |||
| 167 | [Uw] = {U_center, D_center, B_center, F_center, R_center, L_center}, | ||
| 168 | [Uw2] = {U_center, D_center, L_center, R_center, B_center, F_center}, | ||
| 169 | [Uw3] = {U_center, D_center, F_center, B_center, L_center, R_center}, | ||
| 170 | [Dw] = {U_center, D_center, F_center, B_center, L_center, R_center}, | ||
| 171 | [Dw2] = {U_center, D_center, L_center, R_center, B_center, F_center}, | ||
| 172 | [Dw3] = {U_center, D_center, B_center, F_center, R_center, L_center}, | ||
| 173 | [Rw] = {F_center, B_center, R_center, L_center, D_center, U_center}, | ||
| 174 | [Rw2] = {D_center, U_center, R_center, L_center, B_center, F_center}, | ||
| 175 | [Rw3] = {B_center, F_center, R_center, L_center, U_center, D_center}, | ||
| 176 | [Lw] = {B_center, F_center, R_center, L_center, U_center, D_center}, | ||
| 177 | [Lw2] = {D_center, U_center, R_center, L_center, B_center, F_center}, | ||
| 178 | [Lw3] = {F_center, B_center, R_center, L_center, D_center, U_center}, | ||
| 179 | [Fw] = {L_center, R_center, U_center, D_center, F_center, B_center}, | ||
| 180 | [Fw2] = {D_center, U_center, L_center, R_center, F_center, B_center}, | ||
| 181 | [Fw3] = {R_center, L_center, D_center, U_center, F_center, B_center}, | ||
| 182 | [Bw] = {R_center, L_center, D_center, U_center, F_center, B_center}, | ||
| 183 | [Bw2] = {D_center, U_center, L_center, R_center, F_center, B_center}, | ||
| 184 | [Bw3] = {L_center, R_center, U_center, D_center, F_center, B_center}, | ||
| 185 | |||
| 186 | [X] = {F_center, B_center, R_center, L_center, D_center, U_center}, | ||
| 187 | [X2] = {D_center, U_center, R_center, L_center, B_center, F_center}, | ||
| 188 | [X3] = {B_center, F_center, R_center, L_center, U_center, D_center}, | ||
| 189 | [Y] = {U_center, D_center, B_center, F_center, R_center, L_center}, | ||
| 190 | [Y2] = {U_center, D_center, L_center, R_center, B_center, F_center}, | ||
| 191 | [Y3] = {U_center, D_center, F_center, B_center, L_center, R_center}, | ||
| 192 | [Z] = {L_center, R_center, U_center, D_center, F_center, B_center}, | ||
| 193 | [Z2] = {D_center, U_center, L_center, R_center, F_center, B_center}, | ||
| 194 | [Z3] = {R_center, L_center, D_center, U_center, F_center, B_center}, | ||
| 195 | |||
| 196 | [M] = {B_center, F_center, R_center, L_center, U_center, D_center}, | ||
| 197 | [M2] = {D_center, U_center, R_center, L_center, B_center, F_center}, | ||
| 198 | [M3] = {F_center, B_center, R_center, L_center, D_center, U_center}, | ||
| 199 | [E] = {U_center, D_center, F_center, B_center, L_center, R_center}, | ||
| 200 | [E2] = {U_center, D_center, L_center, R_center, B_center, F_center}, | ||
| 201 | [E3] = {U_center, D_center, B_center, F_center, R_center, L_center}, | ||
| 202 | [S] = {L_center, R_center, U_center, D_center, F_center, B_center}, | ||
| 203 | [S2] = {D_center, U_center, L_center, R_center, F_center, B_center}, | ||
| 204 | [S3] = {R_center, L_center, D_center, U_center, F_center, B_center}, | ||
| 205 | |||
| 206 | [NULLMOVE] = {U_center, D_center, R_center, L_center, F_center, B_center}, | ||
| 207 | }; | ||
| 208 | |||
diff --git a/old/2020-unknown-date/pieces.h b/old/2020-unknown-date/pieces.h new file mode 100644 index 0000000..dbdd740 --- /dev/null +++ b/old/2020-unknown-date/pieces.h | |||
| @@ -0,0 +1,59 @@ | |||
| 1 | /* Moves and other things */ | ||
| 2 | |||
| 3 | #ifndef PIECES_H | ||
| 4 | #define PIECES_H | ||
| 5 | |||
| 6 | typedef enum { | ||
| 7 | U, U2, U3, D, D2, D3, R, R2, R3, L, L2, L3, F, F2, F3, B, B2, B3, | ||
| 8 | Uw, Uw2, Uw3, Dw, Dw2, Dw3, Rw, Rw2, Rw3, | ||
| 9 | Lw, Lw2, Lw3, Fw, Fw2, Fw3, Bw, Bw2, Bw3, | ||
| 10 | M, M2, M3, S, S2, S3, E, E2, E3, | ||
| 11 | X, X2, X3, Y, Y2, Y3, Z, Z2, Z3, | ||
| 12 | NULLMOVE | ||
| 13 | } Move; | ||
| 14 | typedef enum { | ||
| 15 | U_center, D_center, R_center, L_center, F_center, B_center | ||
| 16 | } Center; | ||
| 17 | typedef enum { UF, UL, UB, UR, DF, DL, DB, DR, FR, FL, BL, BR } Edge; | ||
| 18 | typedef enum { UFR, UFL, UBL, UBR, DFR, DFL, DBL, DBR } Corner; | ||
| 19 | |||
| 20 | /* Arrays for strings of pieces and moves */ | ||
| 21 | extern char edge_string[12][5]; | ||
| 22 | extern char corner_string[8][5]; | ||
| 23 | extern char center_string[6][5]; | ||
| 24 | extern char move_string[NULLMOVE+1][5]; | ||
| 25 | |||
| 26 | /* Three big arrays that determine the movement of edges, corners and | ||
| 27 | * centers for some of the basic moves. Yes, one can be much more elegant and | ||
| 28 | * write much fewer lines. But then things get less elegant somewhere else. */ | ||
| 29 | extern int edge_cycle[NULLMOVE+1][12]; | ||
| 30 | extern int corner_cycle[NULLMOVE+1][8]; | ||
| 31 | extern int center_cycle[NULLMOVE+1][6]; | ||
| 32 | |||
| 33 | /* Representation of the cube */ | ||
| 34 | typedef struct { | ||
| 35 | /* Edge orientation */ | ||
| 36 | int eofb; | ||
| 37 | int eorl; | ||
| 38 | int eoud; | ||
| 39 | |||
| 40 | /* Corner orientation */ | ||
| 41 | int coud; | ||
| 42 | int cofb; | ||
| 43 | int corl; | ||
| 44 | |||
| 45 | /* Position of M/E/S slice edges */ | ||
| 46 | /* TODO: keep in mind that the 4! positions with edges in correct slice | ||
| 47 | * must be the first 4! indeces */ | ||
| 48 | int epose; | ||
| 49 | int eposs; | ||
| 50 | int eposm; | ||
| 51 | |||
| 52 | /* Permutation of corners */ | ||
| 53 | int cp; | ||
| 54 | |||
| 55 | /* Position of centers */ | ||
| 56 | int centerpos; | ||
| 57 | } Cube; | ||
| 58 | |||
| 59 | #endif | ||
diff --git a/old/2021-02-06/cube.c b/old/2021-02-06/cube.c new file mode 100644 index 0000000..9185281 --- /dev/null +++ b/old/2021-02-06/cube.c | |||
| @@ -0,0 +1,664 @@ | |||
| 1 | #include "cube.h" | ||
| 2 | |||
| 3 | typedef struct { | ||
| 4 | int ep[12], eofb[12], eorl[12], eoud[12], | ||
| 5 | cp[8], coud[8], corl[8], cofb[8], cpos[6]; | ||
| 6 | } CubeArray; | ||
| 7 | |||
| 8 | typedef struct { | ||
| 9 | bool epose, eposs, eposm, eofb, eorl, eoud, cp, coud, cofb, corl, cpos; | ||
| 10 | } PieceFilter; | ||
| 11 | |||
| 12 | PieceFilter fAll = {true,true,true,true,true,true,true,true,true,true,true}; | ||
| 13 | PieceFilter cpos_only = { .cpos = true }; | ||
| 14 | |||
| 15 | void cube_to_arrays(Cube cube, CubeArray *arr, PieceFilter f); | ||
| 16 | Cube arrays_to_cube(CubeArray arr, PieceFilter f); | ||
| 17 | void move_cubearray(Move m, CubeArray *arr, PieceFilter f); | ||
| 18 | Cube move_via_array(Move m, Cube cube, PieceFilter f); | ||
| 19 | void sort_cancel_rotate(NissMove *alg, int n, bool inv, int top, int front); | ||
| 20 | bool read_ttables_file(); | ||
| 21 | bool write_ttables_file(); | ||
| 22 | |||
| 23 | /* Transition tables */ | ||
| 24 | uint16_t epose_ttable[NMOVES][factorial12/factorial8]; | ||
| 25 | uint16_t eposs_ttable[NMOVES][factorial12/factorial8]; | ||
| 26 | uint16_t eposm_ttable[NMOVES][factorial12/factorial8]; | ||
| 27 | uint16_t eofb_ttable[NMOVES][pow2to11]; | ||
| 28 | uint16_t eorl_ttable[NMOVES][pow2to11]; | ||
| 29 | uint16_t eoud_ttable[NMOVES][pow2to11]; | ||
| 30 | uint16_t cp_ttable[NMOVES][factorial8]; | ||
| 31 | uint16_t coud_ttable[NMOVES][pow3to7]; | ||
| 32 | uint16_t cofb_ttable[NMOVES][pow3to7]; | ||
| 33 | uint16_t corl_ttable[NMOVES][pow3to7]; | ||
| 34 | uint16_t cpos_ttable[NMOVES][factorial6]; | ||
| 35 | |||
| 36 | bool commute[NMOVES][NMOVES]; | ||
| 37 | bool possible_next[NMOVES][NMOVES][NMOVES]; | ||
| 38 | Move inverse[NMOVES]; | ||
| 39 | |||
| 40 | char edge_string[12][5] = | ||
| 41 | { "UF", "UL", "UB", "UR", "DF", "DL", "DB", "DR", "FR", "FL", "BL", "BR" }; | ||
| 42 | char corner_string[8][5] = { "UFR","UFL","UBL","UBR","DFR","DFL","DBL","DBR" }; | ||
| 43 | char center_string[6][5] = { "U", "D", "R", "L", "F", "B" }; | ||
| 44 | char move_string[NMOVES][5] = | ||
| 45 | { "-", | ||
| 46 | "U", "U2", "U\'", "D", "D2", "D\'", "R", "R2", "R\'", | ||
| 47 | "L", "L2", "L\'", "F", "F2", "F\'", "B", "B2", "B\'", | ||
| 48 | "Uw", "Uw2", "Uw\'", "Dw", "Dw2", "Dw\'", "Rw", "Rw2", "Rw\'", | ||
| 49 | "Lw", "Lw2", "Lw\'", "Fw", "Fw2", "Fw\'", "Bw", "Bw2", "Bw\'", | ||
| 50 | "M", "M2", "M\'", "S", "S2", "S\'", "E", "E2", "E\'", | ||
| 51 | "x", "x2", "x\'", "y", "y2", "y\'", "z", "z2", "z\'" }; | ||
| 52 | |||
| 53 | /* For each type of pieces only the effects of U, x and y are described */ | ||
| 54 | int edge_cycle[NMOVES][12] = | ||
| 55 | { [U] = {UR, UF, UL, UB, DF, DL, DB, DR, FR, FL, BL, BR}, | ||
| 56 | [x] = {DF, FL, UF, FR, DB, BL, UB, BR, DR, DL, UL, UR}, | ||
| 57 | [y] = {UR, UF, UL, UB, DR, DF, DL, DB, BR, FR, FL, BL} }; | ||
| 58 | int eofb_flipped[NMOVES][12] = | ||
| 59 | { [x] = { [UF] = 1, [UB] = 1, [DF] = 1, [DB] = 1 }, | ||
| 60 | [y] = { [FR] = 1, [FL] = 1, [BL] = 1, [BR] = 1 } }; | ||
| 61 | int eorl_flipped[NMOVES][12] = | ||
| 62 | { [x] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, | ||
| 63 | [y] = { [FR] = 1, [FL] = 1, [BL] = 1, [BR] = 1 } }; | ||
| 64 | int eoud_flipped[NMOVES][12] = | ||
| 65 | { [U] = { [UF] = 1, [UL] = 1, [UB] = 1, [UR] = 1 }, | ||
| 66 | [x] = { [UF] = 1, [UB] = 1, [DF] = 1, [DB] = 1 }, | ||
| 67 | [y] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 } }; | ||
| 68 | int corner_cycle[NMOVES][8] = | ||
| 69 | { [U] = {UBR, UFR, UFL, UBL, DFR, DFL, DBL, DBR}, | ||
| 70 | [x] = {DFR, DFL, UFL, UFR, DBR, DBL, UBL, UBR}, | ||
| 71 | [y] = {UBR, UFR, UFL, UBL, DBR, DFR, DFL, DBL} }; | ||
| 72 | int coud_flipped[NMOVES][8] = | ||
| 73 | { [x] = {[UFR]=2,[UBR]=1,[DBR]=2,[DFR]=1,[UFL]=1,[UBL]=2,[DBL]=1,[DFL]=2} }; | ||
| 74 | int corl_flipped[NMOVES][8] = | ||
| 75 | { [U] = { [UFR] = 1, [UBR] = 2, [UBL] = 1, [UFL] = 2 }, | ||
| 76 | [y] = {[UFR]=1,[UBR]=2,[UBL]=1,[UFL]=2,[DFR]=2,[DBR]=1,[DBL]=2,[DFL]=1} }; | ||
| 77 | int cofb_flipped[NMOVES][8] = | ||
| 78 | { [U] = { [UFR] = 2, [UBR] = 1, [UBL] = 2, [UFL] = 1 }, | ||
| 79 | [x] = {[UFR]=1,[UBR]=2,[DFR]=2,[DBR]=1,[UBL]=2,[UFL]=1,[DBL]=1,[DFL]=2}, | ||
| 80 | [y] = {[UFR]=2,[UBR]=1,[UBL]=2,[UFL]=1,[DFR]=1,[DBR]=2,[DBL]=1,[DFL]=2} }; | ||
| 81 | int center_cycle[NMOVES][6] = | ||
| 82 | { [x] = {F_center, B_center, R_center, L_center, D_center, U_center}, | ||
| 83 | [y] = {U_center, D_center, B_center, F_center, R_center, L_center} }; | ||
| 84 | |||
| 85 | /* Each move is reduced to a combination of U, x and y using this table */ | ||
| 86 | Move equiv_moves[NMOVES][14] = { | ||
| 87 | [U] = { U, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, | ||
| 88 | [U2] = { U, U, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, | ||
| 89 | [U3] = { U, U, U, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, | ||
| 90 | [D] = { x, x, U, x, x, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, | ||
| 91 | [D2] = { x, x, U, U, x, x, 0, 0, 0, 0, 0, 0, 0, 0 }, | ||
| 92 | [D3] = { x, x, U, U, U, x, x, 0, 0, 0, 0, 0, 0, 0 }, | ||
| 93 | [R] = { y, x, U, x, x, x, y, y, y, 0, 0, 0, 0, 0 }, | ||
| 94 | [R2] = { y, x, U, U, x, x, x, y, y, y, 0, 0, 0, 0 }, | ||
| 95 | [R3] = { y, x, U, U, U, x, x, x, y, y, y, 0, 0, 0 }, | ||
| 96 | [L] = { y, y, y, x, U, x, x, x, y, 0, 0, 0, 0, 0 }, | ||
| 97 | [L2] = { y, y, y, x, U, U, x, x, x, y, 0, 0, 0, 0 }, | ||
| 98 | [L3] = { y, y, y, x, U, U, U, x, x, x, y, 0, 0, 0 }, | ||
| 99 | [F] = { x, U, x, x, x, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, | ||
| 100 | [F2] = { x, U, U, x, x, x, 0, 0, 0, 0, 0, 0, 0, 0 }, | ||
| 101 | [F3] = { x, U, U, U, x, x, x, 0, 0, 0, 0, 0, 0, 0 }, | ||
| 102 | [B] = { x, x, x, U, x, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, | ||
| 103 | [B2] = { x, x, x, U, U, x, 0, 0, 0, 0, 0, 0, 0, 0 }, | ||
| 104 | [B3] = { x, x, x, U, U, U, x, 0, 0, 0, 0, 0, 0, 0 }, | ||
| 105 | |||
| 106 | [Uw] = { x, x, U, x, x, y, 0, 0, 0, 0, 0, 0, 0, 0 }, | ||
| 107 | [Uw2] = { x, x, U, U, x, x, y, y, 0, 0, 0, 0, 0, 0 }, | ||
| 108 | [Uw3] = { x, x, U, U, U, x, x, y, y, y, 0, 0, 0, 0 }, | ||
| 109 | [Dw] = { U, y, y, y, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, | ||
| 110 | [Dw2] = { U, U, y, y, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, | ||
| 111 | [Dw3] = { U, U, U, y, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, | ||
| 112 | [Rw] = { y, y, y, x, U, x, x, x, y, x, 0, 0, 0, 0 }, | ||
| 113 | [Rw2] = { y, y, y, x, U, U, x, x, x, y, x, x, 0, 0 }, | ||
| 114 | [Rw3] = { y, y, y, x, U, U, U, y, x, x, x, y, 0, 0 }, | ||
| 115 | [Lw] = { y, x, U, x, x, x, y, y, y, x, x, x, 0, 0 }, | ||
| 116 | [Lw2] = { y, x, U, U, x, x, x, y, y, y, x, x, 0, 0 }, | ||
| 117 | [Lw3] = { y, x, U, U, U, x, x, x, y, y, y, x, 0, 0 }, | ||
| 118 | [Fw] = { x, x, x, U, y, y, y, x, 0, 0, 0, 0, 0, 0 }, | ||
| 119 | [Fw2] = { x, x, x, U, U, y, y, x, 0, 0, 0, 0, 0, 0 }, | ||
| 120 | [Fw3] = { x, x, x, U, U, U, y, x, 0, 0, 0, 0, 0, 0 }, | ||
| 121 | [Bw] = { x, U, y, y, y, x, x, x, 0, 0, 0, 0, 0, 0 }, | ||
| 122 | [Bw2] = { x, U, U, y, y, x, x, x, 0, 0, 0, 0, 0, 0 }, | ||
| 123 | [Bw3] = { x, U, U, U, y, x, x, x, 0, 0, 0, 0, 0, 0 }, | ||
| 124 | |||
| 125 | [M] = { y, x, U, x, x, U, U, U, y, x, y, y, y, 0 }, | ||
| 126 | [M2] = { y, x, U, U, x, x, U, U, x, x, x, y, 0, 0 }, | ||
| 127 | [M3] = { y, x, U, U, U, x, x, U, y, x, x, x, y, 0 }, | ||
| 128 | [S] = { x, U, U, U, x, x, U, y, y, y, x, 0, 0, 0 }, | ||
| 129 | [S2] = { x, U, U, x, x, U, U, y, y, x, 0, 0, 0, 0 }, | ||
| 130 | [S3] = { x, U, x, x, U, U, U, y, x, 0, 0, 0, 0, 0 }, | ||
| 131 | [E] = { U, x, x, U, U, U, x, x, y, y, y, 0, 0, 0 }, | ||
| 132 | [E2] = { U, U, x, x, U, U, x, x, y, y, 0, 0, 0, 0 }, | ||
| 133 | [E3] = { U, U, U, x, x, U, x, x, y, 0, 0, 0, 0, 0 }, | ||
| 134 | |||
| 135 | [x] = { x, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, | ||
| 136 | [x2] = { x, x, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, | ||
| 137 | [x3] = { x, x, x, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, | ||
| 138 | [y] = { y, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, | ||
| 139 | [y2] = { y, y, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, | ||
| 140 | [y3] = { y, y, y, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, | ||
| 141 | [z] = { y, y, y, x, y, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, | ||
| 142 | [z2] = { y, y, x, x, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, | ||
| 143 | [z3] = { y, x, y, y, y, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, | ||
| 144 | }; | ||
| 145 | |||
| 146 | /* Movesets */ | ||
| 147 | bool standard_moveset[NMOVES] = { | ||
| 148 | [U] = true, [U2] = true, [U3] = true, [D] = true, [D2] = true, [D3] = true, | ||
| 149 | [R] = true, [R2] = true, [R3] = true, [L] = true, [L2] = true, [L3] = true, | ||
| 150 | [F] = true, [F2] = true, [F3] = true, [B] = true, [B2] = true, [B3] = true, | ||
| 151 | }; | ||
| 152 | |||
| 153 | int epe_solved[] = {FR, FL, BL, BR}; | ||
| 154 | int eps_solved[] = {UL, UR, DL, DR}; | ||
| 155 | int epm_solved[] = {UF, UB, DF, DB}; | ||
| 156 | |||
| 157 | Cube blank_cube() { | ||
| 158 | Cube c = {0}; | ||
| 159 | return c; | ||
| 160 | } | ||
| 161 | |||
| 162 | void cube_to_arrays(Cube cube, CubeArray *arr, PieceFilter f) { | ||
| 163 | /* ep is the hardest */ | ||
| 164 | if (f.epose || f.eposs || f.eposm) | ||
| 165 | for (int i = 0; i < 12; i++) arr->ep[i] = -1; | ||
| 166 | if (f.epose) { | ||
| 167 | int epe[4], epose[12]; | ||
| 168 | index_to_perm(cube.epose % factorial(4), 4, epe); | ||
| 169 | index_to_subset(cube.epose / factorial(4), 12, 4, epose); | ||
| 170 | for (int i = 0, ie = 0; i < 12; i++) | ||
| 171 | if (epose[i]) arr->ep[i] = epe_solved[epe[ie++]]; | ||
| 172 | } | ||
| 173 | if (f.eposs) { | ||
| 174 | int eps[4], eposs[12]; | ||
| 175 | index_to_perm(cube.eposs % factorial(4), 4, eps); | ||
| 176 | index_to_subset(cube.eposs / factorial(4), 12, 4, eposs); | ||
| 177 | for (int i = 0; i < 4; i++) swap(&eposs[eps_solved[i]], &eposs[i+8]); | ||
| 178 | for (int i = 0, is = 0; i < 12; i++) | ||
| 179 | if (eposs[i]) arr->ep[i] = eps_solved[eps[is++]]; | ||
| 180 | } | ||
| 181 | if (f.eposm) { | ||
| 182 | int epm[4], eposm[12]; | ||
| 183 | index_to_perm(cube.eposm % factorial(4), 4, epm); | ||
| 184 | index_to_subset(cube.eposm / factorial(4), 12, 4, eposm); | ||
| 185 | for (int i = 0; i < 4; i++) swap(&eposm[epm_solved[i]], &eposm[i+8]); | ||
| 186 | for (int i = 0, im = 0; i < 12; i++) | ||
| 187 | if (eposm[i]) arr->ep[i] = epm_solved[epm[im++]]; | ||
| 188 | } | ||
| 189 | |||
| 190 | /* All the others */ | ||
| 191 | if (f.eofb) int_to_sum_zero_array(cube.eofb, 2, 12, arr->eofb); | ||
| 192 | if (f.eorl) int_to_sum_zero_array(cube.eorl, 2, 12, arr->eorl); | ||
| 193 | if (f.eoud) int_to_sum_zero_array(cube.eoud, 2, 12, arr->eoud); | ||
| 194 | if (f.cp) index_to_perm( cube.cp, 8, arr->cp); | ||
| 195 | if (f.coud) int_to_sum_zero_array(cube.coud, 3, 8, arr->coud); | ||
| 196 | if (f.corl) int_to_sum_zero_array(cube.corl, 3, 8, arr->corl); | ||
| 197 | if (f.cofb) int_to_sum_zero_array(cube.cofb, 3, 8, arr->cofb); | ||
| 198 | if (f.cpos) index_to_perm( cube.cpos, 6, arr->cpos); | ||
| 199 | } | ||
| 200 | |||
| 201 | Cube arrays_to_cube(CubeArray arr, PieceFilter f) { | ||
| 202 | Cube ret = {0}; | ||
| 203 | |||
| 204 | /* Again, ep is the hardest part */ | ||
| 205 | if (f.epose) { | ||
| 206 | int epe[4], epose[12] = {0,0,0,0,0,0,0,0,0,0,0,0}; | ||
| 207 | for (int i = 0, ie = 0; i < 12; i++) | ||
| 208 | for (int j = 0; j < 4; j++) | ||
| 209 | if (arr.ep[i] == epe_solved[j]) | ||
| 210 | { epe[ie++] = j; epose[i] = 1; } | ||
| 211 | ret.epose = factorial(4)*subset_to_index(epose,12,4)+perm_to_index(epe,4); | ||
| 212 | } | ||
| 213 | if (f.eposs) { | ||
| 214 | int eps[4], eposs[12] = {0,0,0,0,0,0,0,0,0,0,0,0}; | ||
| 215 | for (int i = 0, is = 0; i < 12; i++) | ||
| 216 | for (int j = 0; j < 4; j++) | ||
| 217 | if (arr.ep[i] == eps_solved[j]) | ||
| 218 | { eps[is++] = j; eposs[i] = 1; } | ||
| 219 | for (int i = 0; i < 4; i++) swap(&eposs[eps_solved[i]], &eposs[i+8]); | ||
| 220 | ret.eposs = factorial(4)*subset_to_index(eposs,12,4)+perm_to_index(eps,4); | ||
| 221 | } | ||
| 222 | if (f.eposm) { | ||
| 223 | int epm[4], eposm[12] = {0,0,0,0,0,0,0,0,0,0,0,0}; | ||
| 224 | for (int i = 0, im = 0; i < 12; i++) | ||
| 225 | for (int j = 0; j < 4; j++) | ||
| 226 | if (arr.ep[i] == epm_solved[j]) | ||
| 227 | { epm[im++] = j; eposm[i] = 1; } | ||
| 228 | for (int i = 0; i < 4; i++) swap(&eposm[epm_solved[i]], &eposm[i+8]); | ||
| 229 | ret.eposm = factorial(4)*subset_to_index(eposm,12,4)+perm_to_index(epm,4); | ||
| 230 | } | ||
| 231 | if (f.eofb) ret.eofb = digit_array_to_int(arr.eofb, 11, 2); | ||
| 232 | if (f.eorl) ret.eorl = digit_array_to_int(arr.eorl, 11, 2); | ||
| 233 | if (f.eoud) ret.eoud = digit_array_to_int(arr.eoud, 11, 2); | ||
| 234 | if (f.cp) ret.cp = perm_to_index( arr.cp, 8 ); | ||
| 235 | if (f.coud) ret.coud = digit_array_to_int(arr.coud, 7, 3); | ||
| 236 | if (f.corl) ret.corl = digit_array_to_int(arr.corl, 7, 3); | ||
| 237 | if (f.cofb) ret.cofb = digit_array_to_int(arr.cofb, 7, 3); | ||
| 238 | if (f.cpos) ret.cpos = perm_to_index( arr.cpos, 6 ); | ||
| 239 | |||
| 240 | return ret; | ||
| 241 | } | ||
| 242 | |||
| 243 | void move_cubearray(Move m, CubeArray *arr, PieceFilter f) { | ||
| 244 | if (f.epose || f.eposs || f.eposm) | ||
| 245 | apply_permutation(edge_cycle[m], arr->ep, 12); | ||
| 246 | if (f.eofb) { | ||
| 247 | apply_permutation(edge_cycle[m], arr->eofb, 12); | ||
| 248 | sum_arrays_mod(eofb_flipped[m], arr->eofb, 12, 2); | ||
| 249 | } | ||
| 250 | if (f.eofb) { | ||
| 251 | apply_permutation(edge_cycle[m], arr->eorl, 12); | ||
| 252 | sum_arrays_mod(eorl_flipped[m], arr->eorl, 12, 2); | ||
| 253 | } | ||
| 254 | if (f.eofb) { | ||
| 255 | apply_permutation(edge_cycle[m], arr->eoud, 12); | ||
| 256 | sum_arrays_mod(eoud_flipped[m], arr->eoud, 12, 2); | ||
| 257 | } | ||
| 258 | if (f.cp) | ||
| 259 | apply_permutation(corner_cycle[m], arr->cp, 8); | ||
| 260 | if (f.coud) { | ||
| 261 | apply_permutation(corner_cycle[m], arr->coud, 8); | ||
| 262 | sum_arrays_mod(coud_flipped[m], arr->coud, 8, 3); | ||
| 263 | } | ||
| 264 | if (f.corl) { | ||
| 265 | apply_permutation(corner_cycle[m], arr->corl, 8); | ||
| 266 | sum_arrays_mod(corl_flipped[m], arr->corl, 8, 3); | ||
| 267 | } | ||
| 268 | if (f.cofb) { | ||
| 269 | apply_permutation(corner_cycle[m], arr->cofb, 8); | ||
| 270 | sum_arrays_mod(cofb_flipped[m], arr->cofb, 8, 3); | ||
| 271 | } | ||
| 272 | if (f.cpos) | ||
| 273 | apply_permutation(center_cycle[m], arr->cpos, 6); | ||
| 274 | } | ||
| 275 | |||
| 276 | Cube move_via_array(Move m, Cube cube, PieceFilter f) { | ||
| 277 | CubeArray arr = {0}; | ||
| 278 | cube_to_arrays(cube, &arr, f); | ||
| 279 | move_cubearray(m, &arr, f); | ||
| 280 | return arrays_to_cube(arr, f); | ||
| 281 | } | ||
| 282 | |||
| 283 | int copy_alg(NissMove *src, NissMove *dest) { | ||
| 284 | int i; | ||
| 285 | for (i = 0; src[i].m != NULLMOVE; i++) | ||
| 286 | dest[i] = src[i]; | ||
| 287 | dest[i].m = NULLMOVE; | ||
| 288 | return i; | ||
| 289 | } | ||
| 290 | |||
| 291 | bool equal(Cube c1, Cube c2) { | ||
| 292 | return c1.eofb == c2.eofb && c1.epose == c2.epose && | ||
| 293 | c1.eposs == c2.eposs && c1.eposm == c2.eposm && | ||
| 294 | c1.coud == c2.coud && c1.cp == c2.cp && | ||
| 295 | c1.cpos == c2.cpos; | ||
| 296 | } | ||
| 297 | |||
| 298 | bool solvable(Cube cube) { | ||
| 299 | /* Since we memorize orientation truncating the last digit, we only need to | ||
| 300 | * check that the permutations have the correct sign. */ | ||
| 301 | CubeArray arr = {0}; | ||
| 302 | cube_to_arrays(cube, &arr, fAll); | ||
| 303 | return (perm_sign(arr.ep,12) ^ perm_sign(arr.cpos,6)) == perm_sign(arr.cp,8); | ||
| 304 | } | ||
| 305 | |||
| 306 | bool is_solved(Cube cube, bool reorient) { | ||
| 307 | if (!reorient || !cube.cpos) | ||
| 308 | return !cube.eofb && !cube.coud && !cube.cp && | ||
| 309 | !cube.epose && !cube.eposs && !cube.eposm; | ||
| 310 | |||
| 311 | bool ret = false; | ||
| 312 | for (int i = x; i <= z3; i++) { | ||
| 313 | ret = ret || is_solved(move_cube(i, cube), false); | ||
| 314 | for (int j = x; j <= z3; j++) | ||
| 315 | ret = ret || is_solved(move_cube(i, move_cube(j, cube)), false); | ||
| 316 | } | ||
| 317 | return ret; | ||
| 318 | } | ||
| 319 | |||
| 320 | void print_cube(Cube cube) { | ||
| 321 | CubeArray arr = {0}; | ||
| 322 | cube_to_arrays(cube, &arr, fAll); | ||
| 323 | |||
| 324 | for (int i = 0; i < 12; i++) printf(" %s ", edge_string[arr.ep[i]]); | ||
| 325 | printf("\n"); | ||
| 326 | for (int i = 0; i < 12; i++) printf(" %c ", arr.eofb[i] + '0'); | ||
| 327 | printf("\n"); | ||
| 328 | for (int i = 0; i < 8; i++) printf("%s ", corner_string[arr.cp[i]]); | ||
| 329 | printf("\n"); | ||
| 330 | for (int i = 0; i < 8; i++) printf(" %c ", arr.coud[i] + '0'); | ||
| 331 | printf("\n"); | ||
| 332 | for (int i = 0; i < 6; i++) printf(" %s ", center_string[arr.cpos[i]]); | ||
| 333 | printf("\n"); | ||
| 334 | } | ||
| 335 | |||
| 336 | /* TODO: all strings start with space?? */ | ||
| 337 | void print_moves(NissMove *alg) { | ||
| 338 | bool niss = false; | ||
| 339 | for (int i = 0; alg[i].m != NULLMOVE; i++) { | ||
| 340 | char *fill = !niss && alg[i].inverse ? " (" : | ||
| 341 | (niss && !alg[i].inverse ? ") " : " "); | ||
| 342 | printf("%s%s", fill, move_string[alg[i].m]); | ||
| 343 | niss = alg[i].inverse; | ||
| 344 | } | ||
| 345 | printf("%s\n", niss ? ")" : ""); | ||
| 346 | } | ||
| 347 | |||
| 348 | int read_moves(char *str, NissMove *alg, int n) { | ||
| 349 | bool niss = false; | ||
| 350 | int c = 0; | ||
| 351 | |||
| 352 | for (int i = 0; str[i] && c < n; i++) { | ||
| 353 | if (str[i] == ' ' || str[i] == '\t' || str[i] == '\n') | ||
| 354 | continue; | ||
| 355 | |||
| 356 | if (str[i] == '(' || str[i] == ')') { | ||
| 357 | if ((niss && str[i] == '(') || (!niss && str[i] == ')')) | ||
| 358 | return -1; | ||
| 359 | niss = !niss; | ||
| 360 | continue; | ||
| 361 | } | ||
| 362 | |||
| 363 | alg[c].inverse = niss; alg[c].m = NULLMOVE; | ||
| 364 | for (Move j = 0; j < NMOVES; j++) { | ||
| 365 | if (str[i] == move_string[j][0]) { | ||
| 366 | alg[c].m = j; | ||
| 367 | if (alg[c].m <= B && str[i+1]=='w') { alg[c].m += Uw - U; i++; } | ||
| 368 | if (str[i+1]=='2') { alg[c].m += 1; i++; } | ||
| 369 | else if (str[i+1]=='\'' || str[i+1]=='3') { alg[c].m += 2; i++; } | ||
| 370 | c++; | ||
| 371 | break; | ||
| 372 | } | ||
| 373 | } | ||
| 374 | } | ||
| 375 | |||
| 376 | alg[c].m = NULLMOVE; | ||
| 377 | return c; | ||
| 378 | } | ||
| 379 | |||
| 380 | /* Helper function for cleanup. alg must contain only basic moves, no 2 or '. | ||
| 381 | top and front describe an admissible orientation of the cube. */ | ||
| 382 | void sort_cancel_rotate(NissMove *alg, int n, bool inv, int top, int front) { | ||
| 383 | int c = 0, i = 0; | ||
| 384 | NissMove aux[n+3]; | ||
| 385 | aux[0].m = NULLMOVE; | ||
| 386 | |||
| 387 | while (i < n && alg[i].m != NULLMOVE) { | ||
| 388 | int j = i; | ||
| 389 | while (j < n && commute[alg[i].m][alg[j].m]) j++; | ||
| 390 | Move base = 6*((alg[i].m-1)/6); | ||
| 391 | int t1 = 0, t2 = 0; | ||
| 392 | for (int k = i; k < j; k++) | ||
| 393 | if (alg[k].m == base+1) t1 = (t1+1)%4; | ||
| 394 | else t2 = (t2+1)%4; | ||
| 395 | if (t1) { aux[c].inverse = inv; aux[c].m = base+t1; c++; } | ||
| 396 | if (t2) { aux[c].inverse = inv; aux[c].m = base+t2+3; c++; } | ||
| 397 | i = j; | ||
| 398 | } | ||
| 399 | aux[c].m = NULLMOVE; | ||
| 400 | |||
| 401 | CubeArray q; | ||
| 402 | cube_to_arrays(blank_cube(), &q, cpos_only); | ||
| 403 | /* First we try to rotate in one move, then we try an x or y rotation | ||
| 404 | followed by a z rotation */ | ||
| 405 | for (int r = x; r <= z3; r++) { | ||
| 406 | move_cubearray(r, &q, cpos_only); | ||
| 407 | if (q.cpos[F_center] == front && q.cpos[U_center] == top) { | ||
| 408 | aux[c].inverse = inv; aux[c].m = r; | ||
| 409 | |||
| 410 | aux[++c].m = NULLMOVE; | ||
| 411 | copy_alg(aux, alg); | ||
| 412 | return; | ||
| 413 | } | ||
| 414 | move_cubearray(inverse[r], &q, cpos_only); | ||
| 415 | } | ||
| 416 | for (int r = x; r <= y3; r++) { | ||
| 417 | move_cubearray(r, &q, cpos_only); | ||
| 418 | if (q.cpos[F_center] == front) { | ||
| 419 | aux[c].inverse = inv; aux[c++].m = r; | ||
| 420 | break; | ||
| 421 | } | ||
| 422 | move_cubearray(inverse[r], &q, cpos_only); | ||
| 423 | } | ||
| 424 | for (int r = z; r <= z3; r++) { | ||
| 425 | move_cubearray(r, &q, cpos_only); | ||
| 426 | if (q.cpos[U_center] == top) { | ||
| 427 | aux[c].inverse = inv; aux[c++].m = r; | ||
| 428 | break; | ||
| 429 | } | ||
| 430 | move_cubearray(inverse[r], &q, cpos_only); | ||
| 431 | } | ||
| 432 | |||
| 433 | aux[c].m = NULLMOVE; | ||
| 434 | copy_alg(aux, alg); | ||
| 435 | } | ||
| 436 | |||
| 437 | void cleanup(NissMove *alg, int n) { | ||
| 438 | int count_n = 0, count_i = 0, *count; | ||
| 439 | NissMove aux_n[n+1], aux_i[n+1], *aux; | ||
| 440 | CubeArray cube_n, cube_i, *cube; | ||
| 441 | cube_to_arrays(blank_cube(), &cube_n, cpos_only); | ||
| 442 | cube_to_arrays(blank_cube(), &cube_i, cpos_only); | ||
| 443 | |||
| 444 | for (int i = 0; count_n + count_i < n && alg[i].m != NULLMOVE; i++) { | ||
| 445 | if (alg[i].inverse) { count = &count_i; aux = aux_i; cube = &cube_i; } | ||
| 446 | else { count = &count_n; aux = aux_n; cube = &cube_n; } | ||
| 447 | |||
| 448 | for (int j = 0; equiv_moves[alg[i].m][j]; j++) { | ||
| 449 | Move m = equiv_moves[alg[i].m][j]; | ||
| 450 | aux[*count].inverse = alg[i].inverse; | ||
| 451 | move_cubearray(m, cube, cpos_only); | ||
| 452 | if (m == U) aux[(*count)++].m = 3 * cube->cpos[0] + 1; | ||
| 453 | } | ||
| 454 | } | ||
| 455 | |||
| 456 | aux_n[count_n].m = NULLMOVE; | ||
| 457 | aux_i[count_i].m = NULLMOVE; | ||
| 458 | sort_cancel_rotate(aux_n, count_n, false, cube_n.cpos[0], cube_n.cpos[4]); | ||
| 459 | sort_cancel_rotate(aux_i, count_i, true, cube_i.cpos[0], cube_n.cpos[4]); | ||
| 460 | copy_alg(aux_n, alg); | ||
| 461 | copy_alg(aux_i, alg+count_n); | ||
| 462 | } | ||
| 463 | |||
| 464 | Cube inverse_cube(Cube cube) { | ||
| 465 | CubeArray arr = {0}, inv = {0}; | ||
| 466 | cube_to_arrays(cube, &arr, fAll); | ||
| 467 | |||
| 468 | for (int i = 0; i < 12; i++) { | ||
| 469 | inv.ep[arr.ep[i]] = i; | ||
| 470 | inv.eofb[arr.ep[i]] = arr.eofb[i]; | ||
| 471 | inv.eorl[arr.ep[i]] = arr.eorl[i]; | ||
| 472 | inv.eoud[arr.ep[i]] = arr.eoud[i]; | ||
| 473 | } | ||
| 474 | for (int i = 0; i < 8; i++) { | ||
| 475 | inv.cp[arr.cp[i]] = i; | ||
| 476 | inv.coud[arr.cp[i]] = arr.coud[i]; | ||
| 477 | inv.corl[arr.cp[i]] = arr.corl[i]; | ||
| 478 | inv.cofb[arr.cp[i]] = arr.cofb[i]; | ||
| 479 | } | ||
| 480 | for (int i = 0; i < 6; i++) | ||
| 481 | inv.cpos[arr.cpos[i]] = i; | ||
| 482 | |||
| 483 | return arrays_to_cube(inv, fAll); | ||
| 484 | } | ||
| 485 | |||
| 486 | bool read_ttables_file() { | ||
| 487 | FILE *ttf; | ||
| 488 | if ((ttf = fopen("ttables", "rb")) != NULL) { | ||
| 489 | for (int m = 0; m < NMOVES; m++) { | ||
| 490 | fread(epose_ttable[m], sizeof(uint16_t), factorial12/factorial8, ttf); | ||
| 491 | fread(eposs_ttable[m], sizeof(uint16_t), factorial12/factorial8, ttf); | ||
| 492 | fread(eposm_ttable[m], sizeof(uint16_t), factorial12/factorial8, ttf); | ||
| 493 | fread(eofb_ttable[m], sizeof(uint16_t), pow2to11, ttf); | ||
| 494 | fread(eorl_ttable[m], sizeof(uint16_t), pow2to11, ttf); | ||
| 495 | fread(eoud_ttable[m], sizeof(uint16_t), pow2to11, ttf); | ||
| 496 | fread(cp_ttable[m], sizeof(uint16_t), factorial8, ttf); | ||
| 497 | fread(coud_ttable[m], sizeof(uint16_t), pow3to7, ttf); | ||
| 498 | fread(corl_ttable[m], sizeof(uint16_t), pow3to7, ttf); | ||
| 499 | fread(cofb_ttable[m], sizeof(uint16_t), pow3to7, ttf); | ||
| 500 | fread(cpos_ttable[m], sizeof(uint16_t), factorial6, ttf); | ||
| 501 | } | ||
| 502 | fclose(ttf); | ||
| 503 | return true; | ||
| 504 | } else return false; | ||
| 505 | } | ||
| 506 | |||
| 507 | bool write_ttables_file() { | ||
| 508 | FILE *ttf; | ||
| 509 | if ((ttf = fopen("ttables", "wb")) != NULL) { | ||
| 510 | for (int m = 0; m < NMOVES; m++) { | ||
| 511 | fwrite(epose_ttable[m], sizeof(uint16_t), factorial12/factorial8, ttf); | ||
| 512 | fwrite(eposs_ttable[m], sizeof(uint16_t), factorial12/factorial8, ttf); | ||
| 513 | fwrite(eposm_ttable[m], sizeof(uint16_t), factorial12/factorial8, ttf); | ||
| 514 | fwrite(eofb_ttable[m], sizeof(uint16_t), pow2to11, ttf); | ||
| 515 | fwrite(eorl_ttable[m], sizeof(uint16_t), pow2to11, ttf); | ||
| 516 | fwrite(eoud_ttable[m], sizeof(uint16_t), pow2to11, ttf); | ||
| 517 | fwrite(cp_ttable[m], sizeof(uint16_t), factorial8, ttf); | ||
| 518 | fwrite(coud_ttable[m], sizeof(uint16_t), pow3to7, ttf); | ||
| 519 | fwrite(corl_ttable[m], sizeof(uint16_t), pow3to7, ttf); | ||
| 520 | fwrite(cofb_ttable[m], sizeof(uint16_t), pow3to7, ttf); | ||
| 521 | fwrite(cpos_ttable[m], sizeof(uint16_t), factorial6, ttf); | ||
| 522 | } | ||
| 523 | fclose(ttf); | ||
| 524 | return true; | ||
| 525 | } else return false; | ||
| 526 | } | ||
| 527 | |||
| 528 | void init_ttables(bool read, bool write) { | ||
| 529 | /* Generate all move cycles and flips; I do this regardless */ | ||
| 530 | for (int i = 0; i < NMOVES; i++) { | ||
| 531 | if (i == U || i == x || i == y) | ||
| 532 | continue; | ||
| 533 | |||
| 534 | CubeArray arr = {0}; | ||
| 535 | cube_to_arrays(blank_cube(), &arr, fAll); | ||
| 536 | for (int j = 0; equiv_moves[i][j]; j++) | ||
| 537 | move_cubearray(equiv_moves[i][j], &arr, fAll); | ||
| 538 | |||
| 539 | intarrcopy(arr.ep, edge_cycle[i], 12); | ||
| 540 | intarrcopy(arr.eofb, eofb_flipped[i], 12); | ||
| 541 | intarrcopy(arr.eorl, eorl_flipped[i], 12); | ||
| 542 | intarrcopy(arr.eoud, eoud_flipped[i], 12); | ||
| 543 | intarrcopy(arr.cp, corner_cycle[i], 8); | ||
| 544 | intarrcopy(arr.coud, coud_flipped[i], 8); | ||
| 545 | intarrcopy(arr.corl, corl_flipped[i], 8); | ||
| 546 | intarrcopy(arr.cofb, cofb_flipped[i], 8); | ||
| 547 | intarrcopy(arr.cpos, center_cycle[i], 6); | ||
| 548 | } | ||
| 549 | |||
| 550 | if (read) | ||
| 551 | if (read_ttables_file()) | ||
| 552 | return; | ||
| 553 | |||
| 554 | /* Initialize transition tables */ | ||
| 555 | Cube c = {0}; | ||
| 556 | PieceFilter fe = {.epose=true}, fs = {.eposs=true}, fm = {.eposm=true}; | ||
| 557 | PieceFilter feo = { .eofb = true, .eorl = true, .eoud = true }; | ||
| 558 | PieceFilter fcp = { .cp = true }; | ||
| 559 | PieceFilter fco = { .cofb = true, .corl = true, .coud = true }; | ||
| 560 | PieceFilter fcc = { .cpos = true }; | ||
| 561 | for (int m = 0; m < NMOVES; m++) { | ||
| 562 | for (uint16_t i = 0; i < factorial12/factorial8; i++) { | ||
| 563 | c.epose = i; epose_ttable[m][i] = move_via_array(m, c, fe).epose; | ||
| 564 | c.eposs = i; eposs_ttable[m][i] = move_via_array(m, c, fs).eposs; | ||
| 565 | c.eposm = i; eposm_ttable[m][i] = move_via_array(m, c, fm).eposm; | ||
| 566 | } | ||
| 567 | for (uint16_t i = 0; i < pow2to11; i++ ) { | ||
| 568 | c.eofb = i; eofb_ttable[m][i] = move_via_array(m, c, feo).eofb; | ||
| 569 | c.eorl = i; eorl_ttable[m][i] = move_via_array(m, c, feo).eorl; | ||
| 570 | c.eoud = i; eoud_ttable[m][i] = move_via_array(m, c, feo).eoud; | ||
| 571 | } | ||
| 572 | for (uint16_t i = 0; i < factorial8; i++) { | ||
| 573 | c.cp = i; cp_ttable[m][i] = move_via_array(m, c, fcp).cp; | ||
| 574 | } | ||
| 575 | for (uint16_t i = 0; i < pow3to7; i++) { | ||
| 576 | c.coud = i; coud_ttable[m][i] = move_via_array(m, c, fco).coud; | ||
| 577 | c.corl = i; corl_ttable[m][i] = move_via_array(m, c, fco).corl; | ||
| 578 | c.cofb = i; cofb_ttable[m][i] = move_via_array(m, c, fco).cofb; | ||
| 579 | } | ||
| 580 | for (uint16_t i = 0; i < factorial6; i++) { | ||
| 581 | c.cpos = i; cpos_ttable[m][i] = move_via_array(m, c, fcc).cpos; | ||
| 582 | } | ||
| 583 | } | ||
| 584 | |||
| 585 | if (write) write_ttables_file(); | ||
| 586 | } | ||
| 587 | |||
| 588 | Cube move_cube(Move m, Cube cube) { | ||
| 589 | Cube moved = cube; | ||
| 590 | |||
| 591 | moved.epose = epose_ttable[m][cube.epose]; | ||
| 592 | moved.eposs = eposs_ttable[m][cube.eposs]; | ||
| 593 | moved.eposm = eposm_ttable[m][cube.eposm]; | ||
| 594 | moved.eofb = eofb_ttable[m][cube.eofb]; | ||
| 595 | moved.eorl = eorl_ttable[m][cube.eorl]; | ||
| 596 | moved.eoud = eoud_ttable[m][cube.eoud]; | ||
| 597 | moved.coud = coud_ttable[m][cube.coud]; | ||
| 598 | moved.cofb = cofb_ttable[m][cube.cofb]; | ||
| 599 | moved.corl = corl_ttable[m][cube.corl]; | ||
| 600 | moved.cp = cp_ttable[m][cube.cp]; | ||
| 601 | moved.cpos = cpos_ttable[m][cube.cpos]; | ||
| 602 | |||
| 603 | return moved; | ||
| 604 | } | ||
| 605 | |||
| 606 | Cube compose(Cube c2, Cube c1) { | ||
| 607 | /* This is basically the same as the move_cubearray function above */ | ||
| 608 | CubeArray arr2 = {0}, arr1 = {0}; | ||
| 609 | cube_to_arrays(c2, &arr2, fAll); | ||
| 610 | cube_to_arrays(c1, &arr1, fAll); | ||
| 611 | |||
| 612 | apply_permutation(arr2.ep, arr1.ep, 12); | ||
| 613 | apply_permutation(arr2.ep, arr1.eofb, 12); | ||
| 614 | apply_permutation(arr2.ep, arr1.eorl, 12); | ||
| 615 | apply_permutation(arr2.ep, arr1.eoud, 12); | ||
| 616 | sum_arrays_mod(arr2.eofb, arr1.eofb, 12, 2); | ||
| 617 | sum_arrays_mod(arr2.eorl, arr1.eorl, 12, 2); | ||
| 618 | sum_arrays_mod(arr2.eoud, arr1.eoud, 12, 2); | ||
| 619 | apply_permutation(arr2.cp, arr1.cp, 8); | ||
| 620 | apply_permutation(arr2.cp, arr1.coud, 8); | ||
| 621 | apply_permutation(arr2.cp, arr1.corl, 8); | ||
| 622 | apply_permutation(arr2.cp, arr1.cofb, 8); | ||
| 623 | sum_arrays_mod(arr2.coud, arr1.coud, 8, 3); | ||
| 624 | sum_arrays_mod(arr2.corl, arr1.corl, 8, 3); | ||
| 625 | sum_arrays_mod(arr2.cofb, arr1.cofb, 8, 3); | ||
| 626 | apply_permutation(arr2.cpos, arr1.cpos, 6); | ||
| 627 | |||
| 628 | return arrays_to_cube(arr1, fAll); | ||
| 629 | } | ||
| 630 | |||
| 631 | Cube apply_alg(NissMove *alg, Cube cube) { | ||
| 632 | Cube ret = {0}; | ||
| 633 | for (int i = 0; alg[i].m != NULLMOVE; i++) | ||
| 634 | if (alg[i].inverse) | ||
| 635 | ret = move_cube(alg[i].m, ret); | ||
| 636 | ret = compose(cube, inverse_cube(ret)); | ||
| 637 | |||
| 638 | for (int i = 0; alg[i].m != NULLMOVE; i++) | ||
| 639 | if (!alg[i].inverse) | ||
| 640 | ret = move_cube(alg[i].m, ret); | ||
| 641 | return ret; | ||
| 642 | } | ||
| 643 | |||
| 644 | void init_aux_tables() { | ||
| 645 | /* Commute */ | ||
| 646 | for (int i = 0; i < NMOVES; i++) | ||
| 647 | for (int j = 0; j < NMOVES; j++) | ||
| 648 | commute[i][j] = equal(move_cube(i, move_cube(j, blank_cube())), | ||
| 649 | move_cube(j, move_cube(i, blank_cube()))); | ||
| 650 | |||
| 651 | /* Possible next (if the sequence i j k is valid) */ | ||
| 652 | for (int i = 0; i < NMOVES; i++) | ||
| 653 | for (int j = 0; j < NMOVES; j++) | ||
| 654 | for (int k = 0; k < NMOVES; k++) | ||
| 655 | possible_next[i][j][k] = | ||
| 656 | (j == 0) || | ||
| 657 | (j != 0 && (j-(j-1)%3) != (k-(k-1)%3) && | ||
| 658 | !(i != 0 && commute[i][j] && (i-(i-1)%3) == (k-(k-1)%3))); | ||
| 659 | |||
| 660 | /* Inverse */ | ||
| 661 | for (int i = 0; i < NMOVES; i++) | ||
| 662 | inverse[i] = i == 0 ? 0 : i + 2 - 2*((i-1)%3); | ||
| 663 | } | ||
| 664 | |||
diff --git a/old/2021-02-06/cube.h b/old/2021-02-06/cube.h new file mode 100644 index 0000000..bc4f14b --- /dev/null +++ b/old/2021-02-06/cube.h | |||
| @@ -0,0 +1,60 @@ | |||
| 1 | #ifndef CUBE_H | ||
| 2 | #define CUBE_H | ||
| 3 | |||
| 4 | #include <stdio.h> | ||
| 5 | #include <stdbool.h> | ||
| 6 | #include <stdint.h> | ||
| 7 | #include "utils.h" | ||
| 8 | |||
| 9 | #define NMOVES (z3+1) | ||
| 10 | |||
| 11 | /* Constants for moves and pieces */ | ||
| 12 | typedef enum { | ||
| 13 | NULLMOVE, | ||
| 14 | U, U2, U3, D, D2, D3, R, R2, R3, L, L2, L3, F, F2, F3, B, B2, B3, | ||
| 15 | Uw, Uw2, Uw3, Dw, Dw2, Dw3, Rw, Rw2, Rw3, | ||
| 16 | Lw, Lw2, Lw3, Fw, Fw2, Fw3, Bw, Bw2, Bw3, | ||
| 17 | M, M2, M3, S, S2, S3, E, E2, E3, | ||
| 18 | x, x2, x3, y, y2, y3, z, z2, z3, | ||
| 19 | } Move; | ||
| 20 | typedef enum {U_center,D_center,R_center,L_center,F_center,B_center} Center; | ||
| 21 | typedef enum { UF, UL, UB, UR, DF, DL, DB, DR, FR, FL, BL, BR } Edge; | ||
| 22 | typedef enum { UFR, UFL, UBL, UBR, DFR, DFL, DBL, DBR } Corner; | ||
| 23 | |||
| 24 | /* An alg is an array of "NissMoves", which can be on normal or on inverse. */ | ||
| 25 | typedef struct { bool inverse; Move m; } NissMove; | ||
| 26 | |||
| 27 | /* Representation of the cube */ | ||
| 28 | typedef struct { | ||
| 29 | uint16_t eofb, eorl, eoud, coud, cofb, corl, | ||
| 30 | epose, eposs, eposm, cp, cpos; | ||
| 31 | } Cube; | ||
| 32 | |||
| 33 | extern bool commute[NMOVES][NMOVES]; | ||
| 34 | extern bool possible_next[NMOVES][NMOVES][NMOVES]; | ||
| 35 | extern Move inverse[NMOVES]; | ||
| 36 | /* Movesets */ | ||
| 37 | extern bool standard_moveset[NMOVES]; | ||
| 38 | |||
| 39 | int copy_alg(NissMove *src, NissMove *dest); /*return number of moves copied */ | ||
| 40 | |||
| 41 | bool equal(Cube c1, Cube c2); | ||
| 42 | bool is_solvable(Cube cube); | ||
| 43 | /* reorient=true allows solved in wrong orientation */ | ||
| 44 | bool is_solved(Cube cube, bool reorient); | ||
| 45 | void print_cube(Cube cube); | ||
| 46 | void print_moves(NissMove *alg); | ||
| 47 | int read_moves(char *str, NissMove *alg, int n); /* reads at most n moves */ | ||
| 48 | void cleanup(NissMove *src, int n); /* rewrites using basic moves, at most n */ | ||
| 49 | Cube blank_cube(); | ||
| 50 | Cube inverse_cube(Cube cube); | ||
| 51 | Cube move_cube(Move m, Cube cube); | ||
| 52 | Cube compose(Cube c2, Cube c1); /* Use c2 as an alg */ | ||
| 53 | Cube apply_alg(NissMove *alg, Cube cube); | ||
| 54 | |||
| 55 | void init_ttables(bool read, bool write); | ||
| 56 | void init_aux_tables(); | ||
| 57 | |||
| 58 | void init_dbg(); | ||
| 59 | |||
| 60 | #endif | ||
diff --git a/old/2021-02-06/main.c b/old/2021-02-06/main.c new file mode 100644 index 0000000..c7be782 --- /dev/null +++ b/old/2021-02-06/main.c | |||
| @@ -0,0 +1,46 @@ | |||
| 1 | #include <stdio.h> | ||
| 2 | #include "cube.h" | ||
| 3 | #include "solve.h" | ||
| 4 | |||
| 5 | int main() { | ||
| 6 | init_ttables(true, true); | ||
| 7 | init_aux_tables(); | ||
| 8 | |||
| 9 | |||
| 10 | char moves[100] = "MR U' B2 Bw F z xE2 M' x Dw' y Fw2 y2"; | ||
| 11 | NissMove alg[100]; | ||
| 12 | read_moves(moves, alg, 100); | ||
| 13 | Cube cube = apply_alg(alg, blank_cube()); | ||
| 14 | |||
| 15 | /*f_eofb(cube);*/ | ||
| 16 | |||
| 17 | |||
| 18 | /* NissMove sol[MAXS][MAXM];*/ | ||
| 19 | SolveData d = { .optimal_only = true, .available = standard_moveset, | ||
| 20 | .max_moves = 10, | ||
| 21 | .cleanup = true, | ||
| 22 | .max_solutions = 10, | ||
| 23 | .f = f_eofb }; | ||
| 24 | read_moves("y", d.pre_rotation, 2); | ||
| 25 | int n = solve(cube, &d); | ||
| 26 | printf("%d solutions found:\n", n); | ||
| 27 | for (int i = 0; i < n; i++) | ||
| 28 | print_moves(d.solutions[i]); | ||
| 29 | |||
| 30 | NissMove a[5], b[5]; | ||
| 31 | read_moves("R", a, 5); | ||
| 32 | read_moves("U", b, 5); | ||
| 33 | Cube c1 = apply_alg(a,blank_cube()), c2 = apply_alg(b,blank_cube()); | ||
| 34 | print_cube(compose(c2,c1)); | ||
| 35 | print_cube(compose(c1,c2)); | ||
| 36 | /*print_cube(compose(c2,blank_cube()));*/ | ||
| 37 | |||
| 38 | NissMove nm[10]; | ||
| 39 | read_moves("y(y)RU", nm, 10); | ||
| 40 | |||
| 41 | print_moves(nm); | ||
| 42 | cleanup(nm, 10); | ||
| 43 | print_moves(nm); | ||
| 44 | |||
| 45 | return 0; | ||
| 46 | } | ||
diff --git a/old/2021-02-06/solve.c b/old/2021-02-06/solve.c new file mode 100644 index 0000000..f6274e9 --- /dev/null +++ b/old/2021-02-06/solve.c | |||
| @@ -0,0 +1,177 @@ | |||
| 1 | #include "solve.h" | ||
| 2 | |||
| 3 | /* Data for creating a pruning table: | ||
| 4 | - compressed: if set to true, each entry occupies only 4 bits, but values | ||
| 5 | larger than 15 cannot be stored. | ||
| 6 | - available[] is the list of availabel moves, as above. | ||
| 7 | - *ptable is the actual table to fill. | ||
| 8 | - n is the number of states (size of ptable). | ||
| 9 | - index must "linearize" the cube, i.e. return its index in ptable. | ||
| 10 | - fname is the name of the file where to store the table */ | ||
| 11 | typedef struct { | ||
| 12 | bool compressed, *available; | ||
| 13 | int max_moves; | ||
| 14 | uint8_t *ptable; | ||
| 15 | uint64_t n; | ||
| 16 | uint64_t (*index)(Cube); | ||
| 17 | char *fname; | ||
| 18 | } PruneData; | ||
| 19 | |||
| 20 | /* TODO: comment this */ | ||
| 21 | typedef struct { | ||
| 22 | bool niss; | ||
| 23 | int m, d; | ||
| 24 | uint64_t *n; | ||
| 25 | Move last1, last2; | ||
| 26 | } DfsData; | ||
| 27 | |||
| 28 | void solve_dfs(Cube cube, SolveData *sd, DfsData dd); | ||
| 29 | void init_ptable(PruneData *pd, bool read, bool write); | ||
| 30 | |||
| 31 | /* Search solutions of lenght exactly d */ | ||
| 32 | void solve_dfs(Cube cube, SolveData *sd, DfsData dd) { | ||
| 33 | if (*dd.n >= sd->max_solutions || | ||
| 34 | ((!sd->can_niss || dd.niss) && dd.m + sd->f(cube) > dd.d)) | ||
| 35 | return; | ||
| 36 | |||
| 37 | (sd->solutions[*dd.n][dd.m]).inverse = dd.niss; | ||
| 38 | (sd->solutions[*dd.n][dd.m]).m = NULLMOVE; | ||
| 39 | |||
| 40 | if (!sd->f(cube)) { /* Solved */ | ||
| 41 | if (dd.m == dd.d) { | ||
| 42 | (*dd.n)++; | ||
| 43 | if (*dd.n < sd->max_solutions) | ||
| 44 | copy_alg(sd->solutions[*dd.n-1], sd->solutions[*dd.n]); | ||
| 45 | } | ||
| 46 | return; | ||
| 47 | } | ||
| 48 | |||
| 49 | for (int i = 0; i < NMOVES && sd->sorted_moves[i] != NULLMOVE; i++) { | ||
| 50 | Move move = sd->sorted_moves[i]; | ||
| 51 | if (possible_next[dd.last2][dd.last1][move]) { | ||
| 52 | sd->solutions[*dd.n][dd.m].inverse = dd.niss; | ||
| 53 | sd->solutions[*dd.n][dd.m].m = move; | ||
| 54 | DfsData nn = { .niss = dd.niss, .m = dd.m+1, .d = dd.d, .n = dd.n, | ||
| 55 | .last1 = move, .last2 = dd.last1 }; | ||
| 56 | solve_dfs(move_cube(move, cube), sd, nn); | ||
| 57 | } | ||
| 58 | } | ||
| 59 | |||
| 60 | if (sd->can_niss && !dd.niss && | ||
| 61 | (!dd.m || (dd.m && sd->f(move_cube(dd.last1, blank_cube()))))) { | ||
| 62 | DfsData nn = { .niss = true, .m = dd.m, .d = dd.d, .n = dd.n }; | ||
| 63 | solve_dfs(inverse_cube(cube), sd, nn); | ||
| 64 | } | ||
| 65 | } | ||
| 66 | |||
| 67 | /* Iterative deepening depth-first search: for i running from the minimum | ||
| 68 | to the maximum number of moves allowed, looks for solutions of length i. */ | ||
| 69 | int solve(Cube cube, SolveData *sd) { | ||
| 70 | if (sd->precondition != NULL && !sd->precondition(cube)) | ||
| 71 | return -1; | ||
| 72 | |||
| 73 | /* If not given, generate sorted list of moves */ | ||
| 74 | if (sd->sorted_moves[0] == NULLMOVE) { | ||
| 75 | int a[NMOVES], b[NMOVES], ia = 0, ib = 0; | ||
| 76 | for (int i = 0; i < NMOVES; i++) { | ||
| 77 | if (sd->available[i]) { | ||
| 78 | if (sd->f(move_cube(i, blank_cube()))) | ||
| 79 | a[ia++] = i; | ||
| 80 | else | ||
| 81 | b[ib++] = i; | ||
| 82 | } | ||
| 83 | } | ||
| 84 | intarrcopy(a, (int *)sd->sorted_moves, ia); | ||
| 85 | intarrcopy(b, (int *)sd->sorted_moves+ia, ib); | ||
| 86 | sd->sorted_moves[ia+ib] = NULLMOVE; | ||
| 87 | } | ||
| 88 | |||
| 89 | sd->max_solutions = min(sd->max_solutions, MAXS); | ||
| 90 | Cube rotated = apply_alg(sd->pre_rotation, blank_cube()); | ||
| 91 | cube = apply_alg(inverse_cube(rotated), compose(cube, rotated)); | ||
| 92 | |||
| 93 | uint64_t ret = 0; | ||
| 94 | for (int i=sd->min_moves; i<=sd->max_moves&&!(ret&&sd->optimal_only); i++) { | ||
| 95 | DfsData dd = { .d = i, .n = &ret }; | ||
| 96 | solve_dfs(cube, sd, dd); | ||
| 97 | } | ||
| 98 | |||
| 99 | for (uint64_t i = 0; i < ret; i++) { | ||
| 100 | /* TODO: transform solutions with inverse of pre_rotation */ | ||
| 101 | if (sd->cleanup) | ||
| 102 | cleanup(sd->solutions[i], sd->max_moves*3); | ||
| 103 | } | ||
| 104 | |||
| 105 | return ret; | ||
| 106 | } | ||
| 107 | |||
| 108 | void prune_dfs(Cube cube, PruneData *pd, DfsData dd) { | ||
| 109 | uint64_t ind = pd->index(cube); | ||
| 110 | if ((!ind || pd->ptable[ind]) && pd->ptable[ind] != dd.m) | ||
| 111 | return; | ||
| 112 | if (dd.m == dd.d) { | ||
| 113 | if (ind && !pd->ptable[ind]) { | ||
| 114 | pd->ptable[ind] = dd.m; | ||
| 115 | (*dd.n)++; | ||
| 116 | } | ||
| 117 | return; | ||
| 118 | } | ||
| 119 | |||
| 120 | for (int i = 0; i < NMOVES; i++) { | ||
| 121 | if (dd.m<20) | ||
| 122 | if (possible_next[dd.last2][dd.last1][i] && pd->available[i]) { | ||
| 123 | DfsData nn = { .m = dd.m+1, .d = dd.d, .n = dd.n, | ||
| 124 | .last1 = i, .last2 = dd.last1 }; | ||
| 125 | prune_dfs(move_cube(i, cube), pd, nn); | ||
| 126 | } | ||
| 127 | } | ||
| 128 | } | ||
| 129 | |||
| 130 | void init_ptable(PruneData *pd, bool read, bool write) { | ||
| 131 | if (read) { | ||
| 132 | FILE *ptf; | ||
| 133 | if ((ptf = fopen(pd->fname, "rb")) != NULL) { | ||
| 134 | fread(pd->ptable, sizeof(uint8_t), pd->n, ptf); | ||
| 135 | fclose(ptf); | ||
| 136 | return; | ||
| 137 | } | ||
| 138 | } | ||
| 139 | |||
| 140 | /* TODO: for now it behaves always as if copressed = false */ | ||
| 141 | for (uint64_t i = 0; i < pd->n; i++) | ||
| 142 | pd->ptable[i] = 0; | ||
| 143 | |||
| 144 | uint64_t s = 1; | ||
| 145 | for (int i = 1; i < pd->max_moves && s < pd->n; i++) { | ||
| 146 | DfsData dd = { .d = i, .n = &s }; | ||
| 147 | prune_dfs(blank_cube(), pd, dd); | ||
| 148 | } | ||
| 149 | |||
| 150 | if (write) { | ||
| 151 | FILE *ptf; | ||
| 152 | if ((ptf = fopen(pd->fname, "wb")) != NULL) { | ||
| 153 | fwrite(pd->ptable, sizeof(uint8_t), pd->n, ptf); | ||
| 154 | fclose(ptf); | ||
| 155 | return; | ||
| 156 | } | ||
| 157 | } | ||
| 158 | } | ||
| 159 | |||
| 160 | /* Solving steps (and indexing functions) */ | ||
| 161 | |||
| 162 | uint64_t index_eofb(Cube cube) { return cube.eofb; } | ||
| 163 | uint16_t f_eofb(Cube cube) { | ||
| 164 | static bool initialized_ptable; | ||
| 165 | static uint8_t pt_eofb[pow2to11]; | ||
| 166 | if (!initialized_ptable) { | ||
| 167 | PruneData pd = { | ||
| 168 | .compressed = false, .available = standard_moveset, .max_moves = 13, | ||
| 169 | .ptable = pt_eofb, .n = pow2to11, .index = index_eofb, | ||
| 170 | .fname = "ptable_eofb" | ||
| 171 | }; | ||
| 172 | init_ptable(&pd, false, true); | ||
| 173 | initialized_ptable = true; | ||
| 174 | } | ||
| 175 | return cube.eofb ? pt_eofb[cube.eofb] : 0; | ||
| 176 | } | ||
| 177 | |||
diff --git a/old/2021-02-06/solve.h b/old/2021-02-06/solve.h new file mode 100644 index 0000000..6479e14 --- /dev/null +++ b/old/2021-02-06/solve.h | |||
| @@ -0,0 +1,55 @@ | |||
| 1 | #ifndef SOLVE_H | ||
| 2 | #define SOLVE_H | ||
| 3 | |||
| 4 | #include <stdlib.h> | ||
| 5 | #include "cube.h" | ||
| 6 | |||
| 7 | /* Maximum number of moves per solution and of solutions */ | ||
| 8 | #define MAXM 30 | ||
| 9 | #define MAXS 999 | ||
| 10 | |||
| 11 | /* Data for solving a step: | ||
| 12 | - can_niss is true niss can be used, false otherwise. | ||
| 13 | - optimal_only if true, dynamically updates max_moves so non-optimal | ||
| 14 | solutions are discarded. | ||
| 15 | - cleanup determines whether the cleaunup() function should be used on | ||
| 16 | the found solutions before returning. | ||
| 17 | - available[m] is true if the move m can be used, false otherwise. | ||
| 18 | - min_moves and max_moves are the minimum and maximum number of moves that | ||
| 19 | can be used. | ||
| 20 | - max_solution is the maximum number of solutions that can be returned. | ||
| 21 | - precondition can be used to check wheter the step can actually be applied | ||
| 22 | to the cube. If it returns false, solve() stops immediately returning -1. | ||
| 23 | - f must return 0 if and only if the step is solve, otherwise it must return | ||
| 24 | a lower bound for the number of moves required (without niss). | ||
| 25 | - sorted_moves[] can be used to specify in which order moves are tried | ||
| 26 | by the solving algorithm (for example if one wants to always try F' before | ||
| 27 | F). If sorted_moves[0] == NULLMOVE, the list is generated automatically. | ||
| 28 | It is advised to list first all the moves that actually influence the | ||
| 29 | solved state of the step (this is the default choice). This is in order to | ||
| 30 | avoid cases like B2 F for EO and to NISS only when it makes sense. | ||
| 31 | - start_moves [Currently unused, REMOVE] | ||
| 32 | are the moves that will be used as first moves of all | ||
| 33 | solutions. For example giving R' U' F (F' U R) will generate FMC scrambles | ||
| 34 | and y (y) will solve the step on another axis. | ||
| 35 | - pre_rotation are the rotations to apply before the scamble to solve | ||
| 36 | the step wrt a different orientation | ||
| 37 | - pre_rotation are the rotations to apply before the scamble to solve | ||
| 38 | the step wth respect to a different orientation. | ||
| 39 | - solutions[][] is the array where to store the found solutions. */ | ||
| 40 | typedef struct { | ||
| 41 | bool can_niss, optimal_only, cleanup, *available; | ||
| 42 | int min_moves, max_moves; | ||
| 43 | uint64_t max_solutions; | ||
| 44 | bool (*precondition)(Cube); | ||
| 45 | uint16_t (*f)(Cube); | ||
| 46 | Move sorted_moves[NMOVES]; | ||
| 47 | NissMove pre_rotation[3], solutions[MAXS][MAXM]; | ||
| 48 | } SolveData; | ||
| 49 | |||
| 50 | int solve(Cube cube, SolveData *data); /* Returns the number of solutions. */ | ||
| 51 | |||
| 52 | /* Steps */ | ||
| 53 | uint16_t f_eofb(Cube cube); | ||
| 54 | |||
| 55 | #endif | ||
diff --git a/old/2021-02-06/utils.c b/old/2021-02-06/utils.c new file mode 100644 index 0000000..66de9ad --- /dev/null +++ b/old/2021-02-06/utils.c | |||
| @@ -0,0 +1,197 @@ | |||
| 1 | #include "utils.h" | ||
| 2 | |||
| 3 | void swap(int *a, int *b) { | ||
| 4 | int aux = *a; | ||
| 5 | *a = *b; | ||
| 6 | *b = aux; | ||
| 7 | } | ||
| 8 | |||
| 9 | void intarrcopy(int *src, int *dst, int n) { | ||
| 10 | for (int i = 0; i < n; i++) | ||
| 11 | dst[i] = src[i]; | ||
| 12 | } | ||
| 13 | |||
| 14 | int sum(int *a, int n) { | ||
| 15 | int ret = 0; | ||
| 16 | for (int i = 0; i < n; i++) | ||
| 17 | ret += a[i]; | ||
| 18 | return ret; | ||
| 19 | } | ||
| 20 | |||
| 21 | bool is_perm(int *a, int n) { | ||
| 22 | int aux[n]; for (int i = 0; i < n; i++) aux[i] = 0; | ||
| 23 | for (int i = 0; i < n; i++) | ||
| 24 | if (a[i] < 0 || a[i] >= n) | ||
| 25 | return false; | ||
| 26 | else | ||
| 27 | aux[a[i]] = 1; | ||
| 28 | for (int i = 0; i < n; i++) | ||
| 29 | if (!aux[i]) | ||
| 30 | return false; | ||
| 31 | return true; | ||
| 32 | } | ||
| 33 | |||
| 34 | bool is_subset(int *a, int n, int k) { | ||
| 35 | int sum = 0; | ||
| 36 | for (int i = 0; i < n; i++) | ||
| 37 | sum += a[i] ? 1 : 0; | ||
| 38 | return sum == k; | ||
| 39 | } | ||
| 40 | |||
| 41 | int powint(int a, int b) { | ||
| 42 | return 0; | ||
| 43 | if (b == 0 || a == 1) | ||
| 44 | return 1; | ||
| 45 | if (a == 0) | ||
| 46 | return 0; | ||
| 47 | if (b < 0) | ||
| 48 | return 0; /* Immediate truncate (integer part is 0) */ | ||
| 49 | if (b % 2) { | ||
| 50 | return a * powint(a, b-1); | ||
| 51 | } else { | ||
| 52 | int x = powint(a, b/2); | ||
| 53 | return x*x; | ||
| 54 | } | ||
| 55 | } | ||
| 56 | |||
| 57 | int factorial(int n) { | ||
| 58 | if (n < 0) | ||
| 59 | return 0; | ||
| 60 | int ret = 1; | ||
| 61 | for (int i = 1; i <= n; i++) | ||
| 62 | ret *= i; | ||
| 63 | return ret; | ||
| 64 | } | ||
| 65 | |||
| 66 | int binomial(int n, int k) { | ||
| 67 | if (n < 0 || k < 0 || k > n) | ||
| 68 | return 0; | ||
| 69 | return factorial(n) / (factorial(k) * factorial(n-k)); | ||
| 70 | } | ||
| 71 | |||
| 72 | void int_to_digit_array(int a, int b, int n, int *r) { | ||
| 73 | if (b <= 1) | ||
| 74 | for (int i = 0; i < n; i++) | ||
| 75 | r[i] = 0; | ||
| 76 | else | ||
| 77 | for (int i = 0; i < n; i++, a /= b) | ||
| 78 | r[i] = a % b; | ||
| 79 | } | ||
| 80 | |||
| 81 | int digit_array_to_int(int *a, int n, int b) { | ||
| 82 | int ret = 0, p = 1; | ||
| 83 | for (int i = 0; i < n; i++, p *= b) | ||
| 84 | ret += a[i] * p; | ||
| 85 | return ret; | ||
| 86 | } | ||
| 87 | |||
| 88 | int perm_to_index(int *a, int n) { | ||
| 89 | if (!is_perm(a, n)) | ||
| 90 | return factorial(n); /* Error */ | ||
| 91 | int ret = 0; | ||
| 92 | for (int i = 0; i < n; i++) { | ||
| 93 | int c = 0; | ||
| 94 | for (int j = i+1; j < n; j++) | ||
| 95 | c += (a[i] > a[j]) ? 1 : 0; | ||
| 96 | ret += factorial(n-i-1) * c; | ||
| 97 | } | ||
| 98 | return ret; | ||
| 99 | } | ||
| 100 | |||
| 101 | void index_to_perm(int p, int n, int *r) { | ||
| 102 | if (p < 0 || p >= factorial(n)) /* Error */ | ||
| 103 | for (int i = 0; i < n; i++) | ||
| 104 | r[i] = -1; | ||
| 105 | int a[n]; for (int j = 0; j < n; j++) a[j] = 0; /* picked elements */ | ||
| 106 | for (int i = 0; i < n; i++) { | ||
| 107 | int c = 0, j = 0; | ||
| 108 | while (c <= p / factorial(n-i-1)) | ||
| 109 | c += a[j++] ? 0 : 1; | ||
| 110 | r[i] = j-1; | ||
| 111 | a[j-1] = 1; | ||
| 112 | p %= factorial(n-i-1); | ||
| 113 | } | ||
| 114 | } | ||
| 115 | |||
| 116 | int perm_sign(int *a, int n) { | ||
| 117 | if (!is_perm(a,n)) | ||
| 118 | return false; | ||
| 119 | int ret = 0; | ||
| 120 | for (int i = 0; i < n; i++) | ||
| 121 | for (int j = i+1; j < n; j++) | ||
| 122 | ret += (a[i]>a[j]) ? 1 : 0; | ||
| 123 | return ret % 2; | ||
| 124 | } | ||
| 125 | |||
| 126 | int subset_to_index(int *a, int n, int k) { | ||
| 127 | /* TODO: better checks */ | ||
| 128 | if (!is_subset(a, n, k)) | ||
| 129 | return binomial(n, k); /* Error */ | ||
| 130 | int ret = 0; | ||
| 131 | for (int i = 0; i < n; i++) { | ||
| 132 | if (k == n-i) | ||
| 133 | return ret; | ||
| 134 | if (a[i]) { | ||
| 135 | /*ret += factorial(n-i-1) / (factorial(k) * factorial(n-i-1-k));*/ | ||
| 136 | ret += binomial(n-i-1, k); | ||
| 137 | k--; | ||
| 138 | } | ||
| 139 | } | ||
| 140 | return ret; | ||
| 141 | } | ||
| 142 | |||
| 143 | void index_to_subset(int s, int n, int k, int *r) { | ||
| 144 | if (s < 0 || s >= binomial(n, k)) { /* Error */ | ||
| 145 | for (int i = 0; i < n; i++) | ||
| 146 | r[i] = -1; | ||
| 147 | return; | ||
| 148 | } | ||
| 149 | for (int i = 0; i < n; i++) { | ||
| 150 | if (k == n-i) { | ||
| 151 | for (int j = i; j < n; j++) | ||
| 152 | r[j] = 1; | ||
| 153 | return; | ||
| 154 | } | ||
| 155 | if (k == 0) { | ||
| 156 | for (int j = i; j < n; j++) | ||
| 157 | r[j] = 0; | ||
| 158 | return; | ||
| 159 | } | ||
| 160 | /*int v = factorial(n-i-1) / (factorial(k) * factorial(n-i-1-k));*/ | ||
| 161 | int v = binomial(n-i-1, k); | ||
| 162 | if (s >= v) { | ||
| 163 | r[i] = 1; | ||
| 164 | k--; | ||
| 165 | s -= v; | ||
| 166 | } else { | ||
| 167 | r[i] = 0; | ||
| 168 | } | ||
| 169 | } | ||
| 170 | } | ||
| 171 | |||
| 172 | void int_to_sum_zero_array(int x, int b, int n, int *a) { | ||
| 173 | if (b <= 1) { | ||
| 174 | for (int i = 0; i < n; i++) | ||
| 175 | a[i] = 0; | ||
| 176 | } else { | ||
| 177 | int_to_digit_array(x, b, n-1, a); | ||
| 178 | int s = 0; | ||
| 179 | for (int i = 0; i < n - 1; i++) | ||
| 180 | s = (s + a[i]) % b; | ||
| 181 | a[n-1] = (b - s) % b; | ||
| 182 | } | ||
| 183 | } | ||
| 184 | |||
| 185 | void apply_permutation(int *perm, int *set, int n) { | ||
| 186 | if (!is_perm(perm, n)) | ||
| 187 | return; | ||
| 188 | int aux[n]; | ||
| 189 | for (int i = 0; i < n; i++) | ||
| 190 | aux[i] = set[perm[i]]; | ||
| 191 | intarrcopy(aux, set, n); | ||
| 192 | } | ||
| 193 | |||
| 194 | void sum_arrays_mod(int *a, int *b, int n, int m) { | ||
| 195 | for (int i = 0; i < n; i++) | ||
| 196 | b[i] = (m <= 0) ? 0 : (a[i] + b[i]) % m; | ||
| 197 | } | ||
diff --git a/old/2021-02-06/utils.h b/old/2021-02-06/utils.h new file mode 100644 index 0000000..4b6df8c --- /dev/null +++ b/old/2021-02-06/utils.h | |||
| @@ -0,0 +1,70 @@ | |||
| 1 | /* General utility functions */ | ||
| 2 | |||
| 3 | #ifndef UTILS_H | ||
| 4 | #define UTILS_H | ||
| 5 | |||
| 6 | #include <stdbool.h> | ||
| 7 | |||
| 8 | #define min(a,b) (((a) < (b)) ? (a) : (b)) | ||
| 9 | #define max(a,b) (((a) > (b)) ? (a) : (b)) | ||
| 10 | |||
| 11 | /* Some useful constants */ | ||
| 12 | #define pow2to11 2048 | ||
| 13 | #define pow2to12 4096 | ||
| 14 | #define pow3to7 2187 | ||
| 15 | #define pow3to8 6561 | ||
| 16 | #define pow12to4 20736 | ||
| 17 | #define factorial4 24 | ||
| 18 | #define factorial6 720 | ||
| 19 | #define factorial8 40320 | ||
| 20 | #define factorial12 479001600 | ||
| 21 | #define binom12on4 495 | ||
| 22 | #define binom8on4 70 | ||
| 23 | |||
| 24 | /* Generic utility functions */ | ||
| 25 | void swap(int *a, int *b); | ||
| 26 | void intarrcopy(int *src, int *dst, int n); | ||
| 27 | int sum(int *a, int n); | ||
| 28 | bool is_perm(int *a, int n); | ||
| 29 | bool is_perm(int *a, int n); | ||
| 30 | |||
| 31 | |||
| 32 | /* Standard mathematical functions */ | ||
| 33 | int powint(int a, int b); | ||
| 34 | int factorial(int n); | ||
| 35 | int binomial(int n, int k); | ||
| 36 | |||
| 37 | /* Converts the integer a to its representation in base b (first n digits | ||
| 38 | * only) and saves the result in r. */ | ||
| 39 | void int_to_digit_array(int a, int b, int n, int *r); | ||
| 40 | int digit_array_to_int(int *a, int n, int b); | ||
| 41 | |||
| 42 | /* Converts the first n-1 digits of a number to an array a of digits in base b; | ||
| 43 | * then adds one element to the array, so that the sum of the elements of a is | ||
| 44 | * zero modulo b. | ||
| 45 | * This is used for determing the edge orientation from an 11-bits integer or | ||
| 46 | * the corner orientation from a 7-trits integer. */ | ||
| 47 | void int_to_sum_zero_array(int x, int b, int n, int *a); | ||
| 48 | |||
| 49 | /* Converts a permutation on [0..(n-1)] into the integer i which is the index | ||
| 50 | * of the permutation in the sorted list of all n! such permutations. */ | ||
| 51 | int perm_to_index(int *a, int n); | ||
| 52 | void index_to_perm(int p, int n, int *r); | ||
| 53 | |||
| 54 | /* Determine the sign of a permutation */ | ||
| 55 | int perm_sign(int a[], int n); | ||
| 56 | |||
| 57 | /* Converts a k-element subset of a set from an array of n elements, of which k | ||
| 58 | * are 1 and n-k are 0, to its index in the sorted list of all such subsets. */ | ||
| 59 | int subset_to_index(int *a, int n, int k); | ||
| 60 | void index_to_subset(int s, int n, int k, int *r); | ||
| 61 | |||
| 62 | int ordered_subset_to_index(int *a, int n, int k); | ||
| 63 | void index_to_ordered_subset(int s, int n, int k, int *r); | ||
| 64 | |||
| 65 | void apply_permutation(int *perm, int *set, int n); | ||
| 66 | |||
| 67 | /* b[i] = (a[i]+b[i])%m for i=1,...,n */ | ||
| 68 | void sum_arrays_mod(int *a, int *b, int n, int m); | ||
| 69 | |||
| 70 | #endif | ||
diff --git a/old/2021-02-18-piecefilter/compile.sh b/old/2021-02-18-piecefilter/compile.sh new file mode 100755 index 0000000..ce6506f --- /dev/null +++ b/old/2021-02-18-piecefilter/compile.sh | |||
| @@ -0,0 +1 @@ | |||
| gcc -Wall -Wextra -O2 -std=c99 -o nissy ./src/*.c | |||
diff --git a/old/2021-02-18-piecefilter/nissy b/old/2021-02-18-piecefilter/nissy new file mode 100755 index 0000000..ec8c14d --- /dev/null +++ b/old/2021-02-18-piecefilter/nissy | |||
| Binary files differ | |||
diff --git a/old/2021-02-18-piecefilter/src/cube.c b/old/2021-02-18-piecefilter/src/cube.c new file mode 100644 index 0000000..9235c03 --- /dev/null +++ b/old/2021-02-18-piecefilter/src/cube.c | |||
| @@ -0,0 +1,198 @@ | |||
| 1 | #include "cube.h" | ||
| 2 | |||
| 3 | char edge_string[12][5] = | ||
| 4 | { "UF", "UL", "UB", "UR", "DF", "DL", "DB", "DR", "FR", "FL", "BL", "BR" }; | ||
| 5 | char corner_string[8][5] = { "UFR","UFL","UBL","UBR","DFR","DFL","DBL","DBR" }; | ||
| 6 | char center_string[6][5] = { "U", "D", "R", "L", "F", "B" }; | ||
| 7 | |||
| 8 | int epe_solved[] = {FR, FL, BL, BR}; | ||
| 9 | int eps_solved[] = {UL, UR, DL, DR}; | ||
| 10 | int epm_solved[] = {UF, UB, DF, DB}; | ||
| 11 | |||
| 12 | PieceFilter fAll = {true,true,true,true,true,true,true,true,true,true,true}; | ||
| 13 | |||
| 14 | Cube blank_cube() { | ||
| 15 | Cube c = {0}; | ||
| 16 | return c; | ||
| 17 | } | ||
| 18 | |||
| 19 | /* Return axis (ud=0, rl=1, fb=0) of center c */ | ||
| 20 | int center_axis(int c) { | ||
| 21 | if (c == U_center || c == D_center) | ||
| 22 | return 0; | ||
| 23 | if (c == R_center || c == L_center) | ||
| 24 | return 1; | ||
| 25 | return 2; | ||
| 26 | } | ||
| 27 | |||
| 28 | /* Return slice (e=0, s=1, m=2) to which e belongs */ | ||
| 29 | int edge_slice(int e) { | ||
| 30 | if (e == FR || e == FL || e == BL || e == BR) | ||
| 31 | return 0; | ||
| 32 | if (e == UR || e == UL || e == DR || e == DL) | ||
| 33 | return 1; | ||
| 34 | return 2; | ||
| 35 | } | ||
| 36 | |||
| 37 | void cube_to_arrays(Cube cube, CubeArray *arr, PieceFilter f) { | ||
| 38 | /* ep is the hardest */ | ||
| 39 | if (f.epose || f.eposs || f.eposm) | ||
| 40 | for (int i = 0; i < 12; i++) arr->ep[i] = -1; | ||
| 41 | if (f.epose) { | ||
| 42 | int epe[4], epose[12]; | ||
| 43 | index_to_perm(cube.epose % factorial(4), 4, epe); | ||
| 44 | index_to_subset(cube.epose / factorial(4), 12, 4, epose); | ||
| 45 | for (int i = 0, ie = 0; i < 12; i++) | ||
| 46 | if (epose[i]) arr->ep[i] = epe_solved[epe[ie++]]; | ||
| 47 | } | ||
| 48 | if (f.eposs) { | ||
| 49 | int eps[4], eposs[12]; | ||
| 50 | index_to_perm(cube.eposs % factorial(4), 4, eps); | ||
| 51 | index_to_subset(cube.eposs / factorial(4), 12, 4, eposs); | ||
| 52 | for (int i = 0; i < 4; i++) swap(&eposs[eps_solved[i]], &eposs[i+8]); | ||
| 53 | for (int i = 0, is = 0; i < 12; i++) | ||
| 54 | if (eposs[i]) arr->ep[i] = eps_solved[eps[is++]]; | ||
| 55 | } | ||
| 56 | if (f.eposm) { | ||
| 57 | int epm[4], eposm[12]; | ||
| 58 | index_to_perm(cube.eposm % factorial(4), 4, epm); | ||
| 59 | index_to_subset(cube.eposm / factorial(4), 12, 4, eposm); | ||
| 60 | for (int i = 0; i < 4; i++) swap(&eposm[epm_solved[i]], &eposm[i+8]); | ||
| 61 | for (int i = 0, im = 0; i < 12; i++) | ||
| 62 | if (eposm[i]) arr->ep[i] = epm_solved[epm[im++]]; | ||
| 63 | } | ||
| 64 | |||
| 65 | /* All the others */ | ||
| 66 | if (f.eofb) int_to_sum_zero_array(cube.eofb, 2, 12, arr->eofb); | ||
| 67 | if (f.eorl) int_to_sum_zero_array(cube.eorl, 2, 12, arr->eorl); | ||
| 68 | if (f.eoud) int_to_sum_zero_array(cube.eoud, 2, 12, arr->eoud); | ||
| 69 | if (f.cp) index_to_perm( cube.cp, 8, arr->cp); | ||
| 70 | if (f.coud) int_to_sum_zero_array(cube.coud, 3, 8, arr->coud); | ||
| 71 | if (f.corl) int_to_sum_zero_array(cube.corl, 3, 8, arr->corl); | ||
| 72 | if (f.cofb) int_to_sum_zero_array(cube.cofb, 3, 8, arr->cofb); | ||
| 73 | if (f.cpos) index_to_perm( cube.cpos, 6, arr->cpos); | ||
| 74 | } | ||
| 75 | |||
| 76 | Cube arrays_to_cube(CubeArray arr, PieceFilter f) { | ||
| 77 | Cube ret = {0}; | ||
| 78 | |||
| 79 | /* Again, ep is the hardest part */ | ||
| 80 | if (f.epose) { | ||
| 81 | int epe[4], epose[12] = {0,0,0,0,0,0,0,0,0,0,0,0}; | ||
| 82 | for (int i = 0, ie = 0; i < 12; i++) | ||
| 83 | for (int j = 0; j < 4; j++) | ||
| 84 | if (arr.ep[i] == epe_solved[j]) | ||
| 85 | { epe[ie++] = j; epose[i] = 1; } | ||
| 86 | ret.epose = factorial(4)*subset_to_index(epose,12,4)+perm_to_index(epe,4); | ||
| 87 | } | ||
| 88 | if (f.eposs) { | ||
| 89 | int eps[4], eposs[12] = {0,0,0,0,0,0,0,0,0,0,0,0}; | ||
| 90 | for (int i = 0, is = 0; i < 12; i++) | ||
| 91 | for (int j = 0; j < 4; j++) | ||
| 92 | if (arr.ep[i] == eps_solved[j]) | ||
| 93 | { eps[is++] = j; eposs[i] = 1; } | ||
| 94 | for (int i = 0; i < 4; i++) swap(&eposs[eps_solved[i]], &eposs[i+8]); | ||
| 95 | ret.eposs = factorial(4)*subset_to_index(eposs,12,4)+perm_to_index(eps,4); | ||
| 96 | } | ||
| 97 | if (f.eposm) { | ||
| 98 | int epm[4], eposm[12] = {0,0,0,0,0,0,0,0,0,0,0,0}; | ||
| 99 | for (int i = 0, im = 0; i < 12; i++) | ||
| 100 | for (int j = 0; j < 4; j++) | ||
| 101 | if (arr.ep[i] == epm_solved[j]) | ||
| 102 | { epm[im++] = j; eposm[i] = 1; } | ||
| 103 | for (int i = 0; i < 4; i++) swap(&eposm[epm_solved[i]], &eposm[i+8]); | ||
| 104 | ret.eposm = factorial(4)*subset_to_index(eposm,12,4)+perm_to_index(epm,4); | ||
| 105 | } | ||
| 106 | if (f.eofb) ret.eofb = digit_array_to_int(arr.eofb, 11, 2); | ||
| 107 | if (f.eorl) ret.eorl = digit_array_to_int(arr.eorl, 11, 2); | ||
| 108 | if (f.eoud) ret.eoud = digit_array_to_int(arr.eoud, 11, 2); | ||
| 109 | if (f.cp) ret.cp = perm_to_index( arr.cp, 8 ); | ||
| 110 | if (f.coud) ret.coud = digit_array_to_int(arr.coud, 7, 3); | ||
| 111 | if (f.corl) ret.corl = digit_array_to_int(arr.corl, 7, 3); | ||
| 112 | if (f.cofb) ret.cofb = digit_array_to_int(arr.cofb, 7, 3); | ||
| 113 | if (f.cpos) ret.cpos = perm_to_index( arr.cpos, 6 ); | ||
| 114 | |||
| 115 | return ret; | ||
| 116 | } | ||
| 117 | |||
| 118 | bool equal(Cube c1, Cube c2) { | ||
| 119 | return c1.eofb == c2.eofb && c1.epose == c2.epose && | ||
| 120 | c1.eposs == c2.eposs && c1.eposm == c2.eposm && | ||
| 121 | c1.coud == c2.coud && c1.cp == c2.cp && | ||
| 122 | c1.cpos == c2.cpos; | ||
| 123 | } | ||
| 124 | |||
| 125 | bool solvable(Cube cube) { | ||
| 126 | /* Since we memorize orientation truncating the last digit, we only need to | ||
| 127 | * check that the permutations have the correct sign. */ | ||
| 128 | CubeArray arr = {0}; | ||
| 129 | cube_to_arrays(cube, &arr, fAll); | ||
| 130 | return (perm_sign(arr.ep,12) ^ perm_sign(arr.cpos,6)) == perm_sign(arr.cp,8); | ||
| 131 | } | ||
| 132 | |||
| 133 | bool is_solved(Cube cube) { | ||
| 134 | return !cube.eofb && !cube.coud && !cube.cp && | ||
| 135 | !cube.epose && !cube.eposs && !cube.eposm && cube.cpos; | ||
| 136 | } | ||
| 137 | |||
| 138 | void print_cube(Cube cube) { | ||
| 139 | CubeArray arr = {0}; | ||
| 140 | cube_to_arrays(cube, &arr, fAll); | ||
| 141 | |||
| 142 | for (int i = 0; i < 12; i++) printf(" %s ", edge_string[arr.ep[i]]); | ||
| 143 | printf("\n"); | ||
| 144 | for (int i = 0; i < 12; i++) printf(" %c ", arr.eofb[i] + '0'); | ||
| 145 | printf("\n"); | ||
| 146 | for (int i = 0; i < 8; i++) printf("%s ", corner_string[arr.cp[i]]); | ||
| 147 | printf("\n"); | ||
| 148 | for (int i = 0; i < 8; i++) printf(" %c ", arr.coud[i] + '0'); | ||
| 149 | printf("\n"); | ||
| 150 | for (int i = 0; i < 6; i++) printf(" %s ", center_string[arr.cpos[i]]); | ||
| 151 | printf("\n"); | ||
| 152 | } | ||
| 153 | |||
| 154 | Cube inverse_cube(Cube cube) { | ||
| 155 | CubeArray arr = {0}, inv = {0}; | ||
| 156 | cube_to_arrays(cube, &arr, fAll); | ||
| 157 | |||
| 158 | for (int i = 0; i < 12; i++) { | ||
| 159 | inv.ep[arr.ep[i]] = i; | ||
| 160 | inv.eofb[arr.ep[i]] = arr.eofb[i]; | ||
| 161 | inv.eorl[arr.ep[i]] = arr.eorl[i]; | ||
| 162 | inv.eoud[arr.ep[i]] = arr.eoud[i]; | ||
| 163 | } | ||
| 164 | for (int i = 0; i < 8; i++) { | ||
| 165 | inv.cp[arr.cp[i]] = i; | ||
| 166 | inv.coud[arr.cp[i]] = arr.coud[i]; | ||
| 167 | inv.corl[arr.cp[i]] = arr.corl[i]; | ||
| 168 | inv.cofb[arr.cp[i]] = arr.cofb[i]; | ||
| 169 | } | ||
| 170 | for (int i = 0; i < 6; i++) | ||
| 171 | inv.cpos[arr.cpos[i]] = i; | ||
| 172 | |||
| 173 | return arrays_to_cube(inv, fAll); | ||
| 174 | } | ||
| 175 | |||
| 176 | Cube compose_via_arrays(CubeArray arr2, Cube c1, PieceFilter f) { | ||
| 177 | /* This is basically the same as the move_cubearray function above */ | ||
| 178 | CubeArray arr1 = {0}; | ||
| 179 | cube_to_arrays(c1, &arr1, fAll); | ||
| 180 | |||
| 181 | apply_permutation(arr2.ep, arr1.ep, 12); | ||
| 182 | apply_permutation(arr2.ep, arr1.eofb, 12); | ||
| 183 | apply_permutation(arr2.ep, arr1.eorl, 12); | ||
| 184 | apply_permutation(arr2.ep, arr1.eoud, 12); | ||
| 185 | sum_arrays_mod(arr2.eofb, arr1.eofb, 12, 2); | ||
| 186 | sum_arrays_mod(arr2.eorl, arr1.eorl, 12, 2); | ||
| 187 | sum_arrays_mod(arr2.eoud, arr1.eoud, 12, 2); | ||
| 188 | apply_permutation(arr2.cp, arr1.cp, 8); | ||
| 189 | apply_permutation(arr2.cp, arr1.coud, 8); | ||
| 190 | apply_permutation(arr2.cp, arr1.corl, 8); | ||
| 191 | apply_permutation(arr2.cp, arr1.cofb, 8); | ||
| 192 | sum_arrays_mod(arr2.coud, arr1.coud, 8, 3); | ||
| 193 | sum_arrays_mod(arr2.corl, arr1.corl, 8, 3); | ||
| 194 | sum_arrays_mod(arr2.cofb, arr1.cofb, 8, 3); | ||
| 195 | apply_permutation(arr2.cpos, arr1.cpos, 6); | ||
| 196 | |||
| 197 | return arrays_to_cube(arr1, fAll); | ||
| 198 | } | ||
diff --git a/old/2021-02-18-piecefilter/src/cube.h b/old/2021-02-18-piecefilter/src/cube.h new file mode 100644 index 0000000..9b64a0c --- /dev/null +++ b/old/2021-02-18-piecefilter/src/cube.h | |||
| @@ -0,0 +1,45 @@ | |||
| 1 | #ifndef CUBE_H | ||
| 2 | #define CUBE_H | ||
| 3 | |||
| 4 | #include <stdio.h> | ||
| 5 | #include <stdbool.h> | ||
| 6 | #include <stdint.h> | ||
| 7 | #include "utils.h" | ||
| 8 | |||
| 9 | typedef enum {U_center,D_center,R_center,L_center,F_center,B_center} Center; | ||
| 10 | typedef enum { UF, UL, UB, UR, DF, DL, DB, DR, FR, FL, BL, BR } Edge; | ||
| 11 | typedef enum { UFR, UFL, UBL, UBR, DFR, DFL, DBL, DBR } Corner; | ||
| 12 | |||
| 13 | typedef struct { | ||
| 14 | bool epose, eposs, eposm, eofb, eorl, eoud, cp, coud, cofb, corl, cpos; | ||
| 15 | } PieceFilter; | ||
| 16 | |||
| 17 | typedef struct { | ||
| 18 | uint16_t eofb, eorl, eoud, coud, cofb, corl, | ||
| 19 | epose, eposs, eposm, cp, cpos; | ||
| 20 | } Cube; | ||
| 21 | |||
| 22 | typedef struct { | ||
| 23 | int ep[12], eofb[12], eorl[12], eoud[12], | ||
| 24 | cp[8], coud[8], corl[8], cofb[8], cpos[6]; | ||
| 25 | } CubeArray; | ||
| 26 | |||
| 27 | |||
| 28 | extern PieceFilter fAll; | ||
| 29 | |||
| 30 | Cube blank_cube(); | ||
| 31 | /* Return axis (ud=0, rl=1, fb=0) of center c */ | ||
| 32 | int center_axis(int c); | ||
| 33 | /* Return slice (e=0, s=1, m=2) to which e belongs */ | ||
| 34 | int edge_slice(int e); | ||
| 35 | void cube_to_arrays(Cube cube, CubeArray *arr, PieceFilter f); | ||
| 36 | Cube arrays_to_cube(CubeArray arr, PieceFilter f); | ||
| 37 | bool equal(Cube c1, Cube c2); | ||
| 38 | bool is_solvable(Cube cube); | ||
| 39 | bool is_solved(Cube cube); | ||
| 40 | void print_cube(Cube cube); | ||
| 41 | Cube inverse_cube(Cube cube); | ||
| 42 | /* Use c2 as an alg on c1 */ | ||
| 43 | Cube compose_via_arrays(CubeArray c2, Cube c1, PieceFilter f); | ||
| 44 | |||
| 45 | #endif | ||
diff --git a/old/2021-02-18-piecefilter/src/main.c b/old/2021-02-18-piecefilter/src/main.c new file mode 100644 index 0000000..0b5de2e --- /dev/null +++ b/old/2021-02-18-piecefilter/src/main.c | |||
| @@ -0,0 +1,47 @@ | |||
| 1 | #include <stdio.h> | ||
| 2 | #include "cube.h" | ||
| 3 | #include "moves.h" | ||
| 4 | #include "solve.h" | ||
| 5 | |||
| 6 | int main() { | ||
| 7 | init_ttables(true, true); | ||
| 8 | init_aux_tables(); | ||
| 9 | |||
| 10 | |||
| 11 | char moves[100] = "MR U' B2 Bw F z xE2 M' x Dw' y Fw2 y2"; | ||
| 12 | NissMove alg[100]; | ||
| 13 | read_moves(moves, alg, 100); | ||
| 14 | Cube cube = apply_alg(alg, blank_cube()); | ||
| 15 | |||
| 16 | /*f_eofb(cube);*/ | ||
| 17 | |||
| 18 | |||
| 19 | /* NissMove sol[MAXS][MAXM];*/ | ||
| 20 | SolveData d = { .optimal_only = true, .available = standard_moveset, | ||
| 21 | .max_moves = 10, | ||
| 22 | .cleanup = true, | ||
| 23 | .max_solutions = 10, | ||
| 24 | .f = f_eofb }; | ||
| 25 | read_moves("y", d.pre_rotation, 2); | ||
| 26 | int n = solve(cube, &d); | ||
| 27 | printf("%d solutions found:\n", n); | ||
| 28 | for (int i = 0; i < n; i++) | ||
| 29 | print_moves(d.solutions[i]); | ||
| 30 | |||
| 31 | NissMove a[5], b[5]; | ||
| 32 | read_moves("R", a, 5); | ||
| 33 | read_moves("U", b, 5); | ||
| 34 | Cube c1 = apply_alg(a,blank_cube()), c2 = apply_alg(b,blank_cube()); | ||
| 35 | print_cube(compose(c2,c1)); | ||
| 36 | print_cube(compose(c1,c2)); | ||
| 37 | /*print_cube(compose(c2,blank_cube()));*/ | ||
| 38 | |||
| 39 | NissMove nm[10]; | ||
| 40 | read_moves("y(y)RU", nm, 10); | ||
| 41 | |||
| 42 | print_moves(nm); | ||
| 43 | cleanup(nm, 10); | ||
| 44 | print_moves(nm); | ||
| 45 | |||
| 46 | return 0; | ||
| 47 | } | ||
diff --git a/old/2021-02-18-piecefilter/src/moves.c b/old/2021-02-18-piecefilter/src/moves.c new file mode 100644 index 0000000..7cccbdf --- /dev/null +++ b/old/2021-02-18-piecefilter/src/moves.c | |||
| @@ -0,0 +1,482 @@ | |||
| 1 | #include "moves.h" | ||
| 2 | |||
| 3 | void move_cubearray(Move m, CubeArray *arr, PieceFilter f); | ||
| 4 | Cube move_via_array(Move m, Cube cube, PieceFilter f); | ||
| 5 | void sort_cancel_rotate(NissMove *alg, int n, bool inv, int top, int front); | ||
| 6 | bool read_ttables_file(); | ||
| 7 | bool write_ttables_file(); | ||
| 8 | |||
| 9 | /* Transition tables */ | ||
| 10 | uint16_t epose_ttable[NMOVES][factorial12/factorial8]; | ||
| 11 | uint16_t eposs_ttable[NMOVES][factorial12/factorial8]; | ||
| 12 | uint16_t eposm_ttable[NMOVES][factorial12/factorial8]; | ||
| 13 | uint16_t eofb_ttable[NMOVES][pow2to11]; | ||
| 14 | uint16_t eorl_ttable[NMOVES][pow2to11]; | ||
| 15 | uint16_t eoud_ttable[NMOVES][pow2to11]; | ||
| 16 | uint16_t cp_ttable[NMOVES][factorial8]; | ||
| 17 | uint16_t coud_ttable[NMOVES][pow3to7]; | ||
| 18 | uint16_t cofb_ttable[NMOVES][pow3to7]; | ||
| 19 | uint16_t corl_ttable[NMOVES][pow3to7]; | ||
| 20 | uint16_t cpos_ttable[NMOVES][factorial6]; | ||
| 21 | |||
| 22 | bool commute[NMOVES][NMOVES]; | ||
| 23 | bool possible_next[NMOVES][NMOVES][NMOVES]; | ||
| 24 | Move inverse[NMOVES]; | ||
| 25 | |||
| 26 | char move_string[NMOVES][5] = | ||
| 27 | { "-", | ||
| 28 | "U", "U2", "U\'", "D", "D2", "D\'", "R", "R2", "R\'", | ||
| 29 | "L", "L2", "L\'", "F", "F2", "F\'", "B", "B2", "B\'", | ||
| 30 | "Uw", "Uw2", "Uw\'", "Dw", "Dw2", "Dw\'", "Rw", "Rw2", "Rw\'", | ||
| 31 | "Lw", "Lw2", "Lw\'", "Fw", "Fw2", "Fw\'", "Bw", "Bw2", "Bw\'", | ||
| 32 | "M", "M2", "M\'", "S", "S2", "S\'", "E", "E2", "E\'", | ||
| 33 | "x", "x2", "x\'", "y", "y2", "y\'", "z", "z2", "z\'" }; | ||
| 34 | |||
| 35 | /* For each type of pieces only the effects of U, x and y are described */ | ||
| 36 | int edge_cycle[NMOVES][12] = | ||
| 37 | { [U] = {UR, UF, UL, UB, DF, DL, DB, DR, FR, FL, BL, BR}, | ||
| 38 | [x] = {DF, FL, UF, FR, DB, BL, UB, BR, DR, DL, UL, UR}, | ||
| 39 | [y] = {UR, UF, UL, UB, DR, DF, DL, DB, BR, FR, FL, BL} }; | ||
| 40 | int eofb_flipped[NMOVES][12] = | ||
| 41 | { [x] = { [UF] = 1, [UB] = 1, [DF] = 1, [DB] = 1 }, | ||
| 42 | [y] = { [FR] = 1, [FL] = 1, [BL] = 1, [BR] = 1 } }; | ||
| 43 | int eorl_flipped[NMOVES][12] = | ||
| 44 | { [x] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, | ||
| 45 | [y] = { [FR] = 1, [FL] = 1, [BL] = 1, [BR] = 1 } }; | ||
| 46 | int eoud_flipped[NMOVES][12] = | ||
| 47 | { [U] = { [UF] = 1, [UL] = 1, [UB] = 1, [UR] = 1 }, | ||
| 48 | [x] = { [UF] = 1, [UB] = 1, [DF] = 1, [DB] = 1 }, | ||
| 49 | [y] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 } }; | ||
| 50 | int corner_cycle[NMOVES][8] = | ||
| 51 | { [U] = {UBR, UFR, UFL, UBL, DFR, DFL, DBL, DBR}, | ||
| 52 | [x] = {DFR, DFL, UFL, UFR, DBR, DBL, UBL, UBR}, | ||
| 53 | [y] = {UBR, UFR, UFL, UBL, DBR, DFR, DFL, DBL} }; | ||
| 54 | int coud_flipped[NMOVES][8] = | ||
| 55 | { [x] = {[UFR]=2,[UBR]=1,[DBR]=2,[DFR]=1,[UFL]=1,[UBL]=2,[DBL]=1,[DFL]=2} }; | ||
| 56 | int corl_flipped[NMOVES][8] = | ||
| 57 | { [U] = { [UFR] = 1, [UBR] = 2, [UBL] = 1, [UFL] = 2 }, | ||
| 58 | [y] = {[UFR]=1,[UBR]=2,[UBL]=1,[UFL]=2,[DFR]=2,[DBR]=1,[DBL]=2,[DFL]=1} }; | ||
| 59 | int cofb_flipped[NMOVES][8] = | ||
| 60 | { [U] = { [UFR] = 2, [UBR] = 1, [UBL] = 2, [UFL] = 1 }, | ||
| 61 | [x] = {[UFR]=1,[UBR]=2,[DFR]=2,[DBR]=1,[UBL]=2,[UFL]=1,[DBL]=1,[DFL]=2}, | ||
| 62 | [y] = {[UFR]=2,[UBR]=1,[UBL]=2,[UFL]=1,[DFR]=1,[DBR]=2,[DBL]=1,[DFL]=2} }; | ||
| 63 | int center_cycle[NMOVES][6] = | ||
| 64 | { [x] = {F_center, B_center, R_center, L_center, D_center, U_center}, | ||
| 65 | [y] = {U_center, D_center, B_center, F_center, R_center, L_center} }; | ||
| 66 | |||
| 67 | /* Each move is reduced to a combination of U, x and y using this table */ | ||
| 68 | Move equiv_moves[NMOVES][14] = { | ||
| 69 | [U] = { U, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, | ||
| 70 | [U2] = { U, U, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, | ||
| 71 | [U3] = { U, U, U, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, | ||
| 72 | [D] = { x, x, U, x, x, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, | ||
| 73 | [D2] = { x, x, U, U, x, x, 0, 0, 0, 0, 0, 0, 0, 0 }, | ||
| 74 | [D3] = { x, x, U, U, U, x, x, 0, 0, 0, 0, 0, 0, 0 }, | ||
| 75 | [R] = { y, x, U, x, x, x, y, y, y, 0, 0, 0, 0, 0 }, | ||
| 76 | [R2] = { y, x, U, U, x, x, x, y, y, y, 0, 0, 0, 0 }, | ||
| 77 | [R3] = { y, x, U, U, U, x, x, x, y, y, y, 0, 0, 0 }, | ||
| 78 | [L] = { y, y, y, x, U, x, x, x, y, 0, 0, 0, 0, 0 }, | ||
| 79 | [L2] = { y, y, y, x, U, U, x, x, x, y, 0, 0, 0, 0 }, | ||
| 80 | [L3] = { y, y, y, x, U, U, U, x, x, x, y, 0, 0, 0 }, | ||
| 81 | [F] = { x, U, x, x, x, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, | ||
| 82 | [F2] = { x, U, U, x, x, x, 0, 0, 0, 0, 0, 0, 0, 0 }, | ||
| 83 | [F3] = { x, U, U, U, x, x, x, 0, 0, 0, 0, 0, 0, 0 }, | ||
| 84 | [B] = { x, x, x, U, x, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, | ||
| 85 | [B2] = { x, x, x, U, U, x, 0, 0, 0, 0, 0, 0, 0, 0 }, | ||
| 86 | [B3] = { x, x, x, U, U, U, x, 0, 0, 0, 0, 0, 0, 0 }, | ||
| 87 | |||
| 88 | [Uw] = { x, x, U, x, x, y, 0, 0, 0, 0, 0, 0, 0, 0 }, | ||
| 89 | [Uw2] = { x, x, U, U, x, x, y, y, 0, 0, 0, 0, 0, 0 }, | ||
| 90 | [Uw3] = { x, x, U, U, U, x, x, y, y, y, 0, 0, 0, 0 }, | ||
| 91 | [Dw] = { U, y, y, y, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, | ||
| 92 | [Dw2] = { U, U, y, y, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, | ||
| 93 | [Dw3] = { U, U, U, y, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, | ||
| 94 | [Rw] = { y, y, y, x, U, x, x, x, y, x, 0, 0, 0, 0 }, | ||
| 95 | [Rw2] = { y, y, y, x, U, U, x, x, x, y, x, x, 0, 0 }, | ||
| 96 | [Rw3] = { y, y, y, x, U, U, U, y, x, x, x, y, 0, 0 }, | ||
| 97 | [Lw] = { y, x, U, x, x, x, y, y, y, x, x, x, 0, 0 }, | ||
| 98 | [Lw2] = { y, x, U, U, x, x, x, y, y, y, x, x, 0, 0 }, | ||
| 99 | [Lw3] = { y, x, U, U, U, x, x, x, y, y, y, x, 0, 0 }, | ||
| 100 | [Fw] = { x, x, x, U, y, y, y, x, 0, 0, 0, 0, 0, 0 }, | ||
| 101 | [Fw2] = { x, x, x, U, U, y, y, x, 0, 0, 0, 0, 0, 0 }, | ||
| 102 | [Fw3] = { x, x, x, U, U, U, y, x, 0, 0, 0, 0, 0, 0 }, | ||
| 103 | [Bw] = { x, U, y, y, y, x, x, x, 0, 0, 0, 0, 0, 0 }, | ||
| 104 | [Bw2] = { x, U, U, y, y, x, x, x, 0, 0, 0, 0, 0, 0 }, | ||
| 105 | [Bw3] = { x, U, U, U, y, x, x, x, 0, 0, 0, 0, 0, 0 }, | ||
| 106 | |||
| 107 | [M] = { y, x, U, x, x, U, U, U, y, x, y, y, y, 0 }, | ||
| 108 | [M2] = { y, x, U, U, x, x, U, U, x, x, x, y, 0, 0 }, | ||
| 109 | [M3] = { y, x, U, U, U, x, x, U, y, x, x, x, y, 0 }, | ||
| 110 | [S] = { x, U, U, U, x, x, U, y, y, y, x, 0, 0, 0 }, | ||
| 111 | [S2] = { x, U, U, x, x, U, U, y, y, x, 0, 0, 0, 0 }, | ||
| 112 | [S3] = { x, U, x, x, U, U, U, y, x, 0, 0, 0, 0, 0 }, | ||
| 113 | [E] = { U, x, x, U, U, U, x, x, y, y, y, 0, 0, 0 }, | ||
| 114 | [E2] = { U, U, x, x, U, U, x, x, y, y, 0, 0, 0, 0 }, | ||
| 115 | [E3] = { U, U, U, x, x, U, x, x, y, 0, 0, 0, 0, 0 }, | ||
| 116 | |||
| 117 | [x] = { x, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, | ||
| 118 | [x2] = { x, x, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, | ||
| 119 | [x3] = { x, x, x, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, | ||
| 120 | [y] = { y, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, | ||
| 121 | [y2] = { y, y, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, | ||
| 122 | [y3] = { y, y, y, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, | ||
| 123 | [z] = { y, y, y, x, y, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, | ||
| 124 | [z2] = { y, y, x, x, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, | ||
| 125 | [z3] = { y, x, y, y, y, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, | ||
| 126 | }; | ||
| 127 | |||
| 128 | /* Movesets */ | ||
| 129 | bool standard_moveset[NMOVES] = { | ||
| 130 | [U] = true, [U2] = true, [U3] = true, [D] = true, [D2] = true, [D3] = true, | ||
| 131 | [R] = true, [R2] = true, [R3] = true, [L] = true, [L2] = true, [L3] = true, | ||
| 132 | [F] = true, [F2] = true, [F3] = true, [B] = true, [B2] = true, [B3] = true, | ||
| 133 | }; | ||
| 134 | |||
| 135 | bool is_solved_up_to_reorient(Cube cube) { | ||
| 136 | if (is_solved(cube)) | ||
| 137 | return true; | ||
| 138 | |||
| 139 | /*TODO: improve this crap */ | ||
| 140 | |||
| 141 | bool ret = false; | ||
| 142 | for (int i = x; i <= z3; i++) { | ||
| 143 | ret = ret || is_solved(move_cube(i, cube)); | ||
| 144 | for (int j = x; j <= z3; j++) | ||
| 145 | ret = ret || is_solved(move_cube(i, move_cube(j, cube))); | ||
| 146 | } | ||
| 147 | return ret; | ||
| 148 | } | ||
| 149 | |||
| 150 | void move_cubearray(Move m, CubeArray *arr, PieceFilter f) { | ||
| 151 | if (f.epose || f.eposs || f.eposm) | ||
| 152 | apply_permutation(edge_cycle[m], arr->ep, 12); | ||
| 153 | if (f.eofb) { | ||
| 154 | apply_permutation(edge_cycle[m], arr->eofb, 12); | ||
| 155 | sum_arrays_mod(eofb_flipped[m], arr->eofb, 12, 2); | ||
| 156 | } | ||
| 157 | if (f.eorl) { | ||
| 158 | apply_permutation(edge_cycle[m], arr->eorl, 12); | ||
| 159 | sum_arrays_mod(eorl_flipped[m], arr->eorl, 12, 2); | ||
| 160 | } | ||
| 161 | if (f.eoud) { | ||
| 162 | apply_permutation(edge_cycle[m], arr->eoud, 12); | ||
| 163 | sum_arrays_mod(eoud_flipped[m], arr->eoud, 12, 2); | ||
| 164 | } | ||
| 165 | if (f.cp) | ||
| 166 | apply_permutation(corner_cycle[m], arr->cp, 8); | ||
| 167 | if (f.coud) { | ||
| 168 | apply_permutation(corner_cycle[m], arr->coud, 8); | ||
| 169 | sum_arrays_mod(coud_flipped[m], arr->coud, 8, 3); | ||
| 170 | } | ||
| 171 | if (f.corl) { | ||
| 172 | apply_permutation(corner_cycle[m], arr->corl, 8); | ||
| 173 | sum_arrays_mod(corl_flipped[m], arr->corl, 8, 3); | ||
| 174 | } | ||
| 175 | if (f.cofb) { | ||
| 176 | apply_permutation(corner_cycle[m], arr->cofb, 8); | ||
| 177 | sum_arrays_mod(cofb_flipped[m], arr->cofb, 8, 3); | ||
| 178 | } | ||
| 179 | if (f.cpos) | ||
| 180 | apply_permutation(center_cycle[m], arr->cpos, 6); | ||
| 181 | } | ||
| 182 | |||
| 183 | Cube move_via_array(Move m, Cube cube, PieceFilter f) { | ||
| 184 | CubeArray arr = {0}; | ||
| 185 | cube_to_arrays(cube, &arr, f); | ||
| 186 | move_cubearray(m, &arr, f); | ||
| 187 | return arrays_to_cube(arr, f); | ||
| 188 | } | ||
| 189 | |||
| 190 | int copy_alg(NissMove *src, NissMove *dest) { | ||
| 191 | int i; | ||
| 192 | for (i = 0; src[i].m != NULLMOVE; i++) | ||
| 193 | dest[i] = src[i]; | ||
| 194 | dest[i].m = NULLMOVE; | ||
| 195 | return i; | ||
| 196 | } | ||
| 197 | |||
| 198 | /* TODO: all strings start with space?? */ | ||
| 199 | void print_moves(NissMove *alg) { | ||
| 200 | bool niss = false; | ||
| 201 | for (int i = 0; alg[i].m != NULLMOVE; i++) { | ||
| 202 | char *fill = !niss && alg[i].inverse ? " (" : | ||
| 203 | (niss && !alg[i].inverse ? ") " : " "); | ||
| 204 | printf("%s%s", fill, move_string[alg[i].m]); | ||
| 205 | niss = alg[i].inverse; | ||
| 206 | } | ||
| 207 | printf("%s\n", niss ? ")" : ""); | ||
| 208 | } | ||
| 209 | |||
| 210 | int read_moves(char *str, NissMove *alg, int n) { | ||
| 211 | bool niss = false; | ||
| 212 | int c = 0; | ||
| 213 | |||
| 214 | for (int i = 0; str[i] && c < n; i++) { | ||
| 215 | if (str[i] == ' ' || str[i] == '\t' || str[i] == '\n') | ||
| 216 | continue; | ||
| 217 | |||
| 218 | if (str[i] == '(' || str[i] == ')') { | ||
| 219 | if ((niss && str[i] == '(') || (!niss && str[i] == ')')) | ||
| 220 | return -1; | ||
| 221 | niss = !niss; | ||
| 222 | continue; | ||
| 223 | } | ||
| 224 | |||
| 225 | alg[c].inverse = niss; alg[c].m = NULLMOVE; | ||
| 226 | for (Move j = 0; j < NMOVES; j++) { | ||
| 227 | if (str[i] == move_string[j][0]) { | ||
| 228 | alg[c].m = j; | ||
| 229 | if (alg[c].m <= B && str[i+1]=='w') { alg[c].m += Uw - U; i++; } | ||
| 230 | if (str[i+1]=='2') { alg[c].m += 1; i++; } | ||
| 231 | else if (str[i+1]=='\'' || str[i+1]=='3') { alg[c].m += 2; i++; } | ||
| 232 | c++; | ||
| 233 | break; | ||
| 234 | } | ||
| 235 | } | ||
| 236 | } | ||
| 237 | |||
| 238 | alg[c].m = NULLMOVE; | ||
| 239 | return c; | ||
| 240 | } | ||
| 241 | |||
| 242 | /* Helper function for cleanup. alg must contain only basic moves, no 2 or '. | ||
| 243 | top and front describe an admissible orientation of the cube. */ | ||
| 244 | void sort_cancel_rotate(NissMove *alg, int n, bool inv, int top, int front) { | ||
| 245 | int c = 0, i = 0; | ||
| 246 | PieceFilter cpos_only = { .cpos = true }; | ||
| 247 | NissMove aux[n+3]; | ||
| 248 | aux[0].m = NULLMOVE; | ||
| 249 | |||
| 250 | while (i < n && alg[i].m != NULLMOVE) { | ||
| 251 | int j = i; | ||
| 252 | while (j < n && commute[alg[i].m][alg[j].m]) j++; | ||
| 253 | Move base = 6*((alg[i].m-1)/6); | ||
| 254 | int t1 = 0, t2 = 0; | ||
| 255 | for (int k = i; k < j; k++) | ||
| 256 | if (alg[k].m == base+1) t1 = (t1+1)%4; | ||
| 257 | else t2 = (t2+1)%4; | ||
| 258 | if (t1) { aux[c].inverse = inv; aux[c].m = base+t1; c++; } | ||
| 259 | if (t2) { aux[c].inverse = inv; aux[c].m = base+t2+3; c++; } | ||
| 260 | i = j; | ||
| 261 | } | ||
| 262 | aux[c].m = NULLMOVE; | ||
| 263 | |||
| 264 | CubeArray q; | ||
| 265 | cube_to_arrays(blank_cube(), &q, cpos_only); | ||
| 266 | /* First we try to rotate in one move, then we try an x or y rotation | ||
| 267 | followed by a z rotation */ | ||
| 268 | for (int r = x; r <= z3; r++) { | ||
| 269 | move_cubearray(r, &q, cpos_only); | ||
| 270 | if (q.cpos[F_center] == front && q.cpos[U_center] == top) { | ||
| 271 | aux[c].inverse = inv; aux[c].m = r; | ||
| 272 | |||
| 273 | aux[++c].m = NULLMOVE; | ||
| 274 | copy_alg(aux, alg); | ||
| 275 | return; | ||
| 276 | } | ||
| 277 | move_cubearray(inverse[r], &q, cpos_only); | ||
| 278 | } | ||
| 279 | for (int r = x; r <= y3; r++) { | ||
| 280 | move_cubearray(r, &q, cpos_only); | ||
| 281 | if (q.cpos[F_center] == front) { | ||
| 282 | aux[c].inverse = inv; aux[c++].m = r; | ||
| 283 | break; | ||
| 284 | } | ||
| 285 | move_cubearray(inverse[r], &q, cpos_only); | ||
| 286 | } | ||
| 287 | for (int r = z; r <= z3; r++) { | ||
| 288 | move_cubearray(r, &q, cpos_only); | ||
| 289 | if (q.cpos[U_center] == top) { | ||
| 290 | aux[c].inverse = inv; aux[c++].m = r; | ||
| 291 | break; | ||
| 292 | } | ||
| 293 | move_cubearray(inverse[r], &q, cpos_only); | ||
| 294 | } | ||
| 295 | |||
| 296 | aux[c].m = NULLMOVE; | ||
| 297 | copy_alg(aux, alg); | ||
| 298 | } | ||
| 299 | |||
| 300 | /* TODO: does not work with niss + rotations */ | ||
| 301 | void cleanup(NissMove *alg, int n) { | ||
| 302 | int count_n = 0, count_i = 0, *count; | ||
| 303 | PieceFilter cpos_only = { .cpos = true }; | ||
| 304 | NissMove aux_n[n+1], aux_i[n+1], *aux; | ||
| 305 | CubeArray cube_n, cube_i, *cube; | ||
| 306 | cube_to_arrays(blank_cube(), &cube_n, cpos_only); | ||
| 307 | cube_to_arrays(blank_cube(), &cube_i, cpos_only); | ||
| 308 | |||
| 309 | for (int i = 0; count_n + count_i < n && alg[i].m != NULLMOVE; i++) { | ||
| 310 | if (alg[i].inverse) { count = &count_i; aux = aux_i; cube = &cube_i; } | ||
| 311 | else { count = &count_n; aux = aux_n; cube = &cube_n; } | ||
| 312 | |||
| 313 | for (int j = 0; equiv_moves[alg[i].m][j]; j++) { | ||
| 314 | Move m = equiv_moves[alg[i].m][j]; | ||
| 315 | aux[*count].inverse = alg[i].inverse; | ||
| 316 | move_cubearray(m, cube, cpos_only); | ||
| 317 | if (m == U) aux[(*count)++].m = 3 * cube->cpos[0] + 1; | ||
| 318 | } | ||
| 319 | } | ||
| 320 | |||
| 321 | aux_n[count_n].m = NULLMOVE; | ||
| 322 | aux_i[count_i].m = NULLMOVE; | ||
| 323 | sort_cancel_rotate(aux_n, count_n, false, cube_n.cpos[0], cube_n.cpos[4]); | ||
| 324 | sort_cancel_rotate(aux_i, count_i, true, cube_i.cpos[0], cube_n.cpos[4]); | ||
| 325 | copy_alg(aux_n, alg); | ||
| 326 | copy_alg(aux_i, alg+count_n); | ||
| 327 | } | ||
| 328 | |||
| 329 | bool read_ttables_file() { | ||
| 330 | FILE *ttf; | ||
| 331 | if ((ttf = fopen("ttables", "rb")) != NULL) { | ||
| 332 | for (int m = 0; m < NMOVES; m++) { | ||
| 333 | fread(epose_ttable[m], sizeof(uint16_t), factorial12/factorial8, ttf); | ||
| 334 | fread(eposs_ttable[m], sizeof(uint16_t), factorial12/factorial8, ttf); | ||
| 335 | fread(eposm_ttable[m], sizeof(uint16_t), factorial12/factorial8, ttf); | ||
| 336 | fread(eofb_ttable[m], sizeof(uint16_t), pow2to11, ttf); | ||
| 337 | fread(eorl_ttable[m], sizeof(uint16_t), pow2to11, ttf); | ||
| 338 | fread(eoud_ttable[m], sizeof(uint16_t), pow2to11, ttf); | ||
| 339 | fread(cp_ttable[m], sizeof(uint16_t), factorial8, ttf); | ||
| 340 | fread(coud_ttable[m], sizeof(uint16_t), pow3to7, ttf); | ||
| 341 | fread(corl_ttable[m], sizeof(uint16_t), pow3to7, ttf); | ||
| 342 | fread(cofb_ttable[m], sizeof(uint16_t), pow3to7, ttf); | ||
| 343 | fread(cpos_ttable[m], sizeof(uint16_t), factorial6, ttf); | ||
| 344 | } | ||
| 345 | fclose(ttf); | ||
| 346 | return true; | ||
| 347 | } else return false; | ||
| 348 | } | ||
| 349 | |||
| 350 | bool write_ttables_file() { | ||
| 351 | FILE *ttf; | ||
| 352 | if ((ttf = fopen("ttables", "wb")) != NULL) { | ||
| 353 | for (int m = 0; m < NMOVES; m++) { | ||
| 354 | fwrite(epose_ttable[m], sizeof(uint16_t), factorial12/factorial8, ttf); | ||
| 355 | fwrite(eposs_ttable[m], sizeof(uint16_t), factorial12/factorial8, ttf); | ||
| 356 | fwrite(eposm_ttable[m], sizeof(uint16_t), factorial12/factorial8, ttf); | ||
| 357 | fwrite(eofb_ttable[m], sizeof(uint16_t), pow2to11, ttf); | ||
| 358 | fwrite(eorl_ttable[m], sizeof(uint16_t), pow2to11, ttf); | ||
| 359 | fwrite(eoud_ttable[m], sizeof(uint16_t), pow2to11, ttf); | ||
| 360 | fwrite(cp_ttable[m], sizeof(uint16_t), factorial8, ttf); | ||
| 361 | fwrite(coud_ttable[m], sizeof(uint16_t), pow3to7, ttf); | ||
| 362 | fwrite(corl_ttable[m], sizeof(uint16_t), pow3to7, ttf); | ||
| 363 | fwrite(cofb_ttable[m], sizeof(uint16_t), pow3to7, ttf); | ||
| 364 | fwrite(cpos_ttable[m], sizeof(uint16_t), factorial6, ttf); | ||
| 365 | } | ||
| 366 | fclose(ttf); | ||
| 367 | return true; | ||
| 368 | } else return false; | ||
| 369 | } | ||
| 370 | |||
| 371 | void init_ttables(bool read, bool write) { | ||
| 372 | /* Generate all move cycles and flips; I do this regardless */ | ||
| 373 | for (int i = 0; i < NMOVES; i++) { | ||
| 374 | if (i == U || i == x || i == y) | ||
| 375 | continue; | ||
| 376 | |||
| 377 | CubeArray arr = {0}; | ||
| 378 | cube_to_arrays(blank_cube(), &arr, fAll); | ||
| 379 | for (int j = 0; equiv_moves[i][j]; j++) | ||
| 380 | move_cubearray(equiv_moves[i][j], &arr, fAll); | ||
| 381 | |||
| 382 | intarrcopy(arr.ep, edge_cycle[i], 12); | ||
| 383 | intarrcopy(arr.eofb, eofb_flipped[i], 12); | ||
| 384 | intarrcopy(arr.eorl, eorl_flipped[i], 12); | ||
| 385 | intarrcopy(arr.eoud, eoud_flipped[i], 12); | ||
| 386 | intarrcopy(arr.cp, corner_cycle[i], 8); | ||
| 387 | intarrcopy(arr.coud, coud_flipped[i], 8); | ||
| 388 | intarrcopy(arr.corl, corl_flipped[i], 8); | ||
| 389 | intarrcopy(arr.cofb, cofb_flipped[i], 8); | ||
| 390 | intarrcopy(arr.cpos, center_cycle[i], 6); | ||
| 391 | } | ||
| 392 | |||
| 393 | if (read) | ||
| 394 | if (read_ttables_file()) | ||
| 395 | return; | ||
| 396 | |||
| 397 | /* Initialize transition tables */ | ||
| 398 | Cube c = {0}; | ||
| 399 | PieceFilter fe = {.epose=true}, fs = {.eposs=true}, fm = {.eposm=true}; | ||
| 400 | PieceFilter feo = { .eofb = true, .eorl = true, .eoud = true }; | ||
| 401 | PieceFilter fcp = { .cp = true }; | ||
| 402 | PieceFilter fco = { .cofb = true, .corl = true, .coud = true }; | ||
| 403 | PieceFilter fcc = { .cpos = true }; | ||
| 404 | for (int m = 0; m < NMOVES; m++) { | ||
| 405 | for (uint16_t i = 0; i < factorial12/factorial8; i++) { | ||
| 406 | c.epose = i; epose_ttable[m][i] = move_via_array(m, c, fe).epose; | ||
| 407 | c.eposs = i; eposs_ttable[m][i] = move_via_array(m, c, fs).eposs; | ||
| 408 | c.eposm = i; eposm_ttable[m][i] = move_via_array(m, c, fm).eposm; | ||
| 409 | } | ||
| 410 | for (uint16_t i = 0; i < pow2to11; i++ ) { | ||
| 411 | c.eofb = i; eofb_ttable[m][i] = move_via_array(m, c, feo).eofb; | ||
| 412 | c.eorl = i; eorl_ttable[m][i] = move_via_array(m, c, feo).eorl; | ||
| 413 | c.eoud = i; eoud_ttable[m][i] = move_via_array(m, c, feo).eoud; | ||
| 414 | } | ||
| 415 | for (uint16_t i = 0; i < factorial8; i++) { | ||
| 416 | c.cp = i; cp_ttable[m][i] = move_via_array(m, c, fcp).cp; | ||
| 417 | } | ||
| 418 | for (uint16_t i = 0; i < pow3to7; i++) { | ||
| 419 | c.coud = i; coud_ttable[m][i] = move_via_array(m, c, fco).coud; | ||
| 420 | c.corl = i; corl_ttable[m][i] = move_via_array(m, c, fco).corl; | ||
| 421 | c.cofb = i; cofb_ttable[m][i] = move_via_array(m, c, fco).cofb; | ||
| 422 | } | ||
| 423 | for (uint16_t i = 0; i < factorial6; i++) { | ||
| 424 | c.cpos = i; cpos_ttable[m][i] = move_via_array(m, c, fcc).cpos; | ||
| 425 | } | ||
| 426 | } | ||
| 427 | |||
| 428 | if (write) write_ttables_file(); | ||
| 429 | } | ||
| 430 | |||
| 431 | Cube move_cube(Move m, Cube cube) { | ||
| 432 | Cube moved = cube; | ||
| 433 | |||
| 434 | moved.epose = epose_ttable[m][cube.epose]; | ||
| 435 | moved.eposs = eposs_ttable[m][cube.eposs]; | ||
| 436 | moved.eposm = eposm_ttable[m][cube.eposm]; | ||
| 437 | moved.eofb = eofb_ttable[m][cube.eofb]; | ||
| 438 | moved.eorl = eorl_ttable[m][cube.eorl]; | ||
| 439 | moved.eoud = eoud_ttable[m][cube.eoud]; | ||
| 440 | moved.coud = coud_ttable[m][cube.coud]; | ||
| 441 | moved.cofb = cofb_ttable[m][cube.cofb]; | ||
| 442 | moved.corl = corl_ttable[m][cube.corl]; | ||
| 443 | moved.cp = cp_ttable[m][cube.cp]; | ||
| 444 | moved.cpos = cpos_ttable[m][cube.cpos]; | ||
| 445 | |||
| 446 | return moved; | ||
| 447 | } | ||
| 448 | |||
| 449 | Cube apply_alg(NissMove *alg, Cube cube) { | ||
| 450 | Cube ret = {0}; | ||
| 451 | for (int i = 0; alg[i].m != NULLMOVE; i++) | ||
| 452 | if (alg[i].inverse) | ||
| 453 | ret = move_cube(alg[i].m, ret); | ||
| 454 | ret = compose(cube, inverse_cube(ret)); | ||
| 455 | |||
| 456 | for (int i = 0; alg[i].m != NULLMOVE; i++) | ||
| 457 | if (!alg[i].inverse) | ||
| 458 | ret = move_cube(alg[i].m, ret); | ||
| 459 | return ret; | ||
| 460 | } | ||
| 461 | |||
| 462 | void init_aux_tables() { | ||
| 463 | /* Commute */ | ||
| 464 | for (int i = 0; i < NMOVES; i++) | ||
| 465 | for (int j = 0; j < NMOVES; j++) | ||
| 466 | commute[i][j] = equal(move_cube(i, move_cube(j, blank_cube())), | ||
| 467 | move_cube(j, move_cube(i, blank_cube()))); | ||
| 468 | |||
| 469 | /* Possible next (if the sequence i j k is valid) */ | ||
| 470 | for (int i = 0; i < NMOVES; i++) | ||
| 471 | for (int j = 0; j < NMOVES; j++) | ||
| 472 | for (int k = 0; k < NMOVES; k++) | ||
| 473 | possible_next[i][j][k] = | ||
| 474 | (j == 0) || | ||
| 475 | (j != 0 && (j-(j-1)%3) != (k-(k-1)%3) && | ||
| 476 | !(i != 0 && commute[i][j] && (i-(i-1)%3) == (k-(k-1)%3))); | ||
| 477 | |||
| 478 | /* Inverse */ | ||
| 479 | for (int i = 0; i < NMOVES; i++) | ||
| 480 | inverse[i] = i == 0 ? 0 : i + 2 - 2*((i-1)%3); | ||
| 481 | } | ||
| 482 | |||
diff --git a/old/2021-02-18-piecefilter/src/moves.h b/old/2021-02-18-piecefilter/src/moves.h new file mode 100644 index 0000000..9ccf6e4 --- /dev/null +++ b/old/2021-02-18-piecefilter/src/moves.h | |||
| @@ -0,0 +1,46 @@ | |||
| 1 | #ifndef MOVES_H | ||
| 2 | #define MOVES_H | ||
| 3 | |||
| 4 | #include <stdio.h> | ||
| 5 | #include <stdbool.h> | ||
| 6 | #include <stdint.h> | ||
| 7 | #include "cube.h" | ||
| 8 | #include "utils.h" | ||
| 9 | |||
| 10 | #define NMOVES (z3+1) | ||
| 11 | |||
| 12 | typedef enum { | ||
| 13 | NULLMOVE, | ||
| 14 | U, U2, U3, D, D2, D3, R, R2, R3, L, L2, L3, F, F2, F3, B, B2, B3, | ||
| 15 | Uw, Uw2, Uw3, Dw, Dw2, Dw3, Rw, Rw2, Rw3, | ||
| 16 | Lw, Lw2, Lw3, Fw, Fw2, Fw3, Bw, Bw2, Bw3, | ||
| 17 | M, M2, M3, S, S2, S3, E, E2, E3, | ||
| 18 | x, x2, x3, y, y2, y3, z, z2, z3, | ||
| 19 | } Move; | ||
| 20 | |||
| 21 | /* An alg is an array of "NissMoves", which can be on normal or on inverse. */ | ||
| 22 | typedef struct { bool inverse; Move m; } NissMove; | ||
| 23 | |||
| 24 | /* Movesets */ | ||
| 25 | extern bool standard_moveset[NMOVES]; | ||
| 26 | |||
| 27 | extern bool commute[NMOVES][NMOVES]; | ||
| 28 | extern bool possible_next[NMOVES][NMOVES][NMOVES]; | ||
| 29 | extern Move inverse[NMOVES]; | ||
| 30 | |||
| 31 | bool is_solve_up_to_reorient(Cube cube); | ||
| 32 | int copy_alg(NissMove *src, NissMove *dest); /*return number of moves copied */ | ||
| 33 | void print_moves(NissMove *alg); | ||
| 34 | int read_moves(char *str, NissMove *alg, int n); /* reads at most n moves */ | ||
| 35 | void cleanup(NissMove *src, int n); /* rewrites using basic moves, at most n */ | ||
| 36 | Cube move_cube(Move m, Cube cube); | ||
| 37 | /* I might want to replace this with two versions, one that uses PieceFilter */ | ||
| 38 | Cube apply_alg(NissMove *alg, Cube cube); | ||
| 39 | |||
| 40 | /* Merge the following two? | ||
| 41 | always in this order */ | ||
| 42 | void init_ttables(bool read, bool write); | ||
| 43 | void init_aux_tables(); | ||
| 44 | |||
| 45 | |||
| 46 | #endif | ||
diff --git a/old/2021-02-18-piecefilter/src/solve.c b/old/2021-02-18-piecefilter/src/solve.c new file mode 100644 index 0000000..ac19d6f --- /dev/null +++ b/old/2021-02-18-piecefilter/src/solve.c | |||
| @@ -0,0 +1,179 @@ | |||
| 1 | #include "solve.h" | ||
| 2 | |||
| 3 | /* Data for creating a pruning table: | ||
| 4 | - compressed: if set to true, each entry occupies only 4 bits, but values | ||
| 5 | larger than 15 cannot be stored. | ||
| 6 | - available[] is the list of availabel moves, as above. | ||
| 7 | - *ptable is the actual table to fill. | ||
| 8 | - n is the number of states (size of ptable). | ||
| 9 | - index must "linearize" the cube, i.e. return its index in ptable. | ||
| 10 | - fname is the name of the file where to store the table */ | ||
| 11 | typedef struct { | ||
| 12 | bool compressed, *available; | ||
| 13 | int max_moves; | ||
| 14 | uint8_t *ptable; | ||
| 15 | uint64_t n; | ||
| 16 | uint64_t (*index)(Cube); | ||
| 17 | char *fname; | ||
| 18 | } PruneData; | ||
| 19 | |||
| 20 | /* TODO: comment this */ | ||
| 21 | typedef struct { | ||
| 22 | bool niss; | ||
| 23 | int m, d; | ||
| 24 | uint64_t *n; | ||
| 25 | Move last1, last2; | ||
| 26 | } DfsData; | ||
| 27 | |||
| 28 | void solve_dfs(Cube cube, SolveData *sd, DfsData dd); | ||
| 29 | void init_ptable(PruneData *pd, bool read, bool write); | ||
| 30 | |||
| 31 | /* Search solutions of lenght exactly d */ | ||
| 32 | void solve_dfs(Cube cube, SolveData *sd, DfsData dd) { | ||
| 33 | if (*dd.n >= sd->max_solutions || | ||
| 34 | ((!sd->can_niss || dd.niss) && dd.m + sd->f(cube) > dd.d)) | ||
| 35 | return; | ||
| 36 | |||
| 37 | (sd->solutions[*dd.n][dd.m]).inverse = dd.niss; | ||
| 38 | (sd->solutions[*dd.n][dd.m]).m = NULLMOVE; | ||
| 39 | |||
| 40 | if (!sd->f(cube)) { /* Solved */ | ||
| 41 | if (dd.m == dd.d) { | ||
| 42 | (*dd.n)++; | ||
| 43 | if (*dd.n < sd->max_solutions) | ||
| 44 | copy_alg(sd->solutions[*dd.n-1], sd->solutions[*dd.n]); | ||
| 45 | } | ||
| 46 | return; | ||
| 47 | } | ||
| 48 | |||
| 49 | for (int i = 0; i < NMOVES && sd->sorted_moves[i] != NULLMOVE; i++) { | ||
| 50 | Move move = sd->sorted_moves[i]; | ||
| 51 | if (possible_next[dd.last2][dd.last1][move]) { | ||
| 52 | sd->solutions[*dd.n][dd.m].inverse = dd.niss; | ||
| 53 | sd->solutions[*dd.n][dd.m].m = move; | ||
| 54 | DfsData nn = { .niss = dd.niss, .m = dd.m+1, .d = dd.d, .n = dd.n, | ||
| 55 | .last1 = move, .last2 = dd.last1 }; | ||
| 56 | solve_dfs(move_cube(move, cube), sd, nn); | ||
| 57 | } | ||
| 58 | } | ||
| 59 | |||
| 60 | if (sd->can_niss && !dd.niss && | ||
| 61 | (!dd.m || (dd.m && sd->f(move_cube(dd.last1, blank_cube()))))) { | ||
| 62 | DfsData nn = { .niss = true, .m = dd.m, .d = dd.d, .n = dd.n }; | ||
| 63 | solve_dfs(inverse_cube(cube), sd, nn); | ||
| 64 | } | ||
| 65 | } | ||
| 66 | |||
| 67 | /* Iterative deepening depth-first search: for i running from the minimum | ||
| 68 | to the maximum number of moves allowed, looks for solutions of length i. */ | ||
| 69 | int solve(Cube cube, SolveData *sd) { | ||
| 70 | if (sd->precondition != NULL && !sd->precondition(cube)) | ||
| 71 | return -1; | ||
| 72 | |||
| 73 | /* If not given, generate sorted list of moves */ | ||
| 74 | if (sd->sorted_moves[0] == NULLMOVE) { | ||
| 75 | int a[NMOVES], b[NMOVES], ia = 0, ib = 0; | ||
| 76 | for (int i = 0; i < NMOVES; i++) { | ||
| 77 | if (sd->available[i]) { | ||
| 78 | if (sd->f(move_cube(i, blank_cube()))) | ||
| 79 | a[ia++] = i; | ||
| 80 | else | ||
| 81 | b[ib++] = i; | ||
| 82 | } | ||
| 83 | } | ||
| 84 | intarrcopy(a, (int *)sd->sorted_moves, ia); | ||
| 85 | intarrcopy(b, (int *)sd->sorted_moves+ia, ib); | ||
| 86 | sd->sorted_moves[ia+ib] = NULLMOVE; | ||
| 87 | } | ||
| 88 | |||
| 89 | sd->max_solutions = min(sd->max_solutions, MAXS); | ||
| 90 | /*TODO | ||
| 91 | Cube rotated = apply_alg(sd->pre_rotation, blank_cube()); | ||
| 92 | cube = apply_alg(inverse_cube(rotated), compose(cube, rotated)); | ||
| 93 | */ | ||
| 94 | |||
| 95 | uint64_t ret = 0; | ||
| 96 | for (int i=sd->min_moves; i<=sd->max_moves&&!(ret&&sd->optimal_only); i++) { | ||
| 97 | DfsData dd = { .d = i, .n = &ret }; | ||
| 98 | solve_dfs(cube, sd, dd); | ||
| 99 | } | ||
| 100 | |||
| 101 | for (uint64_t i = 0; i < ret; i++) { | ||
| 102 | /* TODO: transform solutions with inverse of pre_rotation */ | ||
| 103 | if (sd->cleanup) | ||
| 104 | cleanup(sd->solutions[i], sd->max_moves*3); | ||
| 105 | } | ||
| 106 | |||
| 107 | return ret; | ||
| 108 | } | ||
| 109 | |||
| 110 | void prune_dfs(Cube cube, PruneData *pd, DfsData dd) { | ||
| 111 | uint64_t ind = pd->index(cube); | ||
| 112 | if ((!ind || pd->ptable[ind]) && pd->ptable[ind] != dd.m) | ||
| 113 | return; | ||
| 114 | if (dd.m == dd.d) { | ||
| 115 | if (ind && !pd->ptable[ind]) { | ||
| 116 | pd->ptable[ind] = dd.m; | ||
| 117 | (*dd.n)++; | ||
| 118 | } | ||
| 119 | return; | ||
| 120 | } | ||
| 121 | |||
| 122 | for (int i = 0; i < NMOVES; i++) { | ||
| 123 | if (dd.m<20) | ||
| 124 | if (possible_next[dd.last2][dd.last1][i] && pd->available[i]) { | ||
| 125 | DfsData nn = { .m = dd.m+1, .d = dd.d, .n = dd.n, | ||
| 126 | .last1 = i, .last2 = dd.last1 }; | ||
| 127 | prune_dfs(move_cube(i, cube), pd, nn); | ||
| 128 | } | ||
| 129 | } | ||
| 130 | } | ||
| 131 | |||
| 132 | void init_ptable(PruneData *pd, bool read, bool write) { | ||
| 133 | if (read) { | ||
| 134 | FILE *ptf; | ||
| 135 | if ((ptf = fopen(pd->fname, "rb")) != NULL) { | ||
| 136 | fread(pd->ptable, sizeof(uint8_t), pd->n, ptf); | ||
| 137 | fclose(ptf); | ||
| 138 | return; | ||
| 139 | } | ||
| 140 | } | ||
| 141 | |||
| 142 | /* TODO: for now it behaves always as if copressed = false */ | ||
| 143 | for (uint64_t i = 0; i < pd->n; i++) | ||
| 144 | pd->ptable[i] = 0; | ||
| 145 | |||
| 146 | uint64_t s = 1; | ||
| 147 | for (int i = 1; i < pd->max_moves && s < pd->n; i++) { | ||
| 148 | DfsData dd = { .d = i, .n = &s }; | ||
| 149 | prune_dfs(blank_cube(), pd, dd); | ||
| 150 | } | ||
| 151 | |||
| 152 | if (write) { | ||
| 153 | FILE *ptf; | ||
| 154 | if ((ptf = fopen(pd->fname, "wb")) != NULL) { | ||
| 155 | fwrite(pd->ptable, sizeof(uint8_t), pd->n, ptf); | ||
| 156 | fclose(ptf); | ||
| 157 | return; | ||
| 158 | } | ||
| 159 | } | ||
| 160 | } | ||
| 161 | |||
| 162 | /* Solving steps (and indexing functions) */ | ||
| 163 | |||
| 164 | uint64_t index_eofb(Cube cube) { return cube.eofb; } | ||
| 165 | uint16_t f_eofb(Cube cube) { | ||
| 166 | static bool initialized_ptable; | ||
| 167 | static uint8_t pt_eofb[pow2to11]; | ||
| 168 | if (!initialized_ptable) { | ||
| 169 | PruneData pd = { | ||
| 170 | .compressed = false, .available = standard_moveset, .max_moves = 13, | ||
| 171 | .ptable = pt_eofb, .n = pow2to11, .index = index_eofb, | ||
| 172 | .fname = "ptable_eofb" | ||
| 173 | }; | ||
| 174 | init_ptable(&pd, false, true); | ||
| 175 | initialized_ptable = true; | ||
| 176 | } | ||
| 177 | return cube.eofb ? pt_eofb[cube.eofb] : 0; | ||
| 178 | } | ||
| 179 | |||
diff --git a/old/2021-02-18-piecefilter/src/solve.h b/old/2021-02-18-piecefilter/src/solve.h new file mode 100644 index 0000000..d585a8e --- /dev/null +++ b/old/2021-02-18-piecefilter/src/solve.h | |||
| @@ -0,0 +1,56 @@ | |||
| 1 | #ifndef SOLVE_H | ||
| 2 | #define SOLVE_H | ||
| 3 | |||
| 4 | #include <stdlib.h> | ||
| 5 | #include "cube.h" | ||
| 6 | #include "moves.h" | ||
| 7 | |||
| 8 | /* Maximum number of moves per solution and of solutions */ | ||
| 9 | #define MAXM 30 | ||
| 10 | #define MAXS 999 | ||
| 11 | |||
| 12 | /* Data for solving a step: | ||
| 13 | - can_niss is true niss can be used, false otherwise. | ||
| 14 | - optimal_only if true, dynamically updates max_moves so non-optimal | ||
| 15 | solutions are discarded. | ||
| 16 | - cleanup determines whether the cleaunup() function should be used on | ||
| 17 | the found solutions before returning. | ||
| 18 | - available[m] is true if the move m can be used, false otherwise. | ||
| 19 | - min_moves and max_moves are the minimum and maximum number of moves that | ||
| 20 | can be used. | ||
| 21 | - max_solution is the maximum number of solutions that can be returned. | ||
| 22 | - precondition can be used to check wheter the step can actually be applied | ||
| 23 | to the cube. If it returns false, solve() stops immediately returning -1. | ||
| 24 | - f must return 0 if and only if the step is solve, otherwise it must return | ||
| 25 | a lower bound for the number of moves required (without niss). | ||
| 26 | - sorted_moves[] can be used to specify in which order moves are tried | ||
| 27 | by the solving algorithm (for example if one wants to always try F' before | ||
| 28 | F). If sorted_moves[0] == NULLMOVE, the list is generated automatically. | ||
| 29 | It is advised to list first all the moves that actually influence the | ||
| 30 | solved state of the step (this is the default choice). This is in order to | ||
| 31 | avoid cases like B2 F for EO and to NISS only when it makes sense. | ||
| 32 | - start_moves [Currently unused, REMOVE] | ||
| 33 | are the moves that will be used as first moves of all | ||
| 34 | solutions. For example giving R' U' F (F' U R) will generate FMC scrambles | ||
| 35 | and y (y) will solve the step on another axis. | ||
| 36 | - pre_rotation are the rotations to apply before the scamble to solve | ||
| 37 | the step wrt a different orientation | ||
| 38 | - pre_rotation are the rotations to apply before the scamble to solve | ||
| 39 | the step wth respect to a different orientation. | ||
| 40 | - solutions[][] is the array where to store the found solutions. */ | ||
| 41 | typedef struct { | ||
| 42 | bool can_niss, optimal_only, cleanup, *available; | ||
| 43 | int min_moves, max_moves; | ||
| 44 | uint64_t max_solutions; | ||
| 45 | bool (*precondition)(Cube); | ||
| 46 | uint16_t (*f)(Cube); | ||
| 47 | Move sorted_moves[NMOVES]; | ||
| 48 | NissMove pre_rotation[3], solutions[MAXS][MAXM]; | ||
| 49 | } SolveData; | ||
| 50 | |||
| 51 | int solve(Cube cube, SolveData *data); /* Returns the number of solutions. */ | ||
| 52 | |||
| 53 | /* Steps */ | ||
| 54 | uint16_t f_eofb(Cube cube); | ||
| 55 | |||
| 56 | #endif | ||
diff --git a/old/2021-02-18-piecefilter/src/transformations.c b/old/2021-02-18-piecefilter/src/transformations.c new file mode 100644 index 0000000..bcf4115 --- /dev/null +++ b/old/2021-02-18-piecefilter/src/transformations.c | |||
| @@ -0,0 +1,103 @@ | |||
| 1 | #include "transformations.h" | ||
| 2 | /* | ||
| 3 | Cube apply_rotation_alg(Rotation r, Cube c); | ||
| 4 | void apply_rotation_cube(NissMove *alg); | ||
| 5 | Cube apply_mirror_cube(Cube c); | ||
| 6 | void apply_mirror_alg(NissMove *alg); | ||
| 7 | */ | ||
| 8 | |||
| 9 | void compute_sources(); | ||
| 10 | Cube rotate_via_compose(Rotation r, Cube c); | ||
| 11 | |||
| 12 | /* Values mod 3 to determine from which side to take the state to convert */ | ||
| 13 | int epose_source[NROTATIONS]; /* 0 = epose, 1 = eposs, 2 = eposm */ | ||
| 14 | int eposs_source[NROTATIONS]; | ||
| 15 | int eposm_source[NROTATIONS]; | ||
| 16 | int eofb_source[NROTATIONS]; /* 0 = eofb, 1 = eorl, 2 = eoud */ | ||
| 17 | int eorl_source[NROTATIONS]; | ||
| 18 | int eoud_source[NROTATIONS]; | ||
| 19 | int coud_source[NROTATIONS]; /* 0 = coud, 1 = cofb, 2 = corl */ | ||
| 20 | int cofb_source[NROTATIONS]; | ||
| 21 | int corl_source[NROTATIONS]; | ||
| 22 | |||
| 23 | /* Transition tables for rotations */ | ||
| 24 | uint16_t epose_rtable[NROTATIONS][factorial12/factorial8]; | ||
| 25 | uint16_t eposs_rtable[NROTATIONS][factorial12/factorial8]; | ||
| 26 | uint16_t eposm_rtable[NROTATIONS][factorial12/factorial8]; | ||
| 27 | uint16_t eofb_rtable[NROTATIONS][pow2to11]; | ||
| 28 | uint16_t eorl_rtable[NROTATIONS][pow2to11]; | ||
| 29 | uint16_t eoud_rtable[NROTATIONS][pow2to11]; | ||
| 30 | uint16_t cp_rtable[NROTATIONS][factorial8]; | ||
| 31 | uint16_t coud_rtable[NROTATIONS][pow3to7]; | ||
| 32 | uint16_t cofb_rtable[NROTATIONS][pow3to7]; | ||
| 33 | uint16_t corl_rtable[NROTATIONS][pow3to7]; | ||
| 34 | |||
| 35 | /* Transition tables for mirror */ | ||
| 36 | uint16_t epose_mtable[factorial12/factorial8]; | ||
| 37 | uint16_t eposs_mtable[factorial12/factorial8]; | ||
| 38 | uint16_t eposm_mtable[factorial12/factorial8]; | ||
| 39 | uint16_t eofb_mtable[pow2to11]; | ||
| 40 | uint16_t eorl_mtable[pow2to11]; | ||
| 41 | uint16_t eoud_mtable[pow2to11]; | ||
| 42 | uint16_t cp_mtable[factorial8]; | ||
| 43 | uint16_t coud_mtable[pow3to7]; | ||
| 44 | uint16_t cofb_mtable[pow3to7]; | ||
| 45 | uint16_t corl_mtable[pow3to7]; | ||
| 46 | |||
| 47 | /* Same for moves */ | ||
| 48 | uint16_t move_rtable[NROTATIONS][NMOVES]; | ||
| 49 | uint16_t move_mtable[NMOVES]; | ||
| 50 | |||
| 51 | /* Applying a rotation to the cube is equivalent to applying m (m) */ | ||
| 52 | Move equiv_moves[NROTATIONS][3] = { | ||
| 53 | [uf] = {0,0,0}, [ur] = {y,0,0}, [ub] = {y2,0,0}, [ul] = {y3,0,0}, | ||
| 54 | [df] = {z2,0,0}, [dr] = {y,z2,0}, [db] = {y2,z2,0}, [dl] = {y3,z2,0}, | ||
| 55 | [rf] = {z3,0,0}, [rd] = {z3,y,0}, [rb] = {z3,y2,0}, [ru] = {z3,y3,0}, | ||
| 56 | [lf] = {z,0,0}, [ld] = {z,y3,0}, [lb] = {z,y2,0}, [lu] = {z,y,0}, | ||
| 57 | [fu] = {x,y2,0}, [fr] = {x,y,0}, [fd] = {x,0,0}, [fl] = {x,y3,0}, | ||
| 58 | [bu] = {x3,0,0}, [br] = {x3,y,0}, [bd] = {x3,y2,0}, [bl] = {x3,y3,0}, | ||
| 59 | }; | ||
| 60 | |||
| 61 | int mirror_ep[12] = {UF, UR, UB, UL, DF, DR, DB, DL, FL, FR, BR, BL}; | ||
| 62 | int mirror_cp[8] = {UFL, UFR, UBR, UBL, DFL, DFR, DBR, DBL}; | ||
| 63 | int mirror_cpos[6] = {U_center,D_center,L_center,R_center,F_center,B_center}; | ||
| 64 | |||
| 65 | void compute_sources() { | ||
| 66 | /* epos{e,s,m} */ | ||
| 67 | CubeArray arr; | ||
| 68 | for (int i = 0; i < NROTATIONS; i++) { | ||
| 69 | cube_to_arrays(move_cube(equiv_moves[i][1], | ||
| 70 | move_cube(equiv_moves[i][0], blank_cube())), &arr, fAll); | ||
| 71 | epose_source[i] = edge_slice(arr.ep[FR]); | ||
| 72 | eposs_source[i] = edge_slice(arr.ep[UR]); | ||
| 73 | eposm_source[i] = edge_slice(arr.ep[UF]); | ||
| 74 | eofb_source[i] = 2 - center_axis(arr.cpos[F_center]); | ||
| 75 | eorl_source[i] = 2 - center_axis(arr.cpos[R_center]); | ||
| 76 | eoud_source[i] = 2 - center_axis(arr.cpos[U_center]); | ||
| 77 | coud_source[i] = (2 * center_axis(arr.cpos[U_center])) % 3; | ||
| 78 | cofb_source[i] = (2 * center_axis(arr.cpos[F_center])) % 3; | ||
| 79 | corl_source[i] = (2 * center_axis(arr.cpos[R_center])) % 3; | ||
| 80 | } | ||
| 81 | } | ||
| 82 | |||
| 83 | /* Use Piecefilter? */ | ||
| 84 | Cube rotate_via_compose(Rotation r, Cube c) { | ||
| 85 | /* TODO: if this is slow, change compose() in cube.{c,h} to use PieceFilter */ | ||
| 86 | int j = 0; | ||
| 87 | NissMove nm[10] = {0}; | ||
| 88 | for (int i = 1; i >= 0; i--) { | ||
| 89 | if (equiv_moves[r][i] != NULLMOVE) { | ||
| 90 | nm[j].inverse = true; | ||
| 91 | nm[j++].m = inverse[equiv_moves[r][i]]; | ||
| 92 | } | ||
| 93 | } | ||
| 94 | for (int i = 0; equiv_moves[r][i] != NULLMOVE; i++) { | ||
| 95 | nm[j].inverse = false; | ||
| 96 | nm[j++].m = equiv_moves[r][i]; | ||
| 97 | } | ||
| 98 | |||
| 99 | return apply_alg(nm, c); | ||
| 100 | } | ||
| 101 | |||
| 102 | /* Use PieceFilter? Not really necessary, but could be nice */ | ||
| 103 | Cube mirror_via_cubearray(Cube c) { | ||
diff --git a/old/2021-02-18-piecefilter/src/transformations.h b/old/2021-02-18-piecefilter/src/transformations.h new file mode 100644 index 0000000..28dde93 --- /dev/null +++ b/old/2021-02-18-piecefilter/src/transformations.h | |||
| @@ -0,0 +1,37 @@ | |||
| 1 | #ifndef TRANSFORMATIONS_H | ||
| 2 | #define TRANSFORMATIONS_H | ||
| 3 | |||
| 4 | #include <stdio.h> | ||
| 5 | #include <stdbool.h> | ||
| 6 | #include <stdint.h> | ||
| 7 | #include "cube.h" | ||
| 8 | #include "moves.h" | ||
| 9 | #include "utils.h" | ||
| 10 | |||
| 11 | #define NROTATIONS (bl+1) | ||
| 12 | |||
| 13 | /* Letters indicate top and front centers | ||
| 14 | * Lowercase letter to distinguish from pieces */ | ||
| 15 | typedef enum { | ||
| 16 | uf, ur, ub, ul, | ||
| 17 | df, dr, db, dl, | ||
| 18 | rf, rd, rb, ru, | ||
| 19 | lf, ld, lb, lu, | ||
| 20 | fu, fr, fd, fl, | ||
| 21 | bu, br, bd, bl, | ||
| 22 | } Rotation; | ||
| 23 | |||
| 24 | /* Mirror is always on fb axis and applied after rotation */ | ||
| 25 | typedef struct { | ||
| 26 | Rotation rotation; | ||
| 27 | bool mirror; | ||
| 28 | } Transformation; | ||
| 29 | |||
| 30 | void print_transformation(Transformation t); | ||
| 31 | |||
| 32 | Cube transform_cube(Transformation t, Cube cube); | ||
| 33 | void transform_alg(Transformation t, NissMove *alg); /* Applied in-place */ | ||
| 34 | |||
| 35 | void init_transformations(bool read, bool write); | ||
| 36 | |||
| 37 | #endif | ||
diff --git a/old/2021-02-18-piecefilter/src/utils.c b/old/2021-02-18-piecefilter/src/utils.c new file mode 100644 index 0000000..66de9ad --- /dev/null +++ b/old/2021-02-18-piecefilter/src/utils.c | |||
| @@ -0,0 +1,197 @@ | |||
| 1 | #include "utils.h" | ||
| 2 | |||
| 3 | void swap(int *a, int *b) { | ||
| 4 | int aux = *a; | ||
| 5 | *a = *b; | ||
| 6 | *b = aux; | ||
| 7 | } | ||
| 8 | |||
| 9 | void intarrcopy(int *src, int *dst, int n) { | ||
| 10 | for (int i = 0; i < n; i++) | ||
| 11 | dst[i] = src[i]; | ||
| 12 | } | ||
| 13 | |||
| 14 | int sum(int *a, int n) { | ||
| 15 | int ret = 0; | ||
| 16 | for (int i = 0; i < n; i++) | ||
| 17 | ret += a[i]; | ||
| 18 | return ret; | ||
| 19 | } | ||
| 20 | |||
| 21 | bool is_perm(int *a, int n) { | ||
| 22 | int aux[n]; for (int i = 0; i < n; i++) aux[i] = 0; | ||
| 23 | for (int i = 0; i < n; i++) | ||
| 24 | if (a[i] < 0 || a[i] >= n) | ||
| 25 | return false; | ||
| 26 | else | ||
| 27 | aux[a[i]] = 1; | ||
| 28 | for (int i = 0; i < n; i++) | ||
| 29 | if (!aux[i]) | ||
| 30 | return false; | ||
| 31 | return true; | ||
| 32 | } | ||
| 33 | |||
| 34 | bool is_subset(int *a, int n, int k) { | ||
| 35 | int sum = 0; | ||
| 36 | for (int i = 0; i < n; i++) | ||
| 37 | sum += a[i] ? 1 : 0; | ||
| 38 | return sum == k; | ||
| 39 | } | ||
| 40 | |||
| 41 | int powint(int a, int b) { | ||
| 42 | return 0; | ||
| 43 | if (b == 0 || a == 1) | ||
| 44 | return 1; | ||
| 45 | if (a == 0) | ||
| 46 | return 0; | ||
| 47 | if (b < 0) | ||
| 48 | return 0; /* Immediate truncate (integer part is 0) */ | ||
| 49 | if (b % 2) { | ||
| 50 | return a * powint(a, b-1); | ||
| 51 | } else { | ||
| 52 | int x = powint(a, b/2); | ||
| 53 | return x*x; | ||
| 54 | } | ||
| 55 | } | ||
| 56 | |||
| 57 | int factorial(int n) { | ||
| 58 | if (n < 0) | ||
| 59 | return 0; | ||
| 60 | int ret = 1; | ||
| 61 | for (int i = 1; i <= n; i++) | ||
| 62 | ret *= i; | ||
| 63 | return ret; | ||
| 64 | } | ||
| 65 | |||
| 66 | int binomial(int n, int k) { | ||
| 67 | if (n < 0 || k < 0 || k > n) | ||
| 68 | return 0; | ||
| 69 | return factorial(n) / (factorial(k) * factorial(n-k)); | ||
| 70 | } | ||
| 71 | |||
| 72 | void int_to_digit_array(int a, int b, int n, int *r) { | ||
| 73 | if (b <= 1) | ||
| 74 | for (int i = 0; i < n; i++) | ||
| 75 | r[i] = 0; | ||
| 76 | else | ||
| 77 | for (int i = 0; i < n; i++, a /= b) | ||
| 78 | r[i] = a % b; | ||
| 79 | } | ||
| 80 | |||
| 81 | int digit_array_to_int(int *a, int n, int b) { | ||
| 82 | int ret = 0, p = 1; | ||
| 83 | for (int i = 0; i < n; i++, p *= b) | ||
| 84 | ret += a[i] * p; | ||
| 85 | return ret; | ||
| 86 | } | ||
| 87 | |||
| 88 | int perm_to_index(int *a, int n) { | ||
| 89 | if (!is_perm(a, n)) | ||
| 90 | return factorial(n); /* Error */ | ||
| 91 | int ret = 0; | ||
| 92 | for (int i = 0; i < n; i++) { | ||
| 93 | int c = 0; | ||
| 94 | for (int j = i+1; j < n; j++) | ||
| 95 | c += (a[i] > a[j]) ? 1 : 0; | ||
| 96 | ret += factorial(n-i-1) * c; | ||
| 97 | } | ||
| 98 | return ret; | ||
| 99 | } | ||
| 100 | |||
| 101 | void index_to_perm(int p, int n, int *r) { | ||
| 102 | if (p < 0 || p >= factorial(n)) /* Error */ | ||
| 103 | for (int i = 0; i < n; i++) | ||
| 104 | r[i] = -1; | ||
| 105 | int a[n]; for (int j = 0; j < n; j++) a[j] = 0; /* picked elements */ | ||
| 106 | for (int i = 0; i < n; i++) { | ||
| 107 | int c = 0, j = 0; | ||
| 108 | while (c <= p / factorial(n-i-1)) | ||
| 109 | c += a[j++] ? 0 : 1; | ||
| 110 | r[i] = j-1; | ||
| 111 | a[j-1] = 1; | ||
| 112 | p %= factorial(n-i-1); | ||
| 113 | } | ||
| 114 | } | ||
| 115 | |||
| 116 | int perm_sign(int *a, int n) { | ||
| 117 | if (!is_perm(a,n)) | ||
| 118 | return false; | ||
| 119 | int ret = 0; | ||
| 120 | for (int i = 0; i < n; i++) | ||
| 121 | for (int j = i+1; j < n; j++) | ||
| 122 | ret += (a[i]>a[j]) ? 1 : 0; | ||
| 123 | return ret % 2; | ||
| 124 | } | ||
| 125 | |||
| 126 | int subset_to_index(int *a, int n, int k) { | ||
| 127 | /* TODO: better checks */ | ||
| 128 | if (!is_subset(a, n, k)) | ||
| 129 | return binomial(n, k); /* Error */ | ||
| 130 | int ret = 0; | ||
| 131 | for (int i = 0; i < n; i++) { | ||
| 132 | if (k == n-i) | ||
| 133 | return ret; | ||
| 134 | if (a[i]) { | ||
| 135 | /*ret += factorial(n-i-1) / (factorial(k) * factorial(n-i-1-k));*/ | ||
| 136 | ret += binomial(n-i-1, k); | ||
| 137 | k--; | ||
| 138 | } | ||
| 139 | } | ||
| 140 | return ret; | ||
| 141 | } | ||
| 142 | |||
| 143 | void index_to_subset(int s, int n, int k, int *r) { | ||
| 144 | if (s < 0 || s >= binomial(n, k)) { /* Error */ | ||
| 145 | for (int i = 0; i < n; i++) | ||
| 146 | r[i] = -1; | ||
| 147 | return; | ||
| 148 | } | ||
| 149 | for (int i = 0; i < n; i++) { | ||
| 150 | if (k == n-i) { | ||
| 151 | for (int j = i; j < n; j++) | ||
| 152 | r[j] = 1; | ||
| 153 | return; | ||
| 154 | } | ||
| 155 | if (k == 0) { | ||
| 156 | for (int j = i; j < n; j++) | ||
| 157 | r[j] = 0; | ||
| 158 | return; | ||
| 159 | } | ||
| 160 | /*int v = factorial(n-i-1) / (factorial(k) * factorial(n-i-1-k));*/ | ||
| 161 | int v = binomial(n-i-1, k); | ||
| 162 | if (s >= v) { | ||
| 163 | r[i] = 1; | ||
| 164 | k--; | ||
| 165 | s -= v; | ||
| 166 | } else { | ||
| 167 | r[i] = 0; | ||
| 168 | } | ||
| 169 | } | ||
| 170 | } | ||
| 171 | |||
| 172 | void int_to_sum_zero_array(int x, int b, int n, int *a) { | ||
| 173 | if (b <= 1) { | ||
| 174 | for (int i = 0; i < n; i++) | ||
| 175 | a[i] = 0; | ||
| 176 | } else { | ||
| 177 | int_to_digit_array(x, b, n-1, a); | ||
| 178 | int s = 0; | ||
| 179 | for (int i = 0; i < n - 1; i++) | ||
| 180 | s = (s + a[i]) % b; | ||
| 181 | a[n-1] = (b - s) % b; | ||
| 182 | } | ||
| 183 | } | ||
| 184 | |||
| 185 | void apply_permutation(int *perm, int *set, int n) { | ||
| 186 | if (!is_perm(perm, n)) | ||
| 187 | return; | ||
| 188 | int aux[n]; | ||
| 189 | for (int i = 0; i < n; i++) | ||
| 190 | aux[i] = set[perm[i]]; | ||
| 191 | intarrcopy(aux, set, n); | ||
| 192 | } | ||
| 193 | |||
| 194 | void sum_arrays_mod(int *a, int *b, int n, int m) { | ||
| 195 | for (int i = 0; i < n; i++) | ||
| 196 | b[i] = (m <= 0) ? 0 : (a[i] + b[i]) % m; | ||
| 197 | } | ||
diff --git a/old/2021-02-18-piecefilter/src/utils.h b/old/2021-02-18-piecefilter/src/utils.h new file mode 100644 index 0000000..4b6df8c --- /dev/null +++ b/old/2021-02-18-piecefilter/src/utils.h | |||
| @@ -0,0 +1,70 @@ | |||
| 1 | /* General utility functions */ | ||
| 2 | |||
| 3 | #ifndef UTILS_H | ||
| 4 | #define UTILS_H | ||
| 5 | |||
| 6 | #include <stdbool.h> | ||
| 7 | |||
| 8 | #define min(a,b) (((a) < (b)) ? (a) : (b)) | ||
| 9 | #define max(a,b) (((a) > (b)) ? (a) : (b)) | ||
| 10 | |||
| 11 | /* Some useful constants */ | ||
| 12 | #define pow2to11 2048 | ||
| 13 | #define pow2to12 4096 | ||
| 14 | #define pow3to7 2187 | ||
| 15 | #define pow3to8 6561 | ||
| 16 | #define pow12to4 20736 | ||
| 17 | #define factorial4 24 | ||
| 18 | #define factorial6 720 | ||
| 19 | #define factorial8 40320 | ||
| 20 | #define factorial12 479001600 | ||
| 21 | #define binom12on4 495 | ||
| 22 | #define binom8on4 70 | ||
| 23 | |||
| 24 | /* Generic utility functions */ | ||
| 25 | void swap(int *a, int *b); | ||
| 26 | void intarrcopy(int *src, int *dst, int n); | ||
| 27 | int sum(int *a, int n); | ||
| 28 | bool is_perm(int *a, int n); | ||
| 29 | bool is_perm(int *a, int n); | ||
| 30 | |||
| 31 | |||
| 32 | /* Standard mathematical functions */ | ||
| 33 | int powint(int a, int b); | ||
| 34 | int factorial(int n); | ||
| 35 | int binomial(int n, int k); | ||
| 36 | |||
| 37 | /* Converts the integer a to its representation in base b (first n digits | ||
| 38 | * only) and saves the result in r. */ | ||
| 39 | void int_to_digit_array(int a, int b, int n, int *r); | ||
| 40 | int digit_array_to_int(int *a, int n, int b); | ||
| 41 | |||
| 42 | /* Converts the first n-1 digits of a number to an array a of digits in base b; | ||
| 43 | * then adds one element to the array, so that the sum of the elements of a is | ||
| 44 | * zero modulo b. | ||
| 45 | * This is used for determing the edge orientation from an 11-bits integer or | ||
| 46 | * the corner orientation from a 7-trits integer. */ | ||
| 47 | void int_to_sum_zero_array(int x, int b, int n, int *a); | ||
| 48 | |||
| 49 | /* Converts a permutation on [0..(n-1)] into the integer i which is the index | ||
| 50 | * of the permutation in the sorted list of all n! such permutations. */ | ||
| 51 | int perm_to_index(int *a, int n); | ||
| 52 | void index_to_perm(int p, int n, int *r); | ||
| 53 | |||
| 54 | /* Determine the sign of a permutation */ | ||
| 55 | int perm_sign(int a[], int n); | ||
| 56 | |||
| 57 | /* Converts a k-element subset of a set from an array of n elements, of which k | ||
| 58 | * are 1 and n-k are 0, to its index in the sorted list of all such subsets. */ | ||
| 59 | int subset_to_index(int *a, int n, int k); | ||
| 60 | void index_to_subset(int s, int n, int k, int *r); | ||
| 61 | |||
| 62 | int ordered_subset_to_index(int *a, int n, int k); | ||
| 63 | void index_to_ordered_subset(int s, int n, int k, int *r); | ||
| 64 | |||
| 65 | void apply_permutation(int *perm, int *set, int n); | ||
| 66 | |||
| 67 | /* b[i] = (a[i]+b[i])%m for i=1,...,n */ | ||
| 68 | void sum_arrays_mod(int *a, int *b, int n, int m); | ||
| 69 | |||
| 70 | #endif | ||
diff --git a/old/2021-02-28-transformcube-works/src/cube.c b/old/2021-02-28-transformcube-works/src/cube.c new file mode 100644 index 0000000..649a4de --- /dev/null +++ b/old/2021-02-28-transformcube-works/src/cube.c | |||
| @@ -0,0 +1,271 @@ | |||
| 1 | #include "cube.h" | ||
| 2 | |||
| 3 | typedef struct { | ||
| 4 | int ep[12],eofb[12],eorl[12],eoud[12],cp[8],coud[8],corl[8],cofb[8],cpos[6]; | ||
| 5 | } CubeArrayAllocated; | ||
| 6 | |||
| 7 | void allocate_cubearray(CubeArray *arr, CubeArrayAllocated *all); | ||
| 8 | |||
| 9 | char edge_string[12][5] = | ||
| 10 | { "UF", "UL", "UB", "UR", "DF", "DL", "DB", "DR", "FR", "FL", "BL", "BR" }; | ||
| 11 | char corner_string[8][5] = { "UFR","UFL","UBL","UBR","DFR","DFL","DBL","DBR" }; | ||
| 12 | char center_string[6][5] = { "U", "D", "R", "L", "F", "B" }; | ||
| 13 | |||
| 14 | int epe_solved[4] = {FR, FL, BL, BR}; | ||
| 15 | int eps_solved[4] = {UL, UR, DL, DR}; | ||
| 16 | int epm_solved[4] = {UF, UB, DF, DB}; | ||
| 17 | |||
| 18 | PieceFilter pf_all = {true,true,true,true,true,true,true,true,true,true,true}, | ||
| 19 | pf_cpos = { .cpos = true }, pf_cp = { .cp = true }, | ||
| 20 | pf_ep = { .epose = true, .eposs = true, .eposm = true }, | ||
| 21 | pf_e = {.epose=true}, pf_s={.eposs=true}, pf_m={.eposm=true}, | ||
| 22 | pf_eo = { .eofb = true, .eorl = true, .eoud = true }, | ||
| 23 | pf_co = { .coud = true, .cofb = true, .corl = true }; | ||
| 24 | |||
| 25 | void allocate_cubearray(CubeArray *arr, CubeArrayAllocated *all) { | ||
| 26 | arr->ep = all->ep; | ||
| 27 | arr->eofb = all->eofb; | ||
| 28 | arr->eorl = all->eorl; | ||
| 29 | arr->eoud = all->eoud; | ||
| 30 | arr->cp = all->cp; | ||
| 31 | arr->coud = all->coud; | ||
| 32 | arr->corl = all->corl; | ||
| 33 | arr->cofb = all->cofb; | ||
| 34 | arr->cpos = all->cpos; | ||
| 35 | } | ||
| 36 | |||
| 37 | void cube_to_arrays(Cube cube, CubeArray *arr, PieceFilter f) { | ||
| 38 | /* ep is the hardest */ | ||
| 39 | if (f.epose || f.eposs || f.eposm) | ||
| 40 | for (int i = 0; i < 12; i++) arr->ep[i] = -1; | ||
| 41 | if (f.epose) { | ||
| 42 | int epe[4], epose[12]; | ||
| 43 | index_to_perm(cube.epose % factorial(4), 4, epe); | ||
| 44 | index_to_subset(cube.epose / factorial(4), 12, 4, epose); | ||
| 45 | for (int i = 0, ie = 0; i < 12; i++) | ||
| 46 | if (epose[i]) arr->ep[i] = epe_solved[epe[ie++]]; | ||
| 47 | } | ||
| 48 | if (f.eposs) { | ||
| 49 | int eps[4], eposs[12]; | ||
| 50 | index_to_perm(cube.eposs % factorial(4), 4, eps); | ||
| 51 | index_to_subset(cube.eposs / factorial(4), 12, 4, eposs); | ||
| 52 | for (int i = 0; i < 4; i++) swap(&eposs[eps_solved[i]], &eposs[i+8]); | ||
| 53 | for (int i = 0, is = 0; i < 12; i++) | ||
| 54 | if (eposs[i]) arr->ep[i] = eps_solved[eps[is++]]; | ||
| 55 | } | ||
| 56 | if (f.eposm) { | ||
| 57 | int epm[4], eposm[12]; | ||
| 58 | index_to_perm(cube.eposm % factorial(4), 4, epm); | ||
| 59 | index_to_subset(cube.eposm / factorial(4), 12, 4, eposm); | ||
| 60 | for (int i = 0; i < 4; i++) swap(&eposm[epm_solved[i]], &eposm[i+8]); | ||
| 61 | for (int i = 0, im = 0; i < 12; i++) | ||
| 62 | if (eposm[i]) arr->ep[i] = epm_solved[epm[im++]]; | ||
| 63 | } | ||
| 64 | |||
| 65 | /* All the others */ | ||
| 66 | if (f.eofb) int_to_sum_zero_array(cube.eofb, 2, 12, arr->eofb); | ||
| 67 | if (f.eorl) int_to_sum_zero_array(cube.eorl, 2, 12, arr->eorl); | ||
| 68 | if (f.eoud) int_to_sum_zero_array(cube.eoud, 2, 12, arr->eoud); | ||
| 69 | if (f.cp) index_to_perm( cube.cp, 8, arr->cp); | ||
| 70 | if (f.coud) int_to_sum_zero_array(cube.coud, 3, 8, arr->coud); | ||
| 71 | if (f.corl) int_to_sum_zero_array(cube.corl, 3, 8, arr->corl); | ||
| 72 | if (f.cofb) int_to_sum_zero_array(cube.cofb, 3, 8, arr->cofb); | ||
| 73 | if (f.cpos) index_to_perm( cube.cpos, 6, arr->cpos); | ||
| 74 | } | ||
| 75 | |||
| 76 | Cube arrays_to_cube(CubeArray arr, PieceFilter f) { | ||
| 77 | Cube ret = {0}; | ||
| 78 | |||
| 79 | /* Again, ep is the hardest part */ | ||
| 80 | if (f.epose) { | ||
| 81 | int epe[4], epose[12] = {0,0,0,0,0,0,0,0,0,0,0,0}; | ||
| 82 | for (int i = 0, ie = 0; i < 12; i++) | ||
| 83 | for (int j = 0; j < 4; j++) | ||
| 84 | if (arr.ep[i] == epe_solved[j]) | ||
| 85 | { epe[ie++] = j; epose[i] = 1; } | ||
| 86 | ret.epose = factorial(4)*subset_to_index(epose,12,4)+perm_to_index(epe,4); | ||
| 87 | } | ||
| 88 | if (f.eposs) { | ||
| 89 | int eps[4], eposs[12] = {0,0,0,0,0,0,0,0,0,0,0,0}; | ||
| 90 | for (int i = 0, is = 0; i < 12; i++) | ||
| 91 | for (int j = 0; j < 4; j++) | ||
| 92 | if (arr.ep[i] == eps_solved[j]) | ||
| 93 | { eps[is++] = j; eposs[i] = 1; } | ||
| 94 | for (int i = 0; i < 4; i++) swap(&eposs[eps_solved[i]], &eposs[i+8]); | ||
| 95 | ret.eposs = factorial(4)*subset_to_index(eposs,12,4)+perm_to_index(eps,4); | ||
| 96 | } | ||
| 97 | if (f.eposm) { | ||
| 98 | int epm[4], eposm[12] = {0,0,0,0,0,0,0,0,0,0,0,0}; | ||
| 99 | for (int i = 0, im = 0; i < 12; i++) | ||
| 100 | for (int j = 0; j < 4; j++) | ||
| 101 | if (arr.ep[i] == epm_solved[j]) | ||
| 102 | { epm[im++] = j; eposm[i] = 1; } | ||
| 103 | for (int i = 0; i < 4; i++) swap(&eposm[epm_solved[i]], &eposm[i+8]); | ||
| 104 | ret.eposm = factorial(4)*subset_to_index(eposm,12,4)+perm_to_index(epm,4); | ||
| 105 | } | ||
| 106 | if (f.eofb) ret.eofb = digit_array_to_int(arr.eofb, 11, 2); | ||
| 107 | if (f.eorl) ret.eorl = digit_array_to_int(arr.eorl, 11, 2); | ||
| 108 | if (f.eoud) ret.eoud = digit_array_to_int(arr.eoud, 11, 2); | ||
| 109 | if (f.cp) ret.cp = perm_to_index( arr.cp, 8 ); | ||
| 110 | if (f.coud) ret.coud = digit_array_to_int(arr.coud, 7, 3); | ||
| 111 | if (f.corl) ret.corl = digit_array_to_int(arr.corl, 7, 3); | ||
| 112 | if (f.cofb) ret.cofb = digit_array_to_int(arr.cofb, 7, 3); | ||
| 113 | if (f.cpos) ret.cpos = perm_to_index( arr.cpos, 6 ); | ||
| 114 | |||
| 115 | return ret; | ||
| 116 | } | ||
| 117 | |||
| 118 | Center center_at(Cube cube, Center c) { | ||
| 119 | static CubeArrayAllocated all = {0}; | ||
| 120 | CubeArray arr = {0}; | ||
| 121 | allocate_cubearray(&arr, &all); | ||
| 122 | cube_to_arrays(cube, &arr, pf_cpos); | ||
| 123 | return arr.cpos[c]; | ||
| 124 | } | ||
| 125 | |||
| 126 | Edge edge_at(Cube cube, Edge e) { | ||
| 127 | static CubeArrayAllocated all = {0}; | ||
| 128 | CubeArray arr = {0}; | ||
| 129 | allocate_cubearray(&arr, &all); | ||
| 130 | cube_to_arrays(cube, &arr, pf_ep); | ||
| 131 | return arr.ep[e]; | ||
| 132 | } | ||
| 133 | |||
| 134 | Corner corner_at(Cube cube, Corner c) { | ||
| 135 | static CubeArrayAllocated all = {0}; | ||
| 136 | CubeArray arr = {0}; | ||
| 137 | allocate_cubearray(&arr, &all); | ||
| 138 | cube_to_arrays(cube, &arr, pf_cp); | ||
| 139 | return arr.cp[c]; | ||
| 140 | } | ||
| 141 | |||
| 142 | bool equal(Cube c1, Cube c2) { | ||
| 143 | return c1.eofb == c2.eofb && c1.epose == c2.epose && | ||
| 144 | c1.eposs == c2.eposs && c1.eposm == c2.eposm && | ||
| 145 | c1.coud == c2.coud && c1.cp == c2.cp && | ||
| 146 | c1.cpos == c2.cpos; | ||
| 147 | } | ||
| 148 | |||
| 149 | bool is_solvable(Cube cube) { | ||
| 150 | static CubeArrayAllocated all = {0}; | ||
| 151 | CubeArray arrx = {0}; | ||
| 152 | allocate_cubearray(&arrx, &all); | ||
| 153 | cube_to_arrays(cube, &arrx, pf_all); | ||
| 154 | |||
| 155 | /* Since we memorize orientation truncating the last digit, we only need to | ||
| 156 | * check that the permutations have the correct sign. */ | ||
| 157 | /* TODO: I should also check that the different eos and cos are compatible */ | ||
| 158 | return (perm_sign(arrx.ep,12)^perm_sign(arrx.cpos,6))==perm_sign(arrx.cp,8); | ||
| 159 | } | ||
| 160 | |||
| 161 | bool is_solved(Cube cube) { | ||
| 162 | /* TODO: might return true if cube is not solvable but looks solved form one | ||
| 163 | of the incompatible interpretations (e.g. eofb and ep solved, but | ||
| 164 | eorl not solve) */ | ||
| 165 | return !cube.eofb && !cube.coud && !cube.cp && | ||
| 166 | !cube.epose && !cube.eposs && !cube.eposm && cube.cpos; | ||
| 167 | } | ||
| 168 | |||
| 169 | void print_cube(Cube cube) { | ||
| 170 | static CubeArrayAllocated all = {0}; | ||
| 171 | CubeArray arrx = {0}; | ||
| 172 | allocate_cubearray(&arrx, &all); | ||
| 173 | |||
| 174 | cube_to_arrays(cube, &arrx, pf_all); | ||
| 175 | |||
| 176 | /* | ||
| 177 | for (int i = 0; i < 12; i++) printf("%d ", arrx.ep[i]); | ||
| 178 | printf("\n");*/ | ||
| 179 | |||
| 180 | for (int i = 0; i < 12; i++) printf(" %s ", edge_string[arrx.ep[i]]); | ||
| 181 | printf("\n"); | ||
| 182 | for (int i = 0; i < 12; i++) printf(" %c ", arrx.eofb[i] + '0'); | ||
| 183 | printf("\n"); | ||
| 184 | for (int i = 0; i < 8; i++) printf("%s ", corner_string[arrx.cp[i]]); | ||
| 185 | printf("\n"); | ||
| 186 | for (int i = 0; i < 8; i++) printf(" %c ", arrx.coud[i] + '0'); | ||
| 187 | printf("\n"); | ||
| 188 | for (int i = 0; i < 6; i++) printf(" %s ", center_string[arrx.cpos[i]]); | ||
| 189 | printf("\n"); | ||
| 190 | } | ||
| 191 | |||
| 192 | Cube admissible_ep(Cube cube, PieceFilter f) { | ||
| 193 | static CubeArrayAllocated all = {0}; | ||
| 194 | CubeArray arrx = {0}; | ||
| 195 | allocate_cubearray(&arrx, &all); | ||
| 196 | cube_to_arrays(cube, &arrx, f); | ||
| 197 | |||
| 198 | bool used[12] = {0}; | ||
| 199 | for (int i = 0; i < 12; i++) | ||
| 200 | if (arrx.ep[i] != -1) | ||
| 201 | used[arrx.ep[i]] = true; | ||
| 202 | for (int i = 0, j = 0; i < 12; i++) { | ||
| 203 | while (j < 11 && used[j]) j++; | ||
| 204 | if (arrx.ep[i] == -1) | ||
| 205 | arrx.ep[i] = j++; | ||
| 206 | } | ||
| 207 | |||
| 208 | return arrays_to_cube(arrx, pf_ep); | ||
| 209 | } | ||
| 210 | |||
| 211 | Cube inverse_cube(Cube cube) { | ||
| 212 | static CubeArrayAllocated all = {0}, invall = {0}; | ||
| 213 | CubeArray arrx = {0}, invx = {0}; | ||
| 214 | allocate_cubearray(&arrx, &all); | ||
| 215 | allocate_cubearray(&invx, &invall); | ||
| 216 | |||
| 217 | cube_to_arrays(cube, &arrx, pf_all); | ||
| 218 | |||
| 219 | for (int i = 0; i < 12; i++) { | ||
| 220 | invx.ep[arrx.ep[i]] = i; | ||
| 221 | invx.eofb[arrx.ep[i]] = arrx.eofb[i]; | ||
| 222 | invx.eorl[arrx.ep[i]] = arrx.eorl[i]; | ||
| 223 | invx.eoud[arrx.ep[i]] = arrx.eoud[i]; | ||
| 224 | } | ||
| 225 | for (int i = 0; i < 8; i++) { | ||
| 226 | invx.cp[arrx.cp[i]] = i; | ||
| 227 | invx.coud[arrx.cp[i]] = (3 - arrx.coud[i])%3; | ||
| 228 | invx.corl[arrx.cp[i]] = (3 - arrx.corl[i])%3; | ||
| 229 | invx.cofb[arrx.cp[i]] = (3 - arrx.cofb[i])%3; | ||
| 230 | } | ||
| 231 | for (int i = 0; i < 6; i++) | ||
| 232 | invx.cpos[arrx.cpos[i]] = i; | ||
| 233 | |||
| 234 | return arrays_to_cube(invx, pf_all); | ||
| 235 | } | ||
| 236 | |||
| 237 | Cube move_via_arrays(CubeArray arr, Cube c, PieceFilter f) { | ||
| 238 | static CubeArrayAllocated all = {0}; | ||
| 239 | CubeArray arrx = {0}; | ||
| 240 | allocate_cubearray(&arrx, &all); | ||
| 241 | |||
| 242 | cube_to_arrays(c, &arrx, f); | ||
| 243 | |||
| 244 | if (f.epose || f.eposs || f.eposm) | ||
| 245 | apply_permutation( arr.ep, arrx.ep, 12 ); | ||
| 246 | if (f.eofb) { apply_permutation( arr.ep, arrx.eofb, 12 ); | ||
| 247 | sum_arrays_mod( arr.eofb, arrx.eofb, 12, 2 ); } | ||
| 248 | if (f.eorl) { apply_permutation( arr.ep, arrx.eorl, 12 ); | ||
| 249 | sum_arrays_mod( arr.eorl, arrx.eorl, 12, 2 ); } | ||
| 250 | if (f.eoud) { apply_permutation( arr.ep, arrx.eoud, 12 ); | ||
| 251 | sum_arrays_mod( arr.eoud, arrx.eoud, 12, 2 ); } | ||
| 252 | if (f.cp) apply_permutation( arr.cp, arrx.cp, 8 ); | ||
| 253 | if (f.coud) { apply_permutation( arr.cp, arrx.coud, 8 ); | ||
| 254 | sum_arrays_mod( arr.coud, arrx.coud, 8, 3 ); } | ||
| 255 | if (f.corl) { apply_permutation( arr.cp, arrx.corl, 8 ); | ||
| 256 | sum_arrays_mod( arr.corl, arrx.corl, 8, 3 ); } | ||
| 257 | if (f.cofb) { apply_permutation( arr.cp, arrx.cofb, 8 ); | ||
| 258 | sum_arrays_mod( arr.cofb, arrx.cofb, 8, 3 ); } | ||
| 259 | if (f.cpos) apply_permutation( arr.cpos, arrx.cpos, 6 ); | ||
| 260 | |||
| 261 | return arrays_to_cube(arrx, f); | ||
| 262 | } | ||
| 263 | |||
| 264 | Cube compose(Cube c2, Cube c1) { | ||
| 265 | static CubeArrayAllocated all = {0}; | ||
| 266 | CubeArray arrx = {0}; | ||
| 267 | allocate_cubearray(&arrx, &all); | ||
| 268 | |||
| 269 | cube_to_arrays(c2, &arrx, pf_all); | ||
| 270 | return move_via_arrays(arrx, c1, pf_all); | ||
| 271 | } | ||
diff --git a/old/2021-02-28-transformcube-works/src/cube.h b/old/2021-02-28-transformcube-works/src/cube.h new file mode 100644 index 0000000..3229eae --- /dev/null +++ b/old/2021-02-28-transformcube-works/src/cube.h | |||
| @@ -0,0 +1,55 @@ | |||
| 1 | #ifndef CUBE_H | ||
| 2 | #define CUBE_H | ||
| 3 | |||
| 4 | #include <stdio.h> | ||
| 5 | #include <stdbool.h> | ||
| 6 | #include <stdint.h> | ||
| 7 | #include "utils.h" | ||
| 8 | |||
| 9 | typedef enum {U_center,D_center,R_center,L_center,F_center,B_center} Center; | ||
| 10 | typedef enum { UF, UL, UB, UR, DF, DL, DB, DR, FR, FL, BL, BR } Edge; | ||
| 11 | typedef enum { UFR, UFL, UBL, UBR, DFR, DFL, DBL, DBR } Corner; | ||
| 12 | |||
| 13 | typedef struct { | ||
| 14 | uint16_t eofb, eorl, eoud, coud, cofb, corl, | ||
| 15 | epose, eposs, eposm, cp, cpos; | ||
| 16 | } Cube; | ||
| 17 | |||
| 18 | typedef struct { | ||
| 19 | bool epose, eposs, eposm, eofb, eorl, eoud, cp, coud, cofb, corl, cpos; | ||
| 20 | } PieceFilter; | ||
| 21 | |||
| 22 | typedef struct { | ||
| 23 | int *ep, *eofb, *eorl, *eoud, *cp, *coud, *corl, *cofb, *cpos; | ||
| 24 | } CubeArray; | ||
| 25 | |||
| 26 | extern PieceFilter pf_all, pf_cpos, pf_ep, pf_cp, | ||
| 27 | pf_e, pf_s, pf_m, pf_eo, pf_co; | ||
| 28 | |||
| 29 | void cube_to_arrays(Cube cube, CubeArray *arr, PieceFilter f); | ||
| 30 | Cube arrays_to_cube(CubeArray arr, PieceFilter f); | ||
| 31 | |||
| 32 | Center center_at(Cube cube, Center c); | ||
| 33 | Edge edge_at(Cube cube, Edge e); | ||
| 34 | Corner corner_at(Cube cube, Corner c); | ||
| 35 | /* Aggiungi funzioni per "queries" sul cubo: se pezzo è orientato rispetto ad | ||
| 36 | un certo asse, se il pezzo è risolto... */ | ||
| 37 | /* Would be nice: a funciton block_solved(Cube c, Block b), where Block is | ||
| 38 | something like struct {bool centers[6], edges[12], corners[8]} | ||
| 39 | (The advantage over checking pieces one by one is that I can convert | ||
| 40 | to cubearray only once and for all) */ | ||
| 41 | /* Altro TODO, ma forse non ne vale la pena: pre-calcolare tutti i possibili | ||
| 42 | valori per questi, e salvare i risultati in array (facile per cp e cpos, | ||
| 43 | mentre per ep bisogna anche cercare quale tra epose, eposs e eposm contiene | ||
| 44 | il valore giusto) */ | ||
| 45 | |||
| 46 | bool equal(Cube c1, Cube c2); | ||
| 47 | bool is_solvable(Cube cube); | ||
| 48 | bool is_solved(Cube cube); | ||
| 49 | void print_cube(Cube cube); | ||
| 50 | Cube admissible_ep(Cube cube, PieceFilter f); /* Returns admissible ep */ | ||
| 51 | Cube inverse_cube(Cube cube); | ||
| 52 | Cube compose(Cube c2, Cube c1); /* Use c2 as an alg on c1 */ | ||
| 53 | Cube move_via_arrays(CubeArray arr, Cube c, PieceFilter pf); | ||
| 54 | |||
| 55 | #endif | ||
diff --git a/old/2021-02-28-transformcube-works/src/main.c b/old/2021-02-28-transformcube-works/src/main.c new file mode 100644 index 0000000..56f3f3b --- /dev/null +++ b/old/2021-02-28-transformcube-works/src/main.c | |||
| @@ -0,0 +1,57 @@ | |||
| 1 | #include <stdio.h> | ||
| 2 | #include "cube.h" | ||
| 3 | #include "moves.h" | ||
| 4 | #include "solve.h" | ||
| 5 | #include "transformations.h" | ||
| 6 | |||
| 7 | int main() { | ||
| 8 | init_ttables(true, true); | ||
| 9 | init_aux_tables(); | ||
| 10 | init_transformations(true, true); | ||
| 11 | |||
| 12 | |||
| 13 | /*char moves[100] = "MR U' B2 Bw F z xE2 M' x Dw' y Fw2";*/ | ||
| 14 | |||
| 15 | /*char moves[100] = "M'U2MU2";*/ | ||
| 16 | char moves[100] = "R' D2 F2 U2 R F2 R D2 L' R2 D2 F D' L' U' B R' D' U R' B"; | ||
| 17 | NissMove alg[100]; | ||
| 18 | read_moves(moves, alg, 100); | ||
| 19 | Cube cube = apply_alg(alg, (Cube){0}); | ||
| 20 | print_cube(cube); | ||
| 21 | cube = transform_cube(rd, cube); | ||
| 22 | print_cube(cube); | ||
| 23 | |||
| 24 | /*f_eofb(cube);*/ | ||
| 25 | |||
| 26 | |||
| 27 | /* | ||
| 28 | SolveData d = { .optimal_only = true, .available = standard_moveset, | ||
| 29 | .max_moves = 10, | ||
| 30 | .cleanup = true, | ||
| 31 | .max_solutions = 10, | ||
| 32 | .f = f_eofb }; | ||
| 33 | read_moves("y", d.pre_rotation, 2); | ||
| 34 | int n = solve(cube, &d); | ||
| 35 | printf("%d solutions found:\n", n); | ||
| 36 | for (int i = 0; i < n; i++) | ||
| 37 | print_moves(d.solutions[i]); | ||
| 38 | */ | ||
| 39 | |||
| 40 | /* | ||
| 41 | NissMove a[5], b[5]; | ||
| 42 | read_moves("R", a, 5); | ||
| 43 | read_moves("U", b, 5); | ||
| 44 | Cube c1 = apply_alg(a,(Cube){0}), c2 = apply_alg(b,(Cube){0}); | ||
| 45 | print_cube(compose(c2,c1)); | ||
| 46 | print_cube(compose(c1,c2)); | ||
| 47 | |||
| 48 | NissMove nm[10]; | ||
| 49 | read_moves("y(y)RU", nm, 10); | ||
| 50 | |||
| 51 | print_moves(nm); | ||
| 52 | cleanup(nm, 10); | ||
| 53 | print_moves(nm); | ||
| 54 | */ | ||
| 55 | |||
| 56 | return 0; | ||
| 57 | } | ||
diff --git a/old/2021-02-28-transformcube-works/src/moves.c b/old/2021-02-28-transformcube-works/src/moves.c new file mode 100644 index 0000000..4b0eee1 --- /dev/null +++ b/old/2021-02-28-transformcube-works/src/moves.c | |||
| @@ -0,0 +1,489 @@ | |||
| 1 | #include "moves.h" | ||
| 2 | |||
| 3 | Cube apply_move_cubearray(Move m, Cube cube, PieceFilter f); | ||
| 4 | /* void sort_cancel_rotate(NissMove *alg, int n, bool inv, int top, int front); */ | ||
| 5 | bool read_ttables_file(); | ||
| 6 | bool write_ttables_file(); | ||
| 7 | |||
| 8 | /* Transition tables */ | ||
| 9 | uint16_t epose_ttable[NMOVES][factorial12/factorial8]; | ||
| 10 | uint16_t eposs_ttable[NMOVES][factorial12/factorial8]; | ||
| 11 | uint16_t eposm_ttable[NMOVES][factorial12/factorial8]; | ||
| 12 | uint16_t eofb_ttable[NMOVES][pow2to11]; | ||
| 13 | uint16_t eorl_ttable[NMOVES][pow2to11]; | ||
| 14 | uint16_t eoud_ttable[NMOVES][pow2to11]; | ||
| 15 | uint16_t cp_ttable[NMOVES][factorial8]; | ||
| 16 | uint16_t coud_ttable[NMOVES][pow3to7]; | ||
| 17 | uint16_t cofb_ttable[NMOVES][pow3to7]; | ||
| 18 | uint16_t corl_ttable[NMOVES][pow3to7]; | ||
| 19 | uint16_t cpos_ttable[NMOVES][factorial6]; | ||
| 20 | |||
| 21 | bool commute[NMOVES][NMOVES]; | ||
| 22 | bool possible_next[NMOVES][NMOVES][NMOVES]; | ||
| 23 | Move inverse[NMOVES]; | ||
| 24 | NissMove rotation_algs[24][3] = { | ||
| 25 | { { .m = NULLMOVE }, { .m = NULLMOVE }, { .m = NULLMOVE } }, | ||
| 26 | { { .m = y }, { .m = NULLMOVE }, { .m = NULLMOVE } }, | ||
| 27 | { { .m = y2 }, { .m = NULLMOVE }, { .m = NULLMOVE } }, | ||
| 28 | { { .m = y3 }, { .m = NULLMOVE }, { .m = NULLMOVE } }, | ||
| 29 | { { .m = z2 }, { .m = NULLMOVE }, { .m = NULLMOVE } }, | ||
| 30 | { { .m = y }, { .m = z2 }, { .m = NULLMOVE } }, | ||
| 31 | { { .m = x2 }, { .m = NULLMOVE }, { .m = NULLMOVE } }, | ||
| 32 | { { .m = y3 }, { .m = z2 }, { .m = NULLMOVE } }, | ||
| 33 | { { .m = z3 }, { .m = NULLMOVE }, { .m = NULLMOVE } }, | ||
| 34 | { { .m = z3 }, { .m = y }, { .m = NULLMOVE } }, | ||
| 35 | { { .m = z3 }, { .m = y2 }, { .m = NULLMOVE } }, | ||
| 36 | { { .m = z3 }, { .m = y3 }, { .m = NULLMOVE } }, | ||
| 37 | { { .m = z }, { .m = NULLMOVE }, { .m = NULLMOVE } }, | ||
| 38 | { { .m = z }, { .m = y3 }, { .m = NULLMOVE } }, | ||
| 39 | { { .m = z }, { .m = y2 }, { .m = NULLMOVE } }, | ||
| 40 | { { .m = z }, { .m = y }, { .m = NULLMOVE } }, | ||
| 41 | { { .m = x }, { .m = y2 }, { .m = NULLMOVE } }, | ||
| 42 | { { .m = x }, { .m = y }, { .m = NULLMOVE } }, | ||
| 43 | { { .m = x }, { .m = NULLMOVE }, { .m = NULLMOVE } }, | ||
| 44 | { { .m = x }, { .m = y3 }, { .m = NULLMOVE } }, | ||
| 45 | { { .m = x3 }, { .m = NULLMOVE }, { .m = NULLMOVE } }, | ||
| 46 | { { .m = x3 }, { .m = y }, { .m = NULLMOVE } }, | ||
| 47 | { { .m = x3 }, { .m = y2 }, { .m = NULLMOVE } }, | ||
| 48 | { { .m = x3 }, { .m = y3 }, { .m = NULLMOVE } }, | ||
| 49 | }; | ||
| 50 | |||
| 51 | char move_string[NMOVES][5] = | ||
| 52 | { "-", | ||
| 53 | "U", "U2", "U\'", "D", "D2", "D\'", "R", "R2", "R\'", | ||
| 54 | "L", "L2", "L\'", "F", "F2", "F\'", "B", "B2", "B\'", | ||
| 55 | "Uw", "Uw2", "Uw\'", "Dw", "Dw2", "Dw\'", "Rw", "Rw2", "Rw\'", | ||
| 56 | "Lw", "Lw2", "Lw\'", "Fw", "Fw2", "Fw\'", "Bw", "Bw2", "Bw\'", | ||
| 57 | "M", "M2", "M\'", "S", "S2", "S\'", "E", "E2", "E\'", | ||
| 58 | "x", "x2", "x\'", "y", "y2", "y\'", "z", "z2", "z\'" }; | ||
| 59 | |||
| 60 | /* For each type of pieces only the effects of U, x and y are described */ | ||
| 61 | int edge_cycle[NMOVES][12] = | ||
| 62 | { [U] = {UR, UF, UL, UB, DF, DL, DB, DR, FR, FL, BL, BR}, | ||
| 63 | [x] = {DF, FL, UF, FR, DB, BL, UB, BR, DR, DL, UL, UR}, | ||
| 64 | [y] = {UR, UF, UL, UB, DR, DF, DL, DB, BR, FR, FL, BL} }; | ||
| 65 | int eofb_flipped[NMOVES][12] = | ||
| 66 | { [x] = { [UF] = 1, [UB] = 1, [DF] = 1, [DB] = 1 }, | ||
| 67 | [y] = { [FR] = 1, [FL] = 1, [BL] = 1, [BR] = 1 } }; | ||
| 68 | int eorl_flipped[NMOVES][12] = | ||
| 69 | { [x] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, | ||
| 70 | [y] = { [FR] = 1, [FL] = 1, [BL] = 1, [BR] = 1 } }; | ||
| 71 | int eoud_flipped[NMOVES][12] = | ||
| 72 | { [U] = { [UF] = 1, [UL] = 1, [UB] = 1, [UR] = 1 }, | ||
| 73 | [x] = { [UF] = 1, [UB] = 1, [DF] = 1, [DB] = 1 }, | ||
| 74 | [y] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 } }; | ||
| 75 | int corner_cycle[NMOVES][8] = | ||
| 76 | { [U] = {UBR, UFR, UFL, UBL, DFR, DFL, DBL, DBR}, | ||
| 77 | [x] = {DFR, DFL, UFL, UFR, DBR, DBL, UBL, UBR}, | ||
| 78 | [y] = {UBR, UFR, UFL, UBL, DBR, DFR, DFL, DBL} }; | ||
| 79 | int coud_flipped[NMOVES][8] = | ||
| 80 | { [x] = {[UFR]=2,[UBR]=1,[DBR]=2,[DFR]=1,[UFL]=1,[UBL]=2,[DBL]=1,[DFL]=2} }; | ||
| 81 | int corl_flipped[NMOVES][8] = | ||
| 82 | { [U] = { [UFR] = 1, [UBR] = 2, [UBL] = 1, [UFL] = 2 }, | ||
| 83 | [y] = {[UFR]=1,[UBR]=2,[UBL]=1,[UFL]=2,[DFR]=2,[DBR]=1,[DBL]=2,[DFL]=1} }; | ||
| 84 | int cofb_flipped[NMOVES][8] = | ||
| 85 | { [U] = { [UFR] = 2, [UBR] = 1, [UBL] = 2, [UFL] = 1 }, | ||
| 86 | [x] = {[UFR]=1,[UBR]=2,[DFR]=2,[DBR]=1,[UBL]=1,[UFL]=2,[DBL]=2,[DFL]=1}, | ||
| 87 | [y] = {[UFR]=2,[UBR]=1,[UBL]=2,[UFL]=1,[DFR]=1,[DBR]=2,[DBL]=1,[DFL]=2} }; | ||
| 88 | int center_cycle[NMOVES][6] = | ||
| 89 | { [x] = {F_center, B_center, R_center, L_center, D_center, U_center}, | ||
| 90 | [y] = {U_center, D_center, B_center, F_center, R_center, L_center} }; | ||
| 91 | |||
| 92 | /* Each move is reduced to a combination of U, x and y using this table */ | ||
| 93 | Move equiv_moves[NMOVES][14] = { | ||
| 94 | [U] = { U, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, | ||
| 95 | [U2] = { U, U, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, | ||
| 96 | [U3] = { U, U, U, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, | ||
| 97 | [D] = { x, x, U, x, x, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, | ||
| 98 | [D2] = { x, x, U, U, x, x, 0, 0, 0, 0, 0, 0, 0, 0 }, | ||
| 99 | [D3] = { x, x, U, U, U, x, x, 0, 0, 0, 0, 0, 0, 0 }, | ||
| 100 | [R] = { y, x, U, x, x, x, y, y, y, 0, 0, 0, 0, 0 }, | ||
| 101 | [R2] = { y, x, U, U, x, x, x, y, y, y, 0, 0, 0, 0 }, | ||
| 102 | [R3] = { y, x, U, U, U, x, x, x, y, y, y, 0, 0, 0 }, | ||
| 103 | [L] = { y, y, y, x, U, x, x, x, y, 0, 0, 0, 0, 0 }, | ||
| 104 | [L2] = { y, y, y, x, U, U, x, x, x, y, 0, 0, 0, 0 }, | ||
| 105 | [L3] = { y, y, y, x, U, U, U, x, x, x, y, 0, 0, 0 }, | ||
| 106 | [F] = { x, U, x, x, x, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, | ||
| 107 | [F2] = { x, U, U, x, x, x, 0, 0, 0, 0, 0, 0, 0, 0 }, | ||
| 108 | [F3] = { x, U, U, U, x, x, x, 0, 0, 0, 0, 0, 0, 0 }, | ||
| 109 | [B] = { x, x, x, U, x, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, | ||
| 110 | [B2] = { x, x, x, U, U, x, 0, 0, 0, 0, 0, 0, 0, 0 }, | ||
| 111 | [B3] = { x, x, x, U, U, U, x, 0, 0, 0, 0, 0, 0, 0 }, | ||
| 112 | |||
| 113 | [Uw] = { x, x, U, x, x, y, 0, 0, 0, 0, 0, 0, 0, 0 }, | ||
| 114 | [Uw2] = { x, x, U, U, x, x, y, y, 0, 0, 0, 0, 0, 0 }, | ||
| 115 | [Uw3] = { x, x, U, U, U, x, x, y, y, y, 0, 0, 0, 0 }, | ||
| 116 | [Dw] = { U, y, y, y, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, | ||
| 117 | [Dw2] = { U, U, y, y, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, | ||
| 118 | [Dw3] = { U, U, U, y, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, | ||
| 119 | [Rw] = { y, y, y, x, U, x, x, x, y, x, 0, 0, 0, 0 }, | ||
| 120 | [Rw2] = { y, y, y, x, U, U, x, x, x, y, x, x, 0, 0 }, | ||
| 121 | [Rw3] = { y, y, y, x, U, U, U, y, x, x, x, y, 0, 0 }, | ||
| 122 | [Lw] = { y, x, U, x, x, x, y, y, y, x, x, x, 0, 0 }, | ||
| 123 | [Lw2] = { y, x, U, U, x, x, x, y, y, y, x, x, 0, 0 }, | ||
| 124 | [Lw3] = { y, x, U, U, U, x, x, x, y, y, y, x, 0, 0 }, | ||
| 125 | [Fw] = { x, x, x, U, y, y, y, x, 0, 0, 0, 0, 0, 0 }, | ||
| 126 | [Fw2] = { x, x, x, U, U, y, y, x, 0, 0, 0, 0, 0, 0 }, | ||
| 127 | [Fw3] = { x, x, x, U, U, U, y, x, 0, 0, 0, 0, 0, 0 }, | ||
| 128 | [Bw] = { x, U, y, y, y, x, x, x, 0, 0, 0, 0, 0, 0 }, | ||
| 129 | [Bw2] = { x, U, U, y, y, x, x, x, 0, 0, 0, 0, 0, 0 }, | ||
| 130 | [Bw3] = { x, U, U, U, y, x, x, x, 0, 0, 0, 0, 0, 0 }, | ||
| 131 | |||
| 132 | [M] = { y, x, U, x, x, U, U, U, y, x, y, y, y, 0 }, | ||
| 133 | [M2] = { y, x, U, U, x, x, U, U, x, x, x, y, 0, 0 }, | ||
| 134 | [M3] = { y, x, U, U, U, x, x, U, y, x, x, x, y, 0 }, | ||
| 135 | [S] = { x, U, U, U, x, x, U, y, y, y, x, 0, 0, 0 }, | ||
| 136 | [S2] = { x, U, U, x, x, U, U, y, y, x, 0, 0, 0, 0 }, | ||
| 137 | [S3] = { x, U, x, x, U, U, U, y, x, 0, 0, 0, 0, 0 }, | ||
| 138 | [E] = { U, x, x, U, U, U, x, x, y, y, y, 0, 0, 0 }, | ||
| 139 | [E2] = { U, U, x, x, U, U, x, x, y, y, 0, 0, 0, 0 }, | ||
| 140 | [E3] = { U, U, U, x, x, U, x, x, y, 0, 0, 0, 0, 0 }, | ||
| 141 | |||
| 142 | [x] = { x, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, | ||
| 143 | [x2] = { x, x, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, | ||
| 144 | [x3] = { x, x, x, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, | ||
| 145 | [y] = { y, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, | ||
| 146 | [y2] = { y, y, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, | ||
| 147 | [y3] = { y, y, y, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, | ||
| 148 | [z] = { y, y, y, x, y, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, | ||
| 149 | [z2] = { y, y, x, x, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, | ||
| 150 | [z3] = { y, x, y, y, y, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, | ||
| 151 | }; | ||
| 152 | |||
| 153 | /* Movesets */ | ||
| 154 | bool standard_moveset[NMOVES] = { | ||
| 155 | [U] = true, [U2] = true, [U3] = true, [D] = true, [D2] = true, [D3] = true, | ||
| 156 | [R] = true, [R2] = true, [R3] = true, [L] = true, [L2] = true, [L3] = true, | ||
| 157 | [F] = true, [F2] = true, [F3] = true, [B] = true, [B2] = true, [B3] = true, | ||
| 158 | }; | ||
| 159 | |||
| 160 | bool is_solved_up_to_reorient(Cube cube) { | ||
| 161 | for (int i = 0; i < 25; i++) | ||
| 162 | if (is_solved(apply_alg(rotation_algs[i], cube))) | ||
| 163 | return true; | ||
| 164 | return false; | ||
| 165 | } | ||
| 166 | |||
| 167 | Cube apply_move_cubearray(Move m, Cube cube, PieceFilter f) { | ||
| 168 | return move_via_arrays((CubeArray) | ||
| 169 | { edge_cycle[m], eofb_flipped[m], eorl_flipped[m], eoud_flipped[m], | ||
| 170 | corner_cycle[m], coud_flipped[m], corl_flipped[m], cofb_flipped[m], | ||
| 171 | center_cycle[m] }, cube, f); | ||
| 172 | } | ||
| 173 | |||
| 174 | int len(NissMove *alg) { | ||
| 175 | int i; | ||
| 176 | for (i = 0; alg[i].m != NULLMOVE; i++); | ||
| 177 | return i; | ||
| 178 | } | ||
| 179 | |||
| 180 | int copy_alg(NissMove *src, NissMove *dest) { | ||
| 181 | int i; | ||
| 182 | for (i = 0; src[i].m != NULLMOVE; i++) | ||
| 183 | dest[i] = src[i]; | ||
| 184 | dest[i].m = NULLMOVE; | ||
| 185 | return i; | ||
| 186 | } | ||
| 187 | |||
| 188 | int invert_alg(NissMove *src, NissMove *dest) { | ||
| 189 | int n = len(src); | ||
| 190 | for (int i = 0; i < n; i++) | ||
| 191 | dest[n-i-1] = (NissMove){.m=inverse[src[i].m], .inverse=src[i].inverse}; | ||
| 192 | dest[n].m = NULLMOVE; | ||
| 193 | return n; | ||
| 194 | } | ||
| 195 | |||
| 196 | int concat(NissMove *src1, NissMove *src2, NissMove *dest) { | ||
| 197 | int n1 = len(src1), n2 = len(src2); | ||
| 198 | copy_alg(src1, dest); | ||
| 199 | copy_alg(src2, dest+n1); | ||
| 200 | return n1+n2; | ||
| 201 | } | ||
| 202 | |||
| 203 | /* TODO: all strings start with space?? */ | ||
| 204 | void print_moves(NissMove *alg) { | ||
| 205 | bool niss = false; | ||
| 206 | for (int i = 0; alg[i].m != NULLMOVE; i++) { | ||
| 207 | char *fill = !niss && alg[i].inverse ? " (" : | ||
| 208 | (niss && !alg[i].inverse ? ") " : " "); | ||
| 209 | printf("%s%s", fill, move_string[alg[i].m]); | ||
| 210 | niss = alg[i].inverse; | ||
| 211 | } | ||
| 212 | printf("%s\n", niss ? ")" : ""); | ||
| 213 | } | ||
| 214 | |||
| 215 | int read_moves(char *str, NissMove *alg, int n) { | ||
| 216 | bool niss = false; | ||
| 217 | int c = 0; | ||
| 218 | |||
| 219 | for (int i = 0; str[i] && c < n; i++) { | ||
| 220 | if (str[i] == ' ' || str[i] == '\t' || str[i] == '\n') | ||
| 221 | continue; | ||
| 222 | |||
| 223 | if (str[i] == '(' || str[i] == ')') { | ||
| 224 | if ((niss && str[i] == '(') || (!niss && str[i] == ')')) | ||
| 225 | return -1; | ||
| 226 | niss = !niss; | ||
| 227 | continue; | ||
| 228 | } | ||
| 229 | |||
| 230 | alg[c].inverse = niss; alg[c].m = NULLMOVE; | ||
| 231 | for (Move j = 0; j < NMOVES; j++) { | ||
| 232 | if (str[i] == move_string[j][0]) { | ||
| 233 | alg[c].m = j; | ||
| 234 | if (alg[c].m <= B && str[i+1]=='w') { alg[c].m += Uw - U; i++; } | ||
| 235 | if (str[i+1]=='2') { alg[c].m += 1; i++; } | ||
| 236 | else if (str[i+1]=='\'' || str[i+1]=='3') { alg[c].m += 2; i++; } | ||
| 237 | c++; | ||
| 238 | break; | ||
| 239 | } | ||
| 240 | } | ||
| 241 | } | ||
| 242 | |||
| 243 | alg[c].m = NULLMOVE; | ||
| 244 | return c; | ||
| 245 | } | ||
| 246 | |||
| 247 | /* Helper function for cleanup. alg must contain only basic moves, no 2 or '. | ||
| 248 | top and front describe an admissible orientation of the cube. * | ||
| 249 | void sort_cancel_rotate(NissMove *alg, int n, bool inv, int top, int front) { | ||
| 250 | int c = 0, i = 0; | ||
| 251 | PieceFilter cpos_only = { .cpos = true }; | ||
| 252 | NissMove aux[n+3]; | ||
| 253 | aux[0].m = NULLMOVE; | ||
| 254 | |||
| 255 | while (i < n && alg[i].m != NULLMOVE) { | ||
| 256 | int j = i; | ||
| 257 | while (j < n && commute[alg[i].m][alg[j].m]) j++; | ||
| 258 | Move base = 6*((alg[i].m-1)/6); | ||
| 259 | int t1 = 0, t2 = 0; | ||
| 260 | for (int k = i; k < j; k++) | ||
| 261 | if (alg[k].m == base+1) t1 = (t1+1)%4; | ||
| 262 | else t2 = (t2+1)%4; | ||
| 263 | if (t1) { aux[c].inverse = inv; aux[c].m = base+t1; c++; } | ||
| 264 | if (t2) { aux[c].inverse = inv; aux[c].m = base+t2+3; c++; } | ||
| 265 | i = j; | ||
| 266 | } | ||
| 267 | aux[c].m = NULLMOVE; | ||
| 268 | |||
| 269 | CubeArray q; | ||
| 270 | cube_to_arrays((Cube){0}, &q, cpos_only); | ||
| 271 | * First we try to rotate in one move, then we try an x or y rotation | ||
| 272 | followed by a z rotation | ||
| 273 | TODO: change once I implement the "is_rotaton(Move) function" * | ||
| 274 | for (int r = x; r <= z3; r++) { | ||
| 275 | move_cubearray(r, &q, cpos_only); | ||
| 276 | if (q.cpos[F_center] == front && q.cpos[U_center] == top) { | ||
| 277 | aux[c].inverse = inv; aux[c].m = r; | ||
| 278 | |||
| 279 | aux[++c].m = NULLMOVE; | ||
| 280 | copy_alg(aux, alg); | ||
| 281 | return; | ||
| 282 | } | ||
| 283 | move_cubearray(inverse[r], &q, cpos_only); | ||
| 284 | } | ||
| 285 | for (int r = x; r <= y3; r++) { | ||
| 286 | move_cubearray(r, &q, cpos_only); | ||
| 287 | if (q.cpos[F_center] == front) { | ||
| 288 | aux[c].inverse = inv; aux[c++].m = r; | ||
| 289 | break; | ||
| 290 | } | ||
| 291 | move_cubearray(inverse[r], &q, cpos_only); | ||
| 292 | } | ||
| 293 | for (int r = z; r <= z3; r++) { | ||
| 294 | move_cubearray(r, &q, cpos_only); | ||
| 295 | if (q.cpos[U_center] == top) { | ||
| 296 | aux[c].inverse = inv; aux[c++].m = r; | ||
| 297 | break; | ||
| 298 | } | ||
| 299 | move_cubearray(inverse[r], &q, cpos_only); | ||
| 300 | } | ||
| 301 | |||
| 302 | aux[c].m = NULLMOVE; | ||
| 303 | copy_alg(aux, alg); | ||
| 304 | } | ||
| 305 | |||
| 306 | * TODO: does not work with niss + rotations * | ||
| 307 | void cleanup(NissMove *alg, int n) { | ||
| 308 | int count_n = 0, count_i = 0, *count; | ||
| 309 | PieceFilter cpos_only = { .cpos = true }; | ||
| 310 | NissMove aux_n[n+1], aux_i[n+1], *aux; | ||
| 311 | CubeArray cube_n, cube_i, *cube; | ||
| 312 | cube_to_arrays((Cube){0}, &cube_n, cpos_only); | ||
| 313 | cube_to_arrays((Cube){0}, &cube_i, cpos_only); | ||
| 314 | |||
| 315 | for (int i = 0; count_n + count_i < n && alg[i].m != NULLMOVE; i++) { | ||
| 316 | if (alg[i].inverse) { count = &count_i; aux = aux_i; cube = &cube_i; } | ||
| 317 | else { count = &count_n; aux = aux_n; cube = &cube_n; } | ||
| 318 | |||
| 319 | for (int j = 0; equiv_moves[alg[i].m][j]; j++) { | ||
| 320 | Move m = equiv_moves[alg[i].m][j]; | ||
| 321 | aux[*count].inverse = alg[i].inverse; | ||
| 322 | move_cubearray(m, cube, cpos_only); | ||
| 323 | if (m == U) aux[(*count)++].m = 3 * cube->cpos[0] + 1; | ||
| 324 | } | ||
| 325 | } | ||
| 326 | |||
| 327 | aux_n[count_n].m = NULLMOVE; | ||
| 328 | aux_i[count_i].m = NULLMOVE; | ||
| 329 | sort_cancel_rotate(aux_n, count_n, false, cube_n.cpos[0], cube_n.cpos[4]); | ||
| 330 | sort_cancel_rotate(aux_i, count_i, true, cube_i.cpos[0], cube_n.cpos[4]); | ||
| 331 | copy_alg(aux_n, alg); | ||
| 332 | copy_alg(aux_i, alg+count_n); | ||
| 333 | } | ||
| 334 | */ | ||
| 335 | |||
| 336 | bool read_ttables_file() { | ||
| 337 | FILE *ttf; | ||
| 338 | long unsigned int me[11] = { factorial12/factorial8, factorial12/factorial8, | ||
| 339 | factorial12/factorial8, pow2to11, pow2to11, pow2to11, | ||
| 340 | factorial8, pow3to7, pow3to7, pow3to7, factorial6 }; | ||
| 341 | if ((ttf = fopen("ttables", "rb")) != NULL) { | ||
| 342 | bool r = true; | ||
| 343 | for (int m = 0; m < NMOVES; m++) { | ||
| 344 | r = r && fread(epose_ttable[m], sizeof(uint16_t), me[0], ttf) == me[0]; | ||
| 345 | r = r && fread(eposs_ttable[m], sizeof(uint16_t), me[1], ttf) == me[1]; | ||
| 346 | r = r && fread(eposm_ttable[m], sizeof(uint16_t), me[2], ttf) == me[2]; | ||
| 347 | r = r && fread(eofb_ttable[m], sizeof(uint16_t), me[3], ttf) == me[3]; | ||
| 348 | r = r && fread(eorl_ttable[m], sizeof(uint16_t), me[4], ttf) == me[4]; | ||
| 349 | r = r && fread(eoud_ttable[m], sizeof(uint16_t), me[5], ttf) == me[5]; | ||
| 350 | r = r && fread(cp_ttable[m], sizeof(uint16_t), me[6], ttf) == me[6]; | ||
| 351 | r = r && fread(coud_ttable[m], sizeof(uint16_t), me[7], ttf) == me[7]; | ||
| 352 | r = r && fread(corl_ttable[m], sizeof(uint16_t), me[8], ttf) == me[8]; | ||
| 353 | r = r && fread(cofb_ttable[m], sizeof(uint16_t), me[9], ttf) == me[9]; | ||
| 354 | r = r && fread(cpos_ttable[m], sizeof(uint16_t), me[10], ttf) == me[10]; | ||
| 355 | } | ||
| 356 | fclose(ttf); | ||
| 357 | return r; | ||
| 358 | } else return false; | ||
| 359 | } | ||
| 360 | |||
| 361 | bool write_ttables_file() { | ||
| 362 | FILE *ttf; | ||
| 363 | long unsigned int me[11] = { factorial12/factorial8, factorial12/factorial8, | ||
| 364 | factorial12/factorial8, pow2to11, pow2to11, pow2to11, | ||
| 365 | factorial8, pow3to7, pow3to7, pow3to7, factorial6 }; | ||
| 366 | if ((ttf = fopen("ttables", "wb")) != NULL) { | ||
| 367 | bool r = true; | ||
| 368 | for (int m = 0; m < NMOVES; m++) { | ||
| 369 | r = r && fwrite(epose_ttable[m], sizeof(uint16_t), me[0], ttf) == me[0]; | ||
| 370 | r = r && fwrite(eposs_ttable[m], sizeof(uint16_t), me[1], ttf) == me[1]; | ||
| 371 | r = r && fwrite(eposm_ttable[m], sizeof(uint16_t), me[2], ttf) == me[2]; | ||
| 372 | r = r && fwrite(eofb_ttable[m], sizeof(uint16_t), me[3], ttf) == me[3]; | ||
| 373 | r = r && fwrite(eorl_ttable[m], sizeof(uint16_t), me[4], ttf) == me[4]; | ||
| 374 | r = r && fwrite(eoud_ttable[m], sizeof(uint16_t), me[5], ttf) == me[5]; | ||
| 375 | r = r && fwrite(cp_ttable[m], sizeof(uint16_t), me[6], ttf) == me[6]; | ||
| 376 | r = r && fwrite(coud_ttable[m], sizeof(uint16_t), me[7], ttf) == me[7]; | ||
| 377 | r = r && fwrite(corl_ttable[m], sizeof(uint16_t), me[8], ttf) == me[8]; | ||
| 378 | r = r && fwrite(cofb_ttable[m], sizeof(uint16_t), me[9], ttf) == me[9]; | ||
| 379 | r = r && fwrite(cpos_ttable[m], sizeof(uint16_t), me[10],ttf) == me[10]; | ||
| 380 | } | ||
| 381 | fclose(ttf); | ||
| 382 | return r; | ||
| 383 | } else return false; | ||
| 384 | } | ||
| 385 | |||
| 386 | void init_ttables(bool read, bool write) { | ||
| 387 | /* Generate all move cycles and flips; I do this regardless */ | ||
| 388 | for (int i = 0; i < NMOVES; i++) { | ||
| 389 | if (i == U || i == x || i == y) | ||
| 390 | continue; | ||
| 391 | |||
| 392 | Cube c = {0}; | ||
| 393 | for (int j = 0; equiv_moves[i][j]; j++) | ||
| 394 | c = apply_move_cubearray(equiv_moves[i][j], c, pf_all); | ||
| 395 | |||
| 396 | CubeArray arrs = { | ||
| 397 | edge_cycle[i], eofb_flipped[i], eorl_flipped[i], eoud_flipped[i], | ||
| 398 | corner_cycle[i], coud_flipped[i], corl_flipped[i], cofb_flipped[i], | ||
| 399 | center_cycle[i] | ||
| 400 | }; | ||
| 401 | cube_to_arrays(c, &arrs, pf_all); | ||
| 402 | } | ||
| 403 | |||
| 404 | if (read) | ||
| 405 | if (read_ttables_file()) | ||
| 406 | return; | ||
| 407 | |||
| 408 | /* Initialize transition tables */ | ||
| 409 | for (int m = 0; m < NMOVES; m++) { | ||
| 410 | for (uint16_t i = 0; i < factorial12/factorial8; i++) { | ||
| 411 | epose_ttable[m][i] = apply_move_cubearray(m,(Cube){.epose=i},pf_e).epose; | ||
| 412 | eposs_ttable[m][i] = apply_move_cubearray(m,(Cube){.eposs=i},pf_s).eposs; | ||
| 413 | eposm_ttable[m][i] = apply_move_cubearray(m,(Cube){.eposm=i},pf_m).eposm; | ||
| 414 | } | ||
| 415 | for (uint16_t i = 0; i < pow2to11; i++ ) { | ||
| 416 | eofb_ttable[m][i] = apply_move_cubearray(m,(Cube){.eofb=i},pf_eo).eofb; | ||
| 417 | eorl_ttable[m][i] = apply_move_cubearray(m,(Cube){.eorl=i},pf_eo).eorl; | ||
| 418 | eoud_ttable[m][i] = apply_move_cubearray(m,(Cube){.eoud=i},pf_eo).eoud; | ||
| 419 | } | ||
| 420 | for (uint16_t i = 0; i < pow3to7; i++) { | ||
| 421 | coud_ttable[m][i] = apply_move_cubearray(m,(Cube){.coud=i},pf_co).coud; | ||
| 422 | corl_ttable[m][i] = apply_move_cubearray(m,(Cube){.corl=i},pf_co).corl; | ||
| 423 | cofb_ttable[m][i] = apply_move_cubearray(m,(Cube){.cofb=i},pf_co).cofb; | ||
| 424 | } | ||
| 425 | for (uint16_t i = 0; i < factorial8; i++) | ||
| 426 | cp_ttable[m][i] = apply_move_cubearray(m,(Cube){.cp=i},pf_cp).cp; | ||
| 427 | for (uint16_t i = 0; i < factorial6; i++) | ||
| 428 | cpos_ttable[m][i] = apply_move_cubearray(m,(Cube){.cpos=i},pf_cpos).cpos; | ||
| 429 | } | ||
| 430 | |||
| 431 | if (write) | ||
| 432 | if (!write_ttables_file()) | ||
| 433 | printf("Error in writing ttables: file not writable\n"); | ||
| 434 | } | ||
| 435 | |||
| 436 | Cube move_cube(Move m, Cube cube) { | ||
| 437 | Cube moved = {0}; | ||
| 438 | |||
| 439 | moved.epose = epose_ttable[m][cube.epose]; | ||
| 440 | moved.eposs = eposs_ttable[m][cube.eposs]; | ||
| 441 | moved.eposm = eposm_ttable[m][cube.eposm]; | ||
| 442 | moved.eofb = eofb_ttable[m][cube.eofb]; | ||
| 443 | moved.eorl = eorl_ttable[m][cube.eorl]; | ||
| 444 | moved.eoud = eoud_ttable[m][cube.eoud]; | ||
| 445 | moved.coud = coud_ttable[m][cube.coud]; | ||
| 446 | moved.cofb = cofb_ttable[m][cube.cofb]; | ||
| 447 | moved.corl = corl_ttable[m][cube.corl]; | ||
| 448 | moved.cp = cp_ttable[m][cube.cp]; | ||
| 449 | moved.cpos = cpos_ttable[m][cube.cpos]; | ||
| 450 | |||
| 451 | return moved; | ||
| 452 | } | ||
| 453 | |||
| 454 | Cube apply_alg(NissMove *alg, Cube cube) { | ||
| 455 | Cube ret = {0}; | ||
| 456 | for (int i = 0; alg[i].m != NULLMOVE; i++) | ||
| 457 | if (alg[i].inverse) | ||
| 458 | ret = move_cube(alg[i].m, ret); | ||
| 459 | |||
| 460 | ret = compose(cube, inverse_cube(ret)); | ||
| 461 | |||
| 462 | for (int i = 0; alg[i].m != NULLMOVE; i++) | ||
| 463 | if (!alg[i].inverse) | ||
| 464 | ret = move_cube(alg[i].m, ret); | ||
| 465 | return ret; | ||
| 466 | } | ||
| 467 | |||
| 468 | void init_aux_tables() { | ||
| 469 | /* Commute */ | ||
| 470 | for (int i = 0; i < NMOVES; i++) | ||
| 471 | for (int j = 0; j < NMOVES; j++) | ||
| 472 | commute[i][j] = equal(move_cube(i, move_cube(j, (Cube){0})), | ||
| 473 | move_cube(j, move_cube(i, (Cube){0}))); | ||
| 474 | |||
| 475 | /* Possible next (if the sequence i j k is valid) */ | ||
| 476 | for (int i = 0; i < NMOVES; i++) | ||
| 477 | for (int j = 0; j < NMOVES; j++) | ||
| 478 | for (int k = 0; k < NMOVES; k++) | ||
| 479 | possible_next[i][j][k] = | ||
| 480 | (j == 0) || | ||
| 481 | (j != 0 && (j-(j-1)%3) != (k-(k-1)%3) && | ||
| 482 | !(i != 0 && commute[i][j] && (i-(i-1)%3) == (k-(k-1)%3))); | ||
| 483 | |||
| 484 | /* Inverse */ | ||
| 485 | for (int i = 0; i < NMOVES; i++) | ||
| 486 | inverse[i] = i == NULLMOVE ? NULLMOVE : i + 2 - 2*((i-1)%3); | ||
| 487 | |||
| 488 | } | ||
| 489 | |||
diff --git a/old/2021-02-28-transformcube-works/src/moves.h b/old/2021-02-28-transformcube-works/src/moves.h new file mode 100644 index 0000000..c1489a1 --- /dev/null +++ b/old/2021-02-28-transformcube-works/src/moves.h | |||
| @@ -0,0 +1,50 @@ | |||
| 1 | #ifndef MOVES_H | ||
| 2 | #define MOVES_H | ||
| 3 | |||
| 4 | #include <stdio.h> | ||
| 5 | #include <stdbool.h> | ||
| 6 | #include <stdint.h> | ||
| 7 | #include "cube.h" | ||
| 8 | #include "utils.h" | ||
| 9 | |||
| 10 | #define NMOVES (z3+1) | ||
| 11 | |||
| 12 | typedef enum { | ||
| 13 | NULLMOVE, | ||
| 14 | U, U2, U3, D, D2, D3, R, R2, R3, L, L2, L3, F, F2, F3, B, B2, B3, | ||
| 15 | Uw, Uw2, Uw3, Dw, Dw2, Dw3, Rw, Rw2, Rw3, | ||
| 16 | Lw, Lw2, Lw3, Fw, Fw2, Fw3, Bw, Bw2, Bw3, | ||
| 17 | M, M2, M3, S, S2, S3, E, E2, E3, | ||
| 18 | x, x2, x3, y, y2, y3, z, z2, z3, | ||
| 19 | } Move; | ||
| 20 | |||
| 21 | /* An alg is an array of "NissMoves", which can be on normal or on inverse. */ | ||
| 22 | typedef struct { bool inverse; Move m; } NissMove; | ||
| 23 | |||
| 24 | /* Movesets */ | ||
| 25 | extern bool standard_moveset[NMOVES]; | ||
| 26 | |||
| 27 | extern bool commute[NMOVES][NMOVES]; | ||
| 28 | extern bool possible_next[NMOVES][NMOVES][NMOVES]; | ||
| 29 | extern Move inverse[NMOVES]; | ||
| 30 | extern NissMove rotation_algs[24][3]; /* Same order as transformations */ | ||
| 31 | |||
| 32 | int len(NissMove *alg); | ||
| 33 | int copy_alg(NissMove *src, NissMove *dest); /*return number of moves copied */ | ||
| 34 | int invert_alg(NissMove *src, NissMove *dest); | ||
| 35 | int concat(NissMove *src1, NissMove *src2, NissMove *dest); | ||
| 36 | void print_moves(NissMove *alg); | ||
| 37 | int read_moves(char *str, NissMove *alg, int n); /* reads at most n moves */ | ||
| 38 | void cleanup(NissMove *src, int n); /* rewrites using basic moves, at most n */ | ||
| 39 | |||
| 40 | bool is_solved_up_to_reorient(Cube cube); | ||
| 41 | Cube move_cube(Move m, Cube cube); | ||
| 42 | Cube apply_alg(NissMove *alg, Cube cube); | ||
| 43 | |||
| 44 | /* Merge the following two? | ||
| 45 | always in this order */ | ||
| 46 | void init_ttables(bool read, bool write); | ||
| 47 | void init_aux_tables(); | ||
| 48 | |||
| 49 | |||
| 50 | #endif | ||
diff --git a/old/2021-02-28-transformcube-works/src/solve.c b/old/2021-02-28-transformcube-works/src/solve.c new file mode 100644 index 0000000..07c9075 --- /dev/null +++ b/old/2021-02-28-transformcube-works/src/solve.c | |||
| @@ -0,0 +1,180 @@ | |||
| 1 | #include "solve.h" | ||
| 2 | |||
| 3 | /* Data for creating a pruning table: | ||
| 4 | - compressed: if set to true, each entry occupies only 4 bits, but values | ||
| 5 | larger than 15 cannot be stored. | ||
| 6 | - available[] is the list of availabel moves, as above. | ||
| 7 | - *ptable is the actual table to fill. | ||
| 8 | - n is the number of states (size of ptable). | ||
| 9 | - index must "linearize" the cube, i.e. return its index in ptable. | ||
| 10 | - fname is the name of the file where to store the table */ | ||
| 11 | typedef struct { | ||
| 12 | bool compressed, *available; | ||
| 13 | int max_moves; | ||
| 14 | uint8_t *ptable; | ||
| 15 | uint64_t n; | ||
| 16 | uint64_t (*index)(Cube); | ||
| 17 | char *fname; | ||
| 18 | } PruneData; | ||
| 19 | |||
| 20 | /* TODO: comment this */ | ||
| 21 | typedef struct { | ||
| 22 | bool niss; | ||
| 23 | int m, d; | ||
| 24 | uint64_t *n; | ||
| 25 | Move last1, last2; | ||
| 26 | } DfsData; | ||
| 27 | |||
| 28 | void solve_dfs(Cube cube, SolveData *sd, DfsData dd); | ||
| 29 | void init_ptable(PruneData *pd, bool read, bool write); | ||
| 30 | |||
| 31 | /* Search solutions of lenght exactly d */ | ||
| 32 | void solve_dfs(Cube cube, SolveData *sd, DfsData dd) { | ||
| 33 | if (*dd.n >= sd->max_solutions || | ||
| 34 | ((!sd->can_niss || dd.niss) && dd.m + sd->f(cube) > dd.d)) | ||
| 35 | return; | ||
| 36 | |||
| 37 | (sd->solutions[*dd.n][dd.m]).inverse = dd.niss; | ||
| 38 | (sd->solutions[*dd.n][dd.m]).m = NULLMOVE; | ||
| 39 | |||
| 40 | if (!sd->f(cube)) { /* Solved */ | ||
| 41 | if (dd.m == dd.d) { | ||
| 42 | (*dd.n)++; | ||
| 43 | if (*dd.n < sd->max_solutions) | ||
| 44 | copy_alg(sd->solutions[*dd.n-1], sd->solutions[*dd.n]); | ||
| 45 | } | ||
| 46 | return; | ||
| 47 | } | ||
| 48 | |||
| 49 | for (int i = 0; i < NMOVES && sd->sorted_moves[i] != NULLMOVE; i++) { | ||
| 50 | Move move = sd->sorted_moves[i]; | ||
| 51 | if (possible_next[dd.last2][dd.last1][move]) { | ||
| 52 | sd->solutions[*dd.n][dd.m].inverse = dd.niss; | ||
| 53 | sd->solutions[*dd.n][dd.m].m = move; | ||
| 54 | DfsData nn = { .niss = dd.niss, .m = dd.m+1, .d = dd.d, .n = dd.n, | ||
| 55 | .last1 = move, .last2 = dd.last1 }; | ||
| 56 | solve_dfs(move_cube(move, cube), sd, nn); | ||
| 57 | } | ||
| 58 | } | ||
| 59 | |||
| 60 | if (sd->can_niss && !dd.niss && | ||
| 61 | (!dd.m || (dd.m && sd->f(move_cube(dd.last1, (Cube){0}))))) { | ||
| 62 | DfsData nn = { .niss = true, .m = dd.m, .d = dd.d, .n = dd.n }; | ||
| 63 | solve_dfs(inverse_cube(cube), sd, nn); | ||
| 64 | } | ||
| 65 | } | ||
| 66 | |||
| 67 | /* Iterative deepening depth-first search: for i running from the minimum | ||
| 68 | to the maximum number of moves allowed, looks for solutions of length i. */ | ||
| 69 | int solve(Cube cube, SolveData *sd) { | ||
| 70 | if (sd->precondition != NULL && !sd->precondition(cube)) | ||
| 71 | return -1; | ||
| 72 | |||
| 73 | /* If not given, generate sorted list of moves */ | ||
| 74 | if (sd->sorted_moves[0] == NULLMOVE) { | ||
| 75 | int a[NMOVES], b[NMOVES], ia = 0, ib = 0; | ||
| 76 | for (int i = 0; i < NMOVES; i++) { | ||
| 77 | if (sd->available[i]) { | ||
| 78 | if (sd->f(move_cube(i, (Cube){0}))) | ||
| 79 | a[ia++] = i; | ||
| 80 | else | ||
| 81 | b[ib++] = i; | ||
| 82 | } | ||
| 83 | } | ||
| 84 | intarrcopy(a, (int *)sd->sorted_moves, ia); | ||
| 85 | intarrcopy(b, (int *)sd->sorted_moves+ia, ib); | ||
| 86 | sd->sorted_moves[ia+ib] = NULLMOVE; | ||
| 87 | } | ||
| 88 | |||
| 89 | sd->max_solutions = min(sd->max_solutions, MAXS); | ||
| 90 | /*TODO | ||
| 91 | Cube rotated = apply_alg(sd->pre_rotation, (Cube){0}); | ||
| 92 | cube = apply_alg(inverse_cube(rotated), compose(cube, rotated)); | ||
| 93 | */ | ||
| 94 | |||
| 95 | uint64_t ret = 0; | ||
| 96 | for (int i=sd->min_moves; i<=sd->max_moves&&!(ret&&sd->optimal_only); i++) { | ||
| 97 | DfsData dd = { .d = i, .n = &ret }; | ||
| 98 | solve_dfs(cube, sd, dd); | ||
| 99 | } | ||
| 100 | |||
| 101 | /* TODO: transform solutions with inverse of pre_rotation */ | ||
| 102 | /* | ||
| 103 | for (uint64_t i = 0; i < ret; i++) { | ||
| 104 | if (sd->cleanup) | ||
| 105 | cleanup(sd->solutions[i], sd->max_moves*3); | ||
| 106 | }*/ | ||
| 107 | |||
| 108 | return ret; | ||
| 109 | } | ||
| 110 | |||
| 111 | void prune_dfs(Cube cube, PruneData *pd, DfsData dd) { | ||
| 112 | uint64_t ind = pd->index(cube); | ||
| 113 | if ((!ind || pd->ptable[ind]) && pd->ptable[ind] != dd.m) | ||
| 114 | return; | ||
| 115 | if (dd.m == dd.d) { | ||
| 116 | if (ind && !pd->ptable[ind]) { | ||
| 117 | pd->ptable[ind] = dd.m; | ||
| 118 | (*dd.n)++; | ||
| 119 | } | ||
| 120 | return; | ||
| 121 | } | ||
| 122 | |||
| 123 | for (int i = 0; i < NMOVES; i++) { | ||
| 124 | if (dd.m<20) | ||
| 125 | if (possible_next[dd.last2][dd.last1][i] && pd->available[i]) { | ||
| 126 | DfsData nn = { .m = dd.m+1, .d = dd.d, .n = dd.n, | ||
| 127 | .last1 = i, .last2 = dd.last1 }; | ||
| 128 | prune_dfs(move_cube(i, cube), pd, nn); | ||
| 129 | } | ||
| 130 | } | ||
| 131 | } | ||
| 132 | |||
| 133 | void init_ptable(PruneData *pd, bool read, bool write) { | ||
| 134 | if (read) { | ||
| 135 | FILE *ptf; | ||
| 136 | if ((ptf = fopen(pd->fname, "rb")) != NULL) { | ||
| 137 | uint64_t r = fread(pd->ptable, sizeof(uint8_t), pd->n, ptf); | ||
| 138 | fclose(ptf); | ||
| 139 | if (r == pd->n) return; | ||
| 140 | } | ||
| 141 | } | ||
| 142 | |||
| 143 | /* TODO: for now it behaves always as if copressed = false */ | ||
| 144 | for (uint64_t i = 0; i < pd->n; i++) | ||
| 145 | pd->ptable[i] = 0; | ||
| 146 | |||
| 147 | uint64_t s = 1; | ||
| 148 | for (int i = 1; i < pd->max_moves && s < pd->n; i++) { | ||
| 149 | DfsData dd = { .d = i, .n = &s }; | ||
| 150 | prune_dfs((Cube){0}, pd, dd); | ||
| 151 | } | ||
| 152 | |||
| 153 | if (write) { | ||
| 154 | FILE *ptf; | ||
| 155 | if ((ptf = fopen(pd->fname, "wb")) != NULL) { | ||
| 156 | fwrite(pd->ptable, sizeof(uint8_t), pd->n, ptf); | ||
| 157 | fclose(ptf); | ||
| 158 | return; | ||
| 159 | } | ||
| 160 | } | ||
| 161 | } | ||
| 162 | |||
| 163 | /* Solving steps (and indexing functions) */ | ||
| 164 | |||
| 165 | uint64_t index_eofb(Cube cube) { return cube.eofb; } | ||
| 166 | uint16_t f_eofb(Cube cube) { | ||
| 167 | static bool initialized_ptable; | ||
| 168 | static uint8_t pt_eofb[pow2to11]; | ||
| 169 | if (!initialized_ptable) { | ||
| 170 | PruneData pd = { | ||
| 171 | .compressed = false, .available = standard_moveset, .max_moves = 13, | ||
| 172 | .ptable = pt_eofb, .n = pow2to11, .index = index_eofb, | ||
| 173 | .fname = "ptable_eofb" | ||
| 174 | }; | ||
| 175 | init_ptable(&pd, false, true); | ||
| 176 | initialized_ptable = true; | ||
| 177 | } | ||
| 178 | return cube.eofb ? pt_eofb[cube.eofb] : 0; | ||
| 179 | } | ||
| 180 | |||
diff --git a/old/2021-02-28-transformcube-works/src/solve.h b/old/2021-02-28-transformcube-works/src/solve.h new file mode 100644 index 0000000..d585a8e --- /dev/null +++ b/old/2021-02-28-transformcube-works/src/solve.h | |||
| @@ -0,0 +1,56 @@ | |||
| 1 | #ifndef SOLVE_H | ||
| 2 | #define SOLVE_H | ||
| 3 | |||
| 4 | #include <stdlib.h> | ||
| 5 | #include "cube.h" | ||
| 6 | #include "moves.h" | ||
| 7 | |||
| 8 | /* Maximum number of moves per solution and of solutions */ | ||
| 9 | #define MAXM 30 | ||
| 10 | #define MAXS 999 | ||
| 11 | |||
| 12 | /* Data for solving a step: | ||
| 13 | - can_niss is true niss can be used, false otherwise. | ||
| 14 | - optimal_only if true, dynamically updates max_moves so non-optimal | ||
| 15 | solutions are discarded. | ||
| 16 | - cleanup determines whether the cleaunup() function should be used on | ||
| 17 | the found solutions before returning. | ||
| 18 | - available[m] is true if the move m can be used, false otherwise. | ||
| 19 | - min_moves and max_moves are the minimum and maximum number of moves that | ||
| 20 | can be used. | ||
| 21 | - max_solution is the maximum number of solutions that can be returned. | ||
| 22 | - precondition can be used to check wheter the step can actually be applied | ||
| 23 | to the cube. If it returns false, solve() stops immediately returning -1. | ||
| 24 | - f must return 0 if and only if the step is solve, otherwise it must return | ||
| 25 | a lower bound for the number of moves required (without niss). | ||
| 26 | - sorted_moves[] can be used to specify in which order moves are tried | ||
| 27 | by the solving algorithm (for example if one wants to always try F' before | ||
| 28 | F). If sorted_moves[0] == NULLMOVE, the list is generated automatically. | ||
| 29 | It is advised to list first all the moves that actually influence the | ||
| 30 | solved state of the step (this is the default choice). This is in order to | ||
| 31 | avoid cases like B2 F for EO and to NISS only when it makes sense. | ||
| 32 | - start_moves [Currently unused, REMOVE] | ||
| 33 | are the moves that will be used as first moves of all | ||
| 34 | solutions. For example giving R' U' F (F' U R) will generate FMC scrambles | ||
| 35 | and y (y) will solve the step on another axis. | ||
| 36 | - pre_rotation are the rotations to apply before the scamble to solve | ||
| 37 | the step wrt a different orientation | ||
| 38 | - pre_rotation are the rotations to apply before the scamble to solve | ||
| 39 | the step wth respect to a different orientation. | ||
| 40 | - solutions[][] is the array where to store the found solutions. */ | ||
| 41 | typedef struct { | ||
| 42 | bool can_niss, optimal_only, cleanup, *available; | ||
| 43 | int min_moves, max_moves; | ||
| 44 | uint64_t max_solutions; | ||
| 45 | bool (*precondition)(Cube); | ||
| 46 | uint16_t (*f)(Cube); | ||
| 47 | Move sorted_moves[NMOVES]; | ||
| 48 | NissMove pre_rotation[3], solutions[MAXS][MAXM]; | ||
| 49 | } SolveData; | ||
| 50 | |||
| 51 | int solve(Cube cube, SolveData *data); /* Returns the number of solutions. */ | ||
| 52 | |||
| 53 | /* Steps */ | ||
| 54 | uint16_t f_eofb(Cube cube); | ||
| 55 | |||
| 56 | #endif | ||
diff --git a/old/2021-02-28-transformcube-works/src/transformations.c b/old/2021-02-28-transformcube-works/src/transformations.c new file mode 100644 index 0000000..9ae10e9 --- /dev/null +++ b/old/2021-02-28-transformcube-works/src/transformations.c | |||
| @@ -0,0 +1,224 @@ | |||
| 1 | #include "transformations.h" | ||
| 2 | |||
| 3 | int edge_slice(int e); /* Return slice (e=0, s=1, m=2) to which e belongs */ | ||
| 4 | Cube rotate_via_compose(Transformation r, Cube c); | ||
| 5 | bool read_rtables_file(); | ||
| 6 | bool write_rtables_file(); | ||
| 7 | |||
| 8 | /* Values mod 3 to determine from which side to take the state to convert */ | ||
| 9 | int epose_source[NROTATIONS]; /* 0 = epose, 1 = eposs, 2 = eposm */ | ||
| 10 | int eposs_source[NROTATIONS]; | ||
| 11 | int eposm_source[NROTATIONS]; | ||
| 12 | int eofb_source[NROTATIONS]; /* 0 = eoud, 1 = eorl, 2 = eofb */ | ||
| 13 | int eorl_source[NROTATIONS]; | ||
| 14 | int eoud_source[NROTATIONS]; | ||
| 15 | int coud_source[NROTATIONS]; /* 0 = coud, 1 = corl, 2 = cofb */ | ||
| 16 | int cofb_source[NROTATIONS]; | ||
| 17 | int corl_source[NROTATIONS]; | ||
| 18 | |||
| 19 | /* Transition tables for rotations (n+1 is mirror) */ | ||
| 20 | uint16_t epose_rtable[NROTATIONS][factorial12/factorial8]; | ||
| 21 | uint16_t eposs_rtable[NROTATIONS][factorial12/factorial8]; | ||
| 22 | uint16_t eposm_rtable[NROTATIONS][factorial12/factorial8]; | ||
| 23 | uint16_t eo_rtable[NROTATIONS][pow2to11]; | ||
| 24 | /*uint16_t eofb_rtable[NROTATIONS][pow2to11]; | ||
| 25 | uint16_t eorl_rtable[NROTATIONS][pow2to11]; | ||
| 26 | uint16_t eoud_rtable[NROTATIONS][pow2to11];*/ | ||
| 27 | uint16_t cp_rtable[NROTATIONS][factorial8]; | ||
| 28 | uint16_t co_rtable[NROTATIONS][pow3to7]; | ||
| 29 | /*uint16_t coud_rtable[NROTATIONS][pow3to7]; | ||
| 30 | uint16_t cofb_rtable[NROTATIONS][pow3to7]; | ||
| 31 | uint16_t corl_rtable[NROTATIONS][pow3to7];*/ | ||
| 32 | uint16_t cpos_rtable[NROTATIONS][factorial6]; | ||
| 33 | |||
| 34 | /* Same for moves */ | ||
| 35 | uint16_t move_rtable[NROTATIONS][NMOVES]; | ||
| 36 | |||
| 37 | NissMove rotation_niss[NROTATIONS][6]; | ||
| 38 | |||
| 39 | int edge_slice(int e) { | ||
| 40 | if (e == FR || e == FL || e == BL || e == BR) | ||
| 41 | return 0; | ||
| 42 | if (e == UR || e == UL || e == DR || e == DL) | ||
| 43 | return 1; | ||
| 44 | return 2; | ||
| 45 | } | ||
| 46 | |||
| 47 | Cube rotate_via_compose(Transformation r, Cube c) { | ||
| 48 | if (r != mirror) { | ||
| 49 | return apply_alg(rotation_niss[r], c); | ||
| 50 | } else { | ||
| 51 | static int zero12[12] = {0,0,0,0,0,0,0,0,0,0,0,0}, | ||
| 52 | zero8[12] = {0,0,0,0,0,0,0,0}, | ||
| 53 | mirror_ep[12] = {UF,UR,UB,UL,DF,DR,DB,DL,FL,FR,BR,BL}, | ||
| 54 | mirror_cp[8] = {UFL, UFR, UBR, UBL, DFL, DFR, DBR, DBL}, | ||
| 55 | mirror_cpos[6] = | ||
| 56 | {U_center,D_center,L_center,R_center,F_center,B_center}; | ||
| 57 | return move_via_arrays((CubeArray){ | ||
| 58 | .ep = mirror_ep, .eofb = zero12, .eorl = zero12, .eoud = zero12, | ||
| 59 | .cp = mirror_cp, .coud = zero8, .corl = zero8, .cofb = zero8, | ||
| 60 | .cpos = mirror_cpos}, c, pf_all); | ||
| 61 | } | ||
| 62 | } | ||
| 63 | |||
| 64 | bool read_rtables_file() { | ||
| 65 | FILE *ttf; | ||
| 66 | long unsigned int me[12] = { factorial12/factorial8, factorial12/factorial8, | ||
| 67 | factorial12/factorial8, pow2to11, pow2to11, pow2to11, | ||
| 68 | factorial8, pow3to7, pow3to7, pow3to7, factorial6, NMOVES }; | ||
| 69 | if ((ttf = fopen("rtables", "rb")) != NULL) { | ||
| 70 | bool r = true; | ||
| 71 | for (int m = 0; m < NROTATIONS; m++) { | ||
| 72 | r = r && fread(epose_rtable[m], sizeof(uint16_t), me[0], ttf) == me[0]; | ||
| 73 | r = r && fread(eposs_rtable[m], sizeof(uint16_t), me[1], ttf) == me[1]; | ||
| 74 | r = r && fread(eposm_rtable[m], sizeof(uint16_t), me[2], ttf) == me[2]; | ||
| 75 | r = r && fread(eo_rtable[m], sizeof(uint16_t), me[3], ttf) == me[3]; | ||
| 76 | /*r = r && fread(eofb_rtable[m], sizeof(uint16_t), me[3], ttf) == me[3]; | ||
| 77 | r = r && fread(eorl_rtable[m], sizeof(uint16_t), me[4], ttf) == me[4]; | ||
| 78 | r = r && fread(eoud_rtable[m], sizeof(uint16_t), me[5], ttf) == me[5];*/ | ||
| 79 | r = r && fread(cp_rtable[m], sizeof(uint16_t), me[6], ttf) == me[6]; | ||
| 80 | r = r && fread(co_rtable[m], sizeof(uint16_t), me[7], ttf) == me[7]; | ||
| 81 | /*r = r && fread(coud_rtable[m], sizeof(uint16_t), me[7], ttf) == me[7]; | ||
| 82 | r = r && fread(corl_rtable[m], sizeof(uint16_t), me[8], ttf) == me[8]; | ||
| 83 | r = r && fread(cofb_rtable[m], sizeof(uint16_t), me[9], ttf) == me[9];*/ | ||
| 84 | r = r && fread(cpos_rtable[m], sizeof(uint16_t), me[10], ttf) == me[10]; | ||
| 85 | r = r && fread(move_rtable[m], sizeof(uint16_t), me[11], ttf) == me[11]; | ||
| 86 | } | ||
| 87 | fclose(ttf); | ||
| 88 | return r; | ||
| 89 | } else return false; | ||
| 90 | } | ||
| 91 | |||
| 92 | bool write_rtables_file() { | ||
| 93 | FILE *ttf; | ||
| 94 | long unsigned int me[12] = { factorial12/factorial8, factorial12/factorial8, | ||
| 95 | factorial12/factorial8, pow2to11, pow2to11, pow2to11, | ||
| 96 | factorial8, pow3to7, pow3to7, pow3to7, factorial6, NMOVES }; | ||
| 97 | if ((ttf = fopen("rtables", "wb")) != NULL) { | ||
| 98 | bool r = true; | ||
| 99 | for (int m = 0; m < NROTATIONS; m++) { | ||
| 100 | r = r && fwrite(epose_rtable[m], sizeof(uint16_t), me[0], ttf) == me[0]; | ||
| 101 | r = r && fwrite(eposs_rtable[m], sizeof(uint16_t), me[1], ttf) == me[1]; | ||
| 102 | r = r && fwrite(eposm_rtable[m], sizeof(uint16_t), me[2], ttf) == me[2]; | ||
| 103 | r = r && fwrite(eo_rtable[m], sizeof(uint16_t), me[3], ttf) == me[3]; | ||
| 104 | /*r = r && fwrite(eofb_rtable[m], sizeof(uint16_t), me[3], ttf) == me[3]; | ||
| 105 | r = r && fwrite(eorl_rtable[m], sizeof(uint16_t), me[4], ttf) == me[4]; | ||
| 106 | r = r && fwrite(eoud_rtable[m], sizeof(uint16_t), me[5], ttf) == me[5];*/ | ||
| 107 | r = r && fwrite(cp_rtable[m], sizeof(uint16_t), me[6], ttf) == me[6]; | ||
| 108 | r = r && fwrite(co_rtable[m], sizeof(uint16_t), me[7], ttf) == me[7]; | ||
| 109 | /*r = r && fwrite(coud_rtable[m], sizeof(uint16_t), me[7], ttf) == me[7]; | ||
| 110 | r = r && fwrite(corl_rtable[m], sizeof(uint16_t), me[8], ttf) == me[8]; | ||
| 111 | r = r && fwrite(cofb_rtable[m], sizeof(uint16_t), me[9], ttf) == me[9];*/ | ||
| 112 | r = r && fwrite(cpos_rtable[m], sizeof(uint16_t), me[10],ttf) == me[10]; | ||
| 113 | r = r && fwrite(move_rtable[m], sizeof(uint16_t), me[11],ttf) == me[11]; | ||
| 114 | } | ||
| 115 | fclose(ttf); | ||
| 116 | return r; | ||
| 117 | } else return false; | ||
| 118 | } | ||
| 119 | |||
| 120 | void init_transformations(bool read, bool write) { | ||
| 121 | /* Compute sources */ | ||
| 122 | for (int i = 0; i < NROTATIONS; i++) { | ||
| 123 | Cube cube = {0}; | ||
| 124 | if (i != mirror) | ||
| 125 | cube = apply_alg(rotation_algs[i], (Cube){0}); | ||
| 126 | epose_source[i] = edge_slice(edge_at(cube, FR)); | ||
| 127 | eposs_source[i] = edge_slice(edge_at(cube, UR)); | ||
| 128 | eposm_source[i] = edge_slice(edge_at(cube, UF)); | ||
| 129 | eofb_source[i] = center_at(cube, F_center)/2; | ||
| 130 | eorl_source[i] = center_at(cube, R_center)/2; | ||
| 131 | eoud_source[i] = center_at(cube, U_center)/2; | ||
| 132 | coud_source[i] = center_at(cube, U_center)/2; | ||
| 133 | cofb_source[i] = center_at(cube, F_center)/2; | ||
| 134 | corl_source[i] = center_at(cube, R_center)/2; | ||
| 135 | } | ||
| 136 | |||
| 137 | /*TODO: maybe move down*/ | ||
| 138 | /* Compute rotation_niss array, necessary for rotate_via_compose */ | ||
| 139 | for (int r = 0; r != mirror; r++) { | ||
| 140 | concat(rotation_algs[r], rotation_algs[r], rotation_niss[r]); | ||
| 141 | for (int i = len(rotation_algs[r]); rotation_niss[r][i].m != NULLMOVE; i++) | ||
| 142 | rotation_niss[r][i].inverse = true; | ||
| 143 | } | ||
| 144 | |||
| 145 | /* If I can read tables from file, I stop here */ | ||
| 146 | if (read) | ||
| 147 | if (read_rtables_file()) | ||
| 148 | return; | ||
| 149 | |||
| 150 | /* Initialize tables */ | ||
| 151 | for (int m = 0; m < NROTATIONS; m++) { | ||
| 152 | int eparr[12] = {0,0,0,0,0,0,0,0,0,0,0,0}, cparr[8] = {0,0,0,0,0,0,0,0}; | ||
| 153 | CubeArray epcp = { .ep = eparr, .cp = cparr }; | ||
| 154 | cube_to_arrays(apply_alg(rotation_algs[m], (Cube){0}), &epcp, | ||
| 155 | (PieceFilter){.epose=true,.eposs=true,.eposm=true,.cp=true}); | ||
| 156 | for (uint16_t i = 0; i < factorial12/factorial8; i++) { | ||
| 157 | Cube c[3] = { admissible_ep((Cube){ .epose = i}, pf_e), | ||
| 158 | admissible_ep((Cube){ .eposs = i}, pf_s), | ||
| 159 | admissible_ep((Cube){ .eposm = i}, pf_m) }; | ||
| 160 | epose_rtable[m][i] = rotate_via_compose(m, c[epose_source[m]]).epose; | ||
| 161 | eposs_rtable[m][i] = rotate_via_compose(m, c[eposs_source[m]]).eposs; | ||
| 162 | eposm_rtable[m][i] = rotate_via_compose(m, c[eposm_source[m]]).eposm; | ||
| 163 | } | ||
| 164 | for (uint16_t i = 0; i < pow2to11; i++ ) { | ||
| 165 | int eoarr[12]; | ||
| 166 | int_to_sum_zero_array(i, 2, 12, eoarr); | ||
| 167 | apply_permutation(eparr, eoarr, 12); | ||
| 168 | eo_rtable[m][i] = digit_array_to_int(eoarr, 11, 2); | ||
| 169 | /*Cube c[3] = {(Cube){.eoud=i}, (Cube){.eorl=i}, (Cube){.eofb=i}}; | ||
| 170 | eofb_rtable[m][i] = apply_alg(rotation_algs[m], (Cube){.eofb=i}).eofb; | ||
| 171 | eorl_rtable[m][i] = rotate_via_compose(m, c[eorl_source[m]]).eorl; | ||
| 172 | eoud_rtable[m][i] = rotate_via_compose(m, c[eoud_source[m]]).eoud;*/ | ||
| 173 | } | ||
| 174 | for (uint16_t i = 0; i < pow3to7; i++) { | ||
| 175 | int coarr[12]; | ||
| 176 | int_to_sum_zero_array(i, 3, 8, coarr); | ||
| 177 | apply_permutation(cparr, coarr, 8); | ||
| 178 | co_rtable[m][i] = digit_array_to_int(coarr, 8, 3); | ||
| 179 | /*Cube c[3] = {(Cube){.coud=i}, (Cube){.corl=i}, (Cube){.cofb=i}}; | ||
| 180 | coud_rtable[m][i] = rotate_via_compose(m, c[coud_source[m]]).coud; | ||
| 181 | corl_rtable[m][i] = rotate_via_compose(m, c[corl_source[m]]).corl; | ||
| 182 | cofb_rtable[m][i] = rotate_via_compose(m, c[cofb_source[m]]).cofb;*/ | ||
| 183 | } | ||
| 184 | for (uint16_t i = 0; i < factorial8; i++) | ||
| 185 | cp_rtable[m][i] = rotate_via_compose(m, (Cube){.cp=i}).cp; | ||
| 186 | for (uint16_t i = 0; i < factorial6; i++) | ||
| 187 | cpos_rtable[m][i] = rotate_via_compose(m, (Cube){.cpos=i}).cpos; | ||
| 188 | } | ||
| 189 | |||
| 190 | if (write) | ||
| 191 | if (!write_rtables_file()) | ||
| 192 | printf("Error in writing rtables: file not writable\n"); | ||
| 193 | } | ||
| 194 | |||
| 195 | Cube transform_cube(Transformation t, Cube cube) { | ||
| 196 | Cube transformed = {0}; | ||
| 197 | |||
| 198 | uint16_t aux_epos[3] = { cube.epose, cube.eposs, cube.eposm }, | ||
| 199 | aux_eo[3] = { cube.eoud, cube.eorl, cube.eofb }, | ||
| 200 | aux_co[3] = { cube.coud, cube.corl, cube.cofb }; | ||
| 201 | |||
| 202 | transformed.epose = epose_rtable[t][aux_epos[epose_source[t]]]; | ||
| 203 | transformed.eposs = eposs_rtable[t][aux_epos[eposs_source[t]]]; | ||
| 204 | transformed.eposm = eposm_rtable[t][aux_epos[eposm_source[t]]]; | ||
| 205 | transformed.eofb = eo_rtable[t][aux_eo[eofb_source[t]]]; | ||
| 206 | transformed.eorl = eo_rtable[t][aux_eo[eorl_source[t]]]; | ||
| 207 | transformed.eoud = eo_rtable[t][aux_eo[eoud_source[t]]]; | ||
| 208 | transformed.coud = co_rtable[t][aux_co[coud_source[t]]]; | ||
| 209 | transformed.corl = co_rtable[t][aux_co[corl_source[t]]]; | ||
| 210 | transformed.cofb = co_rtable[t][aux_co[cofb_source[t]]]; | ||
| 211 | transformed.cp = cp_rtable[t][cube.cp]; | ||
| 212 | transformed.cpos = cpos_rtable[t][cube.cpos]; | ||
| 213 | |||
| 214 | /* | ||
| 215 | printf("%d\n", coud_source[t]); | ||
| 216 | int ccc[8]; | ||
| 217 | int_to_sum_zero_array(cube.cofb, 3, 8, ccc); | ||
| 218 | for (int i = 0; i < 8; i++) | ||
| 219 | printf("%d ", ccc[i]); | ||
| 220 | printf("\n"); | ||
| 221 | */ | ||
| 222 | |||
| 223 | return transformed; | ||
| 224 | } | ||
diff --git a/old/2021-02-28-transformcube-works/src/transformations.h b/old/2021-02-28-transformcube-works/src/transformations.h new file mode 100644 index 0000000..c42cc34 --- /dev/null +++ b/old/2021-02-28-transformcube-works/src/transformations.h | |||
| @@ -0,0 +1,34 @@ | |||
| 1 | #ifndef TRANSFORMATIONS_H | ||
| 2 | #define TRANSFORMATIONS_H | ||
| 3 | |||
| 4 | #include <stdio.h> | ||
| 5 | #include <stdbool.h> | ||
| 6 | #include <stdint.h> | ||
| 7 | #include "cube.h" | ||
| 8 | #include "moves.h" | ||
| 9 | #include "utils.h" | ||
| 10 | |||
| 11 | #define NROTATIONS (mirror+1) | ||
| 12 | |||
| 13 | /* Letters indicate top and front centers | ||
| 14 | * Mirror is wrt rl | ||
| 15 | * Lowercase letter to distinguish from pieces */ | ||
| 16 | |||
| 17 | typedef enum { | ||
| 18 | uf, ur, ub, ul, | ||
| 19 | df, dr, db, dl, | ||
| 20 | rf, rd, rb, ru, | ||
| 21 | lf, ld, lb, lu, | ||
| 22 | fu, fr, fd, fl, | ||
| 23 | bu, br, bd, bl, | ||
| 24 | mirror, | ||
| 25 | } Transformation; | ||
| 26 | |||
| 27 | void print_transformation(Transformation t); | ||
| 28 | |||
| 29 | Cube transform_cube(Transformation t, Cube cube); | ||
| 30 | void transform_alg(Transformation t, NissMove *alg); /* Applied in-place */ | ||
| 31 | |||
| 32 | void init_transformations(bool read, bool write); | ||
| 33 | |||
| 34 | #endif | ||
diff --git a/old/2021-02-28-transformcube-works/src/utils.c b/old/2021-02-28-transformcube-works/src/utils.c new file mode 100644 index 0000000..66de9ad --- /dev/null +++ b/old/2021-02-28-transformcube-works/src/utils.c | |||
| @@ -0,0 +1,197 @@ | |||
| 1 | #include "utils.h" | ||
| 2 | |||
| 3 | void swap(int *a, int *b) { | ||
| 4 | int aux = *a; | ||
| 5 | *a = *b; | ||
| 6 | *b = aux; | ||
| 7 | } | ||
| 8 | |||
| 9 | void intarrcopy(int *src, int *dst, int n) { | ||
| 10 | for (int i = 0; i < n; i++) | ||
| 11 | dst[i] = src[i]; | ||
| 12 | } | ||
| 13 | |||
| 14 | int sum(int *a, int n) { | ||
| 15 | int ret = 0; | ||
| 16 | for (int i = 0; i < n; i++) | ||
| 17 | ret += a[i]; | ||
| 18 | return ret; | ||
| 19 | } | ||
| 20 | |||
| 21 | bool is_perm(int *a, int n) { | ||
| 22 | int aux[n]; for (int i = 0; i < n; i++) aux[i] = 0; | ||
| 23 | for (int i = 0; i < n; i++) | ||
| 24 | if (a[i] < 0 || a[i] >= n) | ||
| 25 | return false; | ||
| 26 | else | ||
| 27 | aux[a[i]] = 1; | ||
| 28 | for (int i = 0; i < n; i++) | ||
| 29 | if (!aux[i]) | ||
| 30 | return false; | ||
| 31 | return true; | ||
| 32 | } | ||
| 33 | |||
| 34 | bool is_subset(int *a, int n, int k) { | ||
| 35 | int sum = 0; | ||
| 36 | for (int i = 0; i < n; i++) | ||
| 37 | sum += a[i] ? 1 : 0; | ||
| 38 | return sum == k; | ||
| 39 | } | ||
| 40 | |||
| 41 | int powint(int a, int b) { | ||
| 42 | return 0; | ||
| 43 | if (b == 0 || a == 1) | ||
| 44 | return 1; | ||
| 45 | if (a == 0) | ||
| 46 | return 0; | ||
| 47 | if (b < 0) | ||
| 48 | return 0; /* Immediate truncate (integer part is 0) */ | ||
| 49 | if (b % 2) { | ||
| 50 | return a * powint(a, b-1); | ||
| 51 | } else { | ||
| 52 | int x = powint(a, b/2); | ||
| 53 | return x*x; | ||
| 54 | } | ||
| 55 | } | ||
| 56 | |||
| 57 | int factorial(int n) { | ||
| 58 | if (n < 0) | ||
| 59 | return 0; | ||
| 60 | int ret = 1; | ||
| 61 | for (int i = 1; i <= n; i++) | ||
| 62 | ret *= i; | ||
| 63 | return ret; | ||
| 64 | } | ||
| 65 | |||
| 66 | int binomial(int n, int k) { | ||
| 67 | if (n < 0 || k < 0 || k > n) | ||
| 68 | return 0; | ||
| 69 | return factorial(n) / (factorial(k) * factorial(n-k)); | ||
| 70 | } | ||
| 71 | |||
| 72 | void int_to_digit_array(int a, int b, int n, int *r) { | ||
| 73 | if (b <= 1) | ||
| 74 | for (int i = 0; i < n; i++) | ||
| 75 | r[i] = 0; | ||
| 76 | else | ||
| 77 | for (int i = 0; i < n; i++, a /= b) | ||
| 78 | r[i] = a % b; | ||
| 79 | } | ||
| 80 | |||
| 81 | int digit_array_to_int(int *a, int n, int b) { | ||
| 82 | int ret = 0, p = 1; | ||
| 83 | for (int i = 0; i < n; i++, p *= b) | ||
| 84 | ret += a[i] * p; | ||
| 85 | return ret; | ||
| 86 | } | ||
| 87 | |||
| 88 | int perm_to_index(int *a, int n) { | ||
| 89 | if (!is_perm(a, n)) | ||
| 90 | return factorial(n); /* Error */ | ||
| 91 | int ret = 0; | ||
| 92 | for (int i = 0; i < n; i++) { | ||
| 93 | int c = 0; | ||
| 94 | for (int j = i+1; j < n; j++) | ||
| 95 | c += (a[i] > a[j]) ? 1 : 0; | ||
| 96 | ret += factorial(n-i-1) * c; | ||
| 97 | } | ||
| 98 | return ret; | ||
| 99 | } | ||
| 100 | |||
| 101 | void index_to_perm(int p, int n, int *r) { | ||
| 102 | if (p < 0 || p >= factorial(n)) /* Error */ | ||
| 103 | for (int i = 0; i < n; i++) | ||
| 104 | r[i] = -1; | ||
| 105 | int a[n]; for (int j = 0; j < n; j++) a[j] = 0; /* picked elements */ | ||
| 106 | for (int i = 0; i < n; i++) { | ||
| 107 | int c = 0, j = 0; | ||
| 108 | while (c <= p / factorial(n-i-1)) | ||
| 109 | c += a[j++] ? 0 : 1; | ||
| 110 | r[i] = j-1; | ||
| 111 | a[j-1] = 1; | ||
| 112 | p %= factorial(n-i-1); | ||
| 113 | } | ||
| 114 | } | ||
| 115 | |||
| 116 | int perm_sign(int *a, int n) { | ||
| 117 | if (!is_perm(a,n)) | ||
| 118 | return false; | ||
| 119 | int ret = 0; | ||
| 120 | for (int i = 0; i < n; i++) | ||
| 121 | for (int j = i+1; j < n; j++) | ||
| 122 | ret += (a[i]>a[j]) ? 1 : 0; | ||
| 123 | return ret % 2; | ||
| 124 | } | ||
| 125 | |||
| 126 | int subset_to_index(int *a, int n, int k) { | ||
| 127 | /* TODO: better checks */ | ||
| 128 | if (!is_subset(a, n, k)) | ||
| 129 | return binomial(n, k); /* Error */ | ||
| 130 | int ret = 0; | ||
| 131 | for (int i = 0; i < n; i++) { | ||
| 132 | if (k == n-i) | ||
| 133 | return ret; | ||
| 134 | if (a[i]) { | ||
| 135 | /*ret += factorial(n-i-1) / (factorial(k) * factorial(n-i-1-k));*/ | ||
| 136 | ret += binomial(n-i-1, k); | ||
| 137 | k--; | ||
| 138 | } | ||
| 139 | } | ||
| 140 | return ret; | ||
| 141 | } | ||
| 142 | |||
| 143 | void index_to_subset(int s, int n, int k, int *r) { | ||
| 144 | if (s < 0 || s >= binomial(n, k)) { /* Error */ | ||
| 145 | for (int i = 0; i < n; i++) | ||
| 146 | r[i] = -1; | ||
| 147 | return; | ||
| 148 | } | ||
| 149 | for (int i = 0; i < n; i++) { | ||
| 150 | if (k == n-i) { | ||
| 151 | for (int j = i; j < n; j++) | ||
| 152 | r[j] = 1; | ||
| 153 | return; | ||
| 154 | } | ||
| 155 | if (k == 0) { | ||
| 156 | for (int j = i; j < n; j++) | ||
| 157 | r[j] = 0; | ||
| 158 | return; | ||
| 159 | } | ||
| 160 | /*int v = factorial(n-i-1) / (factorial(k) * factorial(n-i-1-k));*/ | ||
| 161 | int v = binomial(n-i-1, k); | ||
| 162 | if (s >= v) { | ||
| 163 | r[i] = 1; | ||
| 164 | k--; | ||
| 165 | s -= v; | ||
| 166 | } else { | ||
| 167 | r[i] = 0; | ||
| 168 | } | ||
| 169 | } | ||
| 170 | } | ||
| 171 | |||
| 172 | void int_to_sum_zero_array(int x, int b, int n, int *a) { | ||
| 173 | if (b <= 1) { | ||
| 174 | for (int i = 0; i < n; i++) | ||
| 175 | a[i] = 0; | ||
| 176 | } else { | ||
| 177 | int_to_digit_array(x, b, n-1, a); | ||
| 178 | int s = 0; | ||
| 179 | for (int i = 0; i < n - 1; i++) | ||
| 180 | s = (s + a[i]) % b; | ||
| 181 | a[n-1] = (b - s) % b; | ||
| 182 | } | ||
| 183 | } | ||
| 184 | |||
| 185 | void apply_permutation(int *perm, int *set, int n) { | ||
| 186 | if (!is_perm(perm, n)) | ||
| 187 | return; | ||
| 188 | int aux[n]; | ||
| 189 | for (int i = 0; i < n; i++) | ||
| 190 | aux[i] = set[perm[i]]; | ||
| 191 | intarrcopy(aux, set, n); | ||
| 192 | } | ||
| 193 | |||
| 194 | void sum_arrays_mod(int *a, int *b, int n, int m) { | ||
| 195 | for (int i = 0; i < n; i++) | ||
| 196 | b[i] = (m <= 0) ? 0 : (a[i] + b[i]) % m; | ||
| 197 | } | ||
diff --git a/old/2021-02-28-transformcube-works/src/utils.h b/old/2021-02-28-transformcube-works/src/utils.h new file mode 100644 index 0000000..4b6df8c --- /dev/null +++ b/old/2021-02-28-transformcube-works/src/utils.h | |||
| @@ -0,0 +1,70 @@ | |||
| 1 | /* General utility functions */ | ||
| 2 | |||
| 3 | #ifndef UTILS_H | ||
| 4 | #define UTILS_H | ||
| 5 | |||
| 6 | #include <stdbool.h> | ||
| 7 | |||
| 8 | #define min(a,b) (((a) < (b)) ? (a) : (b)) | ||
| 9 | #define max(a,b) (((a) > (b)) ? (a) : (b)) | ||
| 10 | |||
| 11 | /* Some useful constants */ | ||
| 12 | #define pow2to11 2048 | ||
| 13 | #define pow2to12 4096 | ||
| 14 | #define pow3to7 2187 | ||
| 15 | #define pow3to8 6561 | ||
| 16 | #define pow12to4 20736 | ||
| 17 | #define factorial4 24 | ||
| 18 | #define factorial6 720 | ||
| 19 | #define factorial8 40320 | ||
| 20 | #define factorial12 479001600 | ||
| 21 | #define binom12on4 495 | ||
| 22 | #define binom8on4 70 | ||
| 23 | |||
| 24 | /* Generic utility functions */ | ||
| 25 | void swap(int *a, int *b); | ||
| 26 | void intarrcopy(int *src, int *dst, int n); | ||
| 27 | int sum(int *a, int n); | ||
| 28 | bool is_perm(int *a, int n); | ||
| 29 | bool is_perm(int *a, int n); | ||
| 30 | |||
| 31 | |||
| 32 | /* Standard mathematical functions */ | ||
| 33 | int powint(int a, int b); | ||
| 34 | int factorial(int n); | ||
| 35 | int binomial(int n, int k); | ||
| 36 | |||
| 37 | /* Converts the integer a to its representation in base b (first n digits | ||
| 38 | * only) and saves the result in r. */ | ||
| 39 | void int_to_digit_array(int a, int b, int n, int *r); | ||
| 40 | int digit_array_to_int(int *a, int n, int b); | ||
| 41 | |||
| 42 | /* Converts the first n-1 digits of a number to an array a of digits in base b; | ||
| 43 | * then adds one element to the array, so that the sum of the elements of a is | ||
| 44 | * zero modulo b. | ||
| 45 | * This is used for determing the edge orientation from an 11-bits integer or | ||
| 46 | * the corner orientation from a 7-trits integer. */ | ||
| 47 | void int_to_sum_zero_array(int x, int b, int n, int *a); | ||
| 48 | |||
| 49 | /* Converts a permutation on [0..(n-1)] into the integer i which is the index | ||
| 50 | * of the permutation in the sorted list of all n! such permutations. */ | ||
| 51 | int perm_to_index(int *a, int n); | ||
| 52 | void index_to_perm(int p, int n, int *r); | ||
| 53 | |||
| 54 | /* Determine the sign of a permutation */ | ||
| 55 | int perm_sign(int a[], int n); | ||
| 56 | |||
| 57 | /* Converts a k-element subset of a set from an array of n elements, of which k | ||
| 58 | * are 1 and n-k are 0, to its index in the sorted list of all such subsets. */ | ||
| 59 | int subset_to_index(int *a, int n, int k); | ||
| 60 | void index_to_subset(int s, int n, int k, int *r); | ||
| 61 | |||
| 62 | int ordered_subset_to_index(int *a, int n, int k); | ||
| 63 | void index_to_ordered_subset(int s, int n, int k, int *r); | ||
| 64 | |||
| 65 | void apply_permutation(int *perm, int *set, int n); | ||
| 66 | |||
| 67 | /* b[i] = (a[i]+b[i])%m for i=1,...,n */ | ||
| 68 | void sum_arrays_mod(int *a, int *b, int n, int m); | ||
| 69 | |||
| 70 | #endif | ||
diff --git a/old/2021-05-26-before-restyle/cube.c b/old/2021-05-26-before-restyle/cube.c new file mode 100644 index 0000000..603c66a --- /dev/null +++ b/old/2021-05-26-before-restyle/cube.c | |||
| @@ -0,0 +1,293 @@ | |||
| 1 | #include "cube.h" | ||
| 2 | |||
| 3 | typedef struct { | ||
| 4 | int ep[12],eofb[12],eorl[12],eoud[12],cp[8],coud[8],corl[8],cofb[8],cpos[6]; | ||
| 5 | } CubeArrayAllocated; | ||
| 6 | |||
| 7 | void allocate_cubearray(CubeArray *arr, CubeArrayAllocated *all); | ||
| 8 | |||
| 9 | char edge_string[12][5] = | ||
| 10 | { "UF", "UL", "UB", "UR", "DF", "DL", "DB", "DR", "FR", "FL", "BL", "BR" }; | ||
| 11 | char corner_string[8][5] = { "UFR","UFL","UBL","UBR","DFR","DFL","DBL","DBR" }; | ||
| 12 | char center_string[6][5] = { "U", "D", "R", "L", "F", "B" }; | ||
| 13 | |||
| 14 | int epe_solved[4] = {FR, FL, BL, BR}; | ||
| 15 | int eps_solved[4] = {UL, UR, DL, DR}; | ||
| 16 | int epm_solved[4] = {UF, UB, DF, DB}; | ||
| 17 | |||
| 18 | PieceFilter pf_all = {true,true,true,true,true,true,true,true,true,true,true}, | ||
| 19 | pf_cpos = { .cpos = true }, pf_cp = { .cp = true }, | ||
| 20 | pf_ep = { .epose = true, .eposs = true, .eposm = true }, | ||
| 21 | pf_e = {.epose=true}, pf_s={.eposs=true}, pf_m={.eposm=true}, | ||
| 22 | pf_eo = { .eofb = true, .eorl = true, .eoud = true }, | ||
| 23 | pf_co = { .coud = true, .cofb = true, .corl = true }; | ||
| 24 | |||
| 25 | void allocate_cubearray(CubeArray *arr, CubeArrayAllocated *all) { | ||
| 26 | arr->ep = all->ep; | ||
| 27 | arr->eofb = all->eofb; | ||
| 28 | arr->eorl = all->eorl; | ||
| 29 | arr->eoud = all->eoud; | ||
| 30 | arr->cp = all->cp; | ||
| 31 | arr->coud = all->coud; | ||
| 32 | arr->corl = all->corl; | ||
| 33 | arr->cofb = all->cofb; | ||
| 34 | arr->cpos = all->cpos; | ||
| 35 | } | ||
| 36 | |||
| 37 | void cube_to_arrays(Cube cube, CubeArray *arr, PieceFilter f) { | ||
| 38 | /* ep is the hardest */ | ||
| 39 | if (f.epose || f.eposs || f.eposm) | ||
| 40 | for (int i = 0; i < 12; i++) arr->ep[i] = -1; | ||
| 41 | if (f.epose) { | ||
| 42 | int epe[4], epose[12]; | ||
| 43 | index_to_perm(cube.epose % factorial(4), 4, epe); | ||
| 44 | index_to_subset(cube.epose / factorial(4), 12, 4, epose); | ||
| 45 | for (int i = 0, ie = 0; i < 12; i++) | ||
| 46 | if (epose[i]) arr->ep[i] = epe_solved[epe[ie++]]; | ||
| 47 | } | ||
| 48 | if (f.eposs) { | ||
| 49 | int eps[4], eposs[12]; | ||
| 50 | index_to_perm(cube.eposs % factorial(4), 4, eps); | ||
| 51 | index_to_subset(cube.eposs / factorial(4), 12, 4, eposs); | ||
| 52 | for (int i = 0; i < 4; i++) swap(&eposs[eps_solved[i]], &eposs[i+8]); | ||
| 53 | for (int i = 0, is = 0; i < 12; i++) | ||
| 54 | if (eposs[i]) arr->ep[i] = eps_solved[eps[is++]]; | ||
| 55 | } | ||
| 56 | if (f.eposm) { | ||
| 57 | int epm[4], eposm[12]; | ||
| 58 | index_to_perm(cube.eposm % factorial(4), 4, epm); | ||
| 59 | index_to_subset(cube.eposm / factorial(4), 12, 4, eposm); | ||
| 60 | for (int i = 0; i < 4; i++) swap(&eposm[epm_solved[i]], &eposm[i+8]); | ||
| 61 | for (int i = 0, im = 0; i < 12; i++) | ||
| 62 | if (eposm[i]) arr->ep[i] = epm_solved[epm[im++]]; | ||
| 63 | } | ||
| 64 | |||
| 65 | /* All the others */ | ||
| 66 | if (f.eofb) int_to_sum_zero_array(cube.eofb, 2, 12, arr->eofb); | ||
| 67 | if (f.eorl) int_to_sum_zero_array(cube.eorl, 2, 12, arr->eorl); | ||
| 68 | if (f.eoud) int_to_sum_zero_array(cube.eoud, 2, 12, arr->eoud); | ||
| 69 | if (f.cp) index_to_perm( cube.cp, 8, arr->cp); | ||
| 70 | if (f.coud) int_to_sum_zero_array(cube.coud, 3, 8, arr->coud); | ||
| 71 | if (f.corl) int_to_sum_zero_array(cube.corl, 3, 8, arr->corl); | ||
| 72 | if (f.cofb) int_to_sum_zero_array(cube.cofb, 3, 8, arr->cofb); | ||
| 73 | if (f.cpos) index_to_perm( cube.cpos, 6, arr->cpos); | ||
| 74 | } | ||
| 75 | |||
| 76 | Cube arrays_to_cube(CubeArray arr, PieceFilter f) { | ||
| 77 | Cube ret = {0}; | ||
| 78 | |||
| 79 | /* Again, ep is the hardest part */ | ||
| 80 | if (f.epose) { | ||
| 81 | int epe[4], epose[12] = {0,0,0,0,0,0,0,0,0,0,0,0}; | ||
| 82 | for (int i = 0, ie = 0; i < 12; i++) | ||
| 83 | for (int j = 0; j < 4; j++) | ||
| 84 | if (arr.ep[i] == epe_solved[j]) | ||
| 85 | { epe[ie++] = j; epose[i] = 1; } | ||
| 86 | ret.epose = factorial(4)*subset_to_index(epose,12,4)+perm_to_index(epe,4); | ||
| 87 | } | ||
| 88 | if (f.eposs) { | ||
| 89 | int eps[4], eposs[12] = {0,0,0,0,0,0,0,0,0,0,0,0}; | ||
| 90 | for (int i = 0, is = 0; i < 12; i++) | ||
| 91 | for (int j = 0; j < 4; j++) | ||
| 92 | if (arr.ep[i] == eps_solved[j]) | ||
| 93 | { eps[is++] = j; eposs[i] = 1; } | ||
| 94 | for (int i = 0; i < 4; i++) swap(&eposs[eps_solved[i]], &eposs[i+8]); | ||
| 95 | ret.eposs = factorial(4)*subset_to_index(eposs,12,4)+perm_to_index(eps,4); | ||
| 96 | } | ||
| 97 | if (f.eposm) { | ||
| 98 | int epm[4], eposm[12] = {0,0,0,0,0,0,0,0,0,0,0,0}; | ||
| 99 | for (int i = 0, im = 0; i < 12; i++) | ||
| 100 | for (int j = 0; j < 4; j++) | ||
| 101 | if (arr.ep[i] == epm_solved[j]) | ||
| 102 | { epm[im++] = j; eposm[i] = 1; } | ||
| 103 | for (int i = 0; i < 4; i++) swap(&eposm[epm_solved[i]], &eposm[i+8]); | ||
| 104 | ret.eposm = factorial(4)*subset_to_index(eposm,12,4)+perm_to_index(epm,4); | ||
| 105 | } | ||
| 106 | if (f.eofb) ret.eofb = digit_array_to_int(arr.eofb, 11, 2); | ||
| 107 | if (f.eorl) ret.eorl = digit_array_to_int(arr.eorl, 11, 2); | ||
| 108 | if (f.eoud) ret.eoud = digit_array_to_int(arr.eoud, 11, 2); | ||
| 109 | if (f.cp) ret.cp = perm_to_index( arr.cp, 8 ); | ||
| 110 | if (f.coud) ret.coud = digit_array_to_int(arr.coud, 7, 3); | ||
| 111 | if (f.corl) ret.corl = digit_array_to_int(arr.corl, 7, 3); | ||
| 112 | if (f.cofb) ret.cofb = digit_array_to_int(arr.cofb, 7, 3); | ||
| 113 | if (f.cpos) ret.cpos = perm_to_index( arr.cpos, 6 ); | ||
| 114 | |||
| 115 | return ret; | ||
| 116 | } | ||
| 117 | |||
| 118 | int piece_orientation(Cube cube, int piece, char *orientation) { | ||
| 119 | int arr[12], n, b; | ||
| 120 | uint16_t x; | ||
| 121 | if (!strcmp(orientation, "eofb")) { x = cube.eofb; n = 12; b = 2; } else | ||
| 122 | if (!strcmp(orientation, "eorl")) { x = cube.eorl; n = 12; b = 2; } else | ||
| 123 | if (!strcmp(orientation, "eoud")) { x = cube.eoud; n = 12; b = 2; } else | ||
| 124 | if (!strcmp(orientation, "coud")) { x = cube.coud; n = 8; b = 3; } else | ||
| 125 | if (!strcmp(orientation, "corl")) { x = cube.corl; n = 8; b = 3; } else | ||
| 126 | if (!strcmp(orientation, "cofb")) { x = cube.cofb; n = 8; b = 3; } | ||
| 127 | else return -1; | ||
| 128 | |||
| 129 | int_to_sum_zero_array(x, b, n, arr); | ||
| 130 | if (piece < n) | ||
| 131 | return arr[piece]; | ||
| 132 | return -1; | ||
| 133 | } | ||
| 134 | |||
| 135 | Center center_at(Cube cube, Center c) { | ||
| 136 | static CubeArrayAllocated all = {0}; | ||
| 137 | CubeArray arr = {0}; | ||
| 138 | allocate_cubearray(&arr, &all); | ||
| 139 | cube_to_arrays(cube, &arr, pf_cpos); | ||
| 140 | return arr.cpos[c]; | ||
| 141 | } | ||
| 142 | |||
| 143 | Edge edge_at(Cube cube, Edge e) { | ||
| 144 | static CubeArrayAllocated all = {0}; | ||
| 145 | CubeArray arr = {0}; | ||
| 146 | allocate_cubearray(&arr, &all); | ||
| 147 | cube_to_arrays(cube, &arr, pf_ep); | ||
| 148 | return arr.ep[e]; | ||
| 149 | } | ||
| 150 | |||
| 151 | Corner corner_at(Cube cube, Corner c) { | ||
| 152 | static CubeArrayAllocated all = {0}; | ||
| 153 | CubeArray arr = {0}; | ||
| 154 | allocate_cubearray(&arr, &all); | ||
| 155 | cube_to_arrays(cube, &arr, pf_cp); | ||
| 156 | return arr.cp[c]; | ||
| 157 | } | ||
| 158 | |||
| 159 | bool block_solved(Cube cube, Block block) { | ||
| 160 | static CubeArrayAllocated all = {0}; | ||
| 161 | CubeArray arr = {0}; | ||
| 162 | allocate_cubearray(&arr, &all); | ||
| 163 | cube_to_arrays(cube, &arr, pf_all); | ||
| 164 | |||
| 165 | bool ret = true; | ||
| 166 | |||
| 167 | for (int i = 0; i < 12; i++) | ||
| 168 | ret = ret && !(block.edge[i] && (arr.ep[i] != i || arr.eofb[i])); | ||
| 169 | for (int i = 0; i < 8; i++) | ||
| 170 | ret = ret && !(block.corner[i] && (arr.cp[i] != i || arr.coud[i])); | ||
| 171 | for (int i = 0; i < 6; i++) | ||
| 172 | ret = ret && !(block.center[i] && arr.cpos[i] != i); | ||
| 173 | |||
| 174 | return ret; | ||
| 175 | } | ||
| 176 | |||
| 177 | bool equal(Cube c1, Cube c2) { | ||
| 178 | return c1.eofb == c2.eofb && c1.epose == c2.epose && | ||
| 179 | c1.eposs == c2.eposs && c1.eposm == c2.eposm && | ||
| 180 | c1.coud == c2.coud && c1.cp == c2.cp && | ||
| 181 | c1.cpos == c2.cpos; | ||
| 182 | } | ||
| 183 | |||
| 184 | bool is_solved(Cube cube) { | ||
| 185 | /* TODO: might return true if cube is not solvable but looks solved form one | ||
| 186 | of the incompatible interpretations (e.g. eofb and ep solved, but | ||
| 187 | eorl not solve) */ | ||
| 188 | return !cube.eofb && !cube.coud && !cube.cp && | ||
| 189 | !cube.epose && !cube.eposs && !cube.eposm && !cube.cpos; | ||
| 190 | } | ||
| 191 | |||
| 192 | void print_cube(Cube cube) { | ||
| 193 | static CubeArrayAllocated all = {0}; | ||
| 194 | CubeArray arrx = {0}; | ||
| 195 | allocate_cubearray(&arrx, &all); | ||
| 196 | cube_to_arrays(cube, &arrx, pf_all); | ||
| 197 | |||
| 198 | for (int i = 0; i < 12; i++) printf(" %s ", edge_string[arrx.ep[i]]); | ||
| 199 | printf("\n"); | ||
| 200 | for (int i = 0; i < 12; i++) printf(" %c ", arrx.eofb[i] + '0'); | ||
| 201 | printf("\n"); | ||
| 202 | for (int i = 0; i < 8; i++) printf("%s ", corner_string[arrx.cp[i]]); | ||
| 203 | printf("\n"); | ||
| 204 | for (int i = 0; i < 8; i++) printf(" %c ", arrx.coud[i] + '0'); | ||
| 205 | printf("\n"); | ||
| 206 | for (int i = 0; i < 6; i++) printf(" %s ", center_string[arrx.cpos[i]]); | ||
| 207 | printf("\n"); | ||
| 208 | } | ||
| 209 | |||
| 210 | Cube admissible_ep(Cube cube, PieceFilter f) { | ||
| 211 | static CubeArrayAllocated all = {0}; | ||
| 212 | CubeArray arrx = {0}; | ||
| 213 | allocate_cubearray(&arrx, &all); | ||
| 214 | cube_to_arrays(cube, &arrx, f); | ||
| 215 | |||
| 216 | bool used[12] = {0}; | ||
| 217 | for (int i = 0; i < 12; i++) | ||
| 218 | if (arrx.ep[i] != -1) | ||
| 219 | used[arrx.ep[i]] = true; | ||
| 220 | for (int i = 0, j = 0; i < 12; i++) { | ||
| 221 | while (j < 11 && used[j]) j++; | ||
| 222 | if (arrx.ep[i] == -1) | ||
| 223 | arrx.ep[i] = j++; | ||
| 224 | } | ||
| 225 | |||
| 226 | return arrays_to_cube(arrx, pf_ep); | ||
| 227 | } | ||
| 228 | |||
| 229 | Cube inverse_cube(Cube cube) { | ||
| 230 | static CubeArrayAllocated all = {0}, invall = {0}; | ||
| 231 | CubeArray arrx = {0}, invx = {0}; | ||
| 232 | allocate_cubearray(&arrx, &all); | ||
| 233 | allocate_cubearray(&invx, &invall); | ||
| 234 | |||
| 235 | cube_to_arrays(cube, &arrx, pf_all); | ||
| 236 | |||
| 237 | for (int i = 0; i < 12; i++) { | ||
| 238 | invx.ep[arrx.ep[i]] = i; | ||
| 239 | invx.eofb[arrx.ep[i]] = arrx.eofb[i]; | ||
| 240 | invx.eorl[arrx.ep[i]] = arrx.eorl[i]; | ||
| 241 | invx.eoud[arrx.ep[i]] = arrx.eoud[i]; | ||
| 242 | } | ||
| 243 | for (int i = 0; i < 8; i++) { | ||
| 244 | invx.cp[arrx.cp[i]] = i; | ||
| 245 | invx.coud[arrx.cp[i]] = (3 - arrx.coud[i])%3; | ||
| 246 | invx.corl[arrx.cp[i]] = (3 - arrx.corl[i])%3; | ||
| 247 | invx.cofb[arrx.cp[i]] = (3 - arrx.cofb[i])%3; | ||
| 248 | } | ||
| 249 | for (int i = 0; i < 6; i++) | ||
| 250 | invx.cpos[arrx.cpos[i]] = i; | ||
| 251 | |||
| 252 | return arrays_to_cube(invx, pf_all); | ||
| 253 | } | ||
| 254 | |||
| 255 | Cube move_via_arrays(CubeArray arr, Cube c, PieceFilter f) { | ||
| 256 | static CubeArrayAllocated all = {0}; | ||
| 257 | CubeArray arrx = {0}; | ||
| 258 | allocate_cubearray(&arrx, &all); | ||
| 259 | |||
| 260 | cube_to_arrays(c, &arrx, f); | ||
| 261 | |||
| 262 | if (f.epose || f.eposs || f.eposm) | ||
| 263 | apply_permutation( arr.ep, arrx.ep, 12 ); | ||
| 264 | if (f.eofb) { apply_permutation( arr.ep, arrx.eofb, 12 ); | ||
| 265 | sum_arrays_mod( arr.eofb, arrx.eofb, 12, 2 ); } | ||
| 266 | if (f.eorl) { apply_permutation( arr.ep, arrx.eorl, 12 ); | ||
| 267 | sum_arrays_mod( arr.eorl, arrx.eorl, 12, 2 ); } | ||
| 268 | if (f.eoud) { apply_permutation( arr.ep, arrx.eoud, 12 ); | ||
| 269 | sum_arrays_mod( arr.eoud, arrx.eoud, 12, 2 ); } | ||
| 270 | if (f.cp) apply_permutation( arr.cp, arrx.cp, 8 ); | ||
| 271 | if (f.coud) { apply_permutation( arr.cp, arrx.coud, 8 ); | ||
| 272 | sum_arrays_mod( arr.coud, arrx.coud, 8, 3 ); } | ||
| 273 | if (f.corl) { apply_permutation( arr.cp, arrx.corl, 8 ); | ||
| 274 | sum_arrays_mod( arr.corl, arrx.corl, 8, 3 ); } | ||
| 275 | if (f.cofb) { apply_permutation( arr.cp, arrx.cofb, 8 ); | ||
| 276 | sum_arrays_mod( arr.cofb, arrx.cofb, 8, 3 ); } | ||
| 277 | if (f.cpos) apply_permutation( arr.cpos, arrx.cpos, 6 ); | ||
| 278 | |||
| 279 | return arrays_to_cube(arrx, f); | ||
| 280 | } | ||
| 281 | |||
| 282 | Cube compose_filtered(Cube c2, Cube c1, PieceFilter f) { | ||
| 283 | static CubeArrayAllocated all = {0}; | ||
| 284 | CubeArray arrx = {0}; | ||
| 285 | allocate_cubearray(&arrx, &all); | ||
| 286 | |||
| 287 | cube_to_arrays(c2, &arrx, f); | ||
| 288 | return move_via_arrays(arrx, c1, f); | ||
| 289 | } | ||
| 290 | |||
| 291 | Cube compose(Cube c2, Cube c1) { | ||
| 292 | return compose_filtered(c2, c1, pf_all); | ||
| 293 | } | ||
diff --git a/old/2021-05-26-before-restyle/cube.h b/old/2021-05-26-before-restyle/cube.h new file mode 100644 index 0000000..0c9fc7b --- /dev/null +++ b/old/2021-05-26-before-restyle/cube.h | |||
| @@ -0,0 +1,65 @@ | |||
| 1 | #ifndef CUBE_H | ||
| 2 | #define CUBE_H | ||
| 3 | |||
| 4 | #include <stdio.h> | ||
| 5 | #include <stdbool.h> | ||
| 6 | #include <stdint.h> | ||
| 7 | #include <string.h> | ||
| 8 | #include "utils.h" | ||
| 9 | |||
| 10 | typedef enum {U_center,D_center,R_center,L_center,F_center,B_center} Center; | ||
| 11 | typedef enum { UF, UL, UB, UR, DF, DL, DB, DR, FR, FL, BL, BR } Edge; | ||
| 12 | typedef enum { UFR, UFL, UBL, UBR, DFR, DFL, DBL, DBR } Corner; | ||
| 13 | |||
| 14 | typedef struct { | ||
| 15 | uint16_t eofb, eorl, eoud, coud, cofb, corl, | ||
| 16 | epose, eposs, eposm, cp, cpos; | ||
| 17 | } Cube; | ||
| 18 | |||
| 19 | typedef struct { | ||
| 20 | bool edge[12], corner[8], center[6]; | ||
| 21 | } Block; | ||
| 22 | |||
| 23 | typedef struct { | ||
| 24 | bool epose, eposs, eposm, eofb, eorl, eoud, cp, coud, cofb, corl, cpos; | ||
| 25 | } PieceFilter; | ||
| 26 | |||
| 27 | typedef struct { | ||
| 28 | int *ep, *eofb, *eorl, *eoud, *cp, *coud, *corl, *cofb, *cpos; | ||
| 29 | } CubeArray; | ||
| 30 | |||
| 31 | extern PieceFilter pf_all, pf_cpos, pf_ep, pf_cp, | ||
| 32 | pf_e, pf_s, pf_m, pf_eo, pf_co; | ||
| 33 | |||
| 34 | void cube_to_arrays(Cube cube, CubeArray *arr, PieceFilter f); | ||
| 35 | Cube arrays_to_cube(CubeArray arr, PieceFilter f); | ||
| 36 | |||
| 37 | /* piece can be edge or corner and orientation is any of the following: | ||
| 38 | "eofb", "eorl", "eoud", "coud", "corl", "cofb" | ||
| 39 | Return either 0 (oriented) or 1 for edges and 0, 1 or 2 for corners */ | ||
| 40 | int piece_orientation(Cube cube, int piece, char *orientation); | ||
| 41 | Center center_at(Cube cube, Center c); | ||
| 42 | Edge edge_at(Cube cube, Edge e); | ||
| 43 | Corner corner_at(Cube cube, Corner c); | ||
| 44 | bool block_solved(Cube cube, Block); | ||
| 45 | /* Aggiungi funzioni per "queries" sul cubo: se pezzo è orientato rispetto ad | ||
| 46 | un certo asse, se il pezzo è risolto... */ | ||
| 47 | /* Would be nice: a funciton block_solved(Cube c, Block b), where Block is | ||
| 48 | something like struct {bool centers[6], edges[12], corners[8]} | ||
| 49 | (The advantage over checking pieces one by one is that I can convert | ||
| 50 | to cubearray only once and for all) */ | ||
| 51 | /* Altro TODO, ma forse non ne vale la pena: pre-calcolare tutti i possibili | ||
| 52 | valori per questi, e salvare i risultati in array (facile per cp e cpos, | ||
| 53 | mentre per ep bisogna anche cercare quale tra epose, eposs e eposm contiene | ||
| 54 | il valore giusto) */ | ||
| 55 | |||
| 56 | bool equal(Cube c1, Cube c2); | ||
| 57 | bool is_solved(Cube cube); | ||
| 58 | void print_cube(Cube cube); | ||
| 59 | Cube admissible_ep(Cube cube, PieceFilter f); /* Returns admissible ep */ | ||
| 60 | Cube inverse_cube(Cube cube); | ||
| 61 | Cube compose(Cube c2, Cube c1); /* Use c2 as an alg on c1 */ | ||
| 62 | Cube compose_filtered(Cube c2, Cube c1, PieceFilter f); | ||
| 63 | Cube move_via_arrays(CubeArray arr, Cube c, PieceFilter pf); | ||
| 64 | |||
| 65 | #endif | ||
diff --git a/old/2021-05-26-before-restyle/main.c b/old/2021-05-26-before-restyle/main.c new file mode 100644 index 0000000..cb61526 --- /dev/null +++ b/old/2021-05-26-before-restyle/main.c | |||
| @@ -0,0 +1,24 @@ | |||
| 1 | #include <stdio.h> | ||
| 2 | #include "cube.h" | ||
| 3 | #include "moves.h" | ||
| 4 | #include "solve.h" | ||
| 5 | #include "transformations.h" | ||
| 6 | |||
| 7 | int main() { | ||
| 8 | init_ttables(true, true); | ||
| 9 | init_aux_tables(); | ||
| 10 | init_transformations(true, true); | ||
| 11 | |||
| 12 | |||
| 13 | char moves[100] = "R' D2 F2 U2 R F2 R D2 L' R2 D2 F D' L' U' B R' D' U R' B"; | ||
| 14 | NissMove alg[100]; | ||
| 15 | read_moves(moves, alg, 100); | ||
| 16 | Cube cube = apply_alg(alg, (Cube){0}); | ||
| 17 | print_cube(transform_cube(rd, cube)); | ||
| 18 | |||
| 19 | transform_alg(rd, alg); | ||
| 20 | print_alg(alg); | ||
| 21 | |||
| 22 | |||
| 23 | return 0; | ||
| 24 | } | ||
diff --git a/old/2021-05-26-before-restyle/moves.c b/old/2021-05-26-before-restyle/moves.c new file mode 100644 index 0000000..15f0238 --- /dev/null +++ b/old/2021-05-26-before-restyle/moves.c | |||
| @@ -0,0 +1,412 @@ | |||
| 1 | #include "moves.h" | ||
| 2 | |||
| 3 | Cube apply_move_cubearray(Move m, Cube cube, PieceFilter f); | ||
| 4 | /* void sort_cancel_rotate(NissMove *alg, int n, bool inv, int top, int front); */ | ||
| 5 | bool read_ttables_file(); | ||
| 6 | bool write_ttables_file(); | ||
| 7 | |||
| 8 | /* Transition tables */ | ||
| 9 | uint16_t epose_ttable[NMOVES][factorial12/factorial8]; | ||
| 10 | uint16_t eposs_ttable[NMOVES][factorial12/factorial8]; | ||
| 11 | uint16_t eposm_ttable[NMOVES][factorial12/factorial8]; | ||
| 12 | uint16_t eofb_ttable[NMOVES][pow2to11]; | ||
| 13 | uint16_t eorl_ttable[NMOVES][pow2to11]; | ||
| 14 | uint16_t eoud_ttable[NMOVES][pow2to11]; | ||
| 15 | uint16_t cp_ttable[NMOVES][factorial8]; | ||
| 16 | uint16_t coud_ttable[NMOVES][pow3to7]; | ||
| 17 | uint16_t cofb_ttable[NMOVES][pow3to7]; | ||
| 18 | uint16_t corl_ttable[NMOVES][pow3to7]; | ||
| 19 | uint16_t cpos_ttable[NMOVES][factorial6]; | ||
| 20 | |||
| 21 | bool commute[NMOVES][NMOVES]; | ||
| 22 | bool possible_next[NMOVES][NMOVES][NMOVES]; | ||
| 23 | Move inverse[NMOVES]; | ||
| 24 | NissMove rotation_algs[24][3] = { | ||
| 25 | { { .m = NULLMOVE }, { .m = NULLMOVE }, { .m = NULLMOVE } }, | ||
| 26 | { { .m = y }, { .m = NULLMOVE }, { .m = NULLMOVE } }, | ||
| 27 | { { .m = y2 }, { .m = NULLMOVE }, { .m = NULLMOVE } }, | ||
| 28 | { { .m = y3 }, { .m = NULLMOVE }, { .m = NULLMOVE } }, | ||
| 29 | { { .m = z2 }, { .m = NULLMOVE }, { .m = NULLMOVE } }, | ||
| 30 | { { .m = y }, { .m = z2 }, { .m = NULLMOVE } }, | ||
| 31 | { { .m = x2 }, { .m = NULLMOVE }, { .m = NULLMOVE } }, | ||
| 32 | { { .m = y3 }, { .m = z2 }, { .m = NULLMOVE } }, | ||
| 33 | { { .m = z3 }, { .m = NULLMOVE }, { .m = NULLMOVE } }, | ||
| 34 | { { .m = z3 }, { .m = y }, { .m = NULLMOVE } }, | ||
| 35 | { { .m = z3 }, { .m = y2 }, { .m = NULLMOVE } }, | ||
| 36 | { { .m = z3 }, { .m = y3 }, { .m = NULLMOVE } }, | ||
| 37 | { { .m = z }, { .m = NULLMOVE }, { .m = NULLMOVE } }, | ||
| 38 | { { .m = z }, { .m = y3 }, { .m = NULLMOVE } }, | ||
| 39 | { { .m = z }, { .m = y2 }, { .m = NULLMOVE } }, | ||
| 40 | { { .m = z }, { .m = y }, { .m = NULLMOVE } }, | ||
| 41 | { { .m = x }, { .m = y2 }, { .m = NULLMOVE } }, | ||
| 42 | { { .m = x }, { .m = y }, { .m = NULLMOVE } }, | ||
| 43 | { { .m = x }, { .m = NULLMOVE }, { .m = NULLMOVE } }, | ||
| 44 | { { .m = x }, { .m = y3 }, { .m = NULLMOVE } }, | ||
| 45 | { { .m = x3 }, { .m = NULLMOVE }, { .m = NULLMOVE } }, | ||
| 46 | { { .m = x3 }, { .m = y }, { .m = NULLMOVE } }, | ||
| 47 | { { .m = x3 }, { .m = y2 }, { .m = NULLMOVE } }, | ||
| 48 | { { .m = x3 }, { .m = y3 }, { .m = NULLMOVE } }, | ||
| 49 | }; | ||
| 50 | |||
| 51 | char move_string[NMOVES][5] = | ||
| 52 | { "-", | ||
| 53 | "U", "U2", "U\'", "D", "D2", "D\'", "R", "R2", "R\'", | ||
| 54 | "L", "L2", "L\'", "F", "F2", "F\'", "B", "B2", "B\'", | ||
| 55 | "Uw", "Uw2", "Uw\'", "Dw", "Dw2", "Dw\'", "Rw", "Rw2", "Rw\'", | ||
| 56 | "Lw", "Lw2", "Lw\'", "Fw", "Fw2", "Fw\'", "Bw", "Bw2", "Bw\'", | ||
| 57 | "M", "M2", "M\'", "S", "S2", "S\'", "E", "E2", "E\'", | ||
| 58 | "x", "x2", "x\'", "y", "y2", "y\'", "z", "z2", "z\'" }; | ||
| 59 | |||
| 60 | /* For each type of pieces only the effects of U, x and y are described */ | ||
| 61 | int edge_cycle[NMOVES][12] = | ||
| 62 | { [U] = {UR, UF, UL, UB, DF, DL, DB, DR, FR, FL, BL, BR}, | ||
| 63 | [x] = {DF, FL, UF, FR, DB, BL, UB, BR, DR, DL, UL, UR}, | ||
| 64 | [y] = {UR, UF, UL, UB, DR, DF, DL, DB, BR, FR, FL, BL} }; | ||
| 65 | int eofb_flipped[NMOVES][12] = | ||
| 66 | { [x] = { [UF] = 1, [UB] = 1, [DF] = 1, [DB] = 1 }, | ||
| 67 | [y] = { [FR] = 1, [FL] = 1, [BL] = 1, [BR] = 1 } }; | ||
| 68 | int eorl_flipped[NMOVES][12] = | ||
| 69 | { [x] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, | ||
| 70 | [y] = { [FR] = 1, [FL] = 1, [BL] = 1, [BR] = 1 } }; | ||
| 71 | int eoud_flipped[NMOVES][12] = | ||
| 72 | { [U] = { [UF] = 1, [UL] = 1, [UB] = 1, [UR] = 1 }, | ||
| 73 | [x] = { [UF] = 1, [UB] = 1, [DF] = 1, [DB] = 1 }, | ||
| 74 | [y] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 } }; | ||
| 75 | int corner_cycle[NMOVES][8] = | ||
| 76 | { [U] = {UBR, UFR, UFL, UBL, DFR, DFL, DBL, DBR}, | ||
| 77 | [x] = {DFR, DFL, UFL, UFR, DBR, DBL, UBL, UBR}, | ||
| 78 | [y] = {UBR, UFR, UFL, UBL, DBR, DFR, DFL, DBL} }; | ||
| 79 | int coud_flipped[NMOVES][8] = | ||
| 80 | { [x] = {[UFR]=2,[UBR]=1,[DBR]=2,[DFR]=1,[UFL]=1,[UBL]=2,[DBL]=1,[DFL]=2} }; | ||
| 81 | int corl_flipped[NMOVES][8] = | ||
| 82 | { [U] = { [UFR] = 1, [UBR] = 2, [UBL] = 1, [UFL] = 2 }, | ||
| 83 | [y] = {[UFR]=1,[UBR]=2,[UBL]=1,[UFL]=2,[DFR]=2,[DBR]=1,[DBL]=2,[DFL]=1} }; | ||
| 84 | int cofb_flipped[NMOVES][8] = | ||
| 85 | { [U] = { [UFR] = 2, [UBR] = 1, [UBL] = 2, [UFL] = 1 }, | ||
| 86 | [x] = {[UFR]=1,[UBR]=2,[DFR]=2,[DBR]=1,[UBL]=1,[UFL]=2,[DBL]=2,[DFL]=1}, | ||
| 87 | [y] = {[UFR]=2,[UBR]=1,[UBL]=2,[UFL]=1,[DFR]=1,[DBR]=2,[DBL]=1,[DFL]=2} }; | ||
| 88 | int center_cycle[NMOVES][6] = | ||
| 89 | { [x] = {F_center, B_center, R_center, L_center, D_center, U_center}, | ||
| 90 | [y] = {U_center, D_center, B_center, F_center, R_center, L_center} }; | ||
| 91 | |||
| 92 | /* Each move is reduced to a combination of U, x and y using this table */ | ||
| 93 | Move equiv_moves[NMOVES][14] = { | ||
| 94 | [U] = { U, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, | ||
| 95 | [U2] = { U, U, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, | ||
| 96 | [U3] = { U, U, U, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, | ||
| 97 | [D] = { x, x, U, x, x, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, | ||
| 98 | [D2] = { x, x, U, U, x, x, 0, 0, 0, 0, 0, 0, 0, 0 }, | ||
| 99 | [D3] = { x, x, U, U, U, x, x, 0, 0, 0, 0, 0, 0, 0 }, | ||
| 100 | [R] = { y, x, U, x, x, x, y, y, y, 0, 0, 0, 0, 0 }, | ||
| 101 | [R2] = { y, x, U, U, x, x, x, y, y, y, 0, 0, 0, 0 }, | ||
| 102 | [R3] = { y, x, U, U, U, x, x, x, y, y, y, 0, 0, 0 }, | ||
| 103 | [L] = { y, y, y, x, U, x, x, x, y, 0, 0, 0, 0, 0 }, | ||
| 104 | [L2] = { y, y, y, x, U, U, x, x, x, y, 0, 0, 0, 0 }, | ||
| 105 | [L3] = { y, y, y, x, U, U, U, x, x, x, y, 0, 0, 0 }, | ||
| 106 | [F] = { x, U, x, x, x, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, | ||
| 107 | [F2] = { x, U, U, x, x, x, 0, 0, 0, 0, 0, 0, 0, 0 }, | ||
| 108 | [F3] = { x, U, U, U, x, x, x, 0, 0, 0, 0, 0, 0, 0 }, | ||
| 109 | [B] = { x, x, x, U, x, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, | ||
| 110 | [B2] = { x, x, x, U, U, x, 0, 0, 0, 0, 0, 0, 0, 0 }, | ||
| 111 | [B3] = { x, x, x, U, U, U, x, 0, 0, 0, 0, 0, 0, 0 }, | ||
| 112 | |||
| 113 | [Uw] = { x, x, U, x, x, y, 0, 0, 0, 0, 0, 0, 0, 0 }, | ||
| 114 | [Uw2] = { x, x, U, U, x, x, y, y, 0, 0, 0, 0, 0, 0 }, | ||
| 115 | [Uw3] = { x, x, U, U, U, x, x, y, y, y, 0, 0, 0, 0 }, | ||
| 116 | [Dw] = { U, y, y, y, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, | ||
| 117 | [Dw2] = { U, U, y, y, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, | ||
| 118 | [Dw3] = { U, U, U, y, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, | ||
| 119 | [Rw] = { y, y, y, x, U, x, x, x, y, x, 0, 0, 0, 0 }, | ||
| 120 | [Rw2] = { y, y, y, x, U, U, x, x, x, y, x, x, 0, 0 }, | ||
| 121 | [Rw3] = { y, y, y, x, U, U, U, y, x, x, x, y, 0, 0 }, | ||
| 122 | [Lw] = { y, x, U, x, x, x, y, y, y, x, x, x, 0, 0 }, | ||
| 123 | [Lw2] = { y, x, U, U, x, x, x, y, y, y, x, x, 0, 0 }, | ||
| 124 | [Lw3] = { y, x, U, U, U, x, x, x, y, y, y, x, 0, 0 }, | ||
| 125 | [Fw] = { x, x, x, U, y, y, y, x, 0, 0, 0, 0, 0, 0 }, | ||
| 126 | [Fw2] = { x, x, x, U, U, y, y, x, 0, 0, 0, 0, 0, 0 }, | ||
| 127 | [Fw3] = { x, x, x, U, U, U, y, x, 0, 0, 0, 0, 0, 0 }, | ||
| 128 | [Bw] = { x, U, y, y, y, x, x, x, 0, 0, 0, 0, 0, 0 }, | ||
| 129 | [Bw2] = { x, U, U, y, y, x, x, x, 0, 0, 0, 0, 0, 0 }, | ||
| 130 | [Bw3] = { x, U, U, U, y, x, x, x, 0, 0, 0, 0, 0, 0 }, | ||
| 131 | |||
| 132 | [M] = { y, x, U, x, x, U, U, U, y, x, y, y, y, 0 }, | ||
| 133 | [M2] = { y, x, U, U, x, x, U, U, x, x, x, y, 0, 0 }, | ||
| 134 | [M3] = { y, x, U, U, U, x, x, U, y, x, x, x, y, 0 }, | ||
| 135 | [S] = { x, U, U, U, x, x, U, y, y, y, x, 0, 0, 0 }, | ||
| 136 | [S2] = { x, U, U, x, x, U, U, y, y, x, 0, 0, 0, 0 }, | ||
| 137 | [S3] = { x, U, x, x, U, U, U, y, x, 0, 0, 0, 0, 0 }, | ||
| 138 | [E] = { U, x, x, U, U, U, x, x, y, y, y, 0, 0, 0 }, | ||
| 139 | [E2] = { U, U, x, x, U, U, x, x, y, y, 0, 0, 0, 0 }, | ||
| 140 | [E3] = { U, U, U, x, x, U, x, x, y, 0, 0, 0, 0, 0 }, | ||
| 141 | |||
| 142 | [x] = { x, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, | ||
| 143 | [x2] = { x, x, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, | ||
| 144 | [x3] = { x, x, x, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, | ||
| 145 | [y] = { y, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, | ||
| 146 | [y2] = { y, y, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, | ||
| 147 | [y3] = { y, y, y, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, | ||
| 148 | [z] = { y, y, y, x, y, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, | ||
| 149 | [z2] = { y, y, x, x, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, | ||
| 150 | [z3] = { y, x, y, y, y, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, | ||
| 151 | }; | ||
| 152 | |||
| 153 | /* Movesets */ | ||
| 154 | bool standard_moveset[NMOVES] = { | ||
| 155 | [U] = true, [U2] = true, [U3] = true, [D] = true, [D2] = true, [D3] = true, | ||
| 156 | [R] = true, [R2] = true, [R3] = true, [L] = true, [L2] = true, [L3] = true, | ||
| 157 | [F] = true, [F2] = true, [F3] = true, [B] = true, [B2] = true, [B3] = true, | ||
| 158 | }; | ||
| 159 | |||
| 160 | bool is_solved_up_to_reorient(Cube cube) { | ||
| 161 | for (int i = 0; i < 25; i++) | ||
| 162 | if (is_solved(apply_alg(rotation_algs[i], cube))) | ||
| 163 | return true; | ||
| 164 | return false; | ||
| 165 | } | ||
| 166 | |||
| 167 | Cube apply_move_cubearray(Move m, Cube cube, PieceFilter f) { | ||
| 168 | return move_via_arrays((CubeArray) | ||
| 169 | { edge_cycle[m], eofb_flipped[m], eorl_flipped[m], eoud_flipped[m], | ||
| 170 | corner_cycle[m], coud_flipped[m], corl_flipped[m], cofb_flipped[m], | ||
| 171 | center_cycle[m] }, cube, f); | ||
| 172 | } | ||
| 173 | |||
| 174 | int len(NissMove *alg) { | ||
| 175 | int i; | ||
| 176 | for (i = 0; alg[i].m != NULLMOVE; i++); | ||
| 177 | return i; | ||
| 178 | } | ||
| 179 | |||
| 180 | int copy_alg(NissMove *src, NissMove *dest) { | ||
| 181 | int i; | ||
| 182 | for (i = 0; src[i].m != NULLMOVE; i++) | ||
| 183 | dest[i] = src[i]; | ||
| 184 | dest[i].m = NULLMOVE; | ||
| 185 | return i; | ||
| 186 | } | ||
| 187 | |||
| 188 | int invert_alg(NissMove *src, NissMove *dest) { | ||
| 189 | int n = len(src); | ||
| 190 | for (int i = 0; i < n; i++) | ||
| 191 | dest[n-i-1] = (NissMove){.m=inverse[src[i].m], .inverse=src[i].inverse}; | ||
| 192 | dest[n].m = NULLMOVE; | ||
| 193 | return n; | ||
| 194 | } | ||
| 195 | |||
| 196 | int concat(NissMove *src1, NissMove *src2, NissMove *dest) { | ||
| 197 | int n1 = len(src1), n2 = len(src2); | ||
| 198 | copy_alg(src1, dest); | ||
| 199 | copy_alg(src2, dest+n1); | ||
| 200 | return n1+n2; | ||
| 201 | } | ||
| 202 | |||
| 203 | /* TODO: all strings start with space?? */ | ||
| 204 | void print_alg(NissMove *alg) { | ||
| 205 | bool niss = false; | ||
| 206 | for (int i = 0; alg[i].m != NULLMOVE; i++) { | ||
| 207 | char *fill = !niss && alg[i].inverse ? " (" : | ||
| 208 | (niss && !alg[i].inverse ? ") " : " "); | ||
| 209 | printf("%s%s", fill, move_string[alg[i].m]); | ||
| 210 | niss = alg[i].inverse; | ||
| 211 | } | ||
| 212 | printf("%s\n", niss ? ")" : ""); | ||
| 213 | } | ||
| 214 | |||
| 215 | int read_moves(char *str, NissMove *alg, int n) { | ||
| 216 | bool niss = false; | ||
| 217 | int c = 0; | ||
| 218 | |||
| 219 | for (int i = 0; str[i] && c < n; i++) { | ||
| 220 | if (str[i] == ' ' || str[i] == '\t' || str[i] == '\n') | ||
| 221 | continue; | ||
| 222 | |||
| 223 | if (str[i] == '(' || str[i] == ')') { | ||
| 224 | if ((niss && str[i] == '(') || (!niss && str[i] == ')')) | ||
| 225 | return -1; | ||
| 226 | niss = !niss; | ||
| 227 | continue; | ||
| 228 | } | ||
| 229 | |||
| 230 | alg[c].inverse = niss; alg[c].m = NULLMOVE; | ||
| 231 | for (Move j = 0; j < NMOVES; j++) { | ||
| 232 | if (str[i] == move_string[j][0]) { | ||
| 233 | alg[c].m = j; | ||
| 234 | if (alg[c].m <= B && str[i+1]=='w') { alg[c].m += Uw - U; i++; } | ||
| 235 | if (str[i+1]=='2') { alg[c].m += 1; i++; } | ||
| 236 | else if (str[i+1]=='\'' || str[i+1]=='3') { alg[c].m += 2; i++; } | ||
| 237 | c++; | ||
| 238 | break; | ||
| 239 | } | ||
| 240 | } | ||
| 241 | } | ||
| 242 | |||
| 243 | alg[c].m = NULLMOVE; | ||
| 244 | return c; | ||
| 245 | } | ||
| 246 | |||
| 247 | /* TODO: rewrite cleanup(). Idea: | ||
| 248 | 1. split alg in normal + inverse part, rewriting each with equiv_moves | ||
| 249 | 2. shift rotations to the end while transforming all moves in between | ||
| 250 | ARGH! this uses transformation! One more reason to merge everything in | ||
| 251 | one file. | ||
| 252 | 3. cancellations | ||
| 253 | */ | ||
| 254 | |||
| 255 | bool read_ttables_file() { | ||
| 256 | FILE *ttf; | ||
| 257 | long unsigned int me[11] = { factorial12/factorial8, factorial12/factorial8, | ||
| 258 | factorial12/factorial8, pow2to11, pow2to11, pow2to11, | ||
| 259 | factorial8, pow3to7, pow3to7, pow3to7, factorial6 }; | ||
| 260 | if ((ttf = fopen("ttables", "rb")) != NULL) { | ||
| 261 | bool r = true; | ||
| 262 | for (int m = 0; m < NMOVES; m++) { | ||
| 263 | r = r && fread(epose_ttable[m], sizeof(uint16_t), me[0], ttf) == me[0]; | ||
| 264 | r = r && fread(eposs_ttable[m], sizeof(uint16_t), me[1], ttf) == me[1]; | ||
| 265 | r = r && fread(eposm_ttable[m], sizeof(uint16_t), me[2], ttf) == me[2]; | ||
| 266 | r = r && fread(eofb_ttable[m], sizeof(uint16_t), me[3], ttf) == me[3]; | ||
| 267 | r = r && fread(eorl_ttable[m], sizeof(uint16_t), me[4], ttf) == me[4]; | ||
| 268 | r = r && fread(eoud_ttable[m], sizeof(uint16_t), me[5], ttf) == me[5]; | ||
| 269 | r = r && fread(cp_ttable[m], sizeof(uint16_t), me[6], ttf) == me[6]; | ||
| 270 | r = r && fread(coud_ttable[m], sizeof(uint16_t), me[7], ttf) == me[7]; | ||
| 271 | r = r && fread(corl_ttable[m], sizeof(uint16_t), me[8], ttf) == me[8]; | ||
| 272 | r = r && fread(cofb_ttable[m], sizeof(uint16_t), me[9], ttf) == me[9]; | ||
| 273 | r = r && fread(cpos_ttable[m], sizeof(uint16_t), me[10], ttf) == me[10]; | ||
| 274 | } | ||
| 275 | fclose(ttf); | ||
| 276 | return r; | ||
| 277 | } else return false; | ||
| 278 | } | ||
| 279 | |||
| 280 | bool write_ttables_file() { | ||
| 281 | FILE *ttf; | ||
| 282 | long unsigned int me[11] = { factorial12/factorial8, factorial12/factorial8, | ||
| 283 | factorial12/factorial8, pow2to11, pow2to11, pow2to11, | ||
| 284 | factorial8, pow3to7, pow3to7, pow3to7, factorial6 }; | ||
| 285 | if ((ttf = fopen("ttables", "wb")) != NULL) { | ||
| 286 | bool r = true; | ||
| 287 | for (int m = 0; m < NMOVES; m++) { | ||
| 288 | r = r && fwrite(epose_ttable[m], sizeof(uint16_t), me[0], ttf) == me[0]; | ||
| 289 | r = r && fwrite(eposs_ttable[m], sizeof(uint16_t), me[1], ttf) == me[1]; | ||
| 290 | r = r && fwrite(eposm_ttable[m], sizeof(uint16_t), me[2], ttf) == me[2]; | ||
| 291 | r = r && fwrite(eofb_ttable[m], sizeof(uint16_t), me[3], ttf) == me[3]; | ||
| 292 | r = r && fwrite(eorl_ttable[m], sizeof(uint16_t), me[4], ttf) == me[4]; | ||
| 293 | r = r && fwrite(eoud_ttable[m], sizeof(uint16_t), me[5], ttf) == me[5]; | ||
| 294 | r = r && fwrite(cp_ttable[m], sizeof(uint16_t), me[6], ttf) == me[6]; | ||
| 295 | r = r && fwrite(coud_ttable[m], sizeof(uint16_t), me[7], ttf) == me[7]; | ||
| 296 | r = r && fwrite(corl_ttable[m], sizeof(uint16_t), me[8], ttf) == me[8]; | ||
| 297 | r = r && fwrite(cofb_ttable[m], sizeof(uint16_t), me[9], ttf) == me[9]; | ||
| 298 | r = r && fwrite(cpos_ttable[m], sizeof(uint16_t), me[10],ttf) == me[10]; | ||
| 299 | } | ||
| 300 | fclose(ttf); | ||
| 301 | return r; | ||
| 302 | } else return false; | ||
| 303 | } | ||
| 304 | |||
| 305 | void init_ttables(bool read, bool write) { | ||
| 306 | /* Generate all move cycles and flips; I do this regardless */ | ||
| 307 | for (int i = 0; i < NMOVES; i++) { | ||
| 308 | if (i == U || i == x || i == y) | ||
| 309 | continue; | ||
| 310 | |||
| 311 | Cube c = {0}; | ||
| 312 | for (int j = 0; equiv_moves[i][j]; j++) | ||
| 313 | c = apply_move_cubearray(equiv_moves[i][j], c, pf_all); | ||
| 314 | |||
| 315 | CubeArray arrs = { | ||
| 316 | edge_cycle[i], eofb_flipped[i], eorl_flipped[i], eoud_flipped[i], | ||
| 317 | corner_cycle[i], coud_flipped[i], corl_flipped[i], cofb_flipped[i], | ||
| 318 | center_cycle[i] | ||
| 319 | }; | ||
| 320 | cube_to_arrays(c, &arrs, pf_all); | ||
| 321 | } | ||
| 322 | |||
| 323 | if (read) | ||
| 324 | if (read_ttables_file()) | ||
| 325 | return; | ||
| 326 | |||
| 327 | /* Initialize transition tables */ | ||
| 328 | for (int m = 0; m < NMOVES; m++) { | ||
| 329 | for (uint16_t i = 0; i < factorial12/factorial8; i++) { | ||
| 330 | epose_ttable[m][i] = apply_move_cubearray(m,(Cube){.epose=i},pf_e).epose; | ||
| 331 | eposs_ttable[m][i] = apply_move_cubearray(m,(Cube){.eposs=i},pf_s).eposs; | ||
| 332 | eposm_ttable[m][i] = apply_move_cubearray(m,(Cube){.eposm=i},pf_m).eposm; | ||
| 333 | } | ||
| 334 | for (uint16_t i = 0; i < pow2to11; i++ ) { | ||
| 335 | eofb_ttable[m][i] = apply_move_cubearray(m,(Cube){.eofb=i},pf_eo).eofb; | ||
| 336 | eorl_ttable[m][i] = apply_move_cubearray(m,(Cube){.eorl=i},pf_eo).eorl; | ||
| 337 | eoud_ttable[m][i] = apply_move_cubearray(m,(Cube){.eoud=i},pf_eo).eoud; | ||
| 338 | } | ||
| 339 | for (uint16_t i = 0; i < pow3to7; i++) { | ||
| 340 | coud_ttable[m][i] = apply_move_cubearray(m,(Cube){.coud=i},pf_co).coud; | ||
| 341 | corl_ttable[m][i] = apply_move_cubearray(m,(Cube){.corl=i},pf_co).corl; | ||
| 342 | cofb_ttable[m][i] = apply_move_cubearray(m,(Cube){.cofb=i},pf_co).cofb; | ||
| 343 | } | ||
| 344 | for (uint16_t i = 0; i < factorial8; i++) | ||
| 345 | cp_ttable[m][i] = apply_move_cubearray(m,(Cube){.cp=i},pf_cp).cp; | ||
| 346 | for (uint16_t i = 0; i < factorial6; i++) | ||
| 347 | cpos_ttable[m][i] = apply_move_cubearray(m,(Cube){.cpos=i},pf_cpos).cpos; | ||
| 348 | } | ||
| 349 | |||
| 350 | if (write) | ||
| 351 | if (!write_ttables_file()) | ||
| 352 | printf("Error in writing ttables: file not writable\n"); | ||
| 353 | } | ||
| 354 | |||
| 355 | Cube move_cube(Move m, Cube cube) { | ||
| 356 | Cube moved = {0}; | ||
| 357 | |||
| 358 | moved.epose = epose_ttable[m][cube.epose]; | ||
| 359 | moved.eposs = eposs_ttable[m][cube.eposs]; | ||
| 360 | moved.eposm = eposm_ttable[m][cube.eposm]; | ||
| 361 | moved.eofb = eofb_ttable[m][cube.eofb]; | ||
| 362 | moved.eorl = eorl_ttable[m][cube.eorl]; | ||
| 363 | moved.eoud = eoud_ttable[m][cube.eoud]; | ||
| 364 | moved.coud = coud_ttable[m][cube.coud]; | ||
| 365 | moved.cofb = cofb_ttable[m][cube.cofb]; | ||
| 366 | moved.corl = corl_ttable[m][cube.corl]; | ||
| 367 | moved.cp = cp_ttable[m][cube.cp]; | ||
| 368 | moved.cpos = cpos_ttable[m][cube.cpos]; | ||
| 369 | |||
| 370 | return moved; | ||
| 371 | } | ||
| 372 | |||
| 373 | Cube apply_alg_filtered(NissMove *alg, Cube cube, PieceFilter f) { | ||
| 374 | Cube ret = {0}; | ||
| 375 | for (int i = 0; alg[i].m != NULLMOVE; i++) | ||
| 376 | if (alg[i].inverse) | ||
| 377 | ret = move_cube(alg[i].m, ret); | ||
| 378 | |||
| 379 | ret = compose_filtered(cube, inverse_cube(ret), f); | ||
| 380 | |||
| 381 | for (int i = 0; alg[i].m != NULLMOVE; i++) | ||
| 382 | if (!alg[i].inverse) | ||
| 383 | ret = move_cube(alg[i].m, ret); | ||
| 384 | return ret; | ||
| 385 | } | ||
| 386 | |||
| 387 | Cube apply_alg(NissMove *alg, Cube cube) { | ||
| 388 | return apply_alg_filtered(alg, cube, pf_all); | ||
| 389 | } | ||
| 390 | |||
| 391 | void init_aux_tables() { | ||
| 392 | /* Commute */ | ||
| 393 | for (int i = 0; i < NMOVES; i++) | ||
| 394 | for (int j = 0; j < NMOVES; j++) | ||
| 395 | commute[i][j] = equal(move_cube(i, move_cube(j, (Cube){0})), | ||
| 396 | move_cube(j, move_cube(i, (Cube){0}))); | ||
| 397 | |||
| 398 | /* Possible next (if the sequence i j k is valid) */ | ||
| 399 | for (int i = 0; i < NMOVES; i++) | ||
| 400 | for (int j = 0; j < NMOVES; j++) | ||
| 401 | for (int k = 0; k < NMOVES; k++) | ||
| 402 | possible_next[i][j][k] = | ||
| 403 | (j == 0) || | ||
| 404 | (j != 0 && (j-(j-1)%3) != (k-(k-1)%3) && | ||
| 405 | !(i != 0 && commute[i][j] && (i-(i-1)%3) == (k-(k-1)%3))); | ||
| 406 | |||
| 407 | /* Inverse */ | ||
| 408 | for (int i = 0; i < NMOVES; i++) | ||
| 409 | inverse[i] = i == NULLMOVE ? NULLMOVE : i + 2 - 2*((i-1)%3); | ||
| 410 | |||
| 411 | } | ||
| 412 | |||
diff --git a/old/2021-05-26-before-restyle/moves.h b/old/2021-05-26-before-restyle/moves.h new file mode 100644 index 0000000..0608e1b --- /dev/null +++ b/old/2021-05-26-before-restyle/moves.h | |||
| @@ -0,0 +1,51 @@ | |||
| 1 | #ifndef MOVES_H | ||
| 2 | #define MOVES_H | ||
| 3 | |||
| 4 | #include <stdio.h> | ||
| 5 | #include <stdbool.h> | ||
| 6 | #include <stdint.h> | ||
| 7 | #include "cube.h" | ||
| 8 | #include "utils.h" | ||
| 9 | |||
| 10 | #define NMOVES (z3+1) | ||
| 11 | |||
| 12 | typedef enum { | ||
| 13 | NULLMOVE, | ||
| 14 | U, U2, U3, D, D2, D3, R, R2, R3, L, L2, L3, F, F2, F3, B, B2, B3, | ||
| 15 | Uw, Uw2, Uw3, Dw, Dw2, Dw3, Rw, Rw2, Rw3, | ||
| 16 | Lw, Lw2, Lw3, Fw, Fw2, Fw3, Bw, Bw2, Bw3, | ||
| 17 | M, M2, M3, S, S2, S3, E, E2, E3, | ||
| 18 | x, x2, x3, y, y2, y3, z, z2, z3, | ||
| 19 | } Move; | ||
| 20 | |||
| 21 | /* An alg is an array of "NissMoves", which can be on normal or on inverse. */ | ||
| 22 | typedef struct { bool inverse; Move m; } NissMove; | ||
| 23 | |||
| 24 | /* Movesets */ | ||
| 25 | extern bool standard_moveset[NMOVES]; | ||
| 26 | |||
| 27 | extern bool commute[NMOVES][NMOVES]; | ||
| 28 | extern bool possible_next[NMOVES][NMOVES][NMOVES]; | ||
| 29 | extern Move inverse[NMOVES]; | ||
| 30 | extern NissMove rotation_algs[24][3]; /* Same order as transformations */ | ||
| 31 | |||
| 32 | int len(NissMove *alg); | ||
| 33 | int copy_alg(NissMove *src, NissMove *dest); /*return number of moves copied */ | ||
| 34 | int invert_alg(NissMove *src, NissMove *dest); | ||
| 35 | int concat(NissMove *src1, NissMove *src2, NissMove *dest); | ||
| 36 | void print_alg(NissMove *alg); | ||
| 37 | int read_moves(char *str, NissMove *alg, int n); /* reads at most n moves */ | ||
| 38 | void cleanup(NissMove *src, int n); /* rewrites using basic moves, at most n */ | ||
| 39 | |||
| 40 | bool is_solved_up_to_reorient(Cube cube); | ||
| 41 | Cube move_cube(Move m, Cube cube); | ||
| 42 | Cube apply_alg(NissMove *alg, Cube cube); | ||
| 43 | Cube apply_alg_filtered(NissMove *alg, Cube cube, PieceFilter f); | ||
| 44 | |||
| 45 | /* Merge the following two? | ||
| 46 | always in this order */ | ||
| 47 | void init_ttables(bool read, bool write); | ||
| 48 | void init_aux_tables(); | ||
| 49 | |||
| 50 | |||
| 51 | #endif | ||
diff --git a/old/2021-05-26-before-restyle/solve.c b/old/2021-05-26-before-restyle/solve.c new file mode 100644 index 0000000..31bd779 --- /dev/null +++ b/old/2021-05-26-before-restyle/solve.c | |||
| @@ -0,0 +1,180 @@ | |||
| 1 | #include "solve.h" | ||
| 2 | |||
| 3 | /* Data for creating a pruning table: | ||
| 4 | - compressed: if set to true, each entry occupies only 4 bits, but values | ||
| 5 | larger than 15 cannot be stored. | ||
| 6 | - available[] is the list of availabel moves, as above. | ||
| 7 | - *ptable is the actual table to fill. | ||
| 8 | - n is the number of states (size of ptable). | ||
| 9 | - index must "linearize" the cube, i.e. return its index in ptable. | ||
| 10 | - fname is the name of the file where to store the table */ | ||
| 11 | typedef struct { | ||
| 12 | bool compressed, *available; | ||
| 13 | int max_moves; | ||
| 14 | uint8_t *ptable; | ||
| 15 | uint64_t n; | ||
| 16 | uint64_t (*index)(Cube); | ||
| 17 | char *fname; | ||
| 18 | } PruneData; | ||
| 19 | |||
| 20 | /* TODO: comment this */ | ||
| 21 | typedef struct { | ||
| 22 | bool niss; | ||
| 23 | int m, d; | ||
| 24 | uint64_t *n; | ||
| 25 | Move last1, last2; | ||
| 26 | } DfsData; | ||
| 27 | |||
| 28 | void solve_dfs(Cube cube, SolveData *sd, DfsData dd); | ||
| 29 | void init_ptable(PruneData *pd, bool read, bool write); | ||
| 30 | |||
| 31 | /* Search solutions of lenght exactly d */ | ||
| 32 | void solve_dfs(Cube cube, SolveData *sd, DfsData dd) { | ||
| 33 | if (*dd.n >= sd->max_solutions || | ||
| 34 | ((!sd->can_niss || dd.niss) && dd.m + sd->f(cube) > dd.d)) | ||
| 35 | return; | ||
| 36 | |||
| 37 | (sd->solutions[*dd.n][dd.m]).inverse = dd.niss; | ||
| 38 | (sd->solutions[*dd.n][dd.m]).m = NULLMOVE; | ||
| 39 | |||
| 40 | if (!sd->f(cube)) { /* Solved */ | ||
| 41 | if (dd.m == dd.d) { | ||
| 42 | (*dd.n)++; | ||
| 43 | if (*dd.n < sd->max_solutions) | ||
| 44 | copy_alg(sd->solutions[*dd.n-1], sd->solutions[*dd.n]); | ||
| 45 | } | ||
| 46 | return; | ||
| 47 | } | ||
| 48 | |||
| 49 | for (int i = 0; i < NMOVES && sd->sorted_moves[i] != NULLMOVE; i++) { | ||
| 50 | Move move = sd->sorted_moves[i]; | ||
| 51 | if (possible_next[dd.last2][dd.last1][move]) { | ||
| 52 | sd->solutions[*dd.n][dd.m].inverse = dd.niss; | ||
| 53 | sd->solutions[*dd.n][dd.m].m = move; | ||
| 54 | DfsData nn = { .niss = dd.niss, .m = dd.m+1, .d = dd.d, .n = dd.n, | ||
| 55 | .last1 = move, .last2 = dd.last1 }; | ||
| 56 | solve_dfs(move_cube(move, cube), sd, nn); | ||
| 57 | } | ||
| 58 | } | ||
| 59 | |||
| 60 | if (sd->can_niss && !dd.niss && | ||
| 61 | (!dd.m || (dd.m && sd->f(move_cube(dd.last1, (Cube){0}))))) { | ||
| 62 | DfsData nn = { .niss = true, .m = dd.m, .d = dd.d, .n = dd.n }; | ||
| 63 | solve_dfs(inverse_cube(cube), sd, nn); | ||
| 64 | } | ||
| 65 | } | ||
| 66 | |||
| 67 | /* Iterative deepening depth-first search: for i running from the minimum | ||
| 68 | to the maximum number of moves allowed, looks for solutions of length i. */ | ||
| 69 | int solve(Cube cube, SolveData *sd) { | ||
| 70 | if (sd->precondition != NULL && !sd->precondition(cube)) | ||
| 71 | return -1; | ||
| 72 | |||
| 73 | /* If not given, generate sorted list of moves */ | ||
| 74 | if (sd->sorted_moves[0] == NULLMOVE) { | ||
| 75 | int a[NMOVES], b[NMOVES], ia = 0, ib = 0; | ||
| 76 | for (int i = 0; i < NMOVES; i++) { | ||
| 77 | if (sd->available[i]) { | ||
| 78 | if (sd->f(move_cube(i, (Cube){0}))) | ||
| 79 | a[ia++] = i; | ||
| 80 | else | ||
| 81 | b[ib++] = i; | ||
| 82 | } | ||
| 83 | } | ||
| 84 | intarrcopy(a, (int *)sd->sorted_moves, ia); | ||
| 85 | intarrcopy(b, (int *)sd->sorted_moves+ia, ib); | ||
| 86 | sd->sorted_moves[ia+ib] = NULLMOVE; | ||
| 87 | } | ||
| 88 | |||
| 89 | sd->max_solutions = min(sd->max_solutions, MAXS); | ||
| 90 | /*TODO | ||
| 91 | Cube rotated = apply_alg(sd->pre_rotation, (Cube){0}); | ||
| 92 | cube = apply_alg(inverse_cube(rotated), compose(cube, rotated)); | ||
| 93 | */ | ||
| 94 | |||
| 95 | uint64_t ret = 0; | ||
| 96 | for (int i=sd->min_moves; i<=sd->max_moves&&!(ret&&sd->optimal_only); i++) { | ||
| 97 | DfsData dd = { .d = i, .n = &ret }; | ||
| 98 | solve_dfs(cube, sd, dd); | ||
| 99 | } | ||
| 100 | |||
| 101 | /* TODO: transform solutions with inverse of pre_rotation */ | ||
| 102 | /* | ||
| 103 | for (uint64_t i = 0; i < ret; i++) { | ||
| 104 | if (sd->cleanup) | ||
| 105 | cleanup(sd->solutions[i], sd->max_moves*3); | ||
| 106 | }*/ | ||
| 107 | |||
| 108 | return ret; | ||
| 109 | } | ||
| 110 | |||
| 111 | void prune_dfs(Cube cube, PruneData *pd, DfsData dd) { | ||
| 112 | uint64_t ind = pd->index(cube); | ||
| 113 | if ((!ind || pd->ptable[ind]) && pd->ptable[ind] != dd.m) | ||
| 114 | return; | ||
| 115 | if (dd.m == dd.d) { | ||
| 116 | if (ind && !pd->ptable[ind]) { | ||
| 117 | pd->ptable[ind] = dd.m; | ||
| 118 | (*dd.n)++; | ||
| 119 | } | ||
| 120 | return; | ||
| 121 | } | ||
| 122 | |||
| 123 | for (int i = 0; i < NMOVES; i++) { | ||
| 124 | if (dd.m<20) | ||
| 125 | if (possible_next[dd.last2][dd.last1][i] && pd->available[i]) { | ||
| 126 | DfsData nn = { .m = dd.m+1, .d = dd.d, .n = dd.n, | ||
| 127 | .last1 = i, .last2 = dd.last1 }; | ||
| 128 | prune_dfs(move_cube(i, cube), pd, nn); | ||
| 129 | } | ||
| 130 | } | ||
| 131 | } | ||
| 132 | |||
| 133 | void init_ptable(PruneData *pd, bool read, bool write) { | ||
| 134 | if (read) { | ||
| 135 | FILE *ptf; | ||
| 136 | if ((ptf = fopen(pd->fname, "rb")) != NULL) { | ||
| 137 | uint64_t r = fread(pd->ptable, sizeof(uint8_t), pd->n, ptf); | ||
| 138 | fclose(ptf); | ||
| 139 | if (r == pd->n) return; | ||
| 140 | } | ||
| 141 | } | ||
| 142 | |||
| 143 | /* TODO: for now it behaves always as if copressed = false */ | ||
| 144 | for (uint64_t i = 0; i < pd->n; i++) | ||
| 145 | pd->ptable[i] = 0; | ||
| 146 | |||
| 147 | uint64_t s = 1; | ||
| 148 | for (int i = 1; i < pd->max_moves && s < pd->n; i++) { | ||
| 149 | DfsData dd = { .d = i, .n = &s }; | ||
| 150 | prune_dfs((Cube){0}, pd, dd); | ||
| 151 | } | ||
| 152 | |||
| 153 | if (write) { | ||
| 154 | FILE *ptf; | ||
| 155 | if ((ptf = fopen(pd->fname, "wb")) != NULL) { | ||
| 156 | fwrite(pd->ptable, sizeof(uint8_t), pd->n, ptf); | ||
| 157 | fclose(ptf); | ||
| 158 | return; | ||
| 159 | } | ||
| 160 | } | ||
| 161 | } | ||
| 162 | |||
| 163 | /* Solving steps (and indexing functions) */ | ||
| 164 | |||
| 165 | uint64_t index_eofb(Cube cube) { return cube.eofb; } | ||
| 166 | int f_eofb(Cube cube) { | ||
| 167 | static bool initialized_ptable; | ||
| 168 | static uint8_t pt_eofb[pow2to11]; | ||
| 169 | if (!initialized_ptable) { | ||
| 170 | PruneData pd = { | ||
| 171 | .compressed = false, .available = standard_moveset, .max_moves = 13, | ||
| 172 | .ptable = pt_eofb, .n = pow2to11, .index = index_eofb, | ||
| 173 | .fname = "ptable_eofb" | ||
| 174 | }; | ||
| 175 | init_ptable(&pd, false, true); | ||
| 176 | initialized_ptable = true; | ||
| 177 | } | ||
| 178 | return cube.eofb ? pt_eofb[cube.eofb] : 0; | ||
| 179 | } | ||
| 180 | |||
diff --git a/old/2021-05-26-before-restyle/solve.h b/old/2021-05-26-before-restyle/solve.h new file mode 100644 index 0000000..0b59cc2 --- /dev/null +++ b/old/2021-05-26-before-restyle/solve.h | |||
| @@ -0,0 +1,59 @@ | |||
| 1 | #ifndef SOLVE_H | ||
| 2 | #define SOLVE_H | ||
| 3 | |||
| 4 | #include <stdlib.h> | ||
| 5 | #include "cube.h" | ||
| 6 | #include "moves.h" | ||
| 7 | #include "transformations.h" | ||
| 8 | |||
| 9 | /* Maximum number of moves per solution and of solutions */ | ||
| 10 | #define MAXM 30 | ||
| 11 | #define MAXS 999 | ||
| 12 | |||
| 13 | /* Data for solving a step: | ||
| 14 | - can_niss is true niss can be used, false otherwise. | ||
| 15 | - optimal_only if true, dynamically updates max_moves so non-optimal | ||
| 16 | solutions are discarded. | ||
| 17 | - cleanup determines whether the cleaunup() function should be used on | ||
| 18 | the found solutions before returning. | ||
| 19 | - available[m] is true if the move m can be used, false otherwise. | ||
| 20 | (Rename to moveset[]?) | ||
| 21 | - min_moves and max_moves are the minimum and maximum number of moves that | ||
| 22 | can be used. | ||
| 23 | - max_solution is the maximum number of solutions that can be returned. | ||
| 24 | - precondition can be used to check wheter the step can actually be applied | ||
| 25 | to the cube. If it returns false, solve() stops immediately returning -1. | ||
| 26 | - f must return 0 if and only if the step is solve, otherwise it must return | ||
| 27 | a lower bound for the number of moves required (without niss). | ||
| 28 | - sorted_moves[] can be used to specify in which order moves are tried | ||
| 29 | by the solving algorithm (for example if one wants to always try F' before | ||
| 30 | F). If sorted_moves[0] == NULLMOVE, the list is generated automatically. | ||
| 31 | It is advised to list first all the moves that actually influence the | ||
| 32 | solved state of the step (this is the default choice). This is in order to | ||
| 33 | avoid cases like B2 F for EO and to NISS only when it makes sense. | ||
| 34 | - start_moves [Currently unused, REMOVE] | ||
| 35 | are the moves that will be used as first moves of all | ||
| 36 | solutions. For example giving R' U' F (F' U R) will generate FMC scrambles | ||
| 37 | and y (y) will solve the step on another axis. | ||
| 38 | - pre_rotation are the rotations to apply before the scamble to solve | ||
| 39 | the step wrt a different orientation | ||
| 40 | - pre_rotation are the rotations to apply before the scamble to solve | ||
| 41 | the step wth respect to a different orientation. | ||
| 42 | TODO: cange name | ||
| 43 | - solutions[][] is the array where to store the found solutions. */ | ||
| 44 | typedef struct { | ||
| 45 | bool can_niss, optimal_only, cleanup, *available; | ||
| 46 | int min_moves, max_moves, max_solutions; | ||
| 47 | int (*f)(Cube); | ||
| 48 | bool (*precondition)(Cube); | ||
| 49 | Move sorted_moves[NMOVES]; | ||
| 50 | Transformation pre_rotation; | ||
| 51 | NissMove solutions[MAXS][MAXM]; | ||
| 52 | } SolveData; | ||
| 53 | |||
| 54 | int solve(Cube cube, SolveData *data); /* Returns the number of solutions. */ | ||
| 55 | |||
| 56 | /* Steps */ | ||
| 57 | int f_eofb(Cube cube); | ||
| 58 | |||
| 59 | #endif | ||
diff --git a/old/2021-05-26-before-restyle/transformations.c b/old/2021-05-26-before-restyle/transformations.c new file mode 100644 index 0000000..c457f0c --- /dev/null +++ b/old/2021-05-26-before-restyle/transformations.c | |||
| @@ -0,0 +1,200 @@ | |||
| 1 | #include "transformations.h" | ||
| 2 | |||
| 3 | int edge_slice(int e); /* Return slice (e=0, s=1, m=2) to which e belongs */ | ||
| 4 | Cube rotate_via_compose(Transformation r, Cube c, PieceFilter f); | ||
| 5 | bool read_rtables_file(); | ||
| 6 | bool write_rtables_file(); | ||
| 7 | |||
| 8 | /* Values mod 3 to determine from which side to take the state to convert */ | ||
| 9 | int epose_source[NTRANS]; /* 0 = epose, 1 = eposs, 2 = eposm */ | ||
| 10 | int eposs_source[NTRANS]; | ||
| 11 | int eposm_source[NTRANS]; | ||
| 12 | int eofb_source[NTRANS]; /* 0 = eoud, 1 = eorl, 2 = eofb */ | ||
| 13 | int eorl_source[NTRANS]; | ||
| 14 | int eoud_source[NTRANS]; | ||
| 15 | int coud_source[NTRANS]; /* 0 = coud, 1 = corl, 2 = cofb */ | ||
| 16 | int cofb_source[NTRANS]; | ||
| 17 | int corl_source[NTRANS]; | ||
| 18 | |||
| 19 | /* Transition tables for rotations (n+1 is mirror) */ | ||
| 20 | uint16_t epose_rtable[NTRANS][factorial12/factorial8]; | ||
| 21 | uint16_t eposs_rtable[NTRANS][factorial12/factorial8]; | ||
| 22 | uint16_t eposm_rtable[NTRANS][factorial12/factorial8]; | ||
| 23 | uint16_t eo_rtable[NTRANS][pow2to11]; | ||
| 24 | uint16_t cp_rtable[NTRANS][factorial8]; | ||
| 25 | uint16_t co_rtable[NTRANS][pow3to7]; | ||
| 26 | uint16_t cpos_rtable[NTRANS][factorial6]; | ||
| 27 | |||
| 28 | /* Same for moves */ | ||
| 29 | uint16_t moves_rtable[NTRANS][NMOVES]; | ||
| 30 | |||
| 31 | NissMove rotation_niss[NTRANS][6]; | ||
| 32 | |||
| 33 | int edge_slice(int e) { | ||
| 34 | if (e == FR || e == FL || e == BL || e == BR) | ||
| 35 | return 0; | ||
| 36 | if (e == UR || e == UL || e == DR || e == DL) | ||
| 37 | return 1; | ||
| 38 | return 2; | ||
| 39 | } | ||
| 40 | |||
| 41 | Cube rotate_via_compose(Transformation r, Cube c, PieceFilter f) { | ||
| 42 | if (r != mirror) { | ||
| 43 | return apply_alg_filtered(rotation_niss[r], c, f); | ||
| 44 | } else { | ||
| 45 | static int zero12[12] = {0,0,0,0,0,0,0,0,0,0,0,0}, | ||
| 46 | zero8[12] = {0,0,0,0,0,0,0,0}, | ||
| 47 | mirror_ep[12] = {UF,UR,UB,UL,DF,DR,DB,DL,FL,FR,BR,BL}, | ||
| 48 | mirror_cp[8] = {UFL, UFR, UBR, UBL, DFL, DFR, DBR, DBL}, | ||
| 49 | mirror_cpos[6] = | ||
| 50 | {U_center,D_center,L_center,R_center,F_center,B_center}; | ||
| 51 | return move_via_arrays((CubeArray){ | ||
| 52 | .ep = mirror_ep, .eofb = zero12, .eorl = zero12, .eoud = zero12, | ||
| 53 | .cp = mirror_cp, .coud = zero8, .corl = zero8, .cofb = zero8, | ||
| 54 | .cpos = mirror_cpos}, c, f); | ||
| 55 | } | ||
| 56 | } | ||
| 57 | |||
| 58 | bool read_rtables_file() { | ||
| 59 | FILE *ttf; | ||
| 60 | long unsigned int me[12] = { factorial12/factorial8, factorial12/factorial8, | ||
| 61 | factorial12/factorial8, pow2to11, pow2to11, pow2to11, | ||
| 62 | factorial8, pow3to7, pow3to7, pow3to7, factorial6, NMOVES }; | ||
| 63 | if ((ttf = fopen("rtables", "rb")) != NULL) { | ||
| 64 | bool r = true; | ||
| 65 | for (int m = 0; m < NTRANS; m++) { | ||
| 66 | r = r && fread(epose_rtable[m], sizeof(uint16_t), me[0], ttf) == me[0]; | ||
| 67 | r = r && fread(eposs_rtable[m], sizeof(uint16_t), me[1], ttf) == me[1]; | ||
| 68 | r = r && fread(eposm_rtable[m], sizeof(uint16_t), me[2], ttf) == me[2]; | ||
| 69 | r = r && fread(eo_rtable[m], sizeof(uint16_t), me[3], ttf) == me[3]; | ||
| 70 | r = r && fread(cp_rtable[m], sizeof(uint16_t), me[6], ttf) == me[6]; | ||
| 71 | r = r && fread(co_rtable[m], sizeof(uint16_t), me[7], ttf) == me[7]; | ||
| 72 | r = r && fread(cpos_rtable[m], sizeof(uint16_t), me[10], ttf) == me[10]; | ||
| 73 | r = r && fread(moves_rtable[m], sizeof(uint16_t), me[11], ttf) == me[11]; | ||
| 74 | } | ||
| 75 | fclose(ttf); | ||
| 76 | return r; | ||
| 77 | } else return false; | ||
| 78 | } | ||
| 79 | |||
| 80 | bool write_rtables_file() { | ||
| 81 | FILE *ttf; | ||
| 82 | long unsigned int me[12] = { factorial12/factorial8, factorial12/factorial8, | ||
| 83 | factorial12/factorial8, pow2to11, pow2to11, pow2to11, | ||
| 84 | factorial8, pow3to7, pow3to7, pow3to7, factorial6, NMOVES }; | ||
| 85 | if ((ttf = fopen("rtables", "wb")) != NULL) { | ||
| 86 | bool r = true; | ||
| 87 | for (int m = 0; m < NTRANS; m++) { | ||
| 88 | r = r && fwrite(epose_rtable[m], sizeof(uint16_t), me[0], ttf) == me[0]; | ||
| 89 | r = r && fwrite(eposs_rtable[m], sizeof(uint16_t), me[1], ttf) == me[1]; | ||
| 90 | r = r && fwrite(eposm_rtable[m], sizeof(uint16_t), me[2], ttf) == me[2]; | ||
| 91 | r = r && fwrite(eo_rtable[m], sizeof(uint16_t), me[3], ttf) == me[3]; | ||
| 92 | r = r && fwrite(cp_rtable[m], sizeof(uint16_t), me[6], ttf) == me[6]; | ||
| 93 | r = r && fwrite(co_rtable[m], sizeof(uint16_t), me[7], ttf) == me[7]; | ||
| 94 | r = r && fwrite(cpos_rtable[m], sizeof(uint16_t), me[10],ttf) == me[10]; | ||
| 95 | r = r && fwrite(moves_rtable[m], sizeof(uint16_t), me[11],ttf) == me[11]; | ||
| 96 | } | ||
| 97 | fclose(ttf); | ||
| 98 | return r; | ||
| 99 | } else return false; | ||
| 100 | } | ||
| 101 | |||
| 102 | void init_transformations(bool read, bool write) { | ||
| 103 | /* Compute sources */ | ||
| 104 | for (int i = 0; i < NTRANS; i++) { | ||
| 105 | Cube cube = {0}; | ||
| 106 | if (i != mirror) | ||
| 107 | cube = apply_alg(rotation_algs[i], (Cube){0}); | ||
| 108 | epose_source[i] = edge_slice(edge_at(cube, FR)); | ||
| 109 | eposs_source[i] = edge_slice(edge_at(cube, UR)); | ||
| 110 | eposm_source[i] = edge_slice(edge_at(cube, UF)); | ||
| 111 | eofb_source[i] = center_at(cube, F_center)/2; | ||
| 112 | eorl_source[i] = center_at(cube, R_center)/2; | ||
| 113 | eoud_source[i] = center_at(cube, U_center)/2; | ||
| 114 | coud_source[i] = center_at(cube, U_center)/2; | ||
| 115 | cofb_source[i] = center_at(cube, F_center)/2; | ||
| 116 | corl_source[i] = center_at(cube, R_center)/2; | ||
| 117 | } | ||
| 118 | |||
| 119 | /*TODO: maybe move down*/ | ||
| 120 | /* Compute rotation_niss array, necessary for rotate_via_compose */ | ||
| 121 | for (int r = 0; r != mirror; r++) { | ||
| 122 | concat(rotation_algs[r], rotation_algs[r], rotation_niss[r]); | ||
| 123 | for (int i = len(rotation_algs[r]); rotation_niss[r][i].m != NULLMOVE; i++) | ||
| 124 | rotation_niss[r][i].inverse = true; | ||
| 125 | } | ||
| 126 | |||
| 127 | /* If I can read tables from file, I stop here */ | ||
| 128 | if (read) | ||
| 129 | if (read_rtables_file()) | ||
| 130 | return; | ||
| 131 | |||
| 132 | /* Initialize tables */ | ||
| 133 | for (int m = 0; m < NTRANS; m++) { | ||
| 134 | int eparr[12] = {0,0,0,0,0,0,0,0,0,0,0,0}, cparr[8] = {0,0,0,0,0,0,0,0}; | ||
| 135 | CubeArray epcp = { .ep = eparr, .cp = cparr }; | ||
| 136 | cube_to_arrays(apply_alg(rotation_algs[m], (Cube){0}), &epcp, | ||
| 137 | (PieceFilter){.epose=true,.eposs=true,.eposm=true,.cp=true}); | ||
| 138 | for (uint16_t i = 0; i < factorial12/factorial8; i++) { | ||
| 139 | Cube c[3] = { admissible_ep((Cube){ .epose = i}, pf_e), | ||
| 140 | admissible_ep((Cube){ .eposs = i}, pf_s), | ||
| 141 | admissible_ep((Cube){ .eposm = i}, pf_m) }; | ||
| 142 | epose_rtable[m][i]=rotate_via_compose(m,c[epose_source[m]],pf_ep).epose; | ||
| 143 | eposs_rtable[m][i]=rotate_via_compose(m,c[eposs_source[m]],pf_ep).eposs; | ||
| 144 | eposm_rtable[m][i]=rotate_via_compose(m,c[eposm_source[m]],pf_ep).eposm; | ||
| 145 | } | ||
| 146 | for (uint16_t i = 0; i < pow2to11; i++ ) { | ||
| 147 | int eoarr[12]; | ||
| 148 | int_to_sum_zero_array(i, 2, 12, eoarr); | ||
| 149 | apply_permutation(eparr, eoarr, 12); | ||
| 150 | eo_rtable[m][i] = digit_array_to_int(eoarr, 11, 2); | ||
| 151 | } | ||
| 152 | for (uint16_t i = 0; i < pow3to7; i++) { | ||
| 153 | int coarr[12]; | ||
| 154 | int_to_sum_zero_array(i, 3, 8, coarr); | ||
| 155 | apply_permutation(cparr, coarr, 8); | ||
| 156 | co_rtable[m][i] = digit_array_to_int(coarr, 7, 3); | ||
| 157 | } | ||
| 158 | for (uint16_t i = 0; i < factorial8; i++) | ||
| 159 | cp_rtable[m][i] = rotate_via_compose(m, (Cube){.cp=i}, pf_cp).cp; | ||
| 160 | for (uint16_t i = 0; i < factorial6; i++) | ||
| 161 | cpos_rtable[m][i] = rotate_via_compose(m, (Cube){.cpos=i}, pf_cpos).cpos; | ||
| 162 | for (Move i = 0; i < NMOVES; i++) { | ||
| 163 | Cube aux = transform_cube(m, move_cube(i, (Cube){0})); | ||
| 164 | for (Move move = 0; move < NMOVES; move++) | ||
| 165 | if (is_solved(move_cube(inverse[move], aux))) | ||
| 166 | moves_rtable[m][i] = move; | ||
| 167 | } | ||
| 168 | } | ||
| 169 | |||
| 170 | if (write) | ||
| 171 | if (!write_rtables_file()) | ||
| 172 | printf("Error in writing rtables: file not writable\n"); | ||
| 173 | } | ||
| 174 | |||
| 175 | Cube transform_cube(Transformation t, Cube cube) { | ||
| 176 | Cube transformed = {0}; | ||
| 177 | |||
| 178 | uint16_t aux_epos[3] = { cube.epose, cube.eposs, cube.eposm }, | ||
| 179 | aux_eo[3] = { cube.eoud, cube.eorl, cube.eofb }, | ||
| 180 | aux_co[3] = { cube.coud, cube.corl, cube.cofb }; | ||
| 181 | |||
| 182 | transformed.epose = epose_rtable[t][aux_epos[epose_source[t]]]; | ||
| 183 | transformed.eposs = eposs_rtable[t][aux_epos[eposs_source[t]]]; | ||
| 184 | transformed.eposm = eposm_rtable[t][aux_epos[eposm_source[t]]]; | ||
| 185 | transformed.eofb = eo_rtable[t][aux_eo[eofb_source[t]]]; | ||
| 186 | transformed.eorl = eo_rtable[t][aux_eo[eorl_source[t]]]; | ||
| 187 | transformed.eoud = eo_rtable[t][aux_eo[eoud_source[t]]]; | ||
| 188 | transformed.coud = co_rtable[t][aux_co[coud_source[t]]]; | ||
| 189 | transformed.corl = co_rtable[t][aux_co[corl_source[t]]]; | ||
| 190 | transformed.cofb = co_rtable[t][aux_co[cofb_source[t]]]; | ||
| 191 | transformed.cp = cp_rtable[t][cube.cp]; | ||
| 192 | transformed.cpos = cpos_rtable[t][cube.cpos]; | ||
| 193 | |||
| 194 | return transformed; | ||
| 195 | } | ||
| 196 | |||
| 197 | void transform_alg(Transformation t, NissMove *alg) { | ||
| 198 | for (int i = 0; alg[i].m; i++) | ||
| 199 | alg[i].m = moves_rtable[t][alg[i].m]; | ||
| 200 | } | ||
diff --git a/old/2021-05-26-before-restyle/transformations.h b/old/2021-05-26-before-restyle/transformations.h new file mode 100644 index 0000000..c673257 --- /dev/null +++ b/old/2021-05-26-before-restyle/transformations.h | |||
| @@ -0,0 +1,34 @@ | |||
| 1 | #ifndef TRANSFORMATIONS_H | ||
| 2 | #define TRANSFORMATIONS_H | ||
| 3 | |||
| 4 | #include <stdio.h> | ||
| 5 | #include <stdbool.h> | ||
| 6 | #include <stdint.h> | ||
| 7 | #include "cube.h" | ||
| 8 | #include "moves.h" | ||
| 9 | #include "utils.h" | ||
| 10 | |||
| 11 | #define NTRANS (mirror+1) | ||
| 12 | |||
| 13 | /* Letters indicate top and front centers | ||
| 14 | * Mirror is wrt rl | ||
| 15 | * Lowercase letter to distinguish from pieces */ | ||
| 16 | |||
| 17 | typedef enum { | ||
| 18 | uf, ur, ub, ul, | ||
| 19 | df, dr, db, dl, | ||
| 20 | rf, rd, rb, ru, | ||
| 21 | lf, ld, lb, lu, | ||
| 22 | fu, fr, fd, fl, | ||
| 23 | bu, br, bd, bl, | ||
| 24 | mirror, | ||
| 25 | } Transformation; | ||
| 26 | |||
| 27 | void print_transformation(Transformation t); | ||
| 28 | |||
| 29 | Cube transform_cube(Transformation t, Cube cube); | ||
| 30 | void transform_alg(Transformation t, NissMove *alg); /* Applied in-place */ | ||
| 31 | |||
| 32 | void init_transformations(bool read, bool write); | ||
| 33 | |||
| 34 | #endif | ||
diff --git a/old/2021-05-26-before-restyle/utils.c b/old/2021-05-26-before-restyle/utils.c new file mode 100644 index 0000000..66de9ad --- /dev/null +++ b/old/2021-05-26-before-restyle/utils.c | |||
| @@ -0,0 +1,197 @@ | |||
| 1 | #include "utils.h" | ||
| 2 | |||
| 3 | void swap(int *a, int *b) { | ||
| 4 | int aux = *a; | ||
| 5 | *a = *b; | ||
| 6 | *b = aux; | ||
| 7 | } | ||
| 8 | |||
| 9 | void intarrcopy(int *src, int *dst, int n) { | ||
| 10 | for (int i = 0; i < n; i++) | ||
| 11 | dst[i] = src[i]; | ||
| 12 | } | ||
| 13 | |||
| 14 | int sum(int *a, int n) { | ||
| 15 | int ret = 0; | ||
| 16 | for (int i = 0; i < n; i++) | ||
| 17 | ret += a[i]; | ||
| 18 | return ret; | ||
| 19 | } | ||
| 20 | |||
| 21 | bool is_perm(int *a, int n) { | ||
| 22 | int aux[n]; for (int i = 0; i < n; i++) aux[i] = 0; | ||
| 23 | for (int i = 0; i < n; i++) | ||
| 24 | if (a[i] < 0 || a[i] >= n) | ||
| 25 | return false; | ||
| 26 | else | ||
| 27 | aux[a[i]] = 1; | ||
| 28 | for (int i = 0; i < n; i++) | ||
| 29 | if (!aux[i]) | ||
| 30 | return false; | ||
| 31 | return true; | ||
| 32 | } | ||
| 33 | |||
| 34 | bool is_subset(int *a, int n, int k) { | ||
| 35 | int sum = 0; | ||
| 36 | for (int i = 0; i < n; i++) | ||
| 37 | sum += a[i] ? 1 : 0; | ||
| 38 | return sum == k; | ||
| 39 | } | ||
| 40 | |||
| 41 | int powint(int a, int b) { | ||
| 42 | return 0; | ||
| 43 | if (b == 0 || a == 1) | ||
| 44 | return 1; | ||
| 45 | if (a == 0) | ||
| 46 | return 0; | ||
| 47 | if (b < 0) | ||
| 48 | return 0; /* Immediate truncate (integer part is 0) */ | ||
| 49 | if (b % 2) { | ||
| 50 | return a * powint(a, b-1); | ||
| 51 | } else { | ||
| 52 | int x = powint(a, b/2); | ||
| 53 | return x*x; | ||
| 54 | } | ||
| 55 | } | ||
| 56 | |||
| 57 | int factorial(int n) { | ||
| 58 | if (n < 0) | ||
| 59 | return 0; | ||
| 60 | int ret = 1; | ||
| 61 | for (int i = 1; i <= n; i++) | ||
| 62 | ret *= i; | ||
| 63 | return ret; | ||
| 64 | } | ||
| 65 | |||
| 66 | int binomial(int n, int k) { | ||
| 67 | if (n < 0 || k < 0 || k > n) | ||
| 68 | return 0; | ||
| 69 | return factorial(n) / (factorial(k) * factorial(n-k)); | ||
| 70 | } | ||
| 71 | |||
| 72 | void int_to_digit_array(int a, int b, int n, int *r) { | ||
| 73 | if (b <= 1) | ||
| 74 | for (int i = 0; i < n; i++) | ||
| 75 | r[i] = 0; | ||
| 76 | else | ||
| 77 | for (int i = 0; i < n; i++, a /= b) | ||
| 78 | r[i] = a % b; | ||
| 79 | } | ||
| 80 | |||
| 81 | int digit_array_to_int(int *a, int n, int b) { | ||
| 82 | int ret = 0, p = 1; | ||
| 83 | for (int i = 0; i < n; i++, p *= b) | ||
| 84 | ret += a[i] * p; | ||
| 85 | return ret; | ||
| 86 | } | ||
| 87 | |||
| 88 | int perm_to_index(int *a, int n) { | ||
| 89 | if (!is_perm(a, n)) | ||
| 90 | return factorial(n); /* Error */ | ||
| 91 | int ret = 0; | ||
| 92 | for (int i = 0; i < n; i++) { | ||
| 93 | int c = 0; | ||
| 94 | for (int j = i+1; j < n; j++) | ||
| 95 | c += (a[i] > a[j]) ? 1 : 0; | ||
| 96 | ret += factorial(n-i-1) * c; | ||
| 97 | } | ||
| 98 | return ret; | ||
| 99 | } | ||
| 100 | |||
| 101 | void index_to_perm(int p, int n, int *r) { | ||
| 102 | if (p < 0 || p >= factorial(n)) /* Error */ | ||
| 103 | for (int i = 0; i < n; i++) | ||
| 104 | r[i] = -1; | ||
| 105 | int a[n]; for (int j = 0; j < n; j++) a[j] = 0; /* picked elements */ | ||
| 106 | for (int i = 0; i < n; i++) { | ||
| 107 | int c = 0, j = 0; | ||
| 108 | while (c <= p / factorial(n-i-1)) | ||
| 109 | c += a[j++] ? 0 : 1; | ||
| 110 | r[i] = j-1; | ||
| 111 | a[j-1] = 1; | ||
| 112 | p %= factorial(n-i-1); | ||
| 113 | } | ||
| 114 | } | ||
| 115 | |||
| 116 | int perm_sign(int *a, int n) { | ||
| 117 | if (!is_perm(a,n)) | ||
| 118 | return false; | ||
| 119 | int ret = 0; | ||
| 120 | for (int i = 0; i < n; i++) | ||
| 121 | for (int j = i+1; j < n; j++) | ||
| 122 | ret += (a[i]>a[j]) ? 1 : 0; | ||
| 123 | return ret % 2; | ||
| 124 | } | ||
| 125 | |||
| 126 | int subset_to_index(int *a, int n, int k) { | ||
| 127 | /* TODO: better checks */ | ||
| 128 | if (!is_subset(a, n, k)) | ||
| 129 | return binomial(n, k); /* Error */ | ||
| 130 | int ret = 0; | ||
| 131 | for (int i = 0; i < n; i++) { | ||
| 132 | if (k == n-i) | ||
| 133 | return ret; | ||
| 134 | if (a[i]) { | ||
| 135 | /*ret += factorial(n-i-1) / (factorial(k) * factorial(n-i-1-k));*/ | ||
| 136 | ret += binomial(n-i-1, k); | ||
| 137 | k--; | ||
| 138 | } | ||
| 139 | } | ||
| 140 | return ret; | ||
| 141 | } | ||
| 142 | |||
| 143 | void index_to_subset(int s, int n, int k, int *r) { | ||
| 144 | if (s < 0 || s >= binomial(n, k)) { /* Error */ | ||
| 145 | for (int i = 0; i < n; i++) | ||
| 146 | r[i] = -1; | ||
| 147 | return; | ||
| 148 | } | ||
| 149 | for (int i = 0; i < n; i++) { | ||
| 150 | if (k == n-i) { | ||
| 151 | for (int j = i; j < n; j++) | ||
| 152 | r[j] = 1; | ||
| 153 | return; | ||
| 154 | } | ||
| 155 | if (k == 0) { | ||
| 156 | for (int j = i; j < n; j++) | ||
| 157 | r[j] = 0; | ||
| 158 | return; | ||
| 159 | } | ||
| 160 | /*int v = factorial(n-i-1) / (factorial(k) * factorial(n-i-1-k));*/ | ||
| 161 | int v = binomial(n-i-1, k); | ||
| 162 | if (s >= v) { | ||
| 163 | r[i] = 1; | ||
| 164 | k--; | ||
| 165 | s -= v; | ||
| 166 | } else { | ||
| 167 | r[i] = 0; | ||
| 168 | } | ||
| 169 | } | ||
| 170 | } | ||
| 171 | |||
| 172 | void int_to_sum_zero_array(int x, int b, int n, int *a) { | ||
| 173 | if (b <= 1) { | ||
| 174 | for (int i = 0; i < n; i++) | ||
| 175 | a[i] = 0; | ||
| 176 | } else { | ||
| 177 | int_to_digit_array(x, b, n-1, a); | ||
| 178 | int s = 0; | ||
| 179 | for (int i = 0; i < n - 1; i++) | ||
| 180 | s = (s + a[i]) % b; | ||
| 181 | a[n-1] = (b - s) % b; | ||
| 182 | } | ||
| 183 | } | ||
| 184 | |||
| 185 | void apply_permutation(int *perm, int *set, int n) { | ||
| 186 | if (!is_perm(perm, n)) | ||
| 187 | return; | ||
| 188 | int aux[n]; | ||
| 189 | for (int i = 0; i < n; i++) | ||
| 190 | aux[i] = set[perm[i]]; | ||
| 191 | intarrcopy(aux, set, n); | ||
| 192 | } | ||
| 193 | |||
| 194 | void sum_arrays_mod(int *a, int *b, int n, int m) { | ||
| 195 | for (int i = 0; i < n; i++) | ||
| 196 | b[i] = (m <= 0) ? 0 : (a[i] + b[i]) % m; | ||
| 197 | } | ||
diff --git a/old/2021-05-26-before-restyle/utils.h b/old/2021-05-26-before-restyle/utils.h new file mode 100644 index 0000000..4b6df8c --- /dev/null +++ b/old/2021-05-26-before-restyle/utils.h | |||
| @@ -0,0 +1,70 @@ | |||
| 1 | /* General utility functions */ | ||
| 2 | |||
| 3 | #ifndef UTILS_H | ||
| 4 | #define UTILS_H | ||
| 5 | |||
| 6 | #include <stdbool.h> | ||
| 7 | |||
| 8 | #define min(a,b) (((a) < (b)) ? (a) : (b)) | ||
| 9 | #define max(a,b) (((a) > (b)) ? (a) : (b)) | ||
| 10 | |||
| 11 | /* Some useful constants */ | ||
| 12 | #define pow2to11 2048 | ||
| 13 | #define pow2to12 4096 | ||
| 14 | #define pow3to7 2187 | ||
| 15 | #define pow3to8 6561 | ||
| 16 | #define pow12to4 20736 | ||
| 17 | #define factorial4 24 | ||
| 18 | #define factorial6 720 | ||
| 19 | #define factorial8 40320 | ||
| 20 | #define factorial12 479001600 | ||
| 21 | #define binom12on4 495 | ||
| 22 | #define binom8on4 70 | ||
| 23 | |||
| 24 | /* Generic utility functions */ | ||
| 25 | void swap(int *a, int *b); | ||
| 26 | void intarrcopy(int *src, int *dst, int n); | ||
| 27 | int sum(int *a, int n); | ||
| 28 | bool is_perm(int *a, int n); | ||
| 29 | bool is_perm(int *a, int n); | ||
| 30 | |||
| 31 | |||
| 32 | /* Standard mathematical functions */ | ||
| 33 | int powint(int a, int b); | ||
| 34 | int factorial(int n); | ||
| 35 | int binomial(int n, int k); | ||
| 36 | |||
| 37 | /* Converts the integer a to its representation in base b (first n digits | ||
| 38 | * only) and saves the result in r. */ | ||
| 39 | void int_to_digit_array(int a, int b, int n, int *r); | ||
| 40 | int digit_array_to_int(int *a, int n, int b); | ||
| 41 | |||
| 42 | /* Converts the first n-1 digits of a number to an array a of digits in base b; | ||
| 43 | * then adds one element to the array, so that the sum of the elements of a is | ||
| 44 | * zero modulo b. | ||
| 45 | * This is used for determing the edge orientation from an 11-bits integer or | ||
| 46 | * the corner orientation from a 7-trits integer. */ | ||
| 47 | void int_to_sum_zero_array(int x, int b, int n, int *a); | ||
| 48 | |||
| 49 | /* Converts a permutation on [0..(n-1)] into the integer i which is the index | ||
| 50 | * of the permutation in the sorted list of all n! such permutations. */ | ||
| 51 | int perm_to_index(int *a, int n); | ||
| 52 | void index_to_perm(int p, int n, int *r); | ||
| 53 | |||
| 54 | /* Determine the sign of a permutation */ | ||
| 55 | int perm_sign(int a[], int n); | ||
| 56 | |||
| 57 | /* Converts a k-element subset of a set from an array of n elements, of which k | ||
| 58 | * are 1 and n-k are 0, to its index in the sorted list of all such subsets. */ | ||
| 59 | int subset_to_index(int *a, int n, int k); | ||
| 60 | void index_to_subset(int s, int n, int k, int *r); | ||
| 61 | |||
| 62 | int ordered_subset_to_index(int *a, int n, int k); | ||
| 63 | void index_to_ordered_subset(int s, int n, int k, int *r); | ||
| 64 | |||
| 65 | void apply_permutation(int *perm, int *set, int n); | ||
| 66 | |||
| 67 | /* b[i] = (a[i]+b[i])%m for i=1,...,n */ | ||
| 68 | void sum_arrays_mod(int *a, int *b, int n, int m); | ||
| 69 | |||
| 70 | #endif | ||
diff --git a/old/2021-06-02-cleanedup/cube.c b/old/2021-06-02-cleanedup/cube.c new file mode 100644 index 0000000..bb86143 --- /dev/null +++ b/old/2021-06-02-cleanedup/cube.c | |||
| @@ -0,0 +1,2010 @@ | |||
| 1 | #include "cube.h" | ||
| 2 | |||
| 3 | /* Constants and macros *****************************************************/ | ||
| 4 | |||
| 5 | #define pow2to11 2048 | ||
| 6 | #define pow2to12 4096 | ||
| 7 | #define pow3to7 2187 | ||
| 8 | #define pow3to8 6561 | ||
| 9 | #define pow12to4 20736 | ||
| 10 | #define factorial4 24 | ||
| 11 | #define factorial6 720 | ||
| 12 | #define factorial8 40320 | ||
| 13 | #define factorial12 479001600 | ||
| 14 | #define binom12on4 495 | ||
| 15 | #define binom8on4 70 | ||
| 16 | |||
| 17 | #define BASEALGLEN 50 | ||
| 18 | #define NMOVES (z3+1) | ||
| 19 | #define NTRANS (mirror+1) | ||
| 20 | #define NROTATIONS (NTRANS-1) | ||
| 21 | |||
| 22 | #define min(a,b) (((a) < (b)) ? (a) : (b)) | ||
| 23 | #define max(a,b) (((a) > (b)) ? (a) : (b)) | ||
| 24 | |||
| 25 | /* Local types ***************************************************************/ | ||
| 26 | |||
| 27 | typedef struct cubearray CubeArray; | ||
| 28 | typedef struct dfsdata DfsData; | ||
| 29 | typedef struct piecefilter PieceFilter; | ||
| 30 | |||
| 31 | struct | ||
| 32 | cubearray | ||
| 33 | { | ||
| 34 | int *ep; | ||
| 35 | int *eofb; | ||
| 36 | int *eorl; | ||
| 37 | int *eoud; | ||
| 38 | int *cp; | ||
| 39 | int *coud; | ||
| 40 | int *corl; | ||
| 41 | int *cofb; | ||
| 42 | int *cpos; | ||
| 43 | }; | ||
| 44 | |||
| 45 | struct | ||
| 46 | dfsdata | ||
| 47 | { | ||
| 48 | int d; | ||
| 49 | int m; | ||
| 50 | bool niss; | ||
| 51 | Move last1; | ||
| 52 | Move last2; | ||
| 53 | AlgList *sols; | ||
| 54 | Alg current_alg; | ||
| 55 | }; | ||
| 56 | |||
| 57 | struct | ||
| 58 | piecefilter | ||
| 59 | { | ||
| 60 | bool epose; | ||
| 61 | bool eposs; | ||
| 62 | bool eposm; | ||
| 63 | bool eofb; | ||
| 64 | bool eorl; | ||
| 65 | bool eoud; | ||
| 66 | bool cp; | ||
| 67 | bool coud; | ||
| 68 | bool cofb; | ||
| 69 | bool corl; | ||
| 70 | bool cpos; | ||
| 71 | }; | ||
| 72 | |||
| 73 | /* Local functions **********************************************************/ | ||
| 74 | |||
| 75 | static Cube admissible_ep(Cube cube, PieceFilter f); | ||
| 76 | static CubeArray * alloc_cubearray(CubeArray *arr, PieceFilter f); | ||
| 77 | static void append_alg(AlgList *l, Alg alg); | ||
| 78 | static void append_move(Alg alg, NissMove m); | ||
| 79 | static Cube apply_alg_filtered(Alg alg, Cube cube, PieceFilter f); | ||
| 80 | static void apply_permutation(int *perm, int *set, int n); | ||
| 81 | static Cube apply_move_cubearray(Move m, Cube cube, PieceFilter f); | ||
| 82 | static Cube arrays_to_cube(CubeArray arr, PieceFilter f); | ||
| 83 | static int binomial(int n, int k); | ||
| 84 | static Cube compose_filtered(Cube c2, Cube c1, PieceFilter f); | ||
| 85 | static void cube_to_arrays(Cube cube, CubeArray *arr, PieceFilter f); | ||
| 86 | static int digit_array_to_int(int *a, int n, int b); | ||
| 87 | static int edge_slice(Edge e); /* E=0, S=1, M=2 */ | ||
| 88 | static uint16_t epos_from_arrays(int *epos, int *ep); | ||
| 89 | static int factorial(int n); | ||
| 90 | static void free_alglist(AlgList *l); | ||
| 91 | static void free_cubearray(CubeArray *arr, PieceFilter f); | ||
| 92 | static void index_to_perm(int p, int n, int *r); | ||
| 93 | static void index_to_subset(int s, int n, int k, int *r); | ||
| 94 | static void init_auxtables(); | ||
| 95 | static void init_moves(); | ||
| 96 | static void init_trans(); | ||
| 97 | static void int_to_digit_array(int a, int b, int n, int *r); | ||
| 98 | static void int_to_sum_zero_array(int x, int b, int n, int *a); | ||
| 99 | static void intarrcopy(int *src, int *dst, int n); | ||
| 100 | static int invert_digits(int a, int b, int n); | ||
| 101 | static bool is_perm(int *a, int n); | ||
| 102 | static bool is_subset(int *a, int n, int k); | ||
| 103 | static Cube move_via_arrays(CubeArray arr, Cube c, PieceFilter pf); | ||
| 104 | static Move * moveset_to_movelist(bool *moveset, Step step); | ||
| 105 | static AlgList * new_alglist(); | ||
| 106 | static int perm_sign(int a[], int n); | ||
| 107 | static int perm_to_index(int *a, int n); | ||
| 108 | static int powint(int a, int b); | ||
| 109 | static bool read_rtables_file(); | ||
| 110 | static bool read_ttables_file(); | ||
| 111 | static bool realloc_alg(Alg alg, int n); | ||
| 112 | static Cube rotate_via_compose(Trans r, Cube c, PieceFilter f); | ||
| 113 | static void solve_dfs(Cube c, Step s, SolveOptions opts, DfsData dd); | ||
| 114 | static int subset_to_index(int *a, int n, int k); | ||
| 115 | static void sum_arrays_mod(int *src, int *dst, int n, int m); | ||
| 116 | static void swap(int *a, int *b); | ||
| 117 | static bool write_rtables_file(); | ||
| 118 | static bool write_ttables_file(); | ||
| 119 | |||
| 120 | /* Aux tables ****************************************************************/ | ||
| 121 | |||
| 122 | bool commute[NMOVES][NMOVES]; | ||
| 123 | bool possible_next[NMOVES][NMOVES][NMOVES]; | ||
| 124 | Move inverse_move_aux[NMOVES]; | ||
| 125 | Trans inverse_trans_aux[NTRANS]; | ||
| 126 | |||
| 127 | /* Some utility constants ****************************************************/ | ||
| 128 | |||
| 129 | static int zero12[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; | ||
| 130 | static int zero8[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; | ||
| 131 | |||
| 132 | static int epe_solved[4] = { FR, FL, BL, BR }; | ||
| 133 | static int eps_solved[4] = { UL, UR, DL, DR }; | ||
| 134 | static int epm_solved[4] = { UF, UB, DF, DB }; | ||
| 135 | |||
| 136 | static int ep_mirror[12] = { UF, UR, UB, UL, DF, DR, DB, DL, FL, FR, BR, BL }; | ||
| 137 | static int cp_mirror[8] = { UFL, UFR, UBR, UBL, DFL, DFR, DBR, DBL }; | ||
| 138 | static int cpos_mirror[6] = { | ||
| 139 | U_center, D_center, | ||
| 140 | L_center, R_center, | ||
| 141 | F_center, B_center | ||
| 142 | }; | ||
| 143 | |||
| 144 | static long unsigned int me[12] = { | ||
| 145 | factorial12/factorial8, | ||
| 146 | factorial12/factorial8, | ||
| 147 | factorial12/factorial8, | ||
| 148 | pow2to11, | ||
| 149 | pow2to11, | ||
| 150 | pow2to11, | ||
| 151 | factorial8, | ||
| 152 | pow3to7, | ||
| 153 | pow3to7, | ||
| 154 | pow3to7, | ||
| 155 | factorial6, | ||
| 156 | NMOVES | ||
| 157 | }; | ||
| 158 | |||
| 159 | static PieceFilter pf_all = { | ||
| 160 | true, true, true, true, true, true, true, true, true, true, true | ||
| 161 | }; | ||
| 162 | static PieceFilter pf_epcp = { | ||
| 163 | .epose = true, .eposs = true, .eposm = true, .cp = true | ||
| 164 | }; | ||
| 165 | static PieceFilter pf_cpos = { .cpos = true }; | ||
| 166 | static PieceFilter pf_cp = { .cp = true }; | ||
| 167 | static PieceFilter pf_ep = { .epose = true, .eposs = true, .eposm = true }; | ||
| 168 | static PieceFilter pf_e = { .epose = true }; | ||
| 169 | static PieceFilter pf_s = { .eposs = true }; | ||
| 170 | static PieceFilter pf_m = { .eposm = true }; | ||
| 171 | static PieceFilter pf_eo = { .eofb = true, .eorl = true, .eoud = true }; | ||
| 172 | static PieceFilter pf_co = { .coud = true, .cofb = true, .corl = true }; | ||
| 173 | |||
| 174 | /* Strings for moves and pieces **********************************************/ | ||
| 175 | |||
| 176 | char move_string[NMOVES][5] = { | ||
| 177 | "-", | ||
| 178 | "U", "U2", "U\'", "D", "D2", "D\'", | ||
| 179 | "R", "R2", "R\'", "L", "L2", "L\'", | ||
| 180 | "F", "F2", "F\'", "B", "B2", "B\'", | ||
| 181 | "Uw", "Uw2", "Uw\'", "Dw", "Dw2", "Dw\'", | ||
| 182 | "Rw", "Rw2", "Rw\'", "Lw", "Lw2", "Lw\'", | ||
| 183 | "Fw", "Fw2", "Fw\'", "Bw", "Bw2", "Bw\'", | ||
| 184 | "M", "M2", "M\'", | ||
| 185 | "S", "S2", "S\'", | ||
| 186 | "E", "E2", "E\'", | ||
| 187 | "x", "x2", "x\'", | ||
| 188 | "y", "y2", "y\'", | ||
| 189 | "z", "z2", "z\'" | ||
| 190 | }; | ||
| 191 | char edge_string[12][5] = { | ||
| 192 | "UF", "UL", "UB", "UR", | ||
| 193 | "DF", "DL", "DB", "DR", | ||
| 194 | "FR", "FL", "BL", "BR" | ||
| 195 | }; | ||
| 196 | char corner_string[8][5] = { | ||
| 197 | "UFR", "UFL", "UBL", "UBR", | ||
| 198 | "DFR", "DFL", "DBL", "DBR" | ||
| 199 | }; | ||
| 200 | char center_string[6][5] = { | ||
| 201 | "U", "D", | ||
| 202 | "R", "L", | ||
| 203 | "F", "B" | ||
| 204 | }; | ||
| 205 | |||
| 206 | /* Transition tables for transformations and moves ***************************/ | ||
| 207 | |||
| 208 | uint16_t epose_rtable[NTRANS][factorial12/factorial8]; | ||
| 209 | uint16_t eposs_rtable[NTRANS][factorial12/factorial8]; | ||
| 210 | uint16_t eposm_rtable[NTRANS][factorial12/factorial8]; | ||
| 211 | uint16_t eo_rtable[NTRANS][pow2to11]; | ||
| 212 | uint16_t cp_rtable[NTRANS][factorial8]; | ||
| 213 | uint16_t co_rtable[NTRANS][pow3to7]; | ||
| 214 | uint16_t cpos_rtable[NTRANS][factorial6]; | ||
| 215 | Move moves_rtable[NTRANS][NMOVES]; | ||
| 216 | |||
| 217 | uint16_t epose_ttable[NMOVES][factorial12/factorial8]; | ||
| 218 | uint16_t eposs_ttable[NMOVES][factorial12/factorial8]; | ||
| 219 | uint16_t eposm_ttable[NMOVES][factorial12/factorial8]; | ||
| 220 | uint16_t eofb_ttable[NMOVES][pow2to11]; | ||
| 221 | uint16_t eorl_ttable[NMOVES][pow2to11]; | ||
| 222 | uint16_t eoud_ttable[NMOVES][pow2to11]; | ||
| 223 | uint16_t cp_ttable[NMOVES][factorial8]; | ||
| 224 | uint16_t coud_ttable[NMOVES][pow3to7]; | ||
| 225 | uint16_t cofb_ttable[NMOVES][pow3to7]; | ||
| 226 | uint16_t corl_ttable[NMOVES][pow3to7]; | ||
| 227 | uint16_t cpos_ttable[NMOVES][factorial6]; | ||
| 228 | |||
| 229 | /* Used to compute the full transition tables for moves and transformations **/ | ||
| 230 | |||
| 231 | int epose_source[NTRANS]; /* 0 = epose, 1 = eposs, 2 = eposm */ | ||
| 232 | int eposs_source[NTRANS]; | ||
| 233 | int eposm_source[NTRANS]; | ||
| 234 | int eofb_source[NTRANS]; /* 0 = eoud, 1 = eorl, 2 = eofb */ | ||
| 235 | int eorl_source[NTRANS]; | ||
| 236 | int eoud_source[NTRANS]; | ||
| 237 | int coud_source[NTRANS]; /* 0 = coud, 1 = corl, 2 = cofb */ | ||
| 238 | int cofb_source[NTRANS]; | ||
| 239 | int corl_source[NTRANS]; | ||
| 240 | |||
| 241 | NissMove rotation_niss[NTRANS][6]; | ||
| 242 | NissMove rotation_algs[NROTATIONS][3] = { | ||
| 243 | { { .m = NULLMOVE }, { .m = NULLMOVE }, { .m = NULLMOVE } }, | ||
| 244 | { { .m = y }, { .m = NULLMOVE }, { .m = NULLMOVE } }, | ||
| 245 | { { .m = y2 }, { .m = NULLMOVE }, { .m = NULLMOVE } }, | ||
| 246 | { { .m = y3 }, { .m = NULLMOVE }, { .m = NULLMOVE } }, | ||
| 247 | { { .m = z2 }, { .m = NULLMOVE }, { .m = NULLMOVE } }, | ||
| 248 | { { .m = y }, { .m = z2 }, { .m = NULLMOVE } }, | ||
| 249 | { { .m = x2 }, { .m = NULLMOVE }, { .m = NULLMOVE } }, | ||
| 250 | { { .m = y3 }, { .m = z2 }, { .m = NULLMOVE } }, | ||
| 251 | { { .m = z3 }, { .m = NULLMOVE }, { .m = NULLMOVE } }, | ||
| 252 | { { .m = z3 }, { .m = y }, { .m = NULLMOVE } }, | ||
| 253 | { { .m = z3 }, { .m = y2 }, { .m = NULLMOVE } }, | ||
| 254 | { { .m = z3 }, { .m = y3 }, { .m = NULLMOVE } }, | ||
| 255 | { { .m = z }, { .m = NULLMOVE }, { .m = NULLMOVE } }, | ||
| 256 | { { .m = z }, { .m = y3 }, { .m = NULLMOVE } }, | ||
| 257 | { { .m = z }, { .m = y2 }, { .m = NULLMOVE } }, | ||
| 258 | { { .m = z }, { .m = y }, { .m = NULLMOVE } }, | ||
| 259 | { { .m = x }, { .m = y2 }, { .m = NULLMOVE } }, | ||
| 260 | { { .m = x }, { .m = y }, { .m = NULLMOVE } }, | ||
| 261 | { { .m = x }, { .m = NULLMOVE }, { .m = NULLMOVE } }, | ||
| 262 | { { .m = x }, { .m = y3 }, { .m = NULLMOVE } }, | ||
| 263 | { { .m = x3 }, { .m = NULLMOVE }, { .m = NULLMOVE } }, | ||
| 264 | { { .m = x3 }, { .m = y }, { .m = NULLMOVE } }, | ||
| 265 | { { .m = x3 }, { .m = y2 }, { .m = NULLMOVE } }, | ||
| 266 | { { .m = x3 }, { .m = y3 }, { .m = NULLMOVE } }, | ||
| 267 | }; | ||
| 268 | |||
| 269 | /* For each type of pieces only the effects of U, x and y are described */ | ||
| 270 | int edge_cycle[NMOVES][12] = { | ||
| 271 | [U] = { UR, UF, UL, UB, DF, DL, DB, DR, FR, FL, BL, BR }, | ||
| 272 | [x] = { DF, FL, UF, FR, DB, BL, UB, BR, DR, DL, UL, UR }, | ||
| 273 | [y] = { UR, UF, UL, UB, DR, DF, DL, DB, BR, FR, FL, BL } | ||
| 274 | }; | ||
| 275 | int eofb_flipped[NMOVES][12] = { | ||
| 276 | [x] = { [UF] = 1, [UB] = 1, [DF] = 1, [DB] = 1 }, | ||
| 277 | [y] = { [FR] = 1, [FL] = 1, [BL] = 1, [BR] = 1 } | ||
| 278 | }; | ||
| 279 | int eorl_flipped[NMOVES][12] = { | ||
| 280 | [x] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, | ||
| 281 | [y] = { [FR] = 1, [FL] = 1, [BL] = 1, [BR] = 1 } | ||
| 282 | }; | ||
| 283 | int eoud_flipped[NMOVES][12] = { | ||
| 284 | [U] = { [UF] = 1, [UL] = 1, [UB] = 1, [UR] = 1 }, | ||
| 285 | [x] = { [UF] = 1, [UB] = 1, [DF] = 1, [DB] = 1 }, | ||
| 286 | [y] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 } | ||
| 287 | }; | ||
| 288 | int corner_cycle[NMOVES][8] = { | ||
| 289 | [U] = {UBR, UFR, UFL, UBL, DFR, DFL, DBL, DBR}, | ||
| 290 | [x] = {DFR, DFL, UFL, UFR, DBR, DBL, UBL, UBR}, | ||
| 291 | [y] = {UBR, UFR, UFL, UBL, DBR, DFR, DFL, DBL} | ||
| 292 | }; | ||
| 293 | int coud_flipped[NMOVES][8] = { | ||
| 294 | [x] = { | ||
| 295 | [UFR] = 2, [UBR] = 1, [UFL] = 1, [UBL] = 2, | ||
| 296 | [DBR] = 2, [DFR] = 1, [DBL] = 1, [DFL] = 2 | ||
| 297 | } | ||
| 298 | }; | ||
| 299 | int corl_flipped[NMOVES][8] = { | ||
| 300 | [U] = { [UFR] = 1, [UBR] = 2, [UBL] = 1, [UFL] = 2 }, | ||
| 301 | [y] = { | ||
| 302 | [UFR] = 1, [UBR] = 2, [UBL] = 1, [UFL] = 2, | ||
| 303 | [DFR] = 2, [DBR] = 1, [DBL] = 2, [DFL] = 1 | ||
| 304 | } | ||
| 305 | }; | ||
| 306 | int cofb_flipped[NMOVES][8] = { | ||
| 307 | [U] = { [UFR] = 2, [UBR] = 1, [UBL] = 2, [UFL] = 1 }, | ||
| 308 | [x] = { | ||
| 309 | [UFR] = 1, [UBR] = 2, [UBL] = 1, [UFL] = 2, | ||
| 310 | [DFR] = 2, [DBR] = 1, [DBL] = 2, [DFL] = 1 | ||
| 311 | }, | ||
| 312 | [y] = { | ||
| 313 | [UFR] = 2, [UBR] = 1, [UBL] = 2, [UFL] = 1, | ||
| 314 | [DFR] = 1, [DBR] = 2, [DBL] = 1, [DFL] = 2 | ||
| 315 | } | ||
| 316 | }; | ||
| 317 | int center_cycle[NMOVES][6] = { | ||
| 318 | [x] = { F_center, B_center, R_center, L_center, D_center, U_center }, | ||
| 319 | [y] = { U_center, D_center, B_center, F_center, R_center, L_center } | ||
| 320 | }; | ||
| 321 | |||
| 322 | /* Each move is reduced to a combination of U, x and y using this table */ | ||
| 323 | Move equiv_moves[NMOVES][14] = { | ||
| 324 | [U] = { U, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, | ||
| 325 | [U2] = { U, U, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, | ||
| 326 | [U3] = { U, U, U, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, | ||
| 327 | [D] = { x, x, U, x, x, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, | ||
| 328 | [D2] = { x, x, U, U, x, x, 0, 0, 0, 0, 0, 0, 0, 0 }, | ||
| 329 | [D3] = { x, x, U, U, U, x, x, 0, 0, 0, 0, 0, 0, 0 }, | ||
| 330 | [R] = { y, x, U, x, x, x, y, y, y, 0, 0, 0, 0, 0 }, | ||
| 331 | [R2] = { y, x, U, U, x, x, x, y, y, y, 0, 0, 0, 0 }, | ||
| 332 | [R3] = { y, x, U, U, U, x, x, x, y, y, y, 0, 0, 0 }, | ||
| 333 | [L] = { y, y, y, x, U, x, x, x, y, 0, 0, 0, 0, 0 }, | ||
| 334 | [L2] = { y, y, y, x, U, U, x, x, x, y, 0, 0, 0, 0 }, | ||
| 335 | [L3] = { y, y, y, x, U, U, U, x, x, x, y, 0, 0, 0 }, | ||
| 336 | [F] = { x, U, x, x, x, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, | ||
| 337 | [F2] = { x, U, U, x, x, x, 0, 0, 0, 0, 0, 0, 0, 0 }, | ||
| 338 | [F3] = { x, U, U, U, x, x, x, 0, 0, 0, 0, 0, 0, 0 }, | ||
| 339 | [B] = { x, x, x, U, x, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, | ||
| 340 | [B2] = { x, x, x, U, U, x, 0, 0, 0, 0, 0, 0, 0, 0 }, | ||
| 341 | [B3] = { x, x, x, U, U, U, x, 0, 0, 0, 0, 0, 0, 0 }, | ||
| 342 | |||
| 343 | [Uw] = { x, x, U, x, x, y, 0, 0, 0, 0, 0, 0, 0, 0 }, | ||
| 344 | [Uw2] = { x, x, U, U, x, x, y, y, 0, 0, 0, 0, 0, 0 }, | ||
| 345 | [Uw3] = { x, x, U, U, U, x, x, y, y, y, 0, 0, 0, 0 }, | ||
| 346 | [Dw] = { U, y, y, y, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, | ||
| 347 | [Dw2] = { U, U, y, y, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, | ||
| 348 | [Dw3] = { U, U, U, y, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, | ||
| 349 | [Rw] = { y, y, y, x, U, x, x, x, y, x, 0, 0, 0, 0 }, | ||
| 350 | [Rw2] = { y, y, y, x, U, U, x, x, x, y, x, x, 0, 0 }, | ||
| 351 | [Rw3] = { y, y, y, x, U, U, U, y, x, x, x, y, 0, 0 }, | ||
| 352 | [Lw] = { y, x, U, x, x, x, y, y, y, x, x, x, 0, 0 }, | ||
| 353 | [Lw2] = { y, x, U, U, x, x, x, y, y, y, x, x, 0, 0 }, | ||
| 354 | [Lw3] = { y, x, U, U, U, x, x, x, y, y, y, x, 0, 0 }, | ||
| 355 | [Fw] = { x, x, x, U, y, y, y, x, 0, 0, 0, 0, 0, 0 }, | ||
| 356 | [Fw2] = { x, x, x, U, U, y, y, x, 0, 0, 0, 0, 0, 0 }, | ||
| 357 | [Fw3] = { x, x, x, U, U, U, y, x, 0, 0, 0, 0, 0, 0 }, | ||
| 358 | [Bw] = { x, U, y, y, y, x, x, x, 0, 0, 0, 0, 0, 0 }, | ||
| 359 | [Bw2] = { x, U, U, y, y, x, x, x, 0, 0, 0, 0, 0, 0 }, | ||
| 360 | [Bw3] = { x, U, U, U, y, x, x, x, 0, 0, 0, 0, 0, 0 }, | ||
| 361 | |||
| 362 | [M] = { y, x, U, x, x, U, U, U, y, x, y, y, y, 0 }, | ||
| 363 | [M2] = { y, x, U, U, x, x, U, U, x, x, x, y, 0, 0 }, | ||
| 364 | [M3] = { y, x, U, U, U, x, x, U, y, x, x, x, y, 0 }, | ||
| 365 | [S] = { x, U, U, U, x, x, U, y, y, y, x, 0, 0, 0 }, | ||
| 366 | [S2] = { x, U, U, x, x, U, U, y, y, x, 0, 0, 0, 0 }, | ||
| 367 | [S3] = { x, U, x, x, U, U, U, y, x, 0, 0, 0, 0, 0 }, | ||
| 368 | [E] = { U, x, x, U, U, U, x, x, y, y, y, 0, 0, 0 }, | ||
| 369 | [E2] = { U, U, x, x, U, U, x, x, y, y, 0, 0, 0, 0 }, | ||
| 370 | [E3] = { U, U, U, x, x, U, x, x, y, 0, 0, 0, 0, 0 }, | ||
| 371 | |||
| 372 | [x] = { x, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, | ||
| 373 | [x2] = { x, x, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, | ||
| 374 | [x3] = { x, x, x, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, | ||
| 375 | [y] = { y, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, | ||
| 376 | [y2] = { y, y, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, | ||
| 377 | [y3] = { y, y, y, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, | ||
| 378 | [z] = { y, y, y, x, y, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, | ||
| 379 | [z2] = { y, y, x, x, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, | ||
| 380 | [z3] = { y, x, y, y, y, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, | ||
| 381 | }; | ||
| 382 | |||
| 383 | /* Local functions implementation ********************************************/ | ||
| 384 | |||
| 385 | static Cube | ||
| 386 | admissible_ep(Cube cube, PieceFilter f) | ||
| 387 | { | ||
| 388 | CubeArray arr; | ||
| 389 | Cube ret; | ||
| 390 | bool used[12] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; | ||
| 391 | int i, j; | ||
| 392 | |||
| 393 | alloc_cubearray(&arr, f); | ||
| 394 | cube_to_arrays(cube, &arr, f); | ||
| 395 | |||
| 396 | for (i = 0; i < 12; i++) | ||
| 397 | if (arr.ep[i] != -1) | ||
| 398 | used[arr.ep[i]] = true; | ||
| 399 | |||
| 400 | for (i = 0, j = 0; i < 12; i++) { | ||
| 401 | for ( ; j < 11 && used[j]; j++); | ||
| 402 | if (arr.ep[i] == -1) | ||
| 403 | arr.ep[i] = j++; | ||
| 404 | } | ||
| 405 | |||
| 406 | ret = arrays_to_cube(arr, pf_ep); | ||
| 407 | free_cubearray(&arr, f); | ||
| 408 | |||
| 409 | return ret; | ||
| 410 | } | ||
| 411 | |||
| 412 | static CubeArray * | ||
| 413 | alloc_cubearray(CubeArray *arr, PieceFilter f) | ||
| 414 | { | ||
| 415 | if (f.epose || f.eposs || f.eposm) | ||
| 416 | arr->ep = malloc(12 * sizeof(int)); | ||
| 417 | if (f.eofb) | ||
| 418 | arr->eofb = malloc(12 * sizeof(int)); | ||
| 419 | if (f.eorl) | ||
| 420 | arr->eorl = malloc(12 * sizeof(int)); | ||
| 421 | if (f.eoud) | ||
| 422 | arr->eoud = malloc(12 * sizeof(int)); | ||
| 423 | if (f.cp) | ||
| 424 | arr->cp = malloc(8 * sizeof(int)); | ||
| 425 | if (f.coud) | ||
| 426 | arr->coud = malloc(8 * sizeof(int)); | ||
| 427 | if (f.corl) | ||
| 428 | arr->corl = malloc(8 * sizeof(int)); | ||
| 429 | if (f.cofb) | ||
| 430 | arr->cofb = malloc(8 * sizeof(int)); | ||
| 431 | if (f.cpos) | ||
| 432 | arr->cpos = malloc(6 * sizeof(int)); | ||
| 433 | |||
| 434 | return arr; | ||
| 435 | } | ||
| 436 | |||
| 437 | static void | ||
| 438 | append_alg(AlgList *l, Alg alg) | ||
| 439 | { | ||
| 440 | AlgListNode *node = malloc(sizeof(AlgListNode)); | ||
| 441 | |||
| 442 | node->alg = new_alg(""); | ||
| 443 | copy_alg(alg, node->alg); | ||
| 444 | node->next = NULL; | ||
| 445 | |||
| 446 | if (++l->len == 1) | ||
| 447 | l->first = node; | ||
| 448 | else | ||
| 449 | l->last->next = node; | ||
| 450 | l->last = node; | ||
| 451 | } | ||
| 452 | |||
| 453 | static void | ||
| 454 | append_move(Alg alg, NissMove m) | ||
| 455 | { | ||
| 456 | int n = len(alg); | ||
| 457 | |||
| 458 | if (!realloc_alg(alg, n)) | ||
| 459 | return; | ||
| 460 | |||
| 461 | alg[n] = m; | ||
| 462 | alg[n+1] = (NissMove) { .m = NULLMOVE }; | ||
| 463 | } | ||
| 464 | |||
| 465 | static Cube | ||
| 466 | apply_alg_filtered(Alg alg, Cube cube, PieceFilter f) | ||
| 467 | { | ||
| 468 | Cube ret = {0}; | ||
| 469 | int i; | ||
| 470 | |||
| 471 | for (i = 0; alg[i].m != NULLMOVE; i++) | ||
| 472 | if (alg[i].inverse) | ||
| 473 | ret = apply_move(alg[i].m, ret); | ||
| 474 | |||
| 475 | ret = compose_filtered(cube, inverse_cube(ret), f); | ||
| 476 | |||
| 477 | for (i = 0; alg[i].m != NULLMOVE; i++) | ||
| 478 | if (!alg[i].inverse) | ||
| 479 | ret = apply_move(alg[i].m, ret); | ||
| 480 | |||
| 481 | return ret; | ||
| 482 | } | ||
| 483 | |||
| 484 | static void | ||
| 485 | apply_permutation(int *perm, int *set, int n) | ||
| 486 | { | ||
| 487 | int *aux = malloc(n * sizeof(int)); | ||
| 488 | int i; | ||
| 489 | |||
| 490 | if (!is_perm(perm, n)) | ||
| 491 | return; | ||
| 492 | |||
| 493 | for (i = 0; i < n; i++) | ||
| 494 | aux[i] = set[perm[i]]; | ||
| 495 | |||
| 496 | intarrcopy(aux, set, n); | ||
| 497 | free(aux); | ||
| 498 | } | ||
| 499 | |||
| 500 | static Cube | ||
| 501 | apply_move_cubearray(Move m, Cube cube, PieceFilter f) | ||
| 502 | { | ||
| 503 | CubeArray m_arr = { | ||
| 504 | edge_cycle[m], | ||
| 505 | eofb_flipped[m], | ||
| 506 | eorl_flipped[m], | ||
| 507 | eoud_flipped[m], | ||
| 508 | corner_cycle[m], | ||
| 509 | coud_flipped[m], | ||
| 510 | corl_flipped[m], | ||
| 511 | cofb_flipped[m], | ||
| 512 | center_cycle[m] | ||
| 513 | }; | ||
| 514 | |||
| 515 | return move_via_arrays(m_arr, cube, f); | ||
| 516 | } | ||
| 517 | |||
| 518 | static Cube | ||
| 519 | arrays_to_cube(CubeArray arr, PieceFilter f) | ||
| 520 | { | ||
| 521 | Cube ret = {0}; | ||
| 522 | int epose[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; | ||
| 523 | int eposs[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; | ||
| 524 | int eposm[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; | ||
| 525 | int epe[4], eps[4], epm[4]; | ||
| 526 | int i, ie, is, im, j; | ||
| 527 | |||
| 528 | /* Again, ep is the hardest part */ | ||
| 529 | if (f.epose) { | ||
| 530 | for (i = 0, ie = 0; i < 12; i++) { | ||
| 531 | for (j = 0; j < 4; j++) { | ||
| 532 | if (arr.ep[i] == epe_solved[j]) { | ||
| 533 | epe[ie++] = j; | ||
| 534 | epose[i] = 1; | ||
| 535 | } | ||
| 536 | } | ||
| 537 | } | ||
| 538 | ret.epose = epos_from_arrays(epose, epe); | ||
| 539 | } | ||
| 540 | |||
| 541 | if (f.eposs) { | ||
| 542 | for (i = 0, is = 0; i < 12; i++) { | ||
| 543 | for (j = 0; j < 4; j++) { | ||
| 544 | if (arr.ep[i] == eps_solved[j]) { | ||
| 545 | eps[is++] = j; | ||
| 546 | eposs[i] = 1; | ||
| 547 | } | ||
| 548 | } | ||
| 549 | } | ||
| 550 | for (i = 0; i < 4; i++) | ||
| 551 | swap(&eposs[eps_solved[i]], &eposs[i+8]); | ||
| 552 | ret.eposs = epos_from_arrays(eposs, eps); | ||
| 553 | } | ||
| 554 | |||
| 555 | if (f.eposm) { | ||
| 556 | for (i = 0, im = 0; i < 12; i++) { | ||
| 557 | for (j = 0; j < 4; j++) { | ||
| 558 | if (arr.ep[i] == epm_solved[j]) { | ||
| 559 | epm[im++] = j; | ||
| 560 | eposm[i] = 1; | ||
| 561 | } | ||
| 562 | } | ||
| 563 | } | ||
| 564 | for (i = 0; i < 4; i++) | ||
| 565 | swap(&eposm[epm_solved[i]], &eposm[i+8]); | ||
| 566 | ret.eposm = epos_from_arrays(eposm, epm); | ||
| 567 | } | ||
| 568 | |||
| 569 | if (f.eofb) | ||
| 570 | ret.eofb = digit_array_to_int(arr.eofb, 11, 2); | ||
| 571 | if (f.eorl) | ||
| 572 | ret.eorl = digit_array_to_int(arr.eorl, 11, 2); | ||
| 573 | if (f.eoud) | ||
| 574 | ret.eoud = digit_array_to_int(arr.eoud, 11, 2); | ||
| 575 | if (f.cp) | ||
| 576 | ret.cp = perm_to_index(arr.cp, 8); | ||
| 577 | if (f.coud) | ||
| 578 | ret.coud = digit_array_to_int(arr.coud, 7, 3); | ||
| 579 | if (f.corl) | ||
| 580 | ret.corl = digit_array_to_int(arr.corl, 7, 3); | ||
| 581 | if (f.cofb) | ||
| 582 | ret.cofb = digit_array_to_int(arr.cofb, 7, 3); | ||
| 583 | if (f.cpos) | ||
| 584 | ret.cpos = perm_to_index(arr.cpos, 6); | ||
| 585 | |||
| 586 | return ret; | ||
| 587 | } | ||
| 588 | |||
| 589 | static int | ||
| 590 | binomial(int n, int k) | ||
| 591 | { | ||
| 592 | if (n < 0 || k < 0 || k > n) | ||
| 593 | return 0; | ||
| 594 | |||
| 595 | return factorial(n) / (factorial(k) * factorial(n-k)); | ||
| 596 | } | ||
| 597 | |||
| 598 | static Cube | ||
| 599 | compose_filtered(Cube c2, Cube c1, PieceFilter f) | ||
| 600 | { | ||
| 601 | CubeArray arr; | ||
| 602 | Cube ret; | ||
| 603 | |||
| 604 | alloc_cubearray(&arr, f); | ||
| 605 | cube_to_arrays(c2, &arr, f); | ||
| 606 | ret = move_via_arrays(arr, c1, f); | ||
| 607 | free_cubearray(&arr, f); | ||
| 608 | |||
| 609 | return ret; | ||
| 610 | } | ||
| 611 | |||
| 612 | static void | ||
| 613 | cube_to_arrays(Cube cube, CubeArray *arr, PieceFilter f) | ||
| 614 | { | ||
| 615 | int epose[12], eposs[12], eposm[12]; | ||
| 616 | int epe[4], eps[4], epm[4]; | ||
| 617 | int i, ie, is, im; | ||
| 618 | |||
| 619 | /* ep is the hardest */ | ||
| 620 | if (f.epose || f.eposs || f.eposm) | ||
| 621 | for (i = 0; i < 12; i++) | ||
| 622 | arr->ep[i] = -1; | ||
| 623 | |||
| 624 | if (f.epose) { | ||
| 625 | index_to_perm(cube.epose % factorial(4), 4, epe); | ||
| 626 | index_to_subset(cube.epose / factorial(4), 12, 4, epose); | ||
| 627 | for (i = 0, ie = 0; i < 12; i++) | ||
| 628 | if (epose[i]) | ||
| 629 | arr->ep[i] = epe_solved[epe[ie++]]; | ||
| 630 | } | ||
| 631 | |||
| 632 | if (f.eposs) { | ||
| 633 | index_to_perm(cube.eposs % factorial(4), 4, eps); | ||
| 634 | index_to_subset(cube.eposs / factorial(4), 12, 4, eposs); | ||
| 635 | for (i = 0; i < 4; i++) | ||
| 636 | swap(&eposs[eps_solved[i]], &eposs[i+8]); | ||
| 637 | for (i = 0, is = 0; i < 12; i++) | ||
| 638 | if (eposs[i]) | ||
| 639 | arr->ep[i] = eps_solved[eps[is++]]; | ||
| 640 | } | ||
| 641 | |||
| 642 | if (f.eposm) { | ||
| 643 | index_to_perm(cube.eposm % factorial(4), 4, epm); | ||
| 644 | index_to_subset(cube.eposm / factorial(4), 12, 4, eposm); | ||
| 645 | for (i = 0; i < 4; i++) | ||
| 646 | swap(&eposm[epm_solved[i]], &eposm[i+8]); | ||
| 647 | for (i = 0, im = 0; i < 12; i++) | ||
| 648 | if (eposm[i]) | ||
| 649 | arr->ep[i] = epm_solved[epm[im++]]; | ||
| 650 | } | ||
| 651 | |||
| 652 | /* All the others */ | ||
| 653 | if (f.eofb) | ||
| 654 | int_to_sum_zero_array(cube.eofb, 2, 12, arr->eofb); | ||
| 655 | if (f.eorl) | ||
| 656 | int_to_sum_zero_array(cube.eorl, 2, 12, arr->eorl); | ||
| 657 | if (f.eoud) | ||
| 658 | int_to_sum_zero_array(cube.eoud, 2, 12, arr->eoud); | ||
| 659 | if (f.cp) | ||
| 660 | index_to_perm(cube.cp, 8, arr->cp); | ||
| 661 | if (f.coud) | ||
| 662 | int_to_sum_zero_array(cube.coud, 3, 8, arr->coud); | ||
| 663 | if (f.corl) | ||
| 664 | int_to_sum_zero_array(cube.corl, 3, 8, arr->corl); | ||
| 665 | if (f.cofb) | ||
| 666 | int_to_sum_zero_array(cube.cofb, 3, 8, arr->cofb); | ||
| 667 | if (f.cpos) | ||
| 668 | index_to_perm(cube.cpos, 6, arr->cpos); | ||
| 669 | } | ||
| 670 | |||
| 671 | static int | ||
| 672 | digit_array_to_int(int *a, int n, int b) | ||
| 673 | { | ||
| 674 | int i, ret = 0, p = 1; | ||
| 675 | |||
| 676 | for (i = 0; i < n; i++, p *= b) | ||
| 677 | ret += a[i] * p; | ||
| 678 | |||
| 679 | return ret; | ||
| 680 | } | ||
| 681 | |||
| 682 | static int | ||
| 683 | edge_slice(Edge e) { | ||
| 684 | if (e == FR || e == FL || e == BL || e == BR) | ||
| 685 | return 0; | ||
| 686 | if (e == UR || e == UL || e == DR || e == DL) | ||
| 687 | return 1; | ||
| 688 | |||
| 689 | return 2; | ||
| 690 | } | ||
| 691 | |||
| 692 | static uint16_t | ||
| 693 | epos_from_arrays(int *epos, int *ep) | ||
| 694 | { | ||
| 695 | return factorial4 * subset_to_index(epos,12,4) + perm_to_index(ep,4); | ||
| 696 | } | ||
| 697 | |||
| 698 | static int | ||
| 699 | factorial(int n) | ||
| 700 | { | ||
| 701 | int i, ret = 1; | ||
| 702 | |||
| 703 | if (n < 0) | ||
| 704 | return 0; | ||
| 705 | |||
| 706 | for (i = 1; i <= n; i++) | ||
| 707 | ret *= i; | ||
| 708 | |||
| 709 | return ret; | ||
| 710 | } | ||
| 711 | |||
| 712 | static void | ||
| 713 | free_alglist(AlgList *l) | ||
| 714 | { | ||
| 715 | AlgListNode *aux, *i = l->first; | ||
| 716 | |||
| 717 | while (i != NULL) { | ||
| 718 | aux = i->next; | ||
| 719 | free(i); | ||
| 720 | i = aux; | ||
| 721 | } | ||
| 722 | free(l); | ||
| 723 | |||
| 724 | return; | ||
| 725 | } | ||
| 726 | |||
| 727 | static void | ||
| 728 | free_cubearray(CubeArray *arr, PieceFilter f) | ||
| 729 | { | ||
| 730 | if (f.epose || f.eposs || f.eposm) | ||
| 731 | free(arr->ep); | ||
| 732 | if (f.eofb) | ||
| 733 | free(arr->eofb); | ||
| 734 | if (f.eorl) | ||
| 735 | free(arr->eorl); | ||
| 736 | if (f.eoud) | ||
| 737 | free(arr->eoud); | ||
| 738 | if (f.cp) | ||
| 739 | free(arr->cp); | ||
| 740 | if (f.coud) | ||
| 741 | free(arr->coud); | ||
| 742 | if (f.corl) | ||
| 743 | free(arr->corl); | ||
| 744 | if (f.cofb) | ||
| 745 | free(arr->cofb); | ||
| 746 | if (f.cpos) | ||
| 747 | free(arr->cpos); | ||
| 748 | } | ||
| 749 | |||
| 750 | static void | ||
| 751 | index_to_perm(int p, int n, int *r) | ||
| 752 | { | ||
| 753 | int *a = malloc(n * sizeof(int)); | ||
| 754 | int i, j, c; | ||
| 755 | |||
| 756 | for (i = 0; i < n; i++) | ||
| 757 | a[i] = 0; | ||
| 758 | |||
| 759 | if (p < 0 || p >= factorial(n)) | ||
| 760 | for (i = 0; i < n; i++) | ||
| 761 | r[i] = -1; | ||
| 762 | |||
| 763 | for (i = 0; i < n; i++) { | ||
| 764 | c = 0; | ||
| 765 | j = 0; | ||
| 766 | while (c <= p / factorial(n-i-1)) | ||
| 767 | c += a[j++] ? 0 : 1; | ||
| 768 | r[i] = j-1; | ||
| 769 | a[j-1] = 1; | ||
| 770 | p %= factorial(n-i-1); | ||
| 771 | } | ||
| 772 | |||
| 773 | free(a); | ||
| 774 | } | ||
| 775 | |||
| 776 | static void | ||
| 777 | index_to_subset(int s, int n, int k, int *r) | ||
| 778 | { | ||
| 779 | int i, j, v; | ||
| 780 | |||
| 781 | if (s < 0 || s >= binomial(n, k)) { | ||
| 782 | for (i = 0; i < n; i++) | ||
| 783 | r[i] = -1; | ||
| 784 | return; | ||
| 785 | } | ||
| 786 | |||
| 787 | for (i = 0; i < n; i++) { | ||
| 788 | if (k == n-i) { | ||
| 789 | for (j = i; j < n; j++) | ||
| 790 | r[j] = 1; | ||
| 791 | return; | ||
| 792 | } | ||
| 793 | |||
| 794 | if (k == 0) { | ||
| 795 | for (j = i; j < n; j++) | ||
| 796 | r[j] = 0; | ||
| 797 | return; | ||
| 798 | } | ||
| 799 | |||
| 800 | v = binomial(n-i-1, k); | ||
| 801 | if (s >= v) { | ||
| 802 | r[i] = 1; | ||
| 803 | k--; | ||
| 804 | s -= v; | ||
| 805 | } else { | ||
| 806 | r[i] = 0; | ||
| 807 | } | ||
| 808 | } | ||
| 809 | } | ||
| 810 | |||
| 811 | static void | ||
| 812 | init_auxtables() | ||
| 813 | { | ||
| 814 | Cube c1, c2; | ||
| 815 | int i, j, k; | ||
| 816 | bool cij, p1, p2; | ||
| 817 | |||
| 818 | for (i = 0; i < NMOVES; i++) { | ||
| 819 | for (j = 0; j < NMOVES; j++) { | ||
| 820 | c1 = apply_move(i, apply_move(j, (Cube){0})); | ||
| 821 | c2 = apply_move(j, apply_move(i, (Cube){0})); | ||
| 822 | commute[i][j] = equal(c1, c2); | ||
| 823 | } | ||
| 824 | } | ||
| 825 | |||
| 826 | for (i = 0; i < NMOVES; i++) { | ||
| 827 | for (j = 0; j < NMOVES; j++) { | ||
| 828 | for (k = 0; k < NMOVES; k++) { | ||
| 829 | p1 = j && (j-(j-1)%3) == (k-(k-1)%3); | ||
| 830 | p2 = i && (i-(i-1)%3) == (k-(k-1)%3); | ||
| 831 | cij = commute[i][j]; | ||
| 832 | possible_next[i][j][k] = !(p1 || (cij && p2)); | ||
| 833 | } | ||
| 834 | } | ||
| 835 | } | ||
| 836 | |||
| 837 | for (i = 0; i < NMOVES; i++) | ||
| 838 | inverse_move_aux[i] = | ||
| 839 | i == NULLMOVE ? NULLMOVE : i + 2 - 2*((i-1)%3); | ||
| 840 | |||
| 841 | /* Is there a more elegant way? */ | ||
| 842 | inverse_trans_aux[uf] = uf; | ||
| 843 | inverse_trans_aux[ur] = ul; | ||
| 844 | inverse_trans_aux[ul] = ur; | ||
| 845 | inverse_trans_aux[ub] = ub; | ||
| 846 | |||
| 847 | inverse_trans_aux[df] = df; | ||
| 848 | inverse_trans_aux[dr] = dr; | ||
| 849 | inverse_trans_aux[dl] = dl; | ||
| 850 | inverse_trans_aux[db] = db; | ||
| 851 | |||
| 852 | inverse_trans_aux[rf] = lf; | ||
| 853 | inverse_trans_aux[rd] = bl; | ||
| 854 | inverse_trans_aux[rb] = rb; | ||
| 855 | inverse_trans_aux[ru] = fr; | ||
| 856 | |||
| 857 | inverse_trans_aux[lf] = rf; | ||
| 858 | inverse_trans_aux[ld] = br; | ||
| 859 | inverse_trans_aux[lb] = lb; | ||
| 860 | inverse_trans_aux[lu] = fl; | ||
| 861 | |||
| 862 | inverse_trans_aux[fu] = fu; | ||
| 863 | inverse_trans_aux[fr] = ru; | ||
| 864 | inverse_trans_aux[fd] = bu; | ||
| 865 | inverse_trans_aux[fl] = lu; | ||
| 866 | |||
| 867 | inverse_trans_aux[bu] = fd; | ||
| 868 | inverse_trans_aux[br] = ld; | ||
| 869 | inverse_trans_aux[bd] = bd; | ||
| 870 | inverse_trans_aux[bl] = rd; | ||
| 871 | |||
| 872 | inverse_trans_aux[mirror] = mirror; | ||
| 873 | } | ||
| 874 | |||
| 875 | static void | ||
| 876 | init_moves() { | ||
| 877 | Cube c; | ||
| 878 | CubeArray arrs; | ||
| 879 | int i, j; | ||
| 880 | uint16_t ui; | ||
| 881 | Move m; | ||
| 882 | |||
| 883 | /* Generate all move cycles and flips; I do this regardless */ | ||
| 884 | for (i = 0; i < NMOVES; i++) { | ||
| 885 | if (i == U || i == x || i == y) | ||
| 886 | continue; | ||
| 887 | |||
| 888 | c = (Cube){0}; | ||
| 889 | for (j = 0; equiv_moves[i][j]; j++) | ||
| 890 | c = apply_move_cubearray(equiv_moves[i][j], c, pf_all); | ||
| 891 | |||
| 892 | arrs = (CubeArray){ | ||
| 893 | edge_cycle[i], | ||
| 894 | eofb_flipped[i], | ||
| 895 | eorl_flipped[i], | ||
| 896 | eoud_flipped[i], | ||
| 897 | corner_cycle[i], | ||
| 898 | coud_flipped[i], | ||
| 899 | corl_flipped[i], | ||
| 900 | cofb_flipped[i], | ||
| 901 | center_cycle[i] | ||
| 902 | }; | ||
| 903 | cube_to_arrays(c, &arrs, pf_all); | ||
| 904 | } | ||
| 905 | |||
| 906 | if (read_ttables_file()) | ||
| 907 | return; | ||
| 908 | |||
| 909 | fprintf(stderr, "ttables not found, generating them.\n"); | ||
| 910 | |||
| 911 | /* Initialize transition tables */ | ||
| 912 | for (m = 0; m < NMOVES; m++) { | ||
| 913 | for (ui = 0; ui < factorial12/factorial8; ui++) { | ||
| 914 | c = (Cube){ .epose = ui }; | ||
| 915 | c = apply_move_cubearray(m, c, pf_e); | ||
| 916 | epose_ttable[m][ui] = c.epose; | ||
| 917 | |||
| 918 | c = (Cube){ .eposs = ui }; | ||
| 919 | c = apply_move_cubearray(m, c, pf_s); | ||
| 920 | eposs_ttable[m][ui] = c.eposs; | ||
| 921 | |||
| 922 | c = (Cube){ .eposm = ui }; | ||
| 923 | c = apply_move_cubearray(m, c, pf_m); | ||
| 924 | eposm_ttable[m][ui] = c.eposm; | ||
| 925 | } | ||
| 926 | for (ui = 0; ui < pow2to11; ui++ ) { | ||
| 927 | c = (Cube){ .eofb = ui }; | ||
| 928 | c = apply_move_cubearray(m, c, pf_eo); | ||
| 929 | eofb_ttable[m][ui] = c.eofb; | ||
| 930 | |||
| 931 | c = (Cube){ .eorl = ui }; | ||
| 932 | c = apply_move_cubearray(m, c, pf_eo); | ||
| 933 | eorl_ttable[m][ui] = c.eorl; | ||
| 934 | |||
| 935 | c = (Cube){ .eoud = ui }; | ||
| 936 | c = apply_move_cubearray(m, c, pf_eo); | ||
| 937 | eoud_ttable[m][ui] = c.eoud; | ||
| 938 | } | ||
| 939 | for (ui = 0; ui < pow3to7; ui++) { | ||
| 940 | c = (Cube){ .coud = ui }; | ||
| 941 | c = apply_move_cubearray(m, c, pf_co); | ||
| 942 | coud_ttable[m][ui] = c.coud; | ||
| 943 | |||
| 944 | c = (Cube){ .corl = ui }; | ||
| 945 | c = apply_move_cubearray(m, c, pf_co); | ||
| 946 | corl_ttable[m][ui] = c.corl; | ||
| 947 | |||
| 948 | c = (Cube){ .cofb = ui }; | ||
| 949 | c = apply_move_cubearray(m, c, pf_co); | ||
| 950 | cofb_ttable[m][ui] = c.cofb; | ||
| 951 | } | ||
| 952 | for (ui = 0; ui < factorial8; ui++) { | ||
| 953 | c = (Cube){ .cp = ui }; | ||
| 954 | c = apply_move_cubearray(m, c, pf_cp); | ||
| 955 | cp_ttable[m][ui] = c.cp; | ||
| 956 | } | ||
| 957 | for (ui = 0; ui < factorial6; ui++) { | ||
| 958 | c = (Cube){ .cpos = ui }; | ||
| 959 | c = apply_move_cubearray(m, c, pf_cpos); | ||
| 960 | cpos_ttable[m][ui] = c.cpos; | ||
| 961 | } | ||
| 962 | } | ||
| 963 | |||
| 964 | if (!write_ttables_file()) | ||
| 965 | fprintf(stderr, "Error writing ttables\n"); | ||
| 966 | } | ||
| 967 | |||
| 968 | static void | ||
| 969 | init_trans() { | ||
| 970 | Cube aux, cube, c[3]; | ||
| 971 | CubeArray epcp; | ||
| 972 | int eparr[12], eoarr[12]; | ||
| 973 | int cparr[8], coarr[8]; | ||
| 974 | int i; | ||
| 975 | bool b1, b2, b3; | ||
| 976 | uint16_t ui; | ||
| 977 | Move mi, move; | ||
| 978 | Trans r, m; | ||
| 979 | |||
| 980 | /* Compute sources */ | ||
| 981 | for (i = 0; i < NTRANS; i++) { | ||
| 982 | if (i == mirror) | ||
| 983 | cube = (Cube){0}; | ||
| 984 | else | ||
| 985 | cube = apply_alg(rotation_algs[i], (Cube){0}); | ||
| 986 | |||
| 987 | epose_source[i] = edge_slice(edge_at(cube, FR)); | ||
| 988 | eposs_source[i] = edge_slice(edge_at(cube, UR)); | ||
| 989 | eposm_source[i] = edge_slice(edge_at(cube, UF)); | ||
| 990 | eofb_source[i] = center_at(cube, F_center)/2; | ||
| 991 | eorl_source[i] = center_at(cube, R_center)/2; | ||
| 992 | eoud_source[i] = center_at(cube, U_center)/2; | ||
| 993 | coud_source[i] = center_at(cube, U_center)/2; | ||
| 994 | cofb_source[i] = center_at(cube, F_center)/2; | ||
| 995 | corl_source[i] = center_at(cube, R_center)/2; | ||
| 996 | } | ||
| 997 | |||
| 998 | /* Compute rotation_niss array, necessary for rotate_via_compose */ | ||
| 999 | for (r = 0; r != mirror; r++) { | ||
| 1000 | concat(rotation_algs[r], rotation_algs[r], rotation_niss[r]); | ||
| 1001 | for (i = len(rotation_algs[r]); rotation_niss[r][i].m; i++) | ||
| 1002 | rotation_niss[r][i].inverse = true; | ||
| 1003 | } | ||
| 1004 | |||
| 1005 | if (read_rtables_file()) | ||
| 1006 | return; | ||
| 1007 | |||
| 1008 | fprintf(stderr, "rtables not found, generating them.\n"); | ||
| 1009 | |||
| 1010 | /* Initialize tables */ | ||
| 1011 | for (m = 0; m < NTRANS; m++) { | ||
| 1012 | if (m == mirror) { | ||
| 1013 | intarrcopy(ep_mirror, eparr, 12); | ||
| 1014 | intarrcopy(cp_mirror, cparr, 8); | ||
| 1015 | } else { | ||
| 1016 | epcp = (CubeArray){ .ep = eparr, .cp = cparr }; | ||
| 1017 | cube = apply_alg(rotation_algs[m], (Cube){0}); | ||
| 1018 | cube_to_arrays(cube, &epcp, pf_epcp); | ||
| 1019 | } | ||
| 1020 | |||
| 1021 | for (ui = 0; ui < factorial12/factorial8; ui++) { | ||
| 1022 | c[0] = admissible_ep((Cube){ .epose = ui }, pf_e); | ||
| 1023 | c[1] = admissible_ep((Cube){ .eposs = ui }, pf_s); | ||
| 1024 | c[2] = admissible_ep((Cube){ .eposm = ui }, pf_m); | ||
| 1025 | |||
| 1026 | cube = rotate_via_compose(m,c[epose_source[m]],pf_ep); | ||
| 1027 | epose_rtable[m][ui] = cube.epose; | ||
| 1028 | |||
| 1029 | cube = rotate_via_compose(m,c[eposs_source[m]],pf_ep); | ||
| 1030 | eposs_rtable[m][ui] = cube.eposs; | ||
| 1031 | |||
| 1032 | cube = rotate_via_compose(m,c[eposm_source[m]],pf_ep); | ||
| 1033 | eposm_rtable[m][ui] = cube.eposm; | ||
| 1034 | } | ||
| 1035 | for (ui = 0; ui < pow2to11; ui++ ) { | ||
| 1036 | int_to_sum_zero_array(ui, 2, 12, eoarr); | ||
| 1037 | apply_permutation(eparr, eoarr, 12); | ||
| 1038 | eo_rtable[m][ui] = digit_array_to_int(eoarr, 11, 2); | ||
| 1039 | } | ||
| 1040 | for (ui = 0; ui < pow3to7; ui++) { | ||
| 1041 | int_to_sum_zero_array(ui, 3, 8, coarr); | ||
| 1042 | apply_permutation(cparr, coarr, 8); | ||
| 1043 | co_rtable[m][ui] = digit_array_to_int(coarr, 7, 3); | ||
| 1044 | if (m == mirror) | ||
| 1045 | co_rtable[m][ui] = | ||
| 1046 | invert_digits(co_rtable[m][ui], 3, 7); | ||
| 1047 | } | ||
| 1048 | for (ui = 0; ui < factorial8; ui++) { | ||
| 1049 | cube = (Cube){ .cp = ui }; | ||
| 1050 | cube = rotate_via_compose(m, cube, pf_cp); | ||
| 1051 | cp_rtable[m][ui] = cube.cp; | ||
| 1052 | } | ||
| 1053 | for (ui = 0; ui < factorial6; ui++) { | ||
| 1054 | cube = (Cube){ .cpos = ui }; | ||
| 1055 | cube = rotate_via_compose(m, cube, pf_cpos); | ||
| 1056 | cpos_rtable[m][ui] = cube.cpos; | ||
| 1057 | } | ||
| 1058 | for (mi = 0; mi < NMOVES; mi++) { | ||
| 1059 | if (m == mirror) { | ||
| 1060 | b1 = (mi >= U && mi <= Bw3); | ||
| 1061 | b2 = (mi >= S && mi <= E3); | ||
| 1062 | b3 = (mi >= x && mi <= z3); | ||
| 1063 | if (b1 || b2 || b3) | ||
| 1064 | moves_rtable[m][mi] = | ||
| 1065 | inverse_move_aux[mi]; | ||
| 1066 | else | ||
| 1067 | moves_rtable[m][mi] = mi; | ||
| 1068 | |||
| 1069 | if ((mi-1)/3==(R-1)/3 || (mi-1)/3==(Rw-1)/3) | ||
| 1070 | moves_rtable[m][mi] += 3; | ||
| 1071 | if ((mi-1)/3==(L-1)/3 || (mi-1)/3==(L2-1)/3) | ||
| 1072 | moves_rtable[m][mi] -= 3; | ||
| 1073 | } else { | ||
| 1074 | aux = apply_trans(m, apply_move(mi,(Cube){0})); | ||
| 1075 | for (move = 0; move < NMOVES; move++) { | ||
| 1076 | cube = apply_move( | ||
| 1077 | inverse_move_aux[move], aux); | ||
| 1078 | if (is_solved(cube, false)) | ||
| 1079 | moves_rtable[m][mi] = move; | ||
| 1080 | } | ||
| 1081 | } | ||
| 1082 | } | ||
| 1083 | } | ||
| 1084 | |||
| 1085 | if (!write_rtables_file()) | ||
| 1086 | fprintf(stderr, "Error writing rtables\n"); | ||
| 1087 | } | ||
| 1088 | |||
| 1089 | static void | ||
| 1090 | int_to_digit_array(int a, int b, int n, int *r) | ||
| 1091 | { | ||
| 1092 | int i; | ||
| 1093 | |||
| 1094 | if (b <= 1) | ||
| 1095 | for (i = 0; i < n; i++) | ||
| 1096 | r[i] = 0; | ||
| 1097 | else | ||
| 1098 | for (i = 0; i < n; i++, a /= b) | ||
| 1099 | r[i] = a % b; | ||
| 1100 | } | ||
| 1101 | |||
| 1102 | static void | ||
| 1103 | int_to_sum_zero_array(int x, int b, int n, int *a) | ||
| 1104 | { | ||
| 1105 | int i, s = 0; | ||
| 1106 | |||
| 1107 | if (b <= 1) { | ||
| 1108 | for (i = 0; i < n; i++) | ||
| 1109 | a[i] = 0; | ||
| 1110 | } else { | ||
| 1111 | int_to_digit_array(x, b, n-1, a); | ||
| 1112 | for (i = 0; i < n - 1; i++) | ||
| 1113 | s = (s + a[i]) % b; | ||
| 1114 | a[n-1] = (b - s) % b; | ||
| 1115 | } | ||
| 1116 | } | ||
| 1117 | |||
| 1118 | static void | ||
| 1119 | intarrcopy(int *src, int *dst, int n) | ||
| 1120 | { | ||
| 1121 | int i; | ||
| 1122 | |||
| 1123 | for (i = 0; i < n; i++) | ||
| 1124 | dst[i] = src[i]; | ||
| 1125 | } | ||
| 1126 | |||
| 1127 | static int | ||
| 1128 | invert_digits(int a, int b, int n) | ||
| 1129 | { | ||
| 1130 | int i, *r = malloc(n * sizeof(int)); | ||
| 1131 | |||
| 1132 | int_to_digit_array(a, b, n, r); | ||
| 1133 | for (i = 0; i < n; i++) | ||
| 1134 | r[i] = (b-r[i]) % b; | ||
| 1135 | |||
| 1136 | return digit_array_to_int(r, n, b); | ||
| 1137 | } | ||
| 1138 | |||
| 1139 | static bool | ||
| 1140 | is_perm(int *a, int n) | ||
| 1141 | { | ||
| 1142 | int *aux = malloc(n * sizeof(int)); | ||
| 1143 | int i; | ||
| 1144 | |||
| 1145 | for (i = 0; i < n; i++) | ||
| 1146 | if (a[i] < 0 || a[i] >= n) | ||
| 1147 | return false; | ||
| 1148 | else | ||
| 1149 | aux[a[i]] = 1; | ||
| 1150 | |||
| 1151 | for (i = 0; i < n; i++) | ||
| 1152 | if (!aux[i]) | ||
| 1153 | return false; | ||
| 1154 | |||
| 1155 | free(aux); | ||
| 1156 | |||
| 1157 | return true; | ||
| 1158 | } | ||
| 1159 | |||
| 1160 | static bool | ||
| 1161 | is_subset(int *a, int n, int k) | ||
| 1162 | { | ||
| 1163 | int i, sum = 0; | ||
| 1164 | |||
| 1165 | for (i = 0; i < n; i++) | ||
| 1166 | sum += a[i] ? 1 : 0; | ||
| 1167 | |||
| 1168 | return sum == k; | ||
| 1169 | } | ||
| 1170 | |||
| 1171 | static Cube | ||
| 1172 | move_via_arrays(CubeArray arr, Cube c, PieceFilter f) | ||
| 1173 | { | ||
| 1174 | CubeArray arrc; | ||
| 1175 | Cube ret; | ||
| 1176 | |||
| 1177 | alloc_cubearray(&arrc, f); | ||
| 1178 | cube_to_arrays(c, &arrc, f); | ||
| 1179 | |||
| 1180 | if (f.epose || f.eposs || f.eposm) | ||
| 1181 | apply_permutation(arr.ep, arrc.ep, 12); | ||
| 1182 | |||
| 1183 | if (f.eofb) { | ||
| 1184 | apply_permutation(arr.ep, arrc.eofb, 12); | ||
| 1185 | sum_arrays_mod(arr.eofb, arrc.eofb, 12, 2); | ||
| 1186 | } | ||
| 1187 | |||
| 1188 | if (f.eorl) { | ||
| 1189 | apply_permutation(arr.ep, arrc.eorl, 12); | ||
| 1190 | sum_arrays_mod(arr.eorl, arrc.eorl, 12, 2); | ||
| 1191 | } | ||
| 1192 | |||
| 1193 | if (f.eoud) { | ||
| 1194 | apply_permutation(arr.ep, arrc.eoud, 12); | ||
| 1195 | sum_arrays_mod(arr.eoud, arrc.eoud, 12, 2); | ||
| 1196 | } | ||
| 1197 | |||
| 1198 | if (f.cp) | ||
| 1199 | apply_permutation(arr.cp, arrc.cp, 8); | ||
| 1200 | |||
| 1201 | if (f.coud) { | ||
| 1202 | apply_permutation(arr.cp, arrc.coud, 8); | ||
| 1203 | sum_arrays_mod(arr.coud, arrc.coud, 8, 3); | ||
| 1204 | } | ||
| 1205 | |||
| 1206 | if (f.corl) { | ||
| 1207 | apply_permutation(arr.cp, arrc.corl, 8); | ||
| 1208 | sum_arrays_mod(arr.corl, arrc.corl, 8, 3); | ||
| 1209 | } | ||
| 1210 | |||
| 1211 | if (f.cofb) { | ||
| 1212 | apply_permutation(arr.cp, arrc.cofb, 8); | ||
| 1213 | sum_arrays_mod(arr.cofb, arrc.cofb, 8, 3); | ||
| 1214 | } | ||
| 1215 | |||
| 1216 | if (f.cpos) | ||
| 1217 | apply_permutation(arr.cpos, arrc.cpos, 6); | ||
| 1218 | |||
| 1219 | ret = arrays_to_cube(arrc, f); | ||
| 1220 | free_cubearray(&arrc, f); | ||
| 1221 | |||
| 1222 | return ret; | ||
| 1223 | } | ||
| 1224 | |||
| 1225 | static Move * | ||
| 1226 | moveset_to_movelist(bool *moveset, Step step) | ||
| 1227 | { | ||
| 1228 | Cube c; | ||
| 1229 | int *a = malloc(NMOVES * sizeof(int)), b[NMOVES]; | ||
| 1230 | int na = 0, nb = 0; | ||
| 1231 | Move i; | ||
| 1232 | |||
| 1233 | if (moveset != NULL) { | ||
| 1234 | for (i = NULLMOVE+1; i < NMOVES; i++) { | ||
| 1235 | if (moveset[i]) { | ||
| 1236 | c = apply_move(i, (Cube){0}); | ||
| 1237 | if (step.f != NULL && step.f(c)) { | ||
| 1238 | a[na++] = i; | ||
| 1239 | } else { | ||
| 1240 | b[nb++] = i; | ||
| 1241 | } | ||
| 1242 | } | ||
| 1243 | } | ||
| 1244 | } | ||
| 1245 | |||
| 1246 | intarrcopy(b, a+na, nb); | ||
| 1247 | a[na+nb] = NULLMOVE; | ||
| 1248 | |||
| 1249 | return (Move *)a; | ||
| 1250 | } | ||
| 1251 | |||
| 1252 | static AlgList * | ||
| 1253 | new_alglist() | ||
| 1254 | { | ||
| 1255 | AlgList *ret = malloc(sizeof(AlgList)); | ||
| 1256 | |||
| 1257 | ret->len = 0; | ||
| 1258 | ret->first = NULL; | ||
| 1259 | ret->last = NULL; | ||
| 1260 | |||
| 1261 | return ret; | ||
| 1262 | } | ||
| 1263 | |||
| 1264 | static int | ||
| 1265 | perm_sign(int *a, int n) | ||
| 1266 | { | ||
| 1267 | int i, j, ret = 0; | ||
| 1268 | |||
| 1269 | if (!is_perm(a,n)) | ||
| 1270 | return -1; | ||
| 1271 | |||
| 1272 | for (i = 0; i < n; i++) | ||
| 1273 | for (j = i+1; j < n; j++) | ||
| 1274 | ret += (a[i] > a[j]) ? 1 : 0; | ||
| 1275 | |||
| 1276 | return ret % 2; | ||
| 1277 | } | ||
| 1278 | |||
| 1279 | static int | ||
| 1280 | perm_to_index(int *a, int n) | ||
| 1281 | { | ||
| 1282 | int i, j, c, ret = 0; | ||
| 1283 | |||
| 1284 | if (!is_perm(a, n)) | ||
| 1285 | return -1; | ||
| 1286 | |||
| 1287 | for (i = 0; i < n; i++) { | ||
| 1288 | c = 0; | ||
| 1289 | for (j = i+1; j < n; j++) | ||
| 1290 | c += (a[i] > a[j]) ? 1 : 0; | ||
| 1291 | ret += factorial(n-i-1) * c; | ||
| 1292 | } | ||
| 1293 | |||
| 1294 | return ret; | ||
| 1295 | } | ||
| 1296 | |||
| 1297 | static int | ||
| 1298 | powint(int a, int b) | ||
| 1299 | { | ||
| 1300 | if (b < 0) | ||
| 1301 | return 0; /* Truncate */ | ||
| 1302 | if (b == 0) | ||
| 1303 | return 1; | ||
| 1304 | |||
| 1305 | if (b % 2) | ||
| 1306 | return a * powint(a, b-1); | ||
| 1307 | else | ||
| 1308 | return powint(a*a, b/2); | ||
| 1309 | } | ||
| 1310 | |||
| 1311 | static bool | ||
| 1312 | read_rtables_file() | ||
| 1313 | { | ||
| 1314 | FILE *ttf; | ||
| 1315 | int b = sizeof(uint16_t); | ||
| 1316 | bool r = true; | ||
| 1317 | Move m; | ||
| 1318 | |||
| 1319 | if ((ttf = fopen("rtables", "rb")) != NULL) { | ||
| 1320 | for (m = 0; m < NTRANS; m++) { | ||
| 1321 | r = r && fread(epose_rtable[m],b,me[0],ttf) == me[0]; | ||
| 1322 | r = r && fread(eposs_rtable[m],b,me[1],ttf) == me[1]; | ||
| 1323 | r = r && fread(eposm_rtable[m],b,me[2],ttf) == me[2]; | ||
| 1324 | r = r && fread(eo_rtable[m],b,me[3],ttf) == me[3]; | ||
| 1325 | r = r && fread(cp_rtable[m],b,me[6],ttf) == me[6]; | ||
| 1326 | r = r && fread(co_rtable[m],b,me[7],ttf) == me[7]; | ||
| 1327 | r = r && fread(cpos_rtable[m],b,me[10],ttf) == me[10]; | ||
| 1328 | r = r && fread(moves_rtable[m],b,me[11],ttf) == me[11]; | ||
| 1329 | } | ||
| 1330 | fclose(ttf); | ||
| 1331 | return r; | ||
| 1332 | } else { | ||
| 1333 | return false; | ||
| 1334 | } | ||
| 1335 | } | ||
| 1336 | |||
| 1337 | static bool | ||
| 1338 | read_ttables_file() | ||
| 1339 | { | ||
| 1340 | FILE *ttf; | ||
| 1341 | int m, b = sizeof(uint16_t); | ||
| 1342 | bool r = true; | ||
| 1343 | |||
| 1344 | if ((ttf = fopen("ttables", "rb")) != NULL) { | ||
| 1345 | for (m = 0; m < NMOVES; m++) { | ||
| 1346 | r = r && fread(epose_ttable[m],b,me[0],ttf) == me[0]; | ||
| 1347 | r = r && fread(eposs_ttable[m],b,me[1],ttf) == me[1]; | ||
| 1348 | r = r && fread(eposm_ttable[m],b,me[2],ttf) == me[2]; | ||
| 1349 | r = r && fread(eofb_ttable[m],b,me[3],ttf) == me[3]; | ||
| 1350 | r = r && fread(eorl_ttable[m],b,me[4],ttf) == me[4]; | ||
| 1351 | r = r && fread(eoud_ttable[m],b,me[5],ttf) == me[5]; | ||
| 1352 | r = r && fread(cp_ttable[m],b,me[6],ttf) == me[6]; | ||
| 1353 | r = r && fread(coud_ttable[m],b,me[7],ttf) == me[7]; | ||
| 1354 | r = r && fread(corl_ttable[m],b,me[8],ttf) == me[8]; | ||
| 1355 | r = r && fread(cofb_ttable[m],b,me[9],ttf) == me[9]; | ||
| 1356 | r = r && fread(cpos_ttable[m],b,me[10],ttf) == me[10]; | ||
| 1357 | } | ||
| 1358 | fclose(ttf); | ||
| 1359 | return r; | ||
| 1360 | } else { | ||
| 1361 | return false; | ||
| 1362 | } | ||
| 1363 | } | ||
| 1364 | |||
| 1365 | static bool | ||
| 1366 | realloc_alg(Alg alg, int n) | ||
| 1367 | { | ||
| 1368 | if (n+1 >= BASEALGLEN) { | ||
| 1369 | if (reallocarray(alg, n+2, sizeof(NissMove)) == NULL) { | ||
| 1370 | fprintf(stderr, "Error reallocating alg\n"); | ||
| 1371 | return false; | ||
| 1372 | } | ||
| 1373 | } | ||
| 1374 | |||
| 1375 | return true; | ||
| 1376 | } | ||
| 1377 | |||
| 1378 | static Cube | ||
| 1379 | rotate_via_compose(Trans r, Cube c, PieceFilter f) | ||
| 1380 | { | ||
| 1381 | Cube ret; | ||
| 1382 | CubeArray ma = { | ||
| 1383 | .ep = ep_mirror, | ||
| 1384 | .eofb = zero12, | ||
| 1385 | .eorl = zero12, | ||
| 1386 | .eoud = zero12, | ||
| 1387 | .cp = cp_mirror, | ||
| 1388 | .coud = zero8, | ||
| 1389 | .corl = zero8, | ||
| 1390 | .cofb = zero8, | ||
| 1391 | .cpos = cpos_mirror | ||
| 1392 | }; | ||
| 1393 | |||
| 1394 | if (r != mirror) { | ||
| 1395 | ret = apply_alg_filtered(rotation_niss[r], c, f); | ||
| 1396 | } else { | ||
| 1397 | ret = move_via_arrays(ma, (Cube){0}, f); | ||
| 1398 | ret = compose_filtered(c, ret, f); | ||
| 1399 | ret = move_via_arrays(ma, ret, f); | ||
| 1400 | } | ||
| 1401 | |||
| 1402 | return ret; | ||
| 1403 | } | ||
| 1404 | |||
| 1405 | static void | ||
| 1406 | solve_dfs(Cube c, Step s, SolveOptions opts, DfsData dd) | ||
| 1407 | { | ||
| 1408 | DfsData newdd; | ||
| 1409 | Move move; | ||
| 1410 | NissMove nm; | ||
| 1411 | int i; | ||
| 1412 | bool found_many, prune, niss_makes_sense; | ||
| 1413 | |||
| 1414 | found_many = dd.sols->len >= opts.max_solutions; | ||
| 1415 | prune = (!opts.can_niss || dd.niss) && dd.m + s.f(c) > dd.d; | ||
| 1416 | if (found_many || prune) | ||
| 1417 | return; | ||
| 1418 | |||
| 1419 | if (!s.f(c)) { | ||
| 1420 | if (dd.m == dd.d) | ||
| 1421 | append_alg(dd.sols, dd.current_alg); | ||
| 1422 | return; | ||
| 1423 | } | ||
| 1424 | |||
| 1425 | for (i = 0; opts.sorted_moves[i] != NULLMOVE; i++) { | ||
| 1426 | move = opts.sorted_moves[i]; | ||
| 1427 | if (possible_next[dd.last2][dd.last1][move]) { | ||
| 1428 | nm = (NissMove){ .m = move, .inverse = dd.niss }; | ||
| 1429 | newdd = (DfsData) { | ||
| 1430 | .d = dd.d, | ||
| 1431 | .m = dd.m + 1, | ||
| 1432 | .niss = dd.niss, | ||
| 1433 | .last1 = move, | ||
| 1434 | .last2 = dd.last1, | ||
| 1435 | .sols = dd.sols, | ||
| 1436 | .current_alg = dd.current_alg, | ||
| 1437 | }; | ||
| 1438 | |||
| 1439 | append_move(dd.current_alg, nm); | ||
| 1440 | solve_dfs(apply_move(move, c), s, opts, newdd); | ||
| 1441 | remove_last_moves(dd.current_alg, 1); | ||
| 1442 | } | ||
| 1443 | } | ||
| 1444 | |||
| 1445 | niss_makes_sense = !dd.m || (s.f(apply_move(dd.last1, (Cube){0}))); | ||
| 1446 | if (opts.can_niss && !dd.niss && niss_makes_sense) { | ||
| 1447 | newdd = (DfsData) { | ||
| 1448 | .d = dd.d, | ||
| 1449 | .m = dd.m, | ||
| 1450 | .niss = true, | ||
| 1451 | .last1 = NULLMOVE, | ||
| 1452 | .last2 = NULLMOVE, | ||
| 1453 | .sols = dd.sols, | ||
| 1454 | .current_alg = dd.current_alg, | ||
| 1455 | }; | ||
| 1456 | solve_dfs(inverse_cube(c), s, opts, newdd); | ||
| 1457 | } | ||
| 1458 | } | ||
| 1459 | |||
| 1460 | static int | ||
| 1461 | subset_to_index(int *a, int n, int k) | ||
| 1462 | { | ||
| 1463 | int i, ret = 0; | ||
| 1464 | |||
| 1465 | if (!is_subset(a, n, k)) | ||
| 1466 | return binomial(n, k); | ||
| 1467 | |||
| 1468 | for (i = 0; i < n; i++) { | ||
| 1469 | if (k == n-i) | ||
| 1470 | return ret; | ||
| 1471 | if (a[i]) { | ||
| 1472 | ret += binomial(n-i-1, k); | ||
| 1473 | k--; | ||
| 1474 | } | ||
| 1475 | } | ||
| 1476 | |||
| 1477 | return ret; | ||
| 1478 | } | ||
| 1479 | |||
| 1480 | static void | ||
| 1481 | sum_arrays_mod(int *src, int *dst, int n, int m) | ||
| 1482 | { | ||
| 1483 | int i; | ||
| 1484 | |||
| 1485 | for (i = 0; i < n; i++) | ||
| 1486 | dst[i] = (m <= 0) ? 0 : (src[i] + dst[i]) % m; | ||
| 1487 | } | ||
| 1488 | |||
| 1489 | static void | ||
| 1490 | swap(int *a, int *b) | ||
| 1491 | { | ||
| 1492 | int aux; | ||
| 1493 | |||
| 1494 | aux = *a; | ||
| 1495 | *a = *b; | ||
| 1496 | *b = aux; | ||
| 1497 | } | ||
| 1498 | |||
| 1499 | static bool | ||
| 1500 | write_rtables_file() | ||
| 1501 | { | ||
| 1502 | FILE *ttf; | ||
| 1503 | bool r = true; | ||
| 1504 | int b = sizeof(uint16_t); | ||
| 1505 | Move m; | ||
| 1506 | |||
| 1507 | if ((ttf = fopen("rtables", "wb")) != NULL) { | ||
| 1508 | for (m = 0; m < NTRANS; m++) { | ||
| 1509 | r = r && fwrite(epose_rtable[m],b,me[0], ttf) == me[0]; | ||
| 1510 | r = r && fwrite(eposs_rtable[m],b,me[1], ttf) == me[1]; | ||
| 1511 | r = r && fwrite(eposm_rtable[m],b,me[2], ttf) == me[2]; | ||
| 1512 | r = r && fwrite(eo_rtable[m],b,me[3], ttf) == me[3]; | ||
| 1513 | r = r && fwrite(cp_rtable[m],b,me[6], ttf) == me[6]; | ||
| 1514 | r = r && fwrite(co_rtable[m],b,me[7], ttf) == me[7]; | ||
| 1515 | r = r && fwrite(cpos_rtable[m],b,me[10],ttf) == me[10]; | ||
| 1516 | r = r && fwrite(moves_rtable[m],b,me[11],ttf)== me[11]; | ||
| 1517 | } | ||
| 1518 | fclose(ttf); | ||
| 1519 | return r; | ||
| 1520 | } else { | ||
| 1521 | return false; | ||
| 1522 | } | ||
| 1523 | } | ||
| 1524 | |||
| 1525 | static bool | ||
| 1526 | write_ttables_file() | ||
| 1527 | { | ||
| 1528 | FILE *ttf; | ||
| 1529 | int m, b = sizeof(uint16_t);; | ||
| 1530 | bool r = true; | ||
| 1531 | |||
| 1532 | if ((ttf = fopen("ttables", "wb")) != NULL) { | ||
| 1533 | for (m = 0; m < NMOVES; m++) { | ||
| 1534 | r = r && fwrite(epose_ttable[m],b,me[0],ttf) == me[0]; | ||
| 1535 | r = r && fwrite(eposs_ttable[m],b,me[1],ttf) == me[1]; | ||
| 1536 | r = r && fwrite(eposm_ttable[m],b,me[2],ttf) == me[2]; | ||
| 1537 | r = r && fwrite(eofb_ttable[m],b,me[3],ttf) == me[3]; | ||
| 1538 | r = r && fwrite(eorl_ttable[m],b,me[4],ttf) == me[4]; | ||
| 1539 | r = r && fwrite(eoud_ttable[m],b,me[5],ttf) == me[5]; | ||
| 1540 | r = r && fwrite(cp_ttable[m],b,me[6],ttf) == me[6]; | ||
| 1541 | r = r && fwrite(coud_ttable[m],b,me[7],ttf) == me[7]; | ||
| 1542 | r = r && fwrite(corl_ttable[m],b,me[8],ttf) == me[8]; | ||
| 1543 | r = r && fwrite(cofb_ttable[m],b,me[9],ttf) == me[9]; | ||
| 1544 | r = r && fwrite(cpos_ttable[m],b,me[10],ttf) == me[10]; | ||
| 1545 | } | ||
| 1546 | fclose(ttf); | ||
| 1547 | return r; | ||
| 1548 | } else { | ||
| 1549 | return false; | ||
| 1550 | } | ||
| 1551 | } | ||
| 1552 | |||
| 1553 | /* Public functions implementation *******************************************/ | ||
| 1554 | |||
| 1555 | Cube | ||
| 1556 | apply_alg(Alg alg, Cube cube) | ||
| 1557 | { | ||
| 1558 | return apply_alg_filtered(alg, cube, pf_all); | ||
| 1559 | } | ||
| 1560 | |||
| 1561 | Cube | ||
| 1562 | apply_move(Move m, Cube cube) | ||
| 1563 | { | ||
| 1564 | Cube moved = {0}; | ||
| 1565 | |||
| 1566 | moved.epose = epose_ttable[m][cube.epose]; | ||
| 1567 | moved.eposs = eposs_ttable[m][cube.eposs]; | ||
| 1568 | moved.eposm = eposm_ttable[m][cube.eposm]; | ||
| 1569 | moved.eofb = eofb_ttable[m][cube.eofb]; | ||
| 1570 | moved.eorl = eorl_ttable[m][cube.eorl]; | ||
| 1571 | moved.eoud = eoud_ttable[m][cube.eoud]; | ||
| 1572 | moved.coud = coud_ttable[m][cube.coud]; | ||
| 1573 | moved.cofb = cofb_ttable[m][cube.cofb]; | ||
| 1574 | moved.corl = corl_ttable[m][cube.corl]; | ||
| 1575 | moved.cp = cp_ttable[m][cube.cp]; | ||
| 1576 | moved.cpos = cpos_ttable[m][cube.cpos]; | ||
| 1577 | |||
| 1578 | return moved; | ||
| 1579 | } | ||
| 1580 | |||
| 1581 | Cube | ||
| 1582 | apply_trans(Trans t, Cube cube) | ||
| 1583 | { | ||
| 1584 | Cube transformed = {0}; | ||
| 1585 | uint16_t aux_epos[3] = { cube.epose, cube.eposs, cube.eposm }; | ||
| 1586 | uint16_t aux_eo[3] = { cube.eoud, cube.eorl, cube.eofb }; | ||
| 1587 | uint16_t aux_co[3] = { cube.coud, cube.corl, cube.cofb }; | ||
| 1588 | |||
| 1589 | transformed.epose = epose_rtable[t][aux_epos[epose_source[t]]]; | ||
| 1590 | transformed.eposs = eposs_rtable[t][aux_epos[eposs_source[t]]]; | ||
| 1591 | transformed.eposm = eposm_rtable[t][aux_epos[eposm_source[t]]]; | ||
| 1592 | transformed.eofb = eo_rtable[t][aux_eo[eofb_source[t]]]; | ||
| 1593 | transformed.eorl = eo_rtable[t][aux_eo[eorl_source[t]]]; | ||
| 1594 | transformed.eoud = eo_rtable[t][aux_eo[eoud_source[t]]]; | ||
| 1595 | transformed.coud = co_rtable[t][aux_co[coud_source[t]]]; | ||
| 1596 | transformed.corl = co_rtable[t][aux_co[corl_source[t]]]; | ||
| 1597 | transformed.cofb = co_rtable[t][aux_co[cofb_source[t]]]; | ||
| 1598 | transformed.cp = cp_rtable[t][cube.cp]; | ||
| 1599 | transformed.cpos = cpos_rtable[t][cube.cpos]; | ||
| 1600 | |||
| 1601 | return transformed; | ||
| 1602 | } | ||
| 1603 | |||
| 1604 | /* TODO: this has to be changed using pre-computations */ | ||
| 1605 | bool | ||
| 1606 | block_solved(Cube cube, Block block) | ||
| 1607 | { | ||
| 1608 | CubeArray arr; | ||
| 1609 | int i; | ||
| 1610 | bool ret = true; | ||
| 1611 | |||
| 1612 | alloc_cubearray(&arr, pf_all); | ||
| 1613 | cube_to_arrays(cube, &arr, pf_all); | ||
| 1614 | |||
| 1615 | for (i = 0; i < 12; i++) | ||
| 1616 | ret = ret && !(block.edge[i] && (arr.ep[i] != i || arr.eofb[i])); | ||
| 1617 | for (i = 0; i < 8; i++) | ||
| 1618 | ret = ret && !(block.corner[i] && (arr.cp[i] != i || arr.coud[i])); | ||
| 1619 | for (i = 0; i < 6; i++) | ||
| 1620 | ret = ret && !(block.center[i] && arr.cpos[i] != i); | ||
| 1621 | |||
| 1622 | free_cubearray(&arr, pf_all); | ||
| 1623 | |||
| 1624 | return ret; | ||
| 1625 | } | ||
| 1626 | |||
| 1627 | Center | ||
| 1628 | center_at(Cube cube, Center c) | ||
| 1629 | { | ||
| 1630 | int ret; | ||
| 1631 | CubeArray arr; | ||
| 1632 | |||
| 1633 | alloc_cubearray(&arr, pf_cpos); | ||
| 1634 | cube_to_arrays(cube, &arr, pf_cpos); | ||
| 1635 | ret = arr.cpos[c]; | ||
| 1636 | free_cubearray(&arr, pf_cpos); | ||
| 1637 | |||
| 1638 | return ret; | ||
| 1639 | } | ||
| 1640 | |||
| 1641 | Cube | ||
| 1642 | compose(Cube c2, Cube c1) | ||
| 1643 | { | ||
| 1644 | return compose_filtered(c2, c1, pf_all); | ||
| 1645 | } | ||
| 1646 | |||
| 1647 | Corner | ||
| 1648 | corner_at(Cube cube, Corner c) | ||
| 1649 | { | ||
| 1650 | int ret; | ||
| 1651 | CubeArray arr; | ||
| 1652 | |||
| 1653 | alloc_cubearray(&arr, pf_cp); | ||
| 1654 | cube_to_arrays(cube, &arr, pf_cp); | ||
| 1655 | ret = arr.cp[c]; | ||
| 1656 | free_cubearray(&arr, pf_cp); | ||
| 1657 | |||
| 1658 | return ret; | ||
| 1659 | } | ||
| 1660 | |||
| 1661 | Edge | ||
| 1662 | edge_at(Cube cube, Edge e) | ||
| 1663 | { | ||
| 1664 | int ret; | ||
| 1665 | CubeArray arr; | ||
| 1666 | |||
| 1667 | alloc_cubearray(&arr, pf_ep); | ||
| 1668 | cube_to_arrays(cube, &arr, pf_ep); | ||
| 1669 | ret = arr.ep[e]; | ||
| 1670 | free_cubearray(&arr, pf_ep); | ||
| 1671 | |||
| 1672 | return ret; | ||
| 1673 | } | ||
| 1674 | |||
| 1675 | bool | ||
| 1676 | equal(Cube c1, Cube c2) | ||
| 1677 | { | ||
| 1678 | return c1.eofb == c2.eofb && | ||
| 1679 | c1.epose == c2.epose && | ||
| 1680 | c1.eposs == c2.eposs && | ||
| 1681 | c1.eposm == c2.eposm && | ||
| 1682 | c1.coud == c2.coud && | ||
| 1683 | c1.cp == c2.cp && | ||
| 1684 | c1.cpos == c2.cpos; | ||
| 1685 | } | ||
| 1686 | |||
| 1687 | Cube | ||
| 1688 | inverse_cube(Cube cube) | ||
| 1689 | { | ||
| 1690 | CubeArray arr, inv; | ||
| 1691 | Cube ret; | ||
| 1692 | int i; | ||
| 1693 | |||
| 1694 | alloc_cubearray(&arr, pf_all); | ||
| 1695 | alloc_cubearray(&inv, pf_all); | ||
| 1696 | |||
| 1697 | cube_to_arrays(cube, &arr, pf_all); | ||
| 1698 | |||
| 1699 | for (i = 0; i < 12; i++) { | ||
| 1700 | inv.ep[arr.ep[i]] = i; | ||
| 1701 | inv.eofb[arr.ep[i]] = arr.eofb[i]; | ||
| 1702 | inv.eorl[arr.ep[i]] = arr.eorl[i]; | ||
| 1703 | inv.eoud[arr.ep[i]] = arr.eoud[i]; | ||
| 1704 | } | ||
| 1705 | |||
| 1706 | for (i = 0; i < 8; i++) { | ||
| 1707 | inv.cp[arr.cp[i]] = i; | ||
| 1708 | inv.coud[arr.cp[i]] = (3 - arr.coud[i]) % 3; | ||
| 1709 | inv.corl[arr.cp[i]] = (3 - arr.corl[i]) % 3; | ||
| 1710 | inv.cofb[arr.cp[i]] = (3 - arr.cofb[i]) % 3; | ||
| 1711 | } | ||
| 1712 | |||
| 1713 | for (int i = 0; i < 6; i++) | ||
| 1714 | inv.cpos[arr.cpos[i]] = i; | ||
| 1715 | |||
| 1716 | ret = arrays_to_cube(inv, pf_all); | ||
| 1717 | free_cubearray(&arr, pf_all); | ||
| 1718 | free_cubearray(&inv, pf_all); | ||
| 1719 | |||
| 1720 | return ret; | ||
| 1721 | } | ||
| 1722 | |||
| 1723 | Move | ||
| 1724 | inverse_move(Move m) | ||
| 1725 | { | ||
| 1726 | return inverse_move_aux[m]; | ||
| 1727 | } | ||
| 1728 | |||
| 1729 | Trans | ||
| 1730 | inverse_trans(Trans t) | ||
| 1731 | { | ||
| 1732 | return inverse_trans_aux[t]; | ||
| 1733 | } | ||
| 1734 | |||
| 1735 | bool | ||
| 1736 | is_solved(Cube cube, bool reorient) | ||
| 1737 | { | ||
| 1738 | int i; | ||
| 1739 | |||
| 1740 | if (reorient) | ||
| 1741 | for (i = 0; i < NROTATIONS; i++) | ||
| 1742 | if (is_solved(apply_alg(rotation_algs[i], cube), false)) | ||
| 1743 | return true; | ||
| 1744 | |||
| 1745 | return equal(cube, (Cube){0}); | ||
| 1746 | } | ||
| 1747 | |||
| 1748 | int | ||
| 1749 | piece_orientation(Cube cube, int piece, char *orientation) | ||
| 1750 | { | ||
| 1751 | int arr[12], n, b; | ||
| 1752 | uint16_t x; | ||
| 1753 | |||
| 1754 | if (!strcmp(orientation, "eofb")) { | ||
| 1755 | x = cube.eofb; | ||
| 1756 | n = 12; | ||
| 1757 | b = 2; | ||
| 1758 | } else if (!strcmp(orientation, "eorl")) { | ||
| 1759 | x = cube.eorl; | ||
| 1760 | n = 12; | ||
| 1761 | b = 2; | ||
| 1762 | } else if (!strcmp(orientation, "eoud")) { | ||
| 1763 | x = cube.eoud; | ||
| 1764 | n = 12; | ||
| 1765 | b = 2; | ||
| 1766 | } else if (!strcmp(orientation, "coud")) { | ||
| 1767 | x = cube.coud; | ||
| 1768 | n = 8; | ||
| 1769 | b = 3; | ||
| 1770 | } else if (!strcmp(orientation, "corl")) { | ||
| 1771 | x = cube.corl; | ||
| 1772 | n = 8; | ||
| 1773 | b = 3; | ||
| 1774 | } else if (!strcmp(orientation, "cofb")) { | ||
| 1775 | x = cube.cofb; | ||
| 1776 | n = 8; | ||
| 1777 | b = 3; | ||
| 1778 | } else { | ||
| 1779 | return -1; | ||
| 1780 | } | ||
| 1781 | |||
| 1782 | int_to_sum_zero_array(x, b, n, arr); | ||
| 1783 | if (piece < n) | ||
| 1784 | return arr[piece]; | ||
| 1785 | |||
| 1786 | return -1; | ||
| 1787 | } | ||
| 1788 | |||
| 1789 | void | ||
| 1790 | print_cube(Cube cube) | ||
| 1791 | { | ||
| 1792 | CubeArray arr; | ||
| 1793 | |||
| 1794 | alloc_cubearray(&arr, pf_all); | ||
| 1795 | cube_to_arrays(cube, &arr, pf_all); | ||
| 1796 | |||
| 1797 | for (int i = 0; i < 12; i++) | ||
| 1798 | printf(" %s ", edge_string[arr.ep[i]]); | ||
| 1799 | printf("\n"); | ||
| 1800 | |||
| 1801 | for (int i = 0; i < 12; i++) | ||
| 1802 | printf(" %c ", arr.eofb[i] + '0'); | ||
| 1803 | printf("\n"); | ||
| 1804 | |||
| 1805 | for (int i = 0; i < 8; i++) | ||
| 1806 | printf("%s ", corner_string[arr.cp[i]]); | ||
| 1807 | printf("\n"); | ||
| 1808 | |||
| 1809 | for (int i = 0; i < 8; i++) | ||
| 1810 | printf(" %c ", arr.coud[i] + '0'); | ||
| 1811 | printf("\n"); | ||
| 1812 | |||
| 1813 | for (int i = 0; i < 6; i++) | ||
| 1814 | printf(" %s ", center_string[arr.cpos[i]]); | ||
| 1815 | printf("\n"); | ||
| 1816 | |||
| 1817 | free_cubearray(&arr, pf_all); | ||
| 1818 | } | ||
| 1819 | |||
| 1820 | void | ||
| 1821 | concat(Alg src1, Alg src2, Alg dest) | ||
| 1822 | { | ||
| 1823 | int n1 = len(src1), n2 = len(src2); | ||
| 1824 | |||
| 1825 | if (!realloc_alg(dest, n1+n2)) | ||
| 1826 | return; | ||
| 1827 | |||
| 1828 | copy_alg(src1, dest); | ||
| 1829 | copy_alg(src2, dest + n1); | ||
| 1830 | } | ||
| 1831 | |||
| 1832 | void | ||
| 1833 | copy_alg(Alg src, Alg dest) | ||
| 1834 | { | ||
| 1835 | int i, n = len(src); | ||
| 1836 | |||
| 1837 | if (!realloc_alg(dest, n)) | ||
| 1838 | return; | ||
| 1839 | |||
| 1840 | for (i = 0; src[i].m != NULLMOVE; i++) | ||
| 1841 | dest[i] = src[i]; | ||
| 1842 | dest[i].m = NULLMOVE; | ||
| 1843 | } | ||
| 1844 | |||
| 1845 | void | ||
| 1846 | invert_alg(Alg src, Alg dest) | ||
| 1847 | { | ||
| 1848 | Move m; | ||
| 1849 | int i, n = len(src); | ||
| 1850 | |||
| 1851 | if (!realloc_alg(dest, n)) | ||
| 1852 | return; | ||
| 1853 | |||
| 1854 | for (i = 0; i < n; i++) { | ||
| 1855 | m = inverse_move_aux[src[i].m]; | ||
| 1856 | dest[n-i-1] = (NissMove) { .m = m, .inverse = src[i].inverse }; | ||
| 1857 | } | ||
| 1858 | dest[n].m = NULLMOVE; | ||
| 1859 | } | ||
| 1860 | |||
| 1861 | int | ||
| 1862 | len(Alg alg) | ||
| 1863 | { | ||
| 1864 | int i; | ||
| 1865 | |||
| 1866 | for (i = 0; alg[i].m != NULLMOVE; i++); | ||
| 1867 | |||
| 1868 | return i; | ||
| 1869 | } | ||
| 1870 | |||
| 1871 | Alg | ||
| 1872 | new_alg(char *str) | ||
| 1873 | { | ||
| 1874 | Alg alg = malloc(BASEALGLEN * sizeof(NissMove)); | ||
| 1875 | int i; | ||
| 1876 | bool niss = false; | ||
| 1877 | Move j, m; | ||
| 1878 | NissMove nm; | ||
| 1879 | |||
| 1880 | alg[0] = (NissMove){ .m = NULLMOVE }; | ||
| 1881 | for (i = 0; str[i]; i++) { | ||
| 1882 | if (str[i] == ' ' || str[i] == '\t' || str[i] == '\n') | ||
| 1883 | continue; | ||
| 1884 | |||
| 1885 | if (str[i] == '(' && niss) { | ||
| 1886 | fprintf(stderr, "Error reading moves: nested ( )\n"); | ||
| 1887 | return alg; | ||
| 1888 | } | ||
| 1889 | |||
| 1890 | if (str[i] == ')' && !niss) { | ||
| 1891 | fprintf(stderr, "Error reading moves: unmatched )\n"); | ||
| 1892 | return alg; | ||
| 1893 | } | ||
| 1894 | |||
| 1895 | if (str[i] == '(' || str[i] == ')') { | ||
| 1896 | niss = !niss; | ||
| 1897 | continue; | ||
| 1898 | } | ||
| 1899 | |||
| 1900 | for (j = 0; j < NMOVES; j++) { | ||
| 1901 | if (str[i] == move_string[j][0]) { | ||
| 1902 | m = j; | ||
| 1903 | if (m <= B && str[i+1]=='w') { | ||
| 1904 | m += Uw - U; | ||
| 1905 | i++; | ||
| 1906 | } | ||
| 1907 | if (str[i+1]=='2') { | ||
| 1908 | m += 1; | ||
| 1909 | i++; | ||
| 1910 | } else if (str[i+1]=='\'' || str[i+1]=='3') { | ||
| 1911 | m += 2; | ||
| 1912 | i++; | ||
| 1913 | } | ||
| 1914 | nm = (NissMove){ .m = m, .inverse = niss }; | ||
| 1915 | append_move(alg, nm); | ||
| 1916 | break; | ||
| 1917 | } | ||
| 1918 | } | ||
| 1919 | } | ||
| 1920 | append_move(alg, (NissMove){ .m = NULLMOVE }); | ||
| 1921 | |||
| 1922 | return alg; | ||
| 1923 | } | ||
| 1924 | |||
| 1925 | void | ||
| 1926 | print_alg(Alg alg) | ||
| 1927 | { | ||
| 1928 | char fill[4]; | ||
| 1929 | int i; | ||
| 1930 | bool niss = false; | ||
| 1931 | |||
| 1932 | for (i = 0; alg[i].m != NULLMOVE; i++) { | ||
| 1933 | if (!niss && alg[i].inverse) | ||
| 1934 | strcpy(fill, i == 0 ? "(" : " ("); | ||
| 1935 | if (niss && !alg[i].inverse) | ||
| 1936 | strcpy(fill, ") "); | ||
| 1937 | if (niss == alg[i].inverse) | ||
| 1938 | strcpy(fill, i == 0 ? "" : " "); | ||
| 1939 | |||
| 1940 | printf("%s%s", fill, move_string[alg[i].m]); | ||
| 1941 | niss = alg[i].inverse; | ||
| 1942 | } | ||
| 1943 | printf("%s\n", niss ? ")" : ""); | ||
| 1944 | } | ||
| 1945 | |||
| 1946 | void | ||
| 1947 | remove_last_moves(Alg alg, int k) | ||
| 1948 | { | ||
| 1949 | int n = len(alg); | ||
| 1950 | int i = max(0, n-k); | ||
| 1951 | |||
| 1952 | alg[i].m = NULLMOVE; | ||
| 1953 | } | ||
| 1954 | |||
| 1955 | AlgList * | ||
| 1956 | solve(Cube cube, Step step, SolveOptions opts) | ||
| 1957 | { | ||
| 1958 | AlgList *sols = new_alglist(); | ||
| 1959 | AlgListNode *node; | ||
| 1960 | Cube c; | ||
| 1961 | DfsData dd; | ||
| 1962 | int i; | ||
| 1963 | |||
| 1964 | if (step.ready != NULL && !step.ready(cube)) | ||
| 1965 | return sols; | ||
| 1966 | |||
| 1967 | if (opts.sorted_moves == NULL) | ||
| 1968 | opts.sorted_moves = moveset_to_movelist(opts.moveset, step); | ||
| 1969 | |||
| 1970 | for (i = opts.min_moves; i <= opts.max_moves; i++) { | ||
| 1971 | if (sols->len && opts.optimal_only) | ||
| 1972 | break; | ||
| 1973 | |||
| 1974 | c = apply_trans(opts.pre_trans, cube); | ||
| 1975 | dd = (DfsData) { | ||
| 1976 | .d = i, | ||
| 1977 | .m = 0, | ||
| 1978 | .niss = false, | ||
| 1979 | .last1 = NULLMOVE, | ||
| 1980 | .last2 = NULLMOVE, | ||
| 1981 | .sols = sols, | ||
| 1982 | .current_alg = new_alg("") | ||
| 1983 | }; | ||
| 1984 | |||
| 1985 | solve_dfs(c, step, opts, dd); | ||
| 1986 | } | ||
| 1987 | |||
| 1988 | for (node = sols->first; node != NULL; node = node->next) | ||
| 1989 | transform_alg(inverse_trans_aux[opts.pre_trans], node->alg); | ||
| 1990 | |||
| 1991 | return sols; | ||
| 1992 | } | ||
| 1993 | |||
| 1994 | void | ||
| 1995 | transform_alg(Trans t, Alg alg) | ||
| 1996 | { | ||
| 1997 | int i; | ||
| 1998 | |||
| 1999 | for (i = 0; alg[i].m != NULLMOVE; i++) | ||
| 2000 | alg[i].m = moves_rtable[t][alg[i].m]; | ||
| 2001 | } | ||
| 2002 | |||
| 2003 | |||
| 2004 | void | ||
| 2005 | init() | ||
| 2006 | { | ||
| 2007 | init_moves(); | ||
| 2008 | init_auxtables(); | ||
| 2009 | init_trans(); | ||
| 2010 | } | ||
diff --git a/old/2021-06-02-cleanedup/cube.h b/old/2021-06-02-cleanedup/cube.h new file mode 100644 index 0000000..f1559a4 --- /dev/null +++ b/old/2021-06-02-cleanedup/cube.h | |||
| @@ -0,0 +1,179 @@ | |||
| 1 | #include <stdio.h> | ||
| 2 | #include <stdbool.h> | ||
| 3 | #include <stdint.h> | ||
| 4 | #include <stdlib.h> | ||
| 5 | #include <string.h> | ||
| 6 | |||
| 7 | /* Constants ****************************************************************/ | ||
| 8 | |||
| 9 | #define NMOVES (z3+1) | ||
| 10 | #define NTRANS (mirror+1) | ||
| 11 | #define NROTATIONS (NTRANS-1) | ||
| 12 | |||
| 13 | /* Typedefs *****************************************************************/ | ||
| 14 | |||
| 15 | typedef enum center Center; | ||
| 16 | typedef enum corner Corner; | ||
| 17 | typedef enum edge Edge; | ||
| 18 | typedef enum move Move; | ||
| 19 | typedef enum trans Trans; | ||
| 20 | |||
| 21 | typedef struct nissmove * Alg; | ||
| 22 | typedef struct alglist AlgList; | ||
| 23 | typedef struct alglistnode AlgListNode; | ||
| 24 | typedef struct block Block; | ||
| 25 | typedef struct cube Cube; | ||
| 26 | typedef struct nissmove NissMove; | ||
| 27 | typedef struct solveoptions SolveOptions; | ||
| 28 | typedef struct step Step; | ||
| 29 | |||
| 30 | /* Type specifications *******************************************************/ | ||
| 31 | |||
| 32 | enum | ||
| 33 | center | ||
| 34 | { | ||
| 35 | U_center, D_center, | ||
| 36 | R_center, L_center, | ||
| 37 | F_center, B_center | ||
| 38 | }; | ||
| 39 | |||
| 40 | enum | ||
| 41 | corner | ||
| 42 | { | ||
| 43 | UFR, UFL, UBL, UBR, | ||
| 44 | DFR, DFL, DBL, DBR | ||
| 45 | }; | ||
| 46 | |||
| 47 | enum | ||
| 48 | edge | ||
| 49 | { | ||
| 50 | UF, UL, UB, UR, | ||
| 51 | DF, DL, DB, DR, | ||
| 52 | FR, FL, BL, BR | ||
| 53 | }; | ||
| 54 | |||
| 55 | enum | ||
| 56 | move | ||
| 57 | { | ||
| 58 | NULLMOVE, | ||
| 59 | U, U2, U3, D, D2, D3, | ||
| 60 | R, R2, R3, L, L2, L3, | ||
| 61 | F, F2, F3, B, B2, B3, | ||
| 62 | Uw, Uw2, Uw3, Dw, Dw2, Dw3, | ||
| 63 | Rw, Rw2, Rw3, Lw, Lw2, Lw3, | ||
| 64 | Fw, Fw2, Fw3, Bw, Bw2, Bw3, | ||
| 65 | M, M2, M3, | ||
| 66 | S, S2, S3, | ||
| 67 | E, E2, E3, | ||
| 68 | x, x2, x3, | ||
| 69 | y, y2, y3, | ||
| 70 | z, z2, z3, | ||
| 71 | }; | ||
| 72 | |||
| 73 | enum | ||
| 74 | trans | ||
| 75 | { | ||
| 76 | uf, ur, ub, ul, | ||
| 77 | df, dr, db, dl, | ||
| 78 | rf, rd, rb, ru, | ||
| 79 | lf, ld, lb, lu, | ||
| 80 | fu, fr, fd, fl, | ||
| 81 | bu, br, bd, bl, | ||
| 82 | mirror, /* R|L */ | ||
| 83 | }; | ||
| 84 | |||
| 85 | struct | ||
| 86 | alglist | ||
| 87 | { | ||
| 88 | AlgListNode *first; | ||
| 89 | AlgListNode *last; | ||
| 90 | int len; | ||
| 91 | }; | ||
| 92 | |||
| 93 | struct | ||
| 94 | alglistnode | ||
| 95 | { | ||
| 96 | Alg alg; | ||
| 97 | AlgListNode *next; | ||
| 98 | }; | ||
| 99 | |||
| 100 | struct | ||
| 101 | block | ||
| 102 | { | ||
| 103 | bool edge[12]; | ||
| 104 | bool corner[8]; | ||
| 105 | bool center[6]; | ||
| 106 | }; | ||
| 107 | |||
| 108 | struct | ||
| 109 | cube | ||
| 110 | { | ||
| 111 | uint16_t epose; | ||
| 112 | uint16_t eposs; | ||
| 113 | uint16_t eposm; | ||
| 114 | uint16_t eofb; | ||
| 115 | uint16_t eorl; | ||
| 116 | uint16_t eoud; | ||
| 117 | uint16_t cp; | ||
| 118 | uint16_t coud; | ||
| 119 | uint16_t cofb; | ||
| 120 | uint16_t corl; | ||
| 121 | uint16_t cpos; | ||
| 122 | }; | ||
| 123 | |||
| 124 | struct | ||
| 125 | nissmove | ||
| 126 | { | ||
| 127 | Move m; | ||
| 128 | bool inverse; | ||
| 129 | }; | ||
| 130 | |||
| 131 | struct | ||
| 132 | solveoptions | ||
| 133 | { | ||
| 134 | int min_moves; | ||
| 135 | int max_moves; | ||
| 136 | int max_solutions; | ||
| 137 | bool optimal_only; | ||
| 138 | bool can_niss; | ||
| 139 | bool *moveset; | ||
| 140 | Move *sorted_moves; | ||
| 141 | Trans pre_trans; | ||
| 142 | }; | ||
| 143 | |||
| 144 | struct | ||
| 145 | step | ||
| 146 | { | ||
| 147 | int (*f)(Cube); | ||
| 148 | bool (*ready)(Cube); | ||
| 149 | }; | ||
| 150 | |||
| 151 | /* Public functions **********************************************************/ | ||
| 152 | |||
| 153 | Cube apply_alg(Alg alg, Cube cube); | ||
| 154 | Cube apply_move(Move m, Cube cube); | ||
| 155 | Cube apply_trans(Trans t, Cube cube); | ||
| 156 | bool block_solved(Cube cube, Block); | ||
| 157 | Center center_at(Cube cube, Center c); | ||
| 158 | Cube compose(Cube c2, Cube c1); /* Use c2 as an alg on c1 */ | ||
| 159 | Corner corner_at(Cube cube, Corner c); | ||
| 160 | Edge edge_at(Cube cube, Edge e); | ||
| 161 | bool equal(Cube c1, Cube c2); | ||
| 162 | Cube inverse_cube(Cube cube); | ||
| 163 | Move inverse_move(Move m); | ||
| 164 | Trans inverse_trans(Trans t); | ||
| 165 | bool is_solved(Cube cube, bool reorient); | ||
| 166 | int piece_orientation(Cube cube, int piece, char *orientation); | ||
| 167 | void print_cube(Cube cube); | ||
| 168 | AlgList * solve(Cube cube, Step step, SolveOptions opts); | ||
| 169 | |||
| 170 | void concat(Alg src1, Alg src2, Alg dest); | ||
| 171 | void copy_alg(Alg src, Alg dest); | ||
| 172 | void invert_alg(Alg src, Alg dest); | ||
| 173 | int len(Alg alg); | ||
| 174 | Alg new_alg(char *str); | ||
| 175 | void print_alg(Alg alg); | ||
| 176 | void remove_last_moves(Alg alg, int k); | ||
| 177 | void transform_alg(Trans t, Alg alg); | ||
| 178 | |||
| 179 | void init(); | ||
diff --git a/old/2021-06-02-cleanedup/main.c b/old/2021-06-02-cleanedup/main.c new file mode 100644 index 0000000..fca5e3c --- /dev/null +++ b/old/2021-06-02-cleanedup/main.c | |||
| @@ -0,0 +1,35 @@ | |||
| 1 | #include <stdio.h> | ||
| 2 | #include "cube.h" | ||
| 3 | #include "steps.h" | ||
| 4 | |||
| 5 | int main() { | ||
| 6 | Alg algo; | ||
| 7 | AlgList *sols; | ||
| 8 | Cube cube; | ||
| 9 | SolveOptions opts; | ||
| 10 | |||
| 11 | init(); | ||
| 12 | |||
| 13 | algo = new_alg("R U R' F"); | ||
| 14 | cube = apply_alg(algo, (Cube){0}); | ||
| 15 | |||
| 16 | print_cube(apply_trans(rd, cube)); | ||
| 17 | |||
| 18 | opts = (SolveOptions) { | ||
| 19 | .min_moves = 0, | ||
| 20 | .max_moves = 5, | ||
| 21 | .optimal_only = true, | ||
| 22 | .max_solutions = 3, | ||
| 23 | .can_niss = false, | ||
| 24 | .moveset = standard_moveset, | ||
| 25 | .pre_trans = fu | ||
| 26 | }; | ||
| 27 | sols = solve(cube, step_eofb, opts); | ||
| 28 | if (sols->len == 0) | ||
| 29 | fprintf(stderr, "No solution found\n"); | ||
| 30 | else | ||
| 31 | print_alg(sols->first->alg); | ||
| 32 | |||
| 33 | |||
| 34 | return 0; | ||
| 35 | } | ||
diff --git a/old/2021-06-02-cleanedup/steps.h b/old/2021-06-02-cleanedup/steps.h new file mode 100644 index 0000000..452b71c --- /dev/null +++ b/old/2021-06-02-cleanedup/steps.h | |||
| @@ -0,0 +1,22 @@ | |||
| 1 | /* Pre-conditions, i.e. "ready(cube)" functions ******************************/ | ||
| 2 | |||
| 3 | bool always_ready(Cube cube) { return true; } | ||
| 4 | |||
| 5 | /* Main functions, i.e. "f(cube)" ********************************************/ | ||
| 6 | |||
| 7 | int f_eofb(Cube cube) { return (cube.eofb != 0) ? 1 : 0; } | ||
| 8 | |||
| 9 | /* Steps *********************************************************************/ | ||
| 10 | |||
| 11 | Step step_eofb = { .f = f_eofb, .ready = always_ready }; | ||
| 12 | |||
| 13 | /* Movesets ******************************************************************/ | ||
| 14 | |||
| 15 | bool standard_moveset[NMOVES] = { | ||
| 16 | [U] = true, [U2] = true, [U3] = true, | ||
| 17 | [D] = true, [D2] = true, [D3] = true, | ||
| 18 | [R] = true, [R2] = true, [R3] = true, | ||
| 19 | [L] = true, [L2] = true, [L3] = true, | ||
| 20 | [F] = true, [F2] = true, [F3] = true, | ||
| 21 | [B] = true, [B2] = true, [B3] = true, | ||
| 22 | }; | ||
diff --git a/old/2021-06-14-oldalg/cube.c b/old/2021-06-14-oldalg/cube.c new file mode 100644 index 0000000..5409896 --- /dev/null +++ b/old/2021-06-14-oldalg/cube.c | |||
| @@ -0,0 +1,2849 @@ | |||
| 1 | #include "cube.h" | ||
| 2 | |||
| 3 | /* Constants and macros *****************************************************/ | ||
| 4 | |||
| 5 | #define POW2TO11 2048ULL | ||
| 6 | #define POW2TO12 4096ULL | ||
| 7 | #define POW3TO7 2187ULL | ||
| 8 | #define POW3TO8 6561ULL | ||
| 9 | #define FACTORIAL4 24ULL | ||
| 10 | #define FACTORIAL6 720ULL | ||
| 11 | #define FACTORIAL8 40320ULL | ||
| 12 | #define FACTORIAL12 479001600ULL | ||
| 13 | #define BINOM12ON4 495ULL | ||
| 14 | #define BINOM8ON4 70ULL | ||
| 15 | #define MIN(a,b) (((a) < (b)) ? (a) : (b)) | ||
| 16 | #define MAX(a,b) (((a) > (b)) ? (a) : (b)) | ||
| 17 | |||
| 18 | #define BASEALGLEN 50 | ||
| 19 | #define NMOVES (z3+1) | ||
| 20 | #define NTRANS (mirror+1) | ||
| 21 | #define NROTATIONS (NTRANS-1) | ||
| 22 | #define PTABLESIZE(n) ((n+1) / 2) | ||
| 23 | #define PTABLEVAL(tab,ind) (((ind)%2) ? (tab[(ind)/2] / 16) : \ | ||
| 24 | (tab[(ind)/2] % 16)) | ||
| 25 | |||
| 26 | |||
| 27 | /* Local functions **********************************************************/ | ||
| 28 | |||
| 29 | static Cube admissible_ep(Cube cube, PieceFilter f); | ||
| 30 | static void append_alg(AlgList *l, Alg *alg); | ||
| 31 | static void append_move(Alg *alg, Move m, bool inverse); | ||
| 32 | static Cube apply_alg_generic(Alg *alg, Cube c, PieceFilter f, bool a); | ||
| 33 | static void apply_permutation(int *perm, int *set, int n); | ||
| 34 | static Cube apply_move_cubearray(Move m, Cube cube, PieceFilter f); | ||
| 35 | static uint16_t array_ep_to_epos(int *ep, int *eps_solved); | ||
| 36 | static Cube arrays_to_cube(CubeArray *arr, PieceFilter f); | ||
| 37 | static Move base_move(Move m); | ||
| 38 | static int binomial(int n, int k); | ||
| 39 | static Cube compose_filtered(Cube c2, Cube c1, PieceFilter f); | ||
| 40 | static void cube_to_arrays(Cube cube, CubeArray *arr, PieceFilter f); | ||
| 41 | static int digit_array_to_int(int *a, int n, int b); | ||
| 42 | static int edge_slice(Edge e); /* E=0, S=1, M=2 */ | ||
| 43 | static int epos_dependent(int pos1, int pos2); | ||
| 44 | static uint16_t epos_from_arrays(int *epos, int *ep); | ||
| 45 | static void epos_to_partial_ep(uint16_t epos, int *ep, int *ss); | ||
| 46 | static int factorial(int n); | ||
| 47 | static void free_alglistnode(AlgListNode *aln); | ||
| 48 | static void free_cubearray(CubeArray *arr, PieceFilter f); | ||
| 49 | static void generate_ptable(PruneData *pd); | ||
| 50 | static void generate_ptable_dfs(Cube c, PruneData *pd, DfsData *dd); | ||
| 51 | static void index_to_perm(int p, int n, int *r); | ||
| 52 | static void index_to_subset(int s, int n, int k, int *r); | ||
| 53 | static void int_to_digit_array(int a, int b, int n, int *r); | ||
| 54 | static void int_to_sum_zero_array(int x, int b, int n, int *a); | ||
| 55 | static int invert_digits(int a, int b, int n); | ||
| 56 | static bool is_perm(int *a, int n); | ||
| 57 | static bool is_subset(int *a, int n, int k); | ||
| 58 | static Cube move_via_arrays(CubeArray *arr, Cube c, PieceFilter pf); | ||
| 59 | static void moveset_to_list(bool (*ms)(Move), int (*f)(Cube), Move *r); | ||
| 60 | static AlgList * new_alglist(); | ||
| 61 | static CubeArray * new_cubearray(Cube cube, PieceFilter f); | ||
| 62 | static int perm_sign(int *a, int n); | ||
| 63 | static int perm_to_index(int *a, int n); | ||
| 64 | static int powint(int a, int b); | ||
| 65 | static void ptable_set_reached(PruneData *pd, uint64_t ind); | ||
| 66 | static void ptable_update(PruneData *pd, uint64_t ind, int m); | ||
| 67 | static bool read_ptable_file(PruneData *pd); | ||
| 68 | static bool read_ttables_file(); | ||
| 69 | static bool read_mtables_file(); | ||
| 70 | static Cube rotate_via_compose(Trans r, Cube c, PieceFilter f); | ||
| 71 | static void solve_dfs(Cube c, Step s, SolveOptions *opts, DfsData *dd); | ||
| 72 | static int subset_to_index(int *a, int n, int k); | ||
| 73 | static void sum_arrays_mod(int *src, int *dst, int n, int m); | ||
| 74 | static void swap(int *a, int *b); | ||
| 75 | static bool write_ptable_file(PruneData *pd); | ||
| 76 | static bool write_ttables_file(); | ||
| 77 | static bool write_mtables_file(); | ||
| 78 | |||
| 79 | static void init_auxtables(); | ||
| 80 | static void init_environment(); | ||
| 81 | static void init_moves(); | ||
| 82 | static void init_moves_aux(); | ||
| 83 | static void init_steps(); | ||
| 84 | static void init_strings(); | ||
| 85 | static void init_trans(); | ||
| 86 | static void init_trans_aux(); | ||
| 87 | |||
| 88 | static bool moveset_HTM(Move m); | ||
| 89 | static bool moveset_URF(Move m); | ||
| 90 | |||
| 91 | /* Steps and related functions and data **************************************/ | ||
| 92 | |||
| 93 | Step eofb_HTM; | ||
| 94 | Step eorl_HTM; | ||
| 95 | Step eoud_HTM; | ||
| 96 | Step coud_HTM; | ||
| 97 | Step corl_HTM; | ||
| 98 | Step cofb_HTM; | ||
| 99 | Step coud_URF; | ||
| 100 | Step corl_URF; | ||
| 101 | Step cofb_URF; | ||
| 102 | Step corners_HTM; | ||
| 103 | Step corners_URF; | ||
| 104 | Step edges_HTM; | ||
| 105 | Step drud_HTM; | ||
| 106 | Step optimal_HTM; | ||
| 107 | |||
| 108 | PruneData pd_eofb_HTM; | ||
| 109 | PruneData pd_coud_HTM; | ||
| 110 | PruneData pd_corners_HTM; | ||
| 111 | PruneData pd_ep_HTM; | ||
| 112 | PruneData pd_drud_HTM; | ||
| 113 | |||
| 114 | static uint64_t index_eofb(Cube cube); | ||
| 115 | static uint64_t index_coud(Cube cube); | ||
| 116 | static uint64_t index_corners(Cube cube); | ||
| 117 | static uint64_t index_ep(Cube cube); | ||
| 118 | static uint64_t index_drud(Cube cube); | ||
| 119 | |||
| 120 | static int check_nothing(Cube cube); | ||
| 121 | static int check_eofb_HTM(Cube cube); | ||
| 122 | static int check_coud_HTM(Cube cube); | ||
| 123 | static int check_coud_URF(Cube cube); | ||
| 124 | static int check_corners_HTM(Cube cube); | ||
| 125 | static int check_corners_URF(Cube cube); | ||
| 126 | static int check_edges_HTM(Cube cube); | ||
| 127 | static int check_drud_HTM(Cube cube); | ||
| 128 | static int check_optimal_HTM(Cube cube); | ||
| 129 | |||
| 130 | /* All sorts of useful costants and tables **********************************/ | ||
| 131 | |||
| 132 | static char * tabledir; | ||
| 133 | |||
| 134 | static PieceFilter pf_all; | ||
| 135 | static PieceFilter pf_4val; | ||
| 136 | static PieceFilter pf_epcp; | ||
| 137 | static PieceFilter pf_cpos; | ||
| 138 | static PieceFilter pf_cp; | ||
| 139 | static PieceFilter pf_ep; | ||
| 140 | static PieceFilter pf_e; | ||
| 141 | static PieceFilter pf_s; | ||
| 142 | static PieceFilter pf_m; | ||
| 143 | static PieceFilter pf_eo; | ||
| 144 | static PieceFilter pf_co; | ||
| 145 | |||
| 146 | static int epe_solved[4]; | ||
| 147 | static int eps_solved[4]; | ||
| 148 | static int epm_solved[4]; | ||
| 149 | |||
| 150 | static char move_string[NMOVES][7]; | ||
| 151 | static char edge_string[12][7]; | ||
| 152 | static char corner_string[8][7]; | ||
| 153 | static char center_string[6][7]; | ||
| 154 | |||
| 155 | static bool commute[NMOVES][NMOVES]; | ||
| 156 | static bool possible_next[NMOVES][NMOVES][NMOVES]; | ||
| 157 | static Move inverse_move_aux[NMOVES]; | ||
| 158 | static Trans inverse_trans_aux[NTRANS]; | ||
| 159 | static int epos_dependent_aux[BINOM12ON4][BINOM12ON4]; | ||
| 160 | |||
| 161 | static uint16_t epose_ttable[NTRANS][FACTORIAL12/FACTORIAL8]; | ||
| 162 | static uint16_t eposs_ttable[NTRANS][FACTORIAL12/FACTORIAL8]; | ||
| 163 | static uint16_t eposm_ttable[NTRANS][FACTORIAL12/FACTORIAL8]; | ||
| 164 | static uint16_t eo_ttable[NTRANS][POW2TO11]; | ||
| 165 | static uint16_t cp_ttable[NTRANS][FACTORIAL8]; | ||
| 166 | static uint16_t co_ttable[NTRANS][POW3TO7]; | ||
| 167 | static uint16_t cpos_ttable[NTRANS][FACTORIAL6]; | ||
| 168 | static Move moves_ttable[NTRANS][NMOVES]; | ||
| 169 | |||
| 170 | static uint16_t epose_mtable[NMOVES][FACTORIAL12/FACTORIAL8]; | ||
| 171 | static uint16_t eposs_mtable[NMOVES][FACTORIAL12/FACTORIAL8]; | ||
| 172 | static uint16_t eposm_mtable[NMOVES][FACTORIAL12/FACTORIAL8]; | ||
| 173 | static uint16_t eofb_mtable[NMOVES][POW2TO11]; | ||
| 174 | static uint16_t eorl_mtable[NMOVES][POW2TO11]; | ||
| 175 | static uint16_t eoud_mtable[NMOVES][POW2TO11]; | ||
| 176 | static uint16_t cp_mtable[NMOVES][FACTORIAL8]; | ||
| 177 | static uint16_t coud_mtable[NMOVES][POW3TO7]; | ||
| 178 | static uint16_t cofb_mtable[NMOVES][POW3TO7]; | ||
| 179 | static uint16_t corl_mtable[NMOVES][POW3TO7]; | ||
| 180 | static uint16_t cpos_mtable[NMOVES][FACTORIAL6]; | ||
| 181 | |||
| 182 | static uint64_t me[12]; | ||
| 183 | |||
| 184 | static int edge_cycle[NMOVES][12]; | ||
| 185 | static int corner_cycle[NMOVES][8]; | ||
| 186 | static int center_cycle[NMOVES][6]; | ||
| 187 | static int eofb_flipped[NMOVES][12]; | ||
| 188 | static int eorl_flipped[NMOVES][12]; | ||
| 189 | static int eoud_flipped[NMOVES][12]; | ||
| 190 | static int coud_flipped[NMOVES][8]; | ||
| 191 | static int corl_flipped[NMOVES][8]; | ||
| 192 | static int cofb_flipped[NMOVES][8]; | ||
| 193 | static Alg * equiv_alg[NMOVES]; | ||
| 194 | |||
| 195 | static int epose_source[NTRANS]; /* 0=epose, 1=eposs, 2=eposm */ | ||
| 196 | static int eposs_source[NTRANS]; | ||
| 197 | static int eposm_source[NTRANS]; | ||
| 198 | static int eofb_source[NTRANS]; /* 0=eoud, 1=eorl, 2=eofb */ | ||
| 199 | static int eorl_source[NTRANS]; | ||
| 200 | static int eoud_source[NTRANS]; | ||
| 201 | static int coud_source[NTRANS]; /* 0=coud, 1=corl, 2=cofb */ | ||
| 202 | static int cofb_source[NTRANS]; | ||
| 203 | static int corl_source[NTRANS]; | ||
| 204 | static int ep_mirror[12]; | ||
| 205 | static int cp_mirror[8]; | ||
| 206 | static int cpos_mirror[6]; | ||
| 207 | static Alg * trans_algs[NROTATIONS]; | ||
| 208 | |||
| 209 | |||
| 210 | /* Local functions implementation ********************************************/ | ||
| 211 | |||
| 212 | static Cube | ||
| 213 | admissible_ep(Cube cube, PieceFilter f) | ||
| 214 | { | ||
| 215 | CubeArray *arr = new_cubearray(cube, f); | ||
| 216 | Cube ret; | ||
| 217 | bool used[12] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; | ||
| 218 | int i, j; | ||
| 219 | |||
| 220 | for (i = 0; i < 12; i++) | ||
| 221 | if (arr->ep[i] != -1) | ||
| 222 | used[arr->ep[i]] = true; | ||
| 223 | |||
| 224 | for (i = 0, j = 0; i < 12; i++) { | ||
| 225 | for ( ; j < 11 && used[j]; j++); | ||
| 226 | if (arr->ep[i] == -1) | ||
| 227 | arr->ep[i] = j++; | ||
| 228 | } | ||
| 229 | |||
| 230 | ret = arrays_to_cube(arr, pf_ep); | ||
| 231 | free_cubearray(arr, f); | ||
| 232 | |||
| 233 | return ret; | ||
| 234 | } | ||
| 235 | |||
| 236 | static void | ||
| 237 | append_alg(AlgList *l, Alg *alg) | ||
| 238 | { | ||
| 239 | AlgListNode *node = malloc(sizeof(AlgListNode)); | ||
| 240 | AlgNode *i; | ||
| 241 | |||
| 242 | node->alg = new_alg(""); | ||
| 243 | for (i = alg->first; i != NULL; i = i->next) | ||
| 244 | append_move(node->alg, i->m, i->inverse); | ||
| 245 | node->next = NULL; | ||
| 246 | |||
| 247 | if (++l->len == 1) | ||
| 248 | l->first = node; | ||
| 249 | else | ||
| 250 | l->last->next = node; | ||
| 251 | l->last = node; | ||
| 252 | } | ||
| 253 | |||
| 254 | static void | ||
| 255 | append_move(Alg *alg, Move m, bool inverse) | ||
| 256 | { | ||
| 257 | AlgNode *node = malloc(sizeof(AlgNode)); | ||
| 258 | |||
| 259 | node->m = m; | ||
| 260 | node->inverse = inverse; | ||
| 261 | node->next = NULL; | ||
| 262 | node->prev = alg->last; | ||
| 263 | |||
| 264 | if (++alg->len == 1) | ||
| 265 | alg->first = node; | ||
| 266 | else | ||
| 267 | alg->last->next = node; | ||
| 268 | alg->last = node; | ||
| 269 | } | ||
| 270 | |||
| 271 | static Cube | ||
| 272 | apply_alg_generic(Alg *alg, Cube c, PieceFilter f, bool a) | ||
| 273 | { | ||
| 274 | Cube ret = {0}; | ||
| 275 | AlgNode *i; | ||
| 276 | |||
| 277 | for (i = alg->first; i != NULL; i = i->next) | ||
| 278 | if (i->inverse) | ||
| 279 | ret = a ? apply_move(i->m, ret) : | ||
| 280 | apply_move_cubearray(i->m, ret, f); | ||
| 281 | |||
| 282 | ret = compose_filtered(c, inverse_cube(ret), f); | ||
| 283 | |||
| 284 | for (i = alg->first; i != NULL; i = i->next) | ||
| 285 | if (!i->inverse) | ||
| 286 | ret = a ? apply_move(i->m, ret) : | ||
| 287 | apply_move_cubearray(i->m, ret, f); | ||
| 288 | |||
| 289 | return ret; | ||
| 290 | } | ||
| 291 | |||
| 292 | static void | ||
| 293 | apply_permutation(int *perm, int *set, int n) | ||
| 294 | { | ||
| 295 | int *aux = malloc(n * sizeof(int)); | ||
| 296 | int i; | ||
| 297 | |||
| 298 | if (!is_perm(perm, n)) | ||
| 299 | return; | ||
| 300 | |||
| 301 | for (i = 0; i < n; i++) | ||
| 302 | aux[i] = set[perm[i]]; | ||
| 303 | |||
| 304 | memcpy(set, aux, n * sizeof(int)); | ||
| 305 | free(aux); | ||
| 306 | } | ||
| 307 | |||
| 308 | static Cube | ||
| 309 | apply_move_cubearray(Move m, Cube cube, PieceFilter f) | ||
| 310 | { | ||
| 311 | CubeArray m_arr = { | ||
| 312 | edge_cycle[m], | ||
| 313 | eofb_flipped[m], | ||
| 314 | eorl_flipped[m], | ||
| 315 | eoud_flipped[m], | ||
| 316 | corner_cycle[m], | ||
| 317 | coud_flipped[m], | ||
| 318 | corl_flipped[m], | ||
| 319 | cofb_flipped[m], | ||
| 320 | center_cycle[m] | ||
| 321 | }; | ||
| 322 | |||
| 323 | return move_via_arrays(&m_arr, cube, f); | ||
| 324 | } | ||
| 325 | |||
| 326 | static uint16_t | ||
| 327 | array_ep_to_epos(int *ep, int *ss) | ||
| 328 | { | ||
| 329 | int epos[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; | ||
| 330 | int eps[4]; | ||
| 331 | int i, j, is; | ||
| 332 | |||
| 333 | for (i = 0, is = 0; i < 12; i++) { | ||
| 334 | for (j = 0; j < 4; j++) { | ||
| 335 | if (ep[i] == ss[j]) { | ||
| 336 | eps[is++] = j; | ||
| 337 | epos[i] = 1; | ||
| 338 | } | ||
| 339 | } | ||
| 340 | } | ||
| 341 | |||
| 342 | for (i = 0; i < 4; i++) | ||
| 343 | swap(&epos[ss[i]], &epos[i+8]); | ||
| 344 | |||
| 345 | return epos_from_arrays(epos, eps); | ||
| 346 | } | ||
| 347 | |||
| 348 | static Cube | ||
| 349 | arrays_to_cube(CubeArray *arr, PieceFilter f) | ||
| 350 | { | ||
| 351 | Cube ret = {0}; | ||
| 352 | |||
| 353 | if (f.epose) | ||
| 354 | ret.epose = array_ep_to_epos(arr->ep, epe_solved); | ||
| 355 | if (f.eposs) | ||
| 356 | ret.eposs = array_ep_to_epos(arr->ep, eps_solved); | ||
| 357 | if (f.eposm) | ||
| 358 | ret.eposm = array_ep_to_epos(arr->ep, epm_solved); | ||
| 359 | if (f.eofb) | ||
| 360 | ret.eofb = digit_array_to_int(arr->eofb, 11, 2); | ||
| 361 | if (f.eorl) | ||
| 362 | ret.eorl = digit_array_to_int(arr->eorl, 11, 2); | ||
| 363 | if (f.eoud) | ||
| 364 | ret.eoud = digit_array_to_int(arr->eoud, 11, 2); | ||
| 365 | if (f.cp) | ||
| 366 | ret.cp = perm_to_index(arr->cp, 8); | ||
| 367 | if (f.coud) | ||
| 368 | ret.coud = digit_array_to_int(arr->coud, 7, 3); | ||
| 369 | if (f.corl) | ||
| 370 | ret.corl = digit_array_to_int(arr->corl, 7, 3); | ||
| 371 | if (f.cofb) | ||
| 372 | ret.cofb = digit_array_to_int(arr->cofb, 7, 3); | ||
| 373 | if (f.cpos) | ||
| 374 | ret.cpos = perm_to_index(arr->cpos, 6); | ||
| 375 | |||
| 376 | return ret; | ||
| 377 | } | ||
| 378 | |||
| 379 | static Move | ||
| 380 | base_move(Move m) | ||
| 381 | { | ||
| 382 | if (m == NULLMOVE) | ||
| 383 | return NULLMOVE; | ||
| 384 | else | ||
| 385 | return m - (m-1)%3; | ||
| 386 | } | ||
| 387 | |||
| 388 | static int | ||
| 389 | binomial(int n, int k) | ||
| 390 | { | ||
| 391 | if (n < 0 || k < 0 || k > n) | ||
| 392 | return 0; | ||
| 393 | |||
| 394 | return factorial(n) / (factorial(k) * factorial(n-k)); | ||
| 395 | } | ||
| 396 | |||
| 397 | static Cube | ||
| 398 | compose_filtered(Cube c2, Cube c1, PieceFilter f) | ||
| 399 | { | ||
| 400 | CubeArray *arr = new_cubearray(c2, f); | ||
| 401 | Cube ret; | ||
| 402 | |||
| 403 | ret = move_via_arrays(arr, c1, f); | ||
| 404 | free_cubearray(arr, f); | ||
| 405 | |||
| 406 | return ret; | ||
| 407 | } | ||
| 408 | |||
| 409 | static void | ||
| 410 | cube_to_arrays(Cube cube, CubeArray *arr, PieceFilter f) | ||
| 411 | { | ||
| 412 | int i; | ||
| 413 | |||
| 414 | if (f.epose || f.eposs || f.eposm) | ||
| 415 | for (i = 0; i < 12; i++) | ||
| 416 | arr->ep[i] = -1; | ||
| 417 | |||
| 418 | if (f.epose) | ||
| 419 | epos_to_partial_ep(cube.epose, arr->ep, epe_solved); | ||
| 420 | if (f.eposs) | ||
| 421 | epos_to_partial_ep(cube.eposs, arr->ep, eps_solved); | ||
| 422 | if (f.eposm) | ||
| 423 | epos_to_partial_ep(cube.eposm, arr->ep, epm_solved); | ||
| 424 | if (f.eofb) | ||
| 425 | int_to_sum_zero_array(cube.eofb, 2, 12, arr->eofb); | ||
| 426 | if (f.eorl) | ||
| 427 | int_to_sum_zero_array(cube.eorl, 2, 12, arr->eorl); | ||
| 428 | if (f.eoud) | ||
| 429 | int_to_sum_zero_array(cube.eoud, 2, 12, arr->eoud); | ||
| 430 | if (f.cp) | ||
| 431 | index_to_perm(cube.cp, 8, arr->cp); | ||
| 432 | if (f.coud) | ||
| 433 | int_to_sum_zero_array(cube.coud, 3, 8, arr->coud); | ||
| 434 | if (f.corl) | ||
| 435 | int_to_sum_zero_array(cube.corl, 3, 8, arr->corl); | ||
| 436 | if (f.cofb) | ||
| 437 | int_to_sum_zero_array(cube.cofb, 3, 8, arr->cofb); | ||
| 438 | if (f.cpos) | ||
| 439 | index_to_perm(cube.cpos, 6, arr->cpos); | ||
| 440 | } | ||
| 441 | |||
| 442 | static int | ||
| 443 | digit_array_to_int(int *a, int n, int b) | ||
| 444 | { | ||
| 445 | int i, ret = 0, p = 1; | ||
| 446 | |||
| 447 | for (i = 0; i < n; i++, p *= b) | ||
| 448 | ret += a[i] * p; | ||
| 449 | |||
| 450 | return ret; | ||
| 451 | } | ||
| 452 | |||
| 453 | static int | ||
| 454 | edge_slice(Edge e) { | ||
| 455 | if (e < 0 || e > 11) | ||
| 456 | return -1; | ||
| 457 | |||
| 458 | if (e == FR || e == FL || e == BL || e == BR) | ||
| 459 | return 0; | ||
| 460 | if (e == UR || e == UL || e == DR || e == DL) | ||
| 461 | return 1; | ||
| 462 | |||
| 463 | return 2; | ||
| 464 | } | ||
| 465 | |||
| 466 | static int | ||
| 467 | epos_dependent(int poss, int pose) | ||
| 468 | { | ||
| 469 | int ep[12] = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}; | ||
| 470 | int ep8[8] = {0, 0, 0, 0, 0, 0, 0, 0}; | ||
| 471 | int i, j; | ||
| 472 | |||
| 473 | epos_to_partial_ep(poss*FACTORIAL4, ep, eps_solved); | ||
| 474 | epos_to_partial_ep(pose*FACTORIAL4, ep, epe_solved); | ||
| 475 | |||
| 476 | for (i = 0, j = 0; i < 12; i++) | ||
| 477 | if (edge_slice(ep[i]) != 1) | ||
| 478 | ep8[j++] = (edge_slice(ep[i]) == 0) ? 1 : 0; | ||
| 479 | |||
| 480 | return subset_to_index(ep8, 8, 4); | ||
| 481 | } | ||
| 482 | |||
| 483 | static uint16_t | ||
| 484 | epos_from_arrays(int *epos, int *ep) | ||
| 485 | { | ||
| 486 | return FACTORIAL4 * subset_to_index(epos,12,4) + perm_to_index(ep,4); | ||
| 487 | } | ||
| 488 | |||
| 489 | static void | ||
| 490 | epos_to_partial_ep(uint16_t epos, int *ep, int *ss) | ||
| 491 | { | ||
| 492 | int i, is, eposs[12], eps[4]; | ||
| 493 | |||
| 494 | index_to_perm(epos % FACTORIAL4, 4, eps); | ||
| 495 | index_to_subset(epos / FACTORIAL4, 12, 4, eposs); | ||
| 496 | |||
| 497 | for (i = 0; i < 4; i++) | ||
| 498 | swap(&eposs[ss[i]], &eposs[i+8]); | ||
| 499 | |||
| 500 | for (i = 0, is = 0; i < 12; i++) | ||
| 501 | if (eposs[i]) | ||
| 502 | ep[i] = ss[eps[is++]]; | ||
| 503 | } | ||
| 504 | |||
| 505 | static int | ||
| 506 | factorial(int n) | ||
| 507 | { | ||
| 508 | int i, ret = 1; | ||
| 509 | |||
| 510 | if (n < 0) | ||
| 511 | return 0; | ||
| 512 | |||
| 513 | for (i = 1; i <= n; i++) | ||
| 514 | ret *= i; | ||
| 515 | |||
| 516 | return ret; | ||
| 517 | } | ||
| 518 | |||
| 519 | void | ||
| 520 | free_alg(Alg *alg) | ||
| 521 | { | ||
| 522 | AlgNode *aux, *i = alg->first; | ||
| 523 | |||
| 524 | while (i != NULL) { | ||
| 525 | aux = i->next; | ||
| 526 | free(i); | ||
| 527 | i = aux; | ||
| 528 | } | ||
| 529 | free(alg); | ||
| 530 | } | ||
| 531 | |||
| 532 | void | ||
| 533 | free_alglist(AlgList *l) | ||
| 534 | { | ||
| 535 | AlgListNode *aux, *i = l->first; | ||
| 536 | |||
| 537 | while (i != NULL) { | ||
| 538 | aux = i->next; | ||
| 539 | free_alglistnode(i); | ||
| 540 | i = aux; | ||
| 541 | } | ||
| 542 | free(l); | ||
| 543 | } | ||
| 544 | |||
| 545 | void | ||
| 546 | free_alglistnode(AlgListNode *aln) | ||
| 547 | { | ||
| 548 | free_alg(aln->alg); | ||
| 549 | free(aln); | ||
| 550 | } | ||
| 551 | |||
| 552 | static void | ||
| 553 | free_cubearray(CubeArray *arr, PieceFilter f) | ||
| 554 | { | ||
| 555 | if (f.epose || f.eposs || f.eposm) | ||
| 556 | free(arr->ep); | ||
| 557 | if (f.eofb) | ||
| 558 | free(arr->eofb); | ||
| 559 | if (f.eorl) | ||
| 560 | free(arr->eorl); | ||
| 561 | if (f.eoud) | ||
| 562 | free(arr->eoud); | ||
| 563 | if (f.cp) | ||
| 564 | free(arr->cp); | ||
| 565 | if (f.coud) | ||
| 566 | free(arr->coud); | ||
| 567 | if (f.corl) | ||
| 568 | free(arr->corl); | ||
| 569 | if (f.cofb) | ||
| 570 | free(arr->cofb); | ||
| 571 | if (f.cpos) | ||
| 572 | free(arr->cpos); | ||
| 573 | |||
| 574 | free(arr); | ||
| 575 | } | ||
| 576 | |||
| 577 | static void | ||
| 578 | generate_ptable(PruneData *pd) | ||
| 579 | { | ||
| 580 | uint64_t j; | ||
| 581 | DfsData dd; | ||
| 582 | |||
| 583 | if (pd->generated) | ||
| 584 | return; | ||
| 585 | |||
| 586 | pd->ptable = malloc(PTABLESIZE(pd->size) * sizeof(uint8_t)); | ||
| 587 | |||
| 588 | if (read_ptable_file(pd)) { | ||
| 589 | pd->generated = true; | ||
| 590 | return; | ||
| 591 | } | ||
| 592 | |||
| 593 | fprintf(stderr, "Cannot load %s, generating it\n", pd->filename); | ||
| 594 | |||
| 595 | dd.m = 0; | ||
| 596 | dd.last1 = NULLMOVE; | ||
| 597 | dd.last2 = NULLMOVE; | ||
| 598 | |||
| 599 | /* We use 4 bits per value, so any distance >= 15 is set to 15 */ | ||
| 600 | for (j = 0; j < pd->size; j++) | ||
| 601 | ptable_update(pd, j, 15); | ||
| 602 | |||
| 603 | moveset_to_list(pd->moveset, NULL, dd.sorted_moves); | ||
| 604 | |||
| 605 | pd->reached = malloc(PTABLESIZE(pd->size) * sizeof(uint8_t)); | ||
| 606 | for (dd.d = 0, pd->n = 0; dd.d < 15 && pd->n < pd->size; dd.d++) { | ||
| 607 | memset(pd->reached, 0, PTABLESIZE(pd->size)*sizeof(uint8_t)); | ||
| 608 | generate_ptable_dfs((Cube){0}, pd, &dd); | ||
| 609 | fprintf(stderr, "Depth %d completed, generated %lu/%lu\n", | ||
| 610 | dd.d, pd->n, pd->size); | ||
| 611 | } | ||
| 612 | |||
| 613 | if (!write_ptable_file(pd)) | ||
| 614 | fprintf(stderr, "Error writing ptable file\n"); | ||
| 615 | |||
| 616 | pd->generated = true; | ||
| 617 | free(pd->reached); | ||
| 618 | } | ||
| 619 | |||
| 620 | static void | ||
| 621 | generate_ptable_dfs(Cube c, PruneData *pd, DfsData *dd) | ||
| 622 | { | ||
| 623 | uint64_t ind = pd->index(c); | ||
| 624 | int oldval = PTABLEVAL(pd->ptable, ind); | ||
| 625 | Move i, move, l1 = dd->last1, l2 = dd->last2; | ||
| 626 | |||
| 627 | if (oldval < dd->m || PTABLEVAL(pd->reached, ind) || pd->n == pd->size) | ||
| 628 | return; | ||
| 629 | |||
| 630 | ptable_set_reached(pd, ind); | ||
| 631 | |||
| 632 | if (dd->m == dd->d) { | ||
| 633 | if (dd->m < oldval) | ||
| 634 | ptable_update(pd, ind, dd->m); | ||
| 635 | return; | ||
| 636 | } | ||
| 637 | |||
| 638 | dd->m++; | ||
| 639 | dd->last2 = dd->last1; | ||
| 640 | |||
| 641 | for (i = 0; dd->sorted_moves[i] != NULLMOVE; i++) { | ||
| 642 | move = dd->sorted_moves[i]; | ||
| 643 | if (possible_next[l2][l1][move]) { | ||
| 644 | dd->last1 = move; | ||
| 645 | generate_ptable_dfs(apply_move(move, c), pd, dd); | ||
| 646 | } | ||
| 647 | } | ||
| 648 | |||
| 649 | dd->m--; | ||
| 650 | dd->last1 = l1; | ||
| 651 | dd->last2 = l2; | ||
| 652 | } | ||
| 653 | |||
| 654 | static void | ||
| 655 | index_to_perm(int p, int n, int *r) | ||
| 656 | { | ||
| 657 | int *a = malloc(n * sizeof(int)); | ||
| 658 | int i, j, c; | ||
| 659 | |||
| 660 | for (i = 0; i < n; i++) | ||
| 661 | a[i] = 0; | ||
| 662 | |||
| 663 | if (p < 0 || p >= factorial(n)) | ||
| 664 | for (i = 0; i < n; i++) | ||
| 665 | r[i] = -1; | ||
| 666 | |||
| 667 | for (i = 0; i < n; i++) { | ||
| 668 | c = 0; | ||
| 669 | j = 0; | ||
| 670 | while (c <= p / factorial(n-i-1)) | ||
| 671 | c += a[j++] ? 0 : 1; | ||
| 672 | r[i] = j-1; | ||
| 673 | a[j-1] = 1; | ||
| 674 | p %= factorial(n-i-1); | ||
| 675 | } | ||
| 676 | |||
| 677 | free(a); | ||
| 678 | } | ||
| 679 | |||
| 680 | static void | ||
| 681 | index_to_subset(int s, int n, int k, int *r) | ||
| 682 | { | ||
| 683 | int i, j, v; | ||
| 684 | |||
| 685 | if (s < 0 || s >= binomial(n, k)) { | ||
| 686 | for (i = 0; i < n; i++) | ||
| 687 | r[i] = -1; | ||
| 688 | return; | ||
| 689 | } | ||
| 690 | |||
| 691 | for (i = 0; i < n; i++) { | ||
| 692 | if (k == n-i) { | ||
| 693 | for (j = i; j < n; j++) | ||
| 694 | r[j] = 1; | ||
| 695 | return; | ||
| 696 | } | ||
| 697 | |||
| 698 | if (k == 0) { | ||
| 699 | for (j = i; j < n; j++) | ||
| 700 | r[j] = 0; | ||
| 701 | return; | ||
| 702 | } | ||
| 703 | |||
| 704 | v = binomial(n-i-1, k); | ||
| 705 | if (s >= v) { | ||
| 706 | r[i] = 1; | ||
| 707 | k--; | ||
| 708 | s -= v; | ||
| 709 | } else { | ||
| 710 | r[i] = 0; | ||
| 711 | } | ||
| 712 | } | ||
| 713 | } | ||
| 714 | |||
| 715 | static void | ||
| 716 | int_to_digit_array(int a, int b, int n, int *r) | ||
| 717 | { | ||
| 718 | int i; | ||
| 719 | |||
| 720 | if (b <= 1) | ||
| 721 | for (i = 0; i < n; i++) | ||
| 722 | r[i] = 0; | ||
| 723 | else | ||
| 724 | for (i = 0; i < n; i++, a /= b) | ||
| 725 | r[i] = a % b; | ||
| 726 | } | ||
| 727 | |||
| 728 | static void | ||
| 729 | int_to_sum_zero_array(int x, int b, int n, int *a) | ||
| 730 | { | ||
| 731 | int i, s = 0; | ||
| 732 | |||
| 733 | if (b <= 1) { | ||
| 734 | for (i = 0; i < n; i++) | ||
| 735 | a[i] = 0; | ||
| 736 | } else { | ||
| 737 | int_to_digit_array(x, b, n-1, a); | ||
| 738 | for (i = 0; i < n - 1; i++) | ||
| 739 | s = (s + a[i]) % b; | ||
| 740 | a[n-1] = (b - s) % b; | ||
| 741 | } | ||
| 742 | } | ||
| 743 | |||
| 744 | static int | ||
| 745 | invert_digits(int a, int b, int n) | ||
| 746 | { | ||
| 747 | int i, ret, *r = malloc(n * sizeof(int)); | ||
| 748 | |||
| 749 | int_to_digit_array(a, b, n, r); | ||
| 750 | for (i = 0; i < n; i++) | ||
| 751 | r[i] = (b-r[i]) % b; | ||
| 752 | |||
| 753 | ret = digit_array_to_int(r, n, b); | ||
| 754 | free(r); | ||
| 755 | return ret; | ||
| 756 | } | ||
| 757 | |||
| 758 | static bool | ||
| 759 | is_perm(int *a, int n) | ||
| 760 | { | ||
| 761 | int *aux = malloc(n * sizeof(int)); | ||
| 762 | int i; | ||
| 763 | |||
| 764 | for (i = 0; i < n; i++) | ||
| 765 | if (a[i] < 0 || a[i] >= n) | ||
| 766 | return false; | ||
| 767 | else | ||
| 768 | aux[a[i]] = 1; | ||
| 769 | |||
| 770 | for (i = 0; i < n; i++) | ||
| 771 | if (!aux[i]) | ||
| 772 | return false; | ||
| 773 | |||
| 774 | free(aux); | ||
| 775 | |||
| 776 | return true; | ||
| 777 | } | ||
| 778 | |||
| 779 | static bool | ||
| 780 | is_subset(int *a, int n, int k) | ||
| 781 | { | ||
| 782 | int i, sum = 0; | ||
| 783 | |||
| 784 | for (i = 0; i < n; i++) | ||
| 785 | sum += a[i] ? 1 : 0; | ||
| 786 | |||
| 787 | return sum == k; | ||
| 788 | } | ||
| 789 | |||
| 790 | static Cube | ||
| 791 | move_via_arrays(CubeArray *arr, Cube c, PieceFilter f) | ||
| 792 | { | ||
| 793 | CubeArray *arrc = new_cubearray(c, f); | ||
| 794 | Cube ret; | ||
| 795 | |||
| 796 | if (f.epose || f.eposs || f.eposm) | ||
| 797 | apply_permutation(arr->ep, arrc->ep, 12); | ||
| 798 | |||
| 799 | if (f.eofb) { | ||
| 800 | apply_permutation(arr->ep, arrc->eofb, 12); | ||
| 801 | sum_arrays_mod(arr->eofb, arrc->eofb, 12, 2); | ||
| 802 | } | ||
| 803 | |||
| 804 | if (f.eorl) { | ||
| 805 | apply_permutation(arr->ep, arrc->eorl, 12); | ||
| 806 | sum_arrays_mod(arr->eorl, arrc->eorl, 12, 2); | ||
| 807 | } | ||
| 808 | |||
| 809 | if (f.eoud) { | ||
| 810 | apply_permutation(arr->ep, arrc->eoud, 12); | ||
| 811 | sum_arrays_mod(arr->eoud, arrc->eoud, 12, 2); | ||
| 812 | } | ||
| 813 | |||
| 814 | if (f.cp) | ||
| 815 | apply_permutation(arr->cp, arrc->cp, 8); | ||
| 816 | |||
| 817 | if (f.coud) { | ||
| 818 | apply_permutation(arr->cp, arrc->coud, 8); | ||
| 819 | sum_arrays_mod(arr->coud, arrc->coud, 8, 3); | ||
| 820 | } | ||
| 821 | |||
| 822 | if (f.corl) { | ||
| 823 | apply_permutation(arr->cp, arrc->corl, 8); | ||
| 824 | sum_arrays_mod(arr->corl, arrc->corl, 8, 3); | ||
| 825 | } | ||
| 826 | |||
| 827 | if (f.cofb) { | ||
| 828 | apply_permutation(arr->cp, arrc->cofb, 8); | ||
| 829 | sum_arrays_mod(arr->cofb, arrc->cofb, 8, 3); | ||
| 830 | } | ||
| 831 | |||
| 832 | if (f.cpos) | ||
| 833 | apply_permutation(arr->cpos, arrc->cpos, 6); | ||
| 834 | |||
| 835 | ret = arrays_to_cube(arrc, f); | ||
| 836 | free_cubearray(arrc, f); | ||
| 837 | |||
| 838 | return ret; | ||
| 839 | } | ||
| 840 | |||
| 841 | static void | ||
| 842 | moveset_to_list(bool (*ms)(Move m), int (*f)(Cube), Move *r) | ||
| 843 | { | ||
| 844 | Cube c; | ||
| 845 | int b[NMOVES]; | ||
| 846 | int na = 0, nb = 0; | ||
| 847 | Move i; | ||
| 848 | |||
| 849 | if (ms == NULL) { | ||
| 850 | fprintf(stderr, "Error: no moveset given\n"); | ||
| 851 | return; | ||
| 852 | } | ||
| 853 | |||
| 854 | for (i = U; i < NMOVES; i++) { | ||
| 855 | if (ms(i)) { | ||
| 856 | c = apply_move(i, (Cube){0}); | ||
| 857 | if (f != NULL && f(c)) | ||
| 858 | r[na++] = i; | ||
| 859 | else | ||
| 860 | b[nb++] = i; | ||
| 861 | } | ||
| 862 | } | ||
| 863 | |||
| 864 | memcpy(r + na, b, nb * sizeof(Move)); | ||
| 865 | r[na+nb] = NULLMOVE; | ||
| 866 | } | ||
| 867 | |||
| 868 | static AlgList * | ||
| 869 | new_alglist() | ||
| 870 | { | ||
| 871 | AlgList *ret = malloc(sizeof(AlgList)); | ||
| 872 | |||
| 873 | ret->len = 0; | ||
| 874 | ret->first = NULL; | ||
| 875 | ret->last = NULL; | ||
| 876 | |||
| 877 | return ret; | ||
| 878 | } | ||
| 879 | |||
| 880 | static CubeArray * | ||
| 881 | new_cubearray(Cube cube, PieceFilter f) | ||
| 882 | { | ||
| 883 | CubeArray *arr = malloc(sizeof(CubeArray)); | ||
| 884 | |||
| 885 | if (f.epose || f.eposs || f.eposm) | ||
| 886 | arr->ep = malloc(12 * sizeof(int)); | ||
| 887 | if (f.eofb) | ||
| 888 | arr->eofb = malloc(12 * sizeof(int)); | ||
| 889 | if (f.eorl) | ||
| 890 | arr->eorl = malloc(12 * sizeof(int)); | ||
| 891 | if (f.eoud) | ||
| 892 | arr->eoud = malloc(12 * sizeof(int)); | ||
| 893 | if (f.cp) | ||
| 894 | arr->cp = malloc(8 * sizeof(int)); | ||
| 895 | if (f.coud) | ||
| 896 | arr->coud = malloc(8 * sizeof(int)); | ||
| 897 | if (f.corl) | ||
| 898 | arr->corl = malloc(8 * sizeof(int)); | ||
| 899 | if (f.cofb) | ||
| 900 | arr->cofb = malloc(8 * sizeof(int)); | ||
| 901 | if (f.cpos) | ||
| 902 | arr->cpos = malloc(6 * sizeof(int)); | ||
| 903 | |||
| 904 | cube_to_arrays(cube, arr, f); | ||
| 905 | |||
| 906 | return arr; | ||
| 907 | } | ||
| 908 | |||
| 909 | static int | ||
| 910 | perm_sign(int *a, int n) | ||
| 911 | { | ||
| 912 | int i, j, ret = 0; | ||
| 913 | |||
| 914 | if (!is_perm(a,n)) | ||
| 915 | return -1; | ||
| 916 | |||
| 917 | for (i = 0; i < n; i++) | ||
| 918 | for (j = i+1; j < n; j++) | ||
| 919 | ret += (a[i] > a[j]) ? 1 : 0; | ||
| 920 | |||
| 921 | return ret % 2; | ||
| 922 | } | ||
| 923 | |||
| 924 | static int | ||
| 925 | perm_to_index(int *a, int n) | ||
| 926 | { | ||
| 927 | int i, j, c, ret = 0; | ||
| 928 | |||
| 929 | if (!is_perm(a, n)) | ||
| 930 | return -1; | ||
| 931 | |||
| 932 | for (i = 0; i < n; i++) { | ||
| 933 | c = 0; | ||
| 934 | for (j = i+1; j < n; j++) | ||
| 935 | c += (a[i] > a[j]) ? 1 : 0; | ||
| 936 | ret += factorial(n-i-1) * c; | ||
| 937 | } | ||
| 938 | |||
| 939 | return ret; | ||
| 940 | } | ||
| 941 | |||
| 942 | static int | ||
| 943 | powint(int a, int b) | ||
| 944 | { | ||
| 945 | if (b < 0) | ||
| 946 | return 0; /* Truncate */ | ||
| 947 | if (b == 0) | ||
| 948 | return 1; | ||
| 949 | |||
| 950 | if (b % 2) | ||
| 951 | return a * powint(a, b-1); | ||
| 952 | else | ||
| 953 | return powint(a*a, b/2); | ||
| 954 | } | ||
| 955 | |||
| 956 | static void | ||
| 957 | ptable_set_reached(PruneData *pd, uint64_t ind) | ||
| 958 | { | ||
| 959 | uint8_t oldval2 = pd->reached[ind/2]; | ||
| 960 | int other = ind % 2 ? oldval2 % 16 : oldval2 / 16; | ||
| 961 | |||
| 962 | pd->reached[ind/2] = ind % 2 ? 16 + other : 16*other + 1; | ||
| 963 | } | ||
| 964 | |||
| 965 | static void | ||
| 966 | ptable_update(PruneData *pd, uint64_t ind, int n) | ||
| 967 | { | ||
| 968 | uint8_t oldval2 = pd->ptable[ind/2]; | ||
| 969 | int other = ind % 2 ? oldval2 % 16 : oldval2 / 16; | ||
| 970 | |||
| 971 | pd->ptable[ind/2] = ind % 2 ? 16*n + other : 16*other + n; | ||
| 972 | pd->n++; | ||
| 973 | } | ||
| 974 | |||
| 975 | static bool | ||
| 976 | read_mtables_file() | ||
| 977 | { | ||
| 978 | FILE *f; | ||
| 979 | char fname[strlen(tabledir)+20]; | ||
| 980 | int m, b = sizeof(uint16_t); | ||
| 981 | bool r = true; | ||
| 982 | |||
| 983 | strcpy(fname, tabledir); | ||
| 984 | strcat(fname, "/mtables"); | ||
| 985 | |||
| 986 | if ((f = fopen(fname, "rb")) == NULL) | ||
| 987 | return false; | ||
| 988 | |||
| 989 | for (m = 0; m < NMOVES; m++) { | ||
| 990 | r = r && fread(epose_mtable[m], b, me[0], f) == me[0]; | ||
| 991 | r = r && fread(eposs_mtable[m], b, me[1], f) == me[1]; | ||
| 992 | r = r && fread(eposm_mtable[m], b, me[2], f) == me[2]; | ||
| 993 | r = r && fread(eofb_mtable[m], b, me[3], f) == me[3]; | ||
| 994 | r = r && fread(eorl_mtable[m], b, me[4], f) == me[4]; | ||
| 995 | r = r && fread(eoud_mtable[m], b, me[5], f) == me[5]; | ||
| 996 | r = r && fread(cp_mtable[m], b, me[6], f) == me[6]; | ||
| 997 | r = r && fread(coud_mtable[m], b, me[7], f) == me[7]; | ||
| 998 | r = r && fread(corl_mtable[m], b, me[8], f) == me[8]; | ||
| 999 | r = r && fread(cofb_mtable[m], b, me[9], f) == me[9]; | ||
| 1000 | r = r && fread(cpos_mtable[m], b, me[10], f) == me[10]; | ||
| 1001 | } | ||
| 1002 | |||
| 1003 | fclose(f); | ||
| 1004 | return r; | ||
| 1005 | } | ||
| 1006 | |||
| 1007 | static bool | ||
| 1008 | read_ptable_file(PruneData *pd) | ||
| 1009 | { | ||
| 1010 | FILE *f; | ||
| 1011 | char fname[strlen(tabledir)+100]; | ||
| 1012 | uint64_t r; | ||
| 1013 | |||
| 1014 | strcpy(fname, tabledir); | ||
| 1015 | strcat(fname, "/"); | ||
| 1016 | strcat(fname, pd->filename); | ||
| 1017 | |||
| 1018 | if ((f = fopen(fname, "rb")) == NULL) | ||
| 1019 | return false; | ||
| 1020 | |||
| 1021 | r = fread(pd->ptable, sizeof(uint8_t), PTABLESIZE(pd->size), f); | ||
| 1022 | fclose(f); | ||
| 1023 | |||
| 1024 | return r == PTABLESIZE(pd->size); | ||
| 1025 | } | ||
| 1026 | |||
| 1027 | static bool | ||
| 1028 | read_ttables_file() | ||
| 1029 | { | ||
| 1030 | FILE *f; | ||
| 1031 | char fname[strlen(tabledir)+20]; | ||
| 1032 | int b = sizeof(uint16_t); | ||
| 1033 | bool r = true; | ||
| 1034 | Move m; | ||
| 1035 | |||
| 1036 | strcpy(fname, tabledir); | ||
| 1037 | strcat(fname, "/"); | ||
| 1038 | strcat(fname, "ttables"); | ||
| 1039 | |||
| 1040 | if ((f = fopen(fname, "rb")) == NULL) | ||
| 1041 | return false; | ||
| 1042 | |||
| 1043 | for (m = 0; m < NTRANS; m++) { | ||
| 1044 | r = r && fread(epose_ttable[m], b, me[0], f) == me[0]; | ||
| 1045 | r = r && fread(eposs_ttable[m], b, me[1], f) == me[1]; | ||
| 1046 | r = r && fread(eposm_ttable[m], b, me[2], f) == me[2]; | ||
| 1047 | r = r && fread(eo_ttable[m], b, me[3], f) == me[3]; | ||
| 1048 | r = r && fread(cp_ttable[m], b, me[6], f) == me[6]; | ||
| 1049 | r = r && fread(co_ttable[m], b, me[7], f) == me[7]; | ||
| 1050 | r = r && fread(cpos_ttable[m], b, me[10], f) == me[10]; | ||
| 1051 | r = r && fread(moves_ttable[m], b, me[11], f) == me[11]; | ||
| 1052 | } | ||
| 1053 | |||
| 1054 | fclose(f); | ||
| 1055 | return r; | ||
| 1056 | } | ||
| 1057 | |||
| 1058 | static Cube | ||
| 1059 | rotate_via_compose(Trans r, Cube c, PieceFilter f) | ||
| 1060 | { | ||
| 1061 | Alg *inv; | ||
| 1062 | static int zero12[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; | ||
| 1063 | static int zero8[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; | ||
| 1064 | static CubeArray ma = { | ||
| 1065 | .ep = ep_mirror, | ||
| 1066 | .eofb = zero12, | ||
| 1067 | .eorl = zero12, | ||
| 1068 | .eoud = zero12, | ||
| 1069 | .cp = cp_mirror, | ||
| 1070 | .coud = zero8, | ||
| 1071 | .corl = zero8, | ||
| 1072 | .cofb = zero8, | ||
| 1073 | .cpos = cpos_mirror | ||
| 1074 | }; | ||
| 1075 | |||
| 1076 | Cube ret; | ||
| 1077 | |||
| 1078 | if (r != mirror) { | ||
| 1079 | ret = apply_alg_generic(trans_algs[r], c, f, true); | ||
| 1080 | inv = on_inverse(trans_algs[r]); | ||
| 1081 | ret = apply_alg_generic(inv, ret, f, true); | ||
| 1082 | free_alg(inv); | ||
| 1083 | } else { | ||
| 1084 | ret = move_via_arrays(&ma, (Cube){0}, f); | ||
| 1085 | ret = compose_filtered(c, ret, f); | ||
| 1086 | ret = move_via_arrays(&ma, ret, f); | ||
| 1087 | } | ||
| 1088 | |||
| 1089 | return ret; | ||
| 1090 | } | ||
| 1091 | |||
| 1092 | static void | ||
| 1093 | solve_dfs(Cube c, Step s, SolveOptions *opts, DfsData *dd) | ||
| 1094 | { | ||
| 1095 | Move move, l1 = dd->last1, l2 = dd->last2; | ||
| 1096 | int i, lower_bound = s.check(c); | ||
| 1097 | bool found_many, prune, niss_make_sense, nissbackup = dd->niss; | ||
| 1098 | |||
| 1099 | if (opts->can_niss && !dd->niss) | ||
| 1100 | lower_bound = MIN(1, lower_bound); | ||
| 1101 | |||
| 1102 | found_many = dd->sols->len >= opts->max_solutions; | ||
| 1103 | prune = dd->current_alg->len + lower_bound > dd->d; | ||
| 1104 | if (found_many || prune) | ||
| 1105 | return; | ||
| 1106 | |||
| 1107 | if (!lower_bound) { /* solved */ | ||
| 1108 | if (dd->current_alg->len == dd->d) | ||
| 1109 | append_alg(dd->sols, dd->current_alg); | ||
| 1110 | return; | ||
| 1111 | } | ||
| 1112 | |||
| 1113 | dd->last2 = dd->last1; | ||
| 1114 | |||
| 1115 | for (i = 0; dd->sorted_moves[i] != NULLMOVE; i++) { | ||
| 1116 | move = dd->sorted_moves[i]; | ||
| 1117 | if (possible_next[l2][l1][move]) { | ||
| 1118 | dd->last1 = move; | ||
| 1119 | append_move(dd->current_alg, move, dd->niss); | ||
| 1120 | solve_dfs(apply_move(move, c), s, opts, dd); | ||
| 1121 | remove_last_move(dd->current_alg); | ||
| 1122 | } | ||
| 1123 | } | ||
| 1124 | |||
| 1125 | niss_make_sense = !dd->current_alg->len || | ||
| 1126 | (s.check(apply_move(l1,(Cube){0}))); | ||
| 1127 | if (opts->can_niss && !dd->niss && niss_make_sense) { | ||
| 1128 | dd->niss = true; | ||
| 1129 | dd->last1 = NULLMOVE; | ||
| 1130 | dd->last2 = NULLMOVE; | ||
| 1131 | solve_dfs(inverse_cube(c), s, opts, dd); | ||
| 1132 | } | ||
| 1133 | |||
| 1134 | dd->last1 = l1; | ||
| 1135 | dd->last2 = l2; | ||
| 1136 | dd->niss = nissbackup; | ||
| 1137 | } | ||
| 1138 | |||
| 1139 | static int | ||
| 1140 | subset_to_index(int *a, int n, int k) | ||
| 1141 | { | ||
| 1142 | int i, ret = 0; | ||
| 1143 | |||
| 1144 | if (!is_subset(a, n, k)) | ||
| 1145 | return binomial(n, k); | ||
| 1146 | |||
| 1147 | for (i = 0; i < n; i++) { | ||
| 1148 | if (k == n-i) | ||
| 1149 | return ret; | ||
| 1150 | if (a[i]) { | ||
| 1151 | ret += binomial(n-i-1, k); | ||
| 1152 | k--; | ||
| 1153 | } | ||
| 1154 | } | ||
| 1155 | |||
| 1156 | return ret; | ||
| 1157 | } | ||
| 1158 | |||
| 1159 | static void | ||
| 1160 | sum_arrays_mod(int *src, int *dst, int n, int m) | ||
| 1161 | { | ||
| 1162 | int i; | ||
| 1163 | |||
| 1164 | for (i = 0; i < n; i++) | ||
| 1165 | dst[i] = (m <= 0) ? 0 : (src[i] + dst[i]) % m; | ||
| 1166 | } | ||
| 1167 | |||
| 1168 | static void | ||
| 1169 | swap(int *a, int *b) | ||
| 1170 | { | ||
| 1171 | int aux; | ||
| 1172 | |||
| 1173 | aux = *a; | ||
| 1174 | *a = *b; | ||
| 1175 | *b = aux; | ||
| 1176 | } | ||
| 1177 | |||
| 1178 | static bool | ||
| 1179 | write_mtables_file() | ||
| 1180 | { | ||
| 1181 | FILE *f; | ||
| 1182 | char fname[strlen(tabledir)+20]; | ||
| 1183 | int m, b = sizeof(uint16_t); | ||
| 1184 | bool r = true; | ||
| 1185 | |||
| 1186 | strcpy(fname, tabledir); | ||
| 1187 | strcat(fname, "/mtables"); | ||
| 1188 | |||
| 1189 | if ((f = fopen(fname, "wb")) == NULL) | ||
| 1190 | return false; | ||
| 1191 | |||
| 1192 | for (m = 0; m < NMOVES; m++) { | ||
| 1193 | r = r && fwrite(epose_mtable[m], b, me[0], f) == me[0]; | ||
| 1194 | r = r && fwrite(eposs_mtable[m], b, me[1], f) == me[1]; | ||
| 1195 | r = r && fwrite(eposm_mtable[m], b, me[2], f) == me[2]; | ||
| 1196 | r = r && fwrite(eofb_mtable[m], b, me[3], f) == me[3]; | ||
| 1197 | r = r && fwrite(eorl_mtable[m], b, me[4], f) == me[4]; | ||
| 1198 | r = r && fwrite(eoud_mtable[m], b, me[5], f) == me[5]; | ||
| 1199 | r = r && fwrite(cp_mtable[m], b, me[6], f) == me[6]; | ||
| 1200 | r = r && fwrite(coud_mtable[m], b, me[7], f) == me[7]; | ||
| 1201 | r = r && fwrite(corl_mtable[m], b, me[8], f) == me[8]; | ||
| 1202 | r = r && fwrite(cofb_mtable[m], b, me[9], f) == me[9]; | ||
| 1203 | r = r && fwrite(cpos_mtable[m], b, me[10], f) == me[10]; | ||
| 1204 | } | ||
| 1205 | |||
| 1206 | fclose(f); | ||
| 1207 | return r; | ||
| 1208 | } | ||
| 1209 | |||
| 1210 | static bool | ||
| 1211 | write_ptable_file(PruneData *pd) | ||
| 1212 | { | ||
| 1213 | FILE *f; | ||
| 1214 | char fname[strlen(tabledir)+100]; | ||
| 1215 | uint64_t written; | ||
| 1216 | |||
| 1217 | strcpy(fname, tabledir); | ||
| 1218 | strcat(fname, "/"); | ||
| 1219 | strcat(fname, pd->filename); | ||
| 1220 | |||
| 1221 | if ((f = fopen(fname, "wb")) == NULL) | ||
| 1222 | return false; | ||
| 1223 | |||
| 1224 | written = fwrite(pd->ptable, sizeof(uint8_t), PTABLESIZE(pd->size), f); | ||
| 1225 | fclose(f); | ||
| 1226 | |||
| 1227 | return written == PTABLESIZE(pd->size); | ||
| 1228 | } | ||
| 1229 | |||
| 1230 | static bool | ||
| 1231 | write_ttables_file() | ||
| 1232 | { | ||
| 1233 | FILE *f; | ||
| 1234 | char fname[strlen(tabledir)+20]; | ||
| 1235 | bool r = true; | ||
| 1236 | int b = sizeof(uint16_t); | ||
| 1237 | Move m; | ||
| 1238 | |||
| 1239 | strcpy(fname, tabledir); | ||
| 1240 | strcat(fname, "/ttables"); | ||
| 1241 | |||
| 1242 | if ((f = fopen(fname, "wb")) == NULL) | ||
| 1243 | return false; | ||
| 1244 | |||
| 1245 | for (m = 0; m < NTRANS; m++) { | ||
| 1246 | r = r && fwrite(epose_ttable[m], b, me[0], f) == me[0]; | ||
| 1247 | r = r && fwrite(eposs_ttable[m], b, me[1], f) == me[1]; | ||
| 1248 | r = r && fwrite(eposm_ttable[m], b, me[2], f) == me[2]; | ||
| 1249 | r = r && fwrite(eo_ttable[m], b, me[3], f) == me[3]; | ||
| 1250 | r = r && fwrite(cp_ttable[m], b, me[6], f) == me[6]; | ||
| 1251 | r = r && fwrite(co_ttable[m], b, me[7], f) == me[7]; | ||
| 1252 | r = r && fwrite(cpos_ttable[m], b, me[10], f) == me[10]; | ||
| 1253 | r = r && fwrite(moves_ttable[m], b, me[11], f) == me[11]; | ||
| 1254 | } | ||
| 1255 | |||
| 1256 | fclose(f); | ||
| 1257 | return r; | ||
| 1258 | } | ||
| 1259 | |||
| 1260 | /* Init functions implementation *********************************************/ | ||
| 1261 | |||
| 1262 | static void | ||
| 1263 | init_auxtables() | ||
| 1264 | { | ||
| 1265 | Cube c1, c2; | ||
| 1266 | uint64_t ui, uj; | ||
| 1267 | int i, j, k; | ||
| 1268 | bool cij, p1, p2; | ||
| 1269 | |||
| 1270 | for (ui = 0; ui < BINOM12ON4; ui++) | ||
| 1271 | for (uj = 0; uj < BINOM12ON4; uj++) | ||
| 1272 | epos_dependent_aux[ui][uj] = epos_dependent(ui, uj); | ||
| 1273 | |||
| 1274 | for (i = 0; i < NMOVES; i++) { | ||
| 1275 | for (j = 0; j < NMOVES; j++) { | ||
| 1276 | c1 = apply_move(i, apply_move(j, (Cube){0})); | ||
| 1277 | c2 = apply_move(j, apply_move(i, (Cube){0})); | ||
| 1278 | commute[i][j] = equal(c1, c2); | ||
| 1279 | } | ||
| 1280 | } | ||
| 1281 | |||
| 1282 | for (i = 0; i < NMOVES; i++) { | ||
| 1283 | for (j = 0; j < NMOVES; j++) { | ||
| 1284 | for (k = 0; k < NMOVES; k++) { | ||
| 1285 | p1 = j && base_move(j) == base_move(k); | ||
| 1286 | p2 = i && base_move(i) == base_move(k); | ||
| 1287 | cij = commute[i][j]; | ||
| 1288 | possible_next[i][j][k] = !(p1 || (cij && p2)); | ||
| 1289 | } | ||
| 1290 | } | ||
| 1291 | } | ||
| 1292 | |||
| 1293 | for (i = 0; i < NMOVES; i++) | ||
| 1294 | inverse_move_aux[i] = i ? i + 2 - 2*((i-1)%3) : NULLMOVE; | ||
| 1295 | |||
| 1296 | /* Is there a more elegant way? */ | ||
| 1297 | inverse_trans_aux[uf] = uf; | ||
| 1298 | inverse_trans_aux[ur] = ul; | ||
| 1299 | inverse_trans_aux[ul] = ur; | ||
| 1300 | inverse_trans_aux[ub] = ub; | ||
| 1301 | |||
| 1302 | inverse_trans_aux[df] = df; | ||
| 1303 | inverse_trans_aux[dr] = dr; | ||
| 1304 | inverse_trans_aux[dl] = dl; | ||
| 1305 | inverse_trans_aux[db] = db; | ||
| 1306 | |||
| 1307 | inverse_trans_aux[rf] = lf; | ||
| 1308 | inverse_trans_aux[rd] = bl; | ||
| 1309 | inverse_trans_aux[rb] = rb; | ||
| 1310 | inverse_trans_aux[ru] = fr; | ||
| 1311 | |||
| 1312 | inverse_trans_aux[lf] = rf; | ||
| 1313 | inverse_trans_aux[ld] = br; | ||
| 1314 | inverse_trans_aux[lb] = lb; | ||
| 1315 | inverse_trans_aux[lu] = fl; | ||
| 1316 | |||
| 1317 | inverse_trans_aux[fu] = fu; | ||
| 1318 | inverse_trans_aux[fr] = ru; | ||
| 1319 | inverse_trans_aux[fd] = bu; | ||
| 1320 | inverse_trans_aux[fl] = lu; | ||
| 1321 | |||
| 1322 | inverse_trans_aux[bu] = fd; | ||
| 1323 | inverse_trans_aux[br] = ld; | ||
| 1324 | inverse_trans_aux[bd] = bd; | ||
| 1325 | inverse_trans_aux[bl] = rd; | ||
| 1326 | |||
| 1327 | inverse_trans_aux[mirror] = mirror; | ||
| 1328 | } | ||
| 1329 | |||
| 1330 | static void | ||
| 1331 | init_environment() | ||
| 1332 | { | ||
| 1333 | char *nissydata = getenv("NISSYDATA"); | ||
| 1334 | char *localdata = getenv("XDG_DATA_HOME"); | ||
| 1335 | char *home = getenv("HOME"); | ||
| 1336 | bool read, write; | ||
| 1337 | |||
| 1338 | if (nissydata != NULL) { | ||
| 1339 | tabledir = malloc(strlen(nissydata) * sizeof(char) + 20); | ||
| 1340 | strcpy(tabledir, nissydata); | ||
| 1341 | } else if (localdata != NULL) { | ||
| 1342 | tabledir = malloc(strlen(localdata) * sizeof(char) + 20); | ||
| 1343 | strcpy(tabledir, localdata); | ||
| 1344 | strcat(tabledir, "/nissy"); | ||
| 1345 | } else if (home != NULL) { | ||
| 1346 | tabledir = malloc(strlen(home) * sizeof(char) + 20); | ||
| 1347 | strcpy(tabledir, home); | ||
| 1348 | strcat(tabledir, "/.nissy"); | ||
| 1349 | } | ||
| 1350 | |||
| 1351 | mkdir(tabledir, 0777); | ||
| 1352 | strcat(tabledir, "/tables"); | ||
| 1353 | mkdir(tabledir, 0777); | ||
| 1354 | |||
| 1355 | read = !access(tabledir, R_OK); | ||
| 1356 | write = !access(tabledir, W_OK); | ||
| 1357 | |||
| 1358 | if (!read) { | ||
| 1359 | fprintf(stderr, "Table files cannot be read.\n"); | ||
| 1360 | } else if (!write) { | ||
| 1361 | fprintf(stderr, "Data directory not writable: "); | ||
| 1362 | fprintf(stderr, "tables can be loaded, but not saved.\n"); | ||
| 1363 | } | ||
| 1364 | } | ||
| 1365 | |||
| 1366 | static void | ||
| 1367 | init_moves() { | ||
| 1368 | Cube c; | ||
| 1369 | CubeArray arrs; | ||
| 1370 | int i; | ||
| 1371 | uint16_t ui; | ||
| 1372 | Move m; | ||
| 1373 | |||
| 1374 | /* Generate all move cycles and flips; I do this regardless */ | ||
| 1375 | for (i = 0; i < NMOVES; i++) { | ||
| 1376 | if (i == U || i == x || i == y) | ||
| 1377 | continue; | ||
| 1378 | |||
| 1379 | c = apply_alg_generic(equiv_alg[i], (Cube){0}, pf_all, false); | ||
| 1380 | |||
| 1381 | arrs = (CubeArray){ | ||
| 1382 | edge_cycle[i], | ||
| 1383 | eofb_flipped[i], | ||
| 1384 | eorl_flipped[i], | ||
| 1385 | eoud_flipped[i], | ||
| 1386 | corner_cycle[i], | ||
| 1387 | coud_flipped[i], | ||
| 1388 | corl_flipped[i], | ||
| 1389 | cofb_flipped[i], | ||
| 1390 | center_cycle[i] | ||
| 1391 | }; | ||
| 1392 | cube_to_arrays(c, &arrs, pf_all); | ||
| 1393 | } | ||
| 1394 | |||
| 1395 | if (read_mtables_file()) | ||
| 1396 | return; | ||
| 1397 | |||
| 1398 | fprintf(stderr, "Cannot load %s, generating it\n", "mtables"); | ||
| 1399 | |||
| 1400 | /* Initialize transition tables */ | ||
| 1401 | for (m = 0; m < NMOVES; m++) { | ||
| 1402 | for (ui = 0; ui < FACTORIAL12/FACTORIAL8; ui++) { | ||
| 1403 | c = (Cube){ .epose = ui }; | ||
| 1404 | c = apply_move_cubearray(m, c, pf_e); | ||
| 1405 | epose_mtable[m][ui] = c.epose; | ||
| 1406 | |||
| 1407 | c = (Cube){ .eposs = ui }; | ||
| 1408 | c = apply_move_cubearray(m, c, pf_s); | ||
| 1409 | eposs_mtable[m][ui] = c.eposs; | ||
| 1410 | |||
| 1411 | c = (Cube){ .eposm = ui }; | ||
| 1412 | c = apply_move_cubearray(m, c, pf_m); | ||
| 1413 | eposm_mtable[m][ui] = c.eposm; | ||
| 1414 | } | ||
| 1415 | for (ui = 0; ui < POW2TO11; ui++ ) { | ||
| 1416 | c = (Cube){ .eofb = ui }; | ||
| 1417 | c = apply_move_cubearray(m, c, pf_eo); | ||
| 1418 | eofb_mtable[m][ui] = c.eofb; | ||
| 1419 | |||
| 1420 | c = (Cube){ .eorl = ui }; | ||
| 1421 | c = apply_move_cubearray(m, c, pf_eo); | ||
| 1422 | eorl_mtable[m][ui] = c.eorl; | ||
| 1423 | |||
| 1424 | c = (Cube){ .eoud = ui }; | ||
| 1425 | c = apply_move_cubearray(m, c, pf_eo); | ||
| 1426 | eoud_mtable[m][ui] = c.eoud; | ||
| 1427 | } | ||
| 1428 | for (ui = 0; ui < POW3TO7; ui++) { | ||
| 1429 | c = (Cube){ .coud = ui }; | ||
| 1430 | c = apply_move_cubearray(m, c, pf_co); | ||
| 1431 | coud_mtable[m][ui] = c.coud; | ||
| 1432 | |||
| 1433 | c = (Cube){ .corl = ui }; | ||
| 1434 | c = apply_move_cubearray(m, c, pf_co); | ||
| 1435 | corl_mtable[m][ui] = c.corl; | ||
| 1436 | |||
| 1437 | c = (Cube){ .cofb = ui }; | ||
| 1438 | c = apply_move_cubearray(m, c, pf_co); | ||
| 1439 | cofb_mtable[m][ui] = c.cofb; | ||
| 1440 | } | ||
| 1441 | for (ui = 0; ui < FACTORIAL8; ui++) { | ||
| 1442 | c = (Cube){ .cp = ui }; | ||
| 1443 | c = apply_move_cubearray(m, c, pf_cp); | ||
| 1444 | cp_mtable[m][ui] = c.cp; | ||
| 1445 | } | ||
| 1446 | for (ui = 0; ui < FACTORIAL6; ui++) { | ||
| 1447 | c = (Cube){ .cpos = ui }; | ||
| 1448 | c = apply_move_cubearray(m, c, pf_cpos); | ||
| 1449 | cpos_mtable[m][ui] = c.cpos; | ||
| 1450 | } | ||
| 1451 | } | ||
| 1452 | |||
| 1453 | if (!write_mtables_file()) | ||
| 1454 | fprintf(stderr, "Error writing mtables\n"); | ||
| 1455 | } | ||
| 1456 | |||
| 1457 | static void | ||
| 1458 | init_moves_aux() | ||
| 1459 | { | ||
| 1460 | /* Some standard PieceFilters */ | ||
| 1461 | pf_all.epose = true; | ||
| 1462 | pf_all.eposs = true; | ||
| 1463 | pf_all.eposm = true; | ||
| 1464 | pf_all.eofb = true; | ||
| 1465 | pf_all.eorl = true; | ||
| 1466 | pf_all.eoud = true; | ||
| 1467 | pf_all.cp = true; | ||
| 1468 | pf_all.cofb = true; | ||
| 1469 | pf_all.corl = true; | ||
| 1470 | pf_all.coud = true; | ||
| 1471 | pf_all.cpos = true; | ||
| 1472 | |||
| 1473 | pf_4val.epose = true; | ||
| 1474 | pf_4val.eposs = true; | ||
| 1475 | pf_4val.eposm = true; | ||
| 1476 | pf_4val.eofb = true; | ||
| 1477 | pf_4val.coud = true; | ||
| 1478 | pf_4val.cp = true; | ||
| 1479 | |||
| 1480 | pf_epcp.epose = true; | ||
| 1481 | pf_epcp.eposs = true; | ||
| 1482 | pf_epcp.eposm = true; | ||
| 1483 | pf_epcp.cp = true; | ||
| 1484 | |||
| 1485 | pf_cpos.cpos = true; | ||
| 1486 | |||
| 1487 | pf_cp.cp = true; | ||
| 1488 | |||
| 1489 | pf_ep.epose = true; | ||
| 1490 | pf_ep.eposs = true; | ||
| 1491 | pf_ep.eposm = true; | ||
| 1492 | |||
| 1493 | pf_e.epose = true; | ||
| 1494 | pf_s.eposs = true; | ||
| 1495 | pf_m.eposm = true; | ||
| 1496 | |||
| 1497 | pf_eo.eofb = true; | ||
| 1498 | pf_eo.eorl = true; | ||
| 1499 | pf_eo.eoud = true; | ||
| 1500 | |||
| 1501 | pf_co.cofb = true; | ||
| 1502 | pf_co.corl = true; | ||
| 1503 | pf_co.coud = true; | ||
| 1504 | |||
| 1505 | /* Used to convert to and from CubeArray */ | ||
| 1506 | epe_solved[0] = FR; | ||
| 1507 | epe_solved[1] = FL; | ||
| 1508 | epe_solved[2] = BL; | ||
| 1509 | epe_solved[3] = BR; | ||
| 1510 | |||
| 1511 | eps_solved[0] = UL; | ||
| 1512 | eps_solved[1] = UR; | ||
| 1513 | eps_solved[2] = DL; | ||
| 1514 | eps_solved[3] = DR; | ||
| 1515 | |||
| 1516 | epm_solved[0] = UF; | ||
| 1517 | epm_solved[1] = UB; | ||
| 1518 | epm_solved[2] = DF; | ||
| 1519 | epm_solved[3] = DB; | ||
| 1520 | |||
| 1521 | /* Table sizes, used for reading and writing files */ | ||
| 1522 | me[0] = FACTORIAL12/FACTORIAL8; | ||
| 1523 | me[1] = FACTORIAL12/FACTORIAL8; | ||
| 1524 | me[2] = FACTORIAL12/FACTORIAL8; | ||
| 1525 | me[3] = POW2TO11; | ||
| 1526 | me[4] = POW2TO11; | ||
| 1527 | me[5] = POW2TO11; | ||
| 1528 | me[6] = FACTORIAL8; | ||
| 1529 | me[7] = POW3TO7; | ||
| 1530 | me[8] = POW3TO7; | ||
| 1531 | me[9] = POW3TO7; | ||
| 1532 | me[10] = FACTORIAL6; | ||
| 1533 | me[11] = NMOVES; | ||
| 1534 | |||
| 1535 | /* Cycles *********************/ | ||
| 1536 | edge_cycle[U][UF] = UR; | ||
| 1537 | edge_cycle[U][UL] = UF; | ||
| 1538 | edge_cycle[U][UB] = UL; | ||
| 1539 | edge_cycle[U][UR] = UB; | ||
| 1540 | edge_cycle[U][DF] = DF; | ||
| 1541 | edge_cycle[U][DL] = DL; | ||
| 1542 | edge_cycle[U][DB] = DB; | ||
| 1543 | edge_cycle[U][DR] = DR; | ||
| 1544 | edge_cycle[U][FR] = FR; | ||
| 1545 | edge_cycle[U][FL] = FL; | ||
| 1546 | edge_cycle[U][BL] = BL; | ||
| 1547 | edge_cycle[U][BR] = BR; | ||
| 1548 | |||
| 1549 | edge_cycle[x][UF] = DF; | ||
| 1550 | edge_cycle[x][UL] = FL; | ||
| 1551 | edge_cycle[x][UB] = UF; | ||
| 1552 | edge_cycle[x][UR] = FR; | ||
| 1553 | edge_cycle[x][DF] = DB; | ||
| 1554 | edge_cycle[x][DL] = BL; | ||
| 1555 | edge_cycle[x][DB] = UB; | ||
| 1556 | edge_cycle[x][DR] = BR; | ||
| 1557 | edge_cycle[x][FR] = DR; | ||
| 1558 | edge_cycle[x][FL] = DL; | ||
| 1559 | edge_cycle[x][BL] = UL; | ||
| 1560 | edge_cycle[x][BR] = UR; | ||
| 1561 | |||
| 1562 | edge_cycle[y][UF] = UR; | ||
| 1563 | edge_cycle[y][UL] = UF; | ||
| 1564 | edge_cycle[y][UB] = UL; | ||
| 1565 | edge_cycle[y][UR] = UB; | ||
| 1566 | edge_cycle[y][DF] = DR; | ||
| 1567 | edge_cycle[y][DL] = DF; | ||
| 1568 | edge_cycle[y][DB] = DL; | ||
| 1569 | edge_cycle[y][DR] = DB; | ||
| 1570 | edge_cycle[y][FR] = BR; | ||
| 1571 | edge_cycle[y][FL] = FR; | ||
| 1572 | edge_cycle[y][BL] = FL; | ||
| 1573 | edge_cycle[y][BR] = BL; | ||
| 1574 | |||
| 1575 | corner_cycle[U][UFR] = UBR; | ||
| 1576 | corner_cycle[U][UFL] = UFR; | ||
| 1577 | corner_cycle[U][UBL] = UFL; | ||
| 1578 | corner_cycle[U][UBR] = UBL; | ||
| 1579 | corner_cycle[U][DFR] = DFR; | ||
| 1580 | corner_cycle[U][DFL] = DFL; | ||
| 1581 | corner_cycle[U][DBL] = DBL; | ||
| 1582 | corner_cycle[U][DBR] = DBR; | ||
| 1583 | |||
| 1584 | corner_cycle[x][UFR] = DFR; | ||
| 1585 | corner_cycle[x][UFL] = DFL; | ||
| 1586 | corner_cycle[x][UBL] = UFL; | ||
| 1587 | corner_cycle[x][UBR] = UFR; | ||
| 1588 | corner_cycle[x][DFR] = DBR; | ||
| 1589 | corner_cycle[x][DFL] = DBL; | ||
| 1590 | corner_cycle[x][DBL] = UBL; | ||
| 1591 | corner_cycle[x][DBR] = UBR; | ||
| 1592 | |||
| 1593 | corner_cycle[y][UFR] = UBR; | ||
| 1594 | corner_cycle[y][UFL] = UFR; | ||
| 1595 | corner_cycle[y][UBL] = UFL; | ||
| 1596 | corner_cycle[y][UBR] = UBL; | ||
| 1597 | corner_cycle[y][DFR] = DBR; | ||
| 1598 | corner_cycle[y][DFL] = DFR; | ||
| 1599 | corner_cycle[y][DBL] = DFL; | ||
| 1600 | corner_cycle[y][DBR] = DBL; | ||
| 1601 | |||
| 1602 | center_cycle[U][U_center] = U_center; | ||
| 1603 | center_cycle[U][D_center] = D_center; | ||
| 1604 | center_cycle[U][R_center] = R_center; | ||
| 1605 | center_cycle[U][L_center] = L_center; | ||
| 1606 | center_cycle[U][F_center] = F_center; | ||
| 1607 | center_cycle[U][B_center] = B_center; | ||
| 1608 | |||
| 1609 | center_cycle[x][U_center] = F_center; | ||
| 1610 | center_cycle[x][D_center] = B_center; | ||
| 1611 | center_cycle[x][R_center] = R_center; | ||
| 1612 | center_cycle[x][L_center] = L_center; | ||
| 1613 | center_cycle[x][F_center] = D_center; | ||
| 1614 | center_cycle[x][B_center] = U_center; | ||
| 1615 | |||
| 1616 | center_cycle[y][U_center] = U_center; | ||
| 1617 | center_cycle[y][D_center] = D_center; | ||
| 1618 | center_cycle[y][R_center] = B_center; | ||
| 1619 | center_cycle[y][L_center] = F_center; | ||
| 1620 | center_cycle[y][F_center] = R_center; | ||
| 1621 | center_cycle[y][B_center] = L_center; | ||
| 1622 | |||
| 1623 | /* Flipped pieces *************/ | ||
| 1624 | eofb_flipped[x][UF] = 1; | ||
| 1625 | eofb_flipped[x][UB] = 1; | ||
| 1626 | eofb_flipped[x][DF] = 1; | ||
| 1627 | eofb_flipped[x][DB] = 1; | ||
| 1628 | |||
| 1629 | eofb_flipped[y][FR] = 1; | ||
| 1630 | eofb_flipped[y][FL] = 1; | ||
| 1631 | eofb_flipped[y][BL] = 1; | ||
| 1632 | eofb_flipped[y][BR] = 1; | ||
| 1633 | |||
| 1634 | eorl_flipped[x][UF] = 1; | ||
| 1635 | eorl_flipped[x][UL] = 1; | ||
| 1636 | eorl_flipped[x][UB] = 1; | ||
| 1637 | eorl_flipped[x][UR] = 1; | ||
| 1638 | eorl_flipped[x][DF] = 1; | ||
| 1639 | eorl_flipped[x][DL] = 1; | ||
| 1640 | eorl_flipped[x][DB] = 1; | ||
| 1641 | eorl_flipped[x][DR] = 1; | ||
| 1642 | eorl_flipped[x][FR] = 1; | ||
| 1643 | eorl_flipped[x][FL] = 1; | ||
| 1644 | eorl_flipped[x][BL] = 1; | ||
| 1645 | eorl_flipped[x][BR] = 1; | ||
| 1646 | |||
| 1647 | eorl_flipped[y][FR] = 1; | ||
| 1648 | eorl_flipped[y][FL] = 1; | ||
| 1649 | eorl_flipped[y][BL] = 1; | ||
| 1650 | eorl_flipped[y][BR] = 1; | ||
| 1651 | |||
| 1652 | eoud_flipped[U][UF] = 1; | ||
| 1653 | eoud_flipped[U][UL] = 1; | ||
| 1654 | eoud_flipped[U][UB] = 1; | ||
| 1655 | eoud_flipped[U][UR] = 1; | ||
| 1656 | |||
| 1657 | eoud_flipped[x][UF] = 1; | ||
| 1658 | eoud_flipped[x][UB] = 1; | ||
| 1659 | eoud_flipped[x][DF] = 1; | ||
| 1660 | eoud_flipped[x][DB] = 1; | ||
| 1661 | |||
| 1662 | eoud_flipped[y][UF] = 1; | ||
| 1663 | eoud_flipped[y][UL] = 1; | ||
| 1664 | eoud_flipped[y][UB] = 1; | ||
| 1665 | eoud_flipped[y][UR] = 1; | ||
| 1666 | eoud_flipped[y][DF] = 1; | ||
| 1667 | eoud_flipped[y][DL] = 1; | ||
| 1668 | eoud_flipped[y][DB] = 1; | ||
| 1669 | eoud_flipped[y][DR] = 1; | ||
| 1670 | eoud_flipped[y][FR] = 1; | ||
| 1671 | eoud_flipped[y][FL] = 1; | ||
| 1672 | eoud_flipped[y][BL] = 1; | ||
| 1673 | eoud_flipped[y][BR] = 1; | ||
| 1674 | |||
| 1675 | coud_flipped[x][UFR] = 2; | ||
| 1676 | coud_flipped[x][UFL] = 1; | ||
| 1677 | coud_flipped[x][UBR] = 1; | ||
| 1678 | coud_flipped[x][UBL] = 2; | ||
| 1679 | coud_flipped[x][DFR] = 1; | ||
| 1680 | coud_flipped[x][DFL] = 2; | ||
| 1681 | coud_flipped[x][DBR] = 2; | ||
| 1682 | coud_flipped[x][DBL] = 1; | ||
| 1683 | |||
| 1684 | corl_flipped[U][UFR] = 1; | ||
| 1685 | corl_flipped[U][UFL] = 2; | ||
| 1686 | corl_flipped[U][UBL] = 1; | ||
| 1687 | corl_flipped[U][UBR] = 2; | ||
| 1688 | |||
| 1689 | corl_flipped[y][UFR] = 1; | ||
| 1690 | corl_flipped[y][UFL] = 2; | ||
| 1691 | corl_flipped[y][UBL] = 1; | ||
| 1692 | corl_flipped[y][UBR] = 2; | ||
| 1693 | corl_flipped[y][DFR] = 2; | ||
| 1694 | corl_flipped[y][DFL] = 1; | ||
| 1695 | corl_flipped[y][DBL] = 2; | ||
| 1696 | corl_flipped[y][DBR] = 1; | ||
| 1697 | |||
| 1698 | cofb_flipped[U][UFR] = 2; | ||
| 1699 | cofb_flipped[U][UFL] = 1; | ||
| 1700 | cofb_flipped[U][UBL] = 2; | ||
| 1701 | cofb_flipped[U][UBR] = 1; | ||
| 1702 | |||
| 1703 | cofb_flipped[x][UFR] = 1; | ||
| 1704 | cofb_flipped[x][UFL] = 2; | ||
| 1705 | cofb_flipped[x][UBL] = 1; | ||
| 1706 | cofb_flipped[x][UBR] = 2; | ||
| 1707 | cofb_flipped[x][DFR] = 2; | ||
| 1708 | cofb_flipped[x][DFL] = 1; | ||
| 1709 | cofb_flipped[x][DBL] = 2; | ||
| 1710 | cofb_flipped[x][DBR] = 1; | ||
| 1711 | |||
| 1712 | cofb_flipped[y][UFR] = 2; | ||
| 1713 | cofb_flipped[y][UFL] = 1; | ||
| 1714 | cofb_flipped[y][UBL] = 2; | ||
| 1715 | cofb_flipped[y][UBR] = 1; | ||
| 1716 | cofb_flipped[y][DFR] = 1; | ||
| 1717 | cofb_flipped[y][DFL] = 2; | ||
| 1718 | cofb_flipped[y][DBL] = 1; | ||
| 1719 | cofb_flipped[y][DBR] = 2; | ||
| 1720 | |||
| 1721 | /* Equivalent moves ***********/ | ||
| 1722 | equiv_alg[NULLMOVE] = new_alg(""); | ||
| 1723 | |||
| 1724 | equiv_alg[U] = new_alg(" U "); | ||
| 1725 | equiv_alg[U2] = new_alg(" UU "); | ||
| 1726 | equiv_alg[U3] = new_alg(" UUU "); | ||
| 1727 | equiv_alg[D] = new_alg(" xx U xx "); | ||
| 1728 | equiv_alg[D2] = new_alg(" xx UU xx "); | ||
| 1729 | equiv_alg[D3] = new_alg(" xx UUU xx "); | ||
| 1730 | equiv_alg[R] = new_alg(" yx U xxxyyy "); | ||
| 1731 | equiv_alg[R2] = new_alg(" yx UU xxxyyy "); | ||
| 1732 | equiv_alg[R3] = new_alg(" yx UUU xxxyyy "); | ||
| 1733 | equiv_alg[L] = new_alg(" yyyx U xxxy "); | ||
| 1734 | equiv_alg[L2] = new_alg(" yyyx UU xxxy "); | ||
| 1735 | equiv_alg[L3] = new_alg(" yyyx UUU xxxy "); | ||
| 1736 | equiv_alg[F] = new_alg(" x U xxx "); | ||
| 1737 | equiv_alg[F2] = new_alg(" x UU xxx "); | ||
| 1738 | equiv_alg[F3] = new_alg(" x UUU xxx "); | ||
| 1739 | equiv_alg[B] = new_alg(" xxx U x "); | ||
| 1740 | equiv_alg[B2] = new_alg(" xxx UU x "); | ||
| 1741 | equiv_alg[B3] = new_alg(" xxx UUU x "); | ||
| 1742 | |||
| 1743 | equiv_alg[Uw] = new_alg(" xx U xx y "); | ||
| 1744 | equiv_alg[Uw2] = new_alg(" xx UU xx yy "); | ||
| 1745 | equiv_alg[Uw3] = new_alg(" xx UUU xx yyy "); | ||
| 1746 | equiv_alg[Dw] = new_alg(" U yyy "); | ||
| 1747 | equiv_alg[Dw2] = new_alg(" UU yy "); | ||
| 1748 | equiv_alg[Dw3] = new_alg(" UUU y "); | ||
| 1749 | equiv_alg[Rw] = new_alg(" yyyx U xxxy x "); | ||
| 1750 | equiv_alg[Rw2] = new_alg(" yyyx UU xxxy xx "); | ||
| 1751 | equiv_alg[Rw3] = new_alg(" yyyx UUU xxxy xxx "); | ||
| 1752 | equiv_alg[Lw] = new_alg(" yx U xxxyyy xxx "); | ||
| 1753 | equiv_alg[Lw2] = new_alg(" yx UU xxxyyy xx "); | ||
| 1754 | equiv_alg[Lw3] = new_alg(" yx UUU xxxyyy x "); | ||
| 1755 | equiv_alg[Fw] = new_alg(" xxx U x yxxxyyy "); | ||
| 1756 | equiv_alg[Fw2] = new_alg(" xxx UU x yxxyyy "); | ||
| 1757 | equiv_alg[Fw3] = new_alg(" xxx UUU x yxyyy "); | ||
| 1758 | equiv_alg[Bw] = new_alg(" x U xxx yxyyy "); | ||
| 1759 | equiv_alg[Bw2] = new_alg(" x UU xxx yxxyyy "); | ||
| 1760 | equiv_alg[Bw3] = new_alg(" x UUU xxx yxxxyyy "); | ||
| 1761 | |||
| 1762 | equiv_alg[M] = new_alg(" yx U xx UUU yxyyy "); | ||
| 1763 | equiv_alg[M2] = new_alg(" yx UU xx UU xxxy "); | ||
| 1764 | equiv_alg[M3] = new_alg(" yx UUU xx U yxxxy "); | ||
| 1765 | equiv_alg[S] = new_alg(" x UUU xx U yyyx "); | ||
| 1766 | equiv_alg[S2] = new_alg(" x UU xx UU yyx "); | ||
| 1767 | equiv_alg[S3] = new_alg(" x U xx UUU yx "); | ||
| 1768 | equiv_alg[E] = new_alg(" U xx UUU xxyyy "); | ||
| 1769 | equiv_alg[E2] = new_alg(" UU xx UU xxyy "); | ||
| 1770 | equiv_alg[E3] = new_alg(" UUU xx U xxy "); | ||
| 1771 | |||
| 1772 | equiv_alg[x] = new_alg(" x "); | ||
| 1773 | equiv_alg[x2] = new_alg(" xx "); | ||
| 1774 | equiv_alg[x3] = new_alg(" xxx "); | ||
| 1775 | equiv_alg[y] = new_alg(" y "); | ||
| 1776 | equiv_alg[y2] = new_alg(" yy "); | ||
| 1777 | equiv_alg[y3] = new_alg(" yyy "); | ||
| 1778 | equiv_alg[z] = new_alg(" yyy x y "); | ||
| 1779 | equiv_alg[z2] = new_alg(" yy xx "); | ||
| 1780 | equiv_alg[z3] = new_alg(" y x yyy "); | ||
| 1781 | } | ||
| 1782 | |||
| 1783 | static void | ||
| 1784 | init_steps() | ||
| 1785 | { | ||
| 1786 | /* PruneData */ | ||
| 1787 | pd_eofb_HTM.filename = "ptable_eofb_HTM"; | ||
| 1788 | pd_eofb_HTM.size = POW2TO11; | ||
| 1789 | pd_eofb_HTM.index = index_eofb; | ||
| 1790 | pd_eofb_HTM.moveset = moveset_HTM; | ||
| 1791 | |||
| 1792 | pd_coud_HTM.filename = "ptable_coud_HTM"; | ||
| 1793 | pd_coud_HTM.size = POW3TO7; | ||
| 1794 | pd_coud_HTM.index = index_coud; | ||
| 1795 | pd_coud_HTM.moveset = moveset_HTM; | ||
| 1796 | |||
| 1797 | pd_corners_HTM.filename = "ptable_corners_HTM"; | ||
| 1798 | pd_corners_HTM.size = POW3TO7 * FACTORIAL8; | ||
| 1799 | pd_corners_HTM.index = index_corners; | ||
| 1800 | pd_corners_HTM.moveset = moveset_HTM; | ||
| 1801 | |||
| 1802 | pd_ep_HTM.filename = "ptable_ep_HTM"; | ||
| 1803 | pd_ep_HTM.size = FACTORIAL12; | ||
| 1804 | pd_ep_HTM.index = index_ep; | ||
| 1805 | pd_ep_HTM.moveset = moveset_HTM; | ||
| 1806 | |||
| 1807 | pd_drud_HTM.filename = "ptable_drud_HTM"; | ||
| 1808 | pd_drud_HTM.size = POW2TO11 * POW3TO7 * BINOM12ON4; | ||
| 1809 | pd_drud_HTM.index = index_drud; | ||
| 1810 | pd_drud_HTM.moveset = moveset_HTM; | ||
| 1811 | |||
| 1812 | |||
| 1813 | /* Actual steps */ | ||
| 1814 | eofb_HTM.check = check_eofb_HTM; | ||
| 1815 | eofb_HTM.ready = check_nothing; | ||
| 1816 | eofb_HTM.pre_trans = uf; | ||
| 1817 | eofb_HTM.moveset = moveset_HTM; | ||
| 1818 | |||
| 1819 | eorl_HTM.check = check_eofb_HTM; | ||
| 1820 | eorl_HTM.ready = check_nothing; | ||
| 1821 | eorl_HTM.pre_trans = ur; | ||
| 1822 | eorl_HTM.moveset = moveset_HTM; | ||
| 1823 | |||
| 1824 | eoud_HTM.check = check_eofb_HTM; | ||
| 1825 | eoud_HTM.ready = check_nothing; | ||
| 1826 | eoud_HTM.pre_trans = bu; | ||
| 1827 | eoud_HTM.moveset = moveset_HTM; | ||
| 1828 | |||
| 1829 | |||
| 1830 | coud_HTM.check = check_coud_HTM; | ||
| 1831 | coud_HTM.ready = check_nothing; | ||
| 1832 | coud_HTM.pre_trans = uf; | ||
| 1833 | coud_HTM.moveset = moveset_HTM; | ||
| 1834 | |||
| 1835 | corl_HTM.check = check_coud_HTM; | ||
| 1836 | corl_HTM.ready = check_nothing; | ||
| 1837 | corl_HTM.pre_trans = rf; | ||
| 1838 | corl_HTM.moveset = moveset_HTM; | ||
| 1839 | |||
| 1840 | cofb_HTM.check = check_coud_HTM; | ||
| 1841 | cofb_HTM.ready = check_nothing; | ||
| 1842 | cofb_HTM.pre_trans = fd; | ||
| 1843 | cofb_HTM.moveset = moveset_HTM; | ||
| 1844 | |||
| 1845 | coud_URF.check = check_coud_URF; | ||
| 1846 | coud_URF.ready = check_nothing; | ||
| 1847 | coud_URF.pre_trans = uf; | ||
| 1848 | coud_URF.moveset = moveset_URF; | ||
| 1849 | |||
| 1850 | corl_URF.check = check_coud_URF; | ||
| 1851 | corl_URF.ready = check_nothing; | ||
| 1852 | corl_URF.pre_trans = rf; | ||
| 1853 | corl_URF.moveset = moveset_URF; | ||
| 1854 | |||
| 1855 | cofb_URF.check = check_coud_URF; | ||
| 1856 | cofb_URF.ready = check_nothing; | ||
| 1857 | cofb_URF.pre_trans = fd; | ||
| 1858 | cofb_URF.moveset = moveset_URF; | ||
| 1859 | |||
| 1860 | corners_HTM.check = check_corners_HTM; | ||
| 1861 | corners_HTM.ready = check_nothing; | ||
| 1862 | corners_HTM.pre_trans = uf; | ||
| 1863 | corners_HTM.moveset = moveset_HTM; | ||
| 1864 | |||
| 1865 | corners_URF.check = check_corners_URF; | ||
| 1866 | corners_URF.ready = check_nothing; | ||
| 1867 | corners_URF.pre_trans = uf; | ||
| 1868 | corners_URF.moveset = moveset_URF; | ||
| 1869 | |||
| 1870 | edges_HTM.check = check_edges_HTM; | ||
| 1871 | edges_HTM.ready = check_nothing; | ||
| 1872 | edges_HTM.pre_trans = uf; | ||
| 1873 | edges_HTM.moveset = moveset_HTM; | ||
| 1874 | |||
| 1875 | drud_HTM.check = check_drud_HTM; | ||
| 1876 | drud_HTM.ready = check_nothing; | ||
| 1877 | drud_HTM.pre_trans = uf; | ||
| 1878 | drud_HTM.moveset = moveset_HTM; | ||
| 1879 | |||
| 1880 | optimal_HTM.check = check_optimal_HTM; | ||
| 1881 | optimal_HTM.ready = check_nothing; | ||
| 1882 | optimal_HTM.pre_trans = uf; | ||
| 1883 | optimal_HTM.moveset = moveset_HTM; | ||
| 1884 | } | ||
| 1885 | |||
| 1886 | static void | ||
| 1887 | init_strings() | ||
| 1888 | { | ||
| 1889 | strcpy(move_string [NULLMOVE], "-" ); | ||
| 1890 | strcpy(move_string [U], "U" ); | ||
| 1891 | strcpy(move_string [U2], "U2" ); | ||
| 1892 | strcpy(move_string [U3], "U\'" ); | ||
| 1893 | strcpy(move_string [D], "D" ); | ||
| 1894 | strcpy(move_string [D2], "D2" ); | ||
| 1895 | strcpy(move_string [D3], "D\'" ); | ||
| 1896 | strcpy(move_string [R], "R" ); | ||
| 1897 | strcpy(move_string [R2], "R2" ); | ||
| 1898 | strcpy(move_string [R3], "R\'" ); | ||
| 1899 | strcpy(move_string [L], "L" ); | ||
| 1900 | strcpy(move_string [L2], "L2" ); | ||
| 1901 | strcpy(move_string [L3], "L\'" ); | ||
| 1902 | strcpy(move_string [F], "F" ); | ||
| 1903 | strcpy(move_string [F2], "F2" ); | ||
| 1904 | strcpy(move_string [F3], "F\'" ); | ||
| 1905 | strcpy(move_string [B], "B" ); | ||
| 1906 | strcpy(move_string [B2], "B2" ); | ||
| 1907 | strcpy(move_string [B3], "B\'" ); | ||
| 1908 | strcpy(move_string [Uw], "Uw" ); | ||
| 1909 | strcpy(move_string [Uw2], "Uw2" ); | ||
| 1910 | strcpy(move_string [Uw3], "Uw\'" ); | ||
| 1911 | strcpy(move_string [Dw], "Dw" ); | ||
| 1912 | strcpy(move_string [Dw2], "Dw2" ); | ||
| 1913 | strcpy(move_string [Dw3], "Dw\'" ); | ||
| 1914 | strcpy(move_string [Rw], "Rw" ); | ||
| 1915 | strcpy(move_string [Rw2], "Rw2" ); | ||
| 1916 | strcpy(move_string [Rw3], "Rw\'" ); | ||
| 1917 | strcpy(move_string [Lw], "Lw" ); | ||
| 1918 | strcpy(move_string [Lw2], "Lw2" ); | ||
| 1919 | strcpy(move_string [Lw3], "Lw\'" ); | ||
| 1920 | strcpy(move_string [Fw], "Fw" ); | ||
| 1921 | strcpy(move_string [Fw2], "Fw2" ); | ||
| 1922 | strcpy(move_string [Fw3], "Fw\'" ); | ||
| 1923 | strcpy(move_string [Bw], "Bw" ); | ||
| 1924 | strcpy(move_string [Bw2], "Bw2" ); | ||
| 1925 | strcpy(move_string [Bw3], "Bw\'" ); | ||
| 1926 | strcpy(move_string [M], "M" ); | ||
| 1927 | strcpy(move_string [M2], "M2" ); | ||
| 1928 | strcpy(move_string [M3], "M\'" ); | ||
| 1929 | strcpy(move_string [S], "S" ); | ||
| 1930 | strcpy(move_string [S2], "S2" ); | ||
| 1931 | strcpy(move_string [S3], "S\'" ); | ||
| 1932 | strcpy(move_string [E], "E" ); | ||
| 1933 | strcpy(move_string [E2], "E2" ); | ||
| 1934 | strcpy(move_string [E3], "E\'" ); | ||
| 1935 | strcpy(move_string [x], "x" ); | ||
| 1936 | strcpy(move_string [x2], "x2" ); | ||
| 1937 | strcpy(move_string [x3], "x\'" ); | ||
| 1938 | strcpy(move_string [y], "y" ); | ||
| 1939 | strcpy(move_string [y2], "y2" ); | ||
| 1940 | strcpy(move_string [y3], "y\'" ); | ||
| 1941 | strcpy(move_string [z], "z" ); | ||
| 1942 | strcpy(move_string [z2], "z2" ); | ||
| 1943 | strcpy(move_string [z3], "z\'" ); | ||
| 1944 | |||
| 1945 | strcpy(edge_string [UF], "UF" ); | ||
| 1946 | strcpy(edge_string [UL], "UL" ); | ||
| 1947 | strcpy(edge_string [UB], "UB" ); | ||
| 1948 | strcpy(edge_string [UR], "UR" ); | ||
| 1949 | strcpy(edge_string [DF], "DF" ); | ||
| 1950 | strcpy(edge_string [DL], "DL" ); | ||
| 1951 | strcpy(edge_string [DB], "DB" ); | ||
| 1952 | strcpy(edge_string [DR], "DR" ); | ||
| 1953 | strcpy(edge_string [FR], "FR" ); | ||
| 1954 | strcpy(edge_string [FL], "FL" ); | ||
| 1955 | strcpy(edge_string [BL], "BL" ); | ||
| 1956 | strcpy(edge_string [BR], "BR" ); | ||
| 1957 | |||
| 1958 | strcpy(corner_string [UFR], "UFR" ); | ||
| 1959 | strcpy(corner_string [UFL], "UFL" ); | ||
| 1960 | strcpy(corner_string [UBL], "UBL" ); | ||
| 1961 | strcpy(corner_string [UBR], "UBR" ); | ||
| 1962 | strcpy(corner_string [DFR], "DFR" ); | ||
| 1963 | strcpy(corner_string [DFL], "DFL" ); | ||
| 1964 | strcpy(corner_string [DBL], "DBL" ); | ||
| 1965 | strcpy(corner_string [DBR], "DBR" ); | ||
| 1966 | |||
| 1967 | strcpy(center_string [U_center], "U" ); | ||
| 1968 | strcpy(center_string [D_center], "D" ); | ||
| 1969 | strcpy(center_string [R_center], "R" ); | ||
| 1970 | strcpy(center_string [L_center], "L" ); | ||
| 1971 | strcpy(center_string [F_center], "F" ); | ||
| 1972 | strcpy(center_string [B_center], "B" ); | ||
| 1973 | } | ||
| 1974 | |||
| 1975 | static void | ||
| 1976 | init_trans() { | ||
| 1977 | Cube aux, cube, c[3]; | ||
| 1978 | CubeArray epcp; | ||
| 1979 | int eparr[12], eoarr[12]; | ||
| 1980 | int cparr[8], coarr[8]; | ||
| 1981 | int i; | ||
| 1982 | bool b1, b2, b3; | ||
| 1983 | uint16_t ui; | ||
| 1984 | Move mi, move; | ||
| 1985 | Trans m; | ||
| 1986 | |||
| 1987 | /* Compute sources */ | ||
| 1988 | for (i = 0; i < NTRANS; i++) { | ||
| 1989 | if (i == mirror) | ||
| 1990 | cube = (Cube){0}; | ||
| 1991 | else | ||
| 1992 | cube = apply_alg(trans_algs[i], (Cube){0}); | ||
| 1993 | |||
| 1994 | epose_source[i] = edge_slice(edge_at(cube, FR)); | ||
| 1995 | eposs_source[i] = edge_slice(edge_at(cube, UR)); | ||
| 1996 | eposm_source[i] = edge_slice(edge_at(cube, UF)); | ||
| 1997 | eofb_source[i] = center_at(cube, F_center)/2; | ||
| 1998 | eorl_source[i] = center_at(cube, R_center)/2; | ||
| 1999 | eoud_source[i] = center_at(cube, U_center)/2; | ||
| 2000 | coud_source[i] = center_at(cube, U_center)/2; | ||
| 2001 | cofb_source[i] = center_at(cube, F_center)/2; | ||
| 2002 | corl_source[i] = center_at(cube, R_center)/2; | ||
| 2003 | } | ||
| 2004 | |||
| 2005 | if (read_ttables_file()) | ||
| 2006 | return; | ||
| 2007 | |||
| 2008 | fprintf(stderr, "Cannot load %s, generating it\n", "ttables"); | ||
| 2009 | |||
| 2010 | /* Initialize tables */ | ||
| 2011 | for (m = 0; m < NTRANS; m++) { | ||
| 2012 | if (m == mirror) { | ||
| 2013 | memcpy(eparr, ep_mirror, 12 * sizeof(int)); | ||
| 2014 | memcpy(cparr, cp_mirror, 8 * sizeof(int)); | ||
| 2015 | } else { | ||
| 2016 | epcp = (CubeArray){ .ep = eparr, .cp = cparr }; | ||
| 2017 | cube = apply_alg(trans_algs[m], (Cube){0}); | ||
| 2018 | cube_to_arrays(cube, &epcp, pf_epcp); | ||
| 2019 | } | ||
| 2020 | |||
| 2021 | for (ui = 0; ui < FACTORIAL12/FACTORIAL8; ui++) { | ||
| 2022 | c[0] = admissible_ep((Cube){ .epose = ui }, pf_e); | ||
| 2023 | c[1] = admissible_ep((Cube){ .eposs = ui }, pf_s); | ||
| 2024 | c[2] = admissible_ep((Cube){ .eposm = ui }, pf_m); | ||
| 2025 | |||
| 2026 | cube = rotate_via_compose(m,c[epose_source[m]],pf_ep); | ||
| 2027 | epose_ttable[m][ui] = cube.epose; | ||
| 2028 | |||
| 2029 | cube = rotate_via_compose(m,c[eposs_source[m]],pf_ep); | ||
| 2030 | eposs_ttable[m][ui] = cube.eposs; | ||
| 2031 | |||
| 2032 | cube = rotate_via_compose(m,c[eposm_source[m]],pf_ep); | ||
| 2033 | eposm_ttable[m][ui] = cube.eposm; | ||
| 2034 | } | ||
| 2035 | for (ui = 0; ui < POW2TO11; ui++ ) { | ||
| 2036 | int_to_sum_zero_array(ui, 2, 12, eoarr); | ||
| 2037 | apply_permutation(eparr, eoarr, 12); | ||
| 2038 | eo_ttable[m][ui] = digit_array_to_int(eoarr, 11, 2); | ||
| 2039 | } | ||
| 2040 | for (ui = 0; ui < POW3TO7; ui++) { | ||
| 2041 | int_to_sum_zero_array(ui, 3, 8, coarr); | ||
| 2042 | apply_permutation(cparr, coarr, 8); | ||
| 2043 | co_ttable[m][ui] = digit_array_to_int(coarr, 7, 3); | ||
| 2044 | if (m == mirror) | ||
| 2045 | co_ttable[m][ui] = | ||
| 2046 | invert_digits(co_ttable[m][ui], 3, 7); | ||
| 2047 | } | ||
| 2048 | for (ui = 0; ui < FACTORIAL8; ui++) { | ||
| 2049 | cube = (Cube){ .cp = ui }; | ||
| 2050 | cube = rotate_via_compose(m, cube, pf_cp); | ||
| 2051 | cp_ttable[m][ui] = cube.cp; | ||
| 2052 | } | ||
| 2053 | for (ui = 0; ui < FACTORIAL6; ui++) { | ||
| 2054 | cube = (Cube){ .cpos = ui }; | ||
| 2055 | cube = rotate_via_compose(m, cube, pf_cpos); | ||
| 2056 | cpos_ttable[m][ui] = cube.cpos; | ||
| 2057 | } | ||
| 2058 | for (mi = 0; mi < NMOVES; mi++) { | ||
| 2059 | if (m == mirror) { | ||
| 2060 | b1 = (mi >= U && mi <= Bw3); | ||
| 2061 | b2 = (mi >= S && mi <= E3); | ||
| 2062 | b3 = (mi >= x && mi <= z3); | ||
| 2063 | if (b1 || b2 || b3) | ||
| 2064 | moves_ttable[m][mi] = | ||
| 2065 | inverse_move_aux[mi]; | ||
| 2066 | else | ||
| 2067 | moves_ttable[m][mi] = mi; | ||
| 2068 | |||
| 2069 | if ((mi-1)/3==(R-1)/3 || (mi-1)/3==(Rw-1)/3) | ||
| 2070 | moves_ttable[m][mi] += 3; | ||
| 2071 | if ((mi-1)/3==(L-1)/3 || (mi-1)/3==(L2-1)/3) | ||
| 2072 | moves_ttable[m][mi] -= 3; | ||
| 2073 | } else { | ||
| 2074 | aux = apply_trans(m, apply_move(mi,(Cube){0})); | ||
| 2075 | for (move = 0; move < NMOVES; move++) { | ||
| 2076 | cube = apply_move( | ||
| 2077 | inverse_move_aux[move], aux); | ||
| 2078 | if (is_solved(cube, false)) | ||
| 2079 | moves_ttable[m][mi] = move; | ||
| 2080 | } | ||
| 2081 | } | ||
| 2082 | } | ||
| 2083 | } | ||
| 2084 | |||
| 2085 | if (!write_ttables_file()) | ||
| 2086 | fprintf(stderr, "Error writing ttables\n"); | ||
| 2087 | } | ||
| 2088 | |||
| 2089 | static void | ||
| 2090 | init_trans_aux() | ||
| 2091 | { | ||
| 2092 | ep_mirror[UF] = UF; | ||
| 2093 | ep_mirror[UL] = UR; | ||
| 2094 | ep_mirror[UB] = UB; | ||
| 2095 | ep_mirror[UR] = UL; | ||
| 2096 | ep_mirror[DF] = DF; | ||
| 2097 | ep_mirror[DL] = DR; | ||
| 2098 | ep_mirror[DB] = DB; | ||
| 2099 | ep_mirror[DR] = DL; | ||
| 2100 | ep_mirror[FR] = FL; | ||
| 2101 | ep_mirror[FL] = FR; | ||
| 2102 | ep_mirror[BR] = BL; | ||
| 2103 | ep_mirror[BL] = BR; | ||
| 2104 | |||
| 2105 | cp_mirror[UFR] = UFL; | ||
| 2106 | cp_mirror[UFL] = UFR; | ||
| 2107 | cp_mirror[UBL] = UBR; | ||
| 2108 | cp_mirror[UBR] = UBL; | ||
| 2109 | cp_mirror[DFR] = DFL; | ||
| 2110 | cp_mirror[DFL] = DFR; | ||
| 2111 | cp_mirror[DBL] = DBR; | ||
| 2112 | cp_mirror[DBR] = DBL; | ||
| 2113 | |||
| 2114 | cpos_mirror[U_center] = U_center; | ||
| 2115 | cpos_mirror[D_center] = D_center; | ||
| 2116 | cpos_mirror[R_center] = L_center; | ||
| 2117 | cpos_mirror[L_center] = R_center; | ||
| 2118 | cpos_mirror[F_center] = F_center; | ||
| 2119 | cpos_mirror[B_center] = B_center; | ||
| 2120 | |||
| 2121 | /* Is there a more elegant way? */ | ||
| 2122 | trans_algs[uf] = new_alg(""); | ||
| 2123 | trans_algs[ur] = new_alg("y"); | ||
| 2124 | trans_algs[ub] = new_alg("y2"); | ||
| 2125 | trans_algs[ul] = new_alg("y3"); | ||
| 2126 | |||
| 2127 | trans_algs[df] = new_alg("z2"); | ||
| 2128 | trans_algs[dr] = new_alg("y z2"); | ||
| 2129 | trans_algs[db] = new_alg("x2"); | ||
| 2130 | trans_algs[dl] = new_alg("y3 z2"); | ||
| 2131 | |||
| 2132 | trans_algs[rf] = new_alg("z3"); | ||
| 2133 | trans_algs[rd] = new_alg("z3 y"); | ||
| 2134 | trans_algs[rb] = new_alg("z3 y2"); | ||
| 2135 | trans_algs[ru] = new_alg("z3 y3"); | ||
| 2136 | |||
| 2137 | trans_algs[lf] = new_alg("z"); | ||
| 2138 | trans_algs[ld] = new_alg("z y3"); | ||
| 2139 | trans_algs[lb] = new_alg("z y2"); | ||
| 2140 | trans_algs[lu] = new_alg("z y"); | ||
| 2141 | |||
| 2142 | trans_algs[fu] = new_alg("x y2"); | ||
| 2143 | trans_algs[fr] = new_alg("x y"); | ||
| 2144 | trans_algs[fd] = new_alg("x"); | ||
| 2145 | trans_algs[fl] = new_alg("x y3"); | ||
| 2146 | |||
| 2147 | trans_algs[bu] = new_alg("x3"); | ||
| 2148 | trans_algs[br] = new_alg("x3 y"); | ||
| 2149 | trans_algs[bd] = new_alg("x3 y2"); | ||
| 2150 | trans_algs[bl] = new_alg("x3 y3"); | ||
| 2151 | } | ||
| 2152 | |||
| 2153 | /* Linearization functions implementation ************************************/ | ||
| 2154 | |||
| 2155 | static uint64_t | ||
| 2156 | index_eofb(Cube cube) | ||
| 2157 | { | ||
| 2158 | return cube.eofb; | ||
| 2159 | } | ||
| 2160 | |||
| 2161 | static uint64_t | ||
| 2162 | index_coud(Cube cube) | ||
| 2163 | { | ||
| 2164 | return cube.coud; | ||
| 2165 | } | ||
| 2166 | |||
| 2167 | static uint64_t | ||
| 2168 | index_corners(Cube cube) | ||
| 2169 | { | ||
| 2170 | return cube.coud * FACTORIAL8 + cube.cp; | ||
| 2171 | } | ||
| 2172 | |||
| 2173 | static uint64_t | ||
| 2174 | index_ep(Cube cube) | ||
| 2175 | { | ||
| 2176 | uint64_t a, b, c; | ||
| 2177 | |||
| 2178 | /* TODO: remove this check */ | ||
| 2179 | if (epos_dependent_aux[cube.eposs/FACTORIAL4][cube.epose/FACTORIAL4] ==BINOM8ON4) | ||
| 2180 | fprintf(stderr, "Impossible\n"); | ||
| 2181 | |||
| 2182 | a = cube.eposs; | ||
| 2183 | b = (cube.epose % FACTORIAL4) + | ||
| 2184 | epos_dependent_aux[cube.eposs/FACTORIAL4][cube.epose/FACTORIAL4] * | ||
| 2185 | FACTORIAL4; | ||
| 2186 | c = cube.eposm % FACTORIAL4; | ||
| 2187 | |||
| 2188 | b *= FACTORIAL4 * BINOM12ON4; | ||
| 2189 | c *= FACTORIAL4 * BINOM12ON4 * FACTORIAL4 * BINOM8ON4; | ||
| 2190 | |||
| 2191 | return a + b + c; | ||
| 2192 | } | ||
| 2193 | |||
| 2194 | static uint64_t | ||
| 2195 | index_drud(Cube cube) | ||
| 2196 | { | ||
| 2197 | uint64_t a, b, c; | ||
| 2198 | |||
| 2199 | a = cube.eofb; | ||
| 2200 | b = cube.coud; | ||
| 2201 | c = cube.epose / FACTORIAL4; | ||
| 2202 | |||
| 2203 | b *= POW2TO11; | ||
| 2204 | c *= POW2TO11 * POW3TO7; | ||
| 2205 | |||
| 2206 | return a + b + c; | ||
| 2207 | } | ||
| 2208 | |||
| 2209 | /* Step checking functions implementation ************************************/ | ||
| 2210 | |||
| 2211 | static int | ||
| 2212 | check_nothing(Cube cube) | ||
| 2213 | { | ||
| 2214 | return true; | ||
| 2215 | } | ||
| 2216 | |||
| 2217 | static int | ||
| 2218 | check_eofb_HTM(Cube cube) | ||
| 2219 | { | ||
| 2220 | if (!pd_eofb_HTM.generated) | ||
| 2221 | generate_ptable(&pd_eofb_HTM); | ||
| 2222 | |||
| 2223 | return PTABLEVAL(pd_eofb_HTM.ptable, cube.eofb); | ||
| 2224 | } | ||
| 2225 | |||
| 2226 | static int | ||
| 2227 | check_coud_HTM(Cube cube) | ||
| 2228 | { | ||
| 2229 | if (!pd_coud_HTM.generated) | ||
| 2230 | generate_ptable(&pd_coud_HTM); | ||
| 2231 | |||
| 2232 | return PTABLEVAL(pd_coud_HTM.ptable, cube.coud); | ||
| 2233 | } | ||
| 2234 | |||
| 2235 | static int | ||
| 2236 | check_coud_URF(Cube cube) | ||
| 2237 | { | ||
| 2238 | /* TODO: I can improve this by checking first the orientation of | ||
| 2239 | * the corner in DBL and use that as a reference */ | ||
| 2240 | |||
| 2241 | int ud = check_coud_HTM(cube); | ||
| 2242 | int rl = check_coud_HTM(apply_move(z, cube)); | ||
| 2243 | int fb = check_coud_HTM(apply_move(x, cube)); | ||
| 2244 | |||
| 2245 | return MIN(ud, MIN(rl, fb)); | ||
| 2246 | } | ||
| 2247 | |||
| 2248 | static int | ||
| 2249 | check_corners_HTM(Cube cube) | ||
| 2250 | { | ||
| 2251 | if (!pd_corners_HTM.generated) | ||
| 2252 | generate_ptable(&pd_corners_HTM); | ||
| 2253 | |||
| 2254 | return PTABLEVAL(pd_corners_HTM.ptable, index_corners(cube)); | ||
| 2255 | } | ||
| 2256 | |||
| 2257 | static int | ||
| 2258 | check_corners_URF(Cube cube) | ||
| 2259 | { | ||
| 2260 | /* TODO: I can improve this by checking first the corner in DBL | ||
| 2261 | * and use that as a reference */ | ||
| 2262 | |||
| 2263 | int ret = 15; | ||
| 2264 | Cube c; | ||
| 2265 | Trans i; | ||
| 2266 | |||
| 2267 | for (i = 0; i < NROTATIONS; i++) { | ||
| 2268 | c = apply_alg(trans_algs[i], cube); | ||
| 2269 | ret = MIN(ret, check_corners_HTM(c)); | ||
| 2270 | } | ||
| 2271 | |||
| 2272 | return ret; | ||
| 2273 | } | ||
| 2274 | |||
| 2275 | static int | ||
| 2276 | check_edges_HTM(Cube cube) | ||
| 2277 | { | ||
| 2278 | int ret = 0; | ||
| 2279 | |||
| 2280 | if (!pd_ep_HTM.generated) | ||
| 2281 | generate_ptable(&pd_ep_HTM); | ||
| 2282 | |||
| 2283 | ret = MAX(ret, PTABLEVAL(pd_ep_HTM.ptable, index_ep(cube))); | ||
| 2284 | ret = MAX(ret, check_eofb_HTM(cube)); | ||
| 2285 | ret = MAX(ret, check_eofb_HTM(apply_trans(ur, cube))); | ||
| 2286 | ret = MAX(ret, check_eofb_HTM(apply_trans(fd, cube))); | ||
| 2287 | |||
| 2288 | return ret; | ||
| 2289 | } | ||
| 2290 | |||
| 2291 | static int | ||
| 2292 | check_drud_HTM(Cube cube) | ||
| 2293 | { | ||
| 2294 | if (!pd_drud_HTM.generated) | ||
| 2295 | generate_ptable(&pd_drud_HTM); | ||
| 2296 | |||
| 2297 | return PTABLEVAL(pd_drud_HTM.ptable, index_drud(cube)); | ||
| 2298 | } | ||
| 2299 | |||
| 2300 | static int | ||
| 2301 | check_optimal_HTM(Cube cube) | ||
| 2302 | { | ||
| 2303 | int dr1, dr2, dr3, drmax, cor; /*ep;*/ | ||
| 2304 | |||
| 2305 | if (!pd_drud_HTM.generated) | ||
| 2306 | generate_ptable(&pd_drud_HTM); | ||
| 2307 | if (!pd_corners_HTM.generated) | ||
| 2308 | generate_ptable(&pd_corners_HTM); | ||
| 2309 | /* | ||
| 2310 | *if (!pd_ep_HTM.generated) | ||
| 2311 | * generate_ptable(&pd_ep_HTM); | ||
| 2312 | */ | ||
| 2313 | |||
| 2314 | dr1 = PTABLEVAL(pd_drud_HTM.ptable, index_drud(cube)); | ||
| 2315 | dr2 = PTABLEVAL(pd_drud_HTM.ptable, index_drud(apply_trans(rf, cube))); | ||
| 2316 | dr3 = PTABLEVAL(pd_drud_HTM.ptable, index_drud(apply_trans(fd, cube))); | ||
| 2317 | |||
| 2318 | drmax = MAX(dr1, MAX(dr2, dr3)); | ||
| 2319 | if (dr1 == dr2 && dr2 == dr3 && dr1 != 0) | ||
| 2320 | drmax++; | ||
| 2321 | |||
| 2322 | cor = PTABLEVAL(pd_corners_HTM.ptable, index_corners(cube)); | ||
| 2323 | /* ep = PTABLEVAL(pd_ep_HTM.ptable, index_ep(cube)); */ | ||
| 2324 | |||
| 2325 | /*return MAX(drmax, MAX(ep, cor));*/ | ||
| 2326 | if (drmax == 0 && cor == 0) | ||
| 2327 | return is_solved(cube, false) ? 0 : 1; | ||
| 2328 | return MAX(drmax, cor); | ||
| 2329 | } | ||
| 2330 | |||
| 2331 | |||
| 2332 | /* Movesets ******************************************************************/ | ||
| 2333 | |||
| 2334 | bool | ||
| 2335 | moveset_HTM(Move m) | ||
| 2336 | { | ||
| 2337 | return m >= U && m <= B3; | ||
| 2338 | } | ||
| 2339 | |||
| 2340 | bool | ||
| 2341 | moveset_URF(Move m) | ||
| 2342 | { | ||
| 2343 | Move b = base_move(m); | ||
| 2344 | |||
| 2345 | return b == U || b == R || b == F; | ||
| 2346 | } | ||
| 2347 | |||
| 2348 | |||
| 2349 | /* Public functions implementation *******************************************/ | ||
| 2350 | |||
| 2351 | Cube | ||
| 2352 | apply_alg(Alg *alg, Cube cube) | ||
| 2353 | { | ||
| 2354 | return apply_alg_generic(alg, cube, pf_all, true); | ||
| 2355 | } | ||
| 2356 | |||
| 2357 | Cube | ||
| 2358 | apply_move(Move m, Cube cube) | ||
| 2359 | { | ||
| 2360 | Cube moved = {0}; | ||
| 2361 | |||
| 2362 | moved.epose = epose_mtable[m][cube.epose]; | ||
| 2363 | moved.eposs = eposs_mtable[m][cube.eposs]; | ||
| 2364 | moved.eposm = eposm_mtable[m][cube.eposm]; | ||
| 2365 | moved.eofb = eofb_mtable[m][cube.eofb]; | ||
| 2366 | moved.eorl = eorl_mtable[m][cube.eorl]; | ||
| 2367 | moved.eoud = eoud_mtable[m][cube.eoud]; | ||
| 2368 | moved.coud = coud_mtable[m][cube.coud]; | ||
| 2369 | moved.cofb = cofb_mtable[m][cube.cofb]; | ||
| 2370 | moved.corl = corl_mtable[m][cube.corl]; | ||
| 2371 | moved.cp = cp_mtable[m][cube.cp]; | ||
| 2372 | moved.cpos = cpos_mtable[m][cube.cpos]; | ||
| 2373 | |||
| 2374 | return moved; | ||
| 2375 | } | ||
| 2376 | |||
| 2377 | Cube | ||
| 2378 | apply_trans(Trans t, Cube cube) | ||
| 2379 | { | ||
| 2380 | Cube transformed = {0}; | ||
| 2381 | uint16_t aux_epos[3] = { cube.epose, cube.eposs, cube.eposm }; | ||
| 2382 | uint16_t aux_eo[3] = { cube.eoud, cube.eorl, cube.eofb }; | ||
| 2383 | uint16_t aux_co[3] = { cube.coud, cube.corl, cube.cofb }; | ||
| 2384 | |||
| 2385 | transformed.epose = epose_ttable[t][aux_epos[epose_source[t]]]; | ||
| 2386 | transformed.eposs = eposs_ttable[t][aux_epos[eposs_source[t]]]; | ||
| 2387 | transformed.eposm = eposm_ttable[t][aux_epos[eposm_source[t]]]; | ||
| 2388 | transformed.eofb = eo_ttable[t][aux_eo[eofb_source[t]]]; | ||
| 2389 | transformed.eorl = eo_ttable[t][aux_eo[eorl_source[t]]]; | ||
| 2390 | transformed.eoud = eo_ttable[t][aux_eo[eoud_source[t]]]; | ||
| 2391 | transformed.coud = co_ttable[t][aux_co[coud_source[t]]]; | ||
| 2392 | transformed.corl = co_ttable[t][aux_co[corl_source[t]]]; | ||
| 2393 | transformed.cofb = co_ttable[t][aux_co[cofb_source[t]]]; | ||
| 2394 | transformed.cp = cp_ttable[t][cube.cp]; | ||
| 2395 | transformed.cpos = cpos_ttable[t][cube.cpos]; | ||
| 2396 | |||
| 2397 | return transformed; | ||
| 2398 | } | ||
| 2399 | |||
| 2400 | /* TODO: this has to be changed using pre-computations */ | ||
| 2401 | bool | ||
| 2402 | block_solved(Cube cube, Block block) | ||
| 2403 | { | ||
| 2404 | CubeArray *arr = new_cubearray(cube, pf_all); | ||
| 2405 | int i; | ||
| 2406 | bool ret = true; | ||
| 2407 | |||
| 2408 | for (i = 0; i < 12; i++) | ||
| 2409 | ret = ret && !(block.edge[i] && (arr->ep[i] != i || arr->eofb[i])); | ||
| 2410 | for (i = 0; i < 8; i++) | ||
| 2411 | ret = ret && !(block.corner[i] && (arr->cp[i] != i || arr->coud[i])); | ||
| 2412 | for (i = 0; i < 6; i++) | ||
| 2413 | ret = ret && !(block.center[i] && arr->cpos[i] != i); | ||
| 2414 | |||
| 2415 | free_cubearray(arr, pf_all); | ||
| 2416 | |||
| 2417 | return ret; | ||
| 2418 | } | ||
| 2419 | |||
| 2420 | Center | ||
| 2421 | center_at(Cube cube, Center c) | ||
| 2422 | { | ||
| 2423 | int ret; | ||
| 2424 | CubeArray *arr = new_cubearray(cube, pf_cpos); | ||
| 2425 | |||
| 2426 | ret = arr->cpos[c]; | ||
| 2427 | free_cubearray(arr, pf_cpos); | ||
| 2428 | |||
| 2429 | return ret; | ||
| 2430 | } | ||
| 2431 | |||
| 2432 | Cube | ||
| 2433 | compose(Cube c2, Cube c1) | ||
| 2434 | { | ||
| 2435 | return compose_filtered(c2, c1, pf_all); | ||
| 2436 | } | ||
| 2437 | |||
| 2438 | Corner | ||
| 2439 | corner_at(Cube cube, Corner c) | ||
| 2440 | { | ||
| 2441 | int ret; | ||
| 2442 | CubeArray *arr = new_cubearray(cube, pf_cp); | ||
| 2443 | |||
| 2444 | ret = arr->cp[c]; | ||
| 2445 | free_cubearray(arr, pf_cp); | ||
| 2446 | |||
| 2447 | return ret; | ||
| 2448 | } | ||
| 2449 | |||
| 2450 | Edge | ||
| 2451 | edge_at(Cube cube, Edge e) | ||
| 2452 | { | ||
| 2453 | int ret; | ||
| 2454 | CubeArray *arr = new_cubearray(cube, pf_ep); | ||
| 2455 | |||
| 2456 | ret = arr->ep[e]; | ||
| 2457 | free_cubearray(arr, pf_ep); | ||
| 2458 | |||
| 2459 | return ret; | ||
| 2460 | } | ||
| 2461 | |||
| 2462 | bool | ||
| 2463 | equal(Cube c1, Cube c2) | ||
| 2464 | { | ||
| 2465 | return c1.eofb == c2.eofb && | ||
| 2466 | c1.epose == c2.epose && | ||
| 2467 | c1.eposs == c2.eposs && | ||
| 2468 | c1.eposm == c2.eposm && | ||
| 2469 | c1.coud == c2.coud && | ||
| 2470 | c1.cp == c2.cp && | ||
| 2471 | c1.cpos == c2.cpos; | ||
| 2472 | } | ||
| 2473 | |||
| 2474 | Cube | ||
| 2475 | inverse_cube(Cube cube) | ||
| 2476 | { | ||
| 2477 | CubeArray *arr = new_cubearray(cube, pf_all); | ||
| 2478 | CubeArray *inv = new_cubearray((Cube){0}, pf_all); | ||
| 2479 | Cube ret; | ||
| 2480 | int i; | ||
| 2481 | |||
| 2482 | for (i = 0; i < 12; i++) { | ||
| 2483 | inv->ep[arr->ep[i]] = i; | ||
| 2484 | inv->eofb[arr->ep[i]] = arr->eofb[i]; | ||
| 2485 | inv->eorl[arr->ep[i]] = arr->eorl[i]; | ||
| 2486 | inv->eoud[arr->ep[i]] = arr->eoud[i]; | ||
| 2487 | } | ||
| 2488 | |||
| 2489 | for (i = 0; i < 8; i++) { | ||
| 2490 | inv->cp[arr->cp[i]] = i; | ||
| 2491 | inv->coud[arr->cp[i]] = (3 - arr->coud[i]) % 3; | ||
| 2492 | inv->corl[arr->cp[i]] = (3 - arr->corl[i]) % 3; | ||
| 2493 | inv->cofb[arr->cp[i]] = (3 - arr->cofb[i]) % 3; | ||
| 2494 | } | ||
| 2495 | |||
| 2496 | for (int i = 0; i < 6; i++) | ||
| 2497 | inv->cpos[arr->cpos[i]] = i; | ||
| 2498 | |||
| 2499 | ret = arrays_to_cube(inv, pf_all); | ||
| 2500 | free_cubearray(arr, pf_all); | ||
| 2501 | free_cubearray(inv, pf_all); | ||
| 2502 | |||
| 2503 | return ret; | ||
| 2504 | } | ||
| 2505 | |||
| 2506 | Move | ||
| 2507 | inverse_move(Move m) | ||
| 2508 | { | ||
| 2509 | return inverse_move_aux[m]; | ||
| 2510 | } | ||
| 2511 | |||
| 2512 | Trans | ||
| 2513 | inverse_trans(Trans t) | ||
| 2514 | { | ||
| 2515 | return inverse_trans_aux[t]; | ||
| 2516 | } | ||
| 2517 | |||
| 2518 | bool | ||
| 2519 | is_admissible(Cube cube) | ||
| 2520 | { | ||
| 2521 | /* TODO: this should check consistency of different orientations */ | ||
| 2522 | /* TODO: check that centers are opposite and admissible */ | ||
| 2523 | |||
| 2524 | CubeArray *a = new_cubearray(cube, pf_all); | ||
| 2525 | int parity; | ||
| 2526 | bool perm; | ||
| 2527 | |||
| 2528 | perm = is_perm(a->ep, 12) && | ||
| 2529 | is_perm(a->cp, 8) && | ||
| 2530 | is_perm(a->cpos, 6); | ||
| 2531 | parity = perm_sign(a->ep, 12) + | ||
| 2532 | perm_sign(a->cp, 8) + | ||
| 2533 | perm_sign(a->cpos, 6); | ||
| 2534 | |||
| 2535 | return perm && parity % 2 == 0; | ||
| 2536 | } | ||
| 2537 | |||
| 2538 | bool | ||
| 2539 | is_solved(Cube cube, bool reorient) | ||
| 2540 | { | ||
| 2541 | Trans i; | ||
| 2542 | |||
| 2543 | if (reorient) | ||
| 2544 | for (i = 0; i < NROTATIONS; i++) | ||
| 2545 | if (is_solved(apply_alg(trans_algs[i],cube), false)) | ||
| 2546 | return true; | ||
| 2547 | |||
| 2548 | return equal(cube, (Cube){0}); | ||
| 2549 | } | ||
| 2550 | |||
| 2551 | int | ||
| 2552 | piece_orientation(Cube cube, int piece, char *orientation) | ||
| 2553 | { | ||
| 2554 | int arr[12], n, b; | ||
| 2555 | uint16_t x; | ||
| 2556 | |||
| 2557 | if (!strcmp(orientation, "eofb")) { | ||
| 2558 | x = cube.eofb; | ||
| 2559 | n = 12; | ||
| 2560 | b = 2; | ||
| 2561 | } else if (!strcmp(orientation, "eorl")) { | ||
| 2562 | x = cube.eorl; | ||
| 2563 | n = 12; | ||
| 2564 | b = 2; | ||
| 2565 | } else if (!strcmp(orientation, "eoud")) { | ||
| 2566 | x = cube.eoud; | ||
| 2567 | n = 12; | ||
| 2568 | b = 2; | ||
| 2569 | } else if (!strcmp(orientation, "coud")) { | ||
| 2570 | x = cube.coud; | ||
| 2571 | n = 8; | ||
| 2572 | b = 3; | ||
| 2573 | } else if (!strcmp(orientation, "corl")) { | ||
| 2574 | x = cube.corl; | ||
| 2575 | n = 8; | ||
| 2576 | b = 3; | ||
| 2577 | } else if (!strcmp(orientation, "cofb")) { | ||
| 2578 | x = cube.cofb; | ||
| 2579 | n = 8; | ||
| 2580 | b = 3; | ||
| 2581 | } else { | ||
| 2582 | return -1; | ||
| 2583 | } | ||
| 2584 | |||
| 2585 | int_to_sum_zero_array(x, b, n, arr); | ||
| 2586 | if (piece < n) | ||
| 2587 | return arr[piece]; | ||
| 2588 | |||
| 2589 | return -1; | ||
| 2590 | } | ||
| 2591 | |||
| 2592 | void | ||
| 2593 | print_cube(Cube cube) | ||
| 2594 | { | ||
| 2595 | CubeArray *arr = new_cubearray(cube, pf_all); | ||
| 2596 | |||
| 2597 | for (int i = 0; i < 12; i++) | ||
| 2598 | printf(" %s ", edge_string[arr->ep[i]]); | ||
| 2599 | printf("\n"); | ||
| 2600 | |||
| 2601 | for (int i = 0; i < 12; i++) | ||
| 2602 | printf(" %c ", arr->eofb[i] + '0'); | ||
| 2603 | printf("\n"); | ||
| 2604 | |||
| 2605 | for (int i = 0; i < 8; i++) | ||
| 2606 | printf("%s ", corner_string[arr->cp[i]]); | ||
| 2607 | printf("\n"); | ||
| 2608 | |||
| 2609 | for (int i = 0; i < 8; i++) | ||
| 2610 | printf(" %c ", arr->coud[i] + '0'); | ||
| 2611 | printf("\n"); | ||
| 2612 | |||
| 2613 | for (int i = 0; i < 6; i++) | ||
| 2614 | printf(" %s ", center_string[arr->cpos[i]]); | ||
| 2615 | printf("\n"); | ||
| 2616 | |||
| 2617 | free_cubearray(arr, pf_all); | ||
| 2618 | } | ||
| 2619 | |||
| 2620 | Cube | ||
| 2621 | random_cube() | ||
| 2622 | { | ||
| 2623 | CubeArray *arr = new_cubearray((Cube){0}, pf_4val); | ||
| 2624 | Cube ret; | ||
| 2625 | int ep, cp, eo, co; | ||
| 2626 | |||
| 2627 | ep = rand() % FACTORIAL12; | ||
| 2628 | cp = rand() % FACTORIAL8; | ||
| 2629 | eo = rand() % POW2TO11; | ||
| 2630 | co = rand() % POW3TO7; | ||
| 2631 | |||
| 2632 | index_to_perm(ep, 12, arr->ep); | ||
| 2633 | index_to_perm(cp, 8, arr->cp); | ||
| 2634 | int_to_sum_zero_array(eo, 2, 12, arr->eofb); | ||
| 2635 | int_to_sum_zero_array(co, 3, 8, arr->coud); | ||
| 2636 | |||
| 2637 | if (perm_sign(arr->ep, 12) != perm_sign(arr->cp, 8)) | ||
| 2638 | swap(&(arr->ep[0]), &(arr->ep[1])); | ||
| 2639 | |||
| 2640 | ret = arrays_to_cube(arr, pf_4val); | ||
| 2641 | free_cubearray(arr, pf_4val); | ||
| 2642 | |||
| 2643 | return ret; | ||
| 2644 | } | ||
| 2645 | |||
| 2646 | AlgList * | ||
| 2647 | solve(Cube cube, Step step, SolveOptions *opts) | ||
| 2648 | { | ||
| 2649 | AlgListNode *node; | ||
| 2650 | AlgList *sols = new_alglist(); | ||
| 2651 | Cube c = apply_trans(step.pre_trans, cube); | ||
| 2652 | DfsData dd = { | ||
| 2653 | .m = 0, | ||
| 2654 | .niss = false, | ||
| 2655 | .last1 = NULLMOVE, | ||
| 2656 | .last2 = NULLMOVE, | ||
| 2657 | .sols = sols, | ||
| 2658 | .current_alg = new_alg("") | ||
| 2659 | }; | ||
| 2660 | |||
| 2661 | if (step.ready != NULL && !step.ready(c)) | ||
| 2662 | return sols; | ||
| 2663 | |||
| 2664 | moveset_to_list(step.moveset, step.check, dd.sorted_moves); | ||
| 2665 | |||
| 2666 | for (dd.d = MAX(opts->min_moves, step.check(c)); | ||
| 2667 | dd.d <= opts->max_moves && !(sols->len && opts->optimal_only); | ||
| 2668 | dd.d++) { | ||
| 2669 | solve_dfs(c, step, opts, &dd); | ||
| 2670 | if (opts->feedback) | ||
| 2671 | fprintf(stderr, | ||
| 2672 | "Depth %d completed, found %d solutions\n", | ||
| 2673 | dd.d, sols->len); | ||
| 2674 | } | ||
| 2675 | |||
| 2676 | for (node = sols->first; node != NULL; node = node->next) | ||
| 2677 | transform_alg(inverse_trans_aux[step.pre_trans], node->alg); | ||
| 2678 | |||
| 2679 | return sols; | ||
| 2680 | } | ||
| 2681 | |||
| 2682 | Alg * | ||
| 2683 | inverse_alg(Alg *alg) | ||
| 2684 | { | ||
| 2685 | Alg *ret = new_alg(""); | ||
| 2686 | AlgNode *i; | ||
| 2687 | |||
| 2688 | for (i = alg->last; i != NULL; i = i->prev) | ||
| 2689 | append_move(ret, i->m, i->inverse); | ||
| 2690 | |||
| 2691 | return ret; | ||
| 2692 | } | ||
| 2693 | |||
| 2694 | Alg * | ||
| 2695 | new_alg(char *str) | ||
| 2696 | { | ||
| 2697 | Alg *alg = malloc(sizeof(Alg)); | ||
| 2698 | int i; | ||
| 2699 | bool niss = false; | ||
| 2700 | Move j, m; | ||
| 2701 | |||
| 2702 | alg->first = NULL; | ||
| 2703 | alg->last = NULL; | ||
| 2704 | alg->len = 0; | ||
| 2705 | |||
| 2706 | for (i = 0; str[i]; i++) { | ||
| 2707 | if (str[i] == ' ' || str[i] == '\t' || str[i] == '\n') | ||
| 2708 | continue; | ||
| 2709 | |||
| 2710 | if (str[i] == '(' && niss) { | ||
| 2711 | fprintf(stderr, "Error reading moves: nested ( )\n"); | ||
| 2712 | return alg; | ||
| 2713 | } | ||
| 2714 | |||
| 2715 | if (str[i] == ')' && !niss) { | ||
| 2716 | fprintf(stderr, "Error reading moves: unmatched )\n"); | ||
| 2717 | return alg; | ||
| 2718 | } | ||
| 2719 | |||
| 2720 | if (str[i] == '(' || str[i] == ')') { | ||
| 2721 | niss = !niss; | ||
| 2722 | continue; | ||
| 2723 | } | ||
| 2724 | |||
| 2725 | for (j = 0; j < NMOVES; j++) { | ||
| 2726 | if (str[i] == move_string[j][0]) { | ||
| 2727 | m = j; | ||
| 2728 | if (m <= B && str[i+1]=='w') { | ||
| 2729 | m += Uw - U; | ||
| 2730 | i++; | ||
| 2731 | } | ||
| 2732 | if (str[i+1]=='2') { | ||
| 2733 | m += 1; | ||
| 2734 | i++; | ||
| 2735 | } else if (str[i+1]=='\'' || str[i+1]=='3') { | ||
| 2736 | m += 2; | ||
| 2737 | i++; | ||
| 2738 | } | ||
| 2739 | append_move(alg, m, niss); | ||
| 2740 | break; | ||
| 2741 | } | ||
| 2742 | } | ||
| 2743 | } | ||
| 2744 | |||
| 2745 | return alg; | ||
| 2746 | } | ||
| 2747 | |||
| 2748 | Alg * | ||
| 2749 | on_inverse(Alg *alg) | ||
| 2750 | { | ||
| 2751 | Alg *ret = new_alg(""); | ||
| 2752 | AlgNode *i; | ||
| 2753 | |||
| 2754 | for (i = alg->first; i != NULL; i = i->next) | ||
| 2755 | append_move(ret, i->m, !i->inverse); | ||
| 2756 | |||
| 2757 | return ret; | ||
| 2758 | } | ||
| 2759 | |||
| 2760 | void | ||
| 2761 | print_alg(Alg *alg, bool l) | ||
| 2762 | { | ||
| 2763 | char fill[4]; | ||
| 2764 | AlgNode *i; | ||
| 2765 | bool niss = false; | ||
| 2766 | |||
| 2767 | for (i = alg->first; i != NULL; i = i->next) { | ||
| 2768 | if (!niss && i->inverse) | ||
| 2769 | strcpy(fill, i == alg->first ? "(" : " ("); | ||
| 2770 | if (niss && !i->inverse) | ||
| 2771 | strcpy(fill, ") "); | ||
| 2772 | if (niss == i->inverse) | ||
| 2773 | strcpy(fill, i == alg->first ? "" : " "); | ||
| 2774 | |||
| 2775 | printf("%s%s", fill, move_string[i->m]); | ||
| 2776 | niss = i->inverse; | ||
| 2777 | } | ||
| 2778 | |||
| 2779 | if (niss) | ||
| 2780 | printf(")"); | ||
| 2781 | if (l) | ||
| 2782 | printf(" (%d)", alg->len); | ||
| 2783 | |||
| 2784 | printf("\n"); | ||
| 2785 | } | ||
| 2786 | |||
| 2787 | void | ||
| 2788 | print_ptable(PruneData *pd) | ||
| 2789 | { | ||
| 2790 | uint64_t i, a[16]; | ||
| 2791 | |||
| 2792 | memset(a, 0, 16 * sizeof(uint64_t)); | ||
| 2793 | |||
| 2794 | if (!pd->generated) | ||
| 2795 | generate_ptable(pd); | ||
| 2796 | |||
| 2797 | for (i = 0; i < pd->size; i++) | ||
| 2798 | a[PTABLEVAL(pd->ptable, i)]++; | ||
| 2799 | |||
| 2800 | fprintf(stderr, "Values for table %s\n", pd->filename); | ||
| 2801 | for (i = 0; i < 16; i++) | ||
| 2802 | printf("%2lu\t%10lu\n", i, a[i]); | ||
| 2803 | } | ||
| 2804 | |||
| 2805 | void | ||
| 2806 | print_alglist(AlgList *al, bool l) | ||
| 2807 | { | ||
| 2808 | AlgListNode *i; | ||
| 2809 | |||
| 2810 | for (i = al->first; i != NULL; i = i->next) | ||
| 2811 | print_alg(i->alg, l); | ||
| 2812 | } | ||
| 2813 | |||
| 2814 | void | ||
| 2815 | remove_last_move(Alg *alg) | ||
| 2816 | { | ||
| 2817 | AlgNode *newlast = alg->last->prev; | ||
| 2818 | free(alg->last); | ||
| 2819 | if (newlast != NULL) | ||
| 2820 | newlast->next = NULL; | ||
| 2821 | alg->last = newlast; | ||
| 2822 | alg->len--; | ||
| 2823 | } | ||
| 2824 | |||
| 2825 | void | ||
| 2826 | transform_alg(Trans t, Alg *alg) | ||
| 2827 | { | ||
| 2828 | AlgNode *i; | ||
| 2829 | |||
| 2830 | for (i = alg->first; i != NULL; i = i->next) | ||
| 2831 | i->m = moves_ttable[t][i->m]; | ||
| 2832 | } | ||
| 2833 | |||
| 2834 | |||
| 2835 | void | ||
| 2836 | init() | ||
| 2837 | { | ||
| 2838 | /* Order is important! */ | ||
| 2839 | init_environment(); | ||
| 2840 | init_strings(); | ||
| 2841 | init_moves_aux(); | ||
| 2842 | init_moves(); | ||
| 2843 | init_auxtables(); | ||
| 2844 | init_trans_aux(); | ||
| 2845 | init_trans(); | ||
| 2846 | init_steps(); | ||
| 2847 | } | ||
| 2848 | |||
| 2849 | |||
diff --git a/old/2021-06-14-oldalg/cube.h b/old/2021-06-14-oldalg/cube.h new file mode 100644 index 0000000..a17c291 --- /dev/null +++ b/old/2021-06-14-oldalg/cube.h | |||
| @@ -0,0 +1,73 @@ | |||
| 1 | #ifndef CUBE_H | ||
| 2 | #define CUBE_H | ||
| 3 | |||
| 4 | #include <stdio.h> | ||
| 5 | #include <stdbool.h> | ||
| 6 | #include <stdint.h> | ||
| 7 | #include <stdlib.h> | ||
| 8 | #include <string.h> | ||
| 9 | #include <time.h> | ||
| 10 | #include <unistd.h> | ||
| 11 | #include <sys/stat.h> | ||
| 12 | #include "cubetypes.h" | ||
| 13 | |||
| 14 | /* Steps *********************************************************************/ | ||
| 15 | |||
| 16 | extern Step eofb_HTM; | ||
| 17 | extern Step eorl_HTM; | ||
| 18 | extern Step eoud_HTM; | ||
| 19 | extern Step coud_HTM; | ||
| 20 | extern Step corl_HTM; | ||
| 21 | extern Step cofb_HTM; | ||
| 22 | extern Step coud_URF; | ||
| 23 | extern Step corl_URF; | ||
| 24 | extern Step cofb_URF; | ||
| 25 | extern Step corners_HTM; | ||
| 26 | extern Step corners_URF; | ||
| 27 | extern Step edges_HTM; | ||
| 28 | extern Step drud_HTM; | ||
| 29 | extern Step optimal_HTM; | ||
| 30 | |||
| 31 | extern PruneData pd_eofb_HTM; | ||
| 32 | extern PruneData pd_coud_HTM; | ||
| 33 | extern PruneData pd_corners_HTM; | ||
| 34 | extern PruneData pd_ep_HTM; | ||
| 35 | extern PruneData pd_drud_HTM; | ||
| 36 | |||
| 37 | /* Public functions **********************************************************/ | ||
| 38 | |||
| 39 | Cube apply_alg(Alg *alg, Cube cube); | ||
| 40 | Cube apply_move(Move m, Cube cube); | ||
| 41 | Cube apply_trans(Trans t, Cube cube); | ||
| 42 | bool block_solved(Cube cube, Block); | ||
| 43 | Center center_at(Cube cube, Center c); | ||
| 44 | Cube compose(Cube c2, Cube c1); /* Use c2 as an alg on c1 */ | ||
| 45 | Corner corner_at(Cube cube, Corner c); | ||
| 46 | Edge edge_at(Cube cube, Edge e); | ||
| 47 | bool equal(Cube c1, Cube c2); | ||
| 48 | Cube inverse_cube(Cube cube); | ||
| 49 | Move inverse_move(Move m); | ||
| 50 | Trans inverse_trans(Trans t); | ||
| 51 | bool is_admissible(Cube cube); | ||
| 52 | bool is_solved(Cube cube, bool reorient); | ||
| 53 | int piece_orientation(Cube cube, int piece, char *orientation); | ||
| 54 | void print_cube(Cube cube); | ||
| 55 | Cube random_cube(); | ||
| 56 | AlgList * solve(Cube cube, Step step, SolveOptions *opts); | ||
| 57 | |||
| 58 | void free_alg(Alg *alg); | ||
| 59 | void free_alglist(AlgList *l); | ||
| 60 | Alg * inverse_alg(Alg *alg); | ||
| 61 | Alg * new_alg(char *str); | ||
| 62 | Alg * on_inverse(Alg *alg); | ||
| 63 | void print_alg(Alg *alg, bool l); | ||
| 64 | void print_alglist(AlgList *al, bool l); | ||
| 65 | void remove_last_move(Alg *alg); | ||
| 66 | void transform_alg(Trans t, Alg *alg); | ||
| 67 | |||
| 68 | void print_ptable(PruneData *pd); | ||
| 69 | |||
| 70 | void init(); | ||
| 71 | |||
| 72 | #endif | ||
| 73 | |||
diff --git a/old/2021-06-14-oldalg/cubetypes.h b/old/2021-06-14-oldalg/cubetypes.h new file mode 100644 index 0000000..292fbb7 --- /dev/null +++ b/old/2021-06-14-oldalg/cubetypes.h | |||
| @@ -0,0 +1,210 @@ | |||
| 1 | /* Typedefs ******************************************************************/ | ||
| 2 | |||
| 3 | typedef enum center Center; | ||
| 4 | typedef enum corner Corner; | ||
| 5 | typedef enum edge Edge; | ||
| 6 | typedef enum move Move; | ||
| 7 | typedef enum trans Trans; | ||
| 8 | |||
| 9 | typedef struct alg Alg; | ||
| 10 | typedef struct algnode AlgNode; | ||
| 11 | typedef struct alglist AlgList; | ||
| 12 | typedef struct alglistnode AlgListNode; | ||
| 13 | typedef struct block Block; | ||
| 14 | typedef struct cube Cube; | ||
| 15 | typedef struct cubearray CubeArray; | ||
| 16 | typedef struct dfsdata DfsData; | ||
| 17 | typedef struct piecefilter PieceFilter; | ||
| 18 | typedef struct prunedata PruneData; | ||
| 19 | typedef struct solveoptions SolveOptions; | ||
| 20 | typedef struct step Step; | ||
| 21 | |||
| 22 | /* Enums *********************************************************************/ | ||
| 23 | |||
| 24 | enum | ||
| 25 | center | ||
| 26 | { | ||
| 27 | U_center, D_center, | ||
| 28 | R_center, L_center, | ||
| 29 | F_center, B_center | ||
| 30 | }; | ||
| 31 | |||
| 32 | enum | ||
| 33 | corner | ||
| 34 | { | ||
| 35 | UFR, UFL, UBL, UBR, | ||
| 36 | DFR, DFL, DBL, DBR | ||
| 37 | }; | ||
| 38 | |||
| 39 | enum | ||
| 40 | edge | ||
| 41 | { | ||
| 42 | UF, UL, UB, UR, | ||
| 43 | DF, DL, DB, DR, | ||
| 44 | FR, FL, BL, BR | ||
| 45 | }; | ||
| 46 | |||
| 47 | enum | ||
| 48 | move | ||
| 49 | { | ||
| 50 | NULLMOVE, | ||
| 51 | U, U2, U3, D, D2, D3, | ||
| 52 | R, R2, R3, L, L2, L3, | ||
| 53 | F, F2, F3, B, B2, B3, | ||
| 54 | Uw, Uw2, Uw3, Dw, Dw2, Dw3, | ||
| 55 | Rw, Rw2, Rw3, Lw, Lw2, Lw3, | ||
| 56 | Fw, Fw2, Fw3, Bw, Bw2, Bw3, | ||
| 57 | M, M2, M3, | ||
| 58 | S, S2, S3, | ||
| 59 | E, E2, E3, | ||
| 60 | x, x2, x3, | ||
| 61 | y, y2, y3, | ||
| 62 | z, z2, z3, | ||
| 63 | }; | ||
| 64 | |||
| 65 | enum | ||
| 66 | trans | ||
| 67 | { | ||
| 68 | uf, ur, ub, ul, | ||
| 69 | df, dr, db, dl, | ||
| 70 | rf, rd, rb, ru, | ||
| 71 | lf, ld, lb, lu, | ||
| 72 | fu, fr, fd, fl, | ||
| 73 | bu, br, bd, bl, | ||
| 74 | mirror, /* R|L */ | ||
| 75 | }; | ||
| 76 | |||
| 77 | |||
| 78 | /* Structs *******************************************************************/ | ||
| 79 | |||
| 80 | struct | ||
| 81 | alg | ||
| 82 | { | ||
| 83 | AlgNode * first; | ||
| 84 | AlgNode * last; | ||
| 85 | int len; | ||
| 86 | }; | ||
| 87 | |||
| 88 | struct | ||
| 89 | algnode | ||
| 90 | { | ||
| 91 | Move m; | ||
| 92 | bool inverse; | ||
| 93 | AlgNode * next; | ||
| 94 | AlgNode * prev; | ||
| 95 | }; | ||
| 96 | |||
| 97 | struct | ||
| 98 | alglist | ||
| 99 | { | ||
| 100 | AlgListNode * first; | ||
| 101 | AlgListNode * last; | ||
| 102 | int len; | ||
| 103 | }; | ||
| 104 | |||
| 105 | struct | ||
| 106 | alglistnode | ||
| 107 | { | ||
| 108 | Alg * alg; | ||
| 109 | AlgListNode * next; | ||
| 110 | }; | ||
| 111 | |||
| 112 | struct | ||
| 113 | block | ||
| 114 | { | ||
| 115 | bool edge[12]; | ||
| 116 | bool corner[8]; | ||
| 117 | bool center[6]; | ||
| 118 | }; | ||
| 119 | |||
| 120 | struct | ||
| 121 | cube | ||
| 122 | { | ||
| 123 | uint16_t epose; | ||
| 124 | uint16_t eposs; | ||
| 125 | uint16_t eposm; | ||
| 126 | uint16_t eofb; | ||
| 127 | uint16_t eorl; | ||
| 128 | uint16_t eoud; | ||
| 129 | uint16_t cp; | ||
| 130 | uint16_t coud; | ||
| 131 | uint16_t cofb; | ||
| 132 | uint16_t corl; | ||
| 133 | uint16_t cpos; | ||
| 134 | }; | ||
| 135 | |||
| 136 | struct | ||
| 137 | cubearray | ||
| 138 | { | ||
| 139 | int * ep; | ||
| 140 | int * eofb; | ||
| 141 | int * eorl; | ||
| 142 | int * eoud; | ||
| 143 | int * cp; | ||
| 144 | int * coud; | ||
| 145 | int * corl; | ||
| 146 | int * cofb; | ||
| 147 | int * cpos; | ||
| 148 | }; | ||
| 149 | |||
| 150 | struct | ||
| 151 | dfsdata | ||
| 152 | { | ||
| 153 | int d; | ||
| 154 | int m; | ||
| 155 | bool niss; | ||
| 156 | Move last1; | ||
| 157 | Move last2; | ||
| 158 | AlgList * sols; | ||
| 159 | Alg * current_alg; | ||
| 160 | Move sorted_moves[z3+1]; | ||
| 161 | }; | ||
| 162 | |||
| 163 | struct | ||
| 164 | piecefilter | ||
| 165 | { | ||
| 166 | bool epose; | ||
| 167 | bool eposs; | ||
| 168 | bool eposm; | ||
| 169 | bool eofb; | ||
| 170 | bool eorl; | ||
| 171 | bool eoud; | ||
| 172 | bool cp; | ||
| 173 | bool coud; | ||
| 174 | bool cofb; | ||
| 175 | bool corl; | ||
| 176 | bool cpos; | ||
| 177 | }; | ||
| 178 | |||
| 179 | struct | ||
| 180 | prunedata | ||
| 181 | { | ||
| 182 | char * filename; | ||
| 183 | uint8_t * ptable; | ||
| 184 | uint8_t * reached; | ||
| 185 | bool generated; | ||
| 186 | uint64_t n; | ||
| 187 | uint64_t size; | ||
| 188 | uint64_t (*index)(Cube); | ||
| 189 | bool (*moveset)(Move); | ||
| 190 | }; | ||
| 191 | |||
| 192 | struct | ||
| 193 | solveoptions | ||
| 194 | { | ||
| 195 | int min_moves; | ||
| 196 | int max_moves; | ||
| 197 | int max_solutions; | ||
| 198 | bool optimal_only; | ||
| 199 | bool can_niss; | ||
| 200 | bool feedback; | ||
| 201 | }; | ||
| 202 | |||
| 203 | struct | ||
| 204 | step | ||
| 205 | { | ||
| 206 | int (*check)(Cube); | ||
| 207 | int (*ready)(Cube); | ||
| 208 | bool (*moveset)(Move); | ||
| 209 | Trans pre_trans; | ||
| 210 | }; | ||
diff --git a/old/2021-06-14-oldalg/main.c b/old/2021-06-14-oldalg/main.c new file mode 100644 index 0000000..445eefc --- /dev/null +++ b/old/2021-06-14-oldalg/main.c | |||
| @@ -0,0 +1,56 @@ | |||
| 1 | #include <stdio.h> | ||
| 2 | #include "cube.h" | ||
| 3 | |||
| 4 | int main() { | ||
| 5 | Alg *algo; | ||
| 6 | AlgList *sols; | ||
| 7 | Cube cube; | ||
| 8 | SolveOptions opts; | ||
| 9 | char line[1000]; | ||
| 10 | int i, ns = 2, nrand = 100000, sum; | ||
| 11 | |||
| 12 | Step *stps[20] = {&drud_HTM, &optimal_HTM}; | ||
| 13 | char sss[30][30] = {"DR on U/D", "Optimal solution"}; | ||
| 14 | |||
| 15 | opts = (SolveOptions) { | ||
| 16 | .min_moves = 0, | ||
| 17 | .max_moves = 20, | ||
| 18 | .optimal_only = true, | ||
| 19 | .max_solutions = 1, | ||
| 20 | .can_niss = false, | ||
| 21 | .feedback = true | ||
| 22 | }; | ||
| 23 | |||
| 24 | init(); | ||
| 25 | |||
| 26 | /* | ||
| 27 | print_ptable(&pd_drud_HTM); | ||
| 28 | print_ptable(&pd_ep_HTM); | ||
| 29 | print_ptable(&pd_corners_HTM); | ||
| 30 | */ | ||
| 31 | |||
| 32 | srand(time(NULL)); | ||
| 33 | sum = 0; | ||
| 34 | for (i = 0; i < nrand; i++) | ||
| 35 | sum += optimal_HTM.check(random_cube()); | ||
| 36 | printf("Average pruning value: %lf\n", ((double)sum) / ((double) nrand)); | ||
| 37 | |||
| 38 | printf("Welcome to nissy 2.0! Insert a scramble:\n"); | ||
| 39 | |||
| 40 | if (fgets(line, 1000, stdin) != NULL) { | ||
| 41 | algo = new_alg(line); | ||
| 42 | cube = apply_alg(algo, (Cube){0}); | ||
| 43 | |||
| 44 | for (i = 0; i < ns; i++) { | ||
| 45 | if (stps[i]->check == NULL) | ||
| 46 | fprintf(stderr, "Check function for step %d is null\n", i); | ||
| 47 | sols = solve(cube, *stps[i], &opts); | ||
| 48 | printf("%s: %d solutions found:\n", sss[i], sols->len); | ||
| 49 | print_alglist(sols, true); | ||
| 50 | free_alglist(sols); | ||
| 51 | } | ||
| 52 | free(algo); | ||
| 53 | } | ||
| 54 | |||
| 55 | return 0; | ||
| 56 | } | ||
diff --git a/old/2021-06-15-before-separating-steps/cube.c b/old/2021-06-15-before-separating-steps/cube.c new file mode 100644 index 0000000..06c829b --- /dev/null +++ b/old/2021-06-15-before-separating-steps/cube.c | |||
| @@ -0,0 +1,2836 @@ | |||
| 1 | #include "cube.h" | ||
| 2 | |||
| 3 | /* Constants and macros *****************************************************/ | ||
| 4 | |||
| 5 | #define POW2TO11 2048ULL | ||
| 6 | #define POW2TO12 4096ULL | ||
| 7 | #define POW3TO7 2187ULL | ||
| 8 | #define POW3TO8 6561ULL | ||
| 9 | #define FACTORIAL4 24ULL | ||
| 10 | #define FACTORIAL6 720ULL | ||
| 11 | #define FACTORIAL8 40320ULL | ||
| 12 | #define FACTORIAL12 479001600ULL | ||
| 13 | #define BINOM12ON4 495ULL | ||
| 14 | #define BINOM8ON4 70ULL | ||
| 15 | #define MIN(a,b) (((a) < (b)) ? (a) : (b)) | ||
| 16 | #define MAX(a,b) (((a) > (b)) ? (a) : (b)) | ||
| 17 | |||
| 18 | #define BASEALGLEN 50 | ||
| 19 | #define NMOVES (z3+1) | ||
| 20 | #define NTRANS (mirror+1) | ||
| 21 | #define NROTATIONS (NTRANS-1) | ||
| 22 | #define PTABLESIZE(n) ((n+1) / 2) | ||
| 23 | #define PTABLEVAL(tab,ind) (((ind)%2) ? (tab[(ind)/2] / 16) : \ | ||
| 24 | (tab[(ind)/2] % 16)) | ||
| 25 | |||
| 26 | |||
| 27 | /* Local functions **********************************************************/ | ||
| 28 | |||
| 29 | static Cube admissible_ep(Cube cube, PieceFilter f); | ||
| 30 | static void append_alg(AlgList *l, Alg *alg); | ||
| 31 | static void append_move(Alg *alg, Move m, bool inverse); | ||
| 32 | static Cube apply_alg_generic(Alg *alg, Cube c, PieceFilter f, bool a); | ||
| 33 | static void apply_permutation(int *perm, int *set, int n); | ||
| 34 | static Cube apply_move_cubearray(Move m, Cube cube, PieceFilter f); | ||
| 35 | static uint16_t array_ep_to_epos(int *ep, int *eps_solved); | ||
| 36 | static Cube arrays_to_cube(CubeArray *arr, PieceFilter f); | ||
| 37 | static Move base_move(Move m); | ||
| 38 | static int binomial(int n, int k); | ||
| 39 | static Cube compose_filtered(Cube c2, Cube c1, PieceFilter f); | ||
| 40 | static void cube_to_arrays(Cube cube, CubeArray *arr, PieceFilter f); | ||
| 41 | static int digit_array_to_int(int *a, int n, int b); | ||
| 42 | static int edge_slice(Edge e); /* E=0, S=1, M=2 */ | ||
| 43 | static int epos_dependent(int pos1, int pos2); | ||
| 44 | static uint16_t epos_from_arrays(int *epos, int *ep); | ||
| 45 | static void epos_to_partial_ep(uint16_t epos, int *ep, int *ss); | ||
| 46 | static int factorial(int n); | ||
| 47 | static void free_alglistnode(AlgListNode *aln); | ||
| 48 | static void free_cubearray(CubeArray *arr, PieceFilter f); | ||
| 49 | static void generate_ptable(PruneData *pd); | ||
| 50 | static void generate_ptable_dfs(Cube c, PruneData *pd, DfsData *dd); | ||
| 51 | static void index_to_perm(int p, int n, int *r); | ||
| 52 | static void index_to_subset(int s, int n, int k, int *r); | ||
| 53 | static void int_to_digit_array(int a, int b, int n, int *r); | ||
| 54 | static void int_to_sum_zero_array(int x, int b, int n, int *a); | ||
| 55 | static int invert_digits(int a, int b, int n); | ||
| 56 | static bool is_perm(int *a, int n); | ||
| 57 | static bool is_subset(int *a, int n, int k); | ||
| 58 | static Cube move_via_arrays(CubeArray *arr, Cube c, PieceFilter pf); | ||
| 59 | static void moveset_to_list(bool (*ms)(Move), int (*f)(Cube), Move *r); | ||
| 60 | static AlgList * new_alglist(); | ||
| 61 | static CubeArray * new_cubearray(Cube cube, PieceFilter f); | ||
| 62 | static int perm_sign(int *a, int n); | ||
| 63 | static int perm_to_index(int *a, int n); | ||
| 64 | static int powint(int a, int b); | ||
| 65 | static void ptable_set_reached(PruneData *pd, uint64_t ind); | ||
| 66 | static void ptable_update(PruneData *pd, uint64_t ind, int m); | ||
| 67 | static bool read_ptable_file(PruneData *pd); | ||
| 68 | static bool read_ttables_file(); | ||
| 69 | static bool read_mtables_file(); | ||
| 70 | static Cube rotate_via_compose(Trans r, Cube c, PieceFilter f); | ||
| 71 | static void solve_dfs(Cube c, Step s, SolveOptions *opts, DfsData *dd); | ||
| 72 | static int subset_to_index(int *a, int n, int k); | ||
| 73 | static void sum_arrays_mod(int *src, int *dst, int n, int m); | ||
| 74 | static void swap(int *a, int *b); | ||
| 75 | static bool write_ptable_file(PruneData *pd); | ||
| 76 | static bool write_ttables_file(); | ||
| 77 | static bool write_mtables_file(); | ||
| 78 | |||
| 79 | static void init_auxtables(); | ||
| 80 | static void init_environment(); | ||
| 81 | static void init_moves(); | ||
| 82 | static void init_moves_aux(); | ||
| 83 | static void init_steps(); | ||
| 84 | static void init_strings(); | ||
| 85 | static void init_trans(); | ||
| 86 | static void init_trans_aux(); | ||
| 87 | |||
| 88 | static bool moveset_HTM(Move m); | ||
| 89 | static bool moveset_URF(Move m); | ||
| 90 | |||
| 91 | /* Steps and related functions and data **************************************/ | ||
| 92 | |||
| 93 | Step eofb_HTM; | ||
| 94 | Step eorl_HTM; | ||
| 95 | Step eoud_HTM; | ||
| 96 | Step coud_HTM; | ||
| 97 | Step corl_HTM; | ||
| 98 | Step cofb_HTM; | ||
| 99 | Step coud_URF; | ||
| 100 | Step corl_URF; | ||
| 101 | Step cofb_URF; | ||
| 102 | Step corners_HTM; | ||
| 103 | Step corners_URF; | ||
| 104 | Step edges_HTM; | ||
| 105 | Step drud_HTM; | ||
| 106 | Step optimal_HTM; | ||
| 107 | |||
| 108 | PruneData pd_eofb_HTM; | ||
| 109 | PruneData pd_coud_HTM; | ||
| 110 | PruneData pd_corners_HTM; | ||
| 111 | PruneData pd_ep_HTM; | ||
| 112 | PruneData pd_drud_HTM; | ||
| 113 | |||
| 114 | static uint64_t index_eofb(Cube cube); | ||
| 115 | static uint64_t index_coud(Cube cube); | ||
| 116 | static uint64_t index_corners(Cube cube); | ||
| 117 | static uint64_t index_ep(Cube cube); | ||
| 118 | static uint64_t index_drud(Cube cube); | ||
| 119 | |||
| 120 | static int check_nothing(Cube cube); | ||
| 121 | static int check_eofb_HTM(Cube cube); | ||
| 122 | static int check_coud_HTM(Cube cube); | ||
| 123 | static int check_coud_URF(Cube cube); | ||
| 124 | static int check_corners_HTM(Cube cube); | ||
| 125 | static int check_corners_URF(Cube cube); | ||
| 126 | static int check_edges_HTM(Cube cube); | ||
| 127 | static int check_drud_HTM(Cube cube); | ||
| 128 | static int check_optimal_HTM(Cube cube); | ||
| 129 | |||
| 130 | /* All sorts of useful costants and tables **********************************/ | ||
| 131 | |||
| 132 | static char * tabledir; | ||
| 133 | |||
| 134 | static PieceFilter pf_all; | ||
| 135 | static PieceFilter pf_4val; | ||
| 136 | static PieceFilter pf_epcp; | ||
| 137 | static PieceFilter pf_cpos; | ||
| 138 | static PieceFilter pf_cp; | ||
| 139 | static PieceFilter pf_ep; | ||
| 140 | static PieceFilter pf_e; | ||
| 141 | static PieceFilter pf_s; | ||
| 142 | static PieceFilter pf_m; | ||
| 143 | static PieceFilter pf_eo; | ||
| 144 | static PieceFilter pf_co; | ||
| 145 | |||
| 146 | static int epe_solved[4]; | ||
| 147 | static int eps_solved[4]; | ||
| 148 | static int epm_solved[4]; | ||
| 149 | |||
| 150 | static char move_string[NMOVES][7]; | ||
| 151 | static char edge_string[12][7]; | ||
| 152 | static char corner_string[8][7]; | ||
| 153 | static char center_string[6][7]; | ||
| 154 | |||
| 155 | static bool commute[NMOVES][NMOVES]; | ||
| 156 | static bool possible_next[NMOVES][NMOVES][NMOVES]; | ||
| 157 | static Move inverse_move_aux[NMOVES]; | ||
| 158 | static Trans inverse_trans_aux[NTRANS]; | ||
| 159 | static int epos_dependent_aux[BINOM12ON4][BINOM12ON4]; | ||
| 160 | |||
| 161 | static uint16_t epose_ttable[NTRANS][FACTORIAL12/FACTORIAL8]; | ||
| 162 | static uint16_t eposs_ttable[NTRANS][FACTORIAL12/FACTORIAL8]; | ||
| 163 | static uint16_t eposm_ttable[NTRANS][FACTORIAL12/FACTORIAL8]; | ||
| 164 | static uint16_t eo_ttable[NTRANS][POW2TO11]; | ||
| 165 | static uint16_t cp_ttable[NTRANS][FACTORIAL8]; | ||
| 166 | static uint16_t co_ttable[NTRANS][POW3TO7]; | ||
| 167 | static uint16_t cpos_ttable[NTRANS][FACTORIAL6]; | ||
| 168 | static Move moves_ttable[NTRANS][NMOVES]; | ||
| 169 | |||
| 170 | static uint16_t epose_mtable[NMOVES][FACTORIAL12/FACTORIAL8]; | ||
| 171 | static uint16_t eposs_mtable[NMOVES][FACTORIAL12/FACTORIAL8]; | ||
| 172 | static uint16_t eposm_mtable[NMOVES][FACTORIAL12/FACTORIAL8]; | ||
| 173 | static uint16_t eofb_mtable[NMOVES][POW2TO11]; | ||
| 174 | static uint16_t eorl_mtable[NMOVES][POW2TO11]; | ||
| 175 | static uint16_t eoud_mtable[NMOVES][POW2TO11]; | ||
| 176 | static uint16_t cp_mtable[NMOVES][FACTORIAL8]; | ||
| 177 | static uint16_t coud_mtable[NMOVES][POW3TO7]; | ||
| 178 | static uint16_t cofb_mtable[NMOVES][POW3TO7]; | ||
| 179 | static uint16_t corl_mtable[NMOVES][POW3TO7]; | ||
| 180 | static uint16_t cpos_mtable[NMOVES][FACTORIAL6]; | ||
| 181 | |||
| 182 | static uint64_t me[12]; | ||
| 183 | |||
| 184 | static int edge_cycle[NMOVES][12]; | ||
| 185 | static int corner_cycle[NMOVES][8]; | ||
| 186 | static int center_cycle[NMOVES][6]; | ||
| 187 | static int eofb_flipped[NMOVES][12]; | ||
| 188 | static int eorl_flipped[NMOVES][12]; | ||
| 189 | static int eoud_flipped[NMOVES][12]; | ||
| 190 | static int coud_flipped[NMOVES][8]; | ||
| 191 | static int corl_flipped[NMOVES][8]; | ||
| 192 | static int cofb_flipped[NMOVES][8]; | ||
| 193 | static Alg * equiv_alg[NMOVES]; | ||
| 194 | |||
| 195 | static int epose_source[NTRANS]; /* 0=epose, 1=eposs, 2=eposm */ | ||
| 196 | static int eposs_source[NTRANS]; | ||
| 197 | static int eposm_source[NTRANS]; | ||
| 198 | static int eofb_source[NTRANS]; /* 0=eoud, 1=eorl, 2=eofb */ | ||
| 199 | static int eorl_source[NTRANS]; | ||
| 200 | static int eoud_source[NTRANS]; | ||
| 201 | static int coud_source[NTRANS]; /* 0=coud, 1=corl, 2=cofb */ | ||
| 202 | static int cofb_source[NTRANS]; | ||
| 203 | static int corl_source[NTRANS]; | ||
| 204 | static int ep_mirror[12]; | ||
| 205 | static int cp_mirror[8]; | ||
| 206 | static int cpos_mirror[6]; | ||
| 207 | static Alg * trans_algs[NROTATIONS]; | ||
| 208 | |||
| 209 | |||
| 210 | /* Local functions implementation ********************************************/ | ||
| 211 | |||
| 212 | static Cube | ||
| 213 | admissible_ep(Cube cube, PieceFilter f) | ||
| 214 | { | ||
| 215 | CubeArray *arr = new_cubearray(cube, f); | ||
| 216 | Cube ret; | ||
| 217 | bool used[12] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; | ||
| 218 | int i, j; | ||
| 219 | |||
| 220 | for (i = 0; i < 12; i++) | ||
| 221 | if (arr->ep[i] != -1) | ||
| 222 | used[arr->ep[i]] = true; | ||
| 223 | |||
| 224 | for (i = 0, j = 0; i < 12; i++) { | ||
| 225 | for ( ; j < 11 && used[j]; j++); | ||
| 226 | if (arr->ep[i] == -1) | ||
| 227 | arr->ep[i] = j++; | ||
| 228 | } | ||
| 229 | |||
| 230 | ret = arrays_to_cube(arr, pf_ep); | ||
| 231 | free_cubearray(arr, f); | ||
| 232 | |||
| 233 | return ret; | ||
| 234 | } | ||
| 235 | |||
| 236 | static void | ||
| 237 | append_alg(AlgList *l, Alg *alg) | ||
| 238 | { | ||
| 239 | AlgListNode *node = malloc(sizeof(AlgListNode)); | ||
| 240 | int i; | ||
| 241 | |||
| 242 | node->alg = new_alg(""); | ||
| 243 | for (i = 0; i < alg->len; i++) | ||
| 244 | append_move(node->alg, alg->move[i], alg->inv[i]); | ||
| 245 | node->next = NULL; | ||
| 246 | |||
| 247 | if (++l->len == 1) | ||
| 248 | l->first = node; | ||
| 249 | else | ||
| 250 | l->last->next = node; | ||
| 251 | l->last = node; | ||
| 252 | } | ||
| 253 | |||
| 254 | static void | ||
| 255 | append_move(Alg *alg, Move m, bool inverse) | ||
| 256 | { | ||
| 257 | if (alg->len == alg->allocated) { | ||
| 258 | if (alg->len > 1000000) { | ||
| 259 | fprintf(stderr, "Warning: very long alg,"); | ||
| 260 | fprintf(stderr, "something might be wrong.\n"); | ||
| 261 | } | ||
| 262 | alg->move = realloc(alg->move, 2 * alg->len * sizeof(Move)); | ||
| 263 | alg->inv = realloc(alg->inv, 2 * alg->len * sizeof(bool)); | ||
| 264 | alg->allocated *= 2; | ||
| 265 | } | ||
| 266 | |||
| 267 | alg->move[alg->len] = m; | ||
| 268 | alg->inv [alg->len] = inverse; | ||
| 269 | alg->len++; | ||
| 270 | } | ||
| 271 | |||
| 272 | static Cube | ||
| 273 | apply_alg_generic(Alg *alg, Cube c, PieceFilter f, bool a) | ||
| 274 | { | ||
| 275 | Cube ret = {0}; | ||
| 276 | int i; | ||
| 277 | |||
| 278 | for (i = 0; i < alg->len; i++) | ||
| 279 | if (alg->inv[i]) | ||
| 280 | ret = a ? apply_move(alg->move[i], ret) : | ||
| 281 | apply_move_cubearray(alg->move[i], ret, f); | ||
| 282 | |||
| 283 | ret = compose_filtered(c, inverse_cube(ret), f); | ||
| 284 | |||
| 285 | for (i = 0; i < alg->len; i++) | ||
| 286 | if (!alg->inv[i]) | ||
| 287 | ret = a ? apply_move(alg->move[i], ret) : | ||
| 288 | apply_move_cubearray(alg->move[i], ret, f); | ||
| 289 | |||
| 290 | return ret; | ||
| 291 | } | ||
| 292 | |||
| 293 | static void | ||
| 294 | apply_permutation(int *perm, int *set, int n) | ||
| 295 | { | ||
| 296 | int *aux = malloc(n * sizeof(int)); | ||
| 297 | int i; | ||
| 298 | |||
| 299 | if (!is_perm(perm, n)) | ||
| 300 | return; | ||
| 301 | |||
| 302 | for (i = 0; i < n; i++) | ||
| 303 | aux[i] = set[perm[i]]; | ||
| 304 | |||
| 305 | memcpy(set, aux, n * sizeof(int)); | ||
| 306 | free(aux); | ||
| 307 | } | ||
| 308 | |||
| 309 | static Cube | ||
| 310 | apply_move_cubearray(Move m, Cube cube, PieceFilter f) | ||
| 311 | { | ||
| 312 | CubeArray m_arr = { | ||
| 313 | edge_cycle[m], | ||
| 314 | eofb_flipped[m], | ||
| 315 | eorl_flipped[m], | ||
| 316 | eoud_flipped[m], | ||
| 317 | corner_cycle[m], | ||
| 318 | coud_flipped[m], | ||
| 319 | corl_flipped[m], | ||
| 320 | cofb_flipped[m], | ||
| 321 | center_cycle[m] | ||
| 322 | }; | ||
| 323 | |||
| 324 | return move_via_arrays(&m_arr, cube, f); | ||
| 325 | } | ||
| 326 | |||
| 327 | static uint16_t | ||
| 328 | array_ep_to_epos(int *ep, int *ss) | ||
| 329 | { | ||
| 330 | int epos[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; | ||
| 331 | int eps[4]; | ||
| 332 | int i, j, is; | ||
| 333 | |||
| 334 | for (i = 0, is = 0; i < 12; i++) { | ||
| 335 | for (j = 0; j < 4; j++) { | ||
| 336 | if (ep[i] == ss[j]) { | ||
| 337 | eps[is++] = j; | ||
| 338 | epos[i] = 1; | ||
| 339 | } | ||
| 340 | } | ||
| 341 | } | ||
| 342 | |||
| 343 | for (i = 0; i < 4; i++) | ||
| 344 | swap(&epos[ss[i]], &epos[i+8]); | ||
| 345 | |||
| 346 | return epos_from_arrays(epos, eps); | ||
| 347 | } | ||
| 348 | |||
| 349 | static Cube | ||
| 350 | arrays_to_cube(CubeArray *arr, PieceFilter f) | ||
| 351 | { | ||
| 352 | Cube ret = {0}; | ||
| 353 | |||
| 354 | if (f.epose) | ||
| 355 | ret.epose = array_ep_to_epos(arr->ep, epe_solved); | ||
| 356 | if (f.eposs) | ||
| 357 | ret.eposs = array_ep_to_epos(arr->ep, eps_solved); | ||
| 358 | if (f.eposm) | ||
| 359 | ret.eposm = array_ep_to_epos(arr->ep, epm_solved); | ||
| 360 | if (f.eofb) | ||
| 361 | ret.eofb = digit_array_to_int(arr->eofb, 11, 2); | ||
| 362 | if (f.eorl) | ||
| 363 | ret.eorl = digit_array_to_int(arr->eorl, 11, 2); | ||
| 364 | if (f.eoud) | ||
| 365 | ret.eoud = digit_array_to_int(arr->eoud, 11, 2); | ||
| 366 | if (f.cp) | ||
| 367 | ret.cp = perm_to_index(arr->cp, 8); | ||
| 368 | if (f.coud) | ||
| 369 | ret.coud = digit_array_to_int(arr->coud, 7, 3); | ||
| 370 | if (f.corl) | ||
| 371 | ret.corl = digit_array_to_int(arr->corl, 7, 3); | ||
| 372 | if (f.cofb) | ||
| 373 | ret.cofb = digit_array_to_int(arr->cofb, 7, 3); | ||
| 374 | if (f.cpos) | ||
| 375 | ret.cpos = perm_to_index(arr->cpos, 6); | ||
| 376 | |||
| 377 | return ret; | ||
| 378 | } | ||
| 379 | |||
| 380 | static Move | ||
| 381 | base_move(Move m) | ||
| 382 | { | ||
| 383 | if (m == NULLMOVE) | ||
| 384 | return NULLMOVE; | ||
| 385 | else | ||
| 386 | return m - (m-1)%3; | ||
| 387 | } | ||
| 388 | |||
| 389 | static int | ||
| 390 | binomial(int n, int k) | ||
| 391 | { | ||
| 392 | if (n < 0 || k < 0 || k > n) | ||
| 393 | return 0; | ||
| 394 | |||
| 395 | return factorial(n) / (factorial(k) * factorial(n-k)); | ||
| 396 | } | ||
| 397 | |||
| 398 | static Cube | ||
| 399 | compose_filtered(Cube c2, Cube c1, PieceFilter f) | ||
| 400 | { | ||
| 401 | CubeArray *arr = new_cubearray(c2, f); | ||
| 402 | Cube ret; | ||
| 403 | |||
| 404 | ret = move_via_arrays(arr, c1, f); | ||
| 405 | free_cubearray(arr, f); | ||
| 406 | |||
| 407 | return ret; | ||
| 408 | } | ||
| 409 | |||
| 410 | static void | ||
| 411 | cube_to_arrays(Cube cube, CubeArray *arr, PieceFilter f) | ||
| 412 | { | ||
| 413 | int i; | ||
| 414 | |||
| 415 | if (f.epose || f.eposs || f.eposm) | ||
| 416 | for (i = 0; i < 12; i++) | ||
| 417 | arr->ep[i] = -1; | ||
| 418 | |||
| 419 | if (f.epose) | ||
| 420 | epos_to_partial_ep(cube.epose, arr->ep, epe_solved); | ||
| 421 | if (f.eposs) | ||
| 422 | epos_to_partial_ep(cube.eposs, arr->ep, eps_solved); | ||
| 423 | if (f.eposm) | ||
| 424 | epos_to_partial_ep(cube.eposm, arr->ep, epm_solved); | ||
| 425 | if (f.eofb) | ||
| 426 | int_to_sum_zero_array(cube.eofb, 2, 12, arr->eofb); | ||
| 427 | if (f.eorl) | ||
| 428 | int_to_sum_zero_array(cube.eorl, 2, 12, arr->eorl); | ||
| 429 | if (f.eoud) | ||
| 430 | int_to_sum_zero_array(cube.eoud, 2, 12, arr->eoud); | ||
| 431 | if (f.cp) | ||
| 432 | index_to_perm(cube.cp, 8, arr->cp); | ||
| 433 | if (f.coud) | ||
| 434 | int_to_sum_zero_array(cube.coud, 3, 8, arr->coud); | ||
| 435 | if (f.corl) | ||
| 436 | int_to_sum_zero_array(cube.corl, 3, 8, arr->corl); | ||
| 437 | if (f.cofb) | ||
| 438 | int_to_sum_zero_array(cube.cofb, 3, 8, arr->cofb); | ||
| 439 | if (f.cpos) | ||
| 440 | index_to_perm(cube.cpos, 6, arr->cpos); | ||
| 441 | } | ||
| 442 | |||
| 443 | static int | ||
| 444 | digit_array_to_int(int *a, int n, int b) | ||
| 445 | { | ||
| 446 | int i, ret = 0, p = 1; | ||
| 447 | |||
| 448 | for (i = 0; i < n; i++, p *= b) | ||
| 449 | ret += a[i] * p; | ||
| 450 | |||
| 451 | return ret; | ||
| 452 | } | ||
| 453 | |||
| 454 | static int | ||
| 455 | edge_slice(Edge e) { | ||
| 456 | if (e < 0 || e > 11) | ||
| 457 | return -1; | ||
| 458 | |||
| 459 | if (e == FR || e == FL || e == BL || e == BR) | ||
| 460 | return 0; | ||
| 461 | if (e == UR || e == UL || e == DR || e == DL) | ||
| 462 | return 1; | ||
| 463 | |||
| 464 | return 2; | ||
| 465 | } | ||
| 466 | |||
| 467 | static int | ||
| 468 | epos_dependent(int poss, int pose) | ||
| 469 | { | ||
| 470 | int ep[12] = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}; | ||
| 471 | int ep8[8] = {0, 0, 0, 0, 0, 0, 0, 0}; | ||
| 472 | int i, j; | ||
| 473 | |||
| 474 | epos_to_partial_ep(poss*FACTORIAL4, ep, eps_solved); | ||
| 475 | epos_to_partial_ep(pose*FACTORIAL4, ep, epe_solved); | ||
| 476 | |||
| 477 | for (i = 0, j = 0; i < 12; i++) | ||
| 478 | if (edge_slice(ep[i]) != 1) | ||
| 479 | ep8[j++] = (edge_slice(ep[i]) == 0) ? 1 : 0; | ||
| 480 | |||
| 481 | return subset_to_index(ep8, 8, 4); | ||
| 482 | } | ||
| 483 | |||
| 484 | static uint16_t | ||
| 485 | epos_from_arrays(int *epos, int *ep) | ||
| 486 | { | ||
| 487 | return FACTORIAL4 * subset_to_index(epos,12,4) + perm_to_index(ep,4); | ||
| 488 | } | ||
| 489 | |||
| 490 | static void | ||
| 491 | epos_to_partial_ep(uint16_t epos, int *ep, int *ss) | ||
| 492 | { | ||
| 493 | int i, is, eposs[12], eps[4]; | ||
| 494 | |||
| 495 | index_to_perm(epos % FACTORIAL4, 4, eps); | ||
| 496 | index_to_subset(epos / FACTORIAL4, 12, 4, eposs); | ||
| 497 | |||
| 498 | for (i = 0; i < 4; i++) | ||
| 499 | swap(&eposs[ss[i]], &eposs[i+8]); | ||
| 500 | |||
| 501 | for (i = 0, is = 0; i < 12; i++) | ||
| 502 | if (eposs[i]) | ||
| 503 | ep[i] = ss[eps[is++]]; | ||
| 504 | } | ||
| 505 | |||
| 506 | static int | ||
| 507 | factorial(int n) | ||
| 508 | { | ||
| 509 | int i, ret = 1; | ||
| 510 | |||
| 511 | if (n < 0) | ||
| 512 | return 0; | ||
| 513 | |||
| 514 | for (i = 1; i <= n; i++) | ||
| 515 | ret *= i; | ||
| 516 | |||
| 517 | return ret; | ||
| 518 | } | ||
| 519 | |||
| 520 | void | ||
| 521 | free_alg(Alg *alg) | ||
| 522 | { | ||
| 523 | free(alg->move); | ||
| 524 | free(alg->inv); | ||
| 525 | free(alg); | ||
| 526 | } | ||
| 527 | |||
| 528 | void | ||
| 529 | free_alglist(AlgList *l) | ||
| 530 | { | ||
| 531 | AlgListNode *aux, *i = l->first; | ||
| 532 | |||
| 533 | while (i != NULL) { | ||
| 534 | aux = i->next; | ||
| 535 | free_alglistnode(i); | ||
| 536 | i = aux; | ||
| 537 | } | ||
| 538 | free(l); | ||
| 539 | } | ||
| 540 | |||
| 541 | void | ||
| 542 | free_alglistnode(AlgListNode *aln) | ||
| 543 | { | ||
| 544 | free_alg(aln->alg); | ||
| 545 | free(aln); | ||
| 546 | } | ||
| 547 | |||
| 548 | static void | ||
| 549 | free_cubearray(CubeArray *arr, PieceFilter f) | ||
| 550 | { | ||
| 551 | if (f.epose || f.eposs || f.eposm) | ||
| 552 | free(arr->ep); | ||
| 553 | if (f.eofb) | ||
| 554 | free(arr->eofb); | ||
| 555 | if (f.eorl) | ||
| 556 | free(arr->eorl); | ||
| 557 | if (f.eoud) | ||
| 558 | free(arr->eoud); | ||
| 559 | if (f.cp) | ||
| 560 | free(arr->cp); | ||
| 561 | if (f.coud) | ||
| 562 | free(arr->coud); | ||
| 563 | if (f.corl) | ||
| 564 | free(arr->corl); | ||
| 565 | if (f.cofb) | ||
| 566 | free(arr->cofb); | ||
| 567 | if (f.cpos) | ||
| 568 | free(arr->cpos); | ||
| 569 | |||
| 570 | free(arr); | ||
| 571 | } | ||
| 572 | |||
| 573 | static void | ||
| 574 | generate_ptable(PruneData *pd) | ||
| 575 | { | ||
| 576 | uint64_t j; | ||
| 577 | DfsData dd; | ||
| 578 | |||
| 579 | if (pd->generated) | ||
| 580 | return; | ||
| 581 | |||
| 582 | /* TODO: check if memory is enough, otherwise maybe crash gracefully? */ | ||
| 583 | pd->ptable = malloc(PTABLESIZE(pd->size) * sizeof(uint8_t)); | ||
| 584 | |||
| 585 | if (read_ptable_file(pd)) { | ||
| 586 | pd->generated = true; | ||
| 587 | return; | ||
| 588 | } | ||
| 589 | |||
| 590 | fprintf(stderr, "Cannot load %s, generating it\n", pd->filename); | ||
| 591 | |||
| 592 | dd.m = 0; | ||
| 593 | dd.last1 = NULLMOVE; | ||
| 594 | dd.last2 = NULLMOVE; | ||
| 595 | |||
| 596 | /* We use 4 bits per value, so any distance >= 15 is set to 15 */ | ||
| 597 | for (j = 0; j < pd->size; j++) | ||
| 598 | ptable_update(pd, j, 15); | ||
| 599 | |||
| 600 | moveset_to_list(pd->moveset, NULL, dd.sorted_moves); | ||
| 601 | |||
| 602 | pd->reached = malloc(PTABLESIZE(pd->size) * sizeof(uint8_t)); | ||
| 603 | for (dd.d = 0, pd->n = 0; dd.d < 15 && pd->n < pd->size; dd.d++) { | ||
| 604 | memset(pd->reached, 0, PTABLESIZE(pd->size)*sizeof(uint8_t)); | ||
| 605 | generate_ptable_dfs((Cube){0}, pd, &dd); | ||
| 606 | fprintf(stderr, "Depth %d completed, generated %lu/%lu\n", | ||
| 607 | dd.d, pd->n, pd->size); | ||
| 608 | } | ||
| 609 | |||
| 610 | if (!write_ptable_file(pd)) | ||
| 611 | fprintf(stderr, "Error writing ptable file\n"); | ||
| 612 | |||
| 613 | pd->generated = true; | ||
| 614 | free(pd->reached); | ||
| 615 | } | ||
| 616 | |||
| 617 | static void | ||
| 618 | generate_ptable_dfs(Cube c, PruneData *pd, DfsData *dd) | ||
| 619 | { | ||
| 620 | uint64_t ind = pd->index(c); | ||
| 621 | int oldval = PTABLEVAL(pd->ptable, ind); | ||
| 622 | Move i, move, l1 = dd->last1, l2 = dd->last2; | ||
| 623 | |||
| 624 | if (oldval < dd->m || PTABLEVAL(pd->reached, ind) || pd->n == pd->size) | ||
| 625 | return; | ||
| 626 | |||
| 627 | ptable_set_reached(pd, ind); | ||
| 628 | |||
| 629 | if (dd->m == dd->d) { | ||
| 630 | if (dd->m < oldval) | ||
| 631 | ptable_update(pd, ind, dd->m); | ||
| 632 | return; | ||
| 633 | } | ||
| 634 | |||
| 635 | dd->m++; | ||
| 636 | dd->last2 = dd->last1; | ||
| 637 | |||
| 638 | for (i = 0; dd->sorted_moves[i] != NULLMOVE; i++) { | ||
| 639 | move = dd->sorted_moves[i]; | ||
| 640 | if (possible_next[l2][l1][move]) { | ||
| 641 | dd->last1 = move; | ||
| 642 | generate_ptable_dfs(apply_move(move, c), pd, dd); | ||
| 643 | } | ||
| 644 | } | ||
| 645 | |||
| 646 | dd->m--; | ||
| 647 | dd->last1 = l1; | ||
| 648 | dd->last2 = l2; | ||
| 649 | } | ||
| 650 | |||
| 651 | static void | ||
| 652 | index_to_perm(int p, int n, int *r) | ||
| 653 | { | ||
| 654 | int *a = malloc(n * sizeof(int)); | ||
| 655 | int i, j, c; | ||
| 656 | |||
| 657 | for (i = 0; i < n; i++) | ||
| 658 | a[i] = 0; | ||
| 659 | |||
| 660 | if (p < 0 || p >= factorial(n)) | ||
| 661 | for (i = 0; i < n; i++) | ||
| 662 | r[i] = -1; | ||
| 663 | |||
| 664 | for (i = 0; i < n; i++) { | ||
| 665 | c = 0; | ||
| 666 | j = 0; | ||
| 667 | while (c <= p / factorial(n-i-1)) | ||
| 668 | c += a[j++] ? 0 : 1; | ||
| 669 | r[i] = j-1; | ||
| 670 | a[j-1] = 1; | ||
| 671 | p %= factorial(n-i-1); | ||
| 672 | } | ||
| 673 | |||
| 674 | free(a); | ||
| 675 | } | ||
| 676 | |||
| 677 | static void | ||
| 678 | index_to_subset(int s, int n, int k, int *r) | ||
| 679 | { | ||
| 680 | int i, j, v; | ||
| 681 | |||
| 682 | if (s < 0 || s >= binomial(n, k)) { | ||
| 683 | for (i = 0; i < n; i++) | ||
| 684 | r[i] = -1; | ||
| 685 | return; | ||
| 686 | } | ||
| 687 | |||
| 688 | for (i = 0; i < n; i++) { | ||
| 689 | if (k == n-i) { | ||
| 690 | for (j = i; j < n; j++) | ||
| 691 | r[j] = 1; | ||
| 692 | return; | ||
| 693 | } | ||
| 694 | |||
| 695 | if (k == 0) { | ||
| 696 | for (j = i; j < n; j++) | ||
| 697 | r[j] = 0; | ||
| 698 | return; | ||
| 699 | } | ||
| 700 | |||
| 701 | v = binomial(n-i-1, k); | ||
| 702 | if (s >= v) { | ||
| 703 | r[i] = 1; | ||
| 704 | k--; | ||
| 705 | s -= v; | ||
| 706 | } else { | ||
| 707 | r[i] = 0; | ||
| 708 | } | ||
| 709 | } | ||
| 710 | } | ||
| 711 | |||
| 712 | static void | ||
| 713 | int_to_digit_array(int a, int b, int n, int *r) | ||
| 714 | { | ||
| 715 | int i; | ||
| 716 | |||
| 717 | if (b <= 1) | ||
| 718 | for (i = 0; i < n; i++) | ||
| 719 | r[i] = 0; | ||
| 720 | else | ||
| 721 | for (i = 0; i < n; i++, a /= b) | ||
| 722 | r[i] = a % b; | ||
| 723 | } | ||
| 724 | |||
| 725 | static void | ||
| 726 | int_to_sum_zero_array(int x, int b, int n, int *a) | ||
| 727 | { | ||
| 728 | int i, s = 0; | ||
| 729 | |||
| 730 | if (b <= 1) { | ||
| 731 | for (i = 0; i < n; i++) | ||
| 732 | a[i] = 0; | ||
| 733 | } else { | ||
| 734 | int_to_digit_array(x, b, n-1, a); | ||
| 735 | for (i = 0; i < n - 1; i++) | ||
| 736 | s = (s + a[i]) % b; | ||
| 737 | a[n-1] = (b - s) % b; | ||
| 738 | } | ||
| 739 | } | ||
| 740 | |||
| 741 | static int | ||
| 742 | invert_digits(int a, int b, int n) | ||
| 743 | { | ||
| 744 | int i, ret, *r = malloc(n * sizeof(int)); | ||
| 745 | |||
| 746 | int_to_digit_array(a, b, n, r); | ||
| 747 | for (i = 0; i < n; i++) | ||
| 748 | r[i] = (b-r[i]) % b; | ||
| 749 | |||
| 750 | ret = digit_array_to_int(r, n, b); | ||
| 751 | free(r); | ||
| 752 | return ret; | ||
| 753 | } | ||
| 754 | |||
| 755 | static bool | ||
| 756 | is_perm(int *a, int n) | ||
| 757 | { | ||
| 758 | int *aux = malloc(n * sizeof(int)); | ||
| 759 | int i; | ||
| 760 | |||
| 761 | for (i = 0; i < n; i++) | ||
| 762 | if (a[i] < 0 || a[i] >= n) | ||
| 763 | return false; | ||
| 764 | else | ||
| 765 | aux[a[i]] = 1; | ||
| 766 | |||
| 767 | for (i = 0; i < n; i++) | ||
| 768 | if (!aux[i]) | ||
| 769 | return false; | ||
| 770 | |||
| 771 | free(aux); | ||
| 772 | |||
| 773 | return true; | ||
| 774 | } | ||
| 775 | |||
| 776 | static bool | ||
| 777 | is_subset(int *a, int n, int k) | ||
| 778 | { | ||
| 779 | int i, sum = 0; | ||
| 780 | |||
| 781 | for (i = 0; i < n; i++) | ||
| 782 | sum += a[i] ? 1 : 0; | ||
| 783 | |||
| 784 | return sum == k; | ||
| 785 | } | ||
| 786 | |||
| 787 | static Cube | ||
| 788 | move_via_arrays(CubeArray *arr, Cube c, PieceFilter f) | ||
| 789 | { | ||
| 790 | CubeArray *arrc = new_cubearray(c, f); | ||
| 791 | Cube ret; | ||
| 792 | |||
| 793 | if (f.epose || f.eposs || f.eposm) | ||
| 794 | apply_permutation(arr->ep, arrc->ep, 12); | ||
| 795 | |||
| 796 | if (f.eofb) { | ||
| 797 | apply_permutation(arr->ep, arrc->eofb, 12); | ||
| 798 | sum_arrays_mod(arr->eofb, arrc->eofb, 12, 2); | ||
| 799 | } | ||
| 800 | |||
| 801 | if (f.eorl) { | ||
| 802 | apply_permutation(arr->ep, arrc->eorl, 12); | ||
| 803 | sum_arrays_mod(arr->eorl, arrc->eorl, 12, 2); | ||
| 804 | } | ||
| 805 | |||
| 806 | if (f.eoud) { | ||
| 807 | apply_permutation(arr->ep, arrc->eoud, 12); | ||
| 808 | sum_arrays_mod(arr->eoud, arrc->eoud, 12, 2); | ||
| 809 | } | ||
| 810 | |||
| 811 | if (f.cp) | ||
| 812 | apply_permutation(arr->cp, arrc->cp, 8); | ||
| 813 | |||
| 814 | if (f.coud) { | ||
| 815 | apply_permutation(arr->cp, arrc->coud, 8); | ||
| 816 | sum_arrays_mod(arr->coud, arrc->coud, 8, 3); | ||
| 817 | } | ||
| 818 | |||
| 819 | if (f.corl) { | ||
| 820 | apply_permutation(arr->cp, arrc->corl, 8); | ||
| 821 | sum_arrays_mod(arr->corl, arrc->corl, 8, 3); | ||
| 822 | } | ||
| 823 | |||
| 824 | if (f.cofb) { | ||
| 825 | apply_permutation(arr->cp, arrc->cofb, 8); | ||
| 826 | sum_arrays_mod(arr->cofb, arrc->cofb, 8, 3); | ||
| 827 | } | ||
| 828 | |||
| 829 | if (f.cpos) | ||
| 830 | apply_permutation(arr->cpos, arrc->cpos, 6); | ||
| 831 | |||
| 832 | ret = arrays_to_cube(arrc, f); | ||
| 833 | free_cubearray(arrc, f); | ||
| 834 | |||
| 835 | return ret; | ||
| 836 | } | ||
| 837 | |||
| 838 | static void | ||
| 839 | moveset_to_list(bool (*ms)(Move m), int (*f)(Cube), Move *r) | ||
| 840 | { | ||
| 841 | Cube c; | ||
| 842 | int b[NMOVES]; | ||
| 843 | int na = 0, nb = 0; | ||
| 844 | Move i; | ||
| 845 | |||
| 846 | if (ms == NULL) { | ||
| 847 | fprintf(stderr, "Error: no moveset given\n"); | ||
| 848 | return; | ||
| 849 | } | ||
| 850 | |||
| 851 | for (i = U; i < NMOVES; i++) { | ||
| 852 | if (ms(i)) { | ||
| 853 | c = apply_move(i, (Cube){0}); | ||
| 854 | if (f != NULL && f(c)) | ||
| 855 | r[na++] = i; | ||
| 856 | else | ||
| 857 | b[nb++] = i; | ||
| 858 | } | ||
| 859 | } | ||
| 860 | |||
| 861 | memcpy(r + na, b, nb * sizeof(Move)); | ||
| 862 | r[na+nb] = NULLMOVE; | ||
| 863 | } | ||
| 864 | |||
| 865 | static AlgList * | ||
| 866 | new_alglist() | ||
| 867 | { | ||
| 868 | AlgList *ret = malloc(sizeof(AlgList)); | ||
| 869 | |||
| 870 | ret->len = 0; | ||
| 871 | ret->first = NULL; | ||
| 872 | ret->last = NULL; | ||
| 873 | |||
| 874 | return ret; | ||
| 875 | } | ||
| 876 | |||
| 877 | static CubeArray * | ||
| 878 | new_cubearray(Cube cube, PieceFilter f) | ||
| 879 | { | ||
| 880 | CubeArray *arr = malloc(sizeof(CubeArray)); | ||
| 881 | |||
| 882 | if (f.epose || f.eposs || f.eposm) | ||
| 883 | arr->ep = malloc(12 * sizeof(int)); | ||
| 884 | if (f.eofb) | ||
| 885 | arr->eofb = malloc(12 * sizeof(int)); | ||
| 886 | if (f.eorl) | ||
| 887 | arr->eorl = malloc(12 * sizeof(int)); | ||
| 888 | if (f.eoud) | ||
| 889 | arr->eoud = malloc(12 * sizeof(int)); | ||
| 890 | if (f.cp) | ||
| 891 | arr->cp = malloc(8 * sizeof(int)); | ||
| 892 | if (f.coud) | ||
| 893 | arr->coud = malloc(8 * sizeof(int)); | ||
| 894 | if (f.corl) | ||
| 895 | arr->corl = malloc(8 * sizeof(int)); | ||
| 896 | if (f.cofb) | ||
| 897 | arr->cofb = malloc(8 * sizeof(int)); | ||
| 898 | if (f.cpos) | ||
| 899 | arr->cpos = malloc(6 * sizeof(int)); | ||
| 900 | |||
| 901 | cube_to_arrays(cube, arr, f); | ||
| 902 | |||
| 903 | return arr; | ||
| 904 | } | ||
| 905 | |||
| 906 | static int | ||
| 907 | perm_sign(int *a, int n) | ||
| 908 | { | ||
| 909 | int i, j, ret = 0; | ||
| 910 | |||
| 911 | if (!is_perm(a,n)) | ||
| 912 | return -1; | ||
| 913 | |||
| 914 | for (i = 0; i < n; i++) | ||
| 915 | for (j = i+1; j < n; j++) | ||
| 916 | ret += (a[i] > a[j]) ? 1 : 0; | ||
| 917 | |||
| 918 | return ret % 2; | ||
| 919 | } | ||
| 920 | |||
| 921 | static int | ||
| 922 | perm_to_index(int *a, int n) | ||
| 923 | { | ||
| 924 | int i, j, c, ret = 0; | ||
| 925 | |||
| 926 | if (!is_perm(a, n)) | ||
| 927 | return -1; | ||
| 928 | |||
| 929 | for (i = 0; i < n; i++) { | ||
| 930 | c = 0; | ||
| 931 | for (j = i+1; j < n; j++) | ||
| 932 | c += (a[i] > a[j]) ? 1 : 0; | ||
| 933 | ret += factorial(n-i-1) * c; | ||
| 934 | } | ||
| 935 | |||
| 936 | return ret; | ||
| 937 | } | ||
| 938 | |||
| 939 | static int | ||
| 940 | powint(int a, int b) | ||
| 941 | { | ||
| 942 | if (b < 0) | ||
| 943 | return 0; /* Truncate */ | ||
| 944 | if (b == 0) | ||
| 945 | return 1; | ||
| 946 | |||
| 947 | if (b % 2) | ||
| 948 | return a * powint(a, b-1); | ||
| 949 | else | ||
| 950 | return powint(a*a, b/2); | ||
| 951 | } | ||
| 952 | |||
| 953 | static void | ||
| 954 | ptable_set_reached(PruneData *pd, uint64_t ind) | ||
| 955 | { | ||
| 956 | uint8_t oldval2 = pd->reached[ind/2]; | ||
| 957 | int other = ind % 2 ? oldval2 % 16 : oldval2 / 16; | ||
| 958 | |||
| 959 | pd->reached[ind/2] = ind % 2 ? 16 + other : 16*other + 1; | ||
| 960 | } | ||
| 961 | |||
| 962 | static void | ||
| 963 | ptable_update(PruneData *pd, uint64_t ind, int n) | ||
| 964 | { | ||
| 965 | uint8_t oldval2 = pd->ptable[ind/2]; | ||
| 966 | int other = ind % 2 ? oldval2 % 16 : oldval2 / 16; | ||
| 967 | |||
| 968 | pd->ptable[ind/2] = ind % 2 ? 16*n + other : 16*other + n; | ||
| 969 | pd->n++; | ||
| 970 | } | ||
| 971 | |||
| 972 | static bool | ||
| 973 | read_mtables_file() | ||
| 974 | { | ||
| 975 | FILE *f; | ||
| 976 | char fname[strlen(tabledir)+20]; | ||
| 977 | int m, b = sizeof(uint16_t); | ||
| 978 | bool r = true; | ||
| 979 | |||
| 980 | strcpy(fname, tabledir); | ||
| 981 | strcat(fname, "/mtables"); | ||
| 982 | |||
| 983 | if ((f = fopen(fname, "rb")) == NULL) | ||
| 984 | return false; | ||
| 985 | |||
| 986 | for (m = 0; m < NMOVES; m++) { | ||
| 987 | r = r && fread(epose_mtable[m], b, me[0], f) == me[0]; | ||
| 988 | r = r && fread(eposs_mtable[m], b, me[1], f) == me[1]; | ||
| 989 | r = r && fread(eposm_mtable[m], b, me[2], f) == me[2]; | ||
| 990 | r = r && fread(eofb_mtable[m], b, me[3], f) == me[3]; | ||
| 991 | r = r && fread(eorl_mtable[m], b, me[4], f) == me[4]; | ||
| 992 | r = r && fread(eoud_mtable[m], b, me[5], f) == me[5]; | ||
| 993 | r = r && fread(cp_mtable[m], b, me[6], f) == me[6]; | ||
| 994 | r = r && fread(coud_mtable[m], b, me[7], f) == me[7]; | ||
| 995 | r = r && fread(corl_mtable[m], b, me[8], f) == me[8]; | ||
| 996 | r = r && fread(cofb_mtable[m], b, me[9], f) == me[9]; | ||
| 997 | r = r && fread(cpos_mtable[m], b, me[10], f) == me[10]; | ||
| 998 | } | ||
| 999 | |||
| 1000 | fclose(f); | ||
| 1001 | return r; | ||
| 1002 | } | ||
| 1003 | |||
| 1004 | static bool | ||
| 1005 | read_ptable_file(PruneData *pd) | ||
| 1006 | { | ||
| 1007 | FILE *f; | ||
| 1008 | char fname[strlen(tabledir)+100]; | ||
| 1009 | uint64_t r; | ||
| 1010 | |||
| 1011 | strcpy(fname, tabledir); | ||
| 1012 | strcat(fname, "/"); | ||
| 1013 | strcat(fname, pd->filename); | ||
| 1014 | |||
| 1015 | if ((f = fopen(fname, "rb")) == NULL) | ||
| 1016 | return false; | ||
| 1017 | |||
| 1018 | r = fread(pd->ptable, sizeof(uint8_t), PTABLESIZE(pd->size), f); | ||
| 1019 | fclose(f); | ||
| 1020 | |||
| 1021 | return r == PTABLESIZE(pd->size); | ||
| 1022 | } | ||
| 1023 | |||
| 1024 | static bool | ||
| 1025 | read_ttables_file() | ||
| 1026 | { | ||
| 1027 | FILE *f; | ||
| 1028 | char fname[strlen(tabledir)+20]; | ||
| 1029 | int b = sizeof(uint16_t); | ||
| 1030 | bool r = true; | ||
| 1031 | Move m; | ||
| 1032 | |||
| 1033 | strcpy(fname, tabledir); | ||
| 1034 | strcat(fname, "/"); | ||
| 1035 | strcat(fname, "ttables"); | ||
| 1036 | |||
| 1037 | if ((f = fopen(fname, "rb")) == NULL) | ||
| 1038 | return false; | ||
| 1039 | |||
| 1040 | for (m = 0; m < NTRANS; m++) { | ||
| 1041 | r = r && fread(epose_ttable[m], b, me[0], f) == me[0]; | ||
| 1042 | r = r && fread(eposs_ttable[m], b, me[1], f) == me[1]; | ||
| 1043 | r = r && fread(eposm_ttable[m], b, me[2], f) == me[2]; | ||
| 1044 | r = r && fread(eo_ttable[m], b, me[3], f) == me[3]; | ||
| 1045 | r = r && fread(cp_ttable[m], b, me[6], f) == me[6]; | ||
| 1046 | r = r && fread(co_ttable[m], b, me[7], f) == me[7]; | ||
| 1047 | r = r && fread(cpos_ttable[m], b, me[10], f) == me[10]; | ||
| 1048 | r = r && fread(moves_ttable[m], b, me[11], f) == me[11]; | ||
| 1049 | } | ||
| 1050 | |||
| 1051 | fclose(f); | ||
| 1052 | return r; | ||
| 1053 | } | ||
| 1054 | |||
| 1055 | static Cube | ||
| 1056 | rotate_via_compose(Trans r, Cube c, PieceFilter f) | ||
| 1057 | { | ||
| 1058 | Alg *inv; | ||
| 1059 | static int zero12[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; | ||
| 1060 | static int zero8[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; | ||
| 1061 | static CubeArray ma = { | ||
| 1062 | .ep = ep_mirror, | ||
| 1063 | .eofb = zero12, | ||
| 1064 | .eorl = zero12, | ||
| 1065 | .eoud = zero12, | ||
| 1066 | .cp = cp_mirror, | ||
| 1067 | .coud = zero8, | ||
| 1068 | .corl = zero8, | ||
| 1069 | .cofb = zero8, | ||
| 1070 | .cpos = cpos_mirror | ||
| 1071 | }; | ||
| 1072 | |||
| 1073 | Cube ret; | ||
| 1074 | |||
| 1075 | if (r != mirror) { | ||
| 1076 | ret = apply_alg_generic(trans_algs[r], c, f, true); | ||
| 1077 | inv = on_inverse(trans_algs[r]); | ||
| 1078 | ret = apply_alg_generic(inv, ret, f, true); | ||
| 1079 | free_alg(inv); | ||
| 1080 | } else { | ||
| 1081 | ret = move_via_arrays(&ma, (Cube){0}, f); | ||
| 1082 | ret = compose_filtered(c, ret, f); | ||
| 1083 | ret = move_via_arrays(&ma, ret, f); | ||
| 1084 | } | ||
| 1085 | |||
| 1086 | return ret; | ||
| 1087 | } | ||
| 1088 | |||
| 1089 | static void | ||
| 1090 | solve_dfs(Cube c, Step s, SolveOptions *opts, DfsData *dd) | ||
| 1091 | { | ||
| 1092 | Move move, l1 = dd->last1, l2 = dd->last2; | ||
| 1093 | int i, lower_bound = s.check(c); | ||
| 1094 | bool found_many, prune, niss_make_sense, nissbackup = dd->niss; | ||
| 1095 | |||
| 1096 | if (opts->can_niss && !dd->niss) | ||
| 1097 | lower_bound = MIN(1, lower_bound); | ||
| 1098 | |||
| 1099 | found_many = dd->sols->len >= opts->max_solutions; | ||
| 1100 | prune = dd->current_alg->len + lower_bound > dd->d; | ||
| 1101 | if (found_many || prune) | ||
| 1102 | return; | ||
| 1103 | |||
| 1104 | if (lower_bound == 0) { | ||
| 1105 | if (dd->current_alg->len == dd->d) | ||
| 1106 | append_alg(dd->sols, dd->current_alg); | ||
| 1107 | return; | ||
| 1108 | } | ||
| 1109 | |||
| 1110 | dd->last2 = dd->last1; | ||
| 1111 | |||
| 1112 | for (i = 0; dd->sorted_moves[i] != NULLMOVE; i++) { | ||
| 1113 | move = dd->sorted_moves[i]; | ||
| 1114 | if (possible_next[l2][l1][move]) { | ||
| 1115 | dd->last1 = move; | ||
| 1116 | append_move(dd->current_alg, move, dd->niss); | ||
| 1117 | solve_dfs(apply_move(move, c), s, opts, dd); | ||
| 1118 | dd->current_alg->len--; | ||
| 1119 | } | ||
| 1120 | } | ||
| 1121 | |||
| 1122 | niss_make_sense = !dd->current_alg->len || | ||
| 1123 | (s.check(apply_move(l1,(Cube){0}))); | ||
| 1124 | if (opts->can_niss && !dd->niss && niss_make_sense) { | ||
| 1125 | dd->niss = true; | ||
| 1126 | dd->last1 = NULLMOVE; | ||
| 1127 | dd->last2 = NULLMOVE; | ||
| 1128 | solve_dfs(inverse_cube(c), s, opts, dd); | ||
| 1129 | } | ||
| 1130 | |||
| 1131 | dd->last1 = l1; | ||
| 1132 | dd->last2 = l2; | ||
| 1133 | dd->niss = nissbackup; | ||
| 1134 | } | ||
| 1135 | |||
| 1136 | static int | ||
| 1137 | subset_to_index(int *a, int n, int k) | ||
| 1138 | { | ||
| 1139 | int i, ret = 0; | ||
| 1140 | |||
| 1141 | if (!is_subset(a, n, k)) | ||
| 1142 | return binomial(n, k); | ||
| 1143 | |||
| 1144 | for (i = 0; i < n; i++) { | ||
| 1145 | if (k == n-i) | ||
| 1146 | return ret; | ||
| 1147 | if (a[i]) { | ||
| 1148 | ret += binomial(n-i-1, k); | ||
| 1149 | k--; | ||
| 1150 | } | ||
| 1151 | } | ||
| 1152 | |||
| 1153 | return ret; | ||
| 1154 | } | ||
| 1155 | |||
| 1156 | static void | ||
| 1157 | sum_arrays_mod(int *src, int *dst, int n, int m) | ||
| 1158 | { | ||
| 1159 | int i; | ||
| 1160 | |||
| 1161 | for (i = 0; i < n; i++) | ||
| 1162 | dst[i] = (m <= 0) ? 0 : (src[i] + dst[i]) % m; | ||
| 1163 | } | ||
| 1164 | |||
| 1165 | static void | ||
| 1166 | swap(int *a, int *b) | ||
| 1167 | { | ||
| 1168 | int aux; | ||
| 1169 | |||
| 1170 | aux = *a; | ||
| 1171 | *a = *b; | ||
| 1172 | *b = aux; | ||
| 1173 | } | ||
| 1174 | |||
| 1175 | static bool | ||
| 1176 | write_mtables_file() | ||
| 1177 | { | ||
| 1178 | FILE *f; | ||
| 1179 | char fname[strlen(tabledir)+20]; | ||
| 1180 | int m, b = sizeof(uint16_t); | ||
| 1181 | bool r = true; | ||
| 1182 | |||
| 1183 | strcpy(fname, tabledir); | ||
| 1184 | strcat(fname, "/mtables"); | ||
| 1185 | |||
| 1186 | if ((f = fopen(fname, "wb")) == NULL) | ||
| 1187 | return false; | ||
| 1188 | |||
| 1189 | for (m = 0; m < NMOVES; m++) { | ||
| 1190 | r = r && fwrite(epose_mtable[m], b, me[0], f) == me[0]; | ||
| 1191 | r = r && fwrite(eposs_mtable[m], b, me[1], f) == me[1]; | ||
| 1192 | r = r && fwrite(eposm_mtable[m], b, me[2], f) == me[2]; | ||
| 1193 | r = r && fwrite(eofb_mtable[m], b, me[3], f) == me[3]; | ||
| 1194 | r = r && fwrite(eorl_mtable[m], b, me[4], f) == me[4]; | ||
| 1195 | r = r && fwrite(eoud_mtable[m], b, me[5], f) == me[5]; | ||
| 1196 | r = r && fwrite(cp_mtable[m], b, me[6], f) == me[6]; | ||
| 1197 | r = r && fwrite(coud_mtable[m], b, me[7], f) == me[7]; | ||
| 1198 | r = r && fwrite(corl_mtable[m], b, me[8], f) == me[8]; | ||
| 1199 | r = r && fwrite(cofb_mtable[m], b, me[9], f) == me[9]; | ||
| 1200 | r = r && fwrite(cpos_mtable[m], b, me[10], f) == me[10]; | ||
| 1201 | } | ||
| 1202 | |||
| 1203 | fclose(f); | ||
| 1204 | return r; | ||
| 1205 | } | ||
| 1206 | |||
| 1207 | static bool | ||
| 1208 | write_ptable_file(PruneData *pd) | ||
| 1209 | { | ||
| 1210 | FILE *f; | ||
| 1211 | char fname[strlen(tabledir)+100]; | ||
| 1212 | uint64_t written; | ||
| 1213 | |||
| 1214 | strcpy(fname, tabledir); | ||
| 1215 | strcat(fname, "/"); | ||
| 1216 | strcat(fname, pd->filename); | ||
| 1217 | |||
| 1218 | if ((f = fopen(fname, "wb")) == NULL) | ||
| 1219 | return false; | ||
| 1220 | |||
| 1221 | written = fwrite(pd->ptable, sizeof(uint8_t), PTABLESIZE(pd->size), f); | ||
| 1222 | fclose(f); | ||
| 1223 | |||
| 1224 | return written == PTABLESIZE(pd->size); | ||
| 1225 | } | ||
| 1226 | |||
| 1227 | static bool | ||
| 1228 | write_ttables_file() | ||
| 1229 | { | ||
| 1230 | FILE *f; | ||
| 1231 | char fname[strlen(tabledir)+20]; | ||
| 1232 | bool r = true; | ||
| 1233 | int b = sizeof(uint16_t); | ||
| 1234 | Move m; | ||
| 1235 | |||
| 1236 | strcpy(fname, tabledir); | ||
| 1237 | strcat(fname, "/ttables"); | ||
| 1238 | |||
| 1239 | if ((f = fopen(fname, "wb")) == NULL) | ||
| 1240 | return false; | ||
| 1241 | |||
| 1242 | for (m = 0; m < NTRANS; m++) { | ||
| 1243 | r = r && fwrite(epose_ttable[m], b, me[0], f) == me[0]; | ||
| 1244 | r = r && fwrite(eposs_ttable[m], b, me[1], f) == me[1]; | ||
| 1245 | r = r && fwrite(eposm_ttable[m], b, me[2], f) == me[2]; | ||
| 1246 | r = r && fwrite(eo_ttable[m], b, me[3], f) == me[3]; | ||
| 1247 | r = r && fwrite(cp_ttable[m], b, me[6], f) == me[6]; | ||
| 1248 | r = r && fwrite(co_ttable[m], b, me[7], f) == me[7]; | ||
| 1249 | r = r && fwrite(cpos_ttable[m], b, me[10], f) == me[10]; | ||
| 1250 | r = r && fwrite(moves_ttable[m], b, me[11], f) == me[11]; | ||
| 1251 | } | ||
| 1252 | |||
| 1253 | fclose(f); | ||
| 1254 | return r; | ||
| 1255 | } | ||
| 1256 | |||
| 1257 | /* Init functions implementation *********************************************/ | ||
| 1258 | |||
| 1259 | static void | ||
| 1260 | init_auxtables() | ||
| 1261 | { | ||
| 1262 | Cube c1, c2; | ||
| 1263 | uint64_t ui, uj; | ||
| 1264 | int i, j, k; | ||
| 1265 | bool cij, p1, p2; | ||
| 1266 | |||
| 1267 | for (ui = 0; ui < BINOM12ON4; ui++) | ||
| 1268 | for (uj = 0; uj < BINOM12ON4; uj++) | ||
| 1269 | epos_dependent_aux[ui][uj] = epos_dependent(ui, uj); | ||
| 1270 | |||
| 1271 | for (i = 0; i < NMOVES; i++) { | ||
| 1272 | for (j = 0; j < NMOVES; j++) { | ||
| 1273 | c1 = apply_move(i, apply_move(j, (Cube){0})); | ||
| 1274 | c2 = apply_move(j, apply_move(i, (Cube){0})); | ||
| 1275 | commute[i][j] = equal(c1, c2); | ||
| 1276 | } | ||
| 1277 | } | ||
| 1278 | |||
| 1279 | for (i = 0; i < NMOVES; i++) { | ||
| 1280 | for (j = 0; j < NMOVES; j++) { | ||
| 1281 | for (k = 0; k < NMOVES; k++) { | ||
| 1282 | p1 = j && base_move(j) == base_move(k); | ||
| 1283 | p2 = i && base_move(i) == base_move(k); | ||
| 1284 | cij = commute[i][j]; | ||
| 1285 | possible_next[i][j][k] = !(p1 || (cij && p2)); | ||
| 1286 | } | ||
| 1287 | } | ||
| 1288 | } | ||
| 1289 | |||
| 1290 | for (i = 0; i < NMOVES; i++) | ||
| 1291 | inverse_move_aux[i] = i ? i + 2 - 2*((i-1)%3) : NULLMOVE; | ||
| 1292 | |||
| 1293 | /* Is there a more elegant way? */ | ||
| 1294 | inverse_trans_aux[uf] = uf; | ||
| 1295 | inverse_trans_aux[ur] = ul; | ||
| 1296 | inverse_trans_aux[ul] = ur; | ||
| 1297 | inverse_trans_aux[ub] = ub; | ||
| 1298 | |||
| 1299 | inverse_trans_aux[df] = df; | ||
| 1300 | inverse_trans_aux[dr] = dr; | ||
| 1301 | inverse_trans_aux[dl] = dl; | ||
| 1302 | inverse_trans_aux[db] = db; | ||
| 1303 | |||
| 1304 | inverse_trans_aux[rf] = lf; | ||
| 1305 | inverse_trans_aux[rd] = bl; | ||
| 1306 | inverse_trans_aux[rb] = rb; | ||
| 1307 | inverse_trans_aux[ru] = fr; | ||
| 1308 | |||
| 1309 | inverse_trans_aux[lf] = rf; | ||
| 1310 | inverse_trans_aux[ld] = br; | ||
| 1311 | inverse_trans_aux[lb] = lb; | ||
| 1312 | inverse_trans_aux[lu] = fl; | ||
| 1313 | |||
| 1314 | inverse_trans_aux[fu] = fu; | ||
| 1315 | inverse_trans_aux[fr] = ru; | ||
| 1316 | inverse_trans_aux[fd] = bu; | ||
| 1317 | inverse_trans_aux[fl] = lu; | ||
| 1318 | |||
| 1319 | inverse_trans_aux[bu] = fd; | ||
| 1320 | inverse_trans_aux[br] = ld; | ||
| 1321 | inverse_trans_aux[bd] = bd; | ||
| 1322 | inverse_trans_aux[bl] = rd; | ||
| 1323 | |||
| 1324 | inverse_trans_aux[mirror] = mirror; | ||
| 1325 | } | ||
| 1326 | |||
| 1327 | static void | ||
| 1328 | init_environment() | ||
| 1329 | { | ||
| 1330 | char *nissydata = getenv("NISSYDATA"); | ||
| 1331 | char *localdata = getenv("XDG_DATA_HOME"); | ||
| 1332 | char *home = getenv("HOME"); | ||
| 1333 | bool read, write; | ||
| 1334 | |||
| 1335 | if (nissydata != NULL) { | ||
| 1336 | tabledir = malloc(strlen(nissydata) * sizeof(char) + 20); | ||
| 1337 | strcpy(tabledir, nissydata); | ||
| 1338 | } else if (localdata != NULL) { | ||
| 1339 | tabledir = malloc(strlen(localdata) * sizeof(char) + 20); | ||
| 1340 | strcpy(tabledir, localdata); | ||
| 1341 | strcat(tabledir, "/nissy"); | ||
| 1342 | } else if (home != NULL) { | ||
| 1343 | tabledir = malloc(strlen(home) * sizeof(char) + 20); | ||
| 1344 | strcpy(tabledir, home); | ||
| 1345 | strcat(tabledir, "/.nissy"); | ||
| 1346 | } | ||
| 1347 | |||
| 1348 | mkdir(tabledir, 0777); | ||
| 1349 | strcat(tabledir, "/tables"); | ||
| 1350 | mkdir(tabledir, 0777); | ||
| 1351 | |||
| 1352 | read = !access(tabledir, R_OK); | ||
| 1353 | write = !access(tabledir, W_OK); | ||
| 1354 | |||
| 1355 | if (!read) { | ||
| 1356 | fprintf(stderr, "Table files cannot be read.\n"); | ||
| 1357 | } else if (!write) { | ||
| 1358 | fprintf(stderr, "Data directory not writable: "); | ||
| 1359 | fprintf(stderr, "tables can be loaded, but not saved.\n"); | ||
| 1360 | } | ||
| 1361 | } | ||
| 1362 | |||
| 1363 | static void | ||
| 1364 | init_moves() { | ||
| 1365 | Cube c; | ||
| 1366 | CubeArray arrs; | ||
| 1367 | int i; | ||
| 1368 | uint16_t ui; | ||
| 1369 | Move m; | ||
| 1370 | |||
| 1371 | /* Generate all move cycles and flips; I do this regardless */ | ||
| 1372 | for (i = 0; i < NMOVES; i++) { | ||
| 1373 | if (i == U || i == x || i == y) | ||
| 1374 | continue; | ||
| 1375 | |||
| 1376 | c = apply_alg_generic(equiv_alg[i], (Cube){0}, pf_all, false); | ||
| 1377 | |||
| 1378 | arrs = (CubeArray){ | ||
| 1379 | edge_cycle[i], | ||
| 1380 | eofb_flipped[i], | ||
| 1381 | eorl_flipped[i], | ||
| 1382 | eoud_flipped[i], | ||
| 1383 | corner_cycle[i], | ||
| 1384 | coud_flipped[i], | ||
| 1385 | corl_flipped[i], | ||
| 1386 | cofb_flipped[i], | ||
| 1387 | center_cycle[i] | ||
| 1388 | }; | ||
| 1389 | cube_to_arrays(c, &arrs, pf_all); | ||
| 1390 | } | ||
| 1391 | |||
| 1392 | if (read_mtables_file()) | ||
| 1393 | return; | ||
| 1394 | |||
| 1395 | fprintf(stderr, "Cannot load %s, generating it\n", "mtables"); | ||
| 1396 | |||
| 1397 | /* Initialize transition tables */ | ||
| 1398 | for (m = 0; m < NMOVES; m++) { | ||
| 1399 | for (ui = 0; ui < FACTORIAL12/FACTORIAL8; ui++) { | ||
| 1400 | c = (Cube){ .epose = ui }; | ||
| 1401 | c = apply_move_cubearray(m, c, pf_e); | ||
| 1402 | epose_mtable[m][ui] = c.epose; | ||
| 1403 | |||
| 1404 | c = (Cube){ .eposs = ui }; | ||
| 1405 | c = apply_move_cubearray(m, c, pf_s); | ||
| 1406 | eposs_mtable[m][ui] = c.eposs; | ||
| 1407 | |||
| 1408 | c = (Cube){ .eposm = ui }; | ||
| 1409 | c = apply_move_cubearray(m, c, pf_m); | ||
| 1410 | eposm_mtable[m][ui] = c.eposm; | ||
| 1411 | } | ||
| 1412 | for (ui = 0; ui < POW2TO11; ui++ ) { | ||
| 1413 | c = (Cube){ .eofb = ui }; | ||
| 1414 | c = apply_move_cubearray(m, c, pf_eo); | ||
| 1415 | eofb_mtable[m][ui] = c.eofb; | ||
| 1416 | |||
| 1417 | c = (Cube){ .eorl = ui }; | ||
| 1418 | c = apply_move_cubearray(m, c, pf_eo); | ||
| 1419 | eorl_mtable[m][ui] = c.eorl; | ||
| 1420 | |||
| 1421 | c = (Cube){ .eoud = ui }; | ||
| 1422 | c = apply_move_cubearray(m, c, pf_eo); | ||
| 1423 | eoud_mtable[m][ui] = c.eoud; | ||
| 1424 | } | ||
| 1425 | for (ui = 0; ui < POW3TO7; ui++) { | ||
| 1426 | c = (Cube){ .coud = ui }; | ||
| 1427 | c = apply_move_cubearray(m, c, pf_co); | ||
| 1428 | coud_mtable[m][ui] = c.coud; | ||
| 1429 | |||
| 1430 | c = (Cube){ .corl = ui }; | ||
| 1431 | c = apply_move_cubearray(m, c, pf_co); | ||
| 1432 | corl_mtable[m][ui] = c.corl; | ||
| 1433 | |||
| 1434 | c = (Cube){ .cofb = ui }; | ||
| 1435 | c = apply_move_cubearray(m, c, pf_co); | ||
| 1436 | cofb_mtable[m][ui] = c.cofb; | ||
| 1437 | } | ||
| 1438 | for (ui = 0; ui < FACTORIAL8; ui++) { | ||
| 1439 | c = (Cube){ .cp = ui }; | ||
| 1440 | c = apply_move_cubearray(m, c, pf_cp); | ||
| 1441 | cp_mtable[m][ui] = c.cp; | ||
| 1442 | } | ||
| 1443 | for (ui = 0; ui < FACTORIAL6; ui++) { | ||
| 1444 | c = (Cube){ .cpos = ui }; | ||
| 1445 | c = apply_move_cubearray(m, c, pf_cpos); | ||
| 1446 | cpos_mtable[m][ui] = c.cpos; | ||
| 1447 | } | ||
| 1448 | } | ||
| 1449 | |||
| 1450 | if (!write_mtables_file()) | ||
| 1451 | fprintf(stderr, "Error writing mtables\n"); | ||
| 1452 | } | ||
| 1453 | |||
| 1454 | static void | ||
| 1455 | init_moves_aux() | ||
| 1456 | { | ||
| 1457 | /* Some standard PieceFilters */ | ||
| 1458 | pf_all.epose = true; | ||
| 1459 | pf_all.eposs = true; | ||
| 1460 | pf_all.eposm = true; | ||
| 1461 | pf_all.eofb = true; | ||
| 1462 | pf_all.eorl = true; | ||
| 1463 | pf_all.eoud = true; | ||
| 1464 | pf_all.cp = true; | ||
| 1465 | pf_all.cofb = true; | ||
| 1466 | pf_all.corl = true; | ||
| 1467 | pf_all.coud = true; | ||
| 1468 | pf_all.cpos = true; | ||
| 1469 | |||
| 1470 | pf_4val.epose = true; | ||
| 1471 | pf_4val.eposs = true; | ||
| 1472 | pf_4val.eposm = true; | ||
| 1473 | pf_4val.eofb = true; | ||
| 1474 | pf_4val.coud = true; | ||
| 1475 | pf_4val.cp = true; | ||
| 1476 | |||
| 1477 | pf_epcp.epose = true; | ||
| 1478 | pf_epcp.eposs = true; | ||
| 1479 | pf_epcp.eposm = true; | ||
| 1480 | pf_epcp.cp = true; | ||
| 1481 | |||
| 1482 | pf_cpos.cpos = true; | ||
| 1483 | |||
| 1484 | pf_cp.cp = true; | ||
| 1485 | |||
| 1486 | pf_ep.epose = true; | ||
| 1487 | pf_ep.eposs = true; | ||
| 1488 | pf_ep.eposm = true; | ||
| 1489 | |||
| 1490 | pf_e.epose = true; | ||
| 1491 | pf_s.eposs = true; | ||
| 1492 | pf_m.eposm = true; | ||
| 1493 | |||
| 1494 | pf_eo.eofb = true; | ||
| 1495 | pf_eo.eorl = true; | ||
| 1496 | pf_eo.eoud = true; | ||
| 1497 | |||
| 1498 | pf_co.cofb = true; | ||
| 1499 | pf_co.corl = true; | ||
| 1500 | pf_co.coud = true; | ||
| 1501 | |||
| 1502 | /* Used to convert to and from CubeArray */ | ||
| 1503 | epe_solved[0] = FR; | ||
| 1504 | epe_solved[1] = FL; | ||
| 1505 | epe_solved[2] = BL; | ||
| 1506 | epe_solved[3] = BR; | ||
| 1507 | |||
| 1508 | eps_solved[0] = UL; | ||
| 1509 | eps_solved[1] = UR; | ||
| 1510 | eps_solved[2] = DL; | ||
| 1511 | eps_solved[3] = DR; | ||
| 1512 | |||
| 1513 | epm_solved[0] = UF; | ||
| 1514 | epm_solved[1] = UB; | ||
| 1515 | epm_solved[2] = DF; | ||
| 1516 | epm_solved[3] = DB; | ||
| 1517 | |||
| 1518 | /* Table sizes, used for reading and writing files */ | ||
| 1519 | me[0] = FACTORIAL12/FACTORIAL8; | ||
| 1520 | me[1] = FACTORIAL12/FACTORIAL8; | ||
| 1521 | me[2] = FACTORIAL12/FACTORIAL8; | ||
| 1522 | me[3] = POW2TO11; | ||
| 1523 | me[4] = POW2TO11; | ||
| 1524 | me[5] = POW2TO11; | ||
| 1525 | me[6] = FACTORIAL8; | ||
| 1526 | me[7] = POW3TO7; | ||
| 1527 | me[8] = POW3TO7; | ||
| 1528 | me[9] = POW3TO7; | ||
| 1529 | me[10] = FACTORIAL6; | ||
| 1530 | me[11] = NMOVES; | ||
| 1531 | |||
| 1532 | /* Cycles *********************/ | ||
| 1533 | edge_cycle[U][UF] = UR; | ||
| 1534 | edge_cycle[U][UL] = UF; | ||
| 1535 | edge_cycle[U][UB] = UL; | ||
| 1536 | edge_cycle[U][UR] = UB; | ||
| 1537 | edge_cycle[U][DF] = DF; | ||
| 1538 | edge_cycle[U][DL] = DL; | ||
| 1539 | edge_cycle[U][DB] = DB; | ||
| 1540 | edge_cycle[U][DR] = DR; | ||
| 1541 | edge_cycle[U][FR] = FR; | ||
| 1542 | edge_cycle[U][FL] = FL; | ||
| 1543 | edge_cycle[U][BL] = BL; | ||
| 1544 | edge_cycle[U][BR] = BR; | ||
| 1545 | |||
| 1546 | edge_cycle[x][UF] = DF; | ||
| 1547 | edge_cycle[x][UL] = FL; | ||
| 1548 | edge_cycle[x][UB] = UF; | ||
| 1549 | edge_cycle[x][UR] = FR; | ||
| 1550 | edge_cycle[x][DF] = DB; | ||
| 1551 | edge_cycle[x][DL] = BL; | ||
| 1552 | edge_cycle[x][DB] = UB; | ||
| 1553 | edge_cycle[x][DR] = BR; | ||
| 1554 | edge_cycle[x][FR] = DR; | ||
| 1555 | edge_cycle[x][FL] = DL; | ||
| 1556 | edge_cycle[x][BL] = UL; | ||
| 1557 | edge_cycle[x][BR] = UR; | ||
| 1558 | |||
| 1559 | edge_cycle[y][UF] = UR; | ||
| 1560 | edge_cycle[y][UL] = UF; | ||
| 1561 | edge_cycle[y][UB] = UL; | ||
| 1562 | edge_cycle[y][UR] = UB; | ||
| 1563 | edge_cycle[y][DF] = DR; | ||
| 1564 | edge_cycle[y][DL] = DF; | ||
| 1565 | edge_cycle[y][DB] = DL; | ||
| 1566 | edge_cycle[y][DR] = DB; | ||
| 1567 | edge_cycle[y][FR] = BR; | ||
| 1568 | edge_cycle[y][FL] = FR; | ||
| 1569 | edge_cycle[y][BL] = FL; | ||
| 1570 | edge_cycle[y][BR] = BL; | ||
| 1571 | |||
| 1572 | corner_cycle[U][UFR] = UBR; | ||
| 1573 | corner_cycle[U][UFL] = UFR; | ||
| 1574 | corner_cycle[U][UBL] = UFL; | ||
| 1575 | corner_cycle[U][UBR] = UBL; | ||
| 1576 | corner_cycle[U][DFR] = DFR; | ||
| 1577 | corner_cycle[U][DFL] = DFL; | ||
| 1578 | corner_cycle[U][DBL] = DBL; | ||
| 1579 | corner_cycle[U][DBR] = DBR; | ||
| 1580 | |||
| 1581 | corner_cycle[x][UFR] = DFR; | ||
| 1582 | corner_cycle[x][UFL] = DFL; | ||
| 1583 | corner_cycle[x][UBL] = UFL; | ||
| 1584 | corner_cycle[x][UBR] = UFR; | ||
| 1585 | corner_cycle[x][DFR] = DBR; | ||
| 1586 | corner_cycle[x][DFL] = DBL; | ||
| 1587 | corner_cycle[x][DBL] = UBL; | ||
| 1588 | corner_cycle[x][DBR] = UBR; | ||
| 1589 | |||
| 1590 | corner_cycle[y][UFR] = UBR; | ||
| 1591 | corner_cycle[y][UFL] = UFR; | ||
| 1592 | corner_cycle[y][UBL] = UFL; | ||
| 1593 | corner_cycle[y][UBR] = UBL; | ||
| 1594 | corner_cycle[y][DFR] = DBR; | ||
| 1595 | corner_cycle[y][DFL] = DFR; | ||
| 1596 | corner_cycle[y][DBL] = DFL; | ||
| 1597 | corner_cycle[y][DBR] = DBL; | ||
| 1598 | |||
| 1599 | center_cycle[U][U_center] = U_center; | ||
| 1600 | center_cycle[U][D_center] = D_center; | ||
| 1601 | center_cycle[U][R_center] = R_center; | ||
| 1602 | center_cycle[U][L_center] = L_center; | ||
| 1603 | center_cycle[U][F_center] = F_center; | ||
| 1604 | center_cycle[U][B_center] = B_center; | ||
| 1605 | |||
| 1606 | center_cycle[x][U_center] = F_center; | ||
| 1607 | center_cycle[x][D_center] = B_center; | ||
| 1608 | center_cycle[x][R_center] = R_center; | ||
| 1609 | center_cycle[x][L_center] = L_center; | ||
| 1610 | center_cycle[x][F_center] = D_center; | ||
| 1611 | center_cycle[x][B_center] = U_center; | ||
| 1612 | |||
| 1613 | center_cycle[y][U_center] = U_center; | ||
| 1614 | center_cycle[y][D_center] = D_center; | ||
| 1615 | center_cycle[y][R_center] = B_center; | ||
| 1616 | center_cycle[y][L_center] = F_center; | ||
| 1617 | center_cycle[y][F_center] = R_center; | ||
| 1618 | center_cycle[y][B_center] = L_center; | ||
| 1619 | |||
| 1620 | /* Flipped pieces *************/ | ||
| 1621 | eofb_flipped[x][UF] = 1; | ||
| 1622 | eofb_flipped[x][UB] = 1; | ||
| 1623 | eofb_flipped[x][DF] = 1; | ||
| 1624 | eofb_flipped[x][DB] = 1; | ||
| 1625 | |||
| 1626 | eofb_flipped[y][FR] = 1; | ||
| 1627 | eofb_flipped[y][FL] = 1; | ||
| 1628 | eofb_flipped[y][BL] = 1; | ||
| 1629 | eofb_flipped[y][BR] = 1; | ||
| 1630 | |||
| 1631 | eorl_flipped[x][UF] = 1; | ||
| 1632 | eorl_flipped[x][UL] = 1; | ||
| 1633 | eorl_flipped[x][UB] = 1; | ||
| 1634 | eorl_flipped[x][UR] = 1; | ||
| 1635 | eorl_flipped[x][DF] = 1; | ||
| 1636 | eorl_flipped[x][DL] = 1; | ||
| 1637 | eorl_flipped[x][DB] = 1; | ||
| 1638 | eorl_flipped[x][DR] = 1; | ||
| 1639 | eorl_flipped[x][FR] = 1; | ||
| 1640 | eorl_flipped[x][FL] = 1; | ||
| 1641 | eorl_flipped[x][BL] = 1; | ||
| 1642 | eorl_flipped[x][BR] = 1; | ||
| 1643 | |||
| 1644 | eorl_flipped[y][FR] = 1; | ||
| 1645 | eorl_flipped[y][FL] = 1; | ||
| 1646 | eorl_flipped[y][BL] = 1; | ||
| 1647 | eorl_flipped[y][BR] = 1; | ||
| 1648 | |||
| 1649 | eoud_flipped[U][UF] = 1; | ||
| 1650 | eoud_flipped[U][UL] = 1; | ||
| 1651 | eoud_flipped[U][UB] = 1; | ||
| 1652 | eoud_flipped[U][UR] = 1; | ||
| 1653 | |||
| 1654 | eoud_flipped[x][UF] = 1; | ||
| 1655 | eoud_flipped[x][UB] = 1; | ||
| 1656 | eoud_flipped[x][DF] = 1; | ||
| 1657 | eoud_flipped[x][DB] = 1; | ||
| 1658 | |||
| 1659 | eoud_flipped[y][UF] = 1; | ||
| 1660 | eoud_flipped[y][UL] = 1; | ||
| 1661 | eoud_flipped[y][UB] = 1; | ||
| 1662 | eoud_flipped[y][UR] = 1; | ||
| 1663 | eoud_flipped[y][DF] = 1; | ||
| 1664 | eoud_flipped[y][DL] = 1; | ||
| 1665 | eoud_flipped[y][DB] = 1; | ||
| 1666 | eoud_flipped[y][DR] = 1; | ||
| 1667 | eoud_flipped[y][FR] = 1; | ||
| 1668 | eoud_flipped[y][FL] = 1; | ||
| 1669 | eoud_flipped[y][BL] = 1; | ||
| 1670 | eoud_flipped[y][BR] = 1; | ||
| 1671 | |||
| 1672 | coud_flipped[x][UFR] = 2; | ||
| 1673 | coud_flipped[x][UFL] = 1; | ||
| 1674 | coud_flipped[x][UBR] = 1; | ||
| 1675 | coud_flipped[x][UBL] = 2; | ||
| 1676 | coud_flipped[x][DFR] = 1; | ||
| 1677 | coud_flipped[x][DFL] = 2; | ||
| 1678 | coud_flipped[x][DBR] = 2; | ||
| 1679 | coud_flipped[x][DBL] = 1; | ||
| 1680 | |||
| 1681 | corl_flipped[U][UFR] = 1; | ||
| 1682 | corl_flipped[U][UFL] = 2; | ||
| 1683 | corl_flipped[U][UBL] = 1; | ||
| 1684 | corl_flipped[U][UBR] = 2; | ||
| 1685 | |||
| 1686 | corl_flipped[y][UFR] = 1; | ||
| 1687 | corl_flipped[y][UFL] = 2; | ||
| 1688 | corl_flipped[y][UBL] = 1; | ||
| 1689 | corl_flipped[y][UBR] = 2; | ||
| 1690 | corl_flipped[y][DFR] = 2; | ||
| 1691 | corl_flipped[y][DFL] = 1; | ||
| 1692 | corl_flipped[y][DBL] = 2; | ||
| 1693 | corl_flipped[y][DBR] = 1; | ||
| 1694 | |||
| 1695 | cofb_flipped[U][UFR] = 2; | ||
| 1696 | cofb_flipped[U][UFL] = 1; | ||
| 1697 | cofb_flipped[U][UBL] = 2; | ||
| 1698 | cofb_flipped[U][UBR] = 1; | ||
| 1699 | |||
| 1700 | cofb_flipped[x][UFR] = 1; | ||
| 1701 | cofb_flipped[x][UFL] = 2; | ||
| 1702 | cofb_flipped[x][UBL] = 1; | ||
| 1703 | cofb_flipped[x][UBR] = 2; | ||
| 1704 | cofb_flipped[x][DFR] = 2; | ||
| 1705 | cofb_flipped[x][DFL] = 1; | ||
| 1706 | cofb_flipped[x][DBL] = 2; | ||
| 1707 | cofb_flipped[x][DBR] = 1; | ||
| 1708 | |||
| 1709 | cofb_flipped[y][UFR] = 2; | ||
| 1710 | cofb_flipped[y][UFL] = 1; | ||
| 1711 | cofb_flipped[y][UBL] = 2; | ||
| 1712 | cofb_flipped[y][UBR] = 1; | ||
| 1713 | cofb_flipped[y][DFR] = 1; | ||
| 1714 | cofb_flipped[y][DFL] = 2; | ||
| 1715 | cofb_flipped[y][DBL] = 1; | ||
| 1716 | cofb_flipped[y][DBR] = 2; | ||
| 1717 | |||
| 1718 | /* Equivalent moves ***********/ | ||
| 1719 | equiv_alg[NULLMOVE] = new_alg(""); | ||
| 1720 | |||
| 1721 | equiv_alg[U] = new_alg(" U "); | ||
| 1722 | equiv_alg[U2] = new_alg(" UU "); | ||
| 1723 | equiv_alg[U3] = new_alg(" UUU "); | ||
| 1724 | equiv_alg[D] = new_alg(" xx U xx "); | ||
| 1725 | equiv_alg[D2] = new_alg(" xx UU xx "); | ||
| 1726 | equiv_alg[D3] = new_alg(" xx UUU xx "); | ||
| 1727 | equiv_alg[R] = new_alg(" yx U xxxyyy "); | ||
| 1728 | equiv_alg[R2] = new_alg(" yx UU xxxyyy "); | ||
| 1729 | equiv_alg[R3] = new_alg(" yx UUU xxxyyy "); | ||
| 1730 | equiv_alg[L] = new_alg(" yyyx U xxxy "); | ||
| 1731 | equiv_alg[L2] = new_alg(" yyyx UU xxxy "); | ||
| 1732 | equiv_alg[L3] = new_alg(" yyyx UUU xxxy "); | ||
| 1733 | equiv_alg[F] = new_alg(" x U xxx "); | ||
| 1734 | equiv_alg[F2] = new_alg(" x UU xxx "); | ||
| 1735 | equiv_alg[F3] = new_alg(" x UUU xxx "); | ||
| 1736 | equiv_alg[B] = new_alg(" xxx U x "); | ||
| 1737 | equiv_alg[B2] = new_alg(" xxx UU x "); | ||
| 1738 | equiv_alg[B3] = new_alg(" xxx UUU x "); | ||
| 1739 | |||
| 1740 | equiv_alg[Uw] = new_alg(" xx U xx y "); | ||
| 1741 | equiv_alg[Uw2] = new_alg(" xx UU xx yy "); | ||
| 1742 | equiv_alg[Uw3] = new_alg(" xx UUU xx yyy "); | ||
| 1743 | equiv_alg[Dw] = new_alg(" U yyy "); | ||
| 1744 | equiv_alg[Dw2] = new_alg(" UU yy "); | ||
| 1745 | equiv_alg[Dw3] = new_alg(" UUU y "); | ||
| 1746 | equiv_alg[Rw] = new_alg(" yyyx U xxxy x "); | ||
| 1747 | equiv_alg[Rw2] = new_alg(" yyyx UU xxxy xx "); | ||
| 1748 | equiv_alg[Rw3] = new_alg(" yyyx UUU xxxy xxx "); | ||
| 1749 | equiv_alg[Lw] = new_alg(" yx U xxxyyy xxx "); | ||
| 1750 | equiv_alg[Lw2] = new_alg(" yx UU xxxyyy xx "); | ||
| 1751 | equiv_alg[Lw3] = new_alg(" yx UUU xxxyyy x "); | ||
| 1752 | equiv_alg[Fw] = new_alg(" xxx U x yxxxyyy "); | ||
| 1753 | equiv_alg[Fw2] = new_alg(" xxx UU x yxxyyy "); | ||
| 1754 | equiv_alg[Fw3] = new_alg(" xxx UUU x yxyyy "); | ||
| 1755 | equiv_alg[Bw] = new_alg(" x U xxx yxyyy "); | ||
| 1756 | equiv_alg[Bw2] = new_alg(" x UU xxx yxxyyy "); | ||
| 1757 | equiv_alg[Bw3] = new_alg(" x UUU xxx yxxxyyy "); | ||
| 1758 | |||
| 1759 | equiv_alg[M] = new_alg(" yx U xx UUU yxyyy "); | ||
| 1760 | equiv_alg[M2] = new_alg(" yx UU xx UU xxxy "); | ||
| 1761 | equiv_alg[M3] = new_alg(" yx UUU xx U yxxxy "); | ||
| 1762 | equiv_alg[S] = new_alg(" x UUU xx U yyyx "); | ||
| 1763 | equiv_alg[S2] = new_alg(" x UU xx UU yyx "); | ||
| 1764 | equiv_alg[S3] = new_alg(" x U xx UUU yx "); | ||
| 1765 | equiv_alg[E] = new_alg(" U xx UUU xxyyy "); | ||
| 1766 | equiv_alg[E2] = new_alg(" UU xx UU xxyy "); | ||
| 1767 | equiv_alg[E3] = new_alg(" UUU xx U xxy "); | ||
| 1768 | |||
| 1769 | equiv_alg[x] = new_alg(" x "); | ||
| 1770 | equiv_alg[x2] = new_alg(" xx "); | ||
| 1771 | equiv_alg[x3] = new_alg(" xxx "); | ||
| 1772 | equiv_alg[y] = new_alg(" y "); | ||
| 1773 | equiv_alg[y2] = new_alg(" yy "); | ||
| 1774 | equiv_alg[y3] = new_alg(" yyy "); | ||
| 1775 | equiv_alg[z] = new_alg(" yyy x y "); | ||
| 1776 | equiv_alg[z2] = new_alg(" yy xx "); | ||
| 1777 | equiv_alg[z3] = new_alg(" y x yyy "); | ||
| 1778 | } | ||
| 1779 | |||
| 1780 | static void | ||
| 1781 | init_steps() | ||
| 1782 | { | ||
| 1783 | /* PruneData */ | ||
| 1784 | pd_eofb_HTM.filename = "ptable_eofb_HTM"; | ||
| 1785 | pd_eofb_HTM.size = POW2TO11; | ||
| 1786 | pd_eofb_HTM.index = index_eofb; | ||
| 1787 | pd_eofb_HTM.moveset = moveset_HTM; | ||
| 1788 | |||
| 1789 | pd_coud_HTM.filename = "ptable_coud_HTM"; | ||
| 1790 | pd_coud_HTM.size = POW3TO7; | ||
| 1791 | pd_coud_HTM.index = index_coud; | ||
| 1792 | pd_coud_HTM.moveset = moveset_HTM; | ||
| 1793 | |||
| 1794 | pd_corners_HTM.filename = "ptable_corners_HTM"; | ||
| 1795 | pd_corners_HTM.size = POW3TO7 * FACTORIAL8; | ||
| 1796 | pd_corners_HTM.index = index_corners; | ||
| 1797 | pd_corners_HTM.moveset = moveset_HTM; | ||
| 1798 | |||
| 1799 | pd_ep_HTM.filename = "ptable_ep_HTM"; | ||
| 1800 | pd_ep_HTM.size = FACTORIAL12; | ||
| 1801 | pd_ep_HTM.index = index_ep; | ||
| 1802 | pd_ep_HTM.moveset = moveset_HTM; | ||
| 1803 | |||
| 1804 | pd_drud_HTM.filename = "ptable_drud_HTM"; | ||
| 1805 | pd_drud_HTM.size = POW2TO11 * POW3TO7 * BINOM12ON4; | ||
| 1806 | pd_drud_HTM.index = index_drud; | ||
| 1807 | pd_drud_HTM.moveset = moveset_HTM; | ||
| 1808 | |||
| 1809 | |||
| 1810 | /* Actual steps */ | ||
| 1811 | eofb_HTM.check = check_eofb_HTM; | ||
| 1812 | eofb_HTM.ready = check_nothing; | ||
| 1813 | eofb_HTM.pre_trans = uf; | ||
| 1814 | eofb_HTM.moveset = moveset_HTM; | ||
| 1815 | |||
| 1816 | eorl_HTM.check = check_eofb_HTM; | ||
| 1817 | eorl_HTM.ready = check_nothing; | ||
| 1818 | eorl_HTM.pre_trans = ur; | ||
| 1819 | eorl_HTM.moveset = moveset_HTM; | ||
| 1820 | |||
| 1821 | eoud_HTM.check = check_eofb_HTM; | ||
| 1822 | eoud_HTM.ready = check_nothing; | ||
| 1823 | eoud_HTM.pre_trans = bu; | ||
| 1824 | eoud_HTM.moveset = moveset_HTM; | ||
| 1825 | |||
| 1826 | |||
| 1827 | coud_HTM.check = check_coud_HTM; | ||
| 1828 | coud_HTM.ready = check_nothing; | ||
| 1829 | coud_HTM.pre_trans = uf; | ||
| 1830 | coud_HTM.moveset = moveset_HTM; | ||
| 1831 | |||
| 1832 | corl_HTM.check = check_coud_HTM; | ||
| 1833 | corl_HTM.ready = check_nothing; | ||
| 1834 | corl_HTM.pre_trans = rf; | ||
| 1835 | corl_HTM.moveset = moveset_HTM; | ||
| 1836 | |||
| 1837 | cofb_HTM.check = check_coud_HTM; | ||
| 1838 | cofb_HTM.ready = check_nothing; | ||
| 1839 | cofb_HTM.pre_trans = fd; | ||
| 1840 | cofb_HTM.moveset = moveset_HTM; | ||
| 1841 | |||
| 1842 | coud_URF.check = check_coud_URF; | ||
| 1843 | coud_URF.ready = check_nothing; | ||
| 1844 | coud_URF.pre_trans = uf; | ||
| 1845 | coud_URF.moveset = moveset_URF; | ||
| 1846 | |||
| 1847 | corl_URF.check = check_coud_URF; | ||
| 1848 | corl_URF.ready = check_nothing; | ||
| 1849 | corl_URF.pre_trans = rf; | ||
| 1850 | corl_URF.moveset = moveset_URF; | ||
| 1851 | |||
| 1852 | cofb_URF.check = check_coud_URF; | ||
| 1853 | cofb_URF.ready = check_nothing; | ||
| 1854 | cofb_URF.pre_trans = fd; | ||
| 1855 | cofb_URF.moveset = moveset_URF; | ||
| 1856 | |||
| 1857 | corners_HTM.check = check_corners_HTM; | ||
| 1858 | corners_HTM.ready = check_nothing; | ||
| 1859 | corners_HTM.pre_trans = uf; | ||
| 1860 | corners_HTM.moveset = moveset_HTM; | ||
| 1861 | |||
| 1862 | corners_URF.check = check_corners_URF; | ||
| 1863 | corners_URF.ready = check_nothing; | ||
| 1864 | corners_URF.pre_trans = uf; | ||
| 1865 | corners_URF.moveset = moveset_URF; | ||
| 1866 | |||
| 1867 | edges_HTM.check = check_edges_HTM; | ||
| 1868 | edges_HTM.ready = check_nothing; | ||
| 1869 | edges_HTM.pre_trans = uf; | ||
| 1870 | edges_HTM.moveset = moveset_HTM; | ||
| 1871 | |||
| 1872 | drud_HTM.check = check_drud_HTM; | ||
| 1873 | drud_HTM.ready = check_nothing; | ||
| 1874 | drud_HTM.pre_trans = uf; | ||
| 1875 | drud_HTM.moveset = moveset_HTM; | ||
| 1876 | |||
| 1877 | optimal_HTM.check = check_optimal_HTM; | ||
| 1878 | optimal_HTM.ready = check_nothing; | ||
| 1879 | optimal_HTM.pre_trans = uf; | ||
| 1880 | optimal_HTM.moveset = moveset_HTM; | ||
| 1881 | } | ||
| 1882 | |||
| 1883 | static void | ||
| 1884 | init_strings() | ||
| 1885 | { | ||
| 1886 | strcpy(move_string [NULLMOVE], "-" ); | ||
| 1887 | strcpy(move_string [U], "U" ); | ||
| 1888 | strcpy(move_string [U2], "U2" ); | ||
| 1889 | strcpy(move_string [U3], "U\'" ); | ||
| 1890 | strcpy(move_string [D], "D" ); | ||
| 1891 | strcpy(move_string [D2], "D2" ); | ||
| 1892 | strcpy(move_string [D3], "D\'" ); | ||
| 1893 | strcpy(move_string [R], "R" ); | ||
| 1894 | strcpy(move_string [R2], "R2" ); | ||
| 1895 | strcpy(move_string [R3], "R\'" ); | ||
| 1896 | strcpy(move_string [L], "L" ); | ||
| 1897 | strcpy(move_string [L2], "L2" ); | ||
| 1898 | strcpy(move_string [L3], "L\'" ); | ||
| 1899 | strcpy(move_string [F], "F" ); | ||
| 1900 | strcpy(move_string [F2], "F2" ); | ||
| 1901 | strcpy(move_string [F3], "F\'" ); | ||
| 1902 | strcpy(move_string [B], "B" ); | ||
| 1903 | strcpy(move_string [B2], "B2" ); | ||
| 1904 | strcpy(move_string [B3], "B\'" ); | ||
| 1905 | strcpy(move_string [Uw], "Uw" ); | ||
| 1906 | strcpy(move_string [Uw2], "Uw2" ); | ||
| 1907 | strcpy(move_string [Uw3], "Uw\'" ); | ||
| 1908 | strcpy(move_string [Dw], "Dw" ); | ||
| 1909 | strcpy(move_string [Dw2], "Dw2" ); | ||
| 1910 | strcpy(move_string [Dw3], "Dw\'" ); | ||
| 1911 | strcpy(move_string [Rw], "Rw" ); | ||
| 1912 | strcpy(move_string [Rw2], "Rw2" ); | ||
| 1913 | strcpy(move_string [Rw3], "Rw\'" ); | ||
| 1914 | strcpy(move_string [Lw], "Lw" ); | ||
| 1915 | strcpy(move_string [Lw2], "Lw2" ); | ||
| 1916 | strcpy(move_string [Lw3], "Lw\'" ); | ||
| 1917 | strcpy(move_string [Fw], "Fw" ); | ||
| 1918 | strcpy(move_string [Fw2], "Fw2" ); | ||
| 1919 | strcpy(move_string [Fw3], "Fw\'" ); | ||
| 1920 | strcpy(move_string [Bw], "Bw" ); | ||
| 1921 | strcpy(move_string [Bw2], "Bw2" ); | ||
| 1922 | strcpy(move_string [Bw3], "Bw\'" ); | ||
| 1923 | strcpy(move_string [M], "M" ); | ||
| 1924 | strcpy(move_string [M2], "M2" ); | ||
| 1925 | strcpy(move_string [M3], "M\'" ); | ||
| 1926 | strcpy(move_string [S], "S" ); | ||
| 1927 | strcpy(move_string [S2], "S2" ); | ||
| 1928 | strcpy(move_string [S3], "S\'" ); | ||
| 1929 | strcpy(move_string [E], "E" ); | ||
| 1930 | strcpy(move_string [E2], "E2" ); | ||
| 1931 | strcpy(move_string [E3], "E\'" ); | ||
| 1932 | strcpy(move_string [x], "x" ); | ||
| 1933 | strcpy(move_string [x2], "x2" ); | ||
| 1934 | strcpy(move_string [x3], "x\'" ); | ||
| 1935 | strcpy(move_string [y], "y" ); | ||
| 1936 | strcpy(move_string [y2], "y2" ); | ||
| 1937 | strcpy(move_string [y3], "y\'" ); | ||
| 1938 | strcpy(move_string [z], "z" ); | ||
| 1939 | strcpy(move_string [z2], "z2" ); | ||
| 1940 | strcpy(move_string [z3], "z\'" ); | ||
| 1941 | |||
| 1942 | strcpy(edge_string [UF], "UF" ); | ||
| 1943 | strcpy(edge_string [UL], "UL" ); | ||
| 1944 | strcpy(edge_string [UB], "UB" ); | ||
| 1945 | strcpy(edge_string [UR], "UR" ); | ||
| 1946 | strcpy(edge_string [DF], "DF" ); | ||
| 1947 | strcpy(edge_string [DL], "DL" ); | ||
| 1948 | strcpy(edge_string [DB], "DB" ); | ||
| 1949 | strcpy(edge_string [DR], "DR" ); | ||
| 1950 | strcpy(edge_string [FR], "FR" ); | ||
| 1951 | strcpy(edge_string [FL], "FL" ); | ||
| 1952 | strcpy(edge_string [BL], "BL" ); | ||
| 1953 | strcpy(edge_string [BR], "BR" ); | ||
| 1954 | |||
| 1955 | strcpy(corner_string [UFR], "UFR" ); | ||
| 1956 | strcpy(corner_string [UFL], "UFL" ); | ||
| 1957 | strcpy(corner_string [UBL], "UBL" ); | ||
| 1958 | strcpy(corner_string [UBR], "UBR" ); | ||
| 1959 | strcpy(corner_string [DFR], "DFR" ); | ||
| 1960 | strcpy(corner_string [DFL], "DFL" ); | ||
| 1961 | strcpy(corner_string [DBL], "DBL" ); | ||
| 1962 | strcpy(corner_string [DBR], "DBR" ); | ||
| 1963 | |||
| 1964 | strcpy(center_string [U_center], "U" ); | ||
| 1965 | strcpy(center_string [D_center], "D" ); | ||
| 1966 | strcpy(center_string [R_center], "R" ); | ||
| 1967 | strcpy(center_string [L_center], "L" ); | ||
| 1968 | strcpy(center_string [F_center], "F" ); | ||
| 1969 | strcpy(center_string [B_center], "B" ); | ||
| 1970 | } | ||
| 1971 | |||
| 1972 | static void | ||
| 1973 | init_trans() { | ||
| 1974 | Cube aux, cube, c[3]; | ||
| 1975 | CubeArray epcp; | ||
| 1976 | int eparr[12], eoarr[12]; | ||
| 1977 | int cparr[8], coarr[8]; | ||
| 1978 | int i; | ||
| 1979 | bool b1, b2, b3; | ||
| 1980 | uint16_t ui; | ||
| 1981 | Move mi, move; | ||
| 1982 | Trans m; | ||
| 1983 | |||
| 1984 | /* Compute sources */ | ||
| 1985 | for (i = 0; i < NTRANS; i++) { | ||
| 1986 | if (i == mirror) | ||
| 1987 | cube = (Cube){0}; | ||
| 1988 | else | ||
| 1989 | cube = apply_alg(trans_algs[i], (Cube){0}); | ||
| 1990 | |||
| 1991 | epose_source[i] = edge_slice(edge_at(cube, FR)); | ||
| 1992 | eposs_source[i] = edge_slice(edge_at(cube, UR)); | ||
| 1993 | eposm_source[i] = edge_slice(edge_at(cube, UF)); | ||
| 1994 | eofb_source[i] = center_at(cube, F_center)/2; | ||
| 1995 | eorl_source[i] = center_at(cube, R_center)/2; | ||
| 1996 | eoud_source[i] = center_at(cube, U_center)/2; | ||
| 1997 | coud_source[i] = center_at(cube, U_center)/2; | ||
| 1998 | cofb_source[i] = center_at(cube, F_center)/2; | ||
| 1999 | corl_source[i] = center_at(cube, R_center)/2; | ||
| 2000 | } | ||
| 2001 | |||
| 2002 | if (read_ttables_file()) | ||
| 2003 | return; | ||
| 2004 | |||
| 2005 | fprintf(stderr, "Cannot load %s, generating it\n", "ttables"); | ||
| 2006 | |||
| 2007 | /* Initialize tables */ | ||
| 2008 | for (m = 0; m < NTRANS; m++) { | ||
| 2009 | if (m == mirror) { | ||
| 2010 | memcpy(eparr, ep_mirror, 12 * sizeof(int)); | ||
| 2011 | memcpy(cparr, cp_mirror, 8 * sizeof(int)); | ||
| 2012 | } else { | ||
| 2013 | epcp = (CubeArray){ .ep = eparr, .cp = cparr }; | ||
| 2014 | cube = apply_alg(trans_algs[m], (Cube){0}); | ||
| 2015 | cube_to_arrays(cube, &epcp, pf_epcp); | ||
| 2016 | } | ||
| 2017 | |||
| 2018 | for (ui = 0; ui < FACTORIAL12/FACTORIAL8; ui++) { | ||
| 2019 | c[0] = admissible_ep((Cube){ .epose = ui }, pf_e); | ||
| 2020 | c[1] = admissible_ep((Cube){ .eposs = ui }, pf_s); | ||
| 2021 | c[2] = admissible_ep((Cube){ .eposm = ui }, pf_m); | ||
| 2022 | |||
| 2023 | cube = rotate_via_compose(m,c[epose_source[m]],pf_ep); | ||
| 2024 | epose_ttable[m][ui] = cube.epose; | ||
| 2025 | |||
| 2026 | cube = rotate_via_compose(m,c[eposs_source[m]],pf_ep); | ||
| 2027 | eposs_ttable[m][ui] = cube.eposs; | ||
| 2028 | |||
| 2029 | cube = rotate_via_compose(m,c[eposm_source[m]],pf_ep); | ||
| 2030 | eposm_ttable[m][ui] = cube.eposm; | ||
| 2031 | } | ||
| 2032 | for (ui = 0; ui < POW2TO11; ui++ ) { | ||
| 2033 | int_to_sum_zero_array(ui, 2, 12, eoarr); | ||
| 2034 | apply_permutation(eparr, eoarr, 12); | ||
| 2035 | eo_ttable[m][ui] = digit_array_to_int(eoarr, 11, 2); | ||
| 2036 | } | ||
| 2037 | for (ui = 0; ui < POW3TO7; ui++) { | ||
| 2038 | int_to_sum_zero_array(ui, 3, 8, coarr); | ||
| 2039 | apply_permutation(cparr, coarr, 8); | ||
| 2040 | co_ttable[m][ui] = digit_array_to_int(coarr, 7, 3); | ||
| 2041 | if (m == mirror) | ||
| 2042 | co_ttable[m][ui] = | ||
| 2043 | invert_digits(co_ttable[m][ui], 3, 7); | ||
| 2044 | } | ||
| 2045 | for (ui = 0; ui < FACTORIAL8; ui++) { | ||
| 2046 | cube = (Cube){ .cp = ui }; | ||
| 2047 | cube = rotate_via_compose(m, cube, pf_cp); | ||
| 2048 | cp_ttable[m][ui] = cube.cp; | ||
| 2049 | } | ||
| 2050 | for (ui = 0; ui < FACTORIAL6; ui++) { | ||
| 2051 | cube = (Cube){ .cpos = ui }; | ||
| 2052 | cube = rotate_via_compose(m, cube, pf_cpos); | ||
| 2053 | cpos_ttable[m][ui] = cube.cpos; | ||
| 2054 | } | ||
| 2055 | for (mi = 0; mi < NMOVES; mi++) { | ||
| 2056 | if (m == mirror) { | ||
| 2057 | b1 = (mi >= U && mi <= Bw3); | ||
| 2058 | b2 = (mi >= S && mi <= E3); | ||
| 2059 | b3 = (mi >= x && mi <= z3); | ||
| 2060 | if (b1 || b2 || b3) | ||
| 2061 | moves_ttable[m][mi] = | ||
| 2062 | inverse_move_aux[mi]; | ||
| 2063 | else | ||
| 2064 | moves_ttable[m][mi] = mi; | ||
| 2065 | |||
| 2066 | if ((mi-1)/3==(R-1)/3 || (mi-1)/3==(Rw-1)/3) | ||
| 2067 | moves_ttable[m][mi] += 3; | ||
| 2068 | if ((mi-1)/3==(L-1)/3 || (mi-1)/3==(L2-1)/3) | ||
| 2069 | moves_ttable[m][mi] -= 3; | ||
| 2070 | } else { | ||
| 2071 | aux = apply_trans(m, apply_move(mi,(Cube){0})); | ||
| 2072 | for (move = 0; move < NMOVES; move++) { | ||
| 2073 | cube = apply_move( | ||
| 2074 | inverse_move_aux[move], aux); | ||
| 2075 | if (is_solved(cube, false)) | ||
| 2076 | moves_ttable[m][mi] = move; | ||
| 2077 | } | ||
| 2078 | } | ||
| 2079 | } | ||
| 2080 | } | ||
| 2081 | |||
| 2082 | if (!write_ttables_file()) | ||
| 2083 | fprintf(stderr, "Error writing ttables\n"); | ||
| 2084 | } | ||
| 2085 | |||
| 2086 | static void | ||
| 2087 | init_trans_aux() | ||
| 2088 | { | ||
| 2089 | ep_mirror[UF] = UF; | ||
| 2090 | ep_mirror[UL] = UR; | ||
| 2091 | ep_mirror[UB] = UB; | ||
| 2092 | ep_mirror[UR] = UL; | ||
| 2093 | ep_mirror[DF] = DF; | ||
| 2094 | ep_mirror[DL] = DR; | ||
| 2095 | ep_mirror[DB] = DB; | ||
| 2096 | ep_mirror[DR] = DL; | ||
| 2097 | ep_mirror[FR] = FL; | ||
| 2098 | ep_mirror[FL] = FR; | ||
| 2099 | ep_mirror[BR] = BL; | ||
| 2100 | ep_mirror[BL] = BR; | ||
| 2101 | |||
| 2102 | cp_mirror[UFR] = UFL; | ||
| 2103 | cp_mirror[UFL] = UFR; | ||
| 2104 | cp_mirror[UBL] = UBR; | ||
| 2105 | cp_mirror[UBR] = UBL; | ||
| 2106 | cp_mirror[DFR] = DFL; | ||
| 2107 | cp_mirror[DFL] = DFR; | ||
| 2108 | cp_mirror[DBL] = DBR; | ||
| 2109 | cp_mirror[DBR] = DBL; | ||
| 2110 | |||
| 2111 | cpos_mirror[U_center] = U_center; | ||
| 2112 | cpos_mirror[D_center] = D_center; | ||
| 2113 | cpos_mirror[R_center] = L_center; | ||
| 2114 | cpos_mirror[L_center] = R_center; | ||
| 2115 | cpos_mirror[F_center] = F_center; | ||
| 2116 | cpos_mirror[B_center] = B_center; | ||
| 2117 | |||
| 2118 | /* Is there a more elegant way? */ | ||
| 2119 | trans_algs[uf] = new_alg(""); | ||
| 2120 | trans_algs[ur] = new_alg("y"); | ||
| 2121 | trans_algs[ub] = new_alg("y2"); | ||
| 2122 | trans_algs[ul] = new_alg("y3"); | ||
| 2123 | |||
| 2124 | trans_algs[df] = new_alg("z2"); | ||
| 2125 | trans_algs[dr] = new_alg("y z2"); | ||
| 2126 | trans_algs[db] = new_alg("x2"); | ||
| 2127 | trans_algs[dl] = new_alg("y3 z2"); | ||
| 2128 | |||
| 2129 | trans_algs[rf] = new_alg("z3"); | ||
| 2130 | trans_algs[rd] = new_alg("z3 y"); | ||
| 2131 | trans_algs[rb] = new_alg("z3 y2"); | ||
| 2132 | trans_algs[ru] = new_alg("z3 y3"); | ||
| 2133 | |||
| 2134 | trans_algs[lf] = new_alg("z"); | ||
| 2135 | trans_algs[ld] = new_alg("z y3"); | ||
| 2136 | trans_algs[lb] = new_alg("z y2"); | ||
| 2137 | trans_algs[lu] = new_alg("z y"); | ||
| 2138 | |||
| 2139 | trans_algs[fu] = new_alg("x y2"); | ||
| 2140 | trans_algs[fr] = new_alg("x y"); | ||
| 2141 | trans_algs[fd] = new_alg("x"); | ||
| 2142 | trans_algs[fl] = new_alg("x y3"); | ||
| 2143 | |||
| 2144 | trans_algs[bu] = new_alg("x3"); | ||
| 2145 | trans_algs[br] = new_alg("x3 y"); | ||
| 2146 | trans_algs[bd] = new_alg("x3 y2"); | ||
| 2147 | trans_algs[bl] = new_alg("x3 y3"); | ||
| 2148 | } | ||
| 2149 | |||
| 2150 | /* Linearization functions implementation ************************************/ | ||
| 2151 | |||
| 2152 | static uint64_t | ||
| 2153 | index_eofb(Cube cube) | ||
| 2154 | { | ||
| 2155 | return cube.eofb; | ||
| 2156 | } | ||
| 2157 | |||
| 2158 | static uint64_t | ||
| 2159 | index_coud(Cube cube) | ||
| 2160 | { | ||
| 2161 | return cube.coud; | ||
| 2162 | } | ||
| 2163 | |||
| 2164 | static uint64_t | ||
| 2165 | index_corners(Cube cube) | ||
| 2166 | { | ||
| 2167 | return cube.coud * FACTORIAL8 + cube.cp; | ||
| 2168 | } | ||
| 2169 | |||
| 2170 | static uint64_t | ||
| 2171 | index_ep(Cube cube) | ||
| 2172 | { | ||
| 2173 | uint64_t a, b, c; | ||
| 2174 | |||
| 2175 | /* TODO: remove this check */ | ||
| 2176 | if (epos_dependent_aux[cube.eposs/FACTORIAL4][cube.epose/FACTORIAL4] ==BINOM8ON4) | ||
| 2177 | fprintf(stderr, "Impossible\n"); | ||
| 2178 | |||
| 2179 | a = cube.eposs; | ||
| 2180 | b = (cube.epose % FACTORIAL4) + | ||
| 2181 | epos_dependent_aux[cube.eposs/FACTORIAL4][cube.epose/FACTORIAL4] * | ||
| 2182 | FACTORIAL4; | ||
| 2183 | c = cube.eposm % FACTORIAL4; | ||
| 2184 | |||
| 2185 | b *= FACTORIAL4 * BINOM12ON4; | ||
| 2186 | c *= FACTORIAL4 * BINOM12ON4 * FACTORIAL4 * BINOM8ON4; | ||
| 2187 | |||
| 2188 | return a + b + c; | ||
| 2189 | } | ||
| 2190 | |||
| 2191 | static uint64_t | ||
| 2192 | index_drud(Cube cube) | ||
| 2193 | { | ||
| 2194 | uint64_t a, b, c; | ||
| 2195 | |||
| 2196 | a = cube.eofb; | ||
| 2197 | b = cube.coud; | ||
| 2198 | c = cube.epose / FACTORIAL4; | ||
| 2199 | |||
| 2200 | b *= POW2TO11; | ||
| 2201 | c *= POW2TO11 * POW3TO7; | ||
| 2202 | |||
| 2203 | return a + b + c; | ||
| 2204 | } | ||
| 2205 | |||
| 2206 | /* Step checking functions implementation ************************************/ | ||
| 2207 | |||
| 2208 | static int | ||
| 2209 | check_nothing(Cube cube) | ||
| 2210 | { | ||
| 2211 | return true; | ||
| 2212 | } | ||
| 2213 | |||
| 2214 | static int | ||
| 2215 | check_eofb_HTM(Cube cube) | ||
| 2216 | { | ||
| 2217 | if (!pd_eofb_HTM.generated) | ||
| 2218 | generate_ptable(&pd_eofb_HTM); | ||
| 2219 | |||
| 2220 | return PTABLEVAL(pd_eofb_HTM.ptable, cube.eofb); | ||
| 2221 | } | ||
| 2222 | |||
| 2223 | static int | ||
| 2224 | check_coud_HTM(Cube cube) | ||
| 2225 | { | ||
| 2226 | if (!pd_coud_HTM.generated) | ||
| 2227 | generate_ptable(&pd_coud_HTM); | ||
| 2228 | |||
| 2229 | return PTABLEVAL(pd_coud_HTM.ptable, cube.coud); | ||
| 2230 | } | ||
| 2231 | |||
| 2232 | static int | ||
| 2233 | check_coud_URF(Cube cube) | ||
| 2234 | { | ||
| 2235 | /* TODO: I can improve this by checking first the orientation of | ||
| 2236 | * the corner in DBL and use that as a reference */ | ||
| 2237 | |||
| 2238 | int ud = check_coud_HTM(cube); | ||
| 2239 | int rl = check_coud_HTM(apply_move(z, cube)); | ||
| 2240 | int fb = check_coud_HTM(apply_move(x, cube)); | ||
| 2241 | |||
| 2242 | return MIN(ud, MIN(rl, fb)); | ||
| 2243 | } | ||
| 2244 | |||
| 2245 | static int | ||
| 2246 | check_corners_HTM(Cube cube) | ||
| 2247 | { | ||
| 2248 | if (!pd_corners_HTM.generated) | ||
| 2249 | generate_ptable(&pd_corners_HTM); | ||
| 2250 | |||
| 2251 | return PTABLEVAL(pd_corners_HTM.ptable, index_corners(cube)); | ||
| 2252 | } | ||
| 2253 | |||
| 2254 | static int | ||
| 2255 | check_corners_URF(Cube cube) | ||
| 2256 | { | ||
| 2257 | /* TODO: I can improve this by checking first the corner in DBL | ||
| 2258 | * and use that as a reference */ | ||
| 2259 | |||
| 2260 | int ret = 15; | ||
| 2261 | Cube c; | ||
| 2262 | Trans i; | ||
| 2263 | |||
| 2264 | for (i = 0; i < NROTATIONS; i++) { | ||
| 2265 | c = apply_alg(trans_algs[i], cube); | ||
| 2266 | ret = MIN(ret, check_corners_HTM(c)); | ||
| 2267 | } | ||
| 2268 | |||
| 2269 | return ret; | ||
| 2270 | } | ||
| 2271 | |||
| 2272 | static int | ||
| 2273 | check_edges_HTM(Cube cube) | ||
| 2274 | { | ||
| 2275 | int ret = 0; | ||
| 2276 | |||
| 2277 | if (!pd_ep_HTM.generated) | ||
| 2278 | generate_ptable(&pd_ep_HTM); | ||
| 2279 | |||
| 2280 | ret = MAX(ret, PTABLEVAL(pd_ep_HTM.ptable, index_ep(cube))); | ||
| 2281 | ret = MAX(ret, check_eofb_HTM(cube)); | ||
| 2282 | ret = MAX(ret, check_eofb_HTM(apply_trans(ur, cube))); | ||
| 2283 | ret = MAX(ret, check_eofb_HTM(apply_trans(fd, cube))); | ||
| 2284 | |||
| 2285 | return ret; | ||
| 2286 | } | ||
| 2287 | |||
| 2288 | static int | ||
| 2289 | check_drud_HTM(Cube cube) | ||
| 2290 | { | ||
| 2291 | if (!pd_drud_HTM.generated) | ||
| 2292 | generate_ptable(&pd_drud_HTM); | ||
| 2293 | |||
| 2294 | return PTABLEVAL(pd_drud_HTM.ptable, index_drud(cube)); | ||
| 2295 | } | ||
| 2296 | |||
| 2297 | static int | ||
| 2298 | check_optimal_HTM(Cube cube) | ||
| 2299 | { | ||
| 2300 | int dr1, dr2, dr3, drmax, cor; /*ep;*/ | ||
| 2301 | |||
| 2302 | if (!pd_drud_HTM.generated) | ||
| 2303 | generate_ptable(&pd_drud_HTM); | ||
| 2304 | if (!pd_corners_HTM.generated) | ||
| 2305 | generate_ptable(&pd_corners_HTM); | ||
| 2306 | /* | ||
| 2307 | *if (!pd_ep_HTM.generated) | ||
| 2308 | * generate_ptable(&pd_ep_HTM); | ||
| 2309 | */ | ||
| 2310 | |||
| 2311 | dr1 = PTABLEVAL(pd_drud_HTM.ptable, index_drud(cube)); | ||
| 2312 | dr2 = PTABLEVAL(pd_drud_HTM.ptable, index_drud(apply_trans(rf, cube))); | ||
| 2313 | dr3 = PTABLEVAL(pd_drud_HTM.ptable, index_drud(apply_trans(fd, cube))); | ||
| 2314 | |||
| 2315 | drmax = MAX(dr1, MAX(dr2, dr3)); | ||
| 2316 | if (dr1 == dr2 && dr2 == dr3 && dr1 != 0) | ||
| 2317 | drmax++; | ||
| 2318 | |||
| 2319 | cor = PTABLEVAL(pd_corners_HTM.ptable, index_corners(cube)); | ||
| 2320 | /* ep = PTABLEVAL(pd_ep_HTM.ptable, index_ep(cube)); */ | ||
| 2321 | |||
| 2322 | /*return MAX(drmax, MAX(ep, cor));*/ | ||
| 2323 | if (drmax == 0 && cor == 0) | ||
| 2324 | return is_solved(cube, false) ? 0 : 1; | ||
| 2325 | return MAX(drmax, cor); | ||
| 2326 | } | ||
| 2327 | |||
| 2328 | |||
| 2329 | /* Movesets ******************************************************************/ | ||
| 2330 | |||
| 2331 | bool | ||
| 2332 | moveset_HTM(Move m) | ||
| 2333 | { | ||
| 2334 | return m >= U && m <= B3; | ||
| 2335 | } | ||
| 2336 | |||
| 2337 | bool | ||
| 2338 | moveset_URF(Move m) | ||
| 2339 | { | ||
| 2340 | Move b = base_move(m); | ||
| 2341 | |||
| 2342 | return b == U || b == R || b == F; | ||
| 2343 | } | ||
| 2344 | |||
| 2345 | |||
| 2346 | /* Public functions implementation *******************************************/ | ||
| 2347 | |||
| 2348 | Cube | ||
| 2349 | apply_alg(Alg *alg, Cube cube) | ||
| 2350 | { | ||
| 2351 | return apply_alg_generic(alg, cube, pf_all, true); | ||
| 2352 | } | ||
| 2353 | |||
| 2354 | Cube | ||
| 2355 | apply_move(Move m, Cube cube) | ||
| 2356 | { | ||
| 2357 | Cube moved = {0}; | ||
| 2358 | |||
| 2359 | moved.epose = epose_mtable[m][cube.epose]; | ||
| 2360 | moved.eposs = eposs_mtable[m][cube.eposs]; | ||
| 2361 | moved.eposm = eposm_mtable[m][cube.eposm]; | ||
| 2362 | moved.eofb = eofb_mtable[m][cube.eofb]; | ||
| 2363 | moved.eorl = eorl_mtable[m][cube.eorl]; | ||
| 2364 | moved.eoud = eoud_mtable[m][cube.eoud]; | ||
| 2365 | moved.coud = coud_mtable[m][cube.coud]; | ||
| 2366 | moved.cofb = cofb_mtable[m][cube.cofb]; | ||
| 2367 | moved.corl = corl_mtable[m][cube.corl]; | ||
| 2368 | moved.cp = cp_mtable[m][cube.cp]; | ||
| 2369 | moved.cpos = cpos_mtable[m][cube.cpos]; | ||
| 2370 | |||
| 2371 | return moved; | ||
| 2372 | } | ||
| 2373 | |||
| 2374 | Cube | ||
| 2375 | apply_trans(Trans t, Cube cube) | ||
| 2376 | { | ||
| 2377 | Cube transformed = {0}; | ||
| 2378 | uint16_t aux_epos[3] = { cube.epose, cube.eposs, cube.eposm }; | ||
| 2379 | uint16_t aux_eo[3] = { cube.eoud, cube.eorl, cube.eofb }; | ||
| 2380 | uint16_t aux_co[3] = { cube.coud, cube.corl, cube.cofb }; | ||
| 2381 | |||
| 2382 | transformed.epose = epose_ttable[t][aux_epos[epose_source[t]]]; | ||
| 2383 | transformed.eposs = eposs_ttable[t][aux_epos[eposs_source[t]]]; | ||
| 2384 | transformed.eposm = eposm_ttable[t][aux_epos[eposm_source[t]]]; | ||
| 2385 | transformed.eofb = eo_ttable[t][aux_eo[eofb_source[t]]]; | ||
| 2386 | transformed.eorl = eo_ttable[t][aux_eo[eorl_source[t]]]; | ||
| 2387 | transformed.eoud = eo_ttable[t][aux_eo[eoud_source[t]]]; | ||
| 2388 | transformed.coud = co_ttable[t][aux_co[coud_source[t]]]; | ||
| 2389 | transformed.corl = co_ttable[t][aux_co[corl_source[t]]]; | ||
| 2390 | transformed.cofb = co_ttable[t][aux_co[cofb_source[t]]]; | ||
| 2391 | transformed.cp = cp_ttable[t][cube.cp]; | ||
| 2392 | transformed.cpos = cpos_ttable[t][cube.cpos]; | ||
| 2393 | |||
| 2394 | return transformed; | ||
| 2395 | } | ||
| 2396 | |||
| 2397 | /* TODO: this has to be changed using pre-computations */ | ||
| 2398 | bool | ||
| 2399 | block_solved(Cube cube, Block block) | ||
| 2400 | { | ||
| 2401 | CubeArray *arr = new_cubearray(cube, pf_all); | ||
| 2402 | int i; | ||
| 2403 | bool ret = true; | ||
| 2404 | |||
| 2405 | for (i = 0; i < 12; i++) | ||
| 2406 | ret = ret && !(block.edge[i] && (arr->ep[i] != i || arr->eofb[i])); | ||
| 2407 | for (i = 0; i < 8; i++) | ||
| 2408 | ret = ret && !(block.corner[i] && (arr->cp[i] != i || arr->coud[i])); | ||
| 2409 | for (i = 0; i < 6; i++) | ||
| 2410 | ret = ret && !(block.center[i] && arr->cpos[i] != i); | ||
| 2411 | |||
| 2412 | free_cubearray(arr, pf_all); | ||
| 2413 | |||
| 2414 | return ret; | ||
| 2415 | } | ||
| 2416 | |||
| 2417 | Center | ||
| 2418 | center_at(Cube cube, Center c) | ||
| 2419 | { | ||
| 2420 | int ret; | ||
| 2421 | CubeArray *arr = new_cubearray(cube, pf_cpos); | ||
| 2422 | |||
| 2423 | ret = arr->cpos[c]; | ||
| 2424 | free_cubearray(arr, pf_cpos); | ||
| 2425 | |||
| 2426 | return ret; | ||
| 2427 | } | ||
| 2428 | |||
| 2429 | Cube | ||
| 2430 | compose(Cube c2, Cube c1) | ||
| 2431 | { | ||
| 2432 | return compose_filtered(c2, c1, pf_all); | ||
| 2433 | } | ||
| 2434 | |||
| 2435 | Corner | ||
| 2436 | corner_at(Cube cube, Corner c) | ||
| 2437 | { | ||
| 2438 | int ret; | ||
| 2439 | CubeArray *arr = new_cubearray(cube, pf_cp); | ||
| 2440 | |||
| 2441 | ret = arr->cp[c]; | ||
| 2442 | free_cubearray(arr, pf_cp); | ||
| 2443 | |||
| 2444 | return ret; | ||
| 2445 | } | ||
| 2446 | |||
| 2447 | Edge | ||
| 2448 | edge_at(Cube cube, Edge e) | ||
| 2449 | { | ||
| 2450 | int ret; | ||
| 2451 | CubeArray *arr = new_cubearray(cube, pf_ep); | ||
| 2452 | |||
| 2453 | ret = arr->ep[e]; | ||
| 2454 | free_cubearray(arr, pf_ep); | ||
| 2455 | |||
| 2456 | return ret; | ||
| 2457 | } | ||
| 2458 | |||
| 2459 | bool | ||
| 2460 | equal(Cube c1, Cube c2) | ||
| 2461 | { | ||
| 2462 | return c1.eofb == c2.eofb && | ||
| 2463 | c1.epose == c2.epose && | ||
| 2464 | c1.eposs == c2.eposs && | ||
| 2465 | c1.eposm == c2.eposm && | ||
| 2466 | c1.coud == c2.coud && | ||
| 2467 | c1.cp == c2.cp && | ||
| 2468 | c1.cpos == c2.cpos; | ||
| 2469 | } | ||
| 2470 | |||
| 2471 | Cube | ||
| 2472 | inverse_cube(Cube cube) | ||
| 2473 | { | ||
| 2474 | CubeArray *arr = new_cubearray(cube, pf_all); | ||
| 2475 | CubeArray *inv = new_cubearray((Cube){0}, pf_all); | ||
| 2476 | Cube ret; | ||
| 2477 | int i; | ||
| 2478 | |||
| 2479 | for (i = 0; i < 12; i++) { | ||
| 2480 | inv->ep[arr->ep[i]] = i; | ||
| 2481 | inv->eofb[arr->ep[i]] = arr->eofb[i]; | ||
| 2482 | inv->eorl[arr->ep[i]] = arr->eorl[i]; | ||
| 2483 | inv->eoud[arr->ep[i]] = arr->eoud[i]; | ||
| 2484 | } | ||
| 2485 | |||
| 2486 | for (i = 0; i < 8; i++) { | ||
| 2487 | inv->cp[arr->cp[i]] = i; | ||
| 2488 | inv->coud[arr->cp[i]] = (3 - arr->coud[i]) % 3; | ||
| 2489 | inv->corl[arr->cp[i]] = (3 - arr->corl[i]) % 3; | ||
| 2490 | inv->cofb[arr->cp[i]] = (3 - arr->cofb[i]) % 3; | ||
| 2491 | } | ||
| 2492 | |||
| 2493 | for (int i = 0; i < 6; i++) | ||
| 2494 | inv->cpos[arr->cpos[i]] = i; | ||
| 2495 | |||
| 2496 | ret = arrays_to_cube(inv, pf_all); | ||
| 2497 | free_cubearray(arr, pf_all); | ||
| 2498 | free_cubearray(inv, pf_all); | ||
| 2499 | |||
| 2500 | return ret; | ||
| 2501 | } | ||
| 2502 | |||
| 2503 | Move | ||
| 2504 | inverse_move(Move m) | ||
| 2505 | { | ||
| 2506 | return inverse_move_aux[m]; | ||
| 2507 | } | ||
| 2508 | |||
| 2509 | Trans | ||
| 2510 | inverse_trans(Trans t) | ||
| 2511 | { | ||
| 2512 | return inverse_trans_aux[t]; | ||
| 2513 | } | ||
| 2514 | |||
| 2515 | bool | ||
| 2516 | is_admissible(Cube cube) | ||
| 2517 | { | ||
| 2518 | /* TODO: this should check consistency of different orientations */ | ||
| 2519 | /* TODO: check that centers are opposite and admissible */ | ||
| 2520 | |||
| 2521 | CubeArray *a = new_cubearray(cube, pf_all); | ||
| 2522 | int parity; | ||
| 2523 | bool perm; | ||
| 2524 | |||
| 2525 | perm = is_perm(a->ep, 12) && | ||
| 2526 | is_perm(a->cp, 8) && | ||
| 2527 | is_perm(a->cpos, 6); | ||
| 2528 | parity = perm_sign(a->ep, 12) + | ||
| 2529 | perm_sign(a->cp, 8) + | ||
| 2530 | perm_sign(a->cpos, 6); | ||
| 2531 | |||
| 2532 | return perm && parity % 2 == 0; | ||
| 2533 | } | ||
| 2534 | |||
| 2535 | bool | ||
| 2536 | is_solved(Cube cube, bool reorient) | ||
| 2537 | { | ||
| 2538 | Trans i; | ||
| 2539 | |||
| 2540 | if (reorient) | ||
| 2541 | for (i = 0; i < NROTATIONS; i++) | ||
| 2542 | if (is_solved(apply_alg(trans_algs[i],cube), false)) | ||
| 2543 | return true; | ||
| 2544 | |||
| 2545 | return equal(cube, (Cube){0}); | ||
| 2546 | } | ||
| 2547 | |||
| 2548 | int | ||
| 2549 | piece_orientation(Cube cube, int piece, char *orientation) | ||
| 2550 | { | ||
| 2551 | int arr[12], n, b; | ||
| 2552 | uint16_t x; | ||
| 2553 | |||
| 2554 | if (!strcmp(orientation, "eofb")) { | ||
| 2555 | x = cube.eofb; | ||
| 2556 | n = 12; | ||
| 2557 | b = 2; | ||
| 2558 | } else if (!strcmp(orientation, "eorl")) { | ||
| 2559 | x = cube.eorl; | ||
| 2560 | n = 12; | ||
| 2561 | b = 2; | ||
| 2562 | } else if (!strcmp(orientation, "eoud")) { | ||
| 2563 | x = cube.eoud; | ||
| 2564 | n = 12; | ||
| 2565 | b = 2; | ||
| 2566 | } else if (!strcmp(orientation, "coud")) { | ||
| 2567 | x = cube.coud; | ||
| 2568 | n = 8; | ||
| 2569 | b = 3; | ||
| 2570 | } else if (!strcmp(orientation, "corl")) { | ||
| 2571 | x = cube.corl; | ||
| 2572 | n = 8; | ||
| 2573 | b = 3; | ||
| 2574 | } else if (!strcmp(orientation, "cofb")) { | ||
| 2575 | x = cube.cofb; | ||
| 2576 | n = 8; | ||
| 2577 | b = 3; | ||
| 2578 | } else { | ||
| 2579 | return -1; | ||
| 2580 | } | ||
| 2581 | |||
| 2582 | int_to_sum_zero_array(x, b, n, arr); | ||
| 2583 | if (piece < n) | ||
| 2584 | return arr[piece]; | ||
| 2585 | |||
| 2586 | return -1; | ||
| 2587 | } | ||
| 2588 | |||
| 2589 | void | ||
| 2590 | print_cube(Cube cube) | ||
| 2591 | { | ||
| 2592 | CubeArray *arr = new_cubearray(cube, pf_all); | ||
| 2593 | |||
| 2594 | for (int i = 0; i < 12; i++) | ||
| 2595 | printf(" %s ", edge_string[arr->ep[i]]); | ||
| 2596 | printf("\n"); | ||
| 2597 | |||
| 2598 | for (int i = 0; i < 12; i++) | ||
| 2599 | printf(" %c ", arr->eofb[i] + '0'); | ||
| 2600 | printf("\n"); | ||
| 2601 | |||
| 2602 | for (int i = 0; i < 8; i++) | ||
| 2603 | printf("%s ", corner_string[arr->cp[i]]); | ||
| 2604 | printf("\n"); | ||
| 2605 | |||
| 2606 | for (int i = 0; i < 8; i++) | ||
| 2607 | printf(" %c ", arr->coud[i] + '0'); | ||
| 2608 | printf("\n"); | ||
| 2609 | |||
| 2610 | for (int i = 0; i < 6; i++) | ||
| 2611 | printf(" %s ", center_string[arr->cpos[i]]); | ||
| 2612 | printf("\n"); | ||
| 2613 | |||
| 2614 | free_cubearray(arr, pf_all); | ||
| 2615 | } | ||
| 2616 | |||
| 2617 | Cube | ||
| 2618 | random_cube() | ||
| 2619 | { | ||
| 2620 | CubeArray *arr = new_cubearray((Cube){0}, pf_4val); | ||
| 2621 | Cube ret; | ||
| 2622 | int ep, cp, eo, co; | ||
| 2623 | |||
| 2624 | ep = rand() % FACTORIAL12; | ||
| 2625 | cp = rand() % FACTORIAL8; | ||
| 2626 | eo = rand() % POW2TO11; | ||
| 2627 | co = rand() % POW3TO7; | ||
| 2628 | |||
| 2629 | index_to_perm(ep, 12, arr->ep); | ||
| 2630 | index_to_perm(cp, 8, arr->cp); | ||
| 2631 | int_to_sum_zero_array(eo, 2, 12, arr->eofb); | ||
| 2632 | int_to_sum_zero_array(co, 3, 8, arr->coud); | ||
| 2633 | |||
| 2634 | if (perm_sign(arr->ep, 12) != perm_sign(arr->cp, 8)) | ||
| 2635 | swap(&(arr->ep[0]), &(arr->ep[1])); | ||
| 2636 | |||
| 2637 | ret = arrays_to_cube(arr, pf_4val); | ||
| 2638 | free_cubearray(arr, pf_4val); | ||
| 2639 | |||
| 2640 | return ret; | ||
| 2641 | } | ||
| 2642 | |||
| 2643 | AlgList * | ||
| 2644 | solve(Cube cube, Step step, SolveOptions *opts) | ||
| 2645 | { | ||
| 2646 | AlgListNode *node; | ||
| 2647 | AlgList *sols = new_alglist(); | ||
| 2648 | Cube c = apply_trans(step.pre_trans, cube); | ||
| 2649 | DfsData dd = { | ||
| 2650 | .m = 0, | ||
| 2651 | .niss = false, | ||
| 2652 | .last1 = NULLMOVE, | ||
| 2653 | .last2 = NULLMOVE, | ||
| 2654 | .sols = sols, | ||
| 2655 | .current_alg = new_alg("") | ||
| 2656 | }; | ||
| 2657 | |||
| 2658 | if (step.ready != NULL && !step.ready(c)) | ||
| 2659 | return sols; | ||
| 2660 | |||
| 2661 | moveset_to_list(step.moveset, step.check, dd.sorted_moves); | ||
| 2662 | |||
| 2663 | for (dd.d = MAX(opts->min_moves, step.check(c)); | ||
| 2664 | dd.d <= opts->max_moves && !(sols->len && opts->optimal_only); | ||
| 2665 | dd.d++) { | ||
| 2666 | solve_dfs(c, step, opts, &dd); | ||
| 2667 | if (opts->feedback) | ||
| 2668 | fprintf(stderr, | ||
| 2669 | "Depth %d completed, found %d solutions\n", | ||
| 2670 | dd.d, sols->len); | ||
| 2671 | } | ||
| 2672 | |||
| 2673 | for (node = sols->first; node != NULL; node = node->next) | ||
| 2674 | transform_alg(inverse_trans_aux[step.pre_trans], node->alg); | ||
| 2675 | |||
| 2676 | return sols; | ||
| 2677 | } | ||
| 2678 | |||
| 2679 | Alg * | ||
| 2680 | inverse_alg(Alg *alg) | ||
| 2681 | { | ||
| 2682 | Alg *ret = new_alg(""); | ||
| 2683 | int i; | ||
| 2684 | |||
| 2685 | for (i = alg->len-1; i >= 0; i--) | ||
| 2686 | append_move(ret, alg->move[i], alg->inv[i]); | ||
| 2687 | |||
| 2688 | return ret; | ||
| 2689 | } | ||
| 2690 | |||
| 2691 | Alg * | ||
| 2692 | new_alg(char *str) | ||
| 2693 | { | ||
| 2694 | Alg *alg = malloc(sizeof(Alg)); | ||
| 2695 | int i; | ||
| 2696 | bool niss = false; | ||
| 2697 | Move j, m; | ||
| 2698 | |||
| 2699 | alg->move = malloc(30 * sizeof(Move)); | ||
| 2700 | alg->inv = malloc(30 * sizeof(bool)); | ||
| 2701 | alg->allocated = 30; | ||
| 2702 | alg->len = 0; | ||
| 2703 | |||
| 2704 | for (i = 0; str[i]; i++) { | ||
| 2705 | if (str[i] == ' ' || str[i] == '\t' || str[i] == '\n') | ||
| 2706 | continue; | ||
| 2707 | |||
| 2708 | if (str[i] == '(' && niss) { | ||
| 2709 | fprintf(stderr, "Error reading moves: nested ( )\n"); | ||
| 2710 | return alg; | ||
| 2711 | } | ||
| 2712 | |||
| 2713 | if (str[i] == ')' && !niss) { | ||
| 2714 | fprintf(stderr, "Error reading moves: unmatched )\n"); | ||
| 2715 | return alg; | ||
| 2716 | } | ||
| 2717 | |||
| 2718 | if (str[i] == '(' || str[i] == ')') { | ||
| 2719 | niss = !niss; | ||
| 2720 | continue; | ||
| 2721 | } | ||
| 2722 | |||
| 2723 | for (j = 0; j < NMOVES; j++) { | ||
| 2724 | if (str[i] == move_string[j][0]) { | ||
| 2725 | m = j; | ||
| 2726 | if (m <= B && str[i+1]=='w') { | ||
| 2727 | m += Uw - U; | ||
| 2728 | i++; | ||
| 2729 | } | ||
| 2730 | if (str[i+1]=='2') { | ||
| 2731 | m += 1; | ||
| 2732 | i++; | ||
| 2733 | } else if (str[i+1]=='\'' || str[i+1]=='3') { | ||
| 2734 | m += 2; | ||
| 2735 | i++; | ||
| 2736 | } | ||
| 2737 | append_move(alg, m, niss); | ||
| 2738 | break; | ||
| 2739 | } | ||
| 2740 | } | ||
| 2741 | } | ||
| 2742 | |||
| 2743 | return alg; | ||
| 2744 | } | ||
| 2745 | |||
| 2746 | Alg * | ||
| 2747 | on_inverse(Alg *alg) | ||
| 2748 | { | ||
| 2749 | Alg *ret = new_alg(""); | ||
| 2750 | int i; | ||
| 2751 | |||
| 2752 | for (i = 0; i < alg->len; i++) | ||
| 2753 | append_move(ret, alg->move[i], !alg->inv[i]); | ||
| 2754 | |||
| 2755 | return ret; | ||
| 2756 | } | ||
| 2757 | |||
| 2758 | void | ||
| 2759 | print_alg(Alg *alg, bool l) | ||
| 2760 | { | ||
| 2761 | char fill[4]; | ||
| 2762 | int i; | ||
| 2763 | bool niss = false; | ||
| 2764 | |||
| 2765 | for (i = 0; i < alg->len; i++) { | ||
| 2766 | if (!niss && alg->inv[i]) | ||
| 2767 | strcpy(fill, i == 0 ? "(" : " ("); | ||
| 2768 | if (niss && !alg->inv[i]) | ||
| 2769 | strcpy(fill, ") "); | ||
| 2770 | if (niss == alg->inv[i]) | ||
| 2771 | strcpy(fill, i == 0 ? "" : " "); | ||
| 2772 | |||
| 2773 | printf("%s%s", fill, move_string[alg->move[i]]); | ||
| 2774 | niss = alg->inv[i]; | ||
| 2775 | } | ||
| 2776 | |||
| 2777 | if (niss) | ||
| 2778 | printf(")"); | ||
| 2779 | if (l) | ||
| 2780 | printf(" (%d)", alg->len); | ||
| 2781 | |||
| 2782 | printf("\n"); | ||
| 2783 | } | ||
| 2784 | |||
| 2785 | void | ||
| 2786 | print_ptable(PruneData *pd) | ||
| 2787 | { | ||
| 2788 | uint64_t i, a[16]; | ||
| 2789 | |||
| 2790 | memset(a, 0, 16 * sizeof(uint64_t)); | ||
| 2791 | |||
| 2792 | if (!pd->generated) | ||
| 2793 | generate_ptable(pd); | ||
| 2794 | |||
| 2795 | for (i = 0; i < pd->size; i++) | ||
| 2796 | a[PTABLEVAL(pd->ptable, i)]++; | ||
| 2797 | |||
| 2798 | fprintf(stderr, "Values for table %s\n", pd->filename); | ||
| 2799 | for (i = 0; i < 16; i++) | ||
| 2800 | printf("%2lu\t%10lu\n", i, a[i]); | ||
| 2801 | } | ||
| 2802 | |||
| 2803 | void | ||
| 2804 | print_alglist(AlgList *al, bool l) | ||
| 2805 | { | ||
| 2806 | AlgListNode *i; | ||
| 2807 | |||
| 2808 | for (i = al->first; i != NULL; i = i->next) | ||
| 2809 | print_alg(i->alg, l); | ||
| 2810 | } | ||
| 2811 | |||
| 2812 | void | ||
| 2813 | transform_alg(Trans t, Alg *alg) | ||
| 2814 | { | ||
| 2815 | int i; | ||
| 2816 | |||
| 2817 | for (i = 0; i < alg->len; i++) | ||
| 2818 | alg->move[i] = moves_ttable[t][alg->move[i]]; | ||
| 2819 | } | ||
| 2820 | |||
| 2821 | |||
| 2822 | void | ||
| 2823 | init() | ||
| 2824 | { | ||
| 2825 | /* Order is important! */ | ||
| 2826 | init_environment(); | ||
| 2827 | init_strings(); | ||
| 2828 | init_moves_aux(); | ||
| 2829 | init_moves(); | ||
| 2830 | init_auxtables(); | ||
| 2831 | init_trans_aux(); | ||
| 2832 | init_trans(); | ||
| 2833 | init_steps(); | ||
| 2834 | } | ||
| 2835 | |||
| 2836 | |||
diff --git a/old/2021-06-15-before-separating-steps/cube.h b/old/2021-06-15-before-separating-steps/cube.h new file mode 100644 index 0000000..c30b53f --- /dev/null +++ b/old/2021-06-15-before-separating-steps/cube.h | |||
| @@ -0,0 +1,72 @@ | |||
| 1 | #ifndef CUBE_H | ||
| 2 | #define CUBE_H | ||
| 3 | |||
| 4 | #include <stdio.h> | ||
| 5 | #include <stdbool.h> | ||
| 6 | #include <stdint.h> | ||
| 7 | #include <stdlib.h> | ||
| 8 | #include <string.h> | ||
| 9 | #include <time.h> | ||
| 10 | #include <unistd.h> | ||
| 11 | #include <sys/stat.h> | ||
| 12 | #include "cubetypes.h" | ||
| 13 | |||
| 14 | /* Steps *********************************************************************/ | ||
| 15 | |||
| 16 | extern Step eofb_HTM; | ||
| 17 | extern Step eorl_HTM; | ||
| 18 | extern Step eoud_HTM; | ||
| 19 | extern Step coud_HTM; | ||
| 20 | extern Step corl_HTM; | ||
| 21 | extern Step cofb_HTM; | ||
| 22 | extern Step coud_URF; | ||
| 23 | extern Step corl_URF; | ||
| 24 | extern Step cofb_URF; | ||
| 25 | extern Step corners_HTM; | ||
| 26 | extern Step corners_URF; | ||
| 27 | extern Step edges_HTM; | ||
| 28 | extern Step drud_HTM; | ||
| 29 | extern Step optimal_HTM; | ||
| 30 | |||
| 31 | extern PruneData pd_eofb_HTM; | ||
| 32 | extern PruneData pd_coud_HTM; | ||
| 33 | extern PruneData pd_corners_HTM; | ||
| 34 | extern PruneData pd_ep_HTM; | ||
| 35 | extern PruneData pd_drud_HTM; | ||
| 36 | |||
| 37 | /* Public functions **********************************************************/ | ||
| 38 | |||
| 39 | Cube apply_alg(Alg *alg, Cube cube); | ||
| 40 | Cube apply_move(Move m, Cube cube); | ||
| 41 | Cube apply_trans(Trans t, Cube cube); | ||
| 42 | bool block_solved(Cube cube, Block); | ||
| 43 | Center center_at(Cube cube, Center c); | ||
| 44 | Cube compose(Cube c2, Cube c1); /* Use c2 as an alg on c1 */ | ||
| 45 | Corner corner_at(Cube cube, Corner c); | ||
| 46 | Edge edge_at(Cube cube, Edge e); | ||
| 47 | bool equal(Cube c1, Cube c2); | ||
| 48 | Cube inverse_cube(Cube cube); | ||
| 49 | Move inverse_move(Move m); | ||
| 50 | Trans inverse_trans(Trans t); | ||
| 51 | bool is_admissible(Cube cube); | ||
| 52 | bool is_solved(Cube cube, bool reorient); | ||
| 53 | int piece_orientation(Cube cube, int piece, char *orientation); | ||
| 54 | void print_cube(Cube cube); | ||
| 55 | Cube random_cube(); | ||
| 56 | AlgList * solve(Cube cube, Step step, SolveOptions *opts); | ||
| 57 | |||
| 58 | void free_alg(Alg *alg); | ||
| 59 | void free_alglist(AlgList *l); | ||
| 60 | Alg * inverse_alg(Alg *alg); | ||
| 61 | Alg * new_alg(char *str); | ||
| 62 | Alg * on_inverse(Alg *alg); | ||
| 63 | void print_alg(Alg *alg, bool l); | ||
| 64 | void print_alglist(AlgList *al, bool l); | ||
| 65 | void transform_alg(Trans t, Alg *alg); | ||
| 66 | |||
| 67 | void print_ptable(PruneData *pd); | ||
| 68 | |||
| 69 | void init(); | ||
| 70 | |||
| 71 | #endif | ||
| 72 | |||
diff --git a/old/2021-06-15-before-separating-steps/cubetypes.h b/old/2021-06-15-before-separating-steps/cubetypes.h new file mode 100644 index 0000000..6ba3675 --- /dev/null +++ b/old/2021-06-15-before-separating-steps/cubetypes.h | |||
| @@ -0,0 +1,201 @@ | |||
| 1 | /* Typedefs ******************************************************************/ | ||
| 2 | |||
| 3 | typedef enum center Center; | ||
| 4 | typedef enum corner Corner; | ||
| 5 | typedef enum edge Edge; | ||
| 6 | typedef enum move Move; | ||
| 7 | typedef enum trans Trans; | ||
| 8 | |||
| 9 | typedef struct alg Alg; | ||
| 10 | typedef struct alglist AlgList; | ||
| 11 | typedef struct alglistnode AlgListNode; | ||
| 12 | typedef struct block Block; | ||
| 13 | typedef struct cube Cube; | ||
| 14 | typedef struct cubearray CubeArray; | ||
| 15 | typedef struct dfsdata DfsData; | ||
| 16 | typedef struct piecefilter PieceFilter; | ||
| 17 | typedef struct prunedata PruneData; | ||
| 18 | typedef struct solveoptions SolveOptions; | ||
| 19 | typedef struct step Step; | ||
| 20 | |||
| 21 | /* Enums *********************************************************************/ | ||
| 22 | |||
| 23 | enum | ||
| 24 | center | ||
| 25 | { | ||
| 26 | U_center, D_center, | ||
| 27 | R_center, L_center, | ||
| 28 | F_center, B_center | ||
| 29 | }; | ||
| 30 | |||
| 31 | enum | ||
| 32 | corner | ||
| 33 | { | ||
| 34 | UFR, UFL, UBL, UBR, | ||
| 35 | DFR, DFL, DBL, DBR | ||
| 36 | }; | ||
| 37 | |||
| 38 | enum | ||
| 39 | edge | ||
| 40 | { | ||
| 41 | UF, UL, UB, UR, | ||
| 42 | DF, DL, DB, DR, | ||
| 43 | FR, FL, BL, BR | ||
| 44 | }; | ||
| 45 | |||
| 46 | enum | ||
| 47 | move | ||
| 48 | { | ||
| 49 | NULLMOVE, | ||
| 50 | U, U2, U3, D, D2, D3, | ||
| 51 | R, R2, R3, L, L2, L3, | ||
| 52 | F, F2, F3, B, B2, B3, | ||
| 53 | Uw, Uw2, Uw3, Dw, Dw2, Dw3, | ||
| 54 | Rw, Rw2, Rw3, Lw, Lw2, Lw3, | ||
| 55 | Fw, Fw2, Fw3, Bw, Bw2, Bw3, | ||
| 56 | M, M2, M3, | ||
| 57 | S, S2, S3, | ||
| 58 | E, E2, E3, | ||
| 59 | x, x2, x3, | ||
| 60 | y, y2, y3, | ||
| 61 | z, z2, z3, | ||
| 62 | }; | ||
| 63 | |||
| 64 | enum | ||
| 65 | trans | ||
| 66 | { | ||
| 67 | uf, ur, ub, ul, | ||
| 68 | df, dr, db, dl, | ||
| 69 | rf, rd, rb, ru, | ||
| 70 | lf, ld, lb, lu, | ||
| 71 | fu, fr, fd, fl, | ||
| 72 | bu, br, bd, bl, | ||
| 73 | mirror, /* R|L */ | ||
| 74 | }; | ||
| 75 | |||
| 76 | |||
| 77 | /* Structs *******************************************************************/ | ||
| 78 | |||
| 79 | struct | ||
| 80 | alg | ||
| 81 | { | ||
| 82 | Move * move; | ||
| 83 | bool * inv; | ||
| 84 | int len; | ||
| 85 | int allocated; | ||
| 86 | }; | ||
| 87 | |||
| 88 | struct | ||
| 89 | alglist | ||
| 90 | { | ||
| 91 | AlgListNode * first; | ||
| 92 | AlgListNode * last; | ||
| 93 | int len; | ||
| 94 | }; | ||
| 95 | |||
| 96 | struct | ||
| 97 | alglistnode | ||
| 98 | { | ||
| 99 | Alg * alg; | ||
| 100 | AlgListNode * next; | ||
| 101 | }; | ||
| 102 | |||
| 103 | struct | ||
| 104 | block | ||
| 105 | { | ||
| 106 | bool edge[12]; | ||
| 107 | bool corner[8]; | ||
| 108 | bool center[6]; | ||
| 109 | }; | ||
| 110 | |||
| 111 | struct | ||
| 112 | cube | ||
| 113 | { | ||
| 114 | uint16_t epose; | ||
| 115 | uint16_t eposs; | ||
| 116 | uint16_t eposm; | ||
| 117 | uint16_t eofb; | ||
| 118 | uint16_t eorl; | ||
| 119 | uint16_t eoud; | ||
| 120 | uint16_t cp; | ||
| 121 | uint16_t coud; | ||
| 122 | uint16_t cofb; | ||
| 123 | uint16_t corl; | ||
| 124 | uint16_t cpos; | ||
| 125 | }; | ||
| 126 | |||
| 127 | struct | ||
| 128 | cubearray | ||
| 129 | { | ||
| 130 | int * ep; | ||
| 131 | int * eofb; | ||
| 132 | int * eorl; | ||
| 133 | int * eoud; | ||
| 134 | int * cp; | ||
| 135 | int * coud; | ||
| 136 | int * corl; | ||
| 137 | int * cofb; | ||
| 138 | int * cpos; | ||
| 139 | }; | ||
| 140 | |||
| 141 | struct | ||
| 142 | dfsdata | ||
| 143 | { | ||
| 144 | int d; | ||
| 145 | int m; | ||
| 146 | bool niss; | ||
| 147 | Move last1; | ||
| 148 | Move last2; | ||
| 149 | AlgList * sols; | ||
| 150 | Alg * current_alg; | ||
| 151 | Move sorted_moves[z3+1]; | ||
| 152 | }; | ||
| 153 | |||
| 154 | struct | ||
| 155 | piecefilter | ||
| 156 | { | ||
| 157 | bool epose; | ||
| 158 | bool eposs; | ||
| 159 | bool eposm; | ||
| 160 | bool eofb; | ||
| 161 | bool eorl; | ||
| 162 | bool eoud; | ||
| 163 | bool cp; | ||
| 164 | bool coud; | ||
| 165 | bool cofb; | ||
| 166 | bool corl; | ||
| 167 | bool cpos; | ||
| 168 | }; | ||
| 169 | |||
| 170 | struct | ||
| 171 | prunedata | ||
| 172 | { | ||
| 173 | char * filename; | ||
| 174 | uint8_t * ptable; | ||
| 175 | uint8_t * reached; | ||
| 176 | bool generated; | ||
| 177 | uint64_t n; | ||
| 178 | uint64_t size; | ||
| 179 | uint64_t (*index)(Cube); | ||
| 180 | bool (*moveset)(Move); | ||
| 181 | }; | ||
| 182 | |||
| 183 | struct | ||
| 184 | solveoptions | ||
| 185 | { | ||
| 186 | int min_moves; | ||
| 187 | int max_moves; | ||
| 188 | int max_solutions; | ||
| 189 | bool optimal_only; | ||
| 190 | bool can_niss; | ||
| 191 | bool feedback; | ||
| 192 | }; | ||
| 193 | |||
| 194 | struct | ||
| 195 | step | ||
| 196 | { | ||
| 197 | int (*check)(Cube); | ||
| 198 | int (*ready)(Cube); | ||
| 199 | bool (*moveset)(Move); | ||
| 200 | Trans pre_trans; | ||
| 201 | }; | ||
diff --git a/old/2021-06-15-before-separating-steps/main.c b/old/2021-06-15-before-separating-steps/main.c new file mode 100644 index 0000000..ff726b5 --- /dev/null +++ b/old/2021-06-15-before-separating-steps/main.c | |||
| @@ -0,0 +1,60 @@ | |||
| 1 | #include <stdio.h> | ||
| 2 | #include "cube.h" | ||
| 3 | |||
| 4 | int main() { | ||
| 5 | Alg *algo; | ||
| 6 | AlgList *sols; | ||
| 7 | Cube cube; | ||
| 8 | SolveOptions opts; | ||
| 9 | char line[1000]; | ||
| 10 | int i, ns = 2, nrand = 100000, sum1, sum2; | ||
| 11 | |||
| 12 | Step *stps[20] = {&drud_HTM, &optimal_HTM}; | ||
| 13 | char sss[30][30] = {"DR on U/D", "Optimal solution"}; | ||
| 14 | |||
| 15 | opts = (SolveOptions) { | ||
| 16 | .min_moves = 0, | ||
| 17 | .max_moves = 20, | ||
| 18 | .optimal_only = true, | ||
| 19 | .max_solutions = 1, | ||
| 20 | .can_niss = false, | ||
| 21 | .feedback = true | ||
| 22 | }; | ||
| 23 | |||
| 24 | init(); | ||
| 25 | |||
| 26 | /* | ||
| 27 | print_ptable(&pd_drud_HTM); | ||
| 28 | print_ptable(&pd_ep_HTM); | ||
| 29 | print_ptable(&pd_corners_HTM); | ||
| 30 | */ | ||
| 31 | |||
| 32 | srand(time(NULL)); | ||
| 33 | sum1 = 0; | ||
| 34 | sum2 = 0; | ||
| 35 | for (i = 0; i < nrand; i++) { | ||
| 36 | sum1 += optimal_HTM.check(random_cube()); | ||
| 37 | sum2 += corners_HTM.check(random_cube()); | ||
| 38 | } | ||
| 39 | printf("Average optimal pruning: %lf\n", ((double)sum1) / ((double) nrand)); | ||
| 40 | printf("Average corners pruning: %lf\n", ((double)sum2) / ((double) nrand)); | ||
| 41 | |||
| 42 | printf("Welcome to nissy 2.0! Insert a scramble:\n"); | ||
| 43 | |||
| 44 | if (fgets(line, 1000, stdin) != NULL) { | ||
| 45 | algo = new_alg(line); | ||
| 46 | cube = apply_alg(algo, (Cube){0}); | ||
| 47 | |||
| 48 | for (i = 0; i < ns; i++) { | ||
| 49 | if (stps[i]->check == NULL) | ||
| 50 | fprintf(stderr, "Check function for step %d is null\n", i); | ||
| 51 | sols = solve(cube, *stps[i], &opts); | ||
| 52 | printf("%s: %d solutions found:\n", sss[i], sols->len); | ||
| 53 | print_alglist(sols, true); | ||
| 54 | free_alglist(sols); | ||
| 55 | } | ||
| 56 | free(algo); | ||
| 57 | } | ||
| 58 | |||
| 59 | return 0; | ||
| 60 | } | ||
diff --git a/old/2021-06-15-before-separating-steps/steps.h b/old/2021-06-15-before-separating-steps/steps.h new file mode 100644 index 0000000..e2b71a0 --- /dev/null +++ b/old/2021-06-15-before-separating-steps/steps.h | |||
| @@ -0,0 +1,20 @@ | |||
| 1 | extern Step eofb_HTM; | ||
| 2 | extern Step eorl_HTM; | ||
| 3 | extern Step eoud_HTM; | ||
| 4 | extern Step coud_HTM; | ||
| 5 | extern Step corl_HTM; | ||
| 6 | extern Step cofb_HTM; | ||
| 7 | extern Step coud_URF; | ||
| 8 | extern Step corl_URF; | ||
| 9 | extern Step cofb_URF; | ||
| 10 | extern Step corners_HTM; | ||
| 11 | extern Step corners_URF; | ||
| 12 | extern Step edges_HTM; | ||
| 13 | extern Step drud_HTM; | ||
| 14 | extern Step optimal_HTM; | ||
| 15 | |||
| 16 | extern PruneData pd_eofb_HTM; | ||
| 17 | extern PruneData pd_coud_HTM; | ||
| 18 | extern PruneData pd_corners_HTM; | ||
| 19 | extern PruneData pd_ep_HTM; | ||
| 20 | extern PruneData pd_drud_HTM; | ||
diff --git a/old/2021-06-17-cachedata/cube.c b/old/2021-06-17-cachedata/cube.c new file mode 100644 index 0000000..58178dc --- /dev/null +++ b/old/2021-06-17-cachedata/cube.c | |||
| @@ -0,0 +1,2738 @@ | |||
| 1 | #include "cube.h" | ||
| 2 | |||
| 3 | /* Constants and macros *****************************************************/ | ||
| 4 | |||
| 5 | #define POW2TO11 2048ULL | ||
| 6 | #define POW2TO12 4096ULL | ||
| 7 | #define POW3TO7 2187ULL | ||
| 8 | #define POW3TO8 6561ULL | ||
| 9 | #define FACTORIAL4 24ULL | ||
| 10 | #define FACTORIAL6 720ULL | ||
| 11 | #define FACTORIAL8 40320ULL | ||
| 12 | #define FACTORIAL12 479001600ULL | ||
| 13 | #define BINOM12ON4 495ULL | ||
| 14 | #define BINOM8ON4 70ULL | ||
| 15 | #define MIN(a,b) (((a) < (b)) ? (a) : (b)) | ||
| 16 | #define MAX(a,b) (((a) > (b)) ? (a) : (b)) | ||
| 17 | |||
| 18 | #define NMOVES (z3+1) | ||
| 19 | #define NTRANS (mirror+1) | ||
| 20 | #define NROTATIONS (NTRANS-1) | ||
| 21 | #define PTABLESIZE(n) ((n+1) / 2) | ||
| 22 | |||
| 23 | |||
| 24 | /* Local functions **********************************************************/ | ||
| 25 | |||
| 26 | static Cube admissible_ep(Cube cube, PieceFilter f); | ||
| 27 | static bool allowed_next_move(Move move, DfsData *dd); | ||
| 28 | static void append_alg(AlgList *l, Alg *alg); | ||
| 29 | static void append_move(Alg *alg, Move m, bool inverse); | ||
| 30 | static Cube apply_alg_generic(Alg *alg, Cube c, PieceFilter f, bool a); | ||
| 31 | static void apply_permutation(int *perm, int *set, int n); | ||
| 32 | static Cube apply_move_cubearray(Move m, Cube cube, PieceFilter f); | ||
| 33 | static uint16_t array_ep_to_epos(int *ep, int *eps_solved); | ||
| 34 | static Cube arrays_to_cube(CubeArray *arr, PieceFilter f); | ||
| 35 | static int binomial(int n, int k); | ||
| 36 | static Cube compose_filtered(Cube c2, Cube c1, PieceFilter f); | ||
| 37 | static void cube_to_arrays(Cube cube, CubeArray *arr, PieceFilter f); | ||
| 38 | static int digit_array_to_int(int *a, int n, int b); | ||
| 39 | static int edge_slice(Edge e); /* E=0, S=1, M=2 */ | ||
| 40 | static int epos_dependent(int pos1, int pos2); | ||
| 41 | static uint16_t epos_from_arrays(int *epos, int *ep); | ||
| 42 | static void epos_to_partial_ep(uint16_t epos, int *ep, int *ss); | ||
| 43 | static int factorial(int n); | ||
| 44 | static void free_alglistnode(AlgListNode *aln); | ||
| 45 | static void free_cubearray(CubeArray *arr, PieceFilter f); | ||
| 46 | static void generate_ctable_dfs(Cube c, CacheData *cd, DfsData *dd); | ||
| 47 | static void generate_ptable_dfs(Cube c, PruneData *pd, DfsData *dd); | ||
| 48 | static void index_to_perm(int p, int n, int *r); | ||
| 49 | static void index_to_subset(int s, int n, int k, int *r); | ||
| 50 | static void int_to_digit_array(int a, int b, int n, int *r); | ||
| 51 | static void int_to_sum_zero_array(int x, int b, int n, int *a); | ||
| 52 | static int invert_digits(int a, int b, int n); | ||
| 53 | static bool is_perm(int *a, int n); | ||
| 54 | static bool is_subset(int *a, int n, int k); | ||
| 55 | static Cube move_via_arrays(CubeArray *arr, Cube c, PieceFilter pf); | ||
| 56 | static void movelist_to_position(Move *movelist, int *position); | ||
| 57 | static void moveset_to_list(Moveset ms, Checker f, Move *r); | ||
| 58 | static AlgList * new_alglist(); | ||
| 59 | static CubeArray * new_cubearray(Cube cube, PieceFilter f); | ||
| 60 | static int perm_sign(int *a, int n); | ||
| 61 | static int perm_to_index(int *a, int n); | ||
| 62 | /*static int powint(int a, int b);*/ | ||
| 63 | static void ptable_set_reached(PruneData *pd, uint64_t ind); | ||
| 64 | static void ptable_update(PruneData *pd, uint64_t ind, int m); | ||
| 65 | static void push_cachenode(CacheData *cd, Cube c, Alg *alg); | ||
| 66 | static void realloc_alg(Alg *alg, int n); | ||
| 67 | static bool read_ctable_file(CacheData *cd); | ||
| 68 | static bool read_mtables_file(); | ||
| 69 | static bool read_ptable_file(PruneData *pd); | ||
| 70 | static bool read_ttables_file(); | ||
| 71 | static Cube rotate_via_compose(Trans r, Cube c, PieceFilter f); | ||
| 72 | static void solve_cd(Cube c, Step s, SolveOptions *opts, DfsData *dd); | ||
| 73 | static void solve_dfs(Cube c, Step s, SolveOptions *opts, DfsData *dd); | ||
| 74 | static int subset_to_index(int *a, int n, int k); | ||
| 75 | static void sum_arrays_mod(int *src, int *dst, int n, int m); | ||
| 76 | static void swap(int *a, int *b); | ||
| 77 | static bool write_ctable_file(CacheData *cd); | ||
| 78 | static bool write_mtables_file(); | ||
| 79 | static bool write_ptable_file(PruneData *pd); | ||
| 80 | static bool write_ttables_file(); | ||
| 81 | |||
| 82 | static void init_auxtables(); | ||
| 83 | static void init_environment(); | ||
| 84 | static void init_moves(); | ||
| 85 | static void init_moves_aux(); | ||
| 86 | static void init_strings(); | ||
| 87 | static void init_trans(); | ||
| 88 | static void init_trans_aux(); | ||
| 89 | |||
| 90 | /* All sorts of useful costants and tables **********************************/ | ||
| 91 | |||
| 92 | static char * tabledir; | ||
| 93 | |||
| 94 | static PieceFilter pf_all; | ||
| 95 | static PieceFilter pf_4val; | ||
| 96 | static PieceFilter pf_epcp; | ||
| 97 | static PieceFilter pf_cpos; | ||
| 98 | static PieceFilter pf_cp; | ||
| 99 | static PieceFilter pf_ep; | ||
| 100 | static PieceFilter pf_e; | ||
| 101 | static PieceFilter pf_s; | ||
| 102 | static PieceFilter pf_m; | ||
| 103 | static PieceFilter pf_eo; | ||
| 104 | static PieceFilter pf_co; | ||
| 105 | |||
| 106 | static int epe_solved[4]; | ||
| 107 | static int eps_solved[4]; | ||
| 108 | static int epm_solved[4]; | ||
| 109 | |||
| 110 | static char move_string[NMOVES][7]; | ||
| 111 | static char edge_string[12][7]; | ||
| 112 | static char corner_string[8][7]; | ||
| 113 | static char center_string[6][7]; | ||
| 114 | |||
| 115 | static bool commute[NMOVES][NMOVES]; | ||
| 116 | static bool possible_next[NMOVES][NMOVES][NMOVES]; | ||
| 117 | static Move inverse_move_aux[NMOVES]; | ||
| 118 | static Trans inverse_trans_aux[NTRANS]; | ||
| 119 | static int epos_dependent_aux[BINOM12ON4][BINOM12ON4]; | ||
| 120 | |||
| 121 | static uint16_t epose_ttable[NTRANS][FACTORIAL12/FACTORIAL8]; | ||
| 122 | static uint16_t eposs_ttable[NTRANS][FACTORIAL12/FACTORIAL8]; | ||
| 123 | static uint16_t eposm_ttable[NTRANS][FACTORIAL12/FACTORIAL8]; | ||
| 124 | static uint16_t eo_ttable[NTRANS][POW2TO11]; | ||
| 125 | static uint16_t cp_ttable[NTRANS][FACTORIAL8]; | ||
| 126 | static uint16_t co_ttable[NTRANS][POW3TO7]; | ||
| 127 | static uint16_t cpos_ttable[NTRANS][FACTORIAL6]; | ||
| 128 | static Move moves_ttable[NTRANS][NMOVES]; | ||
| 129 | |||
| 130 | static uint16_t epose_mtable[NMOVES][FACTORIAL12/FACTORIAL8]; | ||
| 131 | static uint16_t eposs_mtable[NMOVES][FACTORIAL12/FACTORIAL8]; | ||
| 132 | static uint16_t eposm_mtable[NMOVES][FACTORIAL12/FACTORIAL8]; | ||
| 133 | static uint16_t eofb_mtable[NMOVES][POW2TO11]; | ||
| 134 | static uint16_t eorl_mtable[NMOVES][POW2TO11]; | ||
| 135 | static uint16_t eoud_mtable[NMOVES][POW2TO11]; | ||
| 136 | static uint16_t cp_mtable[NMOVES][FACTORIAL8]; | ||
| 137 | static uint16_t coud_mtable[NMOVES][POW3TO7]; | ||
| 138 | static uint16_t cofb_mtable[NMOVES][POW3TO7]; | ||
| 139 | static uint16_t corl_mtable[NMOVES][POW3TO7]; | ||
| 140 | static uint16_t cpos_mtable[NMOVES][FACTORIAL6]; | ||
| 141 | |||
| 142 | static uint64_t me[12]; | ||
| 143 | |||
| 144 | static int edge_cycle[NMOVES][12]; | ||
| 145 | static int corner_cycle[NMOVES][8]; | ||
| 146 | static int center_cycle[NMOVES][6]; | ||
| 147 | static int eofb_flipped[NMOVES][12]; | ||
| 148 | static int eorl_flipped[NMOVES][12]; | ||
| 149 | static int eoud_flipped[NMOVES][12]; | ||
| 150 | static int coud_flipped[NMOVES][8]; | ||
| 151 | static int corl_flipped[NMOVES][8]; | ||
| 152 | static int cofb_flipped[NMOVES][8]; | ||
| 153 | static Alg * equiv_alg[NMOVES]; | ||
| 154 | |||
| 155 | static int epose_source[NTRANS]; /* 0=epose, 1=eposs, 2=eposm */ | ||
| 156 | static int eposs_source[NTRANS]; | ||
| 157 | static int eposm_source[NTRANS]; | ||
| 158 | static int eofb_source[NTRANS]; /* 0=eoud, 1=eorl, 2=eofb */ | ||
| 159 | static int eorl_source[NTRANS]; | ||
| 160 | static int eoud_source[NTRANS]; | ||
| 161 | static int coud_source[NTRANS]; /* 0=coud, 1=corl, 2=cofb */ | ||
| 162 | static int cofb_source[NTRANS]; | ||
| 163 | static int corl_source[NTRANS]; | ||
| 164 | static int ep_mirror[12]; | ||
| 165 | static int cp_mirror[8]; | ||
| 166 | static int cpos_mirror[6]; | ||
| 167 | static Alg * trans_algs[NROTATIONS]; | ||
| 168 | |||
| 169 | |||
| 170 | /* Local functions implementation ********************************************/ | ||
| 171 | |||
| 172 | static Cube | ||
| 173 | admissible_ep(Cube cube, PieceFilter f) | ||
| 174 | { | ||
| 175 | CubeArray *arr = new_cubearray(cube, f); | ||
| 176 | Cube ret; | ||
| 177 | bool used[12] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; | ||
| 178 | int i, j; | ||
| 179 | |||
| 180 | for (i = 0; i < 12; i++) | ||
| 181 | if (arr->ep[i] != -1) | ||
| 182 | used[arr->ep[i]] = true; | ||
| 183 | |||
| 184 | for (i = 0, j = 0; i < 12; i++) { | ||
| 185 | for ( ; j < 11 && used[j]; j++); | ||
| 186 | if (arr->ep[i] == -1) | ||
| 187 | arr->ep[i] = j++; | ||
| 188 | } | ||
| 189 | |||
| 190 | ret = arrays_to_cube(arr, pf_ep); | ||
| 191 | free_cubearray(arr, f); | ||
| 192 | |||
| 193 | return ret; | ||
| 194 | } | ||
| 195 | |||
| 196 | static bool | ||
| 197 | allowed_next_move(Move move, DfsData *dd) | ||
| 198 | { | ||
| 199 | if (!possible_next[dd->last2][dd->last1][move]) | ||
| 200 | return false; | ||
| 201 | |||
| 202 | if (commute[dd->last1][move]) | ||
| 203 | return dd->move_position[dd->last1] < dd->move_position[move]; | ||
| 204 | |||
| 205 | return true; | ||
| 206 | } | ||
| 207 | |||
| 208 | static void | ||
| 209 | append_alg(AlgList *l, Alg *alg) | ||
| 210 | { | ||
| 211 | AlgListNode *node = malloc(sizeof(AlgListNode)); | ||
| 212 | int i; | ||
| 213 | |||
| 214 | node->alg = new_alg(""); | ||
| 215 | for (i = 0; i < alg->len; i++) | ||
| 216 | append_move(node->alg, alg->move[i], alg->inv[i]); | ||
| 217 | node->next = NULL; | ||
| 218 | |||
| 219 | if (++l->len == 1) | ||
| 220 | l->first = node; | ||
| 221 | else | ||
| 222 | l->last->next = node; | ||
| 223 | l->last = node; | ||
| 224 | } | ||
| 225 | |||
| 226 | static void | ||
| 227 | append_move(Alg *alg, Move m, bool inverse) | ||
| 228 | { | ||
| 229 | if (alg->len == alg->allocated) | ||
| 230 | realloc_alg(alg, 2*alg->len); | ||
| 231 | |||
| 232 | alg->move[alg->len] = m; | ||
| 233 | alg->inv [alg->len] = inverse; | ||
| 234 | alg->len++; | ||
| 235 | } | ||
| 236 | |||
| 237 | static Cube | ||
| 238 | apply_alg_generic(Alg *alg, Cube c, PieceFilter f, bool a) | ||
| 239 | { | ||
| 240 | Cube ret = {0}; | ||
| 241 | int i; | ||
| 242 | |||
| 243 | for (i = 0; i < alg->len; i++) | ||
| 244 | if (alg->inv[i]) | ||
| 245 | ret = a ? apply_move(alg->move[i], ret) : | ||
| 246 | apply_move_cubearray(alg->move[i], ret, f); | ||
| 247 | |||
| 248 | ret = compose_filtered(c, inverse_cube(ret), f); | ||
| 249 | |||
| 250 | for (i = 0; i < alg->len; i++) | ||
| 251 | if (!alg->inv[i]) | ||
| 252 | ret = a ? apply_move(alg->move[i], ret) : | ||
| 253 | apply_move_cubearray(alg->move[i], ret, f); | ||
| 254 | |||
| 255 | return ret; | ||
| 256 | } | ||
| 257 | |||
| 258 | static void | ||
| 259 | apply_permutation(int *perm, int *set, int n) | ||
| 260 | { | ||
| 261 | int *aux = malloc(n * sizeof(int)); | ||
| 262 | int i; | ||
| 263 | |||
| 264 | if (!is_perm(perm, n)) | ||
| 265 | return; | ||
| 266 | |||
| 267 | for (i = 0; i < n; i++) | ||
| 268 | aux[i] = set[perm[i]]; | ||
| 269 | |||
| 270 | memcpy(set, aux, n * sizeof(int)); | ||
| 271 | free(aux); | ||
| 272 | } | ||
| 273 | |||
| 274 | static Cube | ||
| 275 | apply_move_cubearray(Move m, Cube cube, PieceFilter f) | ||
| 276 | { | ||
| 277 | CubeArray m_arr = { | ||
| 278 | edge_cycle[m], | ||
| 279 | eofb_flipped[m], | ||
| 280 | eorl_flipped[m], | ||
| 281 | eoud_flipped[m], | ||
| 282 | corner_cycle[m], | ||
| 283 | coud_flipped[m], | ||
| 284 | corl_flipped[m], | ||
| 285 | cofb_flipped[m], | ||
| 286 | center_cycle[m] | ||
| 287 | }; | ||
| 288 | |||
| 289 | return move_via_arrays(&m_arr, cube, f); | ||
| 290 | } | ||
| 291 | |||
| 292 | static uint16_t | ||
| 293 | array_ep_to_epos(int *ep, int *ss) | ||
| 294 | { | ||
| 295 | int epos[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; | ||
| 296 | int eps[4]; | ||
| 297 | int i, j, is; | ||
| 298 | |||
| 299 | for (i = 0, is = 0; i < 12; i++) { | ||
| 300 | for (j = 0; j < 4; j++) { | ||
| 301 | if (ep[i] == ss[j]) { | ||
| 302 | eps[is++] = j; | ||
| 303 | epos[i] = 1; | ||
| 304 | } | ||
| 305 | } | ||
| 306 | } | ||
| 307 | |||
| 308 | for (i = 0; i < 4; i++) | ||
| 309 | swap(&epos[ss[i]], &epos[i+8]); | ||
| 310 | |||
| 311 | return epos_from_arrays(epos, eps); | ||
| 312 | } | ||
| 313 | |||
| 314 | static Cube | ||
| 315 | arrays_to_cube(CubeArray *arr, PieceFilter f) | ||
| 316 | { | ||
| 317 | Cube ret = {0}; | ||
| 318 | |||
| 319 | if (f.epose) | ||
| 320 | ret.epose = array_ep_to_epos(arr->ep, epe_solved); | ||
| 321 | if (f.eposs) | ||
| 322 | ret.eposs = array_ep_to_epos(arr->ep, eps_solved); | ||
| 323 | if (f.eposm) | ||
| 324 | ret.eposm = array_ep_to_epos(arr->ep, epm_solved); | ||
| 325 | if (f.eofb) | ||
| 326 | ret.eofb = digit_array_to_int(arr->eofb, 11, 2); | ||
| 327 | if (f.eorl) | ||
| 328 | ret.eorl = digit_array_to_int(arr->eorl, 11, 2); | ||
| 329 | if (f.eoud) | ||
| 330 | ret.eoud = digit_array_to_int(arr->eoud, 11, 2); | ||
| 331 | if (f.cp) | ||
| 332 | ret.cp = perm_to_index(arr->cp, 8); | ||
| 333 | if (f.coud) | ||
| 334 | ret.coud = digit_array_to_int(arr->coud, 7, 3); | ||
| 335 | if (f.corl) | ||
| 336 | ret.corl = digit_array_to_int(arr->corl, 7, 3); | ||
| 337 | if (f.cofb) | ||
| 338 | ret.cofb = digit_array_to_int(arr->cofb, 7, 3); | ||
| 339 | if (f.cpos) | ||
| 340 | ret.cpos = perm_to_index(arr->cpos, 6); | ||
| 341 | |||
| 342 | return ret; | ||
| 343 | } | ||
| 344 | |||
| 345 | static int | ||
| 346 | binomial(int n, int k) | ||
| 347 | { | ||
| 348 | if (n < 0 || k < 0 || k > n) | ||
| 349 | return 0; | ||
| 350 | |||
| 351 | return factorial(n) / (factorial(k) * factorial(n-k)); | ||
| 352 | } | ||
| 353 | |||
| 354 | static Cube | ||
| 355 | compose_filtered(Cube c2, Cube c1, PieceFilter f) | ||
| 356 | { | ||
| 357 | CubeArray *arr = new_cubearray(c2, f); | ||
| 358 | Cube ret; | ||
| 359 | |||
| 360 | ret = move_via_arrays(arr, c1, f); | ||
| 361 | free_cubearray(arr, f); | ||
| 362 | |||
| 363 | return ret; | ||
| 364 | } | ||
| 365 | |||
| 366 | static void | ||
| 367 | cube_to_arrays(Cube cube, CubeArray *arr, PieceFilter f) | ||
| 368 | { | ||
| 369 | int i; | ||
| 370 | |||
| 371 | if (f.epose || f.eposs || f.eposm) | ||
| 372 | for (i = 0; i < 12; i++) | ||
| 373 | arr->ep[i] = -1; | ||
| 374 | |||
| 375 | if (f.epose) | ||
| 376 | epos_to_partial_ep(cube.epose, arr->ep, epe_solved); | ||
| 377 | if (f.eposs) | ||
| 378 | epos_to_partial_ep(cube.eposs, arr->ep, eps_solved); | ||
| 379 | if (f.eposm) | ||
| 380 | epos_to_partial_ep(cube.eposm, arr->ep, epm_solved); | ||
| 381 | if (f.eofb) | ||
| 382 | int_to_sum_zero_array(cube.eofb, 2, 12, arr->eofb); | ||
| 383 | if (f.eorl) | ||
| 384 | int_to_sum_zero_array(cube.eorl, 2, 12, arr->eorl); | ||
| 385 | if (f.eoud) | ||
| 386 | int_to_sum_zero_array(cube.eoud, 2, 12, arr->eoud); | ||
| 387 | if (f.cp) | ||
| 388 | index_to_perm(cube.cp, 8, arr->cp); | ||
| 389 | if (f.coud) | ||
| 390 | int_to_sum_zero_array(cube.coud, 3, 8, arr->coud); | ||
| 391 | if (f.corl) | ||
| 392 | int_to_sum_zero_array(cube.corl, 3, 8, arr->corl); | ||
| 393 | if (f.cofb) | ||
| 394 | int_to_sum_zero_array(cube.cofb, 3, 8, arr->cofb); | ||
| 395 | if (f.cpos) | ||
| 396 | index_to_perm(cube.cpos, 6, arr->cpos); | ||
| 397 | } | ||
| 398 | |||
| 399 | static int | ||
| 400 | digit_array_to_int(int *a, int n, int b) | ||
| 401 | { | ||
| 402 | int i, ret = 0, p = 1; | ||
| 403 | |||
| 404 | for (i = 0; i < n; i++, p *= b) | ||
| 405 | ret += a[i] * p; | ||
| 406 | |||
| 407 | return ret; | ||
| 408 | } | ||
| 409 | |||
| 410 | static int | ||
| 411 | edge_slice(Edge e) { | ||
| 412 | if (e < 0 || e > 11) | ||
| 413 | return -1; | ||
| 414 | |||
| 415 | if (e == FR || e == FL || e == BL || e == BR) | ||
| 416 | return 0; | ||
| 417 | if (e == UR || e == UL || e == DR || e == DL) | ||
| 418 | return 1; | ||
| 419 | |||
| 420 | return 2; | ||
| 421 | } | ||
| 422 | |||
| 423 | static int | ||
| 424 | epos_dependent(int poss, int pose) | ||
| 425 | { | ||
| 426 | int ep[12] = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}; | ||
| 427 | int ep8[8] = {0, 0, 0, 0, 0, 0, 0, 0}; | ||
| 428 | int i, j; | ||
| 429 | |||
| 430 | epos_to_partial_ep(poss*FACTORIAL4, ep, eps_solved); | ||
| 431 | epos_to_partial_ep(pose*FACTORIAL4, ep, epe_solved); | ||
| 432 | |||
| 433 | for (i = 0, j = 0; i < 12; i++) | ||
| 434 | if (edge_slice(ep[i]) != 1) | ||
| 435 | ep8[j++] = (edge_slice(ep[i]) == 0) ? 1 : 0; | ||
| 436 | |||
| 437 | return subset_to_index(ep8, 8, 4); | ||
| 438 | } | ||
| 439 | |||
| 440 | static uint16_t | ||
| 441 | epos_from_arrays(int *epos, int *ep) | ||
| 442 | { | ||
| 443 | return FACTORIAL4 * subset_to_index(epos,12,4) + perm_to_index(ep,4); | ||
| 444 | } | ||
| 445 | |||
| 446 | static void | ||
| 447 | epos_to_partial_ep(uint16_t epos, int *ep, int *ss) | ||
| 448 | { | ||
| 449 | int i, is, eposs[12], eps[4]; | ||
| 450 | |||
| 451 | index_to_perm(epos % FACTORIAL4, 4, eps); | ||
| 452 | index_to_subset(epos / FACTORIAL4, 12, 4, eposs); | ||
| 453 | |||
| 454 | for (i = 0; i < 4; i++) | ||
| 455 | swap(&eposs[ss[i]], &eposs[i+8]); | ||
| 456 | |||
| 457 | for (i = 0, is = 0; i < 12; i++) | ||
| 458 | if (eposs[i]) | ||
| 459 | ep[i] = ss[eps[is++]]; | ||
| 460 | } | ||
| 461 | |||
| 462 | static int | ||
| 463 | factorial(int n) | ||
| 464 | { | ||
| 465 | int i, ret = 1; | ||
| 466 | |||
| 467 | if (n < 0) | ||
| 468 | return 0; | ||
| 469 | |||
| 470 | for (i = 1; i <= n; i++) | ||
| 471 | ret *= i; | ||
| 472 | |||
| 473 | return ret; | ||
| 474 | } | ||
| 475 | |||
| 476 | void | ||
| 477 | free_alg(Alg *alg) | ||
| 478 | { | ||
| 479 | free(alg->move); | ||
| 480 | free(alg->inv); | ||
| 481 | free(alg); | ||
| 482 | } | ||
| 483 | |||
| 484 | void | ||
| 485 | free_alglist(AlgList *l) | ||
| 486 | { | ||
| 487 | AlgListNode *aux, *i = l->first; | ||
| 488 | |||
| 489 | while (i != NULL) { | ||
| 490 | aux = i->next; | ||
| 491 | free_alglistnode(i); | ||
| 492 | i = aux; | ||
| 493 | } | ||
| 494 | free(l); | ||
| 495 | } | ||
| 496 | |||
| 497 | void | ||
| 498 | free_alglistnode(AlgListNode *aln) | ||
| 499 | { | ||
| 500 | free_alg(aln->alg); | ||
| 501 | free(aln); | ||
| 502 | } | ||
| 503 | |||
| 504 | static void | ||
| 505 | free_cubearray(CubeArray *arr, PieceFilter f) | ||
| 506 | { | ||
| 507 | if (f.epose || f.eposs || f.eposm) | ||
| 508 | free(arr->ep); | ||
| 509 | if (f.eofb) | ||
| 510 | free(arr->eofb); | ||
| 511 | if (f.eorl) | ||
| 512 | free(arr->eorl); | ||
| 513 | if (f.eoud) | ||
| 514 | free(arr->eoud); | ||
| 515 | if (f.cp) | ||
| 516 | free(arr->cp); | ||
| 517 | if (f.coud) | ||
| 518 | free(arr->coud); | ||
| 519 | if (f.corl) | ||
| 520 | free(arr->corl); | ||
| 521 | if (f.cofb) | ||
| 522 | free(arr->cofb); | ||
| 523 | if (f.cpos) | ||
| 524 | free(arr->cpos); | ||
| 525 | |||
| 526 | free(arr); | ||
| 527 | } | ||
| 528 | |||
| 529 | static void | ||
| 530 | generate_ctable_dfs(Cube c, CacheData *cd, DfsData *dd) | ||
| 531 | { | ||
| 532 | int i; | ||
| 533 | bool flag; | ||
| 534 | Move move, l1 = dd->last1, l2 = dd->last2; | ||
| 535 | |||
| 536 | if (dd->current_alg->len > 0) { | ||
| 537 | for (i = 0, flag = true; i < cd->nind; i++) { | ||
| 538 | if (cd->index[i](c) != cd->index[i]((Cube){0})) { | ||
| 539 | flag = false; | ||
| 540 | break; | ||
| 541 | } | ||
| 542 | } | ||
| 543 | if (flag) | ||
| 544 | return; | ||
| 545 | } | ||
| 546 | |||
| 547 | if (dd->current_alg->len == dd->d) { | ||
| 548 | push_cachenode(cd, c, dd->current_alg); | ||
| 549 | return; | ||
| 550 | } | ||
| 551 | |||
| 552 | for (i = 0; dd->sorted_moves[i] != NULLMOVE; i++) { | ||
| 553 | move = dd->sorted_moves[i]; | ||
| 554 | if (allowed_next_move(move, dd)) { | ||
| 555 | dd->last2 = dd->last1; | ||
| 556 | dd->last1 = move; | ||
| 557 | append_move(dd->current_alg, move, false); | ||
| 558 | generate_ctable_dfs(apply_move(move, c), cd, dd); | ||
| 559 | dd->current_alg->len--; | ||
| 560 | dd->last2 = l2; | ||
| 561 | dd->last1 = l1; | ||
| 562 | } | ||
| 563 | } | ||
| 564 | } | ||
| 565 | |||
| 566 | static void | ||
| 567 | generate_ptable_dfs(Cube c, PruneData *pd, DfsData *dd) | ||
| 568 | { | ||
| 569 | uint64_t ind = pd->index(c); | ||
| 570 | int oldval = PTABLEVAL(pd->ptable, ind); | ||
| 571 | Move i, move, l1 = dd->last1, l2 = dd->last2; | ||
| 572 | |||
| 573 | if (oldval < dd->m || PTABLEVAL(pd->reached, ind) || pd->n == pd->size) | ||
| 574 | return; | ||
| 575 | |||
| 576 | ptable_set_reached(pd, ind); | ||
| 577 | |||
| 578 | if (dd->m == dd->d) { | ||
| 579 | if (dd->m < oldval) | ||
| 580 | ptable_update(pd, ind, dd->m); | ||
| 581 | return; | ||
| 582 | } | ||
| 583 | |||
| 584 | dd->m++; | ||
| 585 | for (i = 0; dd->sorted_moves[i] != NULLMOVE; i++) { | ||
| 586 | move = dd->sorted_moves[i]; | ||
| 587 | if (allowed_next_move(move, dd)) { | ||
| 588 | dd->last2 = dd->last1; | ||
| 589 | dd->last1 = move; | ||
| 590 | generate_ptable_dfs(apply_move(move, c), pd, dd); | ||
| 591 | dd->last2 = l2; | ||
| 592 | dd->last1 = l1; | ||
| 593 | } | ||
| 594 | } | ||
| 595 | |||
| 596 | dd->m--; | ||
| 597 | dd->last1 = l1; | ||
| 598 | dd->last2 = l2; | ||
| 599 | } | ||
| 600 | |||
| 601 | static void | ||
| 602 | index_to_perm(int p, int n, int *r) | ||
| 603 | { | ||
| 604 | int *a = malloc(n * sizeof(int)); | ||
| 605 | int i, j, c; | ||
| 606 | |||
| 607 | for (i = 0; i < n; i++) | ||
| 608 | a[i] = 0; | ||
| 609 | |||
| 610 | if (p < 0 || p >= factorial(n)) | ||
| 611 | for (i = 0; i < n; i++) | ||
| 612 | r[i] = -1; | ||
| 613 | |||
| 614 | for (i = 0; i < n; i++) { | ||
| 615 | c = 0; | ||
| 616 | j = 0; | ||
| 617 | while (c <= p / factorial(n-i-1)) | ||
| 618 | c += a[j++] ? 0 : 1; | ||
| 619 | r[i] = j-1; | ||
| 620 | a[j-1] = 1; | ||
| 621 | p %= factorial(n-i-1); | ||
| 622 | } | ||
| 623 | |||
| 624 | free(a); | ||
| 625 | } | ||
| 626 | |||
| 627 | static void | ||
| 628 | index_to_subset(int s, int n, int k, int *r) | ||
| 629 | { | ||
| 630 | int i, j, v; | ||
| 631 | |||
| 632 | if (s < 0 || s >= binomial(n, k)) { | ||
| 633 | for (i = 0; i < n; i++) | ||
| 634 | r[i] = -1; | ||
| 635 | return; | ||
| 636 | } | ||
| 637 | |||
| 638 | for (i = 0; i < n; i++) { | ||
| 639 | if (k == n-i) { | ||
| 640 | for (j = i; j < n; j++) | ||
| 641 | r[j] = 1; | ||
| 642 | return; | ||
| 643 | } | ||
| 644 | |||
| 645 | if (k == 0) { | ||
| 646 | for (j = i; j < n; j++) | ||
| 647 | r[j] = 0; | ||
| 648 | return; | ||
| 649 | } | ||
| 650 | |||
| 651 | v = binomial(n-i-1, k); | ||
| 652 | if (s >= v) { | ||
| 653 | r[i] = 1; | ||
| 654 | k--; | ||
| 655 | s -= v; | ||
| 656 | } else { | ||
| 657 | r[i] = 0; | ||
| 658 | } | ||
| 659 | } | ||
| 660 | } | ||
| 661 | |||
| 662 | static void | ||
| 663 | int_to_digit_array(int a, int b, int n, int *r) | ||
| 664 | { | ||
| 665 | int i; | ||
| 666 | |||
| 667 | if (b <= 1) | ||
| 668 | for (i = 0; i < n; i++) | ||
| 669 | r[i] = 0; | ||
| 670 | else | ||
| 671 | for (i = 0; i < n; i++, a /= b) | ||
| 672 | r[i] = a % b; | ||
| 673 | } | ||
| 674 | |||
| 675 | static void | ||
| 676 | int_to_sum_zero_array(int x, int b, int n, int *a) | ||
| 677 | { | ||
| 678 | int i, s = 0; | ||
| 679 | |||
| 680 | if (b <= 1) { | ||
| 681 | for (i = 0; i < n; i++) | ||
| 682 | a[i] = 0; | ||
| 683 | } else { | ||
| 684 | int_to_digit_array(x, b, n-1, a); | ||
| 685 | for (i = 0; i < n - 1; i++) | ||
| 686 | s = (s + a[i]) % b; | ||
| 687 | a[n-1] = (b - s) % b; | ||
| 688 | } | ||
| 689 | } | ||
| 690 | |||
| 691 | static int | ||
| 692 | invert_digits(int a, int b, int n) | ||
| 693 | { | ||
| 694 | int i, ret, *r = malloc(n * sizeof(int)); | ||
| 695 | |||
| 696 | int_to_digit_array(a, b, n, r); | ||
| 697 | for (i = 0; i < n; i++) | ||
| 698 | r[i] = (b-r[i]) % b; | ||
| 699 | |||
| 700 | ret = digit_array_to_int(r, n, b); | ||
| 701 | free(r); | ||
| 702 | return ret; | ||
| 703 | } | ||
| 704 | |||
| 705 | static bool | ||
| 706 | is_perm(int *a, int n) | ||
| 707 | { | ||
| 708 | int *aux = malloc(n * sizeof(int)); | ||
| 709 | int i; | ||
| 710 | |||
| 711 | for (i = 0; i < n; i++) | ||
| 712 | if (a[i] < 0 || a[i] >= n) | ||
| 713 | return false; | ||
| 714 | else | ||
| 715 | aux[a[i]] = 1; | ||
| 716 | |||
| 717 | for (i = 0; i < n; i++) | ||
| 718 | if (!aux[i]) | ||
| 719 | return false; | ||
| 720 | |||
| 721 | free(aux); | ||
| 722 | |||
| 723 | return true; | ||
| 724 | } | ||
| 725 | |||
| 726 | static bool | ||
| 727 | is_subset(int *a, int n, int k) | ||
| 728 | { | ||
| 729 | int i, sum = 0; | ||
| 730 | |||
| 731 | for (i = 0; i < n; i++) | ||
| 732 | sum += a[i] ? 1 : 0; | ||
| 733 | |||
| 734 | return sum == k; | ||
| 735 | } | ||
| 736 | |||
| 737 | static Cube | ||
| 738 | move_via_arrays(CubeArray *arr, Cube c, PieceFilter f) | ||
| 739 | { | ||
| 740 | CubeArray *arrc = new_cubearray(c, f); | ||
| 741 | Cube ret; | ||
| 742 | |||
| 743 | if (f.epose || f.eposs || f.eposm) | ||
| 744 | apply_permutation(arr->ep, arrc->ep, 12); | ||
| 745 | |||
| 746 | if (f.eofb) { | ||
| 747 | apply_permutation(arr->ep, arrc->eofb, 12); | ||
| 748 | sum_arrays_mod(arr->eofb, arrc->eofb, 12, 2); | ||
| 749 | } | ||
| 750 | |||
| 751 | if (f.eorl) { | ||
| 752 | apply_permutation(arr->ep, arrc->eorl, 12); | ||
| 753 | sum_arrays_mod(arr->eorl, arrc->eorl, 12, 2); | ||
| 754 | } | ||
| 755 | |||
| 756 | if (f.eoud) { | ||
| 757 | apply_permutation(arr->ep, arrc->eoud, 12); | ||
| 758 | sum_arrays_mod(arr->eoud, arrc->eoud, 12, 2); | ||
| 759 | } | ||
| 760 | |||
| 761 | if (f.cp) | ||
| 762 | apply_permutation(arr->cp, arrc->cp, 8); | ||
| 763 | |||
| 764 | if (f.coud) { | ||
| 765 | apply_permutation(arr->cp, arrc->coud, 8); | ||
| 766 | sum_arrays_mod(arr->coud, arrc->coud, 8, 3); | ||
| 767 | } | ||
| 768 | |||
| 769 | if (f.corl) { | ||
| 770 | apply_permutation(arr->cp, arrc->corl, 8); | ||
| 771 | sum_arrays_mod(arr->corl, arrc->corl, 8, 3); | ||
| 772 | } | ||
| 773 | |||
| 774 | if (f.cofb) { | ||
| 775 | apply_permutation(arr->cp, arrc->cofb, 8); | ||
| 776 | sum_arrays_mod(arr->cofb, arrc->cofb, 8, 3); | ||
| 777 | } | ||
| 778 | |||
| 779 | if (f.cpos) | ||
| 780 | apply_permutation(arr->cpos, arrc->cpos, 6); | ||
| 781 | |||
| 782 | ret = arrays_to_cube(arrc, f); | ||
| 783 | free_cubearray(arrc, f); | ||
| 784 | |||
| 785 | return ret; | ||
| 786 | } | ||
| 787 | |||
| 788 | static void | ||
| 789 | movelist_to_position(Move *movelist, int *position) | ||
| 790 | { | ||
| 791 | Move m; | ||
| 792 | |||
| 793 | for (m = 0; m < NMOVES && movelist[m] != NULLMOVE; m++) | ||
| 794 | position[movelist[m]] = m; | ||
| 795 | } | ||
| 796 | |||
| 797 | static void | ||
| 798 | moveset_to_list(bool (*ms)(Move m), int (*f)(Cube), Move *r) | ||
| 799 | { | ||
| 800 | Cube c; | ||
| 801 | int b[NMOVES]; | ||
| 802 | int na = 0, nb = 0; | ||
| 803 | Move i; | ||
| 804 | |||
| 805 | if (ms == NULL) { | ||
| 806 | fprintf(stderr, "Error: no moveset given\n"); | ||
| 807 | return; | ||
| 808 | } | ||
| 809 | |||
| 810 | for (i = U; i < NMOVES; i++) { | ||
| 811 | if (ms(i)) { | ||
| 812 | c = apply_move(i, (Cube){0}); | ||
| 813 | if (f != NULL && f(c)) | ||
| 814 | r[na++] = i; | ||
| 815 | else | ||
| 816 | b[nb++] = i; | ||
| 817 | } | ||
| 818 | } | ||
| 819 | |||
| 820 | memcpy(r + na, b, nb * sizeof(Move)); | ||
| 821 | r[na+nb] = NULLMOVE; | ||
| 822 | } | ||
| 823 | |||
| 824 | static AlgList * | ||
| 825 | new_alglist() | ||
| 826 | { | ||
| 827 | AlgList *ret = malloc(sizeof(AlgList)); | ||
| 828 | |||
| 829 | ret->len = 0; | ||
| 830 | ret->first = NULL; | ||
| 831 | ret->last = NULL; | ||
| 832 | |||
| 833 | return ret; | ||
| 834 | } | ||
| 835 | |||
| 836 | static CubeArray * | ||
| 837 | new_cubearray(Cube cube, PieceFilter f) | ||
| 838 | { | ||
| 839 | CubeArray *arr = malloc(sizeof(CubeArray)); | ||
| 840 | |||
| 841 | if (f.epose || f.eposs || f.eposm) | ||
| 842 | arr->ep = malloc(12 * sizeof(int)); | ||
| 843 | if (f.eofb) | ||
| 844 | arr->eofb = malloc(12 * sizeof(int)); | ||
| 845 | if (f.eorl) | ||
| 846 | arr->eorl = malloc(12 * sizeof(int)); | ||
| 847 | if (f.eoud) | ||
| 848 | arr->eoud = malloc(12 * sizeof(int)); | ||
| 849 | if (f.cp) | ||
| 850 | arr->cp = malloc(8 * sizeof(int)); | ||
| 851 | if (f.coud) | ||
| 852 | arr->coud = malloc(8 * sizeof(int)); | ||
| 853 | if (f.corl) | ||
| 854 | arr->corl = malloc(8 * sizeof(int)); | ||
| 855 | if (f.cofb) | ||
| 856 | arr->cofb = malloc(8 * sizeof(int)); | ||
| 857 | if (f.cpos) | ||
| 858 | arr->cpos = malloc(6 * sizeof(int)); | ||
| 859 | |||
| 860 | cube_to_arrays(cube, arr, f); | ||
| 861 | |||
| 862 | return arr; | ||
| 863 | } | ||
| 864 | |||
| 865 | static int | ||
| 866 | perm_sign(int *a, int n) | ||
| 867 | { | ||
| 868 | int i, j, ret = 0; | ||
| 869 | |||
| 870 | if (!is_perm(a,n)) | ||
| 871 | return -1; | ||
| 872 | |||
| 873 | for (i = 0; i < n; i++) | ||
| 874 | for (j = i+1; j < n; j++) | ||
| 875 | ret += (a[i] > a[j]) ? 1 : 0; | ||
| 876 | |||
| 877 | return ret % 2; | ||
| 878 | } | ||
| 879 | |||
| 880 | static int | ||
| 881 | perm_to_index(int *a, int n) | ||
| 882 | { | ||
| 883 | int i, j, c, ret = 0; | ||
| 884 | |||
| 885 | if (!is_perm(a, n)) | ||
| 886 | return -1; | ||
| 887 | |||
| 888 | for (i = 0; i < n; i++) { | ||
| 889 | c = 0; | ||
| 890 | for (j = i+1; j < n; j++) | ||
| 891 | c += (a[i] > a[j]) ? 1 : 0; | ||
| 892 | ret += factorial(n-i-1) * c; | ||
| 893 | } | ||
| 894 | |||
| 895 | return ret; | ||
| 896 | } | ||
| 897 | |||
| 898 | /* | ||
| 899 | static int | ||
| 900 | powint(int a, int b) | ||
| 901 | { | ||
| 902 | if (b < 0) | ||
| 903 | return 0; | ||
| 904 | if (b == 0) | ||
| 905 | return 1; | ||
| 906 | |||
| 907 | if (b % 2) | ||
| 908 | return a * powint(a, b-1); | ||
| 909 | else | ||
| 910 | return powint(a*a, b/2); | ||
| 911 | } | ||
| 912 | */ | ||
| 913 | |||
| 914 | static void | ||
| 915 | ptable_set_reached(PruneData *pd, uint64_t ind) | ||
| 916 | { | ||
| 917 | uint8_t oldval2 = pd->reached[ind/2]; | ||
| 918 | int other = ind % 2 ? oldval2 % 16 : oldval2 / 16; | ||
| 919 | |||
| 920 | pd->reached[ind/2] = ind % 2 ? 16 + other : 16*other + 1; | ||
| 921 | } | ||
| 922 | |||
| 923 | static void | ||
| 924 | ptable_update(PruneData *pd, uint64_t ind, int n) | ||
| 925 | { | ||
| 926 | uint8_t oldval2 = pd->ptable[ind/2]; | ||
| 927 | int other = ind % 2 ? oldval2 % 16 : oldval2 / 16; | ||
| 928 | |||
| 929 | pd->ptable[ind/2] = ind % 2 ? 16*n + other : 16*other + n; | ||
| 930 | pd->n++; | ||
| 931 | } | ||
| 932 | |||
| 933 | static void | ||
| 934 | push_cachenode(CacheData *cd, Cube c, Alg *alg) | ||
| 935 | { | ||
| 936 | CacheNode *node = malloc(sizeof(CacheNode)); | ||
| 937 | uint64_t ind0 = cd->index[0](c); | ||
| 938 | int i; | ||
| 939 | |||
| 940 | node->indexval = malloc((cd->nind - 1) * sizeof(uint64_t)); | ||
| 941 | for (i = 1; i < cd->nind; i++) | ||
| 942 | node->indexval[i-1] = cd->index[i](c); | ||
| 943 | |||
| 944 | node->sol = inverse_alg(alg); | ||
| 945 | realloc_alg(node->sol, cd->len); | ||
| 946 | node->next = cd->ctable[ind0]; | ||
| 947 | cd->ctable[ind0] = node; | ||
| 948 | } | ||
| 949 | |||
| 950 | static void | ||
| 951 | realloc_alg(Alg *alg, int n) | ||
| 952 | { | ||
| 953 | if (alg == NULL) { | ||
| 954 | fprintf(stderr, "Error: trying to reallocate NULL alg.\n"); | ||
| 955 | return; | ||
| 956 | } | ||
| 957 | |||
| 958 | if (n < alg->len) { | ||
| 959 | fprintf(stderr, "Error: alg too long for reallocation "); | ||
| 960 | fprintf(stderr, "(%d vs %d)\n", alg->len, n); | ||
| 961 | return; | ||
| 962 | } | ||
| 963 | |||
| 964 | if (n > 1000000) { | ||
| 965 | fprintf(stderr, "Warning: very long alg,"); | ||
| 966 | fprintf(stderr, "something might go wrong.\n"); | ||
| 967 | } | ||
| 968 | |||
| 969 | alg->move = realloc(alg->move, n); | ||
| 970 | alg->inv = realloc(alg->inv, n); | ||
| 971 | alg->allocated = n; | ||
| 972 | } | ||
| 973 | |||
| 974 | static bool | ||
| 975 | read_ctable_file(CacheData *cd) | ||
| 976 | { | ||
| 977 | return false; | ||
| 978 | } | ||
| 979 | |||
| 980 | static bool | ||
| 981 | read_mtables_file() | ||
| 982 | { | ||
| 983 | FILE *f; | ||
| 984 | char fname[strlen(tabledir)+20]; | ||
| 985 | int m, b = sizeof(uint16_t); | ||
| 986 | bool r = true; | ||
| 987 | |||
| 988 | strcpy(fname, tabledir); | ||
| 989 | strcat(fname, "/mtables"); | ||
| 990 | |||
| 991 | if ((f = fopen(fname, "rb")) == NULL) | ||
| 992 | return false; | ||
| 993 | |||
| 994 | for (m = 0; m < NMOVES; m++) { | ||
| 995 | r = r && fread(epose_mtable[m], b, me[0], f) == me[0]; | ||
| 996 | r = r && fread(eposs_mtable[m], b, me[1], f) == me[1]; | ||
| 997 | r = r && fread(eposm_mtable[m], b, me[2], f) == me[2]; | ||
| 998 | r = r && fread(eofb_mtable[m], b, me[3], f) == me[3]; | ||
| 999 | r = r && fread(eorl_mtable[m], b, me[4], f) == me[4]; | ||
| 1000 | r = r && fread(eoud_mtable[m], b, me[5], f) == me[5]; | ||
| 1001 | r = r && fread(cp_mtable[m], b, me[6], f) == me[6]; | ||
| 1002 | r = r && fread(coud_mtable[m], b, me[7], f) == me[7]; | ||
| 1003 | r = r && fread(corl_mtable[m], b, me[8], f) == me[8]; | ||
| 1004 | r = r && fread(cofb_mtable[m], b, me[9], f) == me[9]; | ||
| 1005 | r = r && fread(cpos_mtable[m], b, me[10], f) == me[10]; | ||
| 1006 | } | ||
| 1007 | |||
| 1008 | fclose(f); | ||
| 1009 | return r; | ||
| 1010 | } | ||
| 1011 | |||
| 1012 | static bool | ||
| 1013 | read_ptable_file(PruneData *pd) | ||
| 1014 | { | ||
| 1015 | FILE *f; | ||
| 1016 | char fname[strlen(tabledir)+100]; | ||
| 1017 | uint64_t r; | ||
| 1018 | |||
| 1019 | strcpy(fname, tabledir); | ||
| 1020 | strcat(fname, "/"); | ||
| 1021 | strcat(fname, pd->filename); | ||
| 1022 | |||
| 1023 | if ((f = fopen(fname, "rb")) == NULL) | ||
| 1024 | return false; | ||
| 1025 | |||
| 1026 | r = fread(pd->ptable, sizeof(uint8_t), PTABLESIZE(pd->size), f); | ||
| 1027 | fclose(f); | ||
| 1028 | |||
| 1029 | return r == PTABLESIZE(pd->size); | ||
| 1030 | } | ||
| 1031 | |||
| 1032 | static bool | ||
| 1033 | read_ttables_file() | ||
| 1034 | { | ||
| 1035 | FILE *f; | ||
| 1036 | char fname[strlen(tabledir)+20]; | ||
| 1037 | int b = sizeof(uint16_t); | ||
| 1038 | bool r = true; | ||
| 1039 | Move m; | ||
| 1040 | |||
| 1041 | strcpy(fname, tabledir); | ||
| 1042 | strcat(fname, "/"); | ||
| 1043 | strcat(fname, "ttables"); | ||
| 1044 | |||
| 1045 | if ((f = fopen(fname, "rb")) == NULL) | ||
| 1046 | return false; | ||
| 1047 | |||
| 1048 | for (m = 0; m < NTRANS; m++) { | ||
| 1049 | r = r && fread(epose_ttable[m], b, me[0], f) == me[0]; | ||
| 1050 | r = r && fread(eposs_ttable[m], b, me[1], f) == me[1]; | ||
| 1051 | r = r && fread(eposm_ttable[m], b, me[2], f) == me[2]; | ||
| 1052 | r = r && fread(eo_ttable[m], b, me[3], f) == me[3]; | ||
| 1053 | r = r && fread(cp_ttable[m], b, me[6], f) == me[6]; | ||
| 1054 | r = r && fread(co_ttable[m], b, me[7], f) == me[7]; | ||
| 1055 | r = r && fread(cpos_ttable[m], b, me[10], f) == me[10]; | ||
| 1056 | r = r && fread(moves_ttable[m], b, me[11], f) == me[11]; | ||
| 1057 | } | ||
| 1058 | |||
| 1059 | fclose(f); | ||
| 1060 | return r; | ||
| 1061 | } | ||
| 1062 | |||
| 1063 | static Cube | ||
| 1064 | rotate_via_compose(Trans r, Cube c, PieceFilter f) | ||
| 1065 | { | ||
| 1066 | Alg *inv; | ||
| 1067 | static int zero12[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; | ||
| 1068 | static int zero8[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; | ||
| 1069 | static CubeArray ma = { | ||
| 1070 | .ep = ep_mirror, | ||
| 1071 | .eofb = zero12, | ||
| 1072 | .eorl = zero12, | ||
| 1073 | .eoud = zero12, | ||
| 1074 | .cp = cp_mirror, | ||
| 1075 | .coud = zero8, | ||
| 1076 | .corl = zero8, | ||
| 1077 | .cofb = zero8, | ||
| 1078 | .cpos = cpos_mirror | ||
| 1079 | }; | ||
| 1080 | |||
| 1081 | Cube ret; | ||
| 1082 | |||
| 1083 | if (r != mirror) { | ||
| 1084 | ret = apply_alg_generic(trans_algs[r], c, f, true); | ||
| 1085 | inv = on_inverse(trans_algs[r]); | ||
| 1086 | ret = apply_alg_generic(inv, ret, f, true); | ||
| 1087 | free_alg(inv); | ||
| 1088 | } else { | ||
| 1089 | ret = move_via_arrays(&ma, (Cube){0}, f); | ||
| 1090 | ret = compose_filtered(c, ret, f); | ||
| 1091 | ret = move_via_arrays(&ma, ret, f); | ||
| 1092 | } | ||
| 1093 | |||
| 1094 | return ret; | ||
| 1095 | } | ||
| 1096 | |||
| 1097 | static void | ||
| 1098 | solve_cd(Cube c, Step s, SolveOptions *opts, DfsData *dd) | ||
| 1099 | { | ||
| 1100 | int j, k; | ||
| 1101 | bool flag; | ||
| 1102 | uint64_t ind0; | ||
| 1103 | CacheNode *i; | ||
| 1104 | |||
| 1105 | if (!s.cd->generated) | ||
| 1106 | generate_ctable(s.cd); | ||
| 1107 | |||
| 1108 | ind0 = s.cd->index[0](c); | ||
| 1109 | for (i = s.cd->ctable[ind0]; | ||
| 1110 | i != NULL && dd->sols->len < opts->max_solutions; | ||
| 1111 | i = i->next) { | ||
| 1112 | for (j = 1, flag = true; j < s.cd->nind; j++) { | ||
| 1113 | if (s.cd->index[j](c) != i->indexval[j-1]) { | ||
| 1114 | flag = false; | ||
| 1115 | break; | ||
| 1116 | } | ||
| 1117 | } | ||
| 1118 | if (flag) { | ||
| 1119 | for (k = 0; k < s.cd->len; k++) | ||
| 1120 | append_move(dd->current_alg, | ||
| 1121 | i->sol->move[k], dd->niss); | ||
| 1122 | append_alg(dd->sols, dd->current_alg); | ||
| 1123 | if (opts->feedback) { | ||
| 1124 | printf("[cached] "); | ||
| 1125 | print_alg(dd->current_alg, false); | ||
| 1126 | } | ||
| 1127 | } | ||
| 1128 | } | ||
| 1129 | } | ||
| 1130 | |||
| 1131 | static void | ||
| 1132 | solve_dfs(Cube c, Step s, SolveOptions *opts, DfsData *dd) | ||
| 1133 | { | ||
| 1134 | Move move, l1 = dd->last1, l2 = dd->last2; | ||
| 1135 | int i, lower_bound; | ||
| 1136 | bool nissbackup = dd->niss; | ||
| 1137 | |||
| 1138 | if (dd->sols->len >= opts->max_solutions) | ||
| 1139 | return; | ||
| 1140 | |||
| 1141 | lower_bound = s.check(c); | ||
| 1142 | if (opts->can_niss && !dd->niss) | ||
| 1143 | lower_bound = MIN(1, lower_bound); | ||
| 1144 | |||
| 1145 | if (dd->current_alg->len + lower_bound > dd->d) | ||
| 1146 | return; | ||
| 1147 | |||
| 1148 | if (lower_bound == 0) { | ||
| 1149 | if (dd->current_alg->len == dd->d) { | ||
| 1150 | append_alg(dd->sols, dd->current_alg); | ||
| 1151 | if (opts->feedback) | ||
| 1152 | print_alg(dd->current_alg, false); | ||
| 1153 | } | ||
| 1154 | return; | ||
| 1155 | } | ||
| 1156 | |||
| 1157 | if (s.cd != NULL && s.cd->len == dd->d - dd->current_alg->len) { | ||
| 1158 | solve_cd(c, s, opts, dd); | ||
| 1159 | } else { | ||
| 1160 | for (i = 0; | ||
| 1161 | dd->sorted_moves[i] != NULLMOVE && | ||
| 1162 | dd->sols->len < opts->max_solutions; | ||
| 1163 | i++) { | ||
| 1164 | move = dd->sorted_moves[i]; | ||
| 1165 | if (allowed_next_move(move, dd)) { | ||
| 1166 | dd->last2 = dd->last1; | ||
| 1167 | dd->last1 = move; | ||
| 1168 | append_move(dd->current_alg, move, dd->niss); | ||
| 1169 | solve_dfs(apply_move(move, c), s, opts, dd); | ||
| 1170 | dd->current_alg->len--; | ||
| 1171 | dd->last2 = l2; | ||
| 1172 | dd->last1 = l1; | ||
| 1173 | } | ||
| 1174 | } | ||
| 1175 | } | ||
| 1176 | |||
| 1177 | if (opts->can_niss && !dd->niss) { | ||
| 1178 | if (dd->current_alg->len == 0 || | ||
| 1179 | (s.check(apply_move(inverse_move(l1), (Cube){0})))) { | ||
| 1180 | dd->niss = true; | ||
| 1181 | dd->last1 = NULLMOVE; | ||
| 1182 | dd->last2 = NULLMOVE; | ||
| 1183 | solve_dfs(inverse_cube(c), s, opts, dd); | ||
| 1184 | } | ||
| 1185 | } | ||
| 1186 | |||
| 1187 | dd->last1 = l1; | ||
| 1188 | dd->last2 = l2; | ||
| 1189 | dd->niss = nissbackup; | ||
| 1190 | } | ||
| 1191 | |||
| 1192 | static int | ||
| 1193 | subset_to_index(int *a, int n, int k) | ||
| 1194 | { | ||
| 1195 | int i, ret = 0; | ||
| 1196 | |||
| 1197 | if (!is_subset(a, n, k)) | ||
| 1198 | return binomial(n, k); | ||
| 1199 | |||
| 1200 | for (i = 0; i < n; i++) { | ||
| 1201 | if (k == n-i) | ||
| 1202 | return ret; | ||
| 1203 | if (a[i]) { | ||
| 1204 | ret += binomial(n-i-1, k); | ||
| 1205 | k--; | ||
| 1206 | } | ||
| 1207 | } | ||
| 1208 | |||
| 1209 | return ret; | ||
| 1210 | } | ||
| 1211 | |||
| 1212 | static void | ||
| 1213 | sum_arrays_mod(int *src, int *dst, int n, int m) | ||
| 1214 | { | ||
| 1215 | int i; | ||
| 1216 | |||
| 1217 | for (i = 0; i < n; i++) | ||
| 1218 | dst[i] = (m <= 0) ? 0 : (src[i] + dst[i]) % m; | ||
| 1219 | } | ||
| 1220 | |||
| 1221 | static void | ||
| 1222 | swap(int *a, int *b) | ||
| 1223 | { | ||
| 1224 | int aux; | ||
| 1225 | |||
| 1226 | aux = *a; | ||
| 1227 | *a = *b; | ||
| 1228 | *b = aux; | ||
| 1229 | } | ||
| 1230 | |||
| 1231 | static bool | ||
| 1232 | write_ctable_file(CacheData *cd) | ||
| 1233 | { | ||
| 1234 | return false; | ||
| 1235 | } | ||
| 1236 | |||
| 1237 | static bool | ||
| 1238 | write_mtables_file() | ||
| 1239 | { | ||
| 1240 | FILE *f; | ||
| 1241 | char fname[strlen(tabledir)+20]; | ||
| 1242 | int m, b = sizeof(uint16_t); | ||
| 1243 | bool r = true; | ||
| 1244 | |||
| 1245 | strcpy(fname, tabledir); | ||
| 1246 | strcat(fname, "/mtables"); | ||
| 1247 | |||
| 1248 | if ((f = fopen(fname, "wb")) == NULL) | ||
| 1249 | return false; | ||
| 1250 | |||
| 1251 | for (m = 0; m < NMOVES; m++) { | ||
| 1252 | r = r && fwrite(epose_mtable[m], b, me[0], f) == me[0]; | ||
| 1253 | r = r && fwrite(eposs_mtable[m], b, me[1], f) == me[1]; | ||
| 1254 | r = r && fwrite(eposm_mtable[m], b, me[2], f) == me[2]; | ||
| 1255 | r = r && fwrite(eofb_mtable[m], b, me[3], f) == me[3]; | ||
| 1256 | r = r && fwrite(eorl_mtable[m], b, me[4], f) == me[4]; | ||
| 1257 | r = r && fwrite(eoud_mtable[m], b, me[5], f) == me[5]; | ||
| 1258 | r = r && fwrite(cp_mtable[m], b, me[6], f) == me[6]; | ||
| 1259 | r = r && fwrite(coud_mtable[m], b, me[7], f) == me[7]; | ||
| 1260 | r = r && fwrite(corl_mtable[m], b, me[8], f) == me[8]; | ||
| 1261 | r = r && fwrite(cofb_mtable[m], b, me[9], f) == me[9]; | ||
| 1262 | r = r && fwrite(cpos_mtable[m], b, me[10], f) == me[10]; | ||
| 1263 | } | ||
| 1264 | |||
| 1265 | fclose(f); | ||
| 1266 | return r; | ||
| 1267 | } | ||
| 1268 | |||
| 1269 | static bool | ||
| 1270 | write_ptable_file(PruneData *pd) | ||
| 1271 | { | ||
| 1272 | FILE *f; | ||
| 1273 | char fname[strlen(tabledir)+100]; | ||
| 1274 | uint64_t written; | ||
| 1275 | |||
| 1276 | strcpy(fname, tabledir); | ||
| 1277 | strcat(fname, "/"); | ||
| 1278 | strcat(fname, pd->filename); | ||
| 1279 | |||
| 1280 | if ((f = fopen(fname, "wb")) == NULL) | ||
| 1281 | return false; | ||
| 1282 | |||
| 1283 | written = fwrite(pd->ptable, sizeof(uint8_t), PTABLESIZE(pd->size), f); | ||
| 1284 | fclose(f); | ||
| 1285 | |||
| 1286 | return written == PTABLESIZE(pd->size); | ||
| 1287 | } | ||
| 1288 | |||
| 1289 | static bool | ||
| 1290 | write_ttables_file() | ||
| 1291 | { | ||
| 1292 | FILE *f; | ||
| 1293 | char fname[strlen(tabledir)+20]; | ||
| 1294 | bool r = true; | ||
| 1295 | int b = sizeof(uint16_t); | ||
| 1296 | Move m; | ||
| 1297 | |||
| 1298 | strcpy(fname, tabledir); | ||
| 1299 | strcat(fname, "/ttables"); | ||
| 1300 | |||
| 1301 | if ((f = fopen(fname, "wb")) == NULL) | ||
| 1302 | return false; | ||
| 1303 | |||
| 1304 | for (m = 0; m < NTRANS; m++) { | ||
| 1305 | r = r && fwrite(epose_ttable[m], b, me[0], f) == me[0]; | ||
| 1306 | r = r && fwrite(eposs_ttable[m], b, me[1], f) == me[1]; | ||
| 1307 | r = r && fwrite(eposm_ttable[m], b, me[2], f) == me[2]; | ||
| 1308 | r = r && fwrite(eo_ttable[m], b, me[3], f) == me[3]; | ||
| 1309 | r = r && fwrite(cp_ttable[m], b, me[6], f) == me[6]; | ||
| 1310 | r = r && fwrite(co_ttable[m], b, me[7], f) == me[7]; | ||
| 1311 | r = r && fwrite(cpos_ttable[m], b, me[10], f) == me[10]; | ||
| 1312 | r = r && fwrite(moves_ttable[m], b, me[11], f) == me[11]; | ||
| 1313 | } | ||
| 1314 | |||
| 1315 | fclose(f); | ||
| 1316 | return r; | ||
| 1317 | } | ||
| 1318 | |||
| 1319 | /* Init functions implementation *********************************************/ | ||
| 1320 | |||
| 1321 | static void | ||
| 1322 | init_auxtables() | ||
| 1323 | { | ||
| 1324 | Cube c1, c2; | ||
| 1325 | uint64_t ui, uj; | ||
| 1326 | int i, j, k; | ||
| 1327 | bool cij, p1, p2; | ||
| 1328 | |||
| 1329 | for (ui = 0; ui < BINOM12ON4; ui++) | ||
| 1330 | for (uj = 0; uj < BINOM12ON4; uj++) | ||
| 1331 | epos_dependent_aux[ui][uj] = epos_dependent(ui, uj); | ||
| 1332 | |||
| 1333 | for (i = 0; i < NMOVES; i++) { | ||
| 1334 | for (j = 0; j < NMOVES; j++) { | ||
| 1335 | c1 = apply_move(i, apply_move(j, (Cube){0})); | ||
| 1336 | c2 = apply_move(j, apply_move(i, (Cube){0})); | ||
| 1337 | commute[i][j] = equal(c1, c2) && i && j; | ||
| 1338 | } | ||
| 1339 | } | ||
| 1340 | |||
| 1341 | for (i = 0; i < NMOVES; i++) { | ||
| 1342 | for (j = 0; j < NMOVES; j++) { | ||
| 1343 | for (k = 0; k < NMOVES; k++) { | ||
| 1344 | p1 = j && base_move(j) == base_move(k); | ||
| 1345 | p2 = i && base_move(i) == base_move(k); | ||
| 1346 | cij = commute[i][j]; | ||
| 1347 | possible_next[i][j][k] = !(p1 || (cij && p2)); | ||
| 1348 | } | ||
| 1349 | } | ||
| 1350 | } | ||
| 1351 | |||
| 1352 | for (i = 0; i < NMOVES; i++) | ||
| 1353 | inverse_move_aux[i] = i ? i + 2 - 2*((i-1)%3) : NULLMOVE; | ||
| 1354 | |||
| 1355 | /* Is there a more elegant way? */ | ||
| 1356 | inverse_trans_aux[uf] = uf; | ||
| 1357 | inverse_trans_aux[ur] = ul; | ||
| 1358 | inverse_trans_aux[ul] = ur; | ||
| 1359 | inverse_trans_aux[ub] = ub; | ||
| 1360 | |||
| 1361 | inverse_trans_aux[df] = df; | ||
| 1362 | inverse_trans_aux[dr] = dr; | ||
| 1363 | inverse_trans_aux[dl] = dl; | ||
| 1364 | inverse_trans_aux[db] = db; | ||
| 1365 | |||
| 1366 | inverse_trans_aux[rf] = lf; | ||
| 1367 | inverse_trans_aux[rd] = bl; | ||
| 1368 | inverse_trans_aux[rb] = rb; | ||
| 1369 | inverse_trans_aux[ru] = fr; | ||
| 1370 | |||
| 1371 | inverse_trans_aux[lf] = rf; | ||
| 1372 | inverse_trans_aux[ld] = br; | ||
| 1373 | inverse_trans_aux[lb] = lb; | ||
| 1374 | inverse_trans_aux[lu] = fl; | ||
| 1375 | |||
| 1376 | inverse_trans_aux[fu] = fu; | ||
| 1377 | inverse_trans_aux[fr] = ru; | ||
| 1378 | inverse_trans_aux[fd] = bu; | ||
| 1379 | inverse_trans_aux[fl] = lu; | ||
| 1380 | |||
| 1381 | inverse_trans_aux[bu] = fd; | ||
| 1382 | inverse_trans_aux[br] = ld; | ||
| 1383 | inverse_trans_aux[bd] = bd; | ||
| 1384 | inverse_trans_aux[bl] = rd; | ||
| 1385 | |||
| 1386 | inverse_trans_aux[mirror] = mirror; | ||
| 1387 | } | ||
| 1388 | |||
| 1389 | static void | ||
| 1390 | init_environment() | ||
| 1391 | { | ||
| 1392 | char *nissydata = getenv("NISSYDATA"); | ||
| 1393 | char *localdata = getenv("XDG_DATA_HOME"); | ||
| 1394 | char *home = getenv("HOME"); | ||
| 1395 | bool read, write; | ||
| 1396 | |||
| 1397 | if (nissydata != NULL) { | ||
| 1398 | tabledir = malloc(strlen(nissydata) * sizeof(char) + 20); | ||
| 1399 | strcpy(tabledir, nissydata); | ||
| 1400 | } else if (localdata != NULL) { | ||
| 1401 | tabledir = malloc(strlen(localdata) * sizeof(char) + 20); | ||
| 1402 | strcpy(tabledir, localdata); | ||
| 1403 | strcat(tabledir, "/nissy"); | ||
| 1404 | } else if (home != NULL) { | ||
| 1405 | tabledir = malloc(strlen(home) * sizeof(char) + 20); | ||
| 1406 | strcpy(tabledir, home); | ||
| 1407 | strcat(tabledir, "/.nissy"); | ||
| 1408 | } | ||
| 1409 | |||
| 1410 | mkdir(tabledir, 0777); | ||
| 1411 | strcat(tabledir, "/tables"); | ||
| 1412 | mkdir(tabledir, 0777); | ||
| 1413 | |||
| 1414 | read = !access(tabledir, R_OK); | ||
| 1415 | write = !access(tabledir, W_OK); | ||
| 1416 | |||
| 1417 | if (!read) { | ||
| 1418 | fprintf(stderr, "Table files cannot be read.\n"); | ||
| 1419 | } else if (!write) { | ||
| 1420 | fprintf(stderr, "Data directory not writable: "); | ||
| 1421 | fprintf(stderr, "tables can be loaded, but not saved.\n"); | ||
| 1422 | } | ||
| 1423 | } | ||
| 1424 | |||
| 1425 | static void | ||
| 1426 | init_moves() { | ||
| 1427 | Cube c; | ||
| 1428 | CubeArray arrs; | ||
| 1429 | int i; | ||
| 1430 | uint16_t ui; | ||
| 1431 | Move m; | ||
| 1432 | |||
| 1433 | /* Generate all move cycles and flips; I do this regardless */ | ||
| 1434 | for (i = 0; i < NMOVES; i++) { | ||
| 1435 | if (i == U || i == x || i == y) | ||
| 1436 | continue; | ||
| 1437 | |||
| 1438 | c = apply_alg_generic(equiv_alg[i], (Cube){0}, pf_all, false); | ||
| 1439 | |||
| 1440 | arrs = (CubeArray) { | ||
| 1441 | edge_cycle[i], | ||
| 1442 | eofb_flipped[i], | ||
| 1443 | eorl_flipped[i], | ||
| 1444 | eoud_flipped[i], | ||
| 1445 | corner_cycle[i], | ||
| 1446 | coud_flipped[i], | ||
| 1447 | corl_flipped[i], | ||
| 1448 | cofb_flipped[i], | ||
| 1449 | center_cycle[i] | ||
| 1450 | }; | ||
| 1451 | cube_to_arrays(c, &arrs, pf_all); | ||
| 1452 | } | ||
| 1453 | |||
| 1454 | if (read_mtables_file()) | ||
| 1455 | return; | ||
| 1456 | |||
| 1457 | fprintf(stderr, "Cannot load %s, generating it\n", "mtables"); | ||
| 1458 | |||
| 1459 | /* Initialize transition tables */ | ||
| 1460 | for (m = 0; m < NMOVES; m++) { | ||
| 1461 | for (ui = 0; ui < FACTORIAL12/FACTORIAL8; ui++) { | ||
| 1462 | c = (Cube){ .epose = ui }; | ||
| 1463 | c = apply_move_cubearray(m, c, pf_e); | ||
| 1464 | epose_mtable[m][ui] = c.epose; | ||
| 1465 | |||
| 1466 | c = (Cube){ .eposs = ui }; | ||
| 1467 | c = apply_move_cubearray(m, c, pf_s); | ||
| 1468 | eposs_mtable[m][ui] = c.eposs; | ||
| 1469 | |||
| 1470 | c = (Cube){ .eposm = ui }; | ||
| 1471 | c = apply_move_cubearray(m, c, pf_m); | ||
| 1472 | eposm_mtable[m][ui] = c.eposm; | ||
| 1473 | } | ||
| 1474 | for (ui = 0; ui < POW2TO11; ui++ ) { | ||
| 1475 | c = (Cube){ .eofb = ui }; | ||
| 1476 | c = apply_move_cubearray(m, c, pf_eo); | ||
| 1477 | eofb_mtable[m][ui] = c.eofb; | ||
| 1478 | |||
| 1479 | c = (Cube){ .eorl = ui }; | ||
| 1480 | c = apply_move_cubearray(m, c, pf_eo); | ||
| 1481 | eorl_mtable[m][ui] = c.eorl; | ||
| 1482 | |||
| 1483 | c = (Cube){ .eoud = ui }; | ||
| 1484 | c = apply_move_cubearray(m, c, pf_eo); | ||
| 1485 | eoud_mtable[m][ui] = c.eoud; | ||
| 1486 | } | ||
| 1487 | for (ui = 0; ui < POW3TO7; ui++) { | ||
| 1488 | c = (Cube){ .coud = ui }; | ||
| 1489 | c = apply_move_cubearray(m, c, pf_co); | ||
| 1490 | coud_mtable[m][ui] = c.coud; | ||
| 1491 | |||
| 1492 | c = (Cube){ .corl = ui }; | ||
| 1493 | c = apply_move_cubearray(m, c, pf_co); | ||
| 1494 | corl_mtable[m][ui] = c.corl; | ||
| 1495 | |||
| 1496 | c = (Cube){ .cofb = ui }; | ||
| 1497 | c = apply_move_cubearray(m, c, pf_co); | ||
| 1498 | cofb_mtable[m][ui] = c.cofb; | ||
| 1499 | } | ||
| 1500 | for (ui = 0; ui < FACTORIAL8; ui++) { | ||
| 1501 | c = (Cube){ .cp = ui }; | ||
| 1502 | c = apply_move_cubearray(m, c, pf_cp); | ||
| 1503 | cp_mtable[m][ui] = c.cp; | ||
| 1504 | } | ||
| 1505 | for (ui = 0; ui < FACTORIAL6; ui++) { | ||
| 1506 | c = (Cube){ .cpos = ui }; | ||
| 1507 | c = apply_move_cubearray(m, c, pf_cpos); | ||
| 1508 | cpos_mtable[m][ui] = c.cpos; | ||
| 1509 | } | ||
| 1510 | } | ||
| 1511 | |||
| 1512 | if (!write_mtables_file()) | ||
| 1513 | fprintf(stderr, "Error writing mtables\n"); | ||
| 1514 | } | ||
| 1515 | |||
| 1516 | static void | ||
| 1517 | init_moves_aux() | ||
| 1518 | { | ||
| 1519 | /* Some standard PieceFilters */ | ||
| 1520 | pf_all.epose = true; | ||
| 1521 | pf_all.eposs = true; | ||
| 1522 | pf_all.eposm = true; | ||
| 1523 | pf_all.eofb = true; | ||
| 1524 | pf_all.eorl = true; | ||
| 1525 | pf_all.eoud = true; | ||
| 1526 | pf_all.cp = true; | ||
| 1527 | pf_all.cofb = true; | ||
| 1528 | pf_all.corl = true; | ||
| 1529 | pf_all.coud = true; | ||
| 1530 | pf_all.cpos = true; | ||
| 1531 | |||
| 1532 | pf_4val.epose = true; | ||
| 1533 | pf_4val.eposs = true; | ||
| 1534 | pf_4val.eposm = true; | ||
| 1535 | pf_4val.eofb = true; | ||
| 1536 | pf_4val.coud = true; | ||
| 1537 | pf_4val.cp = true; | ||
| 1538 | |||
| 1539 | pf_epcp.epose = true; | ||
| 1540 | pf_epcp.eposs = true; | ||
| 1541 | pf_epcp.eposm = true; | ||
| 1542 | pf_epcp.cp = true; | ||
| 1543 | |||
| 1544 | pf_cpos.cpos = true; | ||
| 1545 | |||
| 1546 | pf_cp.cp = true; | ||
| 1547 | |||
| 1548 | pf_ep.epose = true; | ||
| 1549 | pf_ep.eposs = true; | ||
| 1550 | pf_ep.eposm = true; | ||
| 1551 | |||
| 1552 | pf_e.epose = true; | ||
| 1553 | pf_s.eposs = true; | ||
| 1554 | pf_m.eposm = true; | ||
| 1555 | |||
| 1556 | pf_eo.eofb = true; | ||
| 1557 | pf_eo.eorl = true; | ||
| 1558 | pf_eo.eoud = true; | ||
| 1559 | |||
| 1560 | pf_co.cofb = true; | ||
| 1561 | pf_co.corl = true; | ||
| 1562 | pf_co.coud = true; | ||
| 1563 | |||
| 1564 | /* Used to convert to and from CubeArray */ | ||
| 1565 | epe_solved[0] = FR; | ||
| 1566 | epe_solved[1] = FL; | ||
| 1567 | epe_solved[2] = BL; | ||
| 1568 | epe_solved[3] = BR; | ||
| 1569 | |||
| 1570 | eps_solved[0] = UL; | ||
| 1571 | eps_solved[1] = UR; | ||
| 1572 | eps_solved[2] = DL; | ||
| 1573 | eps_solved[3] = DR; | ||
| 1574 | |||
| 1575 | epm_solved[0] = UF; | ||
| 1576 | epm_solved[1] = UB; | ||
| 1577 | epm_solved[2] = DF; | ||
| 1578 | epm_solved[3] = DB; | ||
| 1579 | |||
| 1580 | /* Table sizes, used for reading and writing files */ | ||
| 1581 | me[0] = FACTORIAL12/FACTORIAL8; | ||
| 1582 | me[1] = FACTORIAL12/FACTORIAL8; | ||
| 1583 | me[2] = FACTORIAL12/FACTORIAL8; | ||
| 1584 | me[3] = POW2TO11; | ||
| 1585 | me[4] = POW2TO11; | ||
| 1586 | me[5] = POW2TO11; | ||
| 1587 | me[6] = FACTORIAL8; | ||
| 1588 | me[7] = POW3TO7; | ||
| 1589 | me[8] = POW3TO7; | ||
| 1590 | me[9] = POW3TO7; | ||
| 1591 | me[10] = FACTORIAL6; | ||
| 1592 | me[11] = NMOVES; | ||
| 1593 | |||
| 1594 | /* Cycles *********************/ | ||
| 1595 | edge_cycle[U][UF] = UR; | ||
| 1596 | edge_cycle[U][UL] = UF; | ||
| 1597 | edge_cycle[U][UB] = UL; | ||
| 1598 | edge_cycle[U][UR] = UB; | ||
| 1599 | edge_cycle[U][DF] = DF; | ||
| 1600 | edge_cycle[U][DL] = DL; | ||
| 1601 | edge_cycle[U][DB] = DB; | ||
| 1602 | edge_cycle[U][DR] = DR; | ||
| 1603 | edge_cycle[U][FR] = FR; | ||
| 1604 | edge_cycle[U][FL] = FL; | ||
| 1605 | edge_cycle[U][BL] = BL; | ||
| 1606 | edge_cycle[U][BR] = BR; | ||
| 1607 | |||
| 1608 | edge_cycle[x][UF] = DF; | ||
| 1609 | edge_cycle[x][UL] = FL; | ||
| 1610 | edge_cycle[x][UB] = UF; | ||
| 1611 | edge_cycle[x][UR] = FR; | ||
| 1612 | edge_cycle[x][DF] = DB; | ||
| 1613 | edge_cycle[x][DL] = BL; | ||
| 1614 | edge_cycle[x][DB] = UB; | ||
| 1615 | edge_cycle[x][DR] = BR; | ||
| 1616 | edge_cycle[x][FR] = DR; | ||
| 1617 | edge_cycle[x][FL] = DL; | ||
| 1618 | edge_cycle[x][BL] = UL; | ||
| 1619 | edge_cycle[x][BR] = UR; | ||
| 1620 | |||
| 1621 | edge_cycle[y][UF] = UR; | ||
| 1622 | edge_cycle[y][UL] = UF; | ||
| 1623 | edge_cycle[y][UB] = UL; | ||
| 1624 | edge_cycle[y][UR] = UB; | ||
| 1625 | edge_cycle[y][DF] = DR; | ||
| 1626 | edge_cycle[y][DL] = DF; | ||
| 1627 | edge_cycle[y][DB] = DL; | ||
| 1628 | edge_cycle[y][DR] = DB; | ||
| 1629 | edge_cycle[y][FR] = BR; | ||
| 1630 | edge_cycle[y][FL] = FR; | ||
| 1631 | edge_cycle[y][BL] = FL; | ||
| 1632 | edge_cycle[y][BR] = BL; | ||
| 1633 | |||
| 1634 | corner_cycle[U][UFR] = UBR; | ||
| 1635 | corner_cycle[U][UFL] = UFR; | ||
| 1636 | corner_cycle[U][UBL] = UFL; | ||
| 1637 | corner_cycle[U][UBR] = UBL; | ||
| 1638 | corner_cycle[U][DFR] = DFR; | ||
| 1639 | corner_cycle[U][DFL] = DFL; | ||
| 1640 | corner_cycle[U][DBL] = DBL; | ||
| 1641 | corner_cycle[U][DBR] = DBR; | ||
| 1642 | |||
| 1643 | corner_cycle[x][UFR] = DFR; | ||
| 1644 | corner_cycle[x][UFL] = DFL; | ||
| 1645 | corner_cycle[x][UBL] = UFL; | ||
| 1646 | corner_cycle[x][UBR] = UFR; | ||
| 1647 | corner_cycle[x][DFR] = DBR; | ||
| 1648 | corner_cycle[x][DFL] = DBL; | ||
| 1649 | corner_cycle[x][DBL] = UBL; | ||
| 1650 | corner_cycle[x][DBR] = UBR; | ||
| 1651 | |||
| 1652 | corner_cycle[y][UFR] = UBR; | ||
| 1653 | corner_cycle[y][UFL] = UFR; | ||
| 1654 | corner_cycle[y][UBL] = UFL; | ||
| 1655 | corner_cycle[y][UBR] = UBL; | ||
| 1656 | corner_cycle[y][DFR] = DBR; | ||
| 1657 | corner_cycle[y][DFL] = DFR; | ||
| 1658 | corner_cycle[y][DBL] = DFL; | ||
| 1659 | corner_cycle[y][DBR] = DBL; | ||
| 1660 | |||
| 1661 | center_cycle[U][U_center] = U_center; | ||
| 1662 | center_cycle[U][D_center] = D_center; | ||
| 1663 | center_cycle[U][R_center] = R_center; | ||
| 1664 | center_cycle[U][L_center] = L_center; | ||
| 1665 | center_cycle[U][F_center] = F_center; | ||
| 1666 | center_cycle[U][B_center] = B_center; | ||
| 1667 | |||
| 1668 | center_cycle[x][U_center] = F_center; | ||
| 1669 | center_cycle[x][D_center] = B_center; | ||
| 1670 | center_cycle[x][R_center] = R_center; | ||
| 1671 | center_cycle[x][L_center] = L_center; | ||
| 1672 | center_cycle[x][F_center] = D_center; | ||
| 1673 | center_cycle[x][B_center] = U_center; | ||
| 1674 | |||
| 1675 | center_cycle[y][U_center] = U_center; | ||
| 1676 | center_cycle[y][D_center] = D_center; | ||
| 1677 | center_cycle[y][R_center] = B_center; | ||
| 1678 | center_cycle[y][L_center] = F_center; | ||
| 1679 | center_cycle[y][F_center] = R_center; | ||
| 1680 | center_cycle[y][B_center] = L_center; | ||
| 1681 | |||
| 1682 | /* Flipped pieces *************/ | ||
| 1683 | eofb_flipped[x][UF] = 1; | ||
| 1684 | eofb_flipped[x][UB] = 1; | ||
| 1685 | eofb_flipped[x][DF] = 1; | ||
| 1686 | eofb_flipped[x][DB] = 1; | ||
| 1687 | |||
| 1688 | eofb_flipped[y][FR] = 1; | ||
| 1689 | eofb_flipped[y][FL] = 1; | ||
| 1690 | eofb_flipped[y][BL] = 1; | ||
| 1691 | eofb_flipped[y][BR] = 1; | ||
| 1692 | |||
| 1693 | eorl_flipped[x][UF] = 1; | ||
| 1694 | eorl_flipped[x][UL] = 1; | ||
| 1695 | eorl_flipped[x][UB] = 1; | ||
| 1696 | eorl_flipped[x][UR] = 1; | ||
| 1697 | eorl_flipped[x][DF] = 1; | ||
| 1698 | eorl_flipped[x][DL] = 1; | ||
| 1699 | eorl_flipped[x][DB] = 1; | ||
| 1700 | eorl_flipped[x][DR] = 1; | ||
| 1701 | eorl_flipped[x][FR] = 1; | ||
| 1702 | eorl_flipped[x][FL] = 1; | ||
| 1703 | eorl_flipped[x][BL] = 1; | ||
| 1704 | eorl_flipped[x][BR] = 1; | ||
| 1705 | |||
| 1706 | eorl_flipped[y][FR] = 1; | ||
| 1707 | eorl_flipped[y][FL] = 1; | ||
| 1708 | eorl_flipped[y][BL] = 1; | ||
| 1709 | eorl_flipped[y][BR] = 1; | ||
| 1710 | |||
| 1711 | eoud_flipped[U][UF] = 1; | ||
| 1712 | eoud_flipped[U][UL] = 1; | ||
| 1713 | eoud_flipped[U][UB] = 1; | ||
| 1714 | eoud_flipped[U][UR] = 1; | ||
| 1715 | |||
| 1716 | eoud_flipped[x][UF] = 1; | ||
| 1717 | eoud_flipped[x][UB] = 1; | ||
| 1718 | eoud_flipped[x][DF] = 1; | ||
| 1719 | eoud_flipped[x][DB] = 1; | ||
| 1720 | |||
| 1721 | eoud_flipped[y][UF] = 1; | ||
| 1722 | eoud_flipped[y][UL] = 1; | ||
| 1723 | eoud_flipped[y][UB] = 1; | ||
| 1724 | eoud_flipped[y][UR] = 1; | ||
| 1725 | eoud_flipped[y][DF] = 1; | ||
| 1726 | eoud_flipped[y][DL] = 1; | ||
| 1727 | eoud_flipped[y][DB] = 1; | ||
| 1728 | eoud_flipped[y][DR] = 1; | ||
| 1729 | eoud_flipped[y][FR] = 1; | ||
| 1730 | eoud_flipped[y][FL] = 1; | ||
| 1731 | eoud_flipped[y][BL] = 1; | ||
| 1732 | eoud_flipped[y][BR] = 1; | ||
| 1733 | |||
| 1734 | coud_flipped[x][UFR] = 2; | ||
| 1735 | coud_flipped[x][UFL] = 1; | ||
| 1736 | coud_flipped[x][UBR] = 1; | ||
| 1737 | coud_flipped[x][UBL] = 2; | ||
| 1738 | coud_flipped[x][DFR] = 1; | ||
| 1739 | coud_flipped[x][DFL] = 2; | ||
| 1740 | coud_flipped[x][DBR] = 2; | ||
| 1741 | coud_flipped[x][DBL] = 1; | ||
| 1742 | |||
| 1743 | corl_flipped[U][UFR] = 1; | ||
| 1744 | corl_flipped[U][UFL] = 2; | ||
| 1745 | corl_flipped[U][UBL] = 1; | ||
| 1746 | corl_flipped[U][UBR] = 2; | ||
| 1747 | |||
| 1748 | corl_flipped[y][UFR] = 1; | ||
| 1749 | corl_flipped[y][UFL] = 2; | ||
| 1750 | corl_flipped[y][UBL] = 1; | ||
| 1751 | corl_flipped[y][UBR] = 2; | ||
| 1752 | corl_flipped[y][DFR] = 2; | ||
| 1753 | corl_flipped[y][DFL] = 1; | ||
| 1754 | corl_flipped[y][DBL] = 2; | ||
| 1755 | corl_flipped[y][DBR] = 1; | ||
| 1756 | |||
| 1757 | cofb_flipped[U][UFR] = 2; | ||
| 1758 | cofb_flipped[U][UFL] = 1; | ||
| 1759 | cofb_flipped[U][UBL] = 2; | ||
| 1760 | cofb_flipped[U][UBR] = 1; | ||
| 1761 | |||
| 1762 | cofb_flipped[x][UFR] = 1; | ||
| 1763 | cofb_flipped[x][UFL] = 2; | ||
| 1764 | cofb_flipped[x][UBL] = 1; | ||
| 1765 | cofb_flipped[x][UBR] = 2; | ||
| 1766 | cofb_flipped[x][DFR] = 2; | ||
| 1767 | cofb_flipped[x][DFL] = 1; | ||
| 1768 | cofb_flipped[x][DBL] = 2; | ||
| 1769 | cofb_flipped[x][DBR] = 1; | ||
| 1770 | |||
| 1771 | cofb_flipped[y][UFR] = 2; | ||
| 1772 | cofb_flipped[y][UFL] = 1; | ||
| 1773 | cofb_flipped[y][UBL] = 2; | ||
| 1774 | cofb_flipped[y][UBR] = 1; | ||
| 1775 | cofb_flipped[y][DFR] = 1; | ||
| 1776 | cofb_flipped[y][DFL] = 2; | ||
| 1777 | cofb_flipped[y][DBL] = 1; | ||
| 1778 | cofb_flipped[y][DBR] = 2; | ||
| 1779 | |||
| 1780 | /* Equivalent moves ***********/ | ||
| 1781 | equiv_alg[NULLMOVE] = new_alg(""); | ||
| 1782 | |||
| 1783 | equiv_alg[U] = new_alg(" U "); | ||
| 1784 | equiv_alg[U2] = new_alg(" UU "); | ||
| 1785 | equiv_alg[U3] = new_alg(" UUU "); | ||
| 1786 | equiv_alg[D] = new_alg(" xx U xx "); | ||
| 1787 | equiv_alg[D2] = new_alg(" xx UU xx "); | ||
| 1788 | equiv_alg[D3] = new_alg(" xx UUU xx "); | ||
| 1789 | equiv_alg[R] = new_alg(" yx U xxxyyy "); | ||
| 1790 | equiv_alg[R2] = new_alg(" yx UU xxxyyy "); | ||
| 1791 | equiv_alg[R3] = new_alg(" yx UUU xxxyyy "); | ||
| 1792 | equiv_alg[L] = new_alg(" yyyx U xxxy "); | ||
| 1793 | equiv_alg[L2] = new_alg(" yyyx UU xxxy "); | ||
| 1794 | equiv_alg[L3] = new_alg(" yyyx UUU xxxy "); | ||
| 1795 | equiv_alg[F] = new_alg(" x U xxx "); | ||
| 1796 | equiv_alg[F2] = new_alg(" x UU xxx "); | ||
| 1797 | equiv_alg[F3] = new_alg(" x UUU xxx "); | ||
| 1798 | equiv_alg[B] = new_alg(" xxx U x "); | ||
| 1799 | equiv_alg[B2] = new_alg(" xxx UU x "); | ||
| 1800 | equiv_alg[B3] = new_alg(" xxx UUU x "); | ||
| 1801 | |||
| 1802 | equiv_alg[Uw] = new_alg(" xx U xx y "); | ||
| 1803 | equiv_alg[Uw2] = new_alg(" xx UU xx yy "); | ||
| 1804 | equiv_alg[Uw3] = new_alg(" xx UUU xx yyy "); | ||
| 1805 | equiv_alg[Dw] = new_alg(" U yyy "); | ||
| 1806 | equiv_alg[Dw2] = new_alg(" UU yy "); | ||
| 1807 | equiv_alg[Dw3] = new_alg(" UUU y "); | ||
| 1808 | equiv_alg[Rw] = new_alg(" yyyx U xxxy x "); | ||
| 1809 | equiv_alg[Rw2] = new_alg(" yyyx UU xxxy xx "); | ||
| 1810 | equiv_alg[Rw3] = new_alg(" yyyx UUU xxxy xxx "); | ||
| 1811 | equiv_alg[Lw] = new_alg(" yx U xxxyyy xxx "); | ||
| 1812 | equiv_alg[Lw2] = new_alg(" yx UU xxxyyy xx "); | ||
| 1813 | equiv_alg[Lw3] = new_alg(" yx UUU xxxyyy x "); | ||
| 1814 | equiv_alg[Fw] = new_alg(" xxx U x yxxxyyy "); | ||
| 1815 | equiv_alg[Fw2] = new_alg(" xxx UU x yxxyyy "); | ||
| 1816 | equiv_alg[Fw3] = new_alg(" xxx UUU x yxyyy "); | ||
| 1817 | equiv_alg[Bw] = new_alg(" x U xxx yxyyy "); | ||
| 1818 | equiv_alg[Bw2] = new_alg(" x UU xxx yxxyyy "); | ||
| 1819 | equiv_alg[Bw3] = new_alg(" x UUU xxx yxxxyyy "); | ||
| 1820 | |||
| 1821 | equiv_alg[M] = new_alg(" yx U xx UUU yxyyy "); | ||
| 1822 | equiv_alg[M2] = new_alg(" yx UU xx UU xxxy "); | ||
| 1823 | equiv_alg[M3] = new_alg(" yx UUU xx U yxxxy "); | ||
| 1824 | equiv_alg[S] = new_alg(" x UUU xx U yyyx "); | ||
| 1825 | equiv_alg[S2] = new_alg(" x UU xx UU yyx "); | ||
| 1826 | equiv_alg[S3] = new_alg(" x U xx UUU yx "); | ||
| 1827 | equiv_alg[E] = new_alg(" U xx UUU xxyyy "); | ||
| 1828 | equiv_alg[E2] = new_alg(" UU xx UU xxyy "); | ||
| 1829 | equiv_alg[E3] = new_alg(" UUU xx U xxy "); | ||
| 1830 | |||
| 1831 | equiv_alg[x] = new_alg(" x "); | ||
| 1832 | equiv_alg[x2] = new_alg(" xx "); | ||
| 1833 | equiv_alg[x3] = new_alg(" xxx "); | ||
| 1834 | equiv_alg[y] = new_alg(" y "); | ||
| 1835 | equiv_alg[y2] = new_alg(" yy "); | ||
| 1836 | equiv_alg[y3] = new_alg(" yyy "); | ||
| 1837 | equiv_alg[z] = new_alg(" yyy x y "); | ||
| 1838 | equiv_alg[z2] = new_alg(" yy xx "); | ||
| 1839 | equiv_alg[z3] = new_alg(" y x yyy "); | ||
| 1840 | } | ||
| 1841 | |||
| 1842 | static void | ||
| 1843 | init_strings() | ||
| 1844 | { | ||
| 1845 | strcpy(move_string [NULLMOVE], "-" ); | ||
| 1846 | strcpy(move_string [U], "U" ); | ||
| 1847 | strcpy(move_string [U2], "U2" ); | ||
| 1848 | strcpy(move_string [U3], "U\'" ); | ||
| 1849 | strcpy(move_string [D], "D" ); | ||
| 1850 | strcpy(move_string [D2], "D2" ); | ||
| 1851 | strcpy(move_string [D3], "D\'" ); | ||
| 1852 | strcpy(move_string [R], "R" ); | ||
| 1853 | strcpy(move_string [R2], "R2" ); | ||
| 1854 | strcpy(move_string [R3], "R\'" ); | ||
| 1855 | strcpy(move_string [L], "L" ); | ||
| 1856 | strcpy(move_string [L2], "L2" ); | ||
| 1857 | strcpy(move_string [L3], "L\'" ); | ||
| 1858 | strcpy(move_string [F], "F" ); | ||
| 1859 | strcpy(move_string [F2], "F2" ); | ||
| 1860 | strcpy(move_string [F3], "F\'" ); | ||
| 1861 | strcpy(move_string [B], "B" ); | ||
| 1862 | strcpy(move_string [B2], "B2" ); | ||
| 1863 | strcpy(move_string [B3], "B\'" ); | ||
| 1864 | strcpy(move_string [Uw], "Uw" ); | ||
| 1865 | strcpy(move_string [Uw2], "Uw2" ); | ||
| 1866 | strcpy(move_string [Uw3], "Uw\'" ); | ||
| 1867 | strcpy(move_string [Dw], "Dw" ); | ||
| 1868 | strcpy(move_string [Dw2], "Dw2" ); | ||
| 1869 | strcpy(move_string [Dw3], "Dw\'" ); | ||
| 1870 | strcpy(move_string [Rw], "Rw" ); | ||
| 1871 | strcpy(move_string [Rw2], "Rw2" ); | ||
| 1872 | strcpy(move_string [Rw3], "Rw\'" ); | ||
| 1873 | strcpy(move_string [Lw], "Lw" ); | ||
| 1874 | strcpy(move_string [Lw2], "Lw2" ); | ||
| 1875 | strcpy(move_string [Lw3], "Lw\'" ); | ||
| 1876 | strcpy(move_string [Fw], "Fw" ); | ||
| 1877 | strcpy(move_string [Fw2], "Fw2" ); | ||
| 1878 | strcpy(move_string [Fw3], "Fw\'" ); | ||
| 1879 | strcpy(move_string [Bw], "Bw" ); | ||
| 1880 | strcpy(move_string [Bw2], "Bw2" ); | ||
| 1881 | strcpy(move_string [Bw3], "Bw\'" ); | ||
| 1882 | strcpy(move_string [M], "M" ); | ||
| 1883 | strcpy(move_string [M2], "M2" ); | ||
| 1884 | strcpy(move_string [M3], "M\'" ); | ||
| 1885 | strcpy(move_string [S], "S" ); | ||
| 1886 | strcpy(move_string [S2], "S2" ); | ||
| 1887 | strcpy(move_string [S3], "S\'" ); | ||
| 1888 | strcpy(move_string [E], "E" ); | ||
| 1889 | strcpy(move_string [E2], "E2" ); | ||
| 1890 | strcpy(move_string [E3], "E\'" ); | ||
| 1891 | strcpy(move_string [x], "x" ); | ||
| 1892 | strcpy(move_string [x2], "x2" ); | ||
| 1893 | strcpy(move_string [x3], "x\'" ); | ||
| 1894 | strcpy(move_string [y], "y" ); | ||
| 1895 | strcpy(move_string [y2], "y2" ); | ||
| 1896 | strcpy(move_string [y3], "y\'" ); | ||
| 1897 | strcpy(move_string [z], "z" ); | ||
| 1898 | strcpy(move_string [z2], "z2" ); | ||
| 1899 | strcpy(move_string [z3], "z\'" ); | ||
| 1900 | |||
| 1901 | strcpy(edge_string [UF], "UF" ); | ||
| 1902 | strcpy(edge_string [UL], "UL" ); | ||
| 1903 | strcpy(edge_string [UB], "UB" ); | ||
| 1904 | strcpy(edge_string [UR], "UR" ); | ||
| 1905 | strcpy(edge_string [DF], "DF" ); | ||
| 1906 | strcpy(edge_string [DL], "DL" ); | ||
| 1907 | strcpy(edge_string [DB], "DB" ); | ||
| 1908 | strcpy(edge_string [DR], "DR" ); | ||
| 1909 | strcpy(edge_string [FR], "FR" ); | ||
| 1910 | strcpy(edge_string [FL], "FL" ); | ||
| 1911 | strcpy(edge_string [BL], "BL" ); | ||
| 1912 | strcpy(edge_string [BR], "BR" ); | ||
| 1913 | |||
| 1914 | strcpy(corner_string [UFR], "UFR" ); | ||
| 1915 | strcpy(corner_string [UFL], "UFL" ); | ||
| 1916 | strcpy(corner_string [UBL], "UBL" ); | ||
| 1917 | strcpy(corner_string [UBR], "UBR" ); | ||
| 1918 | strcpy(corner_string [DFR], "DFR" ); | ||
| 1919 | strcpy(corner_string [DFL], "DFL" ); | ||
| 1920 | strcpy(corner_string [DBL], "DBL" ); | ||
| 1921 | strcpy(corner_string [DBR], "DBR" ); | ||
| 1922 | |||
| 1923 | strcpy(center_string [U_center], "U" ); | ||
| 1924 | strcpy(center_string [D_center], "D" ); | ||
| 1925 | strcpy(center_string [R_center], "R" ); | ||
| 1926 | strcpy(center_string [L_center], "L" ); | ||
| 1927 | strcpy(center_string [F_center], "F" ); | ||
| 1928 | strcpy(center_string [B_center], "B" ); | ||
| 1929 | } | ||
| 1930 | |||
| 1931 | static void | ||
| 1932 | init_trans() { | ||
| 1933 | Cube aux, cube, c[3]; | ||
| 1934 | CubeArray epcp; | ||
| 1935 | int eparr[12], eoarr[12]; | ||
| 1936 | int cparr[8], coarr[8]; | ||
| 1937 | int i; | ||
| 1938 | bool b1, b2, b3; | ||
| 1939 | uint16_t ui; | ||
| 1940 | Move mi, move; | ||
| 1941 | Trans m; | ||
| 1942 | |||
| 1943 | /* Compute sources */ | ||
| 1944 | for (i = 0; i < NTRANS; i++) { | ||
| 1945 | if (i == mirror) | ||
| 1946 | cube = (Cube){0}; | ||
| 1947 | else | ||
| 1948 | cube = apply_alg(trans_algs[i], (Cube){0}); | ||
| 1949 | |||
| 1950 | epose_source[i] = edge_slice(edge_at(cube, FR)); | ||
| 1951 | eposs_source[i] = edge_slice(edge_at(cube, UR)); | ||
| 1952 | eposm_source[i] = edge_slice(edge_at(cube, UF)); | ||
| 1953 | eofb_source[i] = center_at(cube, F_center)/2; | ||
| 1954 | eorl_source[i] = center_at(cube, R_center)/2; | ||
| 1955 | eoud_source[i] = center_at(cube, U_center)/2; | ||
| 1956 | coud_source[i] = center_at(cube, U_center)/2; | ||
| 1957 | cofb_source[i] = center_at(cube, F_center)/2; | ||
| 1958 | corl_source[i] = center_at(cube, R_center)/2; | ||
| 1959 | } | ||
| 1960 | |||
| 1961 | if (read_ttables_file()) | ||
| 1962 | return; | ||
| 1963 | |||
| 1964 | fprintf(stderr, "Cannot load %s, generating it\n", "ttables"); | ||
| 1965 | |||
| 1966 | /* Initialize tables */ | ||
| 1967 | for (m = 0; m < NTRANS; m++) { | ||
| 1968 | if (m == mirror) { | ||
| 1969 | memcpy(eparr, ep_mirror, 12 * sizeof(int)); | ||
| 1970 | memcpy(cparr, cp_mirror, 8 * sizeof(int)); | ||
| 1971 | } else { | ||
| 1972 | epcp = (CubeArray){ .ep = eparr, .cp = cparr }; | ||
| 1973 | cube = apply_alg(trans_algs[m], (Cube){0}); | ||
| 1974 | cube_to_arrays(cube, &epcp, pf_epcp); | ||
| 1975 | } | ||
| 1976 | |||
| 1977 | for (ui = 0; ui < FACTORIAL12/FACTORIAL8; ui++) { | ||
| 1978 | c[0] = admissible_ep((Cube){ .epose = ui }, pf_e); | ||
| 1979 | c[1] = admissible_ep((Cube){ .eposs = ui }, pf_s); | ||
| 1980 | c[2] = admissible_ep((Cube){ .eposm = ui }, pf_m); | ||
| 1981 | |||
| 1982 | cube = rotate_via_compose(m,c[epose_source[m]],pf_ep); | ||
| 1983 | epose_ttable[m][ui] = cube.epose; | ||
| 1984 | |||
| 1985 | cube = rotate_via_compose(m,c[eposs_source[m]],pf_ep); | ||
| 1986 | eposs_ttable[m][ui] = cube.eposs; | ||
| 1987 | |||
| 1988 | cube = rotate_via_compose(m,c[eposm_source[m]],pf_ep); | ||
| 1989 | eposm_ttable[m][ui] = cube.eposm; | ||
| 1990 | } | ||
| 1991 | for (ui = 0; ui < POW2TO11; ui++ ) { | ||
| 1992 | int_to_sum_zero_array(ui, 2, 12, eoarr); | ||
| 1993 | apply_permutation(eparr, eoarr, 12); | ||
| 1994 | eo_ttable[m][ui] = digit_array_to_int(eoarr, 11, 2); | ||
| 1995 | } | ||
| 1996 | for (ui = 0; ui < POW3TO7; ui++) { | ||
| 1997 | int_to_sum_zero_array(ui, 3, 8, coarr); | ||
| 1998 | apply_permutation(cparr, coarr, 8); | ||
| 1999 | co_ttable[m][ui] = digit_array_to_int(coarr, 7, 3); | ||
| 2000 | if (m == mirror) | ||
| 2001 | co_ttable[m][ui] = | ||
| 2002 | invert_digits(co_ttable[m][ui], 3, 7); | ||
| 2003 | } | ||
| 2004 | for (ui = 0; ui < FACTORIAL8; ui++) { | ||
| 2005 | cube = (Cube){ .cp = ui }; | ||
| 2006 | cube = rotate_via_compose(m, cube, pf_cp); | ||
| 2007 | cp_ttable[m][ui] = cube.cp; | ||
| 2008 | } | ||
| 2009 | for (ui = 0; ui < FACTORIAL6; ui++) { | ||
| 2010 | cube = (Cube){ .cpos = ui }; | ||
| 2011 | cube = rotate_via_compose(m, cube, pf_cpos); | ||
| 2012 | cpos_ttable[m][ui] = cube.cpos; | ||
| 2013 | } | ||
| 2014 | for (mi = 0; mi < NMOVES; mi++) { | ||
| 2015 | if (m == mirror) { | ||
| 2016 | b1 = (mi >= U && mi <= Bw3); | ||
| 2017 | b2 = (mi >= S && mi <= E3); | ||
| 2018 | b3 = (mi >= x && mi <= z3); | ||
| 2019 | if (b1 || b2 || b3) | ||
| 2020 | moves_ttable[m][mi] = | ||
| 2021 | inverse_move_aux[mi]; | ||
| 2022 | else | ||
| 2023 | moves_ttable[m][mi] = mi; | ||
| 2024 | |||
| 2025 | if ((mi-1)/3==(R-1)/3 || (mi-1)/3==(Rw-1)/3) | ||
| 2026 | moves_ttable[m][mi] += 3; | ||
| 2027 | if ((mi-1)/3==(L-1)/3 || (mi-1)/3==(L2-1)/3) | ||
| 2028 | moves_ttable[m][mi] -= 3; | ||
| 2029 | } else { | ||
| 2030 | aux = apply_trans(m, apply_move(mi,(Cube){0})); | ||
| 2031 | for (move = 0; move < NMOVES; move++) { | ||
| 2032 | cube = apply_move( | ||
| 2033 | inverse_move_aux[move], aux); | ||
| 2034 | if (is_solved(cube, false)) | ||
| 2035 | moves_ttable[m][mi] = move; | ||
| 2036 | } | ||
| 2037 | } | ||
| 2038 | } | ||
| 2039 | } | ||
| 2040 | |||
| 2041 | if (!write_ttables_file()) | ||
| 2042 | fprintf(stderr, "Error writing ttables\n"); | ||
| 2043 | } | ||
| 2044 | |||
| 2045 | static void | ||
| 2046 | init_trans_aux() | ||
| 2047 | { | ||
| 2048 | ep_mirror[UF] = UF; | ||
| 2049 | ep_mirror[UL] = UR; | ||
| 2050 | ep_mirror[UB] = UB; | ||
| 2051 | ep_mirror[UR] = UL; | ||
| 2052 | ep_mirror[DF] = DF; | ||
| 2053 | ep_mirror[DL] = DR; | ||
| 2054 | ep_mirror[DB] = DB; | ||
| 2055 | ep_mirror[DR] = DL; | ||
| 2056 | ep_mirror[FR] = FL; | ||
| 2057 | ep_mirror[FL] = FR; | ||
| 2058 | ep_mirror[BR] = BL; | ||
| 2059 | ep_mirror[BL] = BR; | ||
| 2060 | |||
| 2061 | cp_mirror[UFR] = UFL; | ||
| 2062 | cp_mirror[UFL] = UFR; | ||
| 2063 | cp_mirror[UBL] = UBR; | ||
| 2064 | cp_mirror[UBR] = UBL; | ||
| 2065 | cp_mirror[DFR] = DFL; | ||
| 2066 | cp_mirror[DFL] = DFR; | ||
| 2067 | cp_mirror[DBL] = DBR; | ||
| 2068 | cp_mirror[DBR] = DBL; | ||
| 2069 | |||
| 2070 | cpos_mirror[U_center] = U_center; | ||
| 2071 | cpos_mirror[D_center] = D_center; | ||
| 2072 | cpos_mirror[R_center] = L_center; | ||
| 2073 | cpos_mirror[L_center] = R_center; | ||
| 2074 | cpos_mirror[F_center] = F_center; | ||
| 2075 | cpos_mirror[B_center] = B_center; | ||
| 2076 | |||
| 2077 | /* Is there a more elegant way? */ | ||
| 2078 | trans_algs[uf] = new_alg(""); | ||
| 2079 | trans_algs[ur] = new_alg("y"); | ||
| 2080 | trans_algs[ub] = new_alg("y2"); | ||
| 2081 | trans_algs[ul] = new_alg("y3"); | ||
| 2082 | |||
| 2083 | trans_algs[df] = new_alg("z2"); | ||
| 2084 | trans_algs[dr] = new_alg("y z2"); | ||
| 2085 | trans_algs[db] = new_alg("x2"); | ||
| 2086 | trans_algs[dl] = new_alg("y3 z2"); | ||
| 2087 | |||
| 2088 | trans_algs[rf] = new_alg("z3"); | ||
| 2089 | trans_algs[rd] = new_alg("z3 y"); | ||
| 2090 | trans_algs[rb] = new_alg("z3 y2"); | ||
| 2091 | trans_algs[ru] = new_alg("z3 y3"); | ||
| 2092 | |||
| 2093 | trans_algs[lf] = new_alg("z"); | ||
| 2094 | trans_algs[ld] = new_alg("z y3"); | ||
| 2095 | trans_algs[lb] = new_alg("z y2"); | ||
| 2096 | trans_algs[lu] = new_alg("z y"); | ||
| 2097 | |||
| 2098 | trans_algs[fu] = new_alg("x y2"); | ||
| 2099 | trans_algs[fr] = new_alg("x y"); | ||
| 2100 | trans_algs[fd] = new_alg("x"); | ||
| 2101 | trans_algs[fl] = new_alg("x y3"); | ||
| 2102 | |||
| 2103 | trans_algs[bu] = new_alg("x3"); | ||
| 2104 | trans_algs[br] = new_alg("x3 y"); | ||
| 2105 | trans_algs[bd] = new_alg("x3 y2"); | ||
| 2106 | trans_algs[bl] = new_alg("x3 y3"); | ||
| 2107 | } | ||
| 2108 | |||
| 2109 | |||
| 2110 | /* Public functions implementation *******************************************/ | ||
| 2111 | |||
| 2112 | Cube | ||
| 2113 | apply_alg(Alg *alg, Cube cube) | ||
| 2114 | { | ||
| 2115 | return apply_alg_generic(alg, cube, pf_all, true); | ||
| 2116 | } | ||
| 2117 | |||
| 2118 | Cube | ||
| 2119 | apply_move(Move m, Cube cube) | ||
| 2120 | { | ||
| 2121 | return (Cube) { | ||
| 2122 | .epose = epose_mtable[m][cube.epose], | ||
| 2123 | .eposs = eposs_mtable[m][cube.eposs], | ||
| 2124 | .eposm = eposm_mtable[m][cube.eposm], | ||
| 2125 | .eofb = eofb_mtable[m][cube.eofb], | ||
| 2126 | .eorl = eorl_mtable[m][cube.eorl], | ||
| 2127 | .eoud = eoud_mtable[m][cube.eoud], | ||
| 2128 | .coud = coud_mtable[m][cube.coud], | ||
| 2129 | .cofb = cofb_mtable[m][cube.cofb], | ||
| 2130 | .corl = corl_mtable[m][cube.corl], | ||
| 2131 | .cp = cp_mtable[m][cube.cp], | ||
| 2132 | .cpos = cpos_mtable[m][cube.cpos] | ||
| 2133 | }; | ||
| 2134 | } | ||
| 2135 | |||
| 2136 | Cube | ||
| 2137 | apply_trans(Trans t, Cube cube) | ||
| 2138 | { | ||
| 2139 | uint16_t aux_epos[3] = { cube.epose, cube.eposs, cube.eposm }; | ||
| 2140 | uint16_t aux_eo[3] = { cube.eoud, cube.eorl, cube.eofb }; | ||
| 2141 | uint16_t aux_co[3] = { cube.coud, cube.corl, cube.cofb }; | ||
| 2142 | |||
| 2143 | return (Cube) { | ||
| 2144 | .epose = epose_ttable[t][aux_epos[epose_source[t]]], | ||
| 2145 | .eposs = eposs_ttable[t][aux_epos[eposs_source[t]]], | ||
| 2146 | .eposm = eposm_ttable[t][aux_epos[eposm_source[t]]], | ||
| 2147 | .eofb = eo_ttable[t][aux_eo[eofb_source[t]]], | ||
| 2148 | .eorl = eo_ttable[t][aux_eo[eorl_source[t]]], | ||
| 2149 | .eoud = eo_ttable[t][aux_eo[eoud_source[t]]], | ||
| 2150 | .coud = co_ttable[t][aux_co[coud_source[t]]], | ||
| 2151 | .corl = co_ttable[t][aux_co[corl_source[t]]], | ||
| 2152 | .cofb = co_ttable[t][aux_co[cofb_source[t]]], | ||
| 2153 | .cp = cp_ttable[t][cube.cp], | ||
| 2154 | .cpos = cpos_ttable[t][cube.cpos] | ||
| 2155 | }; | ||
| 2156 | } | ||
| 2157 | |||
| 2158 | Move | ||
| 2159 | base_move(Move m) | ||
| 2160 | { | ||
| 2161 | if (m == NULLMOVE) | ||
| 2162 | return NULLMOVE; | ||
| 2163 | else | ||
| 2164 | return m - (m-1)%3; | ||
| 2165 | } | ||
| 2166 | |||
| 2167 | /* TODO: this has to be changed using pre-computations */ | ||
| 2168 | bool | ||
| 2169 | block_solved(Cube cube, Block block) | ||
| 2170 | { | ||
| 2171 | CubeArray *arr = new_cubearray(cube, pf_all); | ||
| 2172 | int i; | ||
| 2173 | bool ret = true; | ||
| 2174 | |||
| 2175 | for (i = 0; i < 12; i++) | ||
| 2176 | ret = ret && !(block.edge[i] && (arr->ep[i] != i || arr->eofb[i])); | ||
| 2177 | for (i = 0; i < 8; i++) | ||
| 2178 | ret = ret && !(block.corner[i] && (arr->cp[i] != i || arr->coud[i])); | ||
| 2179 | for (i = 0; i < 6; i++) | ||
| 2180 | ret = ret && !(block.center[i] && arr->cpos[i] != i); | ||
| 2181 | |||
| 2182 | free_cubearray(arr, pf_all); | ||
| 2183 | |||
| 2184 | return ret; | ||
| 2185 | } | ||
| 2186 | |||
| 2187 | Center | ||
| 2188 | center_at(Cube cube, Center c) | ||
| 2189 | { | ||
| 2190 | int ret; | ||
| 2191 | CubeArray *arr = new_cubearray(cube, pf_cpos); | ||
| 2192 | |||
| 2193 | ret = arr->cpos[c]; | ||
| 2194 | free_cubearray(arr, pf_cpos); | ||
| 2195 | |||
| 2196 | return ret; | ||
| 2197 | } | ||
| 2198 | |||
| 2199 | Cube | ||
| 2200 | compose(Cube c2, Cube c1) | ||
| 2201 | { | ||
| 2202 | return compose_filtered(c2, c1, pf_all); | ||
| 2203 | } | ||
| 2204 | |||
| 2205 | Corner | ||
| 2206 | corner_at(Cube cube, Corner c) | ||
| 2207 | { | ||
| 2208 | int ret; | ||
| 2209 | CubeArray *arr = new_cubearray(cube, pf_cp); | ||
| 2210 | |||
| 2211 | ret = arr->cp[c]; | ||
| 2212 | free_cubearray(arr, pf_cp); | ||
| 2213 | |||
| 2214 | return ret; | ||
| 2215 | } | ||
| 2216 | |||
| 2217 | Edge | ||
| 2218 | edge_at(Cube cube, Edge e) | ||
| 2219 | { | ||
| 2220 | int ret; | ||
| 2221 | CubeArray *arr = new_cubearray(cube, pf_ep); | ||
| 2222 | |||
| 2223 | ret = arr->ep[e]; | ||
| 2224 | free_cubearray(arr, pf_ep); | ||
| 2225 | |||
| 2226 | return ret; | ||
| 2227 | } | ||
| 2228 | |||
| 2229 | uint64_t | ||
| 2230 | epos_dependent_cube(Cube c) | ||
| 2231 | { | ||
| 2232 | return epos_dependent_aux[c.eposs/FACTORIAL4][c.epose/FACTORIAL4]; | ||
| 2233 | } | ||
| 2234 | |||
| 2235 | bool | ||
| 2236 | equal(Cube c1, Cube c2) | ||
| 2237 | { | ||
| 2238 | return c1.eofb == c2.eofb && | ||
| 2239 | c1.epose == c2.epose && | ||
| 2240 | c1.eposs == c2.eposs && | ||
| 2241 | c1.eposm == c2.eposm && | ||
| 2242 | c1.coud == c2.coud && | ||
| 2243 | c1.cp == c2.cp && | ||
| 2244 | c1.cpos == c2.cpos; | ||
| 2245 | } | ||
| 2246 | |||
| 2247 | void | ||
| 2248 | generate_ctable(CacheData *cd) | ||
| 2249 | { | ||
| 2250 | uint64_t i; | ||
| 2251 | DfsData dd = { | ||
| 2252 | .d = cd->len, | ||
| 2253 | .last1 = NULLMOVE, | ||
| 2254 | .last2 = NULLMOVE, | ||
| 2255 | .current_alg = new_alg("") | ||
| 2256 | }; | ||
| 2257 | |||
| 2258 | if (cd->generated) | ||
| 2259 | return; | ||
| 2260 | |||
| 2261 | /* TODO: check if memory is enough, otherwise maybe crash gracefully? */ | ||
| 2262 | cd->ctable = malloc(cd->maxind0 * sizeof(CacheNode *)); | ||
| 2263 | for (i = 0; i < cd->maxind0; i++) | ||
| 2264 | cd->ctable[i] = NULL; | ||
| 2265 | |||
| 2266 | if (read_ctable_file(cd)) { | ||
| 2267 | cd->generated = true; | ||
| 2268 | return; | ||
| 2269 | } | ||
| 2270 | |||
| 2271 | fprintf(stderr, "Cannot load %s, generating it\n", cd->filename); | ||
| 2272 | |||
| 2273 | moveset_to_list(cd->moveset, NULL, dd.sorted_moves); | ||
| 2274 | movelist_to_position(dd.sorted_moves, dd.move_position); | ||
| 2275 | |||
| 2276 | generate_ctable_dfs((Cube){0}, cd, &dd); | ||
| 2277 | |||
| 2278 | if (!write_ctable_file(cd)) | ||
| 2279 | fprintf(stderr, "Error writing ctable file\n"); | ||
| 2280 | |||
| 2281 | cd->generated = true; | ||
| 2282 | } | ||
| 2283 | |||
| 2284 | void | ||
| 2285 | generate_ptable(PruneData *pd) | ||
| 2286 | { | ||
| 2287 | uint64_t j; | ||
| 2288 | DfsData dd = { | ||
| 2289 | .m = 0, | ||
| 2290 | .last1 = NULLMOVE, | ||
| 2291 | .last2 = NULLMOVE | ||
| 2292 | }; | ||
| 2293 | |||
| 2294 | if (pd->generated) | ||
| 2295 | return; | ||
| 2296 | |||
| 2297 | /* TODO: check if memory is enough, otherwise maybe crash gracefully? */ | ||
| 2298 | pd->ptable = malloc(PTABLESIZE(pd->size) * sizeof(uint8_t)); | ||
| 2299 | |||
| 2300 | if (read_ptable_file(pd)) { | ||
| 2301 | pd->generated = true; | ||
| 2302 | return; | ||
| 2303 | } | ||
| 2304 | |||
| 2305 | fprintf(stderr, "Cannot load %s, generating it\n", pd->filename); | ||
| 2306 | |||
| 2307 | /* We use 4 bits per value, so any distance >= 15 is set to 15 */ | ||
| 2308 | for (j = 0; j < pd->size; j++) | ||
| 2309 | ptable_update(pd, j, 15); | ||
| 2310 | |||
| 2311 | moveset_to_list(pd->moveset, NULL, dd.sorted_moves); | ||
| 2312 | movelist_to_position(dd.sorted_moves, dd.move_position); | ||
| 2313 | |||
| 2314 | pd->reached = malloc(PTABLESIZE(pd->size) * sizeof(uint8_t)); | ||
| 2315 | for (dd.d = 0, pd->n = 0; dd.d < 15 && pd->n < pd->size; dd.d++) { | ||
| 2316 | memset(pd->reached, 0, PTABLESIZE(pd->size)*sizeof(uint8_t)); | ||
| 2317 | generate_ptable_dfs((Cube){0}, pd, &dd); | ||
| 2318 | fprintf(stderr, "Depth %d completed, generated %lu/%lu\n", | ||
| 2319 | dd.d, pd->n, pd->size); | ||
| 2320 | } | ||
| 2321 | |||
| 2322 | if (!write_ptable_file(pd)) | ||
| 2323 | fprintf(stderr, "Error writing ptable file\n"); | ||
| 2324 | |||
| 2325 | pd->generated = true; | ||
| 2326 | free(pd->reached); | ||
| 2327 | } | ||
| 2328 | |||
| 2329 | Cube | ||
| 2330 | inverse_cube(Cube cube) | ||
| 2331 | { | ||
| 2332 | CubeArray *arr = new_cubearray(cube, pf_all); | ||
| 2333 | CubeArray *inv = new_cubearray((Cube){0}, pf_all); | ||
| 2334 | Cube ret; | ||
| 2335 | int i; | ||
| 2336 | |||
| 2337 | for (i = 0; i < 12; i++) { | ||
| 2338 | inv->ep[arr->ep[i]] = i; | ||
| 2339 | inv->eofb[arr->ep[i]] = arr->eofb[i]; | ||
| 2340 | inv->eorl[arr->ep[i]] = arr->eorl[i]; | ||
| 2341 | inv->eoud[arr->ep[i]] = arr->eoud[i]; | ||
| 2342 | } | ||
| 2343 | |||
| 2344 | for (i = 0; i < 8; i++) { | ||
| 2345 | inv->cp[arr->cp[i]] = i; | ||
| 2346 | inv->coud[arr->cp[i]] = (3 - arr->coud[i]) % 3; | ||
| 2347 | inv->corl[arr->cp[i]] = (3 - arr->corl[i]) % 3; | ||
| 2348 | inv->cofb[arr->cp[i]] = (3 - arr->cofb[i]) % 3; | ||
| 2349 | } | ||
| 2350 | |||
| 2351 | for (int i = 0; i < 6; i++) | ||
| 2352 | inv->cpos[arr->cpos[i]] = i; | ||
| 2353 | |||
| 2354 | ret = arrays_to_cube(inv, pf_all); | ||
| 2355 | free_cubearray(arr, pf_all); | ||
| 2356 | free_cubearray(inv, pf_all); | ||
| 2357 | |||
| 2358 | return ret; | ||
| 2359 | } | ||
| 2360 | |||
| 2361 | Move | ||
| 2362 | inverse_move(Move m) | ||
| 2363 | { | ||
| 2364 | return inverse_move_aux[m]; | ||
| 2365 | } | ||
| 2366 | |||
| 2367 | Trans | ||
| 2368 | inverse_trans(Trans t) | ||
| 2369 | { | ||
| 2370 | return inverse_trans_aux[t]; | ||
| 2371 | } | ||
| 2372 | |||
| 2373 | bool | ||
| 2374 | is_admissible(Cube cube) | ||
| 2375 | { | ||
| 2376 | /* TODO: this should check consistency of different orientations */ | ||
| 2377 | /* TODO: check that centers are opposite and admissible */ | ||
| 2378 | |||
| 2379 | CubeArray *a = new_cubearray(cube, pf_all); | ||
| 2380 | int parity; | ||
| 2381 | bool perm; | ||
| 2382 | |||
| 2383 | perm = is_perm(a->ep, 12) && | ||
| 2384 | is_perm(a->cp, 8) && | ||
| 2385 | is_perm(a->cpos, 6); | ||
| 2386 | parity = perm_sign(a->ep, 12) + | ||
| 2387 | perm_sign(a->cp, 8) + | ||
| 2388 | perm_sign(a->cpos, 6); | ||
| 2389 | |||
| 2390 | return perm && parity % 2 == 0; | ||
| 2391 | } | ||
| 2392 | |||
| 2393 | bool | ||
| 2394 | is_solved(Cube cube, bool reorient) | ||
| 2395 | { | ||
| 2396 | Trans i; | ||
| 2397 | |||
| 2398 | if (reorient) | ||
| 2399 | for (i = 0; i < NROTATIONS; i++) | ||
| 2400 | if (is_solved(apply_alg(trans_algs[i],cube), false)) | ||
| 2401 | return true; | ||
| 2402 | |||
| 2403 | return equal(cube, (Cube){0}); | ||
| 2404 | } | ||
| 2405 | |||
| 2406 | int | ||
| 2407 | piece_orientation(Cube cube, int piece, char *orientation) | ||
| 2408 | { | ||
| 2409 | int arr[12], n, b; | ||
| 2410 | uint16_t x; | ||
| 2411 | |||
| 2412 | if (!strcmp(orientation, "eofb")) { | ||
| 2413 | x = cube.eofb; | ||
| 2414 | n = 12; | ||
| 2415 | b = 2; | ||
| 2416 | } else if (!strcmp(orientation, "eorl")) { | ||
| 2417 | x = cube.eorl; | ||
| 2418 | n = 12; | ||
| 2419 | b = 2; | ||
| 2420 | } else if (!strcmp(orientation, "eoud")) { | ||
| 2421 | x = cube.eoud; | ||
| 2422 | n = 12; | ||
| 2423 | b = 2; | ||
| 2424 | } else if (!strcmp(orientation, "coud")) { | ||
| 2425 | x = cube.coud; | ||
| 2426 | n = 8; | ||
| 2427 | b = 3; | ||
| 2428 | } else if (!strcmp(orientation, "corl")) { | ||
| 2429 | x = cube.corl; | ||
| 2430 | n = 8; | ||
| 2431 | b = 3; | ||
| 2432 | } else if (!strcmp(orientation, "cofb")) { | ||
| 2433 | x = cube.cofb; | ||
| 2434 | n = 8; | ||
| 2435 | b = 3; | ||
| 2436 | } else { | ||
| 2437 | return -1; | ||
| 2438 | } | ||
| 2439 | |||
| 2440 | int_to_sum_zero_array(x, b, n, arr); | ||
| 2441 | if (piece < n) | ||
| 2442 | return arr[piece]; | ||
| 2443 | |||
| 2444 | return -1; | ||
| 2445 | } | ||
| 2446 | |||
| 2447 | void | ||
| 2448 | print_cube(Cube cube) | ||
| 2449 | { | ||
| 2450 | CubeArray *arr = new_cubearray(cube, pf_all); | ||
| 2451 | |||
| 2452 | for (int i = 0; i < 12; i++) | ||
| 2453 | printf(" %s ", edge_string[arr->ep[i]]); | ||
| 2454 | printf("\n"); | ||
| 2455 | |||
| 2456 | for (int i = 0; i < 12; i++) | ||
| 2457 | printf(" %c ", arr->eofb[i] + '0'); | ||
| 2458 | printf("\n"); | ||
| 2459 | |||
| 2460 | for (int i = 0; i < 8; i++) | ||
| 2461 | printf("%s ", corner_string[arr->cp[i]]); | ||
| 2462 | printf("\n"); | ||
| 2463 | |||
| 2464 | for (int i = 0; i < 8; i++) | ||
| 2465 | printf(" %c ", arr->coud[i] + '0'); | ||
| 2466 | printf("\n"); | ||
| 2467 | |||
| 2468 | for (int i = 0; i < 6; i++) | ||
| 2469 | printf(" %s ", center_string[arr->cpos[i]]); | ||
| 2470 | printf("\n"); | ||
| 2471 | |||
| 2472 | free_cubearray(arr, pf_all); | ||
| 2473 | } | ||
| 2474 | |||
| 2475 | Cube | ||
| 2476 | random_cube() | ||
| 2477 | { | ||
| 2478 | CubeArray *arr = new_cubearray((Cube){0}, pf_4val); | ||
| 2479 | Cube ret; | ||
| 2480 | int ep, cp, eo, co; | ||
| 2481 | |||
| 2482 | ep = rand() % FACTORIAL12; | ||
| 2483 | cp = rand() % FACTORIAL8; | ||
| 2484 | eo = rand() % POW2TO11; | ||
| 2485 | co = rand() % POW3TO7; | ||
| 2486 | |||
| 2487 | index_to_perm(ep, 12, arr->ep); | ||
| 2488 | index_to_perm(cp, 8, arr->cp); | ||
| 2489 | int_to_sum_zero_array(eo, 2, 12, arr->eofb); | ||
| 2490 | int_to_sum_zero_array(co, 3, 8, arr->coud); | ||
| 2491 | |||
| 2492 | if (perm_sign(arr->ep, 12) != perm_sign(arr->cp, 8)) | ||
| 2493 | swap(&(arr->ep[0]), &(arr->ep[1])); | ||
| 2494 | |||
| 2495 | ret = arrays_to_cube(arr, pf_4val); | ||
| 2496 | free_cubearray(arr, pf_4val); | ||
| 2497 | |||
| 2498 | return ret; | ||
| 2499 | } | ||
| 2500 | |||
| 2501 | AlgList * | ||
| 2502 | solve(Cube cube, Step step, SolveOptions *opts) | ||
| 2503 | { | ||
| 2504 | AlgListNode *node; | ||
| 2505 | AlgList *sols = new_alglist(); | ||
| 2506 | Cube c = apply_trans(opts->pre_trans, cube); | ||
| 2507 | DfsData dd = { | ||
| 2508 | .m = 0, | ||
| 2509 | .niss = false, | ||
| 2510 | .last1 = NULLMOVE, | ||
| 2511 | .last2 = NULLMOVE, | ||
| 2512 | .sols = sols, | ||
| 2513 | .current_alg = new_alg("") | ||
| 2514 | }; | ||
| 2515 | |||
| 2516 | if (step.ready != NULL && !step.ready(c)) { | ||
| 2517 | fprintf(stderr, "Cube not ready for solving step\n"); | ||
| 2518 | return sols; | ||
| 2519 | } | ||
| 2520 | |||
| 2521 | moveset_to_list(step.moveset, step.check, dd.sorted_moves); | ||
| 2522 | movelist_to_position(dd.sorted_moves, dd.move_position); | ||
| 2523 | |||
| 2524 | for (dd.d = MAX(opts->min_moves, step.check(c)); | ||
| 2525 | dd.d <= opts->max_moves && !(sols->len && opts->optimal_only); | ||
| 2526 | dd.d++) { | ||
| 2527 | if (opts->feedback) | ||
| 2528 | fprintf(stderr, | ||
| 2529 | "Found %d solutions, searching depth %d...\n", | ||
| 2530 | sols->len, dd.d); | ||
| 2531 | solve_dfs(c, step, opts, &dd); | ||
| 2532 | } | ||
| 2533 | |||
| 2534 | for (node = sols->first; node != NULL; node = node->next) | ||
| 2535 | transform_alg(inverse_trans_aux[opts->pre_trans], node->alg); | ||
| 2536 | |||
| 2537 | return sols; | ||
| 2538 | } | ||
| 2539 | |||
| 2540 | Alg * | ||
| 2541 | inverse_alg(Alg *alg) | ||
| 2542 | { | ||
| 2543 | Alg *ret = new_alg(""); | ||
| 2544 | int i; | ||
| 2545 | |||
| 2546 | for (i = alg->len-1; i >= 0; i--) | ||
| 2547 | append_move(ret, alg->move[i], alg->inv[i]); | ||
| 2548 | |||
| 2549 | return ret; | ||
| 2550 | } | ||
| 2551 | |||
| 2552 | Alg * | ||
| 2553 | new_alg(char *str) | ||
| 2554 | { | ||
| 2555 | Alg *alg = malloc(sizeof(Alg)); | ||
| 2556 | int i; | ||
| 2557 | bool niss = false; | ||
| 2558 | Move j, m; | ||
| 2559 | |||
| 2560 | alg->move = malloc(30 * sizeof(Move)); | ||
| 2561 | alg->inv = malloc(30 * sizeof(bool)); | ||
| 2562 | alg->allocated = 30; | ||
| 2563 | alg->len = 0; | ||
| 2564 | |||
| 2565 | for (i = 0; str[i]; i++) { | ||
| 2566 | if (str[i] == ' ' || str[i] == '\t' || str[i] == '\n') | ||
| 2567 | continue; | ||
| 2568 | |||
| 2569 | if (str[i] == '(' && niss) { | ||
| 2570 | fprintf(stderr, "Error reading moves: nested ( )\n"); | ||
| 2571 | return alg; | ||
| 2572 | } | ||
| 2573 | |||
| 2574 | if (str[i] == ')' && !niss) { | ||
| 2575 | fprintf(stderr, "Error reading moves: unmatched )\n"); | ||
| 2576 | return alg; | ||
| 2577 | } | ||
| 2578 | |||
| 2579 | if (str[i] == '(' || str[i] == ')') { | ||
| 2580 | niss = !niss; | ||
| 2581 | continue; | ||
| 2582 | } | ||
| 2583 | |||
| 2584 | for (j = 0; j < NMOVES; j++) { | ||
| 2585 | if (str[i] == move_string[j][0]) { | ||
| 2586 | m = j; | ||
| 2587 | if (m <= B && str[i+1]=='w') { | ||
| 2588 | m += Uw - U; | ||
| 2589 | i++; | ||
| 2590 | } | ||
| 2591 | if (str[i+1]=='2') { | ||
| 2592 | m += 1; | ||
| 2593 | i++; | ||
| 2594 | } else if (str[i+1]=='\'' || str[i+1]=='3') { | ||
| 2595 | m += 2; | ||
| 2596 | i++; | ||
| 2597 | } | ||
| 2598 | append_move(alg, m, niss); | ||
| 2599 | break; | ||
| 2600 | } | ||
| 2601 | } | ||
| 2602 | } | ||
| 2603 | |||
| 2604 | return alg; | ||
| 2605 | } | ||
| 2606 | |||
| 2607 | Alg * | ||
| 2608 | on_inverse(Alg *alg) | ||
| 2609 | { | ||
| 2610 | Alg *ret = new_alg(""); | ||
| 2611 | int i; | ||
| 2612 | |||
| 2613 | for (i = 0; i < alg->len; i++) | ||
| 2614 | append_move(ret, alg->move[i], !alg->inv[i]); | ||
| 2615 | |||
| 2616 | return ret; | ||
| 2617 | } | ||
| 2618 | |||
| 2619 | void | ||
| 2620 | print_alg(Alg *alg, bool l) | ||
| 2621 | { | ||
| 2622 | /* TODO: make it possible to print to stdout or to string */ | ||
| 2623 | /* Maybe just return a string */ | ||
| 2624 | char fill[4]; | ||
| 2625 | int i; | ||
| 2626 | bool niss = false; | ||
| 2627 | |||
| 2628 | for (i = 0; i < alg->len; i++) { | ||
| 2629 | if (!niss && alg->inv[i]) | ||
| 2630 | strcpy(fill, i == 0 ? "(" : " ("); | ||
| 2631 | if (niss && !alg->inv[i]) | ||
| 2632 | strcpy(fill, ") "); | ||
| 2633 | if (niss == alg->inv[i]) | ||
| 2634 | strcpy(fill, i == 0 ? "" : " "); | ||
| 2635 | |||
| 2636 | printf("%s%s", fill, move_string[alg->move[i]]); | ||
| 2637 | niss = alg->inv[i]; | ||
| 2638 | } | ||
| 2639 | |||
| 2640 | if (niss) | ||
| 2641 | printf(")"); | ||
| 2642 | if (l) | ||
| 2643 | printf(" (%d)", alg->len); | ||
| 2644 | |||
| 2645 | printf("\n"); | ||
| 2646 | } | ||
| 2647 | |||
| 2648 | void | ||
| 2649 | print_alglist(AlgList *al, bool l) | ||
| 2650 | { | ||
| 2651 | AlgListNode *i; | ||
| 2652 | |||
| 2653 | for (i = al->first; i != NULL; i = i->next) | ||
| 2654 | print_alg(i->alg, l); | ||
| 2655 | } | ||
| 2656 | |||
| 2657 | void | ||
| 2658 | print_cachedata(CacheData *cd, bool printalgs) | ||
| 2659 | { | ||
| 2660 | CacheNode *j; | ||
| 2661 | uint64_t i, s, maxa = 0, maxs = 0, n = 0, empty = 0; | ||
| 2662 | |||
| 2663 | if (!cd->generated) | ||
| 2664 | generate_ctable(cd); | ||
| 2665 | |||
| 2666 | for (i = 0; i < cd->maxind0; i++) { | ||
| 2667 | if (cd->ctable[i] == NULL) { | ||
| 2668 | empty++; | ||
| 2669 | continue; | ||
| 2670 | } | ||
| 2671 | |||
| 2672 | for (j = cd->ctable[i], s = 0; | ||
| 2673 | j != NULL; j = j->next, n++, s++) | ||
| 2674 | if (printalgs) | ||
| 2675 | print_alg(j->sol, false); | ||
| 2676 | |||
| 2677 | if (s > maxs) { | ||
| 2678 | maxs = s; | ||
| 2679 | maxa = i; | ||
| 2680 | } | ||
| 2681 | } | ||
| 2682 | |||
| 2683 | printf("Cache data %s\n", cd->filename); | ||
| 2684 | printf("Length: %d\n", cd->len); | ||
| 2685 | printf("Main table cells: %lu (of which %lu empty)\n", i, empty); | ||
| 2686 | printf("%lu solutions cached ", n); | ||
| 2687 | printf("(most crowded cell: %lu with %lu)\n", maxa, maxs); | ||
| 2688 | } | ||
| 2689 | |||
| 2690 | void | ||
| 2691 | print_ptable(PruneData *pd) | ||
| 2692 | { | ||
| 2693 | uint64_t i, a[16]; | ||
| 2694 | |||
| 2695 | for (i = 0; i < 16; i++) | ||
| 2696 | a[i] = 0; | ||
| 2697 | |||
| 2698 | if (!pd->generated) | ||
| 2699 | generate_ptable(pd); | ||
| 2700 | |||
| 2701 | for (i = 0; i < pd->size; i++) | ||
| 2702 | a[PTABLEVAL(pd->ptable, i)]++; | ||
| 2703 | |||
| 2704 | fprintf(stderr, "Values for table %s\n", pd->filename); | ||
| 2705 | for (i = 0; i < 16; i++) | ||
| 2706 | printf("%2lu\t%10lu\n", i, a[i]); | ||
| 2707 | } | ||
| 2708 | |||
| 2709 | |||
| 2710 | Alg * | ||
| 2711 | trans_alg(Trans i) | ||
| 2712 | { | ||
| 2713 | return trans_algs[i]; | ||
| 2714 | } | ||
| 2715 | |||
| 2716 | void | ||
| 2717 | transform_alg(Trans t, Alg *alg) | ||
| 2718 | { | ||
| 2719 | int i; | ||
| 2720 | |||
| 2721 | for (i = 0; i < alg->len; i++) | ||
| 2722 | alg->move[i] = moves_ttable[t][alg->move[i]]; | ||
| 2723 | } | ||
| 2724 | |||
| 2725 | |||
| 2726 | void | ||
| 2727 | init() | ||
| 2728 | { | ||
| 2729 | /* Order is important! */ | ||
| 2730 | init_environment(); | ||
| 2731 | init_strings(); | ||
| 2732 | init_moves_aux(); | ||
| 2733 | init_moves(); | ||
| 2734 | init_auxtables(); | ||
| 2735 | init_trans_aux(); | ||
| 2736 | init_trans(); | ||
| 2737 | } | ||
| 2738 | |||
diff --git a/old/2021-06-17-cachedata/cube.h b/old/2021-06-17-cachedata/cube.h new file mode 100644 index 0000000..d233165 --- /dev/null +++ b/old/2021-06-17-cachedata/cube.h | |||
| @@ -0,0 +1,79 @@ | |||
| 1 | #ifndef CUBE_H | ||
| 2 | #define CUBE_H | ||
| 3 | |||
| 4 | #include <stdio.h> | ||
| 5 | #include <stdbool.h> | ||
| 6 | #include <stdint.h> | ||
| 7 | #include <stdlib.h> | ||
| 8 | #include <string.h> | ||
| 9 | #include <time.h> | ||
| 10 | #include <unistd.h> | ||
| 11 | #include <sys/stat.h> | ||
| 12 | |||
| 13 | /* Constants and macros *****************************************************/ | ||
| 14 | |||
| 15 | #define POW2TO11 2048ULL | ||
| 16 | #define POW2TO12 4096ULL | ||
| 17 | #define POW3TO7 2187ULL | ||
| 18 | #define POW3TO8 6561ULL | ||
| 19 | #define FACTORIAL4 24ULL | ||
| 20 | #define FACTORIAL6 720ULL | ||
| 21 | #define FACTORIAL8 40320ULL | ||
| 22 | #define FACTORIAL12 479001600ULL | ||
| 23 | #define BINOM12ON4 495ULL | ||
| 24 | #define BINOM8ON4 70ULL | ||
| 25 | #define MIN(a,b) (((a) < (b)) ? (a) : (b)) | ||
| 26 | #define MAX(a,b) (((a) > (b)) ? (a) : (b)) | ||
| 27 | |||
| 28 | #define NMOVES (z3+1) | ||
| 29 | #define NTRANS (mirror+1) | ||
| 30 | #define NROTATIONS (NTRANS-1) | ||
| 31 | #define PTABLESIZE(n) ((n+1) / 2) | ||
| 32 | #define PTABLEVAL(t,i) (((i)%2) ? (t[(i)/2] / 16) : (t[(i)/2] % 16)) | ||
| 33 | |||
| 34 | /* Type definitions **********************************************************/ | ||
| 35 | |||
| 36 | #include "cubetypes.h" | ||
| 37 | |||
| 38 | /* Public functions **********************************************************/ | ||
| 39 | |||
| 40 | Cube apply_alg(Alg *alg, Cube cube); | ||
| 41 | Cube apply_move(Move m, Cube cube); | ||
| 42 | Cube apply_trans(Trans t, Cube cube); | ||
| 43 | bool block_solved(Cube cube, Block); | ||
| 44 | Center center_at(Cube cube, Center c); | ||
| 45 | Cube compose(Cube c2, Cube c1); /* Use c2 as an alg on c1 */ | ||
| 46 | Corner corner_at(Cube cube, Corner c); | ||
| 47 | Edge edge_at(Cube cube, Edge e); | ||
| 48 | uint64_t epos_dependent_cube(Cube cube); | ||
| 49 | bool equal(Cube c1, Cube c2); | ||
| 50 | Cube inverse_cube(Cube cube); | ||
| 51 | Move inverse_move(Move m); | ||
| 52 | Trans inverse_trans(Trans t); | ||
| 53 | bool is_admissible(Cube cube); | ||
| 54 | bool is_solved(Cube cube, bool reorient); | ||
| 55 | int piece_orientation(Cube cube, int piece, char *orientation); | ||
| 56 | void print_cube(Cube cube); | ||
| 57 | Cube random_cube(); | ||
| 58 | AlgList * solve(Cube cube, Step step, SolveOptions *opts); | ||
| 59 | |||
| 60 | Move base_move(Move m); | ||
| 61 | void free_alg(Alg *alg); | ||
| 62 | void free_alglist(AlgList *l); | ||
| 63 | Alg * inverse_alg(Alg *alg); | ||
| 64 | Alg * new_alg(char *str); | ||
| 65 | Alg * on_inverse(Alg *alg); | ||
| 66 | void print_alg(Alg *alg, bool l); | ||
| 67 | void print_alglist(AlgList *al, bool l); | ||
| 68 | Alg * trans_alg(Trans i); | ||
| 69 | void transform_alg(Trans t, Alg *alg); | ||
| 70 | |||
| 71 | void generate_ctable(CacheData *cd); | ||
| 72 | void generate_ptable(PruneData *pd); | ||
| 73 | void print_cachedata(CacheData *cd, bool printalgs); | ||
| 74 | void print_ptable(PruneData *pd); | ||
| 75 | |||
| 76 | void init(); | ||
| 77 | |||
| 78 | #endif | ||
| 79 | |||
diff --git a/old/2021-06-17-cachedata/cubetypes.h b/old/2021-06-17-cachedata/cubetypes.h new file mode 100644 index 0000000..4369385 --- /dev/null +++ b/old/2021-06-17-cachedata/cubetypes.h | |||
| @@ -0,0 +1,232 @@ | |||
| 1 | /* Typedefs ******************************************************************/ | ||
| 2 | |||
| 3 | typedef enum center Center; | ||
| 4 | typedef enum corner Corner; | ||
| 5 | typedef enum edge Edge; | ||
| 6 | typedef enum move Move; | ||
| 7 | typedef enum trans Trans; | ||
| 8 | |||
| 9 | typedef struct alg Alg; | ||
| 10 | typedef struct alglist AlgList; | ||
| 11 | typedef struct alglistnode AlgListNode; | ||
| 12 | typedef struct block Block; | ||
| 13 | typedef struct cachedata CacheData; | ||
| 14 | typedef struct cachenode CacheNode; | ||
| 15 | typedef struct cube Cube; | ||
| 16 | typedef struct cubearray CubeArray; | ||
| 17 | typedef struct dfsdata DfsData; | ||
| 18 | typedef struct piecefilter PieceFilter; | ||
| 19 | typedef struct prunedata PruneData; | ||
| 20 | typedef struct solveoptions SolveOptions; | ||
| 21 | typedef struct step Step; | ||
| 22 | |||
| 23 | typedef int (*Checker)(Cube); | ||
| 24 | typedef uint64_t (*Indexer)(Cube); | ||
| 25 | typedef bool (*Moveset)(Move); | ||
| 26 | |||
| 27 | |||
| 28 | /* Enums *********************************************************************/ | ||
| 29 | |||
| 30 | enum | ||
| 31 | center | ||
| 32 | { | ||
| 33 | U_center, D_center, | ||
| 34 | R_center, L_center, | ||
| 35 | F_center, B_center | ||
| 36 | }; | ||
| 37 | |||
| 38 | enum | ||
| 39 | corner | ||
| 40 | { | ||
| 41 | UFR, UFL, UBL, UBR, | ||
| 42 | DFR, DFL, DBL, DBR | ||
| 43 | }; | ||
| 44 | |||
| 45 | enum | ||
| 46 | edge | ||
| 47 | { | ||
| 48 | UF, UL, UB, UR, | ||
| 49 | DF, DL, DB, DR, | ||
| 50 | FR, FL, BL, BR | ||
| 51 | }; | ||
| 52 | |||
| 53 | enum | ||
| 54 | move | ||
| 55 | { | ||
| 56 | NULLMOVE, | ||
| 57 | U, U2, U3, D, D2, D3, | ||
| 58 | R, R2, R3, L, L2, L3, | ||
| 59 | F, F2, F3, B, B2, B3, | ||
| 60 | Uw, Uw2, Uw3, Dw, Dw2, Dw3, | ||
| 61 | Rw, Rw2, Rw3, Lw, Lw2, Lw3, | ||
| 62 | Fw, Fw2, Fw3, Bw, Bw2, Bw3, | ||
| 63 | M, M2, M3, | ||
| 64 | S, S2, S3, | ||
| 65 | E, E2, E3, | ||
| 66 | x, x2, x3, | ||
| 67 | y, y2, y3, | ||
| 68 | z, z2, z3, | ||
| 69 | }; | ||
| 70 | |||
| 71 | enum | ||
| 72 | trans | ||
| 73 | { | ||
| 74 | uf, ur, ub, ul, | ||
| 75 | df, dr, db, dl, | ||
| 76 | rf, rd, rb, ru, | ||
| 77 | lf, ld, lb, lu, | ||
| 78 | fu, fr, fd, fl, | ||
| 79 | bu, br, bd, bl, | ||
| 80 | mirror, /* R|L */ | ||
| 81 | }; | ||
| 82 | |||
| 83 | |||
| 84 | /* Structs *******************************************************************/ | ||
| 85 | |||
| 86 | struct | ||
| 87 | alg | ||
| 88 | { | ||
| 89 | Move * move; | ||
| 90 | bool * inv; | ||
| 91 | int len; | ||
| 92 | int allocated; | ||
| 93 | }; | ||
| 94 | |||
| 95 | struct | ||
| 96 | alglist | ||
| 97 | { | ||
| 98 | AlgListNode * first; | ||
| 99 | AlgListNode * last; | ||
| 100 | int len; | ||
| 101 | }; | ||
| 102 | |||
| 103 | struct | ||
| 104 | alglistnode | ||
| 105 | { | ||
| 106 | Alg * alg; | ||
| 107 | AlgListNode * next; | ||
| 108 | }; | ||
| 109 | |||
| 110 | struct | ||
| 111 | block | ||
| 112 | { | ||
| 113 | bool edge[12]; | ||
| 114 | bool corner[8]; | ||
| 115 | bool center[6]; | ||
| 116 | }; | ||
| 117 | |||
| 118 | struct | ||
| 119 | cachedata | ||
| 120 | { | ||
| 121 | char * filename; | ||
| 122 | CacheNode ** ctable; | ||
| 123 | bool generated; | ||
| 124 | uint64_t maxind0; | ||
| 125 | int len; | ||
| 126 | int nind; | ||
| 127 | Indexer index[20]; /* Should be enough */ | ||
| 128 | Checker check; | ||
| 129 | Moveset moveset; | ||
| 130 | }; | ||
| 131 | |||
| 132 | struct | ||
| 133 | cachenode | ||
| 134 | { | ||
| 135 | uint64_t * indexval; | ||
| 136 | Alg * sol; | ||
| 137 | CacheNode * next; | ||
| 138 | }; | ||
| 139 | |||
| 140 | struct | ||
| 141 | cube | ||
| 142 | { | ||
| 143 | uint16_t epose; | ||
| 144 | uint16_t eposs; | ||
| 145 | uint16_t eposm; | ||
| 146 | uint16_t eofb; | ||
| 147 | uint16_t eorl; | ||
| 148 | uint16_t eoud; | ||
| 149 | uint16_t cp; | ||
| 150 | uint16_t coud; | ||
| 151 | uint16_t cofb; | ||
| 152 | uint16_t corl; | ||
| 153 | uint16_t cpos; | ||
| 154 | }; | ||
| 155 | |||
| 156 | struct | ||
| 157 | cubearray | ||
| 158 | { | ||
| 159 | int * ep; | ||
| 160 | int * eofb; | ||
| 161 | int * eorl; | ||
| 162 | int * eoud; | ||
| 163 | int * cp; | ||
| 164 | int * coud; | ||
| 165 | int * corl; | ||
| 166 | int * cofb; | ||
| 167 | int * cpos; | ||
| 168 | }; | ||
| 169 | |||
| 170 | struct | ||
| 171 | dfsdata | ||
| 172 | { | ||
| 173 | int d; | ||
| 174 | int m; | ||
| 175 | bool niss; | ||
| 176 | Move last1; | ||
| 177 | Move last2; | ||
| 178 | AlgList * sols; | ||
| 179 | Alg * current_alg; | ||
| 180 | Move sorted_moves[NMOVES]; | ||
| 181 | int move_position[NMOVES]; | ||
| 182 | }; | ||
| 183 | |||
| 184 | struct | ||
| 185 | piecefilter | ||
| 186 | { | ||
| 187 | bool epose; | ||
| 188 | bool eposs; | ||
| 189 | bool eposm; | ||
| 190 | bool eofb; | ||
| 191 | bool eorl; | ||
| 192 | bool eoud; | ||
| 193 | bool cp; | ||
| 194 | bool coud; | ||
| 195 | bool cofb; | ||
| 196 | bool corl; | ||
| 197 | bool cpos; | ||
| 198 | }; | ||
| 199 | |||
| 200 | struct | ||
| 201 | prunedata | ||
| 202 | { | ||
| 203 | char * filename; | ||
| 204 | uint8_t * ptable; | ||
| 205 | uint8_t * reached; | ||
| 206 | bool generated; | ||
| 207 | uint64_t n; | ||
| 208 | uint64_t size; | ||
| 209 | Indexer index; | ||
| 210 | Moveset moveset; | ||
| 211 | }; | ||
| 212 | |||
| 213 | struct | ||
| 214 | solveoptions | ||
| 215 | { | ||
| 216 | int min_moves; | ||
| 217 | int max_moves; | ||
| 218 | int max_solutions; | ||
| 219 | bool optimal_only; | ||
| 220 | bool can_niss; | ||
| 221 | bool feedback; | ||
| 222 | Trans pre_trans; | ||
| 223 | }; | ||
| 224 | |||
| 225 | struct | ||
| 226 | step | ||
| 227 | { | ||
| 228 | Checker check; | ||
| 229 | Checker ready; | ||
| 230 | Moveset moveset; | ||
| 231 | CacheData * cd; | ||
| 232 | }; | ||
diff --git a/old/2021-06-17-cachedata/main.c b/old/2021-06-17-cachedata/main.c new file mode 100644 index 0000000..bd69ac9 --- /dev/null +++ b/old/2021-06-17-cachedata/main.c | |||
| @@ -0,0 +1,63 @@ | |||
| 1 | #include <stdio.h> | ||
| 2 | #include "cube.h" | ||
| 3 | #include "steps.h" | ||
| 4 | |||
| 5 | int main() { | ||
| 6 | Alg *algo; | ||
| 7 | AlgList *sols; | ||
| 8 | Cube cube; | ||
| 9 | SolveOptions opts; | ||
| 10 | char line[1000]; | ||
| 11 | int i, ns = 3; /*, nrand = 100000, sum1, sum2;*/ | ||
| 12 | |||
| 13 | Step *stps[20] = {&eofb_HTM, &corners_URF, &optimal_HTM}; | ||
| 14 | char sss[30][30] = {"EO on F/B", "Corners URF", "Optimal solution"}; | ||
| 15 | |||
| 16 | opts = (SolveOptions) { | ||
| 17 | .min_moves = 0, | ||
| 18 | .max_moves = 20, | ||
| 19 | .optimal_only = true, | ||
| 20 | .max_solutions = 1, | ||
| 21 | .can_niss = false, | ||
| 22 | .feedback = true, | ||
| 23 | .pre_trans = uf | ||
| 24 | }; | ||
| 25 | |||
| 26 | init(); | ||
| 27 | |||
| 28 | /* | ||
| 29 | print_ptable(&pd_corners_HTM); | ||
| 30 | |||
| 31 | srand(time(NULL)); | ||
| 32 | sum1 = 0; | ||
| 33 | sum2 = 0; | ||
| 34 | for (i = 0; i < nrand; i++) { | ||
| 35 | sum1 += optimal_HTM.check(random_cube()); | ||
| 36 | sum2 += corners_HTM.check(random_cube()); | ||
| 37 | } | ||
| 38 | printf("Average optimal pruning: %lf\n", ((double)sum1) / ((double) nrand)); | ||
| 39 | printf("Average corners pruning: %lf\n", ((double)sum2) / ((double) nrand)); | ||
| 40 | */ | ||
| 41 | |||
| 42 | print_cachedata(&cd_optimal_HTM_6, false); | ||
| 43 | |||
| 44 | printf("Welcome to nissy 2.0! Insert a scramble:\n"); | ||
| 45 | |||
| 46 | if (fgets(line, 1000, stdin) != NULL) { | ||
| 47 | algo = new_alg(line); | ||
| 48 | cube = apply_alg(algo, (Cube){0}); | ||
| 49 | |||
| 50 | for (i = 0; i < ns; i++) { | ||
| 51 | if (stps[i]->check == NULL) | ||
| 52 | fprintf(stderr, "Check function for step %d is null\n", i); | ||
| 53 | sols = solve(cube, *stps[i], &opts); | ||
| 54 | printf("%s: %d solutions found:\n", sss[i], sols->len); | ||
| 55 | print_alglist(sols, true); | ||
| 56 | free_alglist(sols); | ||
| 57 | } | ||
| 58 | free(algo); | ||
| 59 | } | ||
| 60 | |||
| 61 | return 0; | ||
| 62 | } | ||
| 63 | |||
diff --git a/old/2021-06-17-cachedata/steps.c b/old/2021-06-17-cachedata/steps.c new file mode 100644 index 0000000..f1001e6 --- /dev/null +++ b/old/2021-06-17-cachedata/steps.c | |||
| @@ -0,0 +1,327 @@ | |||
| 1 | #include "steps.h" | ||
| 2 | |||
| 3 | /* Check functions ***********************************************************/ | ||
| 4 | |||
| 5 | static int check_nothing(Cube cube); | ||
| 6 | static int check_eofb_HTM(Cube cube); | ||
| 7 | static int check_coud_HTM(Cube cube); | ||
| 8 | static int check_coud_URF(Cube cube); | ||
| 9 | static int check_corners_HTM(Cube cube); | ||
| 10 | static int check_corners_URF(Cube cube); | ||
| 11 | static int check_edges_HTM(Cube cube); | ||
| 12 | static int check_drud_HTM(Cube cube); | ||
| 13 | static int check_optimal_HTM(Cube cube); | ||
| 14 | |||
| 15 | |||
| 16 | /* Index functions ***********************************************************/ | ||
| 17 | |||
| 18 | static uint64_t index_eofb(Cube cube); | ||
| 19 | static uint64_t index_coud(Cube cube); | ||
| 20 | static uint64_t index_corners(Cube cube); | ||
| 21 | static uint64_t index_ep(Cube cube); | ||
| 22 | static uint64_t index_drud(Cube cube); | ||
| 23 | |||
| 24 | |||
| 25 | /* Steps *********************************************************************/ | ||
| 26 | |||
| 27 | Step | ||
| 28 | eofb_HTM = { | ||
| 29 | .check = check_eofb_HTM, | ||
| 30 | .ready = check_nothing, | ||
| 31 | .moveset = moveset_HTM | ||
| 32 | }; | ||
| 33 | |||
| 34 | Step | ||
| 35 | coud_HTM = { | ||
| 36 | .check = check_coud_HTM, | ||
| 37 | .ready = check_nothing, | ||
| 38 | .moveset = moveset_HTM | ||
| 39 | }; | ||
| 40 | |||
| 41 | Step | ||
| 42 | coud_URF = { | ||
| 43 | .check = check_coud_URF, | ||
| 44 | .ready = check_nothing, | ||
| 45 | .moveset = moveset_URF | ||
| 46 | }; | ||
| 47 | |||
| 48 | Step | ||
| 49 | corners_HTM = { | ||
| 50 | .check = check_corners_HTM, | ||
| 51 | .ready = check_nothing, | ||
| 52 | .moveset = moveset_HTM | ||
| 53 | }; | ||
| 54 | |||
| 55 | Step | ||
| 56 | corners_URF = { | ||
| 57 | .check = check_corners_URF, | ||
| 58 | .ready = check_nothing, | ||
| 59 | .moveset = moveset_URF | ||
| 60 | }; | ||
| 61 | |||
| 62 | Step | ||
| 63 | edges_HTM = { | ||
| 64 | .check = check_edges_HTM, | ||
| 65 | .ready = check_nothing, | ||
| 66 | .moveset = moveset_HTM | ||
| 67 | }; | ||
| 68 | |||
| 69 | Step | ||
| 70 | drud_HTM = { | ||
| 71 | .check = check_drud_HTM, | ||
| 72 | .ready = check_nothing, | ||
| 73 | .moveset = moveset_HTM | ||
| 74 | }; | ||
| 75 | |||
| 76 | Step | ||
| 77 | optimal_HTM = { | ||
| 78 | .check = check_optimal_HTM, | ||
| 79 | .ready = check_nothing, | ||
| 80 | .moveset = moveset_HTM, | ||
| 81 | .cd = &cd_optimal_HTM_6 | ||
| 82 | }; | ||
| 83 | |||
| 84 | |||
| 85 | /* Cache solutions ***********************************************************/ | ||
| 86 | |||
| 87 | CacheData | ||
| 88 | cd_optimal_HTM_6 = { | ||
| 89 | .filename = "cd_optimal_HTM_6", | ||
| 90 | .maxind0 = POW3TO7 * FACTORIAL8, | ||
| 91 | .len = 6, | ||
| 92 | .nind = 3, | ||
| 93 | .index = { index_corners, index_eofb, index_ep }, | ||
| 94 | .moveset = moveset_HTM | ||
| 95 | }; | ||
| 96 | |||
| 97 | |||
| 98 | /* Pruning tables ************************************************************/ | ||
| 99 | |||
| 100 | PruneData | ||
| 101 | pd_eofb_HTM = { | ||
| 102 | .filename = "ptable_eofb_HTM", | ||
| 103 | .size = POW2TO11, | ||
| 104 | .index = index_eofb, | ||
| 105 | .moveset = moveset_HTM | ||
| 106 | }; | ||
| 107 | |||
| 108 | PruneData | ||
| 109 | pd_coud_HTM = { | ||
| 110 | .filename = "ptable_coud_HTM", | ||
| 111 | .size = POW3TO7, | ||
| 112 | .index = index_coud, | ||
| 113 | .moveset = moveset_HTM | ||
| 114 | }; | ||
| 115 | |||
| 116 | PruneData | ||
| 117 | pd_corners_HTM = { | ||
| 118 | .filename = "ptable_corners_HTM", | ||
| 119 | .size = POW3TO7 * FACTORIAL8, | ||
| 120 | .index = index_corners, | ||
| 121 | .moveset = moveset_HTM | ||
| 122 | }; | ||
| 123 | |||
| 124 | PruneData | ||
| 125 | pd_ep_HTM = { | ||
| 126 | .filename = "ptable_ep_HTM", | ||
| 127 | .size = FACTORIAL12, | ||
| 128 | .index = index_ep, | ||
| 129 | .moveset = moveset_HTM | ||
| 130 | }; | ||
| 131 | |||
| 132 | PruneData | ||
| 133 | pd_drud_HTM = { | ||
| 134 | .filename = "ptable_drud_HTM", | ||
| 135 | .size = POW2TO11 * POW3TO7 * BINOM12ON4, | ||
| 136 | .index = index_drud, | ||
| 137 | .moveset = moveset_HTM | ||
| 138 | }; | ||
| 139 | |||
| 140 | |||
| 141 | /* Check functions implementation ********************************************/ | ||
| 142 | |||
| 143 | static int | ||
| 144 | check_nothing(Cube cube) | ||
| 145 | { | ||
| 146 | /* At least we check that it is admissible */ | ||
| 147 | return is_admissible(cube); | ||
| 148 | } | ||
| 149 | |||
| 150 | static int | ||
| 151 | check_eofb_HTM(Cube cube) | ||
| 152 | { | ||
| 153 | if (!pd_eofb_HTM.generated) | ||
| 154 | generate_ptable(&pd_eofb_HTM); | ||
| 155 | |||
| 156 | return PTABLEVAL(pd_eofb_HTM.ptable, cube.eofb); | ||
| 157 | } | ||
| 158 | |||
| 159 | static int | ||
| 160 | check_coud_HTM(Cube cube) | ||
| 161 | { | ||
| 162 | if (!pd_coud_HTM.generated) | ||
| 163 | generate_ptable(&pd_coud_HTM); | ||
| 164 | |||
| 165 | return PTABLEVAL(pd_coud_HTM.ptable, cube.coud); | ||
| 166 | } | ||
| 167 | |||
| 168 | static int | ||
| 169 | check_coud_URF(Cube cube) | ||
| 170 | { | ||
| 171 | /* TODO: I can improve this by checking first the orientation of | ||
| 172 | * the corner in DBL and use that as a reference */ | ||
| 173 | |||
| 174 | int ud = check_coud_HTM(cube); | ||
| 175 | int rl = check_coud_HTM(apply_move(z, cube)); | ||
| 176 | int fb = check_coud_HTM(apply_move(x, cube)); | ||
| 177 | |||
| 178 | return MIN(ud, MIN(rl, fb)); | ||
| 179 | } | ||
| 180 | |||
| 181 | static int | ||
| 182 | check_corners_HTM(Cube cube) | ||
| 183 | { | ||
| 184 | if (!pd_corners_HTM.generated) | ||
| 185 | generate_ptable(&pd_corners_HTM); | ||
| 186 | |||
| 187 | return PTABLEVAL(pd_corners_HTM.ptable, index_corners(cube)); | ||
| 188 | } | ||
| 189 | |||
| 190 | static int | ||
| 191 | check_corners_URF(Cube cube) | ||
| 192 | { | ||
| 193 | /* TODO: I can improve this by checking first the corner in DBL | ||
| 194 | * and use that as a reference */ | ||
| 195 | |||
| 196 | int ret = 15; | ||
| 197 | Trans i; | ||
| 198 | |||
| 199 | for (i = 0; i < NROTATIONS; i++) | ||
| 200 | ret = MIN(ret,check_corners_HTM(apply_alg(trans_alg(i),cube))); | ||
| 201 | |||
| 202 | return ret; | ||
| 203 | } | ||
| 204 | |||
| 205 | static int | ||
| 206 | check_edges_HTM(Cube cube) | ||
| 207 | { | ||
| 208 | int ret = 0; | ||
| 209 | |||
| 210 | if (!pd_ep_HTM.generated) | ||
| 211 | generate_ptable(&pd_ep_HTM); | ||
| 212 | |||
| 213 | ret = MAX(ret, PTABLEVAL(pd_ep_HTM.ptable, index_ep(cube))); | ||
| 214 | ret = MAX(ret, check_eofb_HTM(cube)); | ||
| 215 | ret = MAX(ret, check_eofb_HTM(apply_trans(ur, cube))); | ||
| 216 | ret = MAX(ret, check_eofb_HTM(apply_trans(fd, cube))); | ||
| 217 | |||
| 218 | return ret; | ||
| 219 | } | ||
| 220 | |||
| 221 | static int | ||
| 222 | check_drud_HTM(Cube cube) | ||
| 223 | { | ||
| 224 | if (!pd_drud_HTM.generated) | ||
| 225 | generate_ptable(&pd_drud_HTM); | ||
| 226 | |||
| 227 | return PTABLEVAL(pd_drud_HTM.ptable, index_drud(cube)); | ||
| 228 | } | ||
| 229 | |||
| 230 | static int | ||
| 231 | check_optimal_HTM(Cube cube) | ||
| 232 | { | ||
| 233 | int dr1, dr2, dr3, drmax, cor; /*ep;*/ | ||
| 234 | |||
| 235 | if (!pd_drud_HTM.generated) | ||
| 236 | generate_ptable(&pd_drud_HTM); | ||
| 237 | if (!pd_corners_HTM.generated) | ||
| 238 | generate_ptable(&pd_corners_HTM); | ||
| 239 | /* | ||
| 240 | *if (!pd_ep_HTM.generated) | ||
| 241 | * generate_ptable(&pd_ep_HTM); | ||
| 242 | */ | ||
| 243 | |||
| 244 | dr1 = PTABLEVAL(pd_drud_HTM.ptable, index_drud(cube)); | ||
| 245 | dr2 = PTABLEVAL(pd_drud_HTM.ptable, index_drud(apply_trans(rf, cube))); | ||
| 246 | dr3 = PTABLEVAL(pd_drud_HTM.ptable, index_drud(apply_trans(fd, cube))); | ||
| 247 | |||
| 248 | drmax = MAX(dr1, MAX(dr2, dr3)); | ||
| 249 | if (dr1 == dr2 && dr2 == dr3 && dr1 != 0) | ||
| 250 | drmax++; | ||
| 251 | |||
| 252 | cor = PTABLEVAL(pd_corners_HTM.ptable, index_corners(cube)); | ||
| 253 | /* ep = PTABLEVAL(pd_ep_HTM.ptable, index_ep(cube)); */ | ||
| 254 | |||
| 255 | /*return MAX(drmax, MAX(ep, cor));*/ | ||
| 256 | if (drmax == 0 && cor == 0) | ||
| 257 | return is_solved(cube, false) ? 0 : 1; | ||
| 258 | return MAX(drmax, cor); | ||
| 259 | } | ||
| 260 | |||
| 261 | |||
| 262 | /* Index functions implementation ********************************************/ | ||
| 263 | |||
| 264 | static uint64_t | ||
| 265 | index_eofb(Cube cube) | ||
| 266 | { | ||
| 267 | return cube.eofb; | ||
| 268 | } | ||
| 269 | |||
| 270 | static uint64_t | ||
| 271 | index_coud(Cube cube) | ||
| 272 | { | ||
| 273 | return cube.coud; | ||
| 274 | } | ||
| 275 | |||
| 276 | static uint64_t | ||
| 277 | index_corners(Cube cube) | ||
| 278 | { | ||
| 279 | return cube.coud * FACTORIAL8 + cube.cp; | ||
| 280 | } | ||
| 281 | |||
| 282 | static uint64_t | ||
| 283 | index_ep(Cube cube) | ||
| 284 | { | ||
| 285 | uint64_t a, b, c; | ||
| 286 | |||
| 287 | a = cube.eposs; | ||
| 288 | b = (cube.epose % FACTORIAL4) + epos_dependent_cube(cube)*FACTORIAL4; | ||
| 289 | c = cube.eposm % FACTORIAL4; | ||
| 290 | |||
| 291 | b *= FACTORIAL4 * BINOM12ON4; | ||
| 292 | c *= FACTORIAL4 * BINOM12ON4 * FACTORIAL4 * BINOM8ON4; | ||
| 293 | |||
| 294 | return a + b + c; | ||
| 295 | } | ||
| 296 | |||
| 297 | static uint64_t | ||
| 298 | index_drud(Cube cube) | ||
| 299 | { | ||
| 300 | uint64_t a, b, c; | ||
| 301 | |||
| 302 | a = cube.eofb; | ||
| 303 | b = cube.coud; | ||
| 304 | c = cube.epose / FACTORIAL4; | ||
| 305 | |||
| 306 | b *= POW2TO11; | ||
| 307 | c *= POW2TO11 * POW3TO7; | ||
| 308 | |||
| 309 | return a + b + c; | ||
| 310 | } | ||
| 311 | |||
| 312 | /* Movesets ******************************************************************/ | ||
| 313 | |||
| 314 | bool | ||
| 315 | moveset_HTM(Move m) | ||
| 316 | { | ||
| 317 | return m >= U && m <= B3; | ||
| 318 | } | ||
| 319 | |||
| 320 | bool | ||
| 321 | moveset_URF(Move m) | ||
| 322 | { | ||
| 323 | Move b = base_move(m); | ||
| 324 | |||
| 325 | return b == U || b == R || b == F; | ||
| 326 | } | ||
| 327 | |||
diff --git a/old/2021-06-17-cachedata/steps.h b/old/2021-06-17-cachedata/steps.h new file mode 100644 index 0000000..66a31a8 --- /dev/null +++ b/old/2021-06-17-cachedata/steps.h | |||
| @@ -0,0 +1,34 @@ | |||
| 1 | #ifndef STEPS_H | ||
| 2 | #define STEPS_H | ||
| 3 | |||
| 4 | #include "cube.h" | ||
| 5 | |||
| 6 | /* Steps *********************************************************************/ | ||
| 7 | |||
| 8 | extern Step eofb_HTM; | ||
| 9 | extern Step coud_HTM; | ||
| 10 | extern Step coud_URF; | ||
| 11 | extern Step corners_HTM; | ||
| 12 | extern Step corners_URF; | ||
| 13 | extern Step edges_HTM; | ||
| 14 | extern Step drud_HTM; | ||
| 15 | extern Step optimal_HTM; | ||
| 16 | |||
| 17 | /* Cache solutions ***********************************************************/ | ||
| 18 | |||
| 19 | extern CacheData cd_optimal_HTM_6; | ||
| 20 | |||
| 21 | /* Pruning tables ************************************************************/ | ||
| 22 | |||
| 23 | extern PruneData pd_eofb_HTM; | ||
| 24 | extern PruneData pd_coud_HTM; | ||
| 25 | extern PruneData pd_corners_HTM; | ||
| 26 | extern PruneData pd_ep_HTM; | ||
| 27 | extern PruneData pd_drud_HTM; | ||
| 28 | |||
| 29 | /* Movesets ******************************************************************/ | ||
| 30 | |||
| 31 | bool moveset_HTM(Move m); | ||
| 32 | bool moveset_URF(Move m); | ||
| 33 | |||
| 34 | #endif | ||
diff --git a/old/2021-06-23-realizing-bad-tables/HERE b/old/2021-06-23-realizing-bad-tables/HERE new file mode 100644 index 0000000..487e305 --- /dev/null +++ b/old/2021-06-23-realizing-bad-tables/HERE | |||
| @@ -0,0 +1 @@ | |||
| Here you can also find some tables data that I have removed, like ep and tripleeo | |||
diff --git a/old/2021-06-23-realizing-bad-tables/cube.c b/old/2021-06-23-realizing-bad-tables/cube.c new file mode 100644 index 0000000..4e60bb2 --- /dev/null +++ b/old/2021-06-23-realizing-bad-tables/cube.c | |||
| @@ -0,0 +1,2844 @@ | |||
| 1 | #include "cube.h" | ||
| 2 | |||
| 3 | /* Local functions **********************************************************/ | ||
| 4 | |||
| 5 | static Cube admissible_ep(Cube cube, PieceFilter f); | ||
| 6 | static bool allowed_next(Move move, DfsData *dd); | ||
| 7 | static void append_alg(AlgList *l, Alg *alg); | ||
| 8 | static void append_move(Alg *alg, Move m, bool inverse); | ||
| 9 | static Cube apply_alg_generic(Alg *alg, Cube c, PieceFilter f, bool a); | ||
| 10 | static void apply_permutation(int *perm, int *set, int n); | ||
| 11 | static Cube apply_move_cubearray(Move m, Cube cube, PieceFilter f); | ||
| 12 | static int array_ep_to_epos(int *ep, int *eps_solved); | ||
| 13 | static Cube arrays_to_cube(CubeArray *arr, PieceFilter f); | ||
| 14 | static int binomial(int n, int k); | ||
| 15 | static Cube compose_filtered(Cube c2, Cube c1, PieceFilter f); | ||
| 16 | static void cube_to_arrays(Cube cube, CubeArray *arr, PieceFilter f); | ||
| 17 | static void dfs(Cube c, Step s, SolveOptions *opts, DfsData *dd); | ||
| 18 | static void dfs_branch(Cube c, Step s, SolveOptions *opts, DfsData *dd); | ||
| 19 | static bool dfs_check_solved(SolveOptions *opts, DfsData *dd); | ||
| 20 | static void dfs_niss(Cube c, Step s, SolveOptions *opts, DfsData *dd); | ||
| 21 | static bool dfs_stop(Cube c, Step s, SolveOptions *opts, DfsData *dd); | ||
| 22 | static int digit_array_to_int(int *a, int n, int b); | ||
| 23 | static int edge_slice(Edge e); /* E=0, S=1, M=2 */ | ||
| 24 | static int epos_dependent_pos(int pos1, int pos2); | ||
| 25 | static int epos_from_arrays(int *epos, int *ep); | ||
| 26 | static void epos_to_partial_ep(int epos, int *ep, int *ss); | ||
| 27 | static int factorial(int n); | ||
| 28 | static void free_alglistnode(AlgListNode *aln); | ||
| 29 | static void free_cubearray(CubeArray *arr, PieceFilter f); | ||
| 30 | static void genptable_dfs(Cube c, PruneData *pd, DfsData *dd); | ||
| 31 | static void genptable_dfs_branch(Cube c, PruneData *pd, DfsData *dd); | ||
| 32 | static void index_to_perm(int p, int n, int *r); | ||
| 33 | static void index_to_subset(int s, int n, int k, int *r); | ||
| 34 | static void int_to_digit_array(int a, int b, int n, int *r); | ||
| 35 | static void int_to_sum_zero_array(int x, int b, int n, int *a); | ||
| 36 | static int invert_digits(int a, int b, int n); | ||
| 37 | static bool is_perm(int *a, int n); | ||
| 38 | static bool is_subset(int *a, int n, int k); | ||
| 39 | static Cube move_via_arrays(CubeArray *arr, Cube c, PieceFilter pf); | ||
| 40 | static void movelist_to_position(Move *movelist, int *position); | ||
| 41 | static void moveset_to_list(Moveset ms, Checker f, Move *r); | ||
| 42 | static AlgList * new_alglist(); | ||
| 43 | static CubeArray * new_cubearray(Cube cube, PieceFilter f); | ||
| 44 | static int perm_sign(int *a, int n); | ||
| 45 | static int perm_to_index(int *a, int n); | ||
| 46 | static int powint(int a, int b); | ||
| 47 | static bool ptable_has_reached(PruneData *pd, uint64_t ind); | ||
| 48 | static void ptable_set_reached(PruneData *pd, uint64_t ind); | ||
| 49 | static void ptable_update(PruneData *pd, uint64_t ind, int m); | ||
| 50 | static void realloc_alg(Alg *alg, int n); | ||
| 51 | static bool read_algset_file(AlgSet *as); | ||
| 52 | static bool read_mtables_file(); | ||
| 53 | static bool read_ptable_file(PruneData *pd); | ||
| 54 | static bool read_ttables_file(); | ||
| 55 | static Cube rotate_via_compose(Trans r, Cube c, PieceFilter f); | ||
| 56 | static int subset_to_index(int *a, int n, int k); | ||
| 57 | static void sum_arrays_mod(int *src, int *dst, int n, int m); | ||
| 58 | static void swap(int *a, int *b); | ||
| 59 | static bool write_algset_file(AlgSet *as); | ||
| 60 | static bool write_mtables_file(); | ||
| 61 | static bool write_ptable_file(PruneData *pd); | ||
| 62 | static bool write_ttables_file(); | ||
| 63 | |||
| 64 | static void init_auxtables(); | ||
| 65 | static void init_cphtr_cosets(); | ||
| 66 | static void init_cphtr_cosets_bfs(int i, int c); | ||
| 67 | static void init_environment(); | ||
| 68 | static void init_moves(); | ||
| 69 | static void init_moves_aux(); | ||
| 70 | static void init_strings(); | ||
| 71 | static void init_trans(); | ||
| 72 | static void init_trans_aux(); | ||
| 73 | |||
| 74 | /* All sorts of useful costants and tables **********************************/ | ||
| 75 | |||
| 76 | static char * tabledir; | ||
| 77 | |||
| 78 | static PieceFilter pf_all; | ||
| 79 | static PieceFilter pf_4val; | ||
| 80 | static PieceFilter pf_epcp; | ||
| 81 | static PieceFilter pf_cpos; | ||
| 82 | static PieceFilter pf_cp; | ||
| 83 | static PieceFilter pf_ep; | ||
| 84 | static PieceFilter pf_e; | ||
| 85 | static PieceFilter pf_s; | ||
| 86 | static PieceFilter pf_m; | ||
| 87 | static PieceFilter pf_eo; | ||
| 88 | static PieceFilter pf_co; | ||
| 89 | |||
| 90 | static int epe_solved[4]; | ||
| 91 | static int eps_solved[4]; | ||
| 92 | static int epm_solved[4]; | ||
| 93 | |||
| 94 | static char move_string[NMOVES][7]; | ||
| 95 | static char edge_string[12][7]; | ||
| 96 | static char corner_string[8][7]; | ||
| 97 | static char center_string[6][7]; | ||
| 98 | |||
| 99 | static bool commute[NMOVES][NMOVES]; | ||
| 100 | static bool possible_next[NMOVES][NMOVES][NMOVES]; | ||
| 101 | static Move inverse_move_aux[NMOVES]; | ||
| 102 | static Trans inverse_trans_aux[NTRANS]; | ||
| 103 | static int epos_dependent_aux[BINOM12ON4][BINOM12ON4]; | ||
| 104 | static int cphtr_cosets[FACTORIAL8]; | ||
| 105 | static Center what_center_at_aux[FACTORIAL6][6]; | ||
| 106 | static Corner what_corner_at_aux[FACTORIAL8][8]; | ||
| 107 | static int what_orientation_last_corner_aux[POW3TO7]; | ||
| 108 | static int what_orientation_last_edge_aux[POW2TO11]; | ||
| 109 | static Center where_is_center_aux[FACTORIAL6][6]; | ||
| 110 | static Corner where_is_corner_aux[FACTORIAL8][8]; | ||
| 111 | static Edge where_is_edge_aux[3][FACTORIAL12/FACTORIAL8][12]; | ||
| 112 | |||
| 113 | static int epose_ttable[NTRANS][FACTORIAL12/FACTORIAL8]; | ||
| 114 | static int eposs_ttable[NTRANS][FACTORIAL12/FACTORIAL8]; | ||
| 115 | static int eposm_ttable[NTRANS][FACTORIAL12/FACTORIAL8]; | ||
| 116 | static int eo_ttable[NTRANS][POW2TO11]; | ||
| 117 | static int cp_ttable[NTRANS][FACTORIAL8]; | ||
| 118 | static int co_ttable[NTRANS][POW3TO7]; | ||
| 119 | static int cpos_ttable[NTRANS][FACTORIAL6]; | ||
| 120 | static Move moves_ttable[NTRANS][NMOVES]; | ||
| 121 | |||
| 122 | static int epose_mtable[NMOVES][FACTORIAL12/FACTORIAL8]; | ||
| 123 | static int eposs_mtable[NMOVES][FACTORIAL12/FACTORIAL8]; | ||
| 124 | static int eposm_mtable[NMOVES][FACTORIAL12/FACTORIAL8]; | ||
| 125 | static int eofb_mtable[NMOVES][POW2TO11]; | ||
| 126 | static int eorl_mtable[NMOVES][POW2TO11]; | ||
| 127 | static int eoud_mtable[NMOVES][POW2TO11]; | ||
| 128 | static int cp_mtable[NMOVES][FACTORIAL8]; | ||
| 129 | static int coud_mtable[NMOVES][POW3TO7]; | ||
| 130 | static int cofb_mtable[NMOVES][POW3TO7]; | ||
| 131 | static int corl_mtable[NMOVES][POW3TO7]; | ||
| 132 | static int cpos_mtable[NMOVES][FACTORIAL6]; | ||
| 133 | |||
| 134 | static uint64_t me[12]; | ||
| 135 | |||
| 136 | static int edge_cycle[NMOVES][12]; | ||
| 137 | static int corner_cycle[NMOVES][8]; | ||
| 138 | static int center_cycle[NMOVES][6]; | ||
| 139 | static int eofb_flipped[NMOVES][12]; | ||
| 140 | static int eorl_flipped[NMOVES][12]; | ||
| 141 | static int eoud_flipped[NMOVES][12]; | ||
| 142 | static int coud_flipped[NMOVES][8]; | ||
| 143 | static int corl_flipped[NMOVES][8]; | ||
| 144 | static int cofb_flipped[NMOVES][8]; | ||
| 145 | static Alg * equiv_alg[NMOVES]; | ||
| 146 | |||
| 147 | static int epose_source[NTRANS]; /* 0=epose, 1=eposs, 2=eposm */ | ||
| 148 | static int eposs_source[NTRANS]; | ||
| 149 | static int eposm_source[NTRANS]; | ||
| 150 | static int eofb_source[NTRANS]; /* 0=eoud, 1=eorl, 2=eofb */ | ||
| 151 | static int eorl_source[NTRANS]; | ||
| 152 | static int eoud_source[NTRANS]; | ||
| 153 | static int coud_source[NTRANS]; /* 0=coud, 1=corl, 2=cofb */ | ||
| 154 | static int cofb_source[NTRANS]; | ||
| 155 | static int corl_source[NTRANS]; | ||
| 156 | static int ep_mirror[12]; | ||
| 157 | static int cp_mirror[8]; | ||
| 158 | static int cpos_mirror[6]; | ||
| 159 | static Alg * trans_algs[NROTATIONS]; | ||
| 160 | |||
| 161 | |||
| 162 | /* Local functions implementation ********************************************/ | ||
| 163 | |||
| 164 | static Cube | ||
| 165 | admissible_ep(Cube cube, PieceFilter f) | ||
| 166 | { | ||
| 167 | CubeArray *arr = new_cubearray(cube, f); | ||
| 168 | Cube ret; | ||
| 169 | bool used[12] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; | ||
| 170 | int i, j; | ||
| 171 | |||
| 172 | for (i = 0; i < 12; i++) | ||
| 173 | if (arr->ep[i] != -1) | ||
| 174 | used[arr->ep[i]] = true; | ||
| 175 | |||
| 176 | for (i = 0, j = 0; i < 12; i++) { | ||
| 177 | for ( ; j < 11 && used[j]; j++); | ||
| 178 | if (arr->ep[i] == -1) | ||
| 179 | arr->ep[i] = j++; | ||
| 180 | } | ||
| 181 | |||
| 182 | ret = arrays_to_cube(arr, pf_ep); | ||
| 183 | free_cubearray(arr, f); | ||
| 184 | |||
| 185 | return ret; | ||
| 186 | } | ||
| 187 | |||
| 188 | static bool | ||
| 189 | allowed_next(Move move, DfsData *dd) | ||
| 190 | { | ||
| 191 | if (!possible_next[dd->last2][dd->last1][move]) | ||
| 192 | return false; | ||
| 193 | |||
| 194 | if (commute[dd->last1][move]) | ||
| 195 | return dd->move_position[dd->last1] < dd->move_position[move]; | ||
| 196 | |||
| 197 | return true; | ||
| 198 | } | ||
| 199 | |||
| 200 | static void | ||
| 201 | append_alg(AlgList *l, Alg *alg) | ||
| 202 | { | ||
| 203 | AlgListNode *node = malloc(sizeof(AlgListNode)); | ||
| 204 | int i; | ||
| 205 | |||
| 206 | node->alg = new_alg(""); | ||
| 207 | for (i = 0; i < alg->len; i++) | ||
| 208 | append_move(node->alg, alg->move[i], alg->inv[i]); | ||
| 209 | node->next = NULL; | ||
| 210 | |||
| 211 | if (++l->len == 1) | ||
| 212 | l->first = node; | ||
| 213 | else | ||
| 214 | l->last->next = node; | ||
| 215 | l->last = node; | ||
| 216 | } | ||
| 217 | |||
| 218 | static void | ||
| 219 | append_move(Alg *alg, Move m, bool inverse) | ||
| 220 | { | ||
| 221 | if (alg->len == alg->allocated) | ||
| 222 | realloc_alg(alg, 2*alg->len); | ||
| 223 | |||
| 224 | alg->move[alg->len] = m; | ||
| 225 | alg->inv [alg->len] = inverse; | ||
| 226 | alg->len++; | ||
| 227 | } | ||
| 228 | |||
| 229 | static Cube | ||
| 230 | apply_alg_generic(Alg *alg, Cube c, PieceFilter f, bool a) | ||
| 231 | { | ||
| 232 | Cube ret = {0}; | ||
| 233 | int i; | ||
| 234 | |||
| 235 | for (i = 0; i < alg->len; i++) | ||
| 236 | if (alg->inv[i]) | ||
| 237 | ret = a ? apply_move(alg->move[i], ret) : | ||
| 238 | apply_move_cubearray(alg->move[i], ret, f); | ||
| 239 | |||
| 240 | ret = compose_filtered(c, inverse_cube(ret), f); | ||
| 241 | |||
| 242 | for (i = 0; i < alg->len; i++) | ||
| 243 | if (!alg->inv[i]) | ||
| 244 | ret = a ? apply_move(alg->move[i], ret) : | ||
| 245 | apply_move_cubearray(alg->move[i], ret, f); | ||
| 246 | |||
| 247 | return ret; | ||
| 248 | } | ||
| 249 | |||
| 250 | static void | ||
| 251 | apply_permutation(int *perm, int *set, int n) | ||
| 252 | { | ||
| 253 | int *aux = malloc(n * sizeof(int)); | ||
| 254 | int i; | ||
| 255 | |||
| 256 | if (!is_perm(perm, n)) | ||
| 257 | return; | ||
| 258 | |||
| 259 | for (i = 0; i < n; i++) | ||
| 260 | aux[i] = set[perm[i]]; | ||
| 261 | |||
| 262 | memcpy(set, aux, n * sizeof(int)); | ||
| 263 | free(aux); | ||
| 264 | } | ||
| 265 | |||
| 266 | static Cube | ||
| 267 | apply_move_cubearray(Move m, Cube cube, PieceFilter f) | ||
| 268 | { | ||
| 269 | CubeArray m_arr = { | ||
| 270 | edge_cycle[m], | ||
| 271 | eofb_flipped[m], | ||
| 272 | eorl_flipped[m], | ||
| 273 | eoud_flipped[m], | ||
| 274 | corner_cycle[m], | ||
| 275 | coud_flipped[m], | ||
| 276 | corl_flipped[m], | ||
| 277 | cofb_flipped[m], | ||
| 278 | center_cycle[m] | ||
| 279 | }; | ||
| 280 | |||
| 281 | return move_via_arrays(&m_arr, cube, f); | ||
| 282 | } | ||
| 283 | |||
| 284 | static int | ||
| 285 | array_ep_to_epos(int *ep, int *ss) | ||
| 286 | { | ||
| 287 | int epos[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; | ||
| 288 | int eps[4]; | ||
| 289 | int i, j, is; | ||
| 290 | |||
| 291 | for (i = 0, is = 0; i < 12; i++) { | ||
| 292 | for (j = 0; j < 4; j++) { | ||
| 293 | if (ep[i] == ss[j]) { | ||
| 294 | eps[is++] = j; | ||
| 295 | epos[i] = 1; | ||
| 296 | } | ||
| 297 | } | ||
| 298 | } | ||
| 299 | |||
| 300 | for (i = 0; i < 4; i++) | ||
| 301 | swap(&epos[ss[i]], &epos[i+8]); | ||
| 302 | |||
| 303 | return epos_from_arrays(epos, eps); | ||
| 304 | } | ||
| 305 | |||
| 306 | static Cube | ||
| 307 | arrays_to_cube(CubeArray *arr, PieceFilter f) | ||
| 308 | { | ||
| 309 | Cube ret = {0}; | ||
| 310 | |||
| 311 | if (f.epose) | ||
| 312 | ret.epose = array_ep_to_epos(arr->ep, epe_solved); | ||
| 313 | if (f.eposs) | ||
| 314 | ret.eposs = array_ep_to_epos(arr->ep, eps_solved); | ||
| 315 | if (f.eposm) | ||
| 316 | ret.eposm = array_ep_to_epos(arr->ep, epm_solved); | ||
| 317 | if (f.eofb) | ||
| 318 | ret.eofb = digit_array_to_int(arr->eofb, 11, 2); | ||
| 319 | if (f.eorl) | ||
| 320 | ret.eorl = digit_array_to_int(arr->eorl, 11, 2); | ||
| 321 | if (f.eoud) | ||
| 322 | ret.eoud = digit_array_to_int(arr->eoud, 11, 2); | ||
| 323 | if (f.cp) | ||
| 324 | ret.cp = perm_to_index(arr->cp, 8); | ||
| 325 | if (f.coud) | ||
| 326 | ret.coud = digit_array_to_int(arr->coud, 7, 3); | ||
| 327 | if (f.corl) | ||
| 328 | ret.corl = digit_array_to_int(arr->corl, 7, 3); | ||
| 329 | if (f.cofb) | ||
| 330 | ret.cofb = digit_array_to_int(arr->cofb, 7, 3); | ||
| 331 | if (f.cpos) | ||
| 332 | ret.cpos = perm_to_index(arr->cpos, 6); | ||
| 333 | |||
| 334 | return ret; | ||
| 335 | } | ||
| 336 | |||
| 337 | static int | ||
| 338 | binomial(int n, int k) | ||
| 339 | { | ||
| 340 | if (n < 0 || k < 0 || k > n) | ||
| 341 | return 0; | ||
| 342 | |||
| 343 | return factorial(n) / (factorial(k) * factorial(n-k)); | ||
| 344 | } | ||
| 345 | |||
| 346 | static Cube | ||
| 347 | compose_filtered(Cube c2, Cube c1, PieceFilter f) | ||
| 348 | { | ||
| 349 | CubeArray *arr = new_cubearray(c2, f); | ||
| 350 | Cube ret; | ||
| 351 | |||
| 352 | ret = move_via_arrays(arr, c1, f); | ||
| 353 | free_cubearray(arr, f); | ||
| 354 | |||
| 355 | return ret; | ||
| 356 | } | ||
| 357 | |||
| 358 | static void | ||
| 359 | cube_to_arrays(Cube cube, CubeArray *arr, PieceFilter f) | ||
| 360 | { | ||
| 361 | int i; | ||
| 362 | |||
| 363 | if (f.epose || f.eposs || f.eposm) | ||
| 364 | for (i = 0; i < 12; i++) | ||
| 365 | arr->ep[i] = -1; | ||
| 366 | |||
| 367 | if (f.epose) | ||
| 368 | epos_to_partial_ep(cube.epose, arr->ep, epe_solved); | ||
| 369 | if (f.eposs) | ||
| 370 | epos_to_partial_ep(cube.eposs, arr->ep, eps_solved); | ||
| 371 | if (f.eposm) | ||
| 372 | epos_to_partial_ep(cube.eposm, arr->ep, epm_solved); | ||
| 373 | if (f.eofb) | ||
| 374 | int_to_sum_zero_array(cube.eofb, 2, 12, arr->eofb); | ||
| 375 | if (f.eorl) | ||
| 376 | int_to_sum_zero_array(cube.eorl, 2, 12, arr->eorl); | ||
| 377 | if (f.eoud) | ||
| 378 | int_to_sum_zero_array(cube.eoud, 2, 12, arr->eoud); | ||
| 379 | if (f.cp) | ||
| 380 | index_to_perm(cube.cp, 8, arr->cp); | ||
| 381 | if (f.coud) | ||
| 382 | int_to_sum_zero_array(cube.coud, 3, 8, arr->coud); | ||
| 383 | if (f.corl) | ||
| 384 | int_to_sum_zero_array(cube.corl, 3, 8, arr->corl); | ||
| 385 | if (f.cofb) | ||
| 386 | int_to_sum_zero_array(cube.cofb, 3, 8, arr->cofb); | ||
| 387 | if (f.cpos) | ||
| 388 | index_to_perm(cube.cpos, 6, arr->cpos); | ||
| 389 | } | ||
| 390 | |||
| 391 | /* | ||
| 392 | static int | ||
| 393 | cphtr_cp(int cp) | ||
| 394 | { | ||
| 395 | int i, a[8]; | ||
| 396 | |||
| 397 | index_to_perm(cp, 8, a); | ||
| 398 | |||
| 399 | for (i = 0; i < 8; i++) | ||
| 400 | if (a[i] == UFR || a[i] == UBL || a[i] == DFL || a[i] == DBR) | ||
| 401 | a[i] = 0; | ||
| 402 | else | ||
| 403 | a[i] = 1; | ||
| 404 | |||
| 405 | swap(&a[1], &a[5]); | ||
| 406 | swap(&a[3], &a[7]); | ||
| 407 | |||
| 408 | return subset_to_index(a, 8, 4); | ||
| 409 | } | ||
| 410 | */ | ||
| 411 | |||
| 412 | static void | ||
| 413 | dfs(Cube c, Step s, SolveOptions *opts, DfsData *dd) | ||
| 414 | { | ||
| 415 | if (dfs_stop(c, s, opts, dd)) | ||
| 416 | return; | ||
| 417 | |||
| 418 | if (dfs_check_solved(opts, dd)) | ||
| 419 | return; | ||
| 420 | |||
| 421 | dfs_branch(c, s, opts, dd); | ||
| 422 | |||
| 423 | if (opts->can_niss && !dd->niss) | ||
| 424 | dfs_niss(c, s, opts, dd); | ||
| 425 | } | ||
| 426 | |||
| 427 | static void | ||
| 428 | dfs_branch(Cube c, Step s, SolveOptions *opts, DfsData *dd) | ||
| 429 | { | ||
| 430 | Move m, l1 = dd->last1, l2 = dd->last2, *moves = dd->sorted_moves; | ||
| 431 | |||
| 432 | int i, maxnsol = opts->max_solutions; | ||
| 433 | |||
| 434 | for (i = 0; (m=moves[i]) != NULLMOVE && dd->sols->len < maxnsol; i++) { | ||
| 435 | if (allowed_next(m, dd)) { | ||
| 436 | dd->last2 = dd->last1; | ||
| 437 | dd->last1 = m; | ||
| 438 | append_move(dd->current_alg, m, dd->niss); | ||
| 439 | |||
| 440 | dfs(apply_move(m, c), s, opts, dd); | ||
| 441 | |||
| 442 | dd->current_alg->len--; | ||
| 443 | dd->last2 = l2; | ||
| 444 | dd->last1 = l1; | ||
| 445 | } | ||
| 446 | } | ||
| 447 | } | ||
| 448 | |||
| 449 | static bool | ||
| 450 | dfs_check_solved(SolveOptions *opts, DfsData *dd) | ||
| 451 | { | ||
| 452 | if (dd->lb != 0) | ||
| 453 | return false; | ||
| 454 | |||
| 455 | if (dd->current_alg->len == dd->d) { | ||
| 456 | append_alg(dd->sols, dd->current_alg); | ||
| 457 | |||
| 458 | if (opts->feedback) | ||
| 459 | print_alg(dd->current_alg, false); | ||
| 460 | } | ||
| 461 | |||
| 462 | return true; | ||
| 463 | } | ||
| 464 | |||
| 465 | static void | ||
| 466 | dfs_niss(Cube c, Step s, SolveOptions *opts, DfsData *dd) | ||
| 467 | { | ||
| 468 | Move l1 = dd->last1, l2 = dd->last2; | ||
| 469 | |||
| 470 | if (dd->current_alg->len == 0 || | ||
| 471 | (s.check(apply_move(inverse_move(l1), (Cube){0}), 1))) { | ||
| 472 | dd->niss = true; | ||
| 473 | dd->last1 = NULLMOVE; | ||
| 474 | dd->last2 = NULLMOVE; | ||
| 475 | |||
| 476 | dfs(inverse_cube(c), s, opts, dd); | ||
| 477 | |||
| 478 | dd->last1 = l1; | ||
| 479 | dd->last2 = l2; | ||
| 480 | dd->niss = false; | ||
| 481 | } | ||
| 482 | } | ||
| 483 | |||
| 484 | static bool | ||
| 485 | dfs_stop(Cube c, Step s, SolveOptions *opts, DfsData *dd) | ||
| 486 | { | ||
| 487 | if (dd->sols->len >= opts->max_solutions) | ||
| 488 | return true; | ||
| 489 | |||
| 490 | dd->lb = s.check(c, dd->d - dd->current_alg->len); | ||
| 491 | if (opts->can_niss && !dd->niss) | ||
| 492 | dd->lb = MIN(1, dd->lb); | ||
| 493 | |||
| 494 | if (dd->current_alg->len + dd->lb > dd->d) | ||
| 495 | return true; | ||
| 496 | |||
| 497 | return false; | ||
| 498 | } | ||
| 499 | |||
| 500 | static int | ||
| 501 | digit_array_to_int(int *a, int n, int b) | ||
| 502 | { | ||
| 503 | int i, ret = 0, p = 1; | ||
| 504 | |||
| 505 | for (i = 0; i < n; i++, p *= b) | ||
| 506 | ret += a[i] * p; | ||
| 507 | |||
| 508 | return ret; | ||
| 509 | } | ||
| 510 | |||
| 511 | static int | ||
| 512 | edge_slice(Edge e) { | ||
| 513 | if (e < 0 || e > 11) | ||
| 514 | return -1; | ||
| 515 | |||
| 516 | if (e == FR || e == FL || e == BL || e == BR) | ||
| 517 | return 0; | ||
| 518 | if (e == UR || e == UL || e == DR || e == DL) | ||
| 519 | return 1; | ||
| 520 | |||
| 521 | return 2; | ||
| 522 | } | ||
| 523 | |||
| 524 | static int | ||
| 525 | epos_dependent_pos(int poss, int pose) | ||
| 526 | { | ||
| 527 | int ep[12] = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}; | ||
| 528 | int ep8[8] = {0, 0, 0, 0, 0, 0, 0, 0}; | ||
| 529 | int i, j; | ||
| 530 | |||
| 531 | epos_to_partial_ep(poss*FACTORIAL4, ep, eps_solved); | ||
| 532 | epos_to_partial_ep(pose*FACTORIAL4, ep, epe_solved); | ||
| 533 | |||
| 534 | for (i = 0, j = 0; i < 12; i++) | ||
| 535 | if (edge_slice(ep[i]) != 0) | ||
| 536 | ep8[j++] = (edge_slice(ep[i]) == 1) ? 1 : 0; | ||
| 537 | |||
| 538 | swap(&ep8[1], &ep8[4]); | ||
| 539 | swap(&ep8[3], &ep8[6]); | ||
| 540 | |||
| 541 | return subset_to_index(ep8, 8, 4); | ||
| 542 | } | ||
| 543 | |||
| 544 | static int | ||
| 545 | epos_from_arrays(int *epos, int *ep) | ||
| 546 | { | ||
| 547 | return FACTORIAL4 * subset_to_index(epos,12,4) + perm_to_index(ep,4); | ||
| 548 | } | ||
| 549 | |||
| 550 | static void | ||
| 551 | epos_to_partial_ep(int epos, int *ep, int *ss) | ||
| 552 | { | ||
| 553 | int i, is, eposs[12], eps[4]; | ||
| 554 | |||
| 555 | index_to_perm(epos % FACTORIAL4, 4, eps); | ||
| 556 | index_to_subset(epos / FACTORIAL4, 12, 4, eposs); | ||
| 557 | |||
| 558 | for (i = 0; i < 4; i++) | ||
| 559 | swap(&eposs[ss[i]], &eposs[i+8]); | ||
| 560 | |||
| 561 | for (i = 0, is = 0; i < 12; i++) | ||
| 562 | if (eposs[i]) | ||
| 563 | ep[i] = ss[eps[is++]]; | ||
| 564 | } | ||
| 565 | |||
| 566 | static int | ||
| 567 | factorial(int n) | ||
| 568 | { | ||
| 569 | int i, ret = 1; | ||
| 570 | |||
| 571 | if (n < 0) | ||
| 572 | return 0; | ||
| 573 | |||
| 574 | for (i = 1; i <= n; i++) | ||
| 575 | ret *= i; | ||
| 576 | |||
| 577 | return ret; | ||
| 578 | } | ||
| 579 | |||
| 580 | void | ||
| 581 | free_alg(Alg *alg) | ||
| 582 | { | ||
| 583 | free(alg->move); | ||
| 584 | free(alg->inv); | ||
| 585 | free(alg); | ||
| 586 | } | ||
| 587 | |||
| 588 | void | ||
| 589 | free_alglist(AlgList *l) | ||
| 590 | { | ||
| 591 | AlgListNode *aux, *i = l->first; | ||
| 592 | |||
| 593 | while (i != NULL) { | ||
| 594 | aux = i->next; | ||
| 595 | free_alglistnode(i); | ||
| 596 | i = aux; | ||
| 597 | } | ||
| 598 | free(l); | ||
| 599 | } | ||
| 600 | |||
| 601 | void | ||
| 602 | free_alglistnode(AlgListNode *aln) | ||
| 603 | { | ||
| 604 | free_alg(aln->alg); | ||
| 605 | free(aln); | ||
| 606 | } | ||
| 607 | |||
| 608 | static void | ||
| 609 | free_cubearray(CubeArray *arr, PieceFilter f) | ||
| 610 | { | ||
| 611 | if (f.epose || f.eposs || f.eposm) | ||
| 612 | free(arr->ep); | ||
| 613 | if (f.eofb) | ||
| 614 | free(arr->eofb); | ||
| 615 | if (f.eorl) | ||
| 616 | free(arr->eorl); | ||
| 617 | if (f.eoud) | ||
| 618 | free(arr->eoud); | ||
| 619 | if (f.cp) | ||
| 620 | free(arr->cp); | ||
| 621 | if (f.coud) | ||
| 622 | free(arr->coud); | ||
| 623 | if (f.corl) | ||
| 624 | free(arr->corl); | ||
| 625 | if (f.cofb) | ||
| 626 | free(arr->cofb); | ||
| 627 | if (f.cpos) | ||
| 628 | free(arr->cpos); | ||
| 629 | |||
| 630 | free(arr); | ||
| 631 | } | ||
| 632 | |||
| 633 | static void | ||
| 634 | genptable_dfs(Cube c, PruneData *pd, DfsData *dd) | ||
| 635 | { | ||
| 636 | uint64_t ind = pd->index(c); | ||
| 637 | int oldval = ptableval(pd, ind); | ||
| 638 | |||
| 639 | if (oldval < dd->m || ptable_has_reached(pd, ind) || pd->n == pd->size) | ||
| 640 | return; | ||
| 641 | |||
| 642 | ptable_set_reached(pd, ind); | ||
| 643 | |||
| 644 | if (dd->m == dd->d) { | ||
| 645 | if (dd->m < oldval) | ||
| 646 | ptable_update(pd, ind, dd->m); | ||
| 647 | return; | ||
| 648 | } | ||
| 649 | |||
| 650 | genptable_dfs_branch(c, pd, dd); | ||
| 651 | } | ||
| 652 | |||
| 653 | static void | ||
| 654 | genptable_dfs_branch(Cube c, PruneData *pd, DfsData *dd) | ||
| 655 | { | ||
| 656 | Move i, move, l1 = dd->last1, l2 = dd->last2; | ||
| 657 | |||
| 658 | dd->m++; | ||
| 659 | |||
| 660 | for (i = 0; dd->sorted_moves[i] != NULLMOVE; i++) { | ||
| 661 | move = dd->sorted_moves[i]; | ||
| 662 | if (allowed_next(move, dd)) { | ||
| 663 | dd->last2 = dd->last1; | ||
| 664 | dd->last1 = move; | ||
| 665 | |||
| 666 | genptable_dfs(apply_move(move, c), pd, dd); | ||
| 667 | |||
| 668 | dd->last2 = l2; | ||
| 669 | dd->last1 = l1; | ||
| 670 | } | ||
| 671 | } | ||
| 672 | |||
| 673 | dd->m--; | ||
| 674 | } | ||
| 675 | |||
| 676 | static void | ||
| 677 | index_to_perm(int p, int n, int *r) | ||
| 678 | { | ||
| 679 | int *a = malloc(n * sizeof(int)); | ||
| 680 | int i, j, c; | ||
| 681 | |||
| 682 | for (i = 0; i < n; i++) | ||
| 683 | a[i] = 0; | ||
| 684 | |||
| 685 | if (p < 0 || p >= factorial(n)) | ||
| 686 | for (i = 0; i < n; i++) | ||
| 687 | r[i] = -1; | ||
| 688 | |||
| 689 | for (i = 0; i < n; i++) { | ||
| 690 | c = 0; | ||
| 691 | j = 0; | ||
| 692 | while (c <= p / factorial(n-i-1)) | ||
| 693 | c += a[j++] ? 0 : 1; | ||
| 694 | r[i] = j-1; | ||
| 695 | a[j-1] = 1; | ||
| 696 | p %= factorial(n-i-1); | ||
| 697 | } | ||
| 698 | |||
| 699 | free(a); | ||
| 700 | } | ||
| 701 | |||
| 702 | static void | ||
| 703 | index_to_subset(int s, int n, int k, int *r) | ||
| 704 | { | ||
| 705 | int i, j, v; | ||
| 706 | |||
| 707 | if (s < 0 || s >= binomial(n, k)) { | ||
| 708 | for (i = 0; i < n; i++) | ||
| 709 | r[i] = -1; | ||
| 710 | return; | ||
| 711 | } | ||
| 712 | |||
| 713 | for (i = 0; i < n; i++) { | ||
| 714 | if (k == n-i) { | ||
| 715 | for (j = i; j < n; j++) | ||
| 716 | r[j] = 1; | ||
| 717 | return; | ||
| 718 | } | ||
| 719 | |||
| 720 | if (k == 0) { | ||
| 721 | for (j = i; j < n; j++) | ||
| 722 | r[j] = 0; | ||
| 723 | return; | ||
| 724 | } | ||
| 725 | |||
| 726 | v = binomial(n-i-1, k); | ||
| 727 | if (s >= v) { | ||
| 728 | r[i] = 1; | ||
| 729 | k--; | ||
| 730 | s -= v; | ||
| 731 | } else { | ||
| 732 | r[i] = 0; | ||
| 733 | } | ||
| 734 | } | ||
| 735 | } | ||
| 736 | |||
| 737 | static void | ||
| 738 | int_to_digit_array(int a, int b, int n, int *r) | ||
| 739 | { | ||
| 740 | int i; | ||
| 741 | |||
| 742 | if (b <= 1) | ||
| 743 | for (i = 0; i < n; i++) | ||
| 744 | r[i] = 0; | ||
| 745 | else | ||
| 746 | for (i = 0; i < n; i++, a /= b) | ||
| 747 | r[i] = a % b; | ||
| 748 | } | ||
| 749 | |||
| 750 | static void | ||
| 751 | int_to_sum_zero_array(int x, int b, int n, int *a) | ||
| 752 | { | ||
| 753 | int i, s = 0; | ||
| 754 | |||
| 755 | if (b <= 1) { | ||
| 756 | for (i = 0; i < n; i++) | ||
| 757 | a[i] = 0; | ||
| 758 | } else { | ||
| 759 | int_to_digit_array(x, b, n-1, a); | ||
| 760 | for (i = 0; i < n - 1; i++) | ||
| 761 | s = (s + a[i]) % b; | ||
| 762 | a[n-1] = (b - s) % b; | ||
| 763 | } | ||
| 764 | } | ||
| 765 | |||
| 766 | static int | ||
| 767 | invert_digits(int a, int b, int n) | ||
| 768 | { | ||
| 769 | int i, ret, *r = malloc(n * sizeof(int)); | ||
| 770 | |||
| 771 | int_to_digit_array(a, b, n, r); | ||
| 772 | for (i = 0; i < n; i++) | ||
| 773 | r[i] = (b-r[i]) % b; | ||
| 774 | |||
| 775 | ret = digit_array_to_int(r, n, b); | ||
| 776 | free(r); | ||
| 777 | return ret; | ||
| 778 | } | ||
| 779 | |||
| 780 | static bool | ||
| 781 | is_perm(int *a, int n) | ||
| 782 | { | ||
| 783 | int *aux = malloc(n * sizeof(int)); | ||
| 784 | int i; | ||
| 785 | |||
| 786 | for (i = 0; i < n; i++) | ||
| 787 | if (a[i] < 0 || a[i] >= n) | ||
| 788 | return false; | ||
| 789 | else | ||
| 790 | aux[a[i]] = 1; | ||
| 791 | |||
| 792 | for (i = 0; i < n; i++) | ||
| 793 | if (!aux[i]) | ||
| 794 | return false; | ||
| 795 | |||
| 796 | free(aux); | ||
| 797 | |||
| 798 | return true; | ||
| 799 | } | ||
| 800 | |||
| 801 | static bool | ||
| 802 | is_subset(int *a, int n, int k) | ||
| 803 | { | ||
| 804 | int i, sum = 0; | ||
| 805 | |||
| 806 | for (i = 0; i < n; i++) | ||
| 807 | sum += a[i] ? 1 : 0; | ||
| 808 | |||
| 809 | return sum == k; | ||
| 810 | } | ||
| 811 | |||
| 812 | static Cube | ||
| 813 | move_via_arrays(CubeArray *arr, Cube c, PieceFilter f) | ||
| 814 | { | ||
| 815 | CubeArray *arrc = new_cubearray(c, f); | ||
| 816 | Cube ret; | ||
| 817 | |||
| 818 | if (f.epose || f.eposs || f.eposm) | ||
| 819 | apply_permutation(arr->ep, arrc->ep, 12); | ||
| 820 | |||
| 821 | if (f.eofb) { | ||
| 822 | apply_permutation(arr->ep, arrc->eofb, 12); | ||
| 823 | sum_arrays_mod(arr->eofb, arrc->eofb, 12, 2); | ||
| 824 | } | ||
| 825 | |||
| 826 | if (f.eorl) { | ||
| 827 | apply_permutation(arr->ep, arrc->eorl, 12); | ||
| 828 | sum_arrays_mod(arr->eorl, arrc->eorl, 12, 2); | ||
| 829 | } | ||
| 830 | |||
| 831 | if (f.eoud) { | ||
| 832 | apply_permutation(arr->ep, arrc->eoud, 12); | ||
| 833 | sum_arrays_mod(arr->eoud, arrc->eoud, 12, 2); | ||
| 834 | } | ||
| 835 | |||
| 836 | if (f.cp) | ||
| 837 | apply_permutation(arr->cp, arrc->cp, 8); | ||
| 838 | |||
| 839 | if (f.coud) { | ||
| 840 | apply_permutation(arr->cp, arrc->coud, 8); | ||
| 841 | sum_arrays_mod(arr->coud, arrc->coud, 8, 3); | ||
| 842 | } | ||
| 843 | |||
| 844 | if (f.corl) { | ||
| 845 | apply_permutation(arr->cp, arrc->corl, 8); | ||
| 846 | sum_arrays_mod(arr->corl, arrc->corl, 8, 3); | ||
| 847 | } | ||
| 848 | |||
| 849 | if (f.cofb) { | ||
| 850 | apply_permutation(arr->cp, arrc->cofb, 8); | ||
| 851 | sum_arrays_mod(arr->cofb, arrc->cofb, 8, 3); | ||
| 852 | } | ||
| 853 | |||
| 854 | if (f.cpos) | ||
| 855 | apply_permutation(arr->cpos, arrc->cpos, 6); | ||
| 856 | |||
| 857 | ret = arrays_to_cube(arrc, f); | ||
| 858 | free_cubearray(arrc, f); | ||
| 859 | |||
| 860 | return ret; | ||
| 861 | } | ||
| 862 | |||
| 863 | static void | ||
| 864 | movelist_to_position(Move *movelist, int *position) | ||
| 865 | { | ||
| 866 | Move m; | ||
| 867 | |||
| 868 | for (m = 0; m < NMOVES && movelist[m] != NULLMOVE; m++) | ||
| 869 | position[movelist[m]] = m; | ||
| 870 | } | ||
| 871 | |||
| 872 | static void | ||
| 873 | moveset_to_list(Moveset ms, Checker f, Move *r) | ||
| 874 | { | ||
| 875 | Cube c; | ||
| 876 | int b[NMOVES]; | ||
| 877 | int na = 0, nb = 0; | ||
| 878 | Move i; | ||
| 879 | |||
| 880 | if (ms == NULL) { | ||
| 881 | fprintf(stderr, "Error: no moveset given\n"); | ||
| 882 | return; | ||
| 883 | } | ||
| 884 | |||
| 885 | for (i = U; i < NMOVES; i++) { | ||
| 886 | if (ms(i)) { | ||
| 887 | c = apply_move(i, (Cube){0}); | ||
| 888 | if (f != NULL && f(c, 1)) | ||
| 889 | r[na++] = i; | ||
| 890 | else | ||
| 891 | b[nb++] = i; | ||
| 892 | } | ||
| 893 | } | ||
| 894 | |||
| 895 | memcpy(r + na, b, nb * sizeof(Move)); | ||
| 896 | r[na+nb] = NULLMOVE; | ||
| 897 | } | ||
| 898 | |||
| 899 | static AlgList * | ||
| 900 | new_alglist() | ||
| 901 | { | ||
| 902 | AlgList *ret = malloc(sizeof(AlgList)); | ||
| 903 | |||
| 904 | ret->len = 0; | ||
| 905 | ret->first = NULL; | ||
| 906 | ret->last = NULL; | ||
| 907 | |||
| 908 | return ret; | ||
| 909 | } | ||
| 910 | |||
| 911 | static CubeArray * | ||
| 912 | new_cubearray(Cube cube, PieceFilter f) | ||
| 913 | { | ||
| 914 | CubeArray *arr = malloc(sizeof(CubeArray)); | ||
| 915 | |||
| 916 | if (f.epose || f.eposs || f.eposm) | ||
| 917 | arr->ep = malloc(12 * sizeof(int)); | ||
| 918 | if (f.eofb) | ||
| 919 | arr->eofb = malloc(12 * sizeof(int)); | ||
| 920 | if (f.eorl) | ||
| 921 | arr->eorl = malloc(12 * sizeof(int)); | ||
| 922 | if (f.eoud) | ||
| 923 | arr->eoud = malloc(12 * sizeof(int)); | ||
| 924 | if (f.cp) | ||
| 925 | arr->cp = malloc(8 * sizeof(int)); | ||
| 926 | if (f.coud) | ||
| 927 | arr->coud = malloc(8 * sizeof(int)); | ||
| 928 | if (f.corl) | ||
| 929 | arr->corl = malloc(8 * sizeof(int)); | ||
| 930 | if (f.cofb) | ||
| 931 | arr->cofb = malloc(8 * sizeof(int)); | ||
| 932 | if (f.cpos) | ||
| 933 | arr->cpos = malloc(6 * sizeof(int)); | ||
| 934 | |||
| 935 | cube_to_arrays(cube, arr, f); | ||
| 936 | |||
| 937 | return arr; | ||
| 938 | } | ||
| 939 | |||
| 940 | static int | ||
| 941 | perm_sign(int *a, int n) | ||
| 942 | { | ||
| 943 | int i, j, ret = 0; | ||
| 944 | |||
| 945 | if (!is_perm(a,n)) | ||
| 946 | return -1; | ||
| 947 | |||
| 948 | for (i = 0; i < n; i++) | ||
| 949 | for (j = i+1; j < n; j++) | ||
| 950 | ret += (a[i] > a[j]) ? 1 : 0; | ||
| 951 | |||
| 952 | return ret % 2; | ||
| 953 | } | ||
| 954 | |||
| 955 | static int | ||
| 956 | perm_to_index(int *a, int n) | ||
| 957 | { | ||
| 958 | int i, j, c, ret = 0; | ||
| 959 | |||
| 960 | if (!is_perm(a, n)) | ||
| 961 | return -1; | ||
| 962 | |||
| 963 | for (i = 0; i < n; i++) { | ||
| 964 | c = 0; | ||
| 965 | for (j = i+1; j < n; j++) | ||
| 966 | c += (a[i] > a[j]) ? 1 : 0; | ||
| 967 | ret += factorial(n-i-1) * c; | ||
| 968 | } | ||
| 969 | |||
| 970 | return ret; | ||
| 971 | } | ||
| 972 | |||
| 973 | static int | ||
| 974 | powint(int a, int b) | ||
| 975 | { | ||
| 976 | if (b < 0) | ||
| 977 | return 0; | ||
| 978 | if (b == 0) | ||
| 979 | return 1; | ||
| 980 | |||
| 981 | if (b % 2) | ||
| 982 | return a * powint(a, b-1); | ||
| 983 | else | ||
| 984 | return powint(a*a, b/2); | ||
| 985 | } | ||
| 986 | |||
| 987 | static bool | ||
| 988 | ptable_has_reached(PruneData *pd, uint64_t ind) | ||
| 989 | { | ||
| 990 | return (ind % 2) ? pd->reached[ind/2] / 16 : pd->reached[ind/2] % 16; | ||
| 991 | } | ||
| 992 | |||
| 993 | static void | ||
| 994 | ptable_set_reached(PruneData *pd, uint64_t ind) | ||
| 995 | { | ||
| 996 | uint8_t oldval2 = pd->reached[ind/2]; | ||
| 997 | int other = (ind % 2) ? oldval2 % 16 : oldval2 / 16; | ||
| 998 | |||
| 999 | pd->reached[ind/2] = (ind % 2) ? 16 + other : 16*other + 1; | ||
| 1000 | } | ||
| 1001 | |||
| 1002 | static void | ||
| 1003 | ptable_update(PruneData *pd, uint64_t ind, int n) | ||
| 1004 | { | ||
| 1005 | uint8_t oldval2 = pd->ptable[ind/2]; | ||
| 1006 | int other = (ind % 2) ? oldval2 % 16 : oldval2 / 16; | ||
| 1007 | |||
| 1008 | pd->ptable[ind/2] = (ind % 2) ? 16*n + other : 16*other + n; | ||
| 1009 | pd->n++; | ||
| 1010 | } | ||
| 1011 | |||
| 1012 | static void | ||
| 1013 | realloc_alg(Alg *alg, int n) | ||
| 1014 | { | ||
| 1015 | if (alg == NULL) { | ||
| 1016 | fprintf(stderr, "Error: trying to reallocate NULL alg.\n"); | ||
| 1017 | return; | ||
| 1018 | } | ||
| 1019 | |||
| 1020 | if (n < alg->len) { | ||
| 1021 | fprintf(stderr, "Error: alg too long for reallocation "); | ||
| 1022 | fprintf(stderr, "(%d vs %d)\n", alg->len, n); | ||
| 1023 | return; | ||
| 1024 | } | ||
| 1025 | |||
| 1026 | if (n > 1000000) { | ||
| 1027 | fprintf(stderr, "Warning: very long alg,"); | ||
| 1028 | fprintf(stderr, "something might go wrong.\n"); | ||
| 1029 | } | ||
| 1030 | |||
| 1031 | alg->move = realloc(alg->move, n * sizeof(int)); | ||
| 1032 | alg->inv = realloc(alg->inv, n * sizeof(int)); | ||
| 1033 | alg->allocated = n; | ||
| 1034 | } | ||
| 1035 | |||
| 1036 | static bool | ||
| 1037 | read_algset_file(AlgSet *as) | ||
| 1038 | { | ||
| 1039 | return false; | ||
| 1040 | } | ||
| 1041 | |||
| 1042 | static bool | ||
| 1043 | read_mtables_file() | ||
| 1044 | { | ||
| 1045 | FILE *f; | ||
| 1046 | char fname[strlen(tabledir)+20]; | ||
| 1047 | int m, b = sizeof(int); | ||
| 1048 | bool r = true; | ||
| 1049 | |||
| 1050 | strcpy(fname, tabledir); | ||
| 1051 | strcat(fname, "/mtables"); | ||
| 1052 | |||
| 1053 | if ((f = fopen(fname, "rb")) == NULL) | ||
| 1054 | return false; | ||
| 1055 | |||
| 1056 | for (m = 0; m < NMOVES; m++) { | ||
| 1057 | r = r && fread(epose_mtable[m], b, me[0], f) == me[0]; | ||
| 1058 | r = r && fread(eposs_mtable[m], b, me[1], f) == me[1]; | ||
| 1059 | r = r && fread(eposm_mtable[m], b, me[2], f) == me[2]; | ||
| 1060 | r = r && fread(eofb_mtable[m], b, me[3], f) == me[3]; | ||
| 1061 | r = r && fread(eorl_mtable[m], b, me[4], f) == me[4]; | ||
| 1062 | r = r && fread(eoud_mtable[m], b, me[5], f) == me[5]; | ||
| 1063 | r = r && fread(cp_mtable[m], b, me[6], f) == me[6]; | ||
| 1064 | r = r && fread(coud_mtable[m], b, me[7], f) == me[7]; | ||
| 1065 | r = r && fread(corl_mtable[m], b, me[8], f) == me[8]; | ||
| 1066 | r = r && fread(cofb_mtable[m], b, me[9], f) == me[9]; | ||
| 1067 | r = r && fread(cpos_mtable[m], b, me[10], f) == me[10]; | ||
| 1068 | } | ||
| 1069 | |||
| 1070 | fclose(f); | ||
| 1071 | return r; | ||
| 1072 | } | ||
| 1073 | |||
| 1074 | static bool | ||
| 1075 | read_ptable_file(PruneData *pd) | ||
| 1076 | { | ||
| 1077 | FILE *f; | ||
| 1078 | char fname[strlen(tabledir)+100]; | ||
| 1079 | uint64_t r; | ||
| 1080 | |||
| 1081 | strcpy(fname, tabledir); | ||
| 1082 | strcat(fname, "/"); | ||
| 1083 | strcat(fname, pd->filename); | ||
| 1084 | |||
| 1085 | if ((f = fopen(fname, "rb")) == NULL) | ||
| 1086 | return false; | ||
| 1087 | |||
| 1088 | r = fread(pd->ptable, sizeof(uint8_t), ptablesize(pd), f); | ||
| 1089 | fclose(f); | ||
| 1090 | |||
| 1091 | return r == ptablesize(pd); | ||
| 1092 | } | ||
| 1093 | |||
| 1094 | static bool | ||
| 1095 | read_ttables_file() | ||
| 1096 | { | ||
| 1097 | FILE *f; | ||
| 1098 | char fname[strlen(tabledir)+20]; | ||
| 1099 | int b = sizeof(int); | ||
| 1100 | bool r = true; | ||
| 1101 | Move m; | ||
| 1102 | |||
| 1103 | strcpy(fname, tabledir); | ||
| 1104 | strcat(fname, "/"); | ||
| 1105 | strcat(fname, "ttables"); | ||
| 1106 | |||
| 1107 | if ((f = fopen(fname, "rb")) == NULL) | ||
| 1108 | return false; | ||
| 1109 | |||
| 1110 | for (m = 0; m < NTRANS; m++) { | ||
| 1111 | r = r && fread(epose_ttable[m], b, me[0], f) == me[0]; | ||
| 1112 | r = r && fread(eposs_ttable[m], b, me[1], f) == me[1]; | ||
| 1113 | r = r && fread(eposm_ttable[m], b, me[2], f) == me[2]; | ||
| 1114 | r = r && fread(eo_ttable[m], b, me[3], f) == me[3]; | ||
| 1115 | r = r && fread(cp_ttable[m], b, me[6], f) == me[6]; | ||
| 1116 | r = r && fread(co_ttable[m], b, me[7], f) == me[7]; | ||
| 1117 | r = r && fread(cpos_ttable[m], b, me[10], f) == me[10]; | ||
| 1118 | r = r && fread(moves_ttable[m], b, me[11], f) == me[11]; | ||
| 1119 | } | ||
| 1120 | |||
| 1121 | fclose(f); | ||
| 1122 | return r; | ||
| 1123 | } | ||
| 1124 | |||
| 1125 | static Cube | ||
| 1126 | rotate_via_compose(Trans r, Cube c, PieceFilter f) | ||
| 1127 | { | ||
| 1128 | Alg *inv; | ||
| 1129 | static int zero12[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; | ||
| 1130 | static int zero8[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; | ||
| 1131 | static CubeArray ma = { | ||
| 1132 | .ep = ep_mirror, | ||
| 1133 | .eofb = zero12, | ||
| 1134 | .eorl = zero12, | ||
| 1135 | .eoud = zero12, | ||
| 1136 | .cp = cp_mirror, | ||
| 1137 | .coud = zero8, | ||
| 1138 | .corl = zero8, | ||
| 1139 | .cofb = zero8, | ||
| 1140 | .cpos = cpos_mirror | ||
| 1141 | }; | ||
| 1142 | |||
| 1143 | Cube ret; | ||
| 1144 | |||
| 1145 | if (r != mirror) { | ||
| 1146 | ret = apply_alg_generic(trans_algs[r], c, f, true); | ||
| 1147 | inv = on_inverse(trans_algs[r]); | ||
| 1148 | ret = apply_alg_generic(inv, ret, f, true); | ||
| 1149 | free_alg(inv); | ||
| 1150 | } else { | ||
| 1151 | ret = move_via_arrays(&ma, (Cube){0}, f); | ||
| 1152 | ret = compose_filtered(c, ret, f); | ||
| 1153 | ret = move_via_arrays(&ma, ret, f); | ||
| 1154 | } | ||
| 1155 | |||
| 1156 | return ret; | ||
| 1157 | } | ||
| 1158 | |||
| 1159 | static int | ||
| 1160 | subset_to_index(int *a, int n, int k) | ||
| 1161 | { | ||
| 1162 | int i, ret = 0; | ||
| 1163 | |||
| 1164 | if (!is_subset(a, n, k)) | ||
| 1165 | return binomial(n, k); | ||
| 1166 | |||
| 1167 | for (i = 0; i < n; i++) { | ||
| 1168 | if (k == n-i) | ||
| 1169 | return ret; | ||
| 1170 | if (a[i]) { | ||
| 1171 | ret += binomial(n-i-1, k); | ||
| 1172 | k--; | ||
| 1173 | } | ||
| 1174 | } | ||
| 1175 | |||
| 1176 | return ret; | ||
| 1177 | } | ||
| 1178 | |||
| 1179 | static void | ||
| 1180 | sum_arrays_mod(int *src, int *dst, int n, int m) | ||
| 1181 | { | ||
| 1182 | int i; | ||
| 1183 | |||
| 1184 | for (i = 0; i < n; i++) | ||
| 1185 | dst[i] = (m <= 0) ? 0 : (src[i] + dst[i]) % m; | ||
| 1186 | } | ||
| 1187 | |||
| 1188 | static void | ||
| 1189 | swap(int *a, int *b) | ||
| 1190 | { | ||
| 1191 | int aux; | ||
| 1192 | |||
| 1193 | aux = *a; | ||
| 1194 | *a = *b; | ||
| 1195 | *b = aux; | ||
| 1196 | } | ||
| 1197 | |||
| 1198 | static bool | ||
| 1199 | write_algset_file(AlgSet *as) | ||
| 1200 | { | ||
| 1201 | return false; | ||
| 1202 | } | ||
| 1203 | |||
| 1204 | static bool | ||
| 1205 | write_mtables_file() | ||
| 1206 | { | ||
| 1207 | FILE *f; | ||
| 1208 | char fname[strlen(tabledir)+20]; | ||
| 1209 | int m, b = sizeof(int); | ||
| 1210 | bool r = true; | ||
| 1211 | |||
| 1212 | strcpy(fname, tabledir); | ||
| 1213 | strcat(fname, "/mtables"); | ||
| 1214 | |||
| 1215 | if ((f = fopen(fname, "wb")) == NULL) | ||
| 1216 | return false; | ||
| 1217 | |||
| 1218 | for (m = 0; m < NMOVES; m++) { | ||
| 1219 | r = r && fwrite(epose_mtable[m], b, me[0], f) == me[0]; | ||
| 1220 | r = r && fwrite(eposs_mtable[m], b, me[1], f) == me[1]; | ||
| 1221 | r = r && fwrite(eposm_mtable[m], b, me[2], f) == me[2]; | ||
| 1222 | r = r && fwrite(eofb_mtable[m], b, me[3], f) == me[3]; | ||
| 1223 | r = r && fwrite(eorl_mtable[m], b, me[4], f) == me[4]; | ||
| 1224 | r = r && fwrite(eoud_mtable[m], b, me[5], f) == me[5]; | ||
| 1225 | r = r && fwrite(cp_mtable[m], b, me[6], f) == me[6]; | ||
| 1226 | r = r && fwrite(coud_mtable[m], b, me[7], f) == me[7]; | ||
| 1227 | r = r && fwrite(corl_mtable[m], b, me[8], f) == me[8]; | ||
| 1228 | r = r && fwrite(cofb_mtable[m], b, me[9], f) == me[9]; | ||
| 1229 | r = r && fwrite(cpos_mtable[m], b, me[10], f) == me[10]; | ||
| 1230 | } | ||
| 1231 | |||
| 1232 | fclose(f); | ||
| 1233 | return r; | ||
| 1234 | } | ||
| 1235 | |||
| 1236 | static bool | ||
| 1237 | write_ptable_file(PruneData *pd) | ||
| 1238 | { | ||
| 1239 | FILE *f; | ||
| 1240 | char fname[strlen(tabledir)+100]; | ||
| 1241 | uint64_t written; | ||
| 1242 | |||
| 1243 | strcpy(fname, tabledir); | ||
| 1244 | strcat(fname, "/"); | ||
| 1245 | strcat(fname, pd->filename); | ||
| 1246 | |||
| 1247 | if ((f = fopen(fname, "wb")) == NULL) | ||
| 1248 | return false; | ||
| 1249 | |||
| 1250 | written = fwrite(pd->ptable, sizeof(uint8_t), ptablesize(pd), f); | ||
| 1251 | fclose(f); | ||
| 1252 | |||
| 1253 | return written == ptablesize(pd); | ||
| 1254 | } | ||
| 1255 | |||
| 1256 | static bool | ||
| 1257 | write_ttables_file() | ||
| 1258 | { | ||
| 1259 | FILE *f; | ||
| 1260 | char fname[strlen(tabledir)+20]; | ||
| 1261 | bool r = true; | ||
| 1262 | int b = sizeof(int); | ||
| 1263 | Move m; | ||
| 1264 | |||
| 1265 | strcpy(fname, tabledir); | ||
| 1266 | strcat(fname, "/ttables"); | ||
| 1267 | |||
| 1268 | if ((f = fopen(fname, "wb")) == NULL) | ||
| 1269 | return false; | ||
| 1270 | |||
| 1271 | for (m = 0; m < NTRANS; m++) { | ||
| 1272 | r = r && fwrite(epose_ttable[m], b, me[0], f) == me[0]; | ||
| 1273 | r = r && fwrite(eposs_ttable[m], b, me[1], f) == me[1]; | ||
| 1274 | r = r && fwrite(eposm_ttable[m], b, me[2], f) == me[2]; | ||
| 1275 | r = r && fwrite(eo_ttable[m], b, me[3], f) == me[3]; | ||
| 1276 | r = r && fwrite(cp_ttable[m], b, me[6], f) == me[6]; | ||
| 1277 | r = r && fwrite(co_ttable[m], b, me[7], f) == me[7]; | ||
| 1278 | r = r && fwrite(cpos_ttable[m], b, me[10], f) == me[10]; | ||
| 1279 | r = r && fwrite(moves_ttable[m], b, me[11], f) == me[11]; | ||
| 1280 | } | ||
| 1281 | |||
| 1282 | fclose(f); | ||
| 1283 | return r; | ||
| 1284 | } | ||
| 1285 | |||
| 1286 | /* Init functions implementation *********************************************/ | ||
| 1287 | |||
| 1288 | static void | ||
| 1289 | init_auxtables() | ||
| 1290 | { | ||
| 1291 | Cube c1, c2; | ||
| 1292 | CubeArray *arr; | ||
| 1293 | uint64_t ui, uj; | ||
| 1294 | int i, j, k, auxarr[12]; | ||
| 1295 | bool cij, p1, p2; | ||
| 1296 | |||
| 1297 | for (ui = 0; ui < FACTORIAL6; ui++) { | ||
| 1298 | arr = new_cubearray((Cube){.cpos = ui}, pf_cpos); | ||
| 1299 | for (i = 0; i < 6; i++) { | ||
| 1300 | what_center_at_aux[ui][i] = arr->cpos[i]; | ||
| 1301 | where_is_center_aux[ui][arr->cpos[i]] = i; | ||
| 1302 | } | ||
| 1303 | free_cubearray(arr, pf_cpos); | ||
| 1304 | } | ||
| 1305 | |||
| 1306 | for (ui = 0; ui < FACTORIAL8; ui++) { | ||
| 1307 | arr = new_cubearray((Cube){.cp = ui}, pf_cp); | ||
| 1308 | for (i = 0; i < 8; i++) { | ||
| 1309 | what_corner_at_aux[ui][i] = arr->cp[i]; | ||
| 1310 | where_is_corner_aux[ui][arr->cp[i]] = i; | ||
| 1311 | } | ||
| 1312 | free_cubearray(arr, pf_cp); | ||
| 1313 | } | ||
| 1314 | |||
| 1315 | for (ui = 0; ui < FACTORIAL12/FACTORIAL8; ui++) { | ||
| 1316 | arr = new_cubearray((Cube){.epose = ui}, pf_e); | ||
| 1317 | for (i = 0; i < 12; i++) | ||
| 1318 | if (edge_slice(arr->ep[i]) == 0) | ||
| 1319 | where_is_edge_aux[0][ui][arr->ep[i]] = i; | ||
| 1320 | free_cubearray(arr, pf_e); | ||
| 1321 | |||
| 1322 | arr = new_cubearray((Cube){.eposs = ui}, pf_s); | ||
| 1323 | for (i = 0; i < 12; i++) | ||
| 1324 | if (edge_slice(arr->ep[i]) == 1) | ||
| 1325 | where_is_edge_aux[1][ui][arr->ep[i]] = i; | ||
| 1326 | free_cubearray(arr, pf_s); | ||
| 1327 | |||
| 1328 | arr = new_cubearray((Cube){.eposm = ui}, pf_m); | ||
| 1329 | for (i = 0; i < 12; i++) | ||
| 1330 | if (edge_slice(arr->ep[i]) == 2) | ||
| 1331 | where_is_edge_aux[2][ui][arr->ep[i]] = i; | ||
| 1332 | free_cubearray(arr, pf_m); | ||
| 1333 | } | ||
| 1334 | |||
| 1335 | for (ui = 0; ui < POW3TO7; ui++) { | ||
| 1336 | int_to_sum_zero_array(ui, 3, 8, auxarr); | ||
| 1337 | what_orientation_last_corner_aux[ui] = auxarr[7]; | ||
| 1338 | } | ||
| 1339 | |||
| 1340 | for (ui = 0; ui < POW2TO11; ui++) { | ||
| 1341 | int_to_sum_zero_array(ui, 2, 12, auxarr); | ||
| 1342 | what_orientation_last_edge_aux[ui] = auxarr[11]; | ||
| 1343 | } | ||
| 1344 | |||
| 1345 | for (ui = 0; ui < BINOM12ON4; ui++) | ||
| 1346 | for (uj = 0; uj < BINOM12ON4; uj++) | ||
| 1347 | epos_dependent_aux[ui][uj]=epos_dependent_pos(ui, uj); | ||
| 1348 | |||
| 1349 | for (i = 0; i < NMOVES; i++) { | ||
| 1350 | for (j = 0; j < NMOVES; j++) { | ||
| 1351 | c1 = apply_move(i, apply_move(j, (Cube){0})); | ||
| 1352 | c2 = apply_move(j, apply_move(i, (Cube){0})); | ||
| 1353 | commute[i][j] = equal(c1, c2) && i && j; | ||
| 1354 | } | ||
| 1355 | } | ||
| 1356 | |||
| 1357 | for (i = 0; i < NMOVES; i++) { | ||
| 1358 | for (j = 0; j < NMOVES; j++) { | ||
| 1359 | for (k = 0; k < NMOVES; k++) { | ||
| 1360 | p1 = j && base_move(j) == base_move(k); | ||
| 1361 | p2 = i && base_move(i) == base_move(k); | ||
| 1362 | cij = commute[i][j]; | ||
| 1363 | possible_next[i][j][k] = !(p1 || (cij && p2)); | ||
| 1364 | } | ||
| 1365 | } | ||
| 1366 | } | ||
| 1367 | |||
| 1368 | for (i = 0; i < NMOVES; i++) | ||
| 1369 | inverse_move_aux[i] = i ? i + 2 - 2*((i-1)%3) : NULLMOVE; | ||
| 1370 | |||
| 1371 | /* Is there a more elegant way? */ | ||
| 1372 | inverse_trans_aux[uf] = uf; | ||
| 1373 | inverse_trans_aux[ur] = ul; | ||
| 1374 | inverse_trans_aux[ul] = ur; | ||
| 1375 | inverse_trans_aux[ub] = ub; | ||
| 1376 | |||
| 1377 | inverse_trans_aux[df] = df; | ||
| 1378 | inverse_trans_aux[dr] = dr; | ||
| 1379 | inverse_trans_aux[dl] = dl; | ||
| 1380 | inverse_trans_aux[db] = db; | ||
| 1381 | |||
| 1382 | inverse_trans_aux[rf] = lf; | ||
| 1383 | inverse_trans_aux[rd] = bl; | ||
| 1384 | inverse_trans_aux[rb] = rb; | ||
| 1385 | inverse_trans_aux[ru] = fr; | ||
| 1386 | |||
| 1387 | inverse_trans_aux[lf] = rf; | ||
| 1388 | inverse_trans_aux[ld] = br; | ||
| 1389 | inverse_trans_aux[lb] = lb; | ||
| 1390 | inverse_trans_aux[lu] = fl; | ||
| 1391 | |||
| 1392 | inverse_trans_aux[fu] = fu; | ||
| 1393 | inverse_trans_aux[fr] = ru; | ||
| 1394 | inverse_trans_aux[fd] = bu; | ||
| 1395 | inverse_trans_aux[fl] = lu; | ||
| 1396 | |||
| 1397 | inverse_trans_aux[bu] = fd; | ||
| 1398 | inverse_trans_aux[br] = ld; | ||
| 1399 | inverse_trans_aux[bd] = bd; | ||
| 1400 | inverse_trans_aux[bl] = rd; | ||
| 1401 | |||
| 1402 | inverse_trans_aux[mirror] = mirror; | ||
| 1403 | } | ||
| 1404 | |||
| 1405 | /* | ||
| 1406 | * There is certainly a bette way to do this, but for now I just use | ||
| 1407 | * a "graph coloring" algorithm to compute the cosets for cphtr. | ||
| 1408 | * | ||
| 1409 | * For doing it better "Mathematically", we need 3 things: | ||
| 1410 | * - Checking that cp separates the orbits (UFR,UBL,DFL,DBR) and the other | ||
| 1411 | * This is easy and it is done in the commented function cphtr_cp(). | ||
| 1412 | * - Check that there is no ep/cp parity | ||
| 1413 | * - Check that we are not in the "3c" case; this is the part I don't | ||
| 1414 | * know how to do. | ||
| 1415 | */ | ||
| 1416 | static void | ||
| 1417 | init_cphtr_cosets() | ||
| 1418 | { | ||
| 1419 | unsigned int i; | ||
| 1420 | int c = 0; | ||
| 1421 | |||
| 1422 | for (i = 0; i < FACTORIAL8; i++) | ||
| 1423 | cphtr_cosets[i] = -1; | ||
| 1424 | |||
| 1425 | for (i = 0; i < FACTORIAL8; i++) | ||
| 1426 | if (cphtr_cosets[i] == -1) | ||
| 1427 | init_cphtr_cosets_bfs(i, c++); | ||
| 1428 | } | ||
| 1429 | |||
| 1430 | static void | ||
| 1431 | init_cphtr_cosets_bfs(int i, int c) | ||
| 1432 | { | ||
| 1433 | int j, jj, k, next[FACTORIAL8], next2[FACTORIAL8], n, n2; | ||
| 1434 | Move moves[6] = {U2, D2, R2, L2, F2, B2}; | ||
| 1435 | |||
| 1436 | n = 1; | ||
| 1437 | next[0] = i; | ||
| 1438 | cphtr_cosets[i] = c; | ||
| 1439 | |||
| 1440 | while (n != 0) { | ||
| 1441 | for (j = 0, n2 = 0; j < n; j++) { | ||
| 1442 | for (k = 0; k < 6; k++) { | ||
| 1443 | jj = cp_mtable[moves[k]][next[j]]; | ||
| 1444 | if (cphtr_cosets[jj] == -1) { | ||
| 1445 | cphtr_cosets[jj] = c; | ||
| 1446 | next2[n2++] = jj; | ||
| 1447 | } | ||
| 1448 | } | ||
| 1449 | } | ||
| 1450 | |||
| 1451 | for (j = 0; j < n2; j++) | ||
| 1452 | next[j] = next2[j]; | ||
| 1453 | n = n2; | ||
| 1454 | } | ||
| 1455 | } | ||
| 1456 | |||
| 1457 | static void | ||
| 1458 | init_environment() | ||
| 1459 | { | ||
| 1460 | char *nissydata = getenv("NISSYDATA"); | ||
| 1461 | char *localdata = getenv("XDG_DATA_HOME"); | ||
| 1462 | char *home = getenv("HOME"); | ||
| 1463 | bool read, write; | ||
| 1464 | |||
| 1465 | if (nissydata != NULL) { | ||
| 1466 | tabledir = malloc(strlen(nissydata) * sizeof(char) + 20); | ||
| 1467 | strcpy(tabledir, nissydata); | ||
| 1468 | } else if (localdata != NULL) { | ||
| 1469 | tabledir = malloc(strlen(localdata) * sizeof(char) + 20); | ||
| 1470 | strcpy(tabledir, localdata); | ||
| 1471 | strcat(tabledir, "/nissy"); | ||
| 1472 | } else if (home != NULL) { | ||
| 1473 | tabledir = malloc(strlen(home) * sizeof(char) + 20); | ||
| 1474 | strcpy(tabledir, home); | ||
| 1475 | strcat(tabledir, "/.nissy"); | ||
| 1476 | } | ||
| 1477 | |||
| 1478 | mkdir(tabledir, 0777); | ||
| 1479 | strcat(tabledir, "/tables"); | ||
| 1480 | mkdir(tabledir, 0777); | ||
| 1481 | |||
| 1482 | read = !access(tabledir, R_OK); | ||
| 1483 | write = !access(tabledir, W_OK); | ||
| 1484 | |||
| 1485 | if (!read) { | ||
| 1486 | fprintf(stderr, "Table files cannot be read.\n"); | ||
| 1487 | } else if (!write) { | ||
| 1488 | fprintf(stderr, "Data directory not writable: "); | ||
| 1489 | fprintf(stderr, "tables can be loaded, but not saved.\n"); | ||
| 1490 | } | ||
| 1491 | } | ||
| 1492 | |||
| 1493 | static void | ||
| 1494 | init_moves() { | ||
| 1495 | Cube c; | ||
| 1496 | CubeArray arrs; | ||
| 1497 | int i; | ||
| 1498 | unsigned int ui; | ||
| 1499 | Move m; | ||
| 1500 | |||
| 1501 | /* Generate all move cycles and flips; I do this regardless */ | ||
| 1502 | for (i = 0; i < NMOVES; i++) { | ||
| 1503 | if (i == U || i == x || i == y) | ||
| 1504 | continue; | ||
| 1505 | |||
| 1506 | c = apply_alg_generic(equiv_alg[i], (Cube){0}, pf_all, false); | ||
| 1507 | |||
| 1508 | arrs = (CubeArray) { | ||
| 1509 | edge_cycle[i], | ||
| 1510 | eofb_flipped[i], | ||
| 1511 | eorl_flipped[i], | ||
| 1512 | eoud_flipped[i], | ||
| 1513 | corner_cycle[i], | ||
| 1514 | coud_flipped[i], | ||
| 1515 | corl_flipped[i], | ||
| 1516 | cofb_flipped[i], | ||
| 1517 | center_cycle[i] | ||
| 1518 | }; | ||
| 1519 | cube_to_arrays(c, &arrs, pf_all); | ||
| 1520 | } | ||
| 1521 | |||
| 1522 | if (read_mtables_file()) | ||
| 1523 | return; | ||
| 1524 | |||
| 1525 | fprintf(stderr, "Cannot load %s, generating it\n", "mtables"); | ||
| 1526 | |||
| 1527 | /* Initialize transition tables */ | ||
| 1528 | for (m = 0; m < NMOVES; m++) { | ||
| 1529 | for (ui = 0; ui < FACTORIAL12/FACTORIAL8; ui++) { | ||
| 1530 | c = (Cube){ .epose = ui }; | ||
| 1531 | c = apply_move_cubearray(m, c, pf_e); | ||
| 1532 | epose_mtable[m][ui] = c.epose; | ||
| 1533 | |||
| 1534 | c = (Cube){ .eposs = ui }; | ||
| 1535 | c = apply_move_cubearray(m, c, pf_s); | ||
| 1536 | eposs_mtable[m][ui] = c.eposs; | ||
| 1537 | |||
| 1538 | c = (Cube){ .eposm = ui }; | ||
| 1539 | c = apply_move_cubearray(m, c, pf_m); | ||
| 1540 | eposm_mtable[m][ui] = c.eposm; | ||
| 1541 | } | ||
| 1542 | for (ui = 0; ui < POW2TO11; ui++ ) { | ||
| 1543 | c = (Cube){ .eofb = ui }; | ||
| 1544 | c = apply_move_cubearray(m, c, pf_eo); | ||
| 1545 | eofb_mtable[m][ui] = c.eofb; | ||
| 1546 | |||
| 1547 | c = (Cube){ .eorl = ui }; | ||
| 1548 | c = apply_move_cubearray(m, c, pf_eo); | ||
| 1549 | eorl_mtable[m][ui] = c.eorl; | ||
| 1550 | |||
| 1551 | c = (Cube){ .eoud = ui }; | ||
| 1552 | c = apply_move_cubearray(m, c, pf_eo); | ||
| 1553 | eoud_mtable[m][ui] = c.eoud; | ||
| 1554 | } | ||
| 1555 | for (ui = 0; ui < POW3TO7; ui++) { | ||
| 1556 | c = (Cube){ .coud = ui }; | ||
| 1557 | c = apply_move_cubearray(m, c, pf_co); | ||
| 1558 | coud_mtable[m][ui] = c.coud; | ||
| 1559 | |||
| 1560 | c = (Cube){ .corl = ui }; | ||
| 1561 | c = apply_move_cubearray(m, c, pf_co); | ||
| 1562 | corl_mtable[m][ui] = c.corl; | ||
| 1563 | |||
| 1564 | c = (Cube){ .cofb = ui }; | ||
| 1565 | c = apply_move_cubearray(m, c, pf_co); | ||
| 1566 | cofb_mtable[m][ui] = c.cofb; | ||
| 1567 | } | ||
| 1568 | for (ui = 0; ui < FACTORIAL8; ui++) { | ||
| 1569 | c = (Cube){ .cp = ui }; | ||
| 1570 | c = apply_move_cubearray(m, c, pf_cp); | ||
| 1571 | cp_mtable[m][ui] = c.cp; | ||
| 1572 | } | ||
| 1573 | for (ui = 0; ui < FACTORIAL6; ui++) { | ||
| 1574 | c = (Cube){ .cpos = ui }; | ||
| 1575 | c = apply_move_cubearray(m, c, pf_cpos); | ||
| 1576 | cpos_mtable[m][ui] = c.cpos; | ||
| 1577 | } | ||
| 1578 | } | ||
| 1579 | |||
| 1580 | if (!write_mtables_file()) | ||
| 1581 | fprintf(stderr, "Error writing mtables\n"); | ||
| 1582 | } | ||
| 1583 | |||
| 1584 | static void | ||
| 1585 | init_moves_aux() | ||
| 1586 | { | ||
| 1587 | /* Some standard PieceFilters */ | ||
| 1588 | pf_all.epose = true; | ||
| 1589 | pf_all.eposs = true; | ||
| 1590 | pf_all.eposm = true; | ||
| 1591 | pf_all.eofb = true; | ||
| 1592 | pf_all.eorl = true; | ||
| 1593 | pf_all.eoud = true; | ||
| 1594 | pf_all.cp = true; | ||
| 1595 | pf_all.cofb = true; | ||
| 1596 | pf_all.corl = true; | ||
| 1597 | pf_all.coud = true; | ||
| 1598 | pf_all.cpos = true; | ||
| 1599 | |||
| 1600 | pf_4val.epose = true; | ||
| 1601 | pf_4val.eposs = true; | ||
| 1602 | pf_4val.eposm = true; | ||
| 1603 | pf_4val.eofb = true; | ||
| 1604 | pf_4val.coud = true; | ||
| 1605 | pf_4val.cp = true; | ||
| 1606 | |||
| 1607 | pf_epcp.epose = true; | ||
| 1608 | pf_epcp.eposs = true; | ||
| 1609 | pf_epcp.eposm = true; | ||
| 1610 | pf_epcp.cp = true; | ||
| 1611 | |||
| 1612 | pf_cpos.cpos = true; | ||
| 1613 | |||
| 1614 | pf_cp.cp = true; | ||
| 1615 | |||
| 1616 | pf_ep.epose = true; | ||
| 1617 | pf_ep.eposs = true; | ||
| 1618 | pf_ep.eposm = true; | ||
| 1619 | |||
| 1620 | pf_e.epose = true; | ||
| 1621 | pf_s.eposs = true; | ||
| 1622 | pf_m.eposm = true; | ||
| 1623 | |||
| 1624 | pf_eo.eofb = true; | ||
| 1625 | pf_eo.eorl = true; | ||
| 1626 | pf_eo.eoud = true; | ||
| 1627 | |||
| 1628 | pf_co.cofb = true; | ||
| 1629 | pf_co.corl = true; | ||
| 1630 | pf_co.coud = true; | ||
| 1631 | |||
| 1632 | /* Used to convert to and from CubeArray */ | ||
| 1633 | epe_solved[0] = FR; | ||
| 1634 | epe_solved[1] = FL; | ||
| 1635 | epe_solved[2] = BL; | ||
| 1636 | epe_solved[3] = BR; | ||
| 1637 | |||
| 1638 | eps_solved[0] = UL; | ||
| 1639 | eps_solved[1] = UR; | ||
| 1640 | eps_solved[2] = DL; | ||
| 1641 | eps_solved[3] = DR; | ||
| 1642 | |||
| 1643 | epm_solved[0] = UF; | ||
| 1644 | epm_solved[1] = UB; | ||
| 1645 | epm_solved[2] = DF; | ||
| 1646 | epm_solved[3] = DB; | ||
| 1647 | |||
| 1648 | /* Table sizes, used for reading and writing files */ | ||
| 1649 | me[0] = FACTORIAL12/FACTORIAL8; | ||
| 1650 | me[1] = FACTORIAL12/FACTORIAL8; | ||
| 1651 | me[2] = FACTORIAL12/FACTORIAL8; | ||
| 1652 | me[3] = POW2TO11; | ||
| 1653 | me[4] = POW2TO11; | ||
| 1654 | me[5] = POW2TO11; | ||
| 1655 | me[6] = FACTORIAL8; | ||
| 1656 | me[7] = POW3TO7; | ||
| 1657 | me[8] = POW3TO7; | ||
| 1658 | me[9] = POW3TO7; | ||
| 1659 | me[10] = FACTORIAL6; | ||
| 1660 | me[11] = NMOVES; | ||
| 1661 | |||
| 1662 | /* Cycles *********************/ | ||
| 1663 | edge_cycle[U][UF] = UR; | ||
| 1664 | edge_cycle[U][UL] = UF; | ||
| 1665 | edge_cycle[U][UB] = UL; | ||
| 1666 | edge_cycle[U][UR] = UB; | ||
| 1667 | edge_cycle[U][DF] = DF; | ||
| 1668 | edge_cycle[U][DL] = DL; | ||
| 1669 | edge_cycle[U][DB] = DB; | ||
| 1670 | edge_cycle[U][DR] = DR; | ||
| 1671 | edge_cycle[U][FR] = FR; | ||
| 1672 | edge_cycle[U][FL] = FL; | ||
| 1673 | edge_cycle[U][BL] = BL; | ||
| 1674 | edge_cycle[U][BR] = BR; | ||
| 1675 | |||
| 1676 | edge_cycle[x][UF] = DF; | ||
| 1677 | edge_cycle[x][UL] = FL; | ||
| 1678 | edge_cycle[x][UB] = UF; | ||
| 1679 | edge_cycle[x][UR] = FR; | ||
| 1680 | edge_cycle[x][DF] = DB; | ||
| 1681 | edge_cycle[x][DL] = BL; | ||
| 1682 | edge_cycle[x][DB] = UB; | ||
| 1683 | edge_cycle[x][DR] = BR; | ||
| 1684 | edge_cycle[x][FR] = DR; | ||
| 1685 | edge_cycle[x][FL] = DL; | ||
| 1686 | edge_cycle[x][BL] = UL; | ||
| 1687 | edge_cycle[x][BR] = UR; | ||
| 1688 | |||
| 1689 | edge_cycle[y][UF] = UR; | ||
| 1690 | edge_cycle[y][UL] = UF; | ||
| 1691 | edge_cycle[y][UB] = UL; | ||
| 1692 | edge_cycle[y][UR] = UB; | ||
| 1693 | edge_cycle[y][DF] = DR; | ||
| 1694 | edge_cycle[y][DL] = DF; | ||
| 1695 | edge_cycle[y][DB] = DL; | ||
| 1696 | edge_cycle[y][DR] = DB; | ||
| 1697 | edge_cycle[y][FR] = BR; | ||
| 1698 | edge_cycle[y][FL] = FR; | ||
| 1699 | edge_cycle[y][BL] = FL; | ||
| 1700 | edge_cycle[y][BR] = BL; | ||
| 1701 | |||
| 1702 | corner_cycle[U][UFR] = UBR; | ||
| 1703 | corner_cycle[U][UFL] = UFR; | ||
| 1704 | corner_cycle[U][UBL] = UFL; | ||
| 1705 | corner_cycle[U][UBR] = UBL; | ||
| 1706 | corner_cycle[U][DFR] = DFR; | ||
| 1707 | corner_cycle[U][DFL] = DFL; | ||
| 1708 | corner_cycle[U][DBL] = DBL; | ||
| 1709 | corner_cycle[U][DBR] = DBR; | ||
| 1710 | |||
| 1711 | corner_cycle[x][UFR] = DFR; | ||
| 1712 | corner_cycle[x][UFL] = DFL; | ||
| 1713 | corner_cycle[x][UBL] = UFL; | ||
| 1714 | corner_cycle[x][UBR] = UFR; | ||
| 1715 | corner_cycle[x][DFR] = DBR; | ||
| 1716 | corner_cycle[x][DFL] = DBL; | ||
| 1717 | corner_cycle[x][DBL] = UBL; | ||
| 1718 | corner_cycle[x][DBR] = UBR; | ||
| 1719 | |||
| 1720 | corner_cycle[y][UFR] = UBR; | ||
| 1721 | corner_cycle[y][UFL] = UFR; | ||
| 1722 | corner_cycle[y][UBL] = UFL; | ||
| 1723 | corner_cycle[y][UBR] = UBL; | ||
| 1724 | corner_cycle[y][DFR] = DBR; | ||
| 1725 | corner_cycle[y][DFL] = DFR; | ||
| 1726 | corner_cycle[y][DBL] = DFL; | ||
| 1727 | corner_cycle[y][DBR] = DBL; | ||
| 1728 | |||
| 1729 | center_cycle[U][U_center] = U_center; | ||
| 1730 | center_cycle[U][D_center] = D_center; | ||
| 1731 | center_cycle[U][R_center] = R_center; | ||
| 1732 | center_cycle[U][L_center] = L_center; | ||
| 1733 | center_cycle[U][F_center] = F_center; | ||
| 1734 | center_cycle[U][B_center] = B_center; | ||
| 1735 | |||
| 1736 | center_cycle[x][U_center] = F_center; | ||
| 1737 | center_cycle[x][D_center] = B_center; | ||
| 1738 | center_cycle[x][R_center] = R_center; | ||
| 1739 | center_cycle[x][L_center] = L_center; | ||
| 1740 | center_cycle[x][F_center] = D_center; | ||
| 1741 | center_cycle[x][B_center] = U_center; | ||
| 1742 | |||
| 1743 | center_cycle[y][U_center] = U_center; | ||
| 1744 | center_cycle[y][D_center] = D_center; | ||
| 1745 | center_cycle[y][R_center] = B_center; | ||
| 1746 | center_cycle[y][L_center] = F_center; | ||
| 1747 | center_cycle[y][F_center] = R_center; | ||
| 1748 | center_cycle[y][B_center] = L_center; | ||
| 1749 | |||
| 1750 | /* Flipped pieces *************/ | ||
| 1751 | eofb_flipped[x][UF] = 1; | ||
| 1752 | eofb_flipped[x][UB] = 1; | ||
| 1753 | eofb_flipped[x][DF] = 1; | ||
| 1754 | eofb_flipped[x][DB] = 1; | ||
| 1755 | |||
| 1756 | eofb_flipped[y][FR] = 1; | ||
| 1757 | eofb_flipped[y][FL] = 1; | ||
| 1758 | eofb_flipped[y][BL] = 1; | ||
| 1759 | eofb_flipped[y][BR] = 1; | ||
| 1760 | |||
| 1761 | eorl_flipped[x][UF] = 1; | ||
| 1762 | eorl_flipped[x][UL] = 1; | ||
| 1763 | eorl_flipped[x][UB] = 1; | ||
| 1764 | eorl_flipped[x][UR] = 1; | ||
| 1765 | eorl_flipped[x][DF] = 1; | ||
| 1766 | eorl_flipped[x][DL] = 1; | ||
| 1767 | eorl_flipped[x][DB] = 1; | ||
| 1768 | eorl_flipped[x][DR] = 1; | ||
| 1769 | eorl_flipped[x][FR] = 1; | ||
| 1770 | eorl_flipped[x][FL] = 1; | ||
| 1771 | eorl_flipped[x][BL] = 1; | ||
| 1772 | eorl_flipped[x][BR] = 1; | ||
| 1773 | |||
| 1774 | eorl_flipped[y][FR] = 1; | ||
| 1775 | eorl_flipped[y][FL] = 1; | ||
| 1776 | eorl_flipped[y][BL] = 1; | ||
| 1777 | eorl_flipped[y][BR] = 1; | ||
| 1778 | |||
| 1779 | eoud_flipped[U][UF] = 1; | ||
| 1780 | eoud_flipped[U][UL] = 1; | ||
| 1781 | eoud_flipped[U][UB] = 1; | ||
| 1782 | eoud_flipped[U][UR] = 1; | ||
| 1783 | |||
| 1784 | eoud_flipped[x][UF] = 1; | ||
| 1785 | eoud_flipped[x][UB] = 1; | ||
| 1786 | eoud_flipped[x][DF] = 1; | ||
| 1787 | eoud_flipped[x][DB] = 1; | ||
| 1788 | |||
| 1789 | eoud_flipped[y][UF] = 1; | ||
| 1790 | eoud_flipped[y][UL] = 1; | ||
| 1791 | eoud_flipped[y][UB] = 1; | ||
| 1792 | eoud_flipped[y][UR] = 1; | ||
| 1793 | eoud_flipped[y][DF] = 1; | ||
| 1794 | eoud_flipped[y][DL] = 1; | ||
| 1795 | eoud_flipped[y][DB] = 1; | ||
| 1796 | eoud_flipped[y][DR] = 1; | ||
| 1797 | eoud_flipped[y][FR] = 1; | ||
| 1798 | eoud_flipped[y][FL] = 1; | ||
| 1799 | eoud_flipped[y][BL] = 1; | ||
| 1800 | eoud_flipped[y][BR] = 1; | ||
| 1801 | |||
| 1802 | coud_flipped[x][UFR] = 2; | ||
| 1803 | coud_flipped[x][UFL] = 1; | ||
| 1804 | coud_flipped[x][UBR] = 1; | ||
| 1805 | coud_flipped[x][UBL] = 2; | ||
| 1806 | coud_flipped[x][DFR] = 1; | ||
| 1807 | coud_flipped[x][DFL] = 2; | ||
| 1808 | coud_flipped[x][DBR] = 2; | ||
| 1809 | coud_flipped[x][DBL] = 1; | ||
| 1810 | |||
| 1811 | corl_flipped[U][UFR] = 1; | ||
| 1812 | corl_flipped[U][UFL] = 2; | ||
| 1813 | corl_flipped[U][UBL] = 1; | ||
| 1814 | corl_flipped[U][UBR] = 2; | ||
| 1815 | |||
| 1816 | corl_flipped[y][UFR] = 1; | ||
| 1817 | corl_flipped[y][UFL] = 2; | ||
| 1818 | corl_flipped[y][UBL] = 1; | ||
| 1819 | corl_flipped[y][UBR] = 2; | ||
| 1820 | corl_flipped[y][DFR] = 2; | ||
| 1821 | corl_flipped[y][DFL] = 1; | ||
| 1822 | corl_flipped[y][DBL] = 2; | ||
| 1823 | corl_flipped[y][DBR] = 1; | ||
| 1824 | |||
| 1825 | cofb_flipped[U][UFR] = 2; | ||
| 1826 | cofb_flipped[U][UFL] = 1; | ||
| 1827 | cofb_flipped[U][UBL] = 2; | ||
| 1828 | cofb_flipped[U][UBR] = 1; | ||
| 1829 | |||
| 1830 | cofb_flipped[x][UFR] = 1; | ||
| 1831 | cofb_flipped[x][UFL] = 2; | ||
| 1832 | cofb_flipped[x][UBL] = 1; | ||
| 1833 | cofb_flipped[x][UBR] = 2; | ||
| 1834 | cofb_flipped[x][DFR] = 2; | ||
| 1835 | cofb_flipped[x][DFL] = 1; | ||
| 1836 | cofb_flipped[x][DBL] = 2; | ||
| 1837 | cofb_flipped[x][DBR] = 1; | ||
| 1838 | |||
| 1839 | cofb_flipped[y][UFR] = 2; | ||
| 1840 | cofb_flipped[y][UFL] = 1; | ||
| 1841 | cofb_flipped[y][UBL] = 2; | ||
| 1842 | cofb_flipped[y][UBR] = 1; | ||
| 1843 | cofb_flipped[y][DFR] = 1; | ||
| 1844 | cofb_flipped[y][DFL] = 2; | ||
| 1845 | cofb_flipped[y][DBL] = 1; | ||
| 1846 | cofb_flipped[y][DBR] = 2; | ||
| 1847 | |||
| 1848 | /* Equivalent moves ***********/ | ||
| 1849 | equiv_alg[NULLMOVE] = new_alg(""); | ||
| 1850 | |||
| 1851 | equiv_alg[U] = new_alg(" U "); | ||
| 1852 | equiv_alg[U2] = new_alg(" UU "); | ||
| 1853 | equiv_alg[U3] = new_alg(" UUU "); | ||
| 1854 | equiv_alg[D] = new_alg(" xx U xx "); | ||
| 1855 | equiv_alg[D2] = new_alg(" xx UU xx "); | ||
| 1856 | equiv_alg[D3] = new_alg(" xx UUU xx "); | ||
| 1857 | equiv_alg[R] = new_alg(" yx U xxxyyy "); | ||
| 1858 | equiv_alg[R2] = new_alg(" yx UU xxxyyy "); | ||
| 1859 | equiv_alg[R3] = new_alg(" yx UUU xxxyyy "); | ||
| 1860 | equiv_alg[L] = new_alg(" yyyx U xxxy "); | ||
| 1861 | equiv_alg[L2] = new_alg(" yyyx UU xxxy "); | ||
| 1862 | equiv_alg[L3] = new_alg(" yyyx UUU xxxy "); | ||
| 1863 | equiv_alg[F] = new_alg(" x U xxx "); | ||
| 1864 | equiv_alg[F2] = new_alg(" x UU xxx "); | ||
| 1865 | equiv_alg[F3] = new_alg(" x UUU xxx "); | ||
| 1866 | equiv_alg[B] = new_alg(" xxx U x "); | ||
| 1867 | equiv_alg[B2] = new_alg(" xxx UU x "); | ||
| 1868 | equiv_alg[B3] = new_alg(" xxx UUU x "); | ||
| 1869 | |||
| 1870 | equiv_alg[Uw] = new_alg(" xx U xx y "); | ||
| 1871 | equiv_alg[Uw2] = new_alg(" xx UU xx yy "); | ||
| 1872 | equiv_alg[Uw3] = new_alg(" xx UUU xx yyy "); | ||
| 1873 | equiv_alg[Dw] = new_alg(" U yyy "); | ||
| 1874 | equiv_alg[Dw2] = new_alg(" UU yy "); | ||
| 1875 | equiv_alg[Dw3] = new_alg(" UUU y "); | ||
| 1876 | equiv_alg[Rw] = new_alg(" yyyx U xxxy x "); | ||
| 1877 | equiv_alg[Rw2] = new_alg(" yyyx UU xxxy xx "); | ||
| 1878 | equiv_alg[Rw3] = new_alg(" yyyx UUU xxxy xxx "); | ||
| 1879 | equiv_alg[Lw] = new_alg(" yx U xxxyyy xxx "); | ||
| 1880 | equiv_alg[Lw2] = new_alg(" yx UU xxxyyy xx "); | ||
| 1881 | equiv_alg[Lw3] = new_alg(" yx UUU xxxyyy x "); | ||
| 1882 | equiv_alg[Fw] = new_alg(" xxx U x yxxxyyy "); | ||
| 1883 | equiv_alg[Fw2] = new_alg(" xxx UU x yxxyyy "); | ||
| 1884 | equiv_alg[Fw3] = new_alg(" xxx UUU x yxyyy "); | ||
| 1885 | equiv_alg[Bw] = new_alg(" x U xxx yxyyy "); | ||
| 1886 | equiv_alg[Bw2] = new_alg(" x UU xxx yxxyyy "); | ||
| 1887 | equiv_alg[Bw3] = new_alg(" x UUU xxx yxxxyyy "); | ||
| 1888 | |||
| 1889 | equiv_alg[M] = new_alg(" yx U xx UUU yxyyy "); | ||
| 1890 | equiv_alg[M2] = new_alg(" yx UU xx UU xxxy "); | ||
| 1891 | equiv_alg[M3] = new_alg(" yx UUU xx U yxxxy "); | ||
| 1892 | equiv_alg[S] = new_alg(" x UUU xx U yyyx "); | ||
| 1893 | equiv_alg[S2] = new_alg(" x UU xx UU yyx "); | ||
| 1894 | equiv_alg[S3] = new_alg(" x U xx UUU yx "); | ||
| 1895 | equiv_alg[E] = new_alg(" U xx UUU xxyyy "); | ||
| 1896 | equiv_alg[E2] = new_alg(" UU xx UU xxyy "); | ||
| 1897 | equiv_alg[E3] = new_alg(" UUU xx U xxy "); | ||
| 1898 | |||
| 1899 | equiv_alg[x] = new_alg(" x "); | ||
| 1900 | equiv_alg[x2] = new_alg(" xx "); | ||
| 1901 | equiv_alg[x3] = new_alg(" xxx "); | ||
| 1902 | equiv_alg[y] = new_alg(" y "); | ||
| 1903 | equiv_alg[y2] = new_alg(" yy "); | ||
| 1904 | equiv_alg[y3] = new_alg(" yyy "); | ||
| 1905 | equiv_alg[z] = new_alg(" yyy x y "); | ||
| 1906 | equiv_alg[z2] = new_alg(" yy xx "); | ||
| 1907 | equiv_alg[z3] = new_alg(" y x yyy "); | ||
| 1908 | } | ||
| 1909 | |||
| 1910 | static void | ||
| 1911 | init_strings() | ||
| 1912 | { | ||
| 1913 | strcpy(move_string [NULLMOVE], "-" ); | ||
| 1914 | strcpy(move_string [U], "U" ); | ||
| 1915 | strcpy(move_string [U2], "U2" ); | ||
| 1916 | strcpy(move_string [U3], "U\'" ); | ||
| 1917 | strcpy(move_string [D], "D" ); | ||
| 1918 | strcpy(move_string [D2], "D2" ); | ||
| 1919 | strcpy(move_string [D3], "D\'" ); | ||
| 1920 | strcpy(move_string [R], "R" ); | ||
| 1921 | strcpy(move_string [R2], "R2" ); | ||
| 1922 | strcpy(move_string [R3], "R\'" ); | ||
| 1923 | strcpy(move_string [L], "L" ); | ||
| 1924 | strcpy(move_string [L2], "L2" ); | ||
| 1925 | strcpy(move_string [L3], "L\'" ); | ||
| 1926 | strcpy(move_string [F], "F" ); | ||
| 1927 | strcpy(move_string [F2], "F2" ); | ||
| 1928 | strcpy(move_string [F3], "F\'" ); | ||
| 1929 | strcpy(move_string [B], "B" ); | ||
| 1930 | strcpy(move_string [B2], "B2" ); | ||
| 1931 | strcpy(move_string [B3], "B\'" ); | ||
| 1932 | strcpy(move_string [Uw], "Uw" ); | ||
| 1933 | strcpy(move_string [Uw2], "Uw2" ); | ||
| 1934 | strcpy(move_string [Uw3], "Uw\'" ); | ||
| 1935 | strcpy(move_string [Dw], "Dw" ); | ||
| 1936 | strcpy(move_string [Dw2], "Dw2" ); | ||
| 1937 | strcpy(move_string [Dw3], "Dw\'" ); | ||
| 1938 | strcpy(move_string [Rw], "Rw" ); | ||
| 1939 | strcpy(move_string [Rw2], "Rw2" ); | ||
| 1940 | strcpy(move_string [Rw3], "Rw\'" ); | ||
| 1941 | strcpy(move_string [Lw], "Lw" ); | ||
| 1942 | strcpy(move_string [Lw2], "Lw2" ); | ||
| 1943 | strcpy(move_string [Lw3], "Lw\'" ); | ||
| 1944 | strcpy(move_string [Fw], "Fw" ); | ||
| 1945 | strcpy(move_string [Fw2], "Fw2" ); | ||
| 1946 | strcpy(move_string [Fw3], "Fw\'" ); | ||
| 1947 | strcpy(move_string [Bw], "Bw" ); | ||
| 1948 | strcpy(move_string [Bw2], "Bw2" ); | ||
| 1949 | strcpy(move_string [Bw3], "Bw\'" ); | ||
| 1950 | strcpy(move_string [M], "M" ); | ||
| 1951 | strcpy(move_string [M2], "M2" ); | ||
| 1952 | strcpy(move_string [M3], "M\'" ); | ||
| 1953 | strcpy(move_string [S], "S" ); | ||
| 1954 | strcpy(move_string [S2], "S2" ); | ||
| 1955 | strcpy(move_string [S3], "S\'" ); | ||
| 1956 | strcpy(move_string [E], "E" ); | ||
| 1957 | strcpy(move_string [E2], "E2" ); | ||
| 1958 | strcpy(move_string [E3], "E\'" ); | ||
| 1959 | strcpy(move_string [x], "x" ); | ||
| 1960 | strcpy(move_string [x2], "x2" ); | ||
| 1961 | strcpy(move_string [x3], "x\'" ); | ||
| 1962 | strcpy(move_string [y], "y" ); | ||
| 1963 | strcpy(move_string [y2], "y2" ); | ||
| 1964 | strcpy(move_string [y3], "y\'" ); | ||
| 1965 | strcpy(move_string [z], "z" ); | ||
| 1966 | strcpy(move_string [z2], "z2" ); | ||
| 1967 | strcpy(move_string [z3], "z\'" ); | ||
| 1968 | |||
| 1969 | strcpy(edge_string [UF], "UF" ); | ||
| 1970 | strcpy(edge_string [UL], "UL" ); | ||
| 1971 | strcpy(edge_string [UB], "UB" ); | ||
| 1972 | strcpy(edge_string [UR], "UR" ); | ||
| 1973 | strcpy(edge_string [DF], "DF" ); | ||
| 1974 | strcpy(edge_string [DL], "DL" ); | ||
| 1975 | strcpy(edge_string [DB], "DB" ); | ||
| 1976 | strcpy(edge_string [DR], "DR" ); | ||
| 1977 | strcpy(edge_string [FR], "FR" ); | ||
| 1978 | strcpy(edge_string [FL], "FL" ); | ||
| 1979 | strcpy(edge_string [BL], "BL" ); | ||
| 1980 | strcpy(edge_string [BR], "BR" ); | ||
| 1981 | |||
| 1982 | strcpy(corner_string [UFR], "UFR" ); | ||
| 1983 | strcpy(corner_string [UFL], "UFL" ); | ||
| 1984 | strcpy(corner_string [UBL], "UBL" ); | ||
| 1985 | strcpy(corner_string [UBR], "UBR" ); | ||
| 1986 | strcpy(corner_string [DFR], "DFR" ); | ||
| 1987 | strcpy(corner_string [DFL], "DFL" ); | ||
| 1988 | strcpy(corner_string [DBL], "DBL" ); | ||
| 1989 | strcpy(corner_string [DBR], "DBR" ); | ||
| 1990 | |||
| 1991 | strcpy(center_string [U_center], "U" ); | ||
| 1992 | strcpy(center_string [D_center], "D" ); | ||
| 1993 | strcpy(center_string [R_center], "R" ); | ||
| 1994 | strcpy(center_string [L_center], "L" ); | ||
| 1995 | strcpy(center_string [F_center], "F" ); | ||
| 1996 | strcpy(center_string [B_center], "B" ); | ||
| 1997 | } | ||
| 1998 | |||
| 1999 | static void | ||
| 2000 | init_trans() { | ||
| 2001 | Cube aux, cube, c[3]; | ||
| 2002 | CubeArray epcp; | ||
| 2003 | int eparr[12], eoarr[12]; | ||
| 2004 | int cparr[8], coarr[8]; | ||
| 2005 | int i; | ||
| 2006 | unsigned int ui; | ||
| 2007 | bool b1, b2, b3; | ||
| 2008 | Move mi, move; | ||
| 2009 | Trans m; | ||
| 2010 | |||
| 2011 | /* Compute sources */ | ||
| 2012 | for (i = 0; i < NTRANS; i++) { | ||
| 2013 | if (i == mirror) | ||
| 2014 | cube = (Cube){0}; | ||
| 2015 | else | ||
| 2016 | cube = apply_alg(trans_algs[i], (Cube){0}); | ||
| 2017 | |||
| 2018 | epose_source[i] = edge_slice(what_edge_at(cube, FR)); | ||
| 2019 | eposs_source[i] = edge_slice(what_edge_at(cube, UR)); | ||
| 2020 | eposm_source[i] = edge_slice(what_edge_at(cube, UF)); | ||
| 2021 | eofb_source[i] = what_center_at(cube, F_center)/2; | ||
| 2022 | eorl_source[i] = what_center_at(cube, R_center)/2; | ||
| 2023 | eoud_source[i] = what_center_at(cube, U_center)/2; | ||
| 2024 | coud_source[i] = what_center_at(cube, U_center)/2; | ||
| 2025 | cofb_source[i] = what_center_at(cube, F_center)/2; | ||
| 2026 | corl_source[i] = what_center_at(cube, R_center)/2; | ||
| 2027 | } | ||
| 2028 | |||
| 2029 | if (read_ttables_file()) | ||
| 2030 | return; | ||
| 2031 | |||
| 2032 | fprintf(stderr, "Cannot load %s, generating it\n", "ttables"); | ||
| 2033 | |||
| 2034 | /* Initialize tables */ | ||
| 2035 | for (m = 0; m < NTRANS; m++) { | ||
| 2036 | if (m == mirror) { | ||
| 2037 | memcpy(eparr, ep_mirror, 12 * sizeof(int)); | ||
| 2038 | memcpy(cparr, cp_mirror, 8 * sizeof(int)); | ||
| 2039 | } else { | ||
| 2040 | epcp = (CubeArray){ .ep = eparr, .cp = cparr }; | ||
| 2041 | cube = apply_alg(trans_algs[m], (Cube){0}); | ||
| 2042 | cube_to_arrays(cube, &epcp, pf_epcp); | ||
| 2043 | } | ||
| 2044 | |||
| 2045 | for (ui = 0; ui < FACTORIAL12/FACTORIAL8; ui++) { | ||
| 2046 | c[0] = admissible_ep((Cube){ .epose = ui }, pf_e); | ||
| 2047 | c[1] = admissible_ep((Cube){ .eposs = ui }, pf_s); | ||
| 2048 | c[2] = admissible_ep((Cube){ .eposm = ui }, pf_m); | ||
| 2049 | |||
| 2050 | cube = rotate_via_compose(m,c[epose_source[m]],pf_ep); | ||
| 2051 | epose_ttable[m][ui] = cube.epose; | ||
| 2052 | |||
| 2053 | cube = rotate_via_compose(m,c[eposs_source[m]],pf_ep); | ||
| 2054 | eposs_ttable[m][ui] = cube.eposs; | ||
| 2055 | |||
| 2056 | cube = rotate_via_compose(m,c[eposm_source[m]],pf_ep); | ||
| 2057 | eposm_ttable[m][ui] = cube.eposm; | ||
| 2058 | } | ||
| 2059 | for (ui = 0; ui < POW2TO11; ui++ ) { | ||
| 2060 | int_to_sum_zero_array(ui, 2, 12, eoarr); | ||
| 2061 | apply_permutation(eparr, eoarr, 12); | ||
| 2062 | eo_ttable[m][ui] = digit_array_to_int(eoarr, 11, 2); | ||
| 2063 | } | ||
| 2064 | for (ui = 0; ui < POW3TO7; ui++) { | ||
| 2065 | int_to_sum_zero_array(ui, 3, 8, coarr); | ||
| 2066 | apply_permutation(cparr, coarr, 8); | ||
| 2067 | co_ttable[m][ui] = digit_array_to_int(coarr, 7, 3); | ||
| 2068 | if (m == mirror) | ||
| 2069 | co_ttable[m][ui] = | ||
| 2070 | invert_digits(co_ttable[m][ui], 3, 7); | ||
| 2071 | } | ||
| 2072 | for (ui = 0; ui < FACTORIAL8; ui++) { | ||
| 2073 | cube = (Cube){ .cp = ui }; | ||
| 2074 | cube = rotate_via_compose(m, cube, pf_cp); | ||
| 2075 | cp_ttable[m][ui] = cube.cp; | ||
| 2076 | } | ||
| 2077 | for (ui = 0; ui < FACTORIAL6; ui++) { | ||
| 2078 | cube = (Cube){ .cpos = ui }; | ||
| 2079 | cube = rotate_via_compose(m, cube, pf_cpos); | ||
| 2080 | cpos_ttable[m][ui] = cube.cpos; | ||
| 2081 | } | ||
| 2082 | for (mi = 0; mi < NMOVES; mi++) { | ||
| 2083 | if (m == mirror) { | ||
| 2084 | b1 = (mi >= U && mi <= Bw3); | ||
| 2085 | b2 = (mi >= S && mi <= E3); | ||
| 2086 | b3 = (mi >= x && mi <= z3); | ||
| 2087 | if (b1 || b2 || b3) | ||
| 2088 | moves_ttable[m][mi] = | ||
| 2089 | inverse_move_aux[mi]; | ||
| 2090 | else | ||
| 2091 | moves_ttable[m][mi] = mi; | ||
| 2092 | |||
| 2093 | if ((mi-1)/3==(R-1)/3 || (mi-1)/3==(Rw-1)/3) | ||
| 2094 | moves_ttable[m][mi] += 3; | ||
| 2095 | if ((mi-1)/3==(L-1)/3 || (mi-1)/3==(L2-1)/3) | ||
| 2096 | moves_ttable[m][mi] -= 3; | ||
| 2097 | } else { | ||
| 2098 | aux = apply_trans(m, apply_move(mi,(Cube){0})); | ||
| 2099 | for (move = 0; move < NMOVES; move++) { | ||
| 2100 | cube = apply_move( | ||
| 2101 | inverse_move_aux[move], aux); | ||
| 2102 | if (is_solved(cube, false)) | ||
| 2103 | moves_ttable[m][mi] = move; | ||
| 2104 | } | ||
| 2105 | } | ||
| 2106 | } | ||
| 2107 | } | ||
| 2108 | |||
| 2109 | if (!write_ttables_file()) | ||
| 2110 | fprintf(stderr, "Error writing ttables\n"); | ||
| 2111 | } | ||
| 2112 | |||
| 2113 | static void | ||
| 2114 | init_trans_aux() | ||
| 2115 | { | ||
| 2116 | ep_mirror[UF] = UF; | ||
| 2117 | ep_mirror[UL] = UR; | ||
| 2118 | ep_mirror[UB] = UB; | ||
| 2119 | ep_mirror[UR] = UL; | ||
| 2120 | ep_mirror[DF] = DF; | ||
| 2121 | ep_mirror[DL] = DR; | ||
| 2122 | ep_mirror[DB] = DB; | ||
| 2123 | ep_mirror[DR] = DL; | ||
| 2124 | ep_mirror[FR] = FL; | ||
| 2125 | ep_mirror[FL] = FR; | ||
| 2126 | ep_mirror[BR] = BL; | ||
| 2127 | ep_mirror[BL] = BR; | ||
| 2128 | |||
| 2129 | cp_mirror[UFR] = UFL; | ||
| 2130 | cp_mirror[UFL] = UFR; | ||
| 2131 | cp_mirror[UBL] = UBR; | ||
| 2132 | cp_mirror[UBR] = UBL; | ||
| 2133 | cp_mirror[DFR] = DFL; | ||
| 2134 | cp_mirror[DFL] = DFR; | ||
| 2135 | cp_mirror[DBL] = DBR; | ||
| 2136 | cp_mirror[DBR] = DBL; | ||
| 2137 | |||
| 2138 | cpos_mirror[U_center] = U_center; | ||
| 2139 | cpos_mirror[D_center] = D_center; | ||
| 2140 | cpos_mirror[R_center] = L_center; | ||
| 2141 | cpos_mirror[L_center] = R_center; | ||
| 2142 | cpos_mirror[F_center] = F_center; | ||
| 2143 | cpos_mirror[B_center] = B_center; | ||
| 2144 | |||
| 2145 | /* Is there a more elegant way? */ | ||
| 2146 | trans_algs[uf] = new_alg(""); | ||
| 2147 | trans_algs[ur] = new_alg("y"); | ||
| 2148 | trans_algs[ub] = new_alg("y2"); | ||
| 2149 | trans_algs[ul] = new_alg("y3"); | ||
| 2150 | |||
| 2151 | trans_algs[df] = new_alg("z2"); | ||
| 2152 | trans_algs[dr] = new_alg("y z2"); | ||
| 2153 | trans_algs[db] = new_alg("x2"); | ||
| 2154 | trans_algs[dl] = new_alg("y3 z2"); | ||
| 2155 | |||
| 2156 | trans_algs[rf] = new_alg("z3"); | ||
| 2157 | trans_algs[rd] = new_alg("z3 y"); | ||
| 2158 | trans_algs[rb] = new_alg("z3 y2"); | ||
| 2159 | trans_algs[ru] = new_alg("z3 y3"); | ||
| 2160 | |||
| 2161 | trans_algs[lf] = new_alg("z"); | ||
| 2162 | trans_algs[ld] = new_alg("z y3"); | ||
| 2163 | trans_algs[lb] = new_alg("z y2"); | ||
| 2164 | trans_algs[lu] = new_alg("z y"); | ||
| 2165 | |||
| 2166 | trans_algs[fu] = new_alg("x y2"); | ||
| 2167 | trans_algs[fr] = new_alg("x y"); | ||
| 2168 | trans_algs[fd] = new_alg("x"); | ||
| 2169 | trans_algs[fl] = new_alg("x y3"); | ||
| 2170 | |||
| 2171 | trans_algs[bu] = new_alg("x3"); | ||
| 2172 | trans_algs[br] = new_alg("x3 y"); | ||
| 2173 | trans_algs[bd] = new_alg("x3 y2"); | ||
| 2174 | trans_algs[bl] = new_alg("x3 y3"); | ||
| 2175 | } | ||
| 2176 | |||
| 2177 | |||
| 2178 | /* Public functions implementation *******************************************/ | ||
| 2179 | |||
| 2180 | Cube | ||
| 2181 | apply_alg(Alg *alg, Cube cube) | ||
| 2182 | { | ||
| 2183 | return apply_alg_generic(alg, cube, pf_all, true); | ||
| 2184 | } | ||
| 2185 | |||
| 2186 | Cube | ||
| 2187 | apply_move(Move m, Cube cube) | ||
| 2188 | { | ||
| 2189 | return (Cube) { | ||
| 2190 | .epose = epose_mtable[m][cube.epose], | ||
| 2191 | .eposs = eposs_mtable[m][cube.eposs], | ||
| 2192 | .eposm = eposm_mtable[m][cube.eposm], | ||
| 2193 | .eofb = eofb_mtable[m][cube.eofb], | ||
| 2194 | .eorl = eorl_mtable[m][cube.eorl], | ||
| 2195 | .eoud = eoud_mtable[m][cube.eoud], | ||
| 2196 | .coud = coud_mtable[m][cube.coud], | ||
| 2197 | .cofb = cofb_mtable[m][cube.cofb], | ||
| 2198 | .corl = corl_mtable[m][cube.corl], | ||
| 2199 | .cp = cp_mtable[m][cube.cp], | ||
| 2200 | .cpos = cpos_mtable[m][cube.cpos] | ||
| 2201 | }; | ||
| 2202 | } | ||
| 2203 | |||
| 2204 | Cube | ||
| 2205 | apply_trans(Trans t, Cube cube) | ||
| 2206 | { | ||
| 2207 | int aux_epos[3] = { cube.epose, cube.eposs, cube.eposm }; | ||
| 2208 | int aux_eo[3] = { cube.eoud, cube.eorl, cube.eofb }; | ||
| 2209 | int aux_co[3] = { cube.coud, cube.corl, cube.cofb }; | ||
| 2210 | |||
| 2211 | return (Cube) { | ||
| 2212 | .epose = epose_ttable[t][aux_epos[epose_source[t]]], | ||
| 2213 | .eposs = eposs_ttable[t][aux_epos[eposs_source[t]]], | ||
| 2214 | .eposm = eposm_ttable[t][aux_epos[eposm_source[t]]], | ||
| 2215 | .eofb = eo_ttable[t][aux_eo[eofb_source[t]]], | ||
| 2216 | .eorl = eo_ttable[t][aux_eo[eorl_source[t]]], | ||
| 2217 | .eoud = eo_ttable[t][aux_eo[eoud_source[t]]], | ||
| 2218 | .coud = co_ttable[t][aux_co[coud_source[t]]], | ||
| 2219 | .corl = co_ttable[t][aux_co[corl_source[t]]], | ||
| 2220 | .cofb = co_ttable[t][aux_co[cofb_source[t]]], | ||
| 2221 | .cp = cp_ttable[t][cube.cp], | ||
| 2222 | .cpos = cpos_ttable[t][cube.cpos] | ||
| 2223 | }; | ||
| 2224 | } | ||
| 2225 | |||
| 2226 | Move | ||
| 2227 | base_move(Move m) | ||
| 2228 | { | ||
| 2229 | if (m == NULLMOVE) | ||
| 2230 | return NULLMOVE; | ||
| 2231 | else | ||
| 2232 | return m - (m-1)%3; | ||
| 2233 | } | ||
| 2234 | |||
| 2235 | Cube | ||
| 2236 | compose(Cube c2, Cube c1) | ||
| 2237 | { | ||
| 2238 | return compose_filtered(c2, c1, pf_all); | ||
| 2239 | } | ||
| 2240 | |||
| 2241 | uint64_t | ||
| 2242 | cphtr(Cube cube) | ||
| 2243 | { | ||
| 2244 | return cphtr_cosets[cube.cp]; | ||
| 2245 | } | ||
| 2246 | |||
| 2247 | uint64_t | ||
| 2248 | epos_dependent(Cube c) | ||
| 2249 | { | ||
| 2250 | return epos_dependent_aux[c.eposs/FACTORIAL4][c.epose/FACTORIAL4]; | ||
| 2251 | } | ||
| 2252 | |||
| 2253 | bool | ||
| 2254 | equal(Cube c1, Cube c2) | ||
| 2255 | { | ||
| 2256 | return c1.eofb == c2.eofb && | ||
| 2257 | c1.epose == c2.epose && | ||
| 2258 | c1.eposs == c2.eposs && | ||
| 2259 | c1.eposm == c2.eposm && | ||
| 2260 | c1.coud == c2.coud && | ||
| 2261 | c1.cp == c2.cp && | ||
| 2262 | c1.cpos == c2.cpos; | ||
| 2263 | } | ||
| 2264 | |||
| 2265 | void | ||
| 2266 | genalgset(AlgSet *as) | ||
| 2267 | { | ||
| 2268 | uint64_t i; | ||
| 2269 | |||
| 2270 | if (as->generated) | ||
| 2271 | return; | ||
| 2272 | |||
| 2273 | /* TODO: check if memory is enough, otherwise maybe crash gracefully? */ | ||
| 2274 | as->table = malloc(as->size * sizeof(AlgList *)); | ||
| 2275 | |||
| 2276 | if (read_algset_file(as)) { | ||
| 2277 | as->generated = true; | ||
| 2278 | return; | ||
| 2279 | } | ||
| 2280 | |||
| 2281 | fprintf(stderr, "Cannot load %s, generating it\n", as->filename); | ||
| 2282 | |||
| 2283 | for (i = 0; i < as->size; i++) { | ||
| 2284 | as->table[i] = solve(as->antindex(i), as->step, &as->opts); | ||
| 2285 | fprintf(stderr, "Generated %lu / %lu cases\n", i, as->size); | ||
| 2286 | } | ||
| 2287 | |||
| 2288 | if (!write_algset_file(as)) | ||
| 2289 | fprintf(stderr, "Error writing algset file\n"); | ||
| 2290 | |||
| 2291 | as->generated = true; | ||
| 2292 | } | ||
| 2293 | |||
| 2294 | void | ||
| 2295 | genptable(PruneData *pd) | ||
| 2296 | { | ||
| 2297 | uint64_t j; | ||
| 2298 | DfsData dd = { | ||
| 2299 | .m = 0, | ||
| 2300 | .last1 = NULLMOVE, | ||
| 2301 | .last2 = NULLMOVE | ||
| 2302 | }; | ||
| 2303 | |||
| 2304 | if (pd->generated) | ||
| 2305 | return; | ||
| 2306 | |||
| 2307 | /* TODO: check if memory is enough, otherwise maybe crash gracefully? */ | ||
| 2308 | pd->ptable = malloc(ptablesize(pd) * sizeof(uint8_t)); | ||
| 2309 | |||
| 2310 | if (read_ptable_file(pd)) { | ||
| 2311 | pd->generated = true; | ||
| 2312 | return; | ||
| 2313 | } | ||
| 2314 | |||
| 2315 | fprintf(stderr, "Cannot load %s, generating it\n", pd->filename); | ||
| 2316 | |||
| 2317 | /* We use 4 bits per value, so any distance >= 15 is set to 15 */ | ||
| 2318 | for (j = 0; j < pd->size; j++) | ||
| 2319 | ptable_update(pd, j, 15); | ||
| 2320 | |||
| 2321 | moveset_to_list(pd->moveset, NULL, dd.sorted_moves); | ||
| 2322 | movelist_to_position(dd.sorted_moves, dd.move_position); | ||
| 2323 | |||
| 2324 | pd->reached = malloc(ptablesize(pd) * sizeof(uint8_t)); | ||
| 2325 | for (dd.d = 0, pd->n = 0; dd.d < 15 && pd->n < pd->size; dd.d++) { | ||
| 2326 | memset(pd->reached, 0, ptablesize(pd)*sizeof(uint8_t)); | ||
| 2327 | genptable_dfs((Cube){0}, pd, &dd); | ||
| 2328 | fprintf(stderr, "Depth %d completed, generated %lu/%lu\n", | ||
| 2329 | dd.d, pd->n, pd->size); | ||
| 2330 | } | ||
| 2331 | |||
| 2332 | if (!write_ptable_file(pd)) | ||
| 2333 | fprintf(stderr, "Error writing ptable file\n"); | ||
| 2334 | |||
| 2335 | pd->generated = true; | ||
| 2336 | free(pd->reached); | ||
| 2337 | } | ||
| 2338 | |||
| 2339 | Cube | ||
| 2340 | inverse_cube(Cube cube) | ||
| 2341 | { | ||
| 2342 | CubeArray *arr = new_cubearray(cube, pf_all); | ||
| 2343 | CubeArray *inv = new_cubearray((Cube){0}, pf_all); | ||
| 2344 | Cube ret; | ||
| 2345 | int i; | ||
| 2346 | |||
| 2347 | for (i = 0; i < 12; i++) { | ||
| 2348 | inv->ep[arr->ep[i]] = i; | ||
| 2349 | inv->eofb[arr->ep[i]] = arr->eofb[i]; | ||
| 2350 | inv->eorl[arr->ep[i]] = arr->eorl[i]; | ||
| 2351 | inv->eoud[arr->ep[i]] = arr->eoud[i]; | ||
| 2352 | } | ||
| 2353 | |||
| 2354 | for (i = 0; i < 8; i++) { | ||
| 2355 | inv->cp[arr->cp[i]] = i; | ||
| 2356 | inv->coud[arr->cp[i]] = (3 - arr->coud[i]) % 3; | ||
| 2357 | inv->corl[arr->cp[i]] = (3 - arr->corl[i]) % 3; | ||
| 2358 | inv->cofb[arr->cp[i]] = (3 - arr->cofb[i]) % 3; | ||
| 2359 | } | ||
| 2360 | |||
| 2361 | for (int i = 0; i < 6; i++) | ||
| 2362 | inv->cpos[arr->cpos[i]] = i; | ||
| 2363 | |||
| 2364 | ret = arrays_to_cube(inv, pf_all); | ||
| 2365 | free_cubearray(arr, pf_all); | ||
| 2366 | free_cubearray(inv, pf_all); | ||
| 2367 | |||
| 2368 | return ret; | ||
| 2369 | } | ||
| 2370 | |||
| 2371 | Move | ||
| 2372 | inverse_move(Move m) | ||
| 2373 | { | ||
| 2374 | return inverse_move_aux[m]; | ||
| 2375 | } | ||
| 2376 | |||
| 2377 | Trans | ||
| 2378 | inverse_trans(Trans t) | ||
| 2379 | { | ||
| 2380 | return inverse_trans_aux[t]; | ||
| 2381 | } | ||
| 2382 | |||
| 2383 | bool | ||
| 2384 | is_admissible(Cube cube) | ||
| 2385 | { | ||
| 2386 | /* TODO: this should check consistency of different orientations */ | ||
| 2387 | /* TODO: check that centers are opposite and admissible */ | ||
| 2388 | |||
| 2389 | CubeArray *a = new_cubearray(cube, pf_all); | ||
| 2390 | int parity; | ||
| 2391 | bool perm; | ||
| 2392 | |||
| 2393 | perm = is_perm(a->ep, 12) && | ||
| 2394 | is_perm(a->cp, 8) && | ||
| 2395 | is_perm(a->cpos, 6); | ||
| 2396 | parity = perm_sign(a->ep, 12) + | ||
| 2397 | perm_sign(a->cp, 8) + | ||
| 2398 | perm_sign(a->cpos, 6); | ||
| 2399 | |||
| 2400 | return perm && parity % 2 == 0; | ||
| 2401 | } | ||
| 2402 | |||
| 2403 | bool | ||
| 2404 | is_solved(Cube cube, bool reorient) | ||
| 2405 | { | ||
| 2406 | Trans i; | ||
| 2407 | |||
| 2408 | if (reorient) | ||
| 2409 | for (i = 0; i < NROTATIONS; i++) | ||
| 2410 | if (is_solved(apply_alg(trans_algs[i],cube), false)) | ||
| 2411 | return true; | ||
| 2412 | |||
| 2413 | return equal(cube, (Cube){0}); | ||
| 2414 | } | ||
| 2415 | |||
| 2416 | bool | ||
| 2417 | is_solved_block(Cube cube, Block block) | ||
| 2418 | { | ||
| 2419 | int i; | ||
| 2420 | |||
| 2421 | for (i = 0; i < 12; i++) | ||
| 2422 | if (block.edge[i] && !is_solved_edge(cube, i)) | ||
| 2423 | return false; | ||
| 2424 | for (i = 0; i < 8; i++) | ||
| 2425 | if (block.corner[i] && !is_solved_corner(cube, i)) | ||
| 2426 | return false; | ||
| 2427 | for (i = 0; i < 6; i++) | ||
| 2428 | if (block.center[i] && !is_solved_center(cube, i)) | ||
| 2429 | return false; | ||
| 2430 | |||
| 2431 | return true; | ||
| 2432 | } | ||
| 2433 | |||
| 2434 | bool | ||
| 2435 | is_solved_center(Cube cube, Center c) | ||
| 2436 | { | ||
| 2437 | return what_center_at(cube, c) == c; | ||
| 2438 | } | ||
| 2439 | |||
| 2440 | bool | ||
| 2441 | is_solved_corner(Cube cube, Corner c) | ||
| 2442 | { | ||
| 2443 | return what_corner_at(cube, c) == c && | ||
| 2444 | what_orientation_corner(cube.coud, c); | ||
| 2445 | } | ||
| 2446 | |||
| 2447 | bool | ||
| 2448 | is_solved_edge(Cube cube, Edge e) | ||
| 2449 | { | ||
| 2450 | return what_edge_at(cube, e) == e && | ||
| 2451 | what_orientation_edge(cube.eofb, e); | ||
| 2452 | } | ||
| 2453 | |||
| 2454 | int | ||
| 2455 | piece_orientation(Cube cube, int piece, char *orientation) | ||
| 2456 | { | ||
| 2457 | int arr[12], n, b, x; | ||
| 2458 | |||
| 2459 | if (!strcmp(orientation, "eofb")) { | ||
| 2460 | x = cube.eofb; | ||
| 2461 | n = 12; | ||
| 2462 | b = 2; | ||
| 2463 | } else if (!strcmp(orientation, "eorl")) { | ||
| 2464 | x = cube.eorl; | ||
| 2465 | n = 12; | ||
| 2466 | b = 2; | ||
| 2467 | } else if (!strcmp(orientation, "eoud")) { | ||
| 2468 | x = cube.eoud; | ||
| 2469 | n = 12; | ||
| 2470 | b = 2; | ||
| 2471 | } else if (!strcmp(orientation, "coud")) { | ||
| 2472 | x = cube.coud; | ||
| 2473 | n = 8; | ||
| 2474 | b = 3; | ||
| 2475 | } else if (!strcmp(orientation, "corl")) { | ||
| 2476 | x = cube.corl; | ||
| 2477 | n = 8; | ||
| 2478 | b = 3; | ||
| 2479 | } else if (!strcmp(orientation, "cofb")) { | ||
| 2480 | x = cube.cofb; | ||
| 2481 | n = 8; | ||
| 2482 | b = 3; | ||
| 2483 | } else { | ||
| 2484 | return -1; | ||
| 2485 | } | ||
| 2486 | |||
| 2487 | int_to_sum_zero_array(x, b, n, arr); | ||
| 2488 | if (piece < n) | ||
| 2489 | return arr[piece]; | ||
| 2490 | |||
| 2491 | return -1; | ||
| 2492 | } | ||
| 2493 | |||
| 2494 | void | ||
| 2495 | print_cube(Cube cube) | ||
| 2496 | { | ||
| 2497 | /* | ||
| 2498 | CubeArray *arr = new_cubearray(cube, pf_all); | ||
| 2499 | |||
| 2500 | for (int i = 0; i < 12; i++) | ||
| 2501 | printf(" %s ", edge_string[arr->ep[i]]); | ||
| 2502 | printf("\n"); | ||
| 2503 | |||
| 2504 | for (int i = 0; i < 12; i++) | ||
| 2505 | printf(" %c ", arr->eofb[i] + '0'); | ||
| 2506 | printf("\n"); | ||
| 2507 | |||
| 2508 | for (int i = 0; i < 8; i++) | ||
| 2509 | printf("%s ", corner_string[arr->cp[i]]); | ||
| 2510 | printf("\n"); | ||
| 2511 | |||
| 2512 | for (int i = 0; i < 8; i++) | ||
| 2513 | printf(" %c ", arr->coud[i] + '0'); | ||
| 2514 | printf("\n"); | ||
| 2515 | |||
| 2516 | for (int i = 0; i < 6; i++) | ||
| 2517 | printf(" %s ", center_string[arr->cpos[i]]); | ||
| 2518 | printf("\n"); | ||
| 2519 | |||
| 2520 | free_cubearray(arr, pf_all); | ||
| 2521 | */ | ||
| 2522 | |||
| 2523 | for (int i = 0; i < 12; i++) | ||
| 2524 | printf(" %s ", edge_string[what_edge_at(cube, i)]); | ||
| 2525 | printf("\n"); | ||
| 2526 | |||
| 2527 | for (int i = 0; i < 12; i++) | ||
| 2528 | printf(" %d ", what_orientation_edge(cube.eofb, i)); | ||
| 2529 | printf("\n"); | ||
| 2530 | |||
| 2531 | for (int i = 0; i < 8; i++) | ||
| 2532 | printf("%s ", corner_string[what_corner_at(cube, i)]); | ||
| 2533 | printf("\n"); | ||
| 2534 | |||
| 2535 | for (int i = 0; i < 8; i++) | ||
| 2536 | printf(" %d ", what_orientation_corner(cube.coud, i)); | ||
| 2537 | printf("\n"); | ||
| 2538 | |||
| 2539 | for (int i = 0; i < 6; i++) | ||
| 2540 | printf(" %s ", center_string[what_center_at(cube, i)]); | ||
| 2541 | printf("\n"); | ||
| 2542 | |||
| 2543 | } | ||
| 2544 | |||
| 2545 | Cube | ||
| 2546 | random_cube() | ||
| 2547 | { | ||
| 2548 | CubeArray *arr = new_cubearray((Cube){0}, pf_4val); | ||
| 2549 | Cube ret; | ||
| 2550 | int ep, cp, eo, co; | ||
| 2551 | |||
| 2552 | ep = rand() % FACTORIAL12; | ||
| 2553 | cp = rand() % FACTORIAL8; | ||
| 2554 | eo = rand() % POW2TO11; | ||
| 2555 | co = rand() % POW3TO7; | ||
| 2556 | |||
| 2557 | index_to_perm(ep, 12, arr->ep); | ||
| 2558 | index_to_perm(cp, 8, arr->cp); | ||
| 2559 | int_to_sum_zero_array(eo, 2, 12, arr->eofb); | ||
| 2560 | int_to_sum_zero_array(co, 3, 8, arr->coud); | ||
| 2561 | |||
| 2562 | if (perm_sign(arr->ep, 12) != perm_sign(arr->cp, 8)) | ||
| 2563 | swap(&(arr->ep[0]), &(arr->ep[1])); | ||
| 2564 | |||
| 2565 | ret = arrays_to_cube(arr, pf_4val); | ||
| 2566 | free_cubearray(arr, pf_4val); | ||
| 2567 | |||
| 2568 | return ret; | ||
| 2569 | } | ||
| 2570 | |||
| 2571 | AlgList * | ||
| 2572 | solve(Cube cube, Step step, SolveOptions *opts) | ||
| 2573 | { | ||
| 2574 | AlgListNode *node; | ||
| 2575 | AlgList *sols = new_alglist(); | ||
| 2576 | Cube c = apply_trans(opts->pre_trans, cube); | ||
| 2577 | DfsData dd = { | ||
| 2578 | .m = 0, | ||
| 2579 | .niss = false, | ||
| 2580 | .lb = -1, | ||
| 2581 | .last1 = NULLMOVE, | ||
| 2582 | .last2 = NULLMOVE, | ||
| 2583 | .sols = sols, | ||
| 2584 | .current_alg = new_alg("") | ||
| 2585 | }; | ||
| 2586 | |||
| 2587 | if (step.ready != NULL && step.ready(c, 1) != 0) { | ||
| 2588 | fprintf(stderr, "Cube not ready for solving step\n"); | ||
| 2589 | return sols; | ||
| 2590 | } | ||
| 2591 | |||
| 2592 | moveset_to_list(step.moveset, step.check, dd.sorted_moves); | ||
| 2593 | movelist_to_position(dd.sorted_moves, dd.move_position); | ||
| 2594 | |||
| 2595 | for (dd.d = opts->min_moves; | ||
| 2596 | dd.d <= opts->max_moves && !(sols->len && opts->optimal_only); | ||
| 2597 | dd.d++) { | ||
| 2598 | if (opts->feedback) | ||
| 2599 | fprintf(stderr, | ||
| 2600 | "Found %d solutions, searching depth %d...\n", | ||
| 2601 | sols->len, dd.d); | ||
| 2602 | dfs(c, step, opts, &dd); | ||
| 2603 | } | ||
| 2604 | |||
| 2605 | for (node = sols->first; node != NULL; node = node->next) | ||
| 2606 | transform_alg(inverse_trans_aux[opts->pre_trans], node->alg); | ||
| 2607 | |||
| 2608 | free_alg(dd.current_alg); | ||
| 2609 | return sols; | ||
| 2610 | } | ||
| 2611 | |||
| 2612 | Alg * | ||
| 2613 | inverse_alg(Alg *alg) | ||
| 2614 | { | ||
| 2615 | Alg *ret = new_alg(""); | ||
| 2616 | int i; | ||
| 2617 | |||
| 2618 | for (i = alg->len-1; i >= 0; i--) | ||
| 2619 | append_move(ret, alg->move[i], alg->inv[i]); | ||
| 2620 | |||
| 2621 | return ret; | ||
| 2622 | } | ||
| 2623 | |||
| 2624 | Alg * | ||
| 2625 | new_alg(char *str) | ||
| 2626 | { | ||
| 2627 | Alg *alg = malloc(sizeof(Alg)); | ||
| 2628 | int i; | ||
| 2629 | bool niss = false; | ||
| 2630 | Move j, m; | ||
| 2631 | |||
| 2632 | alg->move = malloc(30 * sizeof(Move)); | ||
| 2633 | alg->inv = malloc(30 * sizeof(bool)); | ||
| 2634 | alg->allocated = 30; | ||
| 2635 | alg->len = 0; | ||
| 2636 | |||
| 2637 | for (i = 0; str[i]; i++) { | ||
| 2638 | if (str[i] == ' ' || str[i] == '\t' || str[i] == '\n') | ||
| 2639 | continue; | ||
| 2640 | |||
| 2641 | if (str[i] == '(' && niss) { | ||
| 2642 | fprintf(stderr, "Error reading moves: nested ( )\n"); | ||
| 2643 | return alg; | ||
| 2644 | } | ||
| 2645 | |||
| 2646 | if (str[i] == ')' && !niss) { | ||
| 2647 | fprintf(stderr, "Error reading moves: unmatched )\n"); | ||
| 2648 | return alg; | ||
| 2649 | } | ||
| 2650 | |||
| 2651 | if (str[i] == '(' || str[i] == ')') { | ||
| 2652 | niss = !niss; | ||
| 2653 | continue; | ||
| 2654 | } | ||
| 2655 | |||
| 2656 | for (j = 0; j < NMOVES; j++) { | ||
| 2657 | if (str[i] == move_string[j][0]) { | ||
| 2658 | m = j; | ||
| 2659 | if (m <= B && str[i+1]=='w') { | ||
| 2660 | m += Uw - U; | ||
| 2661 | i++; | ||
| 2662 | } | ||
| 2663 | if (str[i+1]=='2') { | ||
| 2664 | m += 1; | ||
| 2665 | i++; | ||
| 2666 | } else if (str[i+1]=='\'' || str[i+1]=='3') { | ||
| 2667 | m += 2; | ||
| 2668 | i++; | ||
| 2669 | } | ||
| 2670 | append_move(alg, m, niss); | ||
| 2671 | break; | ||
| 2672 | } | ||
| 2673 | } | ||
| 2674 | } | ||
| 2675 | |||
| 2676 | return alg; | ||
| 2677 | } | ||
| 2678 | |||
| 2679 | Alg * | ||
| 2680 | on_inverse(Alg *alg) | ||
| 2681 | { | ||
| 2682 | Alg *ret = new_alg(""); | ||
| 2683 | int i; | ||
| 2684 | |||
| 2685 | for (i = 0; i < alg->len; i++) | ||
| 2686 | append_move(ret, alg->move[i], !alg->inv[i]); | ||
| 2687 | |||
| 2688 | return ret; | ||
| 2689 | } | ||
| 2690 | |||
| 2691 | void | ||
| 2692 | print_alg(Alg *alg, bool l) | ||
| 2693 | { | ||
| 2694 | /* TODO: make it possible to print to stdout or to string */ | ||
| 2695 | /* Maybe just return a string */ | ||
| 2696 | char fill[4]; | ||
| 2697 | int i; | ||
| 2698 | bool niss = false; | ||
| 2699 | |||
| 2700 | for (i = 0; i < alg->len; i++) { | ||
| 2701 | if (!niss && alg->inv[i]) | ||
| 2702 | strcpy(fill, i == 0 ? "(" : " ("); | ||
| 2703 | if (niss && !alg->inv[i]) | ||
| 2704 | strcpy(fill, ") "); | ||
| 2705 | if (niss == alg->inv[i]) | ||
| 2706 | strcpy(fill, i == 0 ? "" : " "); | ||
| 2707 | |||
| 2708 | printf("%s%s", fill, move_string[alg->move[i]]); | ||
| 2709 | niss = alg->inv[i]; | ||
| 2710 | } | ||
| 2711 | |||
| 2712 | if (niss) | ||
| 2713 | printf(")"); | ||
| 2714 | if (l) | ||
| 2715 | printf(" (%d)", alg->len); | ||
| 2716 | |||
| 2717 | printf("\n"); | ||
| 2718 | } | ||
| 2719 | |||
| 2720 | void | ||
| 2721 | print_alglist(AlgList *al, bool l) | ||
| 2722 | { | ||
| 2723 | AlgListNode *i; | ||
| 2724 | |||
| 2725 | for (i = al->first; i != NULL; i = i->next) | ||
| 2726 | print_alg(i->alg, l); | ||
| 2727 | } | ||
| 2728 | |||
| 2729 | void | ||
| 2730 | print_ptable(PruneData *pd) | ||
| 2731 | { | ||
| 2732 | uint64_t i, a[16]; | ||
| 2733 | |||
| 2734 | for (i = 0; i < 16; i++) | ||
| 2735 | a[i] = 0; | ||
| 2736 | |||
| 2737 | if (!pd->generated) | ||
| 2738 | genptable(pd); | ||
| 2739 | |||
| 2740 | for (i = 0; i < pd->size; i++) | ||
| 2741 | a[ptableval(pd, i)]++; | ||
| 2742 | |||
| 2743 | fprintf(stderr, "Values for table %s\n", pd->filename); | ||
| 2744 | for (i = 0; i < 16; i++) | ||
| 2745 | printf("%2lu\t%10lu\n", i, a[i]); | ||
| 2746 | } | ||
| 2747 | |||
| 2748 | uint64_t | ||
| 2749 | ptablesize(PruneData *pd) | ||
| 2750 | { | ||
| 2751 | return (pd->size + 1) / 2; | ||
| 2752 | } | ||
| 2753 | |||
| 2754 | int | ||
| 2755 | ptableval(PruneData *pd, uint64_t ind) | ||
| 2756 | { | ||
| 2757 | return (ind % 2) ? pd->ptable[ind/2] / 16 : pd->ptable[ind/2] % 16; | ||
| 2758 | } | ||
| 2759 | |||
| 2760 | |||
| 2761 | Alg * | ||
| 2762 | trans_alg(Trans i) | ||
| 2763 | { | ||
| 2764 | return trans_algs[i]; | ||
| 2765 | } | ||
| 2766 | |||
| 2767 | void | ||
| 2768 | transform_alg(Trans t, Alg *alg) | ||
| 2769 | { | ||
| 2770 | int i; | ||
| 2771 | |||
| 2772 | for (i = 0; i < alg->len; i++) | ||
| 2773 | alg->move[i] = moves_ttable[t][alg->move[i]]; | ||
| 2774 | } | ||
| 2775 | |||
| 2776 | Center | ||
| 2777 | what_center_at(Cube cube, Center c) | ||
| 2778 | { | ||
| 2779 | return what_center_at_aux[cube.cpos][c]; | ||
| 2780 | } | ||
| 2781 | |||
| 2782 | Corner | ||
| 2783 | what_corner_at(Cube cube, Corner c) | ||
| 2784 | { | ||
| 2785 | return what_corner_at_aux[cube.cp][c]; | ||
| 2786 | } | ||
| 2787 | |||
| 2788 | Edge | ||
| 2789 | what_edge_at(Cube cube, Edge e) | ||
| 2790 | { | ||
| 2791 | Edge ret; | ||
| 2792 | CubeArray *arr = new_cubearray(cube, pf_ep); | ||
| 2793 | |||
| 2794 | ret = arr->ep[e]; | ||
| 2795 | |||
| 2796 | free_cubearray(arr, pf_ep); | ||
| 2797 | return ret; | ||
| 2798 | } | ||
| 2799 | |||
| 2800 | int | ||
| 2801 | what_orientation_corner(int co, Corner c) | ||
| 2802 | { | ||
| 2803 | if (c < 7) | ||
| 2804 | return (co / powint(3, c)) % 3; | ||
| 2805 | else | ||
| 2806 | return what_orientation_last_corner_aux[co]; | ||
| 2807 | } | ||
| 2808 | |||
| 2809 | int | ||
| 2810 | what_orientation_edge(int eo, Edge e) | ||
| 2811 | { | ||
| 2812 | if (e < 11) | ||
| 2813 | return (eo & (1 << e)) ? 1 : 0; | ||
| 2814 | else | ||
| 2815 | return what_orientation_last_edge_aux[eo]; | ||
| 2816 | } | ||
| 2817 | |||
| 2818 | Center | ||
| 2819 | where_is_center(Cube cube, Center c) | ||
| 2820 | { | ||
| 2821 | return where_is_center_aux[cube.cpos][c]; | ||
| 2822 | } | ||
| 2823 | |||
| 2824 | Corner | ||
| 2825 | where_is_corner(Cube cube, Corner c) | ||
| 2826 | { | ||
| 2827 | return where_is_corner_aux[cube.cp][c]; | ||
| 2828 | } | ||
| 2829 | |||
| 2830 | |||
| 2831 | void | ||
| 2832 | init() | ||
| 2833 | { | ||
| 2834 | /* Order is important! */ | ||
| 2835 | init_environment(); | ||
| 2836 | init_strings(); | ||
| 2837 | init_moves_aux(); | ||
| 2838 | init_moves(); | ||
| 2839 | init_auxtables(); | ||
| 2840 | init_cphtr_cosets(); | ||
| 2841 | init_trans_aux(); | ||
| 2842 | init_trans(); | ||
| 2843 | } | ||
| 2844 | |||
diff --git a/old/2021-06-23-realizing-bad-tables/cube.h b/old/2021-06-23-realizing-bad-tables/cube.h new file mode 100644 index 0000000..dcad047 --- /dev/null +++ b/old/2021-06-23-realizing-bad-tables/cube.h | |||
| @@ -0,0 +1,88 @@ | |||
| 1 | #ifndef CUBE_H | ||
| 2 | #define CUBE_H | ||
| 3 | |||
| 4 | #include <stdio.h> | ||
| 5 | #include <stdbool.h> | ||
| 6 | #include <stdint.h> | ||
| 7 | #include <stdlib.h> | ||
| 8 | #include <string.h> | ||
| 9 | #include <time.h> | ||
| 10 | #include <unistd.h> | ||
| 11 | #include <sys/stat.h> | ||
| 12 | |||
| 13 | /* Constants and macros *****************************************************/ | ||
| 14 | |||
| 15 | #define POW2TO6 64ULL | ||
| 16 | #define POW2TO11 2048ULL | ||
| 17 | #define POW2TO12 4096ULL | ||
| 18 | #define POW3TO7 2187ULL | ||
| 19 | #define POW3TO8 6561ULL | ||
| 20 | #define FACTORIAL4 24ULL | ||
| 21 | #define FACTORIAL6 720ULL | ||
| 22 | #define FACTORIAL7 5040ULL | ||
| 23 | #define FACTORIAL8 40320ULL | ||
| 24 | #define FACTORIAL12 479001600ULL | ||
| 25 | #define BINOM12ON4 495ULL | ||
| 26 | #define BINOM8ON4 70ULL | ||
| 27 | #define MIN(a,b) (((a) < (b)) ? (a) : (b)) | ||
| 28 | #define MAX(a,b) (((a) > (b)) ? (a) : (b)) | ||
| 29 | |||
| 30 | #define NMOVES (z3+1) | ||
| 31 | #define NTRANS (mirror+1) | ||
| 32 | #define NROTATIONS (NTRANS-1) | ||
| 33 | |||
| 34 | /* Type definitions **********************************************************/ | ||
| 35 | |||
| 36 | #include "cubetypes.h" | ||
| 37 | |||
| 38 | /* Public functions **********************************************************/ | ||
| 39 | |||
| 40 | Cube apply_alg(Alg *alg, Cube cube); | ||
| 41 | Cube apply_move(Move m, Cube cube); | ||
| 42 | Cube apply_trans(Trans t, Cube cube); | ||
| 43 | bool block_solved(Cube cube, Block); | ||
| 44 | Cube compose(Cube c2, Cube c1); /* Use c2 as an alg on c1 */ | ||
| 45 | uint64_t cphtr(Cube cube); | ||
| 46 | uint64_t epos_dependent(Cube cube); | ||
| 47 | bool equal(Cube c1, Cube c2); | ||
| 48 | Cube inverse_cube(Cube cube); | ||
| 49 | Move inverse_move(Move m); | ||
| 50 | Trans inverse_trans(Trans t); | ||
| 51 | bool is_admissible(Cube cube); | ||
| 52 | bool is_solved(Cube cube, bool reorient); | ||
| 53 | bool is_solved_center(Cube cube, Center c); | ||
| 54 | bool is_solved_corner(Cube cube, Corner c); | ||
| 55 | bool is_solved_edge(Cube cube, Edge e); | ||
| 56 | void print_cube(Cube cube); | ||
| 57 | Cube random_cube(); | ||
| 58 | AlgList * solve(Cube cube, Step step, SolveOptions *opts); | ||
| 59 | Center what_center_at(Cube cube, Center c); | ||
| 60 | Corner what_corner_at(Cube cube, Corner c); | ||
| 61 | Edge what_edge_at(Cube cube, Edge e); | ||
| 62 | int what_orientation_corner(int co, Corner c); | ||
| 63 | int what_orientation_edge(int eo, Edge e); | ||
| 64 | Center where_is_center(Cube cube, Center c); | ||
| 65 | Corner where_is_corner(Cube cube, Corner c); | ||
| 66 | Edge where_is_edge(Cube cube, Edge e); | ||
| 67 | |||
| 68 | Move base_move(Move m); | ||
| 69 | void free_alg(Alg *alg); | ||
| 70 | void free_alglist(AlgList *l); | ||
| 71 | Alg * inverse_alg(Alg *alg); | ||
| 72 | Alg * new_alg(char *str); | ||
| 73 | Alg * on_inverse(Alg *alg); | ||
| 74 | void print_alg(Alg *alg, bool l); | ||
| 75 | void print_alglist(AlgList *al, bool l); | ||
| 76 | Alg * trans_alg(Trans i); | ||
| 77 | void transform_alg(Trans t, Alg *alg); | ||
| 78 | |||
| 79 | void genalgset(AlgSet *as); | ||
| 80 | void genptable(PruneData *pd); | ||
| 81 | void print_ptable(PruneData *pd); | ||
| 82 | uint64_t ptablesize(PruneData *pd); | ||
| 83 | int ptableval(PruneData *pd, uint64_t ind); | ||
| 84 | |||
| 85 | void init(); | ||
| 86 | |||
| 87 | #endif | ||
| 88 | |||
diff --git a/old/2021-06-23-realizing-bad-tables/cubetypes.h b/old/2021-06-23-realizing-bad-tables/cubetypes.h new file mode 100644 index 0000000..886295c --- /dev/null +++ b/old/2021-06-23-realizing-bad-tables/cubetypes.h | |||
| @@ -0,0 +1,224 @@ | |||
| 1 | /* Typedefs ******************************************************************/ | ||
| 2 | |||
| 3 | typedef enum center Center; | ||
| 4 | typedef enum corner Corner; | ||
| 5 | typedef enum edge Edge; | ||
| 6 | typedef enum move Move; | ||
| 7 | typedef enum trans Trans; | ||
| 8 | |||
| 9 | typedef struct alg Alg; | ||
| 10 | typedef struct alglist AlgList; | ||
| 11 | typedef struct alglistnode AlgListNode; | ||
| 12 | typedef struct algset AlgSet; | ||
| 13 | typedef struct block Block; | ||
| 14 | typedef struct cube Cube; | ||
| 15 | typedef struct cubearray CubeArray; | ||
| 16 | typedef struct dfsdata DfsData; | ||
| 17 | typedef struct piecefilter PieceFilter; | ||
| 18 | typedef struct prunedata PruneData; | ||
| 19 | typedef struct solveoptions SolveOptions; | ||
| 20 | typedef struct step Step; | ||
| 21 | |||
| 22 | typedef Cube (*AntiIndexer) (uint64_t); | ||
| 23 | typedef int (*Checker) (Cube, int); | ||
| 24 | typedef uint64_t (*Indexer) (Cube); | ||
| 25 | typedef bool (*Moveset) (Move); | ||
| 26 | |||
| 27 | |||
| 28 | /* Enums *********************************************************************/ | ||
| 29 | |||
| 30 | enum | ||
| 31 | center | ||
| 32 | { | ||
| 33 | U_center, D_center, | ||
| 34 | R_center, L_center, | ||
| 35 | F_center, B_center | ||
| 36 | }; | ||
| 37 | |||
| 38 | enum | ||
| 39 | corner | ||
| 40 | { | ||
| 41 | UFR, UFL, UBL, UBR, | ||
| 42 | DFR, DFL, DBL, DBR | ||
| 43 | }; | ||
| 44 | |||
| 45 | enum | ||
| 46 | edge | ||
| 47 | { | ||
| 48 | UF, UL, UB, UR, | ||
| 49 | DF, DL, DB, DR, | ||
| 50 | FR, FL, BL, BR | ||
| 51 | }; | ||
| 52 | |||
| 53 | enum | ||
| 54 | move | ||
| 55 | { | ||
| 56 | NULLMOVE, | ||
| 57 | U, U2, U3, D, D2, D3, | ||
| 58 | R, R2, R3, L, L2, L3, | ||
| 59 | F, F2, F3, B, B2, B3, | ||
| 60 | Uw, Uw2, Uw3, Dw, Dw2, Dw3, | ||
| 61 | Rw, Rw2, Rw3, Lw, Lw2, Lw3, | ||
| 62 | Fw, Fw2, Fw3, Bw, Bw2, Bw3, | ||
| 63 | M, M2, M3, | ||
| 64 | S, S2, S3, | ||
| 65 | E, E2, E3, | ||
| 66 | x, x2, x3, | ||
| 67 | y, y2, y3, | ||
| 68 | z, z2, z3, | ||
| 69 | }; | ||
| 70 | |||
| 71 | enum | ||
| 72 | trans | ||
| 73 | { | ||
| 74 | uf, ur, ub, ul, | ||
| 75 | df, dr, db, dl, | ||
| 76 | rf, rd, rb, ru, | ||
| 77 | lf, ld, lb, lu, | ||
| 78 | fu, fr, fd, fl, | ||
| 79 | bu, br, bd, bl, | ||
| 80 | mirror, /* R|L */ | ||
| 81 | }; | ||
| 82 | |||
| 83 | |||
| 84 | /* Structs *******************************************************************/ | ||
| 85 | |||
| 86 | struct | ||
| 87 | alg | ||
| 88 | { | ||
| 89 | Move * move; | ||
| 90 | bool * inv; | ||
| 91 | int len; | ||
| 92 | int allocated; | ||
| 93 | }; | ||
| 94 | |||
| 95 | struct | ||
| 96 | alglist | ||
| 97 | { | ||
| 98 | AlgListNode * first; | ||
| 99 | AlgListNode * last; | ||
| 100 | int len; | ||
| 101 | }; | ||
| 102 | |||
| 103 | struct | ||
| 104 | alglistnode | ||
| 105 | { | ||
| 106 | Alg * alg; | ||
| 107 | AlgListNode * next; | ||
| 108 | }; | ||
| 109 | |||
| 110 | struct | ||
| 111 | block | ||
| 112 | { | ||
| 113 | bool edge[12]; | ||
| 114 | bool corner[8]; | ||
| 115 | bool center[6]; | ||
| 116 | }; | ||
| 117 | |||
| 118 | struct | ||
| 119 | cube | ||
| 120 | { | ||
| 121 | int epose; | ||
| 122 | int eposs; | ||
| 123 | int eposm; | ||
| 124 | int eofb; | ||
| 125 | int eorl; | ||
| 126 | int eoud; | ||
| 127 | int cp; | ||
| 128 | int coud; | ||
| 129 | int cofb; | ||
| 130 | int corl; | ||
| 131 | int cpos; | ||
| 132 | }; | ||
| 133 | |||
| 134 | struct | ||
| 135 | cubearray | ||
| 136 | { | ||
| 137 | int * ep; | ||
| 138 | int * eofb; | ||
| 139 | int * eorl; | ||
| 140 | int * eoud; | ||
| 141 | int * cp; | ||
| 142 | int * coud; | ||
| 143 | int * corl; | ||
| 144 | int * cofb; | ||
| 145 | int * cpos; | ||
| 146 | }; | ||
| 147 | |||
| 148 | struct | ||
| 149 | dfsdata | ||
| 150 | { | ||
| 151 | int d; | ||
| 152 | int m; | ||
| 153 | int lb; | ||
| 154 | bool niss; | ||
| 155 | Move last1; | ||
| 156 | Move last2; | ||
| 157 | AlgList * sols; | ||
| 158 | Alg * current_alg; | ||
| 159 | Move sorted_moves[NMOVES]; | ||
| 160 | int move_position[NMOVES]; | ||
| 161 | }; | ||
| 162 | |||
| 163 | struct | ||
| 164 | piecefilter | ||
| 165 | { | ||
| 166 | bool epose; | ||
| 167 | bool eposs; | ||
| 168 | bool eposm; | ||
| 169 | bool eofb; | ||
| 170 | bool eorl; | ||
| 171 | bool eoud; | ||
| 172 | bool cp; | ||
| 173 | bool coud; | ||
| 174 | bool cofb; | ||
| 175 | bool corl; | ||
| 176 | bool cpos; | ||
| 177 | }; | ||
| 178 | |||
| 179 | struct | ||
| 180 | prunedata | ||
| 181 | { | ||
| 182 | char * filename; | ||
| 183 | uint8_t * ptable; | ||
| 184 | uint8_t * reached; | ||
| 185 | bool generated; | ||
| 186 | uint64_t n; | ||
| 187 | uint64_t size; | ||
| 188 | Indexer index; | ||
| 189 | Moveset moveset; | ||
| 190 | }; | ||
| 191 | |||
| 192 | struct | ||
| 193 | solveoptions | ||
| 194 | { | ||
| 195 | int min_moves; | ||
| 196 | int max_moves; | ||
| 197 | int max_solutions; | ||
| 198 | bool optimal_only; | ||
| 199 | bool can_niss; | ||
| 200 | bool feedback; | ||
| 201 | Trans pre_trans; | ||
| 202 | }; | ||
| 203 | |||
| 204 | struct | ||
| 205 | step | ||
| 206 | { | ||
| 207 | Checker check; | ||
| 208 | Checker ready; | ||
| 209 | Moveset moveset; | ||
| 210 | }; | ||
| 211 | |||
| 212 | /* TODO: I put it here because it needs the definition of Step, sort it out */ | ||
| 213 | struct | ||
| 214 | algset | ||
| 215 | { | ||
| 216 | char * filename; | ||
| 217 | AlgList ** table; | ||
| 218 | bool generated; | ||
| 219 | uint64_t size; | ||
| 220 | Indexer index; | ||
| 221 | AntiIndexer antindex; | ||
| 222 | Step step; | ||
| 223 | SolveOptions opts; | ||
| 224 | }; | ||
diff --git a/old/2021-06-23-realizing-bad-tables/main.c b/old/2021-06-23-realizing-bad-tables/main.c new file mode 100644 index 0000000..e0e049a --- /dev/null +++ b/old/2021-06-23-realizing-bad-tables/main.c | |||
| @@ -0,0 +1,70 @@ | |||
| 1 | #include <stdio.h> | ||
| 2 | #include "cube.h" | ||
| 3 | #include "steps.h" | ||
| 4 | |||
| 5 | int main() { | ||
| 6 | Alg *algo; | ||
| 7 | AlgList *sols; | ||
| 8 | Cube cube; | ||
| 9 | SolveOptions opts; | ||
| 10 | char line[1000]; | ||
| 11 | int i, ns = 3; | ||
| 12 | /* int nrand = 10000, sum1, sum2, sum3;*/ | ||
| 13 | |||
| 14 | Step *stps[20] = {&corners_HTM, &eofb_HTM, &optimal_HTM}; | ||
| 15 | char sss[30][30] = {"Corners", "EO on F/B", "Optimal solution"}; | ||
| 16 | |||
| 17 | opts = (SolveOptions) { | ||
| 18 | .min_moves = 0, | ||
| 19 | .max_moves = 20, | ||
| 20 | .optimal_only = true, | ||
| 21 | .max_solutions = 1, | ||
| 22 | .can_niss = false, | ||
| 23 | .feedback = true, | ||
| 24 | .pre_trans = uf | ||
| 25 | }; | ||
| 26 | |||
| 27 | init(); | ||
| 28 | |||
| 29 | print_ptable(&pd_corners_HTM); | ||
| 30 | |||
| 31 | /* | ||
| 32 | srand(time(NULL)); | ||
| 33 | sum1 = 0; | ||
| 34 | sum2 = 0; | ||
| 35 | sum3 = 0; | ||
| 36 | for (i = 0; i < nrand; i++) { | ||
| 37 | cube = random_cube(); | ||
| 38 | sum1 += corners_HTM.check(cube, 20); | ||
| 39 | sum2 += cornershtr_HTM.check(cube, 20); | ||
| 40 | sum3 += optimal_HTM.check(cube, 20); | ||
| 41 | } | ||
| 42 | printf("Average corners pruning: %lf\n", ((double)sum1) / ((double) nrand)); | ||
| 43 | printf("Average corners htr pruning: %lf\n", ((double)sum2) / ((double) nrand)); | ||
| 44 | printf("Average optimal pruning: %lf\n", ((double)sum3) / ((double) nrand)); | ||
| 45 | */ | ||
| 46 | |||
| 47 | printf("Welcome to nissy 2.0! Insert a scramble:\n"); | ||
| 48 | |||
| 49 | if (fgets(line, 1000, stdin) != NULL) { | ||
| 50 | algo = new_alg(line); | ||
| 51 | cube = apply_alg(algo, (Cube){0}); | ||
| 52 | |||
| 53 | print_cube(cube); | ||
| 54 | printf("Index: %lu\n", pd_cornershtr_HTM.index(cube)); | ||
| 55 | |||
| 56 | for (i = 0; i < ns; i++) { | ||
| 57 | if (stps[i]->check == NULL) | ||
| 58 | fprintf(stderr, "Check function for step %d is null\n", i); | ||
| 59 | printf("Check: %d\n", stps[i]->check(cube, 20)); | ||
| 60 | sols = solve(cube, *stps[i], &opts); | ||
| 61 | printf("%s: %d solutions found:\n", sss[i], sols->len); | ||
| 62 | print_alglist(sols, true); | ||
| 63 | free_alglist(sols); | ||
| 64 | } | ||
| 65 | free_alg(algo); | ||
| 66 | } | ||
| 67 | |||
| 68 | return 0; | ||
| 69 | } | ||
| 70 | |||
diff --git a/old/2021-06-23-realizing-bad-tables/steps.c b/old/2021-06-23-realizing-bad-tables/steps.c new file mode 100644 index 0000000..2b029b8 --- /dev/null +++ b/old/2021-06-23-realizing-bad-tables/steps.c | |||
| @@ -0,0 +1,486 @@ | |||
| 1 | #include "steps.h" | ||
| 2 | |||
| 3 | /* Check functions ***********************************************************/ | ||
| 4 | |||
| 5 | static int check_nothing(Cube cube, int target); | ||
| 6 | static int check_centers(Cube cube, int target); | ||
| 7 | static int check_eofb_HTM(Cube cube, int target); | ||
| 8 | static int check_coud_HTM(Cube cube, int target); | ||
| 9 | static int check_coud_URF(Cube cube, int target); | ||
| 10 | static int check_corners_HTM(Cube cube, int target); | ||
| 11 | static int check_cornershtr_HTM(Cube cube, int target); | ||
| 12 | static int check_corners_URF(Cube cube, int target); | ||
| 13 | static int check_cornershtr_URF(Cube cube, int target); | ||
| 14 | static int check_ep_HTM(Cube cube, int target); | ||
| 15 | static int check_edges_HTM(Cube cube, int target); | ||
| 16 | static int check_drud_HTM(Cube cube, int target); | ||
| 17 | static int check_optimal_HTM(Cube cube, int target); | ||
| 18 | static int check_corners6eo_HTM(Cube cube, int target); | ||
| 19 | static int check_tripleeo_HTM(Cube cube, int target); | ||
| 20 | |||
| 21 | |||
| 22 | /* Index functions ***********************************************************/ | ||
| 23 | |||
| 24 | static uint64_t index_eofb(Cube cube); | ||
| 25 | static uint64_t index_coud(Cube cube); | ||
| 26 | static uint64_t index_corners(Cube cube); | ||
| 27 | static uint64_t index_cornershtr(Cube cube); | ||
| 28 | static uint64_t index_ep(Cube cube); | ||
| 29 | static uint64_t index_drud(Cube cube); | ||
| 30 | static uint64_t index_corners6eo(Cube cube); | ||
| 31 | static uint64_t index_tripleeo(Cube cube); | ||
| 32 | |||
| 33 | |||
| 34 | /* Steps *********************************************************************/ | ||
| 35 | |||
| 36 | Step | ||
| 37 | eofb_HTM = { | ||
| 38 | .check = check_eofb_HTM, | ||
| 39 | .ready = check_centers, | ||
| 40 | .moveset = moveset_HTM | ||
| 41 | }; | ||
| 42 | |||
| 43 | Step | ||
| 44 | coud_HTM = { | ||
| 45 | .check = check_coud_HTM, | ||
| 46 | .ready = check_centers, | ||
| 47 | .moveset = moveset_HTM | ||
| 48 | }; | ||
| 49 | |||
| 50 | Step | ||
| 51 | coud_URF = { | ||
| 52 | .check = check_coud_URF, | ||
| 53 | .ready = check_nothing, | ||
| 54 | .moveset = moveset_URF | ||
| 55 | }; | ||
| 56 | |||
| 57 | Step | ||
| 58 | corners_HTM = { | ||
| 59 | .check = check_corners_HTM, | ||
| 60 | .ready = check_centers, | ||
| 61 | .moveset = moveset_HTM | ||
| 62 | }; | ||
| 63 | |||
| 64 | Step | ||
| 65 | cornershtr_HTM = { | ||
| 66 | .check = check_cornershtr_HTM, | ||
| 67 | .ready = check_centers, | ||
| 68 | .moveset = moveset_HTM | ||
| 69 | }; | ||
| 70 | |||
| 71 | Step | ||
| 72 | cornershtr_URF = { | ||
| 73 | .check = check_cornershtr_URF, | ||
| 74 | .ready = check_nothing, | ||
| 75 | .moveset = moveset_URF | ||
| 76 | }; | ||
| 77 | |||
| 78 | Step | ||
| 79 | corners_URF = { | ||
| 80 | .check = check_corners_URF, | ||
| 81 | .ready = check_nothing, | ||
| 82 | .moveset = moveset_URF | ||
| 83 | }; | ||
| 84 | |||
| 85 | Step | ||
| 86 | edges_HTM = { | ||
| 87 | .check = check_edges_HTM, | ||
| 88 | .ready = check_centers, | ||
| 89 | .moveset = moveset_HTM | ||
| 90 | }; | ||
| 91 | |||
| 92 | Step | ||
| 93 | drud_HTM = { | ||
| 94 | .check = check_drud_HTM, | ||
| 95 | .ready = check_centers, | ||
| 96 | .moveset = moveset_HTM | ||
| 97 | }; | ||
| 98 | |||
| 99 | Step | ||
| 100 | optimal_HTM = { | ||
| 101 | .check = check_optimal_HTM, | ||
| 102 | .ready = check_centers, | ||
| 103 | .moveset = moveset_HTM | ||
| 104 | }; | ||
| 105 | |||
| 106 | Step | ||
| 107 | tripleeo_HTM = { | ||
| 108 | .check = check_tripleeo_HTM, | ||
| 109 | .ready = check_centers, | ||
| 110 | .moveset = moveset_HTM | ||
| 111 | }; | ||
| 112 | |||
| 113 | |||
| 114 | /* Blocks ********************************************************************/ | ||
| 115 | |||
| 116 | Block | ||
| 117 | block_223dl = { | ||
| 118 | .edge = { [DF] = 1, [DL] = 1, [DB] = 1, [FL] = 1, [BL] = 1 }, | ||
| 119 | .corner = { [DFL] = 1, [DBL] = 1 }, | ||
| 120 | .center = { [D_center] = 1, [L_center] = 1 } | ||
| 121 | }; | ||
| 122 | |||
| 123 | |||
| 124 | /* Pruning tables ************************************************************/ | ||
| 125 | |||
| 126 | PruneData | ||
| 127 | pd_eofb_HTM = { | ||
| 128 | .filename = "ptable_eofb_HTM", | ||
| 129 | .size = POW2TO11, | ||
| 130 | .index = index_eofb, | ||
| 131 | .moveset = moveset_HTM | ||
| 132 | }; | ||
| 133 | |||
| 134 | PruneData | ||
| 135 | pd_coud_HTM = { | ||
| 136 | .filename = "ptable_coud_HTM", | ||
| 137 | .size = POW3TO7, | ||
| 138 | .index = index_coud, | ||
| 139 | .moveset = moveset_HTM | ||
| 140 | }; | ||
| 141 | |||
| 142 | PruneData | ||
| 143 | pd_cornershtr_HTM = { | ||
| 144 | .filename = "ptable_cornershtr_HTM", | ||
| 145 | .size = POW3TO7 * BINOM8ON4 * 6, /*TODO: check */ | ||
| 146 | .index = index_cornershtr, | ||
| 147 | .moveset = moveset_HTM | ||
| 148 | }; | ||
| 149 | |||
| 150 | PruneData | ||
| 151 | pd_corners_HTM = { | ||
| 152 | .filename = "ptable_corners_HTM", | ||
| 153 | .size = POW3TO7 * FACTORIAL8, | ||
| 154 | .index = index_corners, | ||
| 155 | .moveset = moveset_HTM | ||
| 156 | }; | ||
| 157 | |||
| 158 | PruneData | ||
| 159 | pd_ep_HTM = { | ||
| 160 | .filename = "ptable_ep_HTM", | ||
| 161 | .size = FACTORIAL12, | ||
| 162 | .index = index_ep, | ||
| 163 | .moveset = moveset_HTM | ||
| 164 | }; | ||
| 165 | |||
| 166 | PruneData | ||
| 167 | pd_drud_HTM = { | ||
| 168 | .filename = "ptable_drud_HTM", | ||
| 169 | .size = POW2TO11 * POW3TO7 * BINOM12ON4, | ||
| 170 | .index = index_drud, | ||
| 171 | .moveset = moveset_HTM | ||
| 172 | }; | ||
| 173 | |||
| 174 | PruneData | ||
| 175 | pd_corners6eo_HTM = { | ||
| 176 | .filename = "ptable_corners6eo_HTM", | ||
| 177 | .size = POW2TO6 * POW3TO7 * FACTORIAL8, | ||
| 178 | .index = index_corners6eo, | ||
| 179 | .moveset = moveset_HTM | ||
| 180 | }; | ||
| 181 | |||
| 182 | PruneData | ||
| 183 | pd_tripleeo_HTM = { | ||
| 184 | .filename = "ptable_tripleeo_HTM", | ||
| 185 | .size = BINOM12ON4 * BINOM8ON4 * POW2TO11, | ||
| 186 | .index = index_tripleeo, | ||
| 187 | .moveset = moveset_HTM | ||
| 188 | }; | ||
| 189 | |||
| 190 | |||
| 191 | /* Alg sets ******************************************************************/ | ||
| 192 | |||
| 193 | /* TODO: remove this (I am only keeping it as an example for future algesets) | ||
| 194 | AlgSet | ||
| 195 | as_ephtr_HTM = { | ||
| 196 | .filename = "algset_ephtr_HTM", | ||
| 197 | .size = FACTORIAL4 * FACTORIAL4 * FACTORIAL4, | ||
| 198 | .index = index_ephtr, | ||
| 199 | .antindex = index_to_cube_ephtr, | ||
| 200 | .step = (Step) { | ||
| 201 | .check = check_optimal_HTM, | ||
| 202 | .ready = check_htr_solved_corners_HTM, | ||
| 203 | .moveset = moveset_HTM | ||
| 204 | }, | ||
| 205 | .opts = (SolveOptions) { | ||
| 206 | .min_moves = 0, | ||
| 207 | .max_moves = 20, | ||
| 208 | .max_solutions = 1, | ||
| 209 | .optimal_only = true, | ||
| 210 | .can_niss = false, | ||
| 211 | .feedback = true, | ||
| 212 | .pre_trans = uf | ||
| 213 | } | ||
| 214 | }; | ||
| 215 | */ | ||
| 216 | |||
| 217 | |||
| 218 | /* Check functions implementation ********************************************/ | ||
| 219 | |||
| 220 | static int | ||
| 221 | check_nothing(Cube cube, int target) | ||
| 222 | { | ||
| 223 | return 0; | ||
| 224 | } | ||
| 225 | |||
| 226 | static int | ||
| 227 | check_centers(Cube cube, int target) | ||
| 228 | { | ||
| 229 | return (cube.cpos == 0) ? 0 : 1; | ||
| 230 | } | ||
| 231 | |||
| 232 | static int | ||
| 233 | check_eofb_HTM(Cube cube, int target) | ||
| 234 | { | ||
| 235 | if (!pd_eofb_HTM.generated) | ||
| 236 | genptable(&pd_eofb_HTM); | ||
| 237 | |||
| 238 | return ptableval(&pd_eofb_HTM, cube.eofb); | ||
| 239 | } | ||
| 240 | |||
| 241 | static int | ||
| 242 | check_coud_HTM(Cube cube, int target) | ||
| 243 | { | ||
| 244 | if (!pd_coud_HTM.generated) | ||
| 245 | genptable(&pd_coud_HTM); | ||
| 246 | |||
| 247 | return ptableval(&pd_coud_HTM, cube.coud); | ||
| 248 | } | ||
| 249 | |||
| 250 | static int | ||
| 251 | check_coud_URF(Cube cube, int target) | ||
| 252 | { | ||
| 253 | /* TODO: I can improve this by checking first the orientation of | ||
| 254 | * the corner in DBL and use that as a reference */ | ||
| 255 | |||
| 256 | int ud = check_coud_HTM(cube, target); | ||
| 257 | int rl = check_coud_HTM(apply_move(z, cube), target); | ||
| 258 | int fb = check_coud_HTM(apply_move(x, cube), target); | ||
| 259 | |||
| 260 | return MIN(ud, MIN(rl, fb)); | ||
| 261 | } | ||
| 262 | |||
| 263 | static int | ||
| 264 | check_corners_HTM(Cube cube, int target) | ||
| 265 | { | ||
| 266 | if (!pd_corners_HTM.generated) | ||
| 267 | genptable(&pd_corners_HTM); | ||
| 268 | |||
| 269 | return ptableval(&pd_corners_HTM, index_corners(cube)); | ||
| 270 | } | ||
| 271 | |||
| 272 | static int | ||
| 273 | check_cornershtr_HTM(Cube cube, int target) | ||
| 274 | { | ||
| 275 | if (!pd_cornershtr_HTM.generated) | ||
| 276 | genptable(&pd_cornershtr_HTM); | ||
| 277 | |||
| 278 | return ptableval(&pd_cornershtr_HTM, index_cornershtr(cube)); | ||
| 279 | } | ||
| 280 | |||
| 281 | static int | ||
| 282 | check_cornershtr_URF(Cube cube, int target) | ||
| 283 | { | ||
| 284 | /* TODO: I can improve this by checking first the corner in DBL | ||
| 285 | * and use that as a reference */ | ||
| 286 | |||
| 287 | int c, ret = 15; | ||
| 288 | Trans i; | ||
| 289 | |||
| 290 | for (i = 0; i < NROTATIONS; i++) { | ||
| 291 | c = check_cornershtr_HTM(apply_alg(trans_alg(i),cube), target); | ||
| 292 | ret = MIN(ret, c); | ||
| 293 | } | ||
| 294 | |||
| 295 | return ret; | ||
| 296 | } | ||
| 297 | |||
| 298 | static int | ||
| 299 | check_corners_URF(Cube cube, int target) | ||
| 300 | { | ||
| 301 | /* TODO: I can improve this by checking first the corner in DBL | ||
| 302 | * and use that as a reference */ | ||
| 303 | |||
| 304 | int ret = 15; | ||
| 305 | Trans i; | ||
| 306 | |||
| 307 | for (i = 0; i < NROTATIONS; i++) | ||
| 308 | ret = MIN(ret, check_corners_HTM( | ||
| 309 | apply_alg(trans_alg(i), cube), target)); | ||
| 310 | |||
| 311 | return ret; | ||
| 312 | } | ||
| 313 | |||
| 314 | static int | ||
| 315 | check_ep_HTM(Cube cube, int target) | ||
| 316 | { | ||
| 317 | if (!pd_ep_HTM.generated) | ||
| 318 | genptable(&pd_ep_HTM); | ||
| 319 | |||
| 320 | return ptableval(&pd_ep_HTM, index_ep(cube)); | ||
| 321 | } | ||
| 322 | |||
| 323 | static int | ||
| 324 | check_edges_HTM(Cube cube, int target) | ||
| 325 | { | ||
| 326 | return MAX(check_ep_HTM(cube, target), | ||
| 327 | check_tripleeo_HTM(cube, target)); | ||
| 328 | } | ||
| 329 | |||
| 330 | static int | ||
| 331 | check_drud_HTM(Cube cube, int target) | ||
| 332 | { | ||
| 333 | if (!pd_drud_HTM.generated) | ||
| 334 | genptable(&pd_drud_HTM); | ||
| 335 | |||
| 336 | return ptableval(&pd_drud_HTM, index_drud(cube)); | ||
| 337 | } | ||
| 338 | |||
| 339 | static int | ||
| 340 | check_optimal_HTM(Cube cube, int target) | ||
| 341 | { | ||
| 342 | int dr1, dr2, dr3, cor, ret; | ||
| 343 | Cube cube2, cube3; | ||
| 344 | |||
| 345 | dr1 = check_drud_HTM(cube, target); | ||
| 346 | /*cor = check_corners6eo_HTM(cube, target);*/ | ||
| 347 | cor = check_corners_HTM(cube, target); | ||
| 348 | ret = MAX(dr1, cor); | ||
| 349 | |||
| 350 | if (ret > target) | ||
| 351 | return ret; | ||
| 352 | |||
| 353 | cube2 = apply_trans(rf, cube); | ||
| 354 | dr2 = check_drud_HTM(cube2, target); | ||
| 355 | /*cor = check_corners6eo_HTM(cube2, target); | ||
| 356 | ret = MAX(ret, MAX(dr2, cor));*/ | ||
| 357 | ret = MAX(ret, dr2); | ||
| 358 | |||
| 359 | if (ret > target) | ||
| 360 | return ret; | ||
| 361 | |||
| 362 | cube3 = apply_trans(bd, cube); | ||
| 363 | dr3 = check_drud_HTM(cube3, target); | ||
| 364 | /*cor = check_corners6eo_HTM(cube3, target);*/ | ||
| 365 | |||
| 366 | if (dr1 == dr2 && dr2 == dr3 && dr1 != 0) | ||
| 367 | dr3++; | ||
| 368 | |||
| 369 | /*ret = MAX(ret, MAX(dr3, cor));*/ | ||
| 370 | ret = MAX(ret, dr3); | ||
| 371 | |||
| 372 | if (ret == 0) | ||
| 373 | return (!cube.epose && !cube.eposs && !cube.eposm) ? 0 : 6; | ||
| 374 | |||
| 375 | return ret; | ||
| 376 | } | ||
| 377 | |||
| 378 | static int | ||
| 379 | check_corners6eo_HTM(Cube cube, int target) | ||
| 380 | { | ||
| 381 | if (!pd_corners6eo_HTM.generated) | ||
| 382 | genptable(&pd_corners6eo_HTM); | ||
| 383 | |||
| 384 | return ptableval(&pd_corners6eo_HTM, index_corners6eo(cube)); | ||
| 385 | } | ||
| 386 | |||
| 387 | static int | ||
| 388 | check_tripleeo_HTM(Cube cube, int target) | ||
| 389 | { | ||
| 390 | if (!pd_tripleeo_HTM.generated) | ||
| 391 | genptable(&pd_tripleeo_HTM); | ||
| 392 | |||
| 393 | return ptableval(&pd_tripleeo_HTM, index_tripleeo(cube)); | ||
| 394 | } | ||
| 395 | |||
| 396 | |||
| 397 | /* Index functions implementation ********************************************/ | ||
| 398 | |||
| 399 | static uint64_t | ||
| 400 | index_eofb(Cube cube) | ||
| 401 | { | ||
| 402 | return cube.eofb; | ||
| 403 | } | ||
| 404 | |||
| 405 | static uint64_t | ||
| 406 | index_coud(Cube cube) | ||
| 407 | { | ||
| 408 | return cube.coud; | ||
| 409 | } | ||
| 410 | |||
| 411 | static uint64_t | ||
| 412 | index_cornershtr(Cube cube) | ||
| 413 | { | ||
| 414 | return cube.coud * BINOM8ON4 * 6 + cphtr(cube); | ||
| 415 | } | ||
| 416 | |||
| 417 | static uint64_t | ||
| 418 | index_corners(Cube cube) | ||
| 419 | { | ||
| 420 | return cube.coud * FACTORIAL8 + cube.cp; | ||
| 421 | } | ||
| 422 | |||
| 423 | static uint64_t | ||
| 424 | index_ep(Cube cube) | ||
| 425 | { | ||
| 426 | uint64_t a, b, c; | ||
| 427 | |||
| 428 | a = cube.epose; | ||
| 429 | b = (cube.eposs % FACTORIAL4) + epos_dependent(cube)*FACTORIAL4; | ||
| 430 | c = cube.eposm % FACTORIAL4; | ||
| 431 | |||
| 432 | b *= FACTORIAL4 * BINOM12ON4; | ||
| 433 | c *= FACTORIAL4 * BINOM12ON4 * FACTORIAL4 * BINOM8ON4; | ||
| 434 | |||
| 435 | return a + b + c; | ||
| 436 | } | ||
| 437 | |||
| 438 | static uint64_t | ||
| 439 | index_drud(Cube cube) | ||
| 440 | { | ||
| 441 | uint64_t a, b, c; | ||
| 442 | |||
| 443 | a = cube.eofb; | ||
| 444 | b = cube.coud; | ||
| 445 | c = cube.epose / FACTORIAL4; | ||
| 446 | |||
| 447 | b *= POW2TO11; | ||
| 448 | c *= POW2TO11 * POW3TO7; | ||
| 449 | |||
| 450 | return a + b + c; | ||
| 451 | } | ||
| 452 | |||
| 453 | static uint64_t | ||
| 454 | index_corners6eo(Cube cube) | ||
| 455 | { | ||
| 456 | return (cube.coud*FACTORIAL8 + cube.cp)*POW2TO6 + (cube.eofb%POW2TO6); | ||
| 457 | } | ||
| 458 | |||
| 459 | static uint64_t | ||
| 460 | index_tripleeo(Cube cube) | ||
| 461 | { | ||
| 462 | uint64_t ee, es; | ||
| 463 | |||
| 464 | ee = cube.epose / FACTORIAL4; | ||
| 465 | es = epos_dependent(cube); | ||
| 466 | |||
| 467 | return (ee * BINOM8ON4 + es) * POW2TO11 + cube.eofb; | ||
| 468 | } | ||
| 469 | |||
| 470 | |||
| 471 | /* Movesets ******************************************************************/ | ||
| 472 | |||
| 473 | bool | ||
| 474 | moveset_HTM(Move m) | ||
| 475 | { | ||
| 476 | return m >= U && m <= B3; | ||
| 477 | } | ||
| 478 | |||
| 479 | bool | ||
| 480 | moveset_URF(Move m) | ||
| 481 | { | ||
| 482 | Move b = base_move(m); | ||
| 483 | |||
| 484 | return b == U || b == R || b == F; | ||
| 485 | } | ||
| 486 | |||
diff --git a/old/2021-06-23-realizing-bad-tables/steps.h b/old/2021-06-23-realizing-bad-tables/steps.h new file mode 100644 index 0000000..9d8bf6a --- /dev/null +++ b/old/2021-06-23-realizing-bad-tables/steps.h | |||
| @@ -0,0 +1,42 @@ | |||
| 1 | #ifndef STEPS_H | ||
| 2 | #define STEPS_H | ||
| 3 | |||
| 4 | #include "cube.h" | ||
| 5 | |||
| 6 | /* Steps *********************************************************************/ | ||
| 7 | |||
| 8 | extern Step eofb_HTM; | ||
| 9 | extern Step coud_HTM; | ||
| 10 | extern Step coud_URF; | ||
| 11 | extern Step corners_HTM; | ||
| 12 | extern Step cornershtr_HTM; | ||
| 13 | extern Step corners_URF; | ||
| 14 | extern Step cornershtr_URF; | ||
| 15 | extern Step edges_HTM; | ||
| 16 | extern Step drud_HTM; | ||
| 17 | extern Step optimal_HTM; | ||
| 18 | extern Step tripleeo_HTM; | ||
| 19 | |||
| 20 | /* Blocks ********************************************************************/ | ||
| 21 | |||
| 22 | extern Block block_223dl; | ||
| 23 | |||
| 24 | /* Pruning tables ************************************************************/ | ||
| 25 | |||
| 26 | extern PruneData pd_eofb_HTM; | ||
| 27 | extern PruneData pd_coud_HTM; | ||
| 28 | extern PruneData pd_corners_HTM; | ||
| 29 | extern PruneData pd_cornershtr_HTM; | ||
| 30 | extern PruneData pd_ep_HTM; | ||
| 31 | extern PruneData pd_drud_HTM; | ||
| 32 | extern PruneData pd_tripleeo_HTM; | ||
| 33 | |||
| 34 | /* Alg sets ******************************************************************/ | ||
| 35 | |||
| 36 | |||
| 37 | /* Movesets ******************************************************************/ | ||
| 38 | |||
| 39 | bool moveset_HTM(Move m); | ||
| 40 | bool moveset_URF(Move m); | ||
| 41 | |||
| 42 | #endif | ||
diff --git a/old/2021-06-23-uint16t/cube.c b/old/2021-06-23-uint16t/cube.c new file mode 100644 index 0000000..0381ba0 --- /dev/null +++ b/old/2021-06-23-uint16t/cube.c | |||
| @@ -0,0 +1,2762 @@ | |||
| 1 | #include "cube.h" | ||
| 2 | |||
| 3 | /* Local functions **********************************************************/ | ||
| 4 | |||
| 5 | static Cube admissible_ep(Cube cube, PieceFilter f); | ||
| 6 | static bool allowed_next(Move move, DfsData *dd); | ||
| 7 | static void append_alg(AlgList *l, Alg *alg); | ||
| 8 | static void append_move(Alg *alg, Move m, bool inverse); | ||
| 9 | static Cube apply_alg_generic(Alg *alg, Cube c, PieceFilter f, bool a); | ||
| 10 | static void apply_permutation(int *perm, int *set, int n); | ||
| 11 | static Cube apply_move_cubearray(Move m, Cube cube, PieceFilter f); | ||
| 12 | static uint16_t array_ep_to_epos(int *ep, int *eps_solved); | ||
| 13 | static Cube arrays_to_cube(CubeArray *arr, PieceFilter f); | ||
| 14 | static int binomial(int n, int k); | ||
| 15 | static Cube compose_filtered(Cube c2, Cube c1, PieceFilter f); | ||
| 16 | static void cube_to_arrays(Cube cube, CubeArray *arr, PieceFilter f); | ||
| 17 | static void dfs(Cube c, Step s, SolveOptions *opts, DfsData *dd); | ||
| 18 | static void dfs_branch(Cube c, Step s, SolveOptions *opts, DfsData *dd); | ||
| 19 | static bool dfs_check_solved(SolveOptions *opts, DfsData *dd); | ||
| 20 | static void dfs_niss(Cube c, Step s, SolveOptions *opts, DfsData *dd); | ||
| 21 | static bool dfs_stop(Cube c, Step s, SolveOptions *opts, DfsData *dd); | ||
| 22 | static int digit_array_to_int(int *a, int n, int b); | ||
| 23 | static int edge_slice(Edge e); /* E=0, S=1, M=2 */ | ||
| 24 | static int epos_dependent(int pos1, int pos2); | ||
| 25 | static uint16_t epos_from_arrays(int *epos, int *ep); | ||
| 26 | static void epos_to_partial_ep(uint16_t epos, int *ep, int *ss); | ||
| 27 | static int factorial(int n); | ||
| 28 | static void free_alglistnode(AlgListNode *aln); | ||
| 29 | static void free_cubearray(CubeArray *arr, PieceFilter f); | ||
| 30 | static void genptable_dfs(Cube c, PruneData *pd, DfsData *dd); | ||
| 31 | static void genptable_dfs_branch(Cube c, PruneData *pd, DfsData *dd); | ||
| 32 | static void index_to_perm(int p, int n, int *r); | ||
| 33 | static void index_to_subset(int s, int n, int k, int *r); | ||
| 34 | static void int_to_digit_array(int a, int b, int n, int *r); | ||
| 35 | static void int_to_sum_zero_array(int x, int b, int n, int *a); | ||
| 36 | static int invert_digits(int a, int b, int n); | ||
| 37 | static bool is_perm(int *a, int n); | ||
| 38 | static bool is_subset(int *a, int n, int k); | ||
| 39 | static Cube move_via_arrays(CubeArray *arr, Cube c, PieceFilter pf); | ||
| 40 | static void movelist_to_position(Move *movelist, int *position); | ||
| 41 | static void moveset_to_list(Moveset ms, Checker f, Move *r); | ||
| 42 | static AlgList * new_alglist(); | ||
| 43 | static CubeArray * new_cubearray(Cube cube, PieceFilter f); | ||
| 44 | static int perm_sign(int *a, int n); | ||
| 45 | static int perm_to_index(int *a, int n); | ||
| 46 | static int powint(int a, int b); | ||
| 47 | static bool ptable_has_reached(PruneData *pd, uint64_t ind); | ||
| 48 | static void ptable_set_reached(PruneData *pd, uint64_t ind); | ||
| 49 | static void ptable_update(PruneData *pd, uint64_t ind, int m); | ||
| 50 | static void realloc_alg(Alg *alg, int n); | ||
| 51 | static bool read_algset_file(AlgSet *as); | ||
| 52 | static bool read_mtables_file(); | ||
| 53 | static bool read_ptable_file(PruneData *pd); | ||
| 54 | static bool read_ttables_file(); | ||
| 55 | static Cube rotate_via_compose(Trans r, Cube c, PieceFilter f); | ||
| 56 | static int subset_to_index(int *a, int n, int k); | ||
| 57 | static void sum_arrays_mod(int *src, int *dst, int n, int m); | ||
| 58 | static void swap(int *a, int *b); | ||
| 59 | static bool write_algset_file(AlgSet *as); | ||
| 60 | static bool write_mtables_file(); | ||
| 61 | static bool write_ptable_file(PruneData *pd); | ||
| 62 | static bool write_ttables_file(); | ||
| 63 | |||
| 64 | static void init_auxtables(); | ||
| 65 | static void init_environment(); | ||
| 66 | static void init_moves(); | ||
| 67 | static void init_moves_aux(); | ||
| 68 | static void init_strings(); | ||
| 69 | static void init_trans(); | ||
| 70 | static void init_trans_aux(); | ||
| 71 | |||
| 72 | /* All sorts of useful costants and tables **********************************/ | ||
| 73 | |||
| 74 | static char * tabledir; | ||
| 75 | |||
| 76 | static PieceFilter pf_all; | ||
| 77 | static PieceFilter pf_4val; | ||
| 78 | static PieceFilter pf_epcp; | ||
| 79 | static PieceFilter pf_cpos; | ||
| 80 | static PieceFilter pf_cp; | ||
| 81 | static PieceFilter pf_ep; | ||
| 82 | static PieceFilter pf_e; | ||
| 83 | static PieceFilter pf_s; | ||
| 84 | static PieceFilter pf_m; | ||
| 85 | static PieceFilter pf_eo; | ||
| 86 | static PieceFilter pf_co; | ||
| 87 | |||
| 88 | static int epe_solved[4]; | ||
| 89 | static int eps_solved[4]; | ||
| 90 | static int epm_solved[4]; | ||
| 91 | |||
| 92 | static char move_string[NMOVES][7]; | ||
| 93 | static char edge_string[12][7]; | ||
| 94 | static char corner_string[8][7]; | ||
| 95 | static char center_string[6][7]; | ||
| 96 | |||
| 97 | static bool commute[NMOVES][NMOVES]; | ||
| 98 | static bool possible_next[NMOVES][NMOVES][NMOVES]; | ||
| 99 | static Move inverse_move_aux[NMOVES]; | ||
| 100 | static Trans inverse_trans_aux[NTRANS]; | ||
| 101 | static int epos_dependent_aux[BINOM12ON4][BINOM12ON4]; | ||
| 102 | static Center what_center_at_aux[FACTORIAL6][6]; | ||
| 103 | static Corner what_corner_at_aux[FACTORIAL8][8]; | ||
| 104 | static int what_orientation_last_corner_aux[POW3TO7]; | ||
| 105 | static int what_orientation_last_edge_aux[POW2TO11]; | ||
| 106 | static Center where_is_center_aux[FACTORIAL6][6]; | ||
| 107 | static Corner where_is_corner_aux[FACTORIAL8][8]; | ||
| 108 | static Edge where_is_edge_aux[3][FACTORIAL12/FACTORIAL8][12]; | ||
| 109 | |||
| 110 | static uint16_t epose_ttable[NTRANS][FACTORIAL12/FACTORIAL8]; | ||
| 111 | static uint16_t eposs_ttable[NTRANS][FACTORIAL12/FACTORIAL8]; | ||
| 112 | static uint16_t eposm_ttable[NTRANS][FACTORIAL12/FACTORIAL8]; | ||
| 113 | static uint16_t eo_ttable[NTRANS][POW2TO11]; | ||
| 114 | static uint16_t cp_ttable[NTRANS][FACTORIAL8]; | ||
| 115 | static uint16_t co_ttable[NTRANS][POW3TO7]; | ||
| 116 | static uint16_t cpos_ttable[NTRANS][FACTORIAL6]; | ||
| 117 | static Move moves_ttable[NTRANS][NMOVES]; | ||
| 118 | |||
| 119 | static uint16_t epose_mtable[NMOVES][FACTORIAL12/FACTORIAL8]; | ||
| 120 | static uint16_t eposs_mtable[NMOVES][FACTORIAL12/FACTORIAL8]; | ||
| 121 | static uint16_t eposm_mtable[NMOVES][FACTORIAL12/FACTORIAL8]; | ||
| 122 | static uint16_t eofb_mtable[NMOVES][POW2TO11]; | ||
| 123 | static uint16_t eorl_mtable[NMOVES][POW2TO11]; | ||
| 124 | static uint16_t eoud_mtable[NMOVES][POW2TO11]; | ||
| 125 | static uint16_t cp_mtable[NMOVES][FACTORIAL8]; | ||
| 126 | static uint16_t coud_mtable[NMOVES][POW3TO7]; | ||
| 127 | static uint16_t cofb_mtable[NMOVES][POW3TO7]; | ||
| 128 | static uint16_t corl_mtable[NMOVES][POW3TO7]; | ||
| 129 | static uint16_t cpos_mtable[NMOVES][FACTORIAL6]; | ||
| 130 | |||
| 131 | static uint64_t me[12]; | ||
| 132 | |||
| 133 | static int edge_cycle[NMOVES][12]; | ||
| 134 | static int corner_cycle[NMOVES][8]; | ||
| 135 | static int center_cycle[NMOVES][6]; | ||
| 136 | static int eofb_flipped[NMOVES][12]; | ||
| 137 | static int eorl_flipped[NMOVES][12]; | ||
| 138 | static int eoud_flipped[NMOVES][12]; | ||
| 139 | static int coud_flipped[NMOVES][8]; | ||
| 140 | static int corl_flipped[NMOVES][8]; | ||
| 141 | static int cofb_flipped[NMOVES][8]; | ||
| 142 | static Alg * equiv_alg[NMOVES]; | ||
| 143 | |||
| 144 | static int epose_source[NTRANS]; /* 0=epose, 1=eposs, 2=eposm */ | ||
| 145 | static int eposs_source[NTRANS]; | ||
| 146 | static int eposm_source[NTRANS]; | ||
| 147 | static int eofb_source[NTRANS]; /* 0=eoud, 1=eorl, 2=eofb */ | ||
| 148 | static int eorl_source[NTRANS]; | ||
| 149 | static int eoud_source[NTRANS]; | ||
| 150 | static int coud_source[NTRANS]; /* 0=coud, 1=corl, 2=cofb */ | ||
| 151 | static int cofb_source[NTRANS]; | ||
| 152 | static int corl_source[NTRANS]; | ||
| 153 | static int ep_mirror[12]; | ||
| 154 | static int cp_mirror[8]; | ||
| 155 | static int cpos_mirror[6]; | ||
| 156 | static Alg * trans_algs[NROTATIONS]; | ||
| 157 | |||
| 158 | |||
| 159 | /* Local functions implementation ********************************************/ | ||
| 160 | |||
| 161 | static Cube | ||
| 162 | admissible_ep(Cube cube, PieceFilter f) | ||
| 163 | { | ||
| 164 | CubeArray *arr = new_cubearray(cube, f); | ||
| 165 | Cube ret; | ||
| 166 | bool used[12] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; | ||
| 167 | int i, j; | ||
| 168 | |||
| 169 | for (i = 0; i < 12; i++) | ||
| 170 | if (arr->ep[i] != -1) | ||
| 171 | used[arr->ep[i]] = true; | ||
| 172 | |||
| 173 | for (i = 0, j = 0; i < 12; i++) { | ||
| 174 | for ( ; j < 11 && used[j]; j++); | ||
| 175 | if (arr->ep[i] == -1) | ||
| 176 | arr->ep[i] = j++; | ||
| 177 | } | ||
| 178 | |||
| 179 | ret = arrays_to_cube(arr, pf_ep); | ||
| 180 | free_cubearray(arr, f); | ||
| 181 | |||
| 182 | return ret; | ||
| 183 | } | ||
| 184 | |||
| 185 | static bool | ||
| 186 | allowed_next(Move move, DfsData *dd) | ||
| 187 | { | ||
| 188 | if (!possible_next[dd->last2][dd->last1][move]) | ||
| 189 | return false; | ||
| 190 | |||
| 191 | if (commute[dd->last1][move]) | ||
| 192 | return dd->move_position[dd->last1] < dd->move_position[move]; | ||
| 193 | |||
| 194 | return true; | ||
| 195 | } | ||
| 196 | |||
| 197 | static void | ||
| 198 | append_alg(AlgList *l, Alg *alg) | ||
| 199 | { | ||
| 200 | AlgListNode *node = malloc(sizeof(AlgListNode)); | ||
| 201 | int i; | ||
| 202 | |||
| 203 | node->alg = new_alg(""); | ||
| 204 | for (i = 0; i < alg->len; i++) | ||
| 205 | append_move(node->alg, alg->move[i], alg->inv[i]); | ||
| 206 | node->next = NULL; | ||
| 207 | |||
| 208 | if (++l->len == 1) | ||
| 209 | l->first = node; | ||
| 210 | else | ||
| 211 | l->last->next = node; | ||
| 212 | l->last = node; | ||
| 213 | } | ||
| 214 | |||
| 215 | static void | ||
| 216 | append_move(Alg *alg, Move m, bool inverse) | ||
| 217 | { | ||
| 218 | if (alg->len == alg->allocated) | ||
| 219 | realloc_alg(alg, 2*alg->len); | ||
| 220 | |||
| 221 | alg->move[alg->len] = m; | ||
| 222 | alg->inv [alg->len] = inverse; | ||
| 223 | alg->len++; | ||
| 224 | } | ||
| 225 | |||
| 226 | static Cube | ||
| 227 | apply_alg_generic(Alg *alg, Cube c, PieceFilter f, bool a) | ||
| 228 | { | ||
| 229 | Cube ret = {0}; | ||
| 230 | int i; | ||
| 231 | |||
| 232 | for (i = 0; i < alg->len; i++) | ||
| 233 | if (alg->inv[i]) | ||
| 234 | ret = a ? apply_move(alg->move[i], ret) : | ||
| 235 | apply_move_cubearray(alg->move[i], ret, f); | ||
| 236 | |||
| 237 | ret = compose_filtered(c, inverse_cube(ret), f); | ||
| 238 | |||
| 239 | for (i = 0; i < alg->len; i++) | ||
| 240 | if (!alg->inv[i]) | ||
| 241 | ret = a ? apply_move(alg->move[i], ret) : | ||
| 242 | apply_move_cubearray(alg->move[i], ret, f); | ||
| 243 | |||
| 244 | return ret; | ||
| 245 | } | ||
| 246 | |||
| 247 | static void | ||
| 248 | apply_permutation(int *perm, int *set, int n) | ||
| 249 | { | ||
| 250 | int *aux = malloc(n * sizeof(int)); | ||
| 251 | int i; | ||
| 252 | |||
| 253 | if (!is_perm(perm, n)) | ||
| 254 | return; | ||
| 255 | |||
| 256 | for (i = 0; i < n; i++) | ||
| 257 | aux[i] = set[perm[i]]; | ||
| 258 | |||
| 259 | memcpy(set, aux, n * sizeof(int)); | ||
| 260 | free(aux); | ||
| 261 | } | ||
| 262 | |||
| 263 | static Cube | ||
| 264 | apply_move_cubearray(Move m, Cube cube, PieceFilter f) | ||
| 265 | { | ||
| 266 | CubeArray m_arr = { | ||
| 267 | edge_cycle[m], | ||
| 268 | eofb_flipped[m], | ||
| 269 | eorl_flipped[m], | ||
| 270 | eoud_flipped[m], | ||
| 271 | corner_cycle[m], | ||
| 272 | coud_flipped[m], | ||
| 273 | corl_flipped[m], | ||
| 274 | cofb_flipped[m], | ||
| 275 | center_cycle[m] | ||
| 276 | }; | ||
| 277 | |||
| 278 | return move_via_arrays(&m_arr, cube, f); | ||
| 279 | } | ||
| 280 | |||
| 281 | static uint16_t | ||
| 282 | array_ep_to_epos(int *ep, int *ss) | ||
| 283 | { | ||
| 284 | int epos[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; | ||
| 285 | int eps[4]; | ||
| 286 | int i, j, is; | ||
| 287 | |||
| 288 | for (i = 0, is = 0; i < 12; i++) { | ||
| 289 | for (j = 0; j < 4; j++) { | ||
| 290 | if (ep[i] == ss[j]) { | ||
| 291 | eps[is++] = j; | ||
| 292 | epos[i] = 1; | ||
| 293 | } | ||
| 294 | } | ||
| 295 | } | ||
| 296 | |||
| 297 | for (i = 0; i < 4; i++) | ||
| 298 | swap(&epos[ss[i]], &epos[i+8]); | ||
| 299 | |||
| 300 | return epos_from_arrays(epos, eps); | ||
| 301 | } | ||
| 302 | |||
| 303 | static Cube | ||
| 304 | arrays_to_cube(CubeArray *arr, PieceFilter f) | ||
| 305 | { | ||
| 306 | Cube ret = {0}; | ||
| 307 | |||
| 308 | if (f.epose) | ||
| 309 | ret.epose = array_ep_to_epos(arr->ep, epe_solved); | ||
| 310 | if (f.eposs) | ||
| 311 | ret.eposs = array_ep_to_epos(arr->ep, eps_solved); | ||
| 312 | if (f.eposm) | ||
| 313 | ret.eposm = array_ep_to_epos(arr->ep, epm_solved); | ||
| 314 | if (f.eofb) | ||
| 315 | ret.eofb = digit_array_to_int(arr->eofb, 11, 2); | ||
| 316 | if (f.eorl) | ||
| 317 | ret.eorl = digit_array_to_int(arr->eorl, 11, 2); | ||
| 318 | if (f.eoud) | ||
| 319 | ret.eoud = digit_array_to_int(arr->eoud, 11, 2); | ||
| 320 | if (f.cp) | ||
| 321 | ret.cp = perm_to_index(arr->cp, 8); | ||
| 322 | if (f.coud) | ||
| 323 | ret.coud = digit_array_to_int(arr->coud, 7, 3); | ||
| 324 | if (f.corl) | ||
| 325 | ret.corl = digit_array_to_int(arr->corl, 7, 3); | ||
| 326 | if (f.cofb) | ||
| 327 | ret.cofb = digit_array_to_int(arr->cofb, 7, 3); | ||
| 328 | if (f.cpos) | ||
| 329 | ret.cpos = perm_to_index(arr->cpos, 6); | ||
| 330 | |||
| 331 | return ret; | ||
| 332 | } | ||
| 333 | |||
| 334 | static int | ||
| 335 | binomial(int n, int k) | ||
| 336 | { | ||
| 337 | if (n < 0 || k < 0 || k > n) | ||
| 338 | return 0; | ||
| 339 | |||
| 340 | return factorial(n) / (factorial(k) * factorial(n-k)); | ||
| 341 | } | ||
| 342 | |||
| 343 | static Cube | ||
| 344 | compose_filtered(Cube c2, Cube c1, PieceFilter f) | ||
| 345 | { | ||
| 346 | CubeArray *arr = new_cubearray(c2, f); | ||
| 347 | Cube ret; | ||
| 348 | |||
| 349 | ret = move_via_arrays(arr, c1, f); | ||
| 350 | free_cubearray(arr, f); | ||
| 351 | |||
| 352 | return ret; | ||
| 353 | } | ||
| 354 | |||
| 355 | static void | ||
| 356 | cube_to_arrays(Cube cube, CubeArray *arr, PieceFilter f) | ||
| 357 | { | ||
| 358 | int i; | ||
| 359 | |||
| 360 | if (f.epose || f.eposs || f.eposm) | ||
| 361 | for (i = 0; i < 12; i++) | ||
| 362 | arr->ep[i] = -1; | ||
| 363 | |||
| 364 | if (f.epose) | ||
| 365 | epos_to_partial_ep(cube.epose, arr->ep, epe_solved); | ||
| 366 | if (f.eposs) | ||
| 367 | epos_to_partial_ep(cube.eposs, arr->ep, eps_solved); | ||
| 368 | if (f.eposm) | ||
| 369 | epos_to_partial_ep(cube.eposm, arr->ep, epm_solved); | ||
| 370 | if (f.eofb) | ||
| 371 | int_to_sum_zero_array(cube.eofb, 2, 12, arr->eofb); | ||
| 372 | if (f.eorl) | ||
| 373 | int_to_sum_zero_array(cube.eorl, 2, 12, arr->eorl); | ||
| 374 | if (f.eoud) | ||
| 375 | int_to_sum_zero_array(cube.eoud, 2, 12, arr->eoud); | ||
| 376 | if (f.cp) | ||
| 377 | index_to_perm(cube.cp, 8, arr->cp); | ||
| 378 | if (f.coud) | ||
| 379 | int_to_sum_zero_array(cube.coud, 3, 8, arr->coud); | ||
| 380 | if (f.corl) | ||
| 381 | int_to_sum_zero_array(cube.corl, 3, 8, arr->corl); | ||
| 382 | if (f.cofb) | ||
| 383 | int_to_sum_zero_array(cube.cofb, 3, 8, arr->cofb); | ||
| 384 | if (f.cpos) | ||
| 385 | index_to_perm(cube.cpos, 6, arr->cpos); | ||
| 386 | } | ||
| 387 | |||
| 388 | static void | ||
| 389 | dfs(Cube c, Step s, SolveOptions *opts, DfsData *dd) | ||
| 390 | { | ||
| 391 | if (dfs_stop(c, s, opts, dd)) | ||
| 392 | return; | ||
| 393 | |||
| 394 | if (dfs_check_solved(opts, dd)) | ||
| 395 | return; | ||
| 396 | |||
| 397 | dfs_branch(c, s, opts, dd); | ||
| 398 | |||
| 399 | if (opts->can_niss && !dd->niss) | ||
| 400 | dfs_niss(c, s, opts, dd); | ||
| 401 | } | ||
| 402 | |||
| 403 | static void | ||
| 404 | dfs_branch(Cube c, Step s, SolveOptions *opts, DfsData *dd) | ||
| 405 | { | ||
| 406 | Move m, l1 = dd->last1, l2 = dd->last2, *moves = dd->sorted_moves; | ||
| 407 | |||
| 408 | int i, maxnsol = opts->max_solutions; | ||
| 409 | |||
| 410 | for (i = 0; (m=moves[i]) != NULLMOVE && dd->sols->len < maxnsol; i++) { | ||
| 411 | if (allowed_next(m, dd)) { | ||
| 412 | dd->last2 = dd->last1; | ||
| 413 | dd->last1 = m; | ||
| 414 | append_move(dd->current_alg, m, dd->niss); | ||
| 415 | |||
| 416 | dfs(apply_move(m, c), s, opts, dd); | ||
| 417 | |||
| 418 | dd->current_alg->len--; | ||
| 419 | dd->last2 = l2; | ||
| 420 | dd->last1 = l1; | ||
| 421 | } | ||
| 422 | } | ||
| 423 | } | ||
| 424 | |||
| 425 | static bool | ||
| 426 | dfs_check_solved(SolveOptions *opts, DfsData *dd) | ||
| 427 | { | ||
| 428 | if (dd->lb != 0) | ||
| 429 | return false; | ||
| 430 | |||
| 431 | if (dd->current_alg->len == dd->d) { | ||
| 432 | append_alg(dd->sols, dd->current_alg); | ||
| 433 | |||
| 434 | if (opts->feedback) | ||
| 435 | print_alg(dd->current_alg, false); | ||
| 436 | } | ||
| 437 | |||
| 438 | return true; | ||
| 439 | } | ||
| 440 | |||
| 441 | static void | ||
| 442 | dfs_niss(Cube c, Step s, SolveOptions *opts, DfsData *dd) | ||
| 443 | { | ||
| 444 | Move l1 = dd->last1, l2 = dd->last2; | ||
| 445 | |||
| 446 | if (dd->current_alg->len == 0 || | ||
| 447 | (s.check(apply_move(inverse_move(l1), (Cube){0}), 1))) { | ||
| 448 | dd->niss = true; | ||
| 449 | dd->last1 = NULLMOVE; | ||
| 450 | dd->last2 = NULLMOVE; | ||
| 451 | |||
| 452 | dfs(inverse_cube(c), s, opts, dd); | ||
| 453 | |||
| 454 | dd->last1 = l1; | ||
| 455 | dd->last2 = l2; | ||
| 456 | dd->niss = false; | ||
| 457 | } | ||
| 458 | } | ||
| 459 | |||
| 460 | static bool | ||
| 461 | dfs_stop(Cube c, Step s, SolveOptions *opts, DfsData *dd) | ||
| 462 | { | ||
| 463 | if (dd->sols->len >= opts->max_solutions) | ||
| 464 | return true; | ||
| 465 | |||
| 466 | dd->lb = s.check(c, dd->d - dd->current_alg->len); | ||
| 467 | if (opts->can_niss && !dd->niss) | ||
| 468 | dd->lb = MIN(1, dd->lb); | ||
| 469 | |||
| 470 | if (dd->current_alg->len + dd->lb > dd->d) | ||
| 471 | return true; | ||
| 472 | |||
| 473 | return false; | ||
| 474 | } | ||
| 475 | |||
| 476 | static int | ||
| 477 | digit_array_to_int(int *a, int n, int b) | ||
| 478 | { | ||
| 479 | int i, ret = 0, p = 1; | ||
| 480 | |||
| 481 | for (i = 0; i < n; i++, p *= b) | ||
| 482 | ret += a[i] * p; | ||
| 483 | |||
| 484 | return ret; | ||
| 485 | } | ||
| 486 | |||
| 487 | static int | ||
| 488 | edge_slice(Edge e) { | ||
| 489 | if (e < 0 || e > 11) | ||
| 490 | return -1; | ||
| 491 | |||
| 492 | if (e == FR || e == FL || e == BL || e == BR) | ||
| 493 | return 0; | ||
| 494 | if (e == UR || e == UL || e == DR || e == DL) | ||
| 495 | return 1; | ||
| 496 | |||
| 497 | return 2; | ||
| 498 | } | ||
| 499 | |||
| 500 | static int | ||
| 501 | epos_dependent(int poss, int pose) | ||
| 502 | { | ||
| 503 | int ep[12] = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}; | ||
| 504 | int ep8[8] = {0, 0, 0, 0, 0, 0, 0, 0}; | ||
| 505 | int i, j; | ||
| 506 | |||
| 507 | epos_to_partial_ep(poss*FACTORIAL4, ep, eps_solved); | ||
| 508 | epos_to_partial_ep(pose*FACTORIAL4, ep, epe_solved); | ||
| 509 | |||
| 510 | for (i = 0, j = 0; i < 12; i++) | ||
| 511 | if (edge_slice(ep[i]) != 0) | ||
| 512 | ep8[j++] = (edge_slice(ep[i]) == 1) ? 1 : 0; | ||
| 513 | |||
| 514 | swap(&ep8[1], &ep8[4]); | ||
| 515 | swap(&ep8[3], &ep8[6]); | ||
| 516 | |||
| 517 | return subset_to_index(ep8, 8, 4); | ||
| 518 | } | ||
| 519 | |||
| 520 | static uint16_t | ||
| 521 | epos_from_arrays(int *epos, int *ep) | ||
| 522 | { | ||
| 523 | return FACTORIAL4 * subset_to_index(epos,12,4) + perm_to_index(ep,4); | ||
| 524 | } | ||
| 525 | |||
| 526 | static void | ||
| 527 | epos_to_partial_ep(uint16_t epos, int *ep, int *ss) | ||
| 528 | { | ||
| 529 | int i, is, eposs[12], eps[4]; | ||
| 530 | |||
| 531 | index_to_perm(epos % FACTORIAL4, 4, eps); | ||
| 532 | index_to_subset(epos / FACTORIAL4, 12, 4, eposs); | ||
| 533 | |||
| 534 | for (i = 0; i < 4; i++) | ||
| 535 | swap(&eposs[ss[i]], &eposs[i+8]); | ||
| 536 | |||
| 537 | for (i = 0, is = 0; i < 12; i++) | ||
| 538 | if (eposs[i]) | ||
| 539 | ep[i] = ss[eps[is++]]; | ||
| 540 | } | ||
| 541 | |||
| 542 | static int | ||
| 543 | factorial(int n) | ||
| 544 | { | ||
| 545 | int i, ret = 1; | ||
| 546 | |||
| 547 | if (n < 0) | ||
| 548 | return 0; | ||
| 549 | |||
| 550 | for (i = 1; i <= n; i++) | ||
| 551 | ret *= i; | ||
| 552 | |||
| 553 | return ret; | ||
| 554 | } | ||
| 555 | |||
| 556 | void | ||
| 557 | free_alg(Alg *alg) | ||
| 558 | { | ||
| 559 | free(alg->move); | ||
| 560 | free(alg->inv); | ||
| 561 | free(alg); | ||
| 562 | } | ||
| 563 | |||
| 564 | void | ||
| 565 | free_alglist(AlgList *l) | ||
| 566 | { | ||
| 567 | AlgListNode *aux, *i = l->first; | ||
| 568 | |||
| 569 | while (i != NULL) { | ||
| 570 | aux = i->next; | ||
| 571 | free_alglistnode(i); | ||
| 572 | i = aux; | ||
| 573 | } | ||
| 574 | free(l); | ||
| 575 | } | ||
| 576 | |||
| 577 | void | ||
| 578 | free_alglistnode(AlgListNode *aln) | ||
| 579 | { | ||
| 580 | free_alg(aln->alg); | ||
| 581 | free(aln); | ||
| 582 | } | ||
| 583 | |||
| 584 | static void | ||
| 585 | free_cubearray(CubeArray *arr, PieceFilter f) | ||
| 586 | { | ||
| 587 | if (f.epose || f.eposs || f.eposm) | ||
| 588 | free(arr->ep); | ||
| 589 | if (f.eofb) | ||
| 590 | free(arr->eofb); | ||
| 591 | if (f.eorl) | ||
| 592 | free(arr->eorl); | ||
| 593 | if (f.eoud) | ||
| 594 | free(arr->eoud); | ||
| 595 | if (f.cp) | ||
| 596 | free(arr->cp); | ||
| 597 | if (f.coud) | ||
| 598 | free(arr->coud); | ||
| 599 | if (f.corl) | ||
| 600 | free(arr->corl); | ||
| 601 | if (f.cofb) | ||
| 602 | free(arr->cofb); | ||
| 603 | if (f.cpos) | ||
| 604 | free(arr->cpos); | ||
| 605 | |||
| 606 | free(arr); | ||
| 607 | } | ||
| 608 | |||
| 609 | static void | ||
| 610 | genptable_dfs(Cube c, PruneData *pd, DfsData *dd) | ||
| 611 | { | ||
| 612 | uint64_t ind = pd->index(c); | ||
| 613 | int oldval = ptableval(pd, ind); | ||
| 614 | |||
| 615 | if (oldval < dd->m || ptable_has_reached(pd, ind) || pd->n == pd->size) | ||
| 616 | return; | ||
| 617 | |||
| 618 | ptable_set_reached(pd, ind); | ||
| 619 | |||
| 620 | if (dd->m == dd->d) { | ||
| 621 | if (dd->m < oldval) | ||
| 622 | ptable_update(pd, ind, dd->m); | ||
| 623 | return; | ||
| 624 | } | ||
| 625 | |||
| 626 | genptable_dfs_branch(c, pd, dd); | ||
| 627 | } | ||
| 628 | |||
| 629 | static void | ||
| 630 | genptable_dfs_branch(Cube c, PruneData *pd, DfsData *dd) | ||
| 631 | { | ||
| 632 | Move i, move, l1 = dd->last1, l2 = dd->last2; | ||
| 633 | |||
| 634 | dd->m++; | ||
| 635 | |||
| 636 | for (i = 0; dd->sorted_moves[i] != NULLMOVE; i++) { | ||
| 637 | move = dd->sorted_moves[i]; | ||
| 638 | if (allowed_next(move, dd)) { | ||
| 639 | dd->last2 = dd->last1; | ||
| 640 | dd->last1 = move; | ||
| 641 | |||
| 642 | genptable_dfs(apply_move(move, c), pd, dd); | ||
| 643 | |||
| 644 | dd->last2 = l2; | ||
| 645 | dd->last1 = l1; | ||
| 646 | } | ||
| 647 | } | ||
| 648 | |||
| 649 | dd->m--; | ||
| 650 | } | ||
| 651 | |||
| 652 | static void | ||
| 653 | index_to_perm(int p, int n, int *r) | ||
| 654 | { | ||
| 655 | int *a = malloc(n * sizeof(int)); | ||
| 656 | int i, j, c; | ||
| 657 | |||
| 658 | for (i = 0; i < n; i++) | ||
| 659 | a[i] = 0; | ||
| 660 | |||
| 661 | if (p < 0 || p >= factorial(n)) | ||
| 662 | for (i = 0; i < n; i++) | ||
| 663 | r[i] = -1; | ||
| 664 | |||
| 665 | for (i = 0; i < n; i++) { | ||
| 666 | c = 0; | ||
| 667 | j = 0; | ||
| 668 | while (c <= p / factorial(n-i-1)) | ||
| 669 | c += a[j++] ? 0 : 1; | ||
| 670 | r[i] = j-1; | ||
| 671 | a[j-1] = 1; | ||
| 672 | p %= factorial(n-i-1); | ||
| 673 | } | ||
| 674 | |||
| 675 | free(a); | ||
| 676 | } | ||
| 677 | |||
| 678 | static void | ||
| 679 | index_to_subset(int s, int n, int k, int *r) | ||
| 680 | { | ||
| 681 | int i, j, v; | ||
| 682 | |||
| 683 | if (s < 0 || s >= binomial(n, k)) { | ||
| 684 | for (i = 0; i < n; i++) | ||
| 685 | r[i] = -1; | ||
| 686 | return; | ||
| 687 | } | ||
| 688 | |||
| 689 | for (i = 0; i < n; i++) { | ||
| 690 | if (k == n-i) { | ||
| 691 | for (j = i; j < n; j++) | ||
| 692 | r[j] = 1; | ||
| 693 | return; | ||
| 694 | } | ||
| 695 | |||
| 696 | if (k == 0) { | ||
| 697 | for (j = i; j < n; j++) | ||
| 698 | r[j] = 0; | ||
| 699 | return; | ||
| 700 | } | ||
| 701 | |||
| 702 | v = binomial(n-i-1, k); | ||
| 703 | if (s >= v) { | ||
| 704 | r[i] = 1; | ||
| 705 | k--; | ||
| 706 | s -= v; | ||
| 707 | } else { | ||
| 708 | r[i] = 0; | ||
| 709 | } | ||
| 710 | } | ||
| 711 | } | ||
| 712 | |||
| 713 | static void | ||
| 714 | int_to_digit_array(int a, int b, int n, int *r) | ||
| 715 | { | ||
| 716 | int i; | ||
| 717 | |||
| 718 | if (b <= 1) | ||
| 719 | for (i = 0; i < n; i++) | ||
| 720 | r[i] = 0; | ||
| 721 | else | ||
| 722 | for (i = 0; i < n; i++, a /= b) | ||
| 723 | r[i] = a % b; | ||
| 724 | } | ||
| 725 | |||
| 726 | static void | ||
| 727 | int_to_sum_zero_array(int x, int b, int n, int *a) | ||
| 728 | { | ||
| 729 | int i, s = 0; | ||
| 730 | |||
| 731 | if (b <= 1) { | ||
| 732 | for (i = 0; i < n; i++) | ||
| 733 | a[i] = 0; | ||
| 734 | } else { | ||
| 735 | int_to_digit_array(x, b, n-1, a); | ||
| 736 | for (i = 0; i < n - 1; i++) | ||
| 737 | s = (s + a[i]) % b; | ||
| 738 | a[n-1] = (b - s) % b; | ||
| 739 | } | ||
| 740 | } | ||
| 741 | |||
| 742 | static int | ||
| 743 | invert_digits(int a, int b, int n) | ||
| 744 | { | ||
| 745 | int i, ret, *r = malloc(n * sizeof(int)); | ||
| 746 | |||
| 747 | int_to_digit_array(a, b, n, r); | ||
| 748 | for (i = 0; i < n; i++) | ||
| 749 | r[i] = (b-r[i]) % b; | ||
| 750 | |||
| 751 | ret = digit_array_to_int(r, n, b); | ||
| 752 | free(r); | ||
| 753 | return ret; | ||
| 754 | } | ||
| 755 | |||
| 756 | static bool | ||
| 757 | is_perm(int *a, int n) | ||
| 758 | { | ||
| 759 | int *aux = malloc(n * sizeof(int)); | ||
| 760 | int i; | ||
| 761 | |||
| 762 | for (i = 0; i < n; i++) | ||
| 763 | if (a[i] < 0 || a[i] >= n) | ||
| 764 | return false; | ||
| 765 | else | ||
| 766 | aux[a[i]] = 1; | ||
| 767 | |||
| 768 | for (i = 0; i < n; i++) | ||
| 769 | if (!aux[i]) | ||
| 770 | return false; | ||
| 771 | |||
| 772 | free(aux); | ||
| 773 | |||
| 774 | return true; | ||
| 775 | } | ||
| 776 | |||
| 777 | static bool | ||
| 778 | is_subset(int *a, int n, int k) | ||
| 779 | { | ||
| 780 | int i, sum = 0; | ||
| 781 | |||
| 782 | for (i = 0; i < n; i++) | ||
| 783 | sum += a[i] ? 1 : 0; | ||
| 784 | |||
| 785 | return sum == k; | ||
| 786 | } | ||
| 787 | |||
| 788 | static Cube | ||
| 789 | move_via_arrays(CubeArray *arr, Cube c, PieceFilter f) | ||
| 790 | { | ||
| 791 | CubeArray *arrc = new_cubearray(c, f); | ||
| 792 | Cube ret; | ||
| 793 | |||
| 794 | if (f.epose || f.eposs || f.eposm) | ||
| 795 | apply_permutation(arr->ep, arrc->ep, 12); | ||
| 796 | |||
| 797 | if (f.eofb) { | ||
| 798 | apply_permutation(arr->ep, arrc->eofb, 12); | ||
| 799 | sum_arrays_mod(arr->eofb, arrc->eofb, 12, 2); | ||
| 800 | } | ||
| 801 | |||
| 802 | if (f.eorl) { | ||
| 803 | apply_permutation(arr->ep, arrc->eorl, 12); | ||
| 804 | sum_arrays_mod(arr->eorl, arrc->eorl, 12, 2); | ||
| 805 | } | ||
| 806 | |||
| 807 | if (f.eoud) { | ||
| 808 | apply_permutation(arr->ep, arrc->eoud, 12); | ||
| 809 | sum_arrays_mod(arr->eoud, arrc->eoud, 12, 2); | ||
| 810 | } | ||
| 811 | |||
| 812 | if (f.cp) | ||
| 813 | apply_permutation(arr->cp, arrc->cp, 8); | ||
| 814 | |||
| 815 | if (f.coud) { | ||
| 816 | apply_permutation(arr->cp, arrc->coud, 8); | ||
| 817 | sum_arrays_mod(arr->coud, arrc->coud, 8, 3); | ||
| 818 | } | ||
| 819 | |||
| 820 | if (f.corl) { | ||
| 821 | apply_permutation(arr->cp, arrc->corl, 8); | ||
| 822 | sum_arrays_mod(arr->corl, arrc->corl, 8, 3); | ||
| 823 | } | ||
| 824 | |||
| 825 | if (f.cofb) { | ||
| 826 | apply_permutation(arr->cp, arrc->cofb, 8); | ||
| 827 | sum_arrays_mod(arr->cofb, arrc->cofb, 8, 3); | ||
| 828 | } | ||
| 829 | |||
| 830 | if (f.cpos) | ||
| 831 | apply_permutation(arr->cpos, arrc->cpos, 6); | ||
| 832 | |||
| 833 | ret = arrays_to_cube(arrc, f); | ||
| 834 | free_cubearray(arrc, f); | ||
| 835 | |||
| 836 | return ret; | ||
| 837 | } | ||
| 838 | |||
| 839 | static void | ||
| 840 | movelist_to_position(Move *movelist, int *position) | ||
| 841 | { | ||
| 842 | Move m; | ||
| 843 | |||
| 844 | for (m = 0; m < NMOVES && movelist[m] != NULLMOVE; m++) | ||
| 845 | position[movelist[m]] = m; | ||
| 846 | } | ||
| 847 | |||
| 848 | static void | ||
| 849 | moveset_to_list(Moveset ms, Checker f, Move *r) | ||
| 850 | { | ||
| 851 | Cube c; | ||
| 852 | int b[NMOVES]; | ||
| 853 | int na = 0, nb = 0; | ||
| 854 | Move i; | ||
| 855 | |||
| 856 | if (ms == NULL) { | ||
| 857 | fprintf(stderr, "Error: no moveset given\n"); | ||
| 858 | return; | ||
| 859 | } | ||
| 860 | |||
| 861 | for (i = U; i < NMOVES; i++) { | ||
| 862 | if (ms(i)) { | ||
| 863 | c = apply_move(i, (Cube){0}); | ||
| 864 | if (f != NULL && f(c, 1)) | ||
| 865 | r[na++] = i; | ||
| 866 | else | ||
| 867 | b[nb++] = i; | ||
| 868 | } | ||
| 869 | } | ||
| 870 | |||
| 871 | memcpy(r + na, b, nb * sizeof(Move)); | ||
| 872 | r[na+nb] = NULLMOVE; | ||
| 873 | } | ||
| 874 | |||
| 875 | static AlgList * | ||
| 876 | new_alglist() | ||
| 877 | { | ||
| 878 | AlgList *ret = malloc(sizeof(AlgList)); | ||
| 879 | |||
| 880 | ret->len = 0; | ||
| 881 | ret->first = NULL; | ||
| 882 | ret->last = NULL; | ||
| 883 | |||
| 884 | return ret; | ||
| 885 | } | ||
| 886 | |||
| 887 | static CubeArray * | ||
| 888 | new_cubearray(Cube cube, PieceFilter f) | ||
| 889 | { | ||
| 890 | CubeArray *arr = malloc(sizeof(CubeArray)); | ||
| 891 | |||
| 892 | if (f.epose || f.eposs || f.eposm) | ||
| 893 | arr->ep = malloc(12 * sizeof(int)); | ||
| 894 | if (f.eofb) | ||
| 895 | arr->eofb = malloc(12 * sizeof(int)); | ||
| 896 | if (f.eorl) | ||
| 897 | arr->eorl = malloc(12 * sizeof(int)); | ||
| 898 | if (f.eoud) | ||
| 899 | arr->eoud = malloc(12 * sizeof(int)); | ||
| 900 | if (f.cp) | ||
| 901 | arr->cp = malloc(8 * sizeof(int)); | ||
| 902 | if (f.coud) | ||
| 903 | arr->coud = malloc(8 * sizeof(int)); | ||
| 904 | if (f.corl) | ||
| 905 | arr->corl = malloc(8 * sizeof(int)); | ||
| 906 | if (f.cofb) | ||
| 907 | arr->cofb = malloc(8 * sizeof(int)); | ||
| 908 | if (f.cpos) | ||
| 909 | arr->cpos = malloc(6 * sizeof(int)); | ||
| 910 | |||
| 911 | cube_to_arrays(cube, arr, f); | ||
| 912 | |||
| 913 | return arr; | ||
| 914 | } | ||
| 915 | |||
| 916 | static int | ||
| 917 | perm_sign(int *a, int n) | ||
| 918 | { | ||
| 919 | int i, j, ret = 0; | ||
| 920 | |||
| 921 | if (!is_perm(a,n)) | ||
| 922 | return -1; | ||
| 923 | |||
| 924 | for (i = 0; i < n; i++) | ||
| 925 | for (j = i+1; j < n; j++) | ||
| 926 | ret += (a[i] > a[j]) ? 1 : 0; | ||
| 927 | |||
| 928 | return ret % 2; | ||
| 929 | } | ||
| 930 | |||
| 931 | static int | ||
| 932 | perm_to_index(int *a, int n) | ||
| 933 | { | ||
| 934 | int i, j, c, ret = 0; | ||
| 935 | |||
| 936 | if (!is_perm(a, n)) | ||
| 937 | return -1; | ||
| 938 | |||
| 939 | for (i = 0; i < n; i++) { | ||
| 940 | c = 0; | ||
| 941 | for (j = i+1; j < n; j++) | ||
| 942 | c += (a[i] > a[j]) ? 1 : 0; | ||
| 943 | ret += factorial(n-i-1) * c; | ||
| 944 | } | ||
| 945 | |||
| 946 | return ret; | ||
| 947 | } | ||
| 948 | |||
| 949 | static int | ||
| 950 | powint(int a, int b) | ||
| 951 | { | ||
| 952 | if (b < 0) | ||
| 953 | return 0; | ||
| 954 | if (b == 0) | ||
| 955 | return 1; | ||
| 956 | |||
| 957 | if (b % 2) | ||
| 958 | return a * powint(a, b-1); | ||
| 959 | else | ||
| 960 | return powint(a*a, b/2); | ||
| 961 | } | ||
| 962 | |||
| 963 | static bool | ||
| 964 | ptable_has_reached(PruneData *pd, uint64_t ind) | ||
| 965 | { | ||
| 966 | return ind % 2 ? pd->reached[ind/2] / 16 : pd->reached[ind/2] % 16; | ||
| 967 | } | ||
| 968 | |||
| 969 | static void | ||
| 970 | ptable_set_reached(PruneData *pd, uint64_t ind) | ||
| 971 | { | ||
| 972 | uint8_t oldval2 = pd->reached[ind/2]; | ||
| 973 | int other = ind % 2 ? oldval2 % 16 : oldval2 / 16; | ||
| 974 | |||
| 975 | pd->reached[ind/2] = ind % 2 ? 16 + other : 16*other + 1; | ||
| 976 | } | ||
| 977 | |||
| 978 | static void | ||
| 979 | ptable_update(PruneData *pd, uint64_t ind, int n) | ||
| 980 | { | ||
| 981 | uint8_t oldval2 = pd->ptable[ind/2]; | ||
| 982 | int other = ind % 2 ? oldval2 % 16 : oldval2 / 16; | ||
| 983 | |||
| 984 | pd->ptable[ind/2] = ind % 2 ? 16*n + other : 16*other + n; | ||
| 985 | pd->n++; | ||
| 986 | } | ||
| 987 | |||
| 988 | static void | ||
| 989 | realloc_alg(Alg *alg, int n) | ||
| 990 | { | ||
| 991 | if (alg == NULL) { | ||
| 992 | fprintf(stderr, "Error: trying to reallocate NULL alg.\n"); | ||
| 993 | return; | ||
| 994 | } | ||
| 995 | |||
| 996 | if (n < alg->len) { | ||
| 997 | fprintf(stderr, "Error: alg too long for reallocation "); | ||
| 998 | fprintf(stderr, "(%d vs %d)\n", alg->len, n); | ||
| 999 | return; | ||
| 1000 | } | ||
| 1001 | |||
| 1002 | if (n > 1000000) { | ||
| 1003 | fprintf(stderr, "Warning: very long alg,"); | ||
| 1004 | fprintf(stderr, "something might go wrong.\n"); | ||
| 1005 | } | ||
| 1006 | |||
| 1007 | alg->move = realloc(alg->move, n * sizeof(int)); | ||
| 1008 | alg->inv = realloc(alg->inv, n * sizeof(int)); | ||
| 1009 | alg->allocated = n; | ||
| 1010 | } | ||
| 1011 | |||
| 1012 | static bool | ||
| 1013 | read_algset_file(AlgSet *as) | ||
| 1014 | { | ||
| 1015 | return false; | ||
| 1016 | } | ||
| 1017 | |||
| 1018 | static bool | ||
| 1019 | read_mtables_file() | ||
| 1020 | { | ||
| 1021 | FILE *f; | ||
| 1022 | char fname[strlen(tabledir)+20]; | ||
| 1023 | int m, b = sizeof(uint16_t); | ||
| 1024 | bool r = true; | ||
| 1025 | |||
| 1026 | strcpy(fname, tabledir); | ||
| 1027 | strcat(fname, "/mtables"); | ||
| 1028 | |||
| 1029 | if ((f = fopen(fname, "rb")) == NULL) | ||
| 1030 | return false; | ||
| 1031 | |||
| 1032 | for (m = 0; m < NMOVES; m++) { | ||
| 1033 | r = r && fread(epose_mtable[m], b, me[0], f) == me[0]; | ||
| 1034 | r = r && fread(eposs_mtable[m], b, me[1], f) == me[1]; | ||
| 1035 | r = r && fread(eposm_mtable[m], b, me[2], f) == me[2]; | ||
| 1036 | r = r && fread(eofb_mtable[m], b, me[3], f) == me[3]; | ||
| 1037 | r = r && fread(eorl_mtable[m], b, me[4], f) == me[4]; | ||
| 1038 | r = r && fread(eoud_mtable[m], b, me[5], f) == me[5]; | ||
| 1039 | r = r && fread(cp_mtable[m], b, me[6], f) == me[6]; | ||
| 1040 | r = r && fread(coud_mtable[m], b, me[7], f) == me[7]; | ||
| 1041 | r = r && fread(corl_mtable[m], b, me[8], f) == me[8]; | ||
| 1042 | r = r && fread(cofb_mtable[m], b, me[9], f) == me[9]; | ||
| 1043 | r = r && fread(cpos_mtable[m], b, me[10], f) == me[10]; | ||
| 1044 | } | ||
| 1045 | |||
| 1046 | fclose(f); | ||
| 1047 | return r; | ||
| 1048 | } | ||
| 1049 | |||
| 1050 | static bool | ||
| 1051 | read_ptable_file(PruneData *pd) | ||
| 1052 | { | ||
| 1053 | FILE *f; | ||
| 1054 | char fname[strlen(tabledir)+100]; | ||
| 1055 | uint64_t r; | ||
| 1056 | |||
| 1057 | strcpy(fname, tabledir); | ||
| 1058 | strcat(fname, "/"); | ||
| 1059 | strcat(fname, pd->filename); | ||
| 1060 | |||
| 1061 | if ((f = fopen(fname, "rb")) == NULL) | ||
| 1062 | return false; | ||
| 1063 | |||
| 1064 | r = fread(pd->ptable, sizeof(uint8_t), ptablesize(pd), f); | ||
| 1065 | fclose(f); | ||
| 1066 | |||
| 1067 | return r == ptablesize(pd); | ||
| 1068 | } | ||
| 1069 | |||
| 1070 | static bool | ||
| 1071 | read_ttables_file() | ||
| 1072 | { | ||
| 1073 | FILE *f; | ||
| 1074 | char fname[strlen(tabledir)+20]; | ||
| 1075 | int b = sizeof(uint16_t); | ||
| 1076 | bool r = true; | ||
| 1077 | Move m; | ||
| 1078 | |||
| 1079 | strcpy(fname, tabledir); | ||
| 1080 | strcat(fname, "/"); | ||
| 1081 | strcat(fname, "ttables"); | ||
| 1082 | |||
| 1083 | if ((f = fopen(fname, "rb")) == NULL) | ||
| 1084 | return false; | ||
| 1085 | |||
| 1086 | for (m = 0; m < NTRANS; m++) { | ||
| 1087 | r = r && fread(epose_ttable[m], b, me[0], f) == me[0]; | ||
| 1088 | r = r && fread(eposs_ttable[m], b, me[1], f) == me[1]; | ||
| 1089 | r = r && fread(eposm_ttable[m], b, me[2], f) == me[2]; | ||
| 1090 | r = r && fread(eo_ttable[m], b, me[3], f) == me[3]; | ||
| 1091 | r = r && fread(cp_ttable[m], b, me[6], f) == me[6]; | ||
| 1092 | r = r && fread(co_ttable[m], b, me[7], f) == me[7]; | ||
| 1093 | r = r && fread(cpos_ttable[m], b, me[10], f) == me[10]; | ||
| 1094 | r = r && fread(moves_ttable[m], b, me[11], f) == me[11]; | ||
| 1095 | } | ||
| 1096 | |||
| 1097 | fclose(f); | ||
| 1098 | return r; | ||
| 1099 | } | ||
| 1100 | |||
| 1101 | static Cube | ||
| 1102 | rotate_via_compose(Trans r, Cube c, PieceFilter f) | ||
| 1103 | { | ||
| 1104 | Alg *inv; | ||
| 1105 | static int zero12[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; | ||
| 1106 | static int zero8[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; | ||
| 1107 | static CubeArray ma = { | ||
| 1108 | .ep = ep_mirror, | ||
| 1109 | .eofb = zero12, | ||
| 1110 | .eorl = zero12, | ||
| 1111 | .eoud = zero12, | ||
| 1112 | .cp = cp_mirror, | ||
| 1113 | .coud = zero8, | ||
| 1114 | .corl = zero8, | ||
| 1115 | .cofb = zero8, | ||
| 1116 | .cpos = cpos_mirror | ||
| 1117 | }; | ||
| 1118 | |||
| 1119 | Cube ret; | ||
| 1120 | |||
| 1121 | if (r != mirror) { | ||
| 1122 | ret = apply_alg_generic(trans_algs[r], c, f, true); | ||
| 1123 | inv = on_inverse(trans_algs[r]); | ||
| 1124 | ret = apply_alg_generic(inv, ret, f, true); | ||
| 1125 | free_alg(inv); | ||
| 1126 | } else { | ||
| 1127 | ret = move_via_arrays(&ma, (Cube){0}, f); | ||
| 1128 | ret = compose_filtered(c, ret, f); | ||
| 1129 | ret = move_via_arrays(&ma, ret, f); | ||
| 1130 | } | ||
| 1131 | |||
| 1132 | return ret; | ||
| 1133 | } | ||
| 1134 | |||
| 1135 | static int | ||
| 1136 | subset_to_index(int *a, int n, int k) | ||
| 1137 | { | ||
| 1138 | int i, ret = 0; | ||
| 1139 | |||
| 1140 | if (!is_subset(a, n, k)) | ||
| 1141 | return binomial(n, k); | ||
| 1142 | |||
| 1143 | for (i = 0; i < n; i++) { | ||
| 1144 | if (k == n-i) | ||
| 1145 | return ret; | ||
| 1146 | if (a[i]) { | ||
| 1147 | ret += binomial(n-i-1, k); | ||
| 1148 | k--; | ||
| 1149 | } | ||
| 1150 | } | ||
| 1151 | |||
| 1152 | return ret; | ||
| 1153 | } | ||
| 1154 | |||
| 1155 | static void | ||
| 1156 | sum_arrays_mod(int *src, int *dst, int n, int m) | ||
| 1157 | { | ||
| 1158 | int i; | ||
| 1159 | |||
| 1160 | for (i = 0; i < n; i++) | ||
| 1161 | dst[i] = (m <= 0) ? 0 : (src[i] + dst[i]) % m; | ||
| 1162 | } | ||
| 1163 | |||
| 1164 | static void | ||
| 1165 | swap(int *a, int *b) | ||
| 1166 | { | ||
| 1167 | int aux; | ||
| 1168 | |||
| 1169 | aux = *a; | ||
| 1170 | *a = *b; | ||
| 1171 | *b = aux; | ||
| 1172 | } | ||
| 1173 | |||
| 1174 | static bool | ||
| 1175 | write_algset_file(AlgSet *as) | ||
| 1176 | { | ||
| 1177 | return false; | ||
| 1178 | } | ||
| 1179 | |||
| 1180 | static bool | ||
| 1181 | write_mtables_file() | ||
| 1182 | { | ||
| 1183 | FILE *f; | ||
| 1184 | char fname[strlen(tabledir)+20]; | ||
| 1185 | int m, b = sizeof(uint16_t); | ||
| 1186 | bool r = true; | ||
| 1187 | |||
| 1188 | strcpy(fname, tabledir); | ||
| 1189 | strcat(fname, "/mtables"); | ||
| 1190 | |||
| 1191 | if ((f = fopen(fname, "wb")) == NULL) | ||
| 1192 | return false; | ||
| 1193 | |||
| 1194 | for (m = 0; m < NMOVES; m++) { | ||
| 1195 | r = r && fwrite(epose_mtable[m], b, me[0], f) == me[0]; | ||
| 1196 | r = r && fwrite(eposs_mtable[m], b, me[1], f) == me[1]; | ||
| 1197 | r = r && fwrite(eposm_mtable[m], b, me[2], f) == me[2]; | ||
| 1198 | r = r && fwrite(eofb_mtable[m], b, me[3], f) == me[3]; | ||
| 1199 | r = r && fwrite(eorl_mtable[m], b, me[4], f) == me[4]; | ||
| 1200 | r = r && fwrite(eoud_mtable[m], b, me[5], f) == me[5]; | ||
| 1201 | r = r && fwrite(cp_mtable[m], b, me[6], f) == me[6]; | ||
| 1202 | r = r && fwrite(coud_mtable[m], b, me[7], f) == me[7]; | ||
| 1203 | r = r && fwrite(corl_mtable[m], b, me[8], f) == me[8]; | ||
| 1204 | r = r && fwrite(cofb_mtable[m], b, me[9], f) == me[9]; | ||
| 1205 | r = r && fwrite(cpos_mtable[m], b, me[10], f) == me[10]; | ||
| 1206 | } | ||
| 1207 | |||
| 1208 | fclose(f); | ||
| 1209 | return r; | ||
| 1210 | } | ||
| 1211 | |||
| 1212 | static bool | ||
| 1213 | write_ptable_file(PruneData *pd) | ||
| 1214 | { | ||
| 1215 | FILE *f; | ||
| 1216 | char fname[strlen(tabledir)+100]; | ||
| 1217 | uint64_t written; | ||
| 1218 | |||
| 1219 | strcpy(fname, tabledir); | ||
| 1220 | strcat(fname, "/"); | ||
| 1221 | strcat(fname, pd->filename); | ||
| 1222 | |||
| 1223 | if ((f = fopen(fname, "wb")) == NULL) | ||
| 1224 | return false; | ||
| 1225 | |||
| 1226 | written = fwrite(pd->ptable, sizeof(uint8_t), ptablesize(pd), f); | ||
| 1227 | fclose(f); | ||
| 1228 | |||
| 1229 | return written == ptablesize(pd); | ||
| 1230 | } | ||
| 1231 | |||
| 1232 | static bool | ||
| 1233 | write_ttables_file() | ||
| 1234 | { | ||
| 1235 | FILE *f; | ||
| 1236 | char fname[strlen(tabledir)+20]; | ||
| 1237 | bool r = true; | ||
| 1238 | int b = sizeof(uint16_t); | ||
| 1239 | Move m; | ||
| 1240 | |||
| 1241 | strcpy(fname, tabledir); | ||
| 1242 | strcat(fname, "/ttables"); | ||
| 1243 | |||
| 1244 | if ((f = fopen(fname, "wb")) == NULL) | ||
| 1245 | return false; | ||
| 1246 | |||
| 1247 | for (m = 0; m < NTRANS; m++) { | ||
| 1248 | r = r && fwrite(epose_ttable[m], b, me[0], f) == me[0]; | ||
| 1249 | r = r && fwrite(eposs_ttable[m], b, me[1], f) == me[1]; | ||
| 1250 | r = r && fwrite(eposm_ttable[m], b, me[2], f) == me[2]; | ||
| 1251 | r = r && fwrite(eo_ttable[m], b, me[3], f) == me[3]; | ||
| 1252 | r = r && fwrite(cp_ttable[m], b, me[6], f) == me[6]; | ||
| 1253 | r = r && fwrite(co_ttable[m], b, me[7], f) == me[7]; | ||
| 1254 | r = r && fwrite(cpos_ttable[m], b, me[10], f) == me[10]; | ||
| 1255 | r = r && fwrite(moves_ttable[m], b, me[11], f) == me[11]; | ||
| 1256 | } | ||
| 1257 | |||
| 1258 | fclose(f); | ||
| 1259 | return r; | ||
| 1260 | } | ||
| 1261 | |||
| 1262 | /* Init functions implementation *********************************************/ | ||
| 1263 | |||
| 1264 | static void | ||
| 1265 | init_auxtables() | ||
| 1266 | { | ||
| 1267 | Cube c1, c2; | ||
| 1268 | CubeArray *arr; | ||
| 1269 | uint64_t ui, uj; | ||
| 1270 | int i, j, k, auxarr[12]; | ||
| 1271 | bool cij, p1, p2; | ||
| 1272 | |||
| 1273 | for (ui = 0; ui < FACTORIAL6; ui++) { | ||
| 1274 | arr = new_cubearray((Cube){.cpos = ui}, pf_cpos); | ||
| 1275 | for (i = 0; i < 6; i++) { | ||
| 1276 | what_center_at_aux[ui][i] = arr->cpos[i]; | ||
| 1277 | where_is_center_aux[ui][arr->cpos[i]] = i; | ||
| 1278 | } | ||
| 1279 | free_cubearray(arr, pf_cpos); | ||
| 1280 | } | ||
| 1281 | |||
| 1282 | for (ui = 0; ui < FACTORIAL8; ui++) { | ||
| 1283 | arr = new_cubearray((Cube){.cp = ui}, pf_cp); | ||
| 1284 | for (i = 0; i < 8; i++) { | ||
| 1285 | what_corner_at_aux[ui][i] = arr->cp[i]; | ||
| 1286 | where_is_corner_aux[ui][arr->cp[i]] = i; | ||
| 1287 | } | ||
| 1288 | free_cubearray(arr, pf_cp); | ||
| 1289 | } | ||
| 1290 | |||
| 1291 | for (ui = 0; ui < FACTORIAL12/FACTORIAL8; ui++) { | ||
| 1292 | arr = new_cubearray((Cube){.epose = ui}, pf_e); | ||
| 1293 | for (i = 0; i < 12; i++) | ||
| 1294 | if (edge_slice(arr->ep[i]) == 0) | ||
| 1295 | where_is_edge_aux[0][ui][arr->ep[i]] = i; | ||
| 1296 | free_cubearray(arr, pf_e); | ||
| 1297 | |||
| 1298 | arr = new_cubearray((Cube){.eposs = ui}, pf_s); | ||
| 1299 | for (i = 0; i < 12; i++) | ||
| 1300 | if (edge_slice(arr->ep[i]) == 1) | ||
| 1301 | where_is_edge_aux[1][ui][arr->ep[i]] = i; | ||
| 1302 | free_cubearray(arr, pf_s); | ||
| 1303 | |||
| 1304 | arr = new_cubearray((Cube){.eposm = ui}, pf_m); | ||
| 1305 | for (i = 0; i < 12; i++) | ||
| 1306 | if (edge_slice(arr->ep[i]) == 2) | ||
| 1307 | where_is_edge_aux[2][ui][arr->ep[i]] = i; | ||
| 1308 | free_cubearray(arr, pf_m); | ||
| 1309 | } | ||
| 1310 | |||
| 1311 | for (ui = 0; ui < POW3TO7; ui++) { | ||
| 1312 | int_to_sum_zero_array(ui, 3, 8, auxarr); | ||
| 1313 | what_orientation_last_corner_aux[ui] = auxarr[7]; | ||
| 1314 | } | ||
| 1315 | |||
| 1316 | for (ui = 0; ui < POW2TO11; ui++) { | ||
| 1317 | int_to_sum_zero_array(ui, 2, 12, auxarr); | ||
| 1318 | what_orientation_last_edge_aux[ui] = auxarr[11]; | ||
| 1319 | } | ||
| 1320 | |||
| 1321 | for (ui = 0; ui < BINOM12ON4; ui++) | ||
| 1322 | for (uj = 0; uj < BINOM12ON4; uj++) | ||
| 1323 | epos_dependent_aux[ui][uj] = epos_dependent(ui, uj); | ||
| 1324 | |||
| 1325 | for (i = 0; i < NMOVES; i++) { | ||
| 1326 | for (j = 0; j < NMOVES; j++) { | ||
| 1327 | c1 = apply_move(i, apply_move(j, (Cube){0})); | ||
| 1328 | c2 = apply_move(j, apply_move(i, (Cube){0})); | ||
| 1329 | commute[i][j] = equal(c1, c2) && i && j; | ||
| 1330 | } | ||
| 1331 | } | ||
| 1332 | |||
| 1333 | for (i = 0; i < NMOVES; i++) { | ||
| 1334 | for (j = 0; j < NMOVES; j++) { | ||
| 1335 | for (k = 0; k < NMOVES; k++) { | ||
| 1336 | p1 = j && base_move(j) == base_move(k); | ||
| 1337 | p2 = i && base_move(i) == base_move(k); | ||
| 1338 | cij = commute[i][j]; | ||
| 1339 | possible_next[i][j][k] = !(p1 || (cij && p2)); | ||
| 1340 | } | ||
| 1341 | } | ||
| 1342 | } | ||
| 1343 | |||
| 1344 | for (i = 0; i < NMOVES; i++) | ||
| 1345 | inverse_move_aux[i] = i ? i + 2 - 2*((i-1)%3) : NULLMOVE; | ||
| 1346 | |||
| 1347 | /* Is there a more elegant way? */ | ||
| 1348 | inverse_trans_aux[uf] = uf; | ||
| 1349 | inverse_trans_aux[ur] = ul; | ||
| 1350 | inverse_trans_aux[ul] = ur; | ||
| 1351 | inverse_trans_aux[ub] = ub; | ||
| 1352 | |||
| 1353 | inverse_trans_aux[df] = df; | ||
| 1354 | inverse_trans_aux[dr] = dr; | ||
| 1355 | inverse_trans_aux[dl] = dl; | ||
| 1356 | inverse_trans_aux[db] = db; | ||
| 1357 | |||
| 1358 | inverse_trans_aux[rf] = lf; | ||
| 1359 | inverse_trans_aux[rd] = bl; | ||
| 1360 | inverse_trans_aux[rb] = rb; | ||
| 1361 | inverse_trans_aux[ru] = fr; | ||
| 1362 | |||
| 1363 | inverse_trans_aux[lf] = rf; | ||
| 1364 | inverse_trans_aux[ld] = br; | ||
| 1365 | inverse_trans_aux[lb] = lb; | ||
| 1366 | inverse_trans_aux[lu] = fl; | ||
| 1367 | |||
| 1368 | inverse_trans_aux[fu] = fu; | ||
| 1369 | inverse_trans_aux[fr] = ru; | ||
| 1370 | inverse_trans_aux[fd] = bu; | ||
| 1371 | inverse_trans_aux[fl] = lu; | ||
| 1372 | |||
| 1373 | inverse_trans_aux[bu] = fd; | ||
| 1374 | inverse_trans_aux[br] = ld; | ||
| 1375 | inverse_trans_aux[bd] = bd; | ||
| 1376 | inverse_trans_aux[bl] = rd; | ||
| 1377 | |||
| 1378 | inverse_trans_aux[mirror] = mirror; | ||
| 1379 | } | ||
| 1380 | |||
| 1381 | static void | ||
| 1382 | init_environment() | ||
| 1383 | { | ||
| 1384 | char *nissydata = getenv("NISSYDATA"); | ||
| 1385 | char *localdata = getenv("XDG_DATA_HOME"); | ||
| 1386 | char *home = getenv("HOME"); | ||
| 1387 | bool read, write; | ||
| 1388 | |||
| 1389 | if (nissydata != NULL) { | ||
| 1390 | tabledir = malloc(strlen(nissydata) * sizeof(char) + 20); | ||
| 1391 | strcpy(tabledir, nissydata); | ||
| 1392 | } else if (localdata != NULL) { | ||
| 1393 | tabledir = malloc(strlen(localdata) * sizeof(char) + 20); | ||
| 1394 | strcpy(tabledir, localdata); | ||
| 1395 | strcat(tabledir, "/nissy"); | ||
| 1396 | } else if (home != NULL) { | ||
| 1397 | tabledir = malloc(strlen(home) * sizeof(char) + 20); | ||
| 1398 | strcpy(tabledir, home); | ||
| 1399 | strcat(tabledir, "/.nissy"); | ||
| 1400 | } | ||
| 1401 | |||
| 1402 | mkdir(tabledir, 0777); | ||
| 1403 | strcat(tabledir, "/tables"); | ||
| 1404 | mkdir(tabledir, 0777); | ||
| 1405 | |||
| 1406 | read = !access(tabledir, R_OK); | ||
| 1407 | write = !access(tabledir, W_OK); | ||
| 1408 | |||
| 1409 | if (!read) { | ||
| 1410 | fprintf(stderr, "Table files cannot be read.\n"); | ||
| 1411 | } else if (!write) { | ||
| 1412 | fprintf(stderr, "Data directory not writable: "); | ||
| 1413 | fprintf(stderr, "tables can be loaded, but not saved.\n"); | ||
| 1414 | } | ||
| 1415 | } | ||
| 1416 | |||
| 1417 | static void | ||
| 1418 | init_moves() { | ||
| 1419 | Cube c; | ||
| 1420 | CubeArray arrs; | ||
| 1421 | int i; | ||
| 1422 | uint16_t ui; | ||
| 1423 | Move m; | ||
| 1424 | |||
| 1425 | /* Generate all move cycles and flips; I do this regardless */ | ||
| 1426 | for (i = 0; i < NMOVES; i++) { | ||
| 1427 | if (i == U || i == x || i == y) | ||
| 1428 | continue; | ||
| 1429 | |||
| 1430 | c = apply_alg_generic(equiv_alg[i], (Cube){0}, pf_all, false); | ||
| 1431 | |||
| 1432 | arrs = (CubeArray) { | ||
| 1433 | edge_cycle[i], | ||
| 1434 | eofb_flipped[i], | ||
| 1435 | eorl_flipped[i], | ||
| 1436 | eoud_flipped[i], | ||
| 1437 | corner_cycle[i], | ||
| 1438 | coud_flipped[i], | ||
| 1439 | corl_flipped[i], | ||
| 1440 | cofb_flipped[i], | ||
| 1441 | center_cycle[i] | ||
| 1442 | }; | ||
| 1443 | cube_to_arrays(c, &arrs, pf_all); | ||
| 1444 | } | ||
| 1445 | |||
| 1446 | if (read_mtables_file()) | ||
| 1447 | return; | ||
| 1448 | |||
| 1449 | fprintf(stderr, "Cannot load %s, generating it\n", "mtables"); | ||
| 1450 | |||
| 1451 | /* Initialize transition tables */ | ||
| 1452 | for (m = 0; m < NMOVES; m++) { | ||
| 1453 | for (ui = 0; ui < FACTORIAL12/FACTORIAL8; ui++) { | ||
| 1454 | c = (Cube){ .epose = ui }; | ||
| 1455 | c = apply_move_cubearray(m, c, pf_e); | ||
| 1456 | epose_mtable[m][ui] = c.epose; | ||
| 1457 | |||
| 1458 | c = (Cube){ .eposs = ui }; | ||
| 1459 | c = apply_move_cubearray(m, c, pf_s); | ||
| 1460 | eposs_mtable[m][ui] = c.eposs; | ||
| 1461 | |||
| 1462 | c = (Cube){ .eposm = ui }; | ||
| 1463 | c = apply_move_cubearray(m, c, pf_m); | ||
| 1464 | eposm_mtable[m][ui] = c.eposm; | ||
| 1465 | } | ||
| 1466 | for (ui = 0; ui < POW2TO11; ui++ ) { | ||
| 1467 | c = (Cube){ .eofb = ui }; | ||
| 1468 | c = apply_move_cubearray(m, c, pf_eo); | ||
| 1469 | eofb_mtable[m][ui] = c.eofb; | ||
| 1470 | |||
| 1471 | c = (Cube){ .eorl = ui }; | ||
| 1472 | c = apply_move_cubearray(m, c, pf_eo); | ||
| 1473 | eorl_mtable[m][ui] = c.eorl; | ||
| 1474 | |||
| 1475 | c = (Cube){ .eoud = ui }; | ||
| 1476 | c = apply_move_cubearray(m, c, pf_eo); | ||
| 1477 | eoud_mtable[m][ui] = c.eoud; | ||
| 1478 | } | ||
| 1479 | for (ui = 0; ui < POW3TO7; ui++) { | ||
| 1480 | c = (Cube){ .coud = ui }; | ||
| 1481 | c = apply_move_cubearray(m, c, pf_co); | ||
| 1482 | coud_mtable[m][ui] = c.coud; | ||
| 1483 | |||
| 1484 | c = (Cube){ .corl = ui }; | ||
| 1485 | c = apply_move_cubearray(m, c, pf_co); | ||
| 1486 | corl_mtable[m][ui] = c.corl; | ||
| 1487 | |||
| 1488 | c = (Cube){ .cofb = ui }; | ||
| 1489 | c = apply_move_cubearray(m, c, pf_co); | ||
| 1490 | cofb_mtable[m][ui] = c.cofb; | ||
| 1491 | } | ||
| 1492 | for (ui = 0; ui < FACTORIAL8; ui++) { | ||
| 1493 | c = (Cube){ .cp = ui }; | ||
| 1494 | c = apply_move_cubearray(m, c, pf_cp); | ||
| 1495 | cp_mtable[m][ui] = c.cp; | ||
| 1496 | } | ||
| 1497 | for (ui = 0; ui < FACTORIAL6; ui++) { | ||
| 1498 | c = (Cube){ .cpos = ui }; | ||
| 1499 | c = apply_move_cubearray(m, c, pf_cpos); | ||
| 1500 | cpos_mtable[m][ui] = c.cpos; | ||
| 1501 | } | ||
| 1502 | } | ||
| 1503 | |||
| 1504 | if (!write_mtables_file()) | ||
| 1505 | fprintf(stderr, "Error writing mtables\n"); | ||
| 1506 | } | ||
| 1507 | |||
| 1508 | static void | ||
| 1509 | init_moves_aux() | ||
| 1510 | { | ||
| 1511 | /* Some standard PieceFilters */ | ||
| 1512 | pf_all.epose = true; | ||
| 1513 | pf_all.eposs = true; | ||
| 1514 | pf_all.eposm = true; | ||
| 1515 | pf_all.eofb = true; | ||
| 1516 | pf_all.eorl = true; | ||
| 1517 | pf_all.eoud = true; | ||
| 1518 | pf_all.cp = true; | ||
| 1519 | pf_all.cofb = true; | ||
| 1520 | pf_all.corl = true; | ||
| 1521 | pf_all.coud = true; | ||
| 1522 | pf_all.cpos = true; | ||
| 1523 | |||
| 1524 | pf_4val.epose = true; | ||
| 1525 | pf_4val.eposs = true; | ||
| 1526 | pf_4val.eposm = true; | ||
| 1527 | pf_4val.eofb = true; | ||
| 1528 | pf_4val.coud = true; | ||
| 1529 | pf_4val.cp = true; | ||
| 1530 | |||
| 1531 | pf_epcp.epose = true; | ||
| 1532 | pf_epcp.eposs = true; | ||
| 1533 | pf_epcp.eposm = true; | ||
| 1534 | pf_epcp.cp = true; | ||
| 1535 | |||
| 1536 | pf_cpos.cpos = true; | ||
| 1537 | |||
| 1538 | pf_cp.cp = true; | ||
| 1539 | |||
| 1540 | pf_ep.epose = true; | ||
| 1541 | pf_ep.eposs = true; | ||
| 1542 | pf_ep.eposm = true; | ||
| 1543 | |||
| 1544 | pf_e.epose = true; | ||
| 1545 | pf_s.eposs = true; | ||
| 1546 | pf_m.eposm = true; | ||
| 1547 | |||
| 1548 | pf_eo.eofb = true; | ||
| 1549 | pf_eo.eorl = true; | ||
| 1550 | pf_eo.eoud = true; | ||
| 1551 | |||
| 1552 | pf_co.cofb = true; | ||
| 1553 | pf_co.corl = true; | ||
| 1554 | pf_co.coud = true; | ||
| 1555 | |||
| 1556 | /* Used to convert to and from CubeArray */ | ||
| 1557 | epe_solved[0] = FR; | ||
| 1558 | epe_solved[1] = FL; | ||
| 1559 | epe_solved[2] = BL; | ||
| 1560 | epe_solved[3] = BR; | ||
| 1561 | |||
| 1562 | eps_solved[0] = UL; | ||
| 1563 | eps_solved[1] = UR; | ||
| 1564 | eps_solved[2] = DL; | ||
| 1565 | eps_solved[3] = DR; | ||
| 1566 | |||
| 1567 | epm_solved[0] = UF; | ||
| 1568 | epm_solved[1] = UB; | ||
| 1569 | epm_solved[2] = DF; | ||
| 1570 | epm_solved[3] = DB; | ||
| 1571 | |||
| 1572 | /* Table sizes, used for reading and writing files */ | ||
| 1573 | me[0] = FACTORIAL12/FACTORIAL8; | ||
| 1574 | me[1] = FACTORIAL12/FACTORIAL8; | ||
| 1575 | me[2] = FACTORIAL12/FACTORIAL8; | ||
| 1576 | me[3] = POW2TO11; | ||
| 1577 | me[4] = POW2TO11; | ||
| 1578 | me[5] = POW2TO11; | ||
| 1579 | me[6] = FACTORIAL8; | ||
| 1580 | me[7] = POW3TO7; | ||
| 1581 | me[8] = POW3TO7; | ||
| 1582 | me[9] = POW3TO7; | ||
| 1583 | me[10] = FACTORIAL6; | ||
| 1584 | me[11] = NMOVES; | ||
| 1585 | |||
| 1586 | /* Cycles *********************/ | ||
| 1587 | edge_cycle[U][UF] = UR; | ||
| 1588 | edge_cycle[U][UL] = UF; | ||
| 1589 | edge_cycle[U][UB] = UL; | ||
| 1590 | edge_cycle[U][UR] = UB; | ||
| 1591 | edge_cycle[U][DF] = DF; | ||
| 1592 | edge_cycle[U][DL] = DL; | ||
| 1593 | edge_cycle[U][DB] = DB; | ||
| 1594 | edge_cycle[U][DR] = DR; | ||
| 1595 | edge_cycle[U][FR] = FR; | ||
| 1596 | edge_cycle[U][FL] = FL; | ||
| 1597 | edge_cycle[U][BL] = BL; | ||
| 1598 | edge_cycle[U][BR] = BR; | ||
| 1599 | |||
| 1600 | edge_cycle[x][UF] = DF; | ||
| 1601 | edge_cycle[x][UL] = FL; | ||
| 1602 | edge_cycle[x][UB] = UF; | ||
| 1603 | edge_cycle[x][UR] = FR; | ||
| 1604 | edge_cycle[x][DF] = DB; | ||
| 1605 | edge_cycle[x][DL] = BL; | ||
| 1606 | edge_cycle[x][DB] = UB; | ||
| 1607 | edge_cycle[x][DR] = BR; | ||
| 1608 | edge_cycle[x][FR] = DR; | ||
| 1609 | edge_cycle[x][FL] = DL; | ||
| 1610 | edge_cycle[x][BL] = UL; | ||
| 1611 | edge_cycle[x][BR] = UR; | ||
| 1612 | |||
| 1613 | edge_cycle[y][UF] = UR; | ||
| 1614 | edge_cycle[y][UL] = UF; | ||
| 1615 | edge_cycle[y][UB] = UL; | ||
| 1616 | edge_cycle[y][UR] = UB; | ||
| 1617 | edge_cycle[y][DF] = DR; | ||
| 1618 | edge_cycle[y][DL] = DF; | ||
| 1619 | edge_cycle[y][DB] = DL; | ||
| 1620 | edge_cycle[y][DR] = DB; | ||
| 1621 | edge_cycle[y][FR] = BR; | ||
| 1622 | edge_cycle[y][FL] = FR; | ||
| 1623 | edge_cycle[y][BL] = FL; | ||
| 1624 | edge_cycle[y][BR] = BL; | ||
| 1625 | |||
| 1626 | corner_cycle[U][UFR] = UBR; | ||
| 1627 | corner_cycle[U][UFL] = UFR; | ||
| 1628 | corner_cycle[U][UBL] = UFL; | ||
| 1629 | corner_cycle[U][UBR] = UBL; | ||
| 1630 | corner_cycle[U][DFR] = DFR; | ||
| 1631 | corner_cycle[U][DFL] = DFL; | ||
| 1632 | corner_cycle[U][DBL] = DBL; | ||
| 1633 | corner_cycle[U][DBR] = DBR; | ||
| 1634 | |||
| 1635 | corner_cycle[x][UFR] = DFR; | ||
| 1636 | corner_cycle[x][UFL] = DFL; | ||
| 1637 | corner_cycle[x][UBL] = UFL; | ||
| 1638 | corner_cycle[x][UBR] = UFR; | ||
| 1639 | corner_cycle[x][DFR] = DBR; | ||
| 1640 | corner_cycle[x][DFL] = DBL; | ||
| 1641 | corner_cycle[x][DBL] = UBL; | ||
| 1642 | corner_cycle[x][DBR] = UBR; | ||
| 1643 | |||
| 1644 | corner_cycle[y][UFR] = UBR; | ||
| 1645 | corner_cycle[y][UFL] = UFR; | ||
| 1646 | corner_cycle[y][UBL] = UFL; | ||
| 1647 | corner_cycle[y][UBR] = UBL; | ||
| 1648 | corner_cycle[y][DFR] = DBR; | ||
| 1649 | corner_cycle[y][DFL] = DFR; | ||
| 1650 | corner_cycle[y][DBL] = DFL; | ||
| 1651 | corner_cycle[y][DBR] = DBL; | ||
| 1652 | |||
| 1653 | center_cycle[U][U_center] = U_center; | ||
| 1654 | center_cycle[U][D_center] = D_center; | ||
| 1655 | center_cycle[U][R_center] = R_center; | ||
| 1656 | center_cycle[U][L_center] = L_center; | ||
| 1657 | center_cycle[U][F_center] = F_center; | ||
| 1658 | center_cycle[U][B_center] = B_center; | ||
| 1659 | |||
| 1660 | center_cycle[x][U_center] = F_center; | ||
| 1661 | center_cycle[x][D_center] = B_center; | ||
| 1662 | center_cycle[x][R_center] = R_center; | ||
| 1663 | center_cycle[x][L_center] = L_center; | ||
| 1664 | center_cycle[x][F_center] = D_center; | ||
| 1665 | center_cycle[x][B_center] = U_center; | ||
| 1666 | |||
| 1667 | center_cycle[y][U_center] = U_center; | ||
| 1668 | center_cycle[y][D_center] = D_center; | ||
| 1669 | center_cycle[y][R_center] = B_center; | ||
| 1670 | center_cycle[y][L_center] = F_center; | ||
| 1671 | center_cycle[y][F_center] = R_center; | ||
| 1672 | center_cycle[y][B_center] = L_center; | ||
| 1673 | |||
| 1674 | /* Flipped pieces *************/ | ||
| 1675 | eofb_flipped[x][UF] = 1; | ||
| 1676 | eofb_flipped[x][UB] = 1; | ||
| 1677 | eofb_flipped[x][DF] = 1; | ||
| 1678 | eofb_flipped[x][DB] = 1; | ||
| 1679 | |||
| 1680 | eofb_flipped[y][FR] = 1; | ||
| 1681 | eofb_flipped[y][FL] = 1; | ||
| 1682 | eofb_flipped[y][BL] = 1; | ||
| 1683 | eofb_flipped[y][BR] = 1; | ||
| 1684 | |||
| 1685 | eorl_flipped[x][UF] = 1; | ||
| 1686 | eorl_flipped[x][UL] = 1; | ||
| 1687 | eorl_flipped[x][UB] = 1; | ||
| 1688 | eorl_flipped[x][UR] = 1; | ||
| 1689 | eorl_flipped[x][DF] = 1; | ||
| 1690 | eorl_flipped[x][DL] = 1; | ||
| 1691 | eorl_flipped[x][DB] = 1; | ||
| 1692 | eorl_flipped[x][DR] = 1; | ||
| 1693 | eorl_flipped[x][FR] = 1; | ||
| 1694 | eorl_flipped[x][FL] = 1; | ||
| 1695 | eorl_flipped[x][BL] = 1; | ||
| 1696 | eorl_flipped[x][BR] = 1; | ||
| 1697 | |||
| 1698 | eorl_flipped[y][FR] = 1; | ||
| 1699 | eorl_flipped[y][FL] = 1; | ||
| 1700 | eorl_flipped[y][BL] = 1; | ||
| 1701 | eorl_flipped[y][BR] = 1; | ||
| 1702 | |||
| 1703 | eoud_flipped[U][UF] = 1; | ||
| 1704 | eoud_flipped[U][UL] = 1; | ||
| 1705 | eoud_flipped[U][UB] = 1; | ||
| 1706 | eoud_flipped[U][UR] = 1; | ||
| 1707 | |||
| 1708 | eoud_flipped[x][UF] = 1; | ||
| 1709 | eoud_flipped[x][UB] = 1; | ||
| 1710 | eoud_flipped[x][DF] = 1; | ||
| 1711 | eoud_flipped[x][DB] = 1; | ||
| 1712 | |||
| 1713 | eoud_flipped[y][UF] = 1; | ||
| 1714 | eoud_flipped[y][UL] = 1; | ||
| 1715 | eoud_flipped[y][UB] = 1; | ||
| 1716 | eoud_flipped[y][UR] = 1; | ||
| 1717 | eoud_flipped[y][DF] = 1; | ||
| 1718 | eoud_flipped[y][DL] = 1; | ||
| 1719 | eoud_flipped[y][DB] = 1; | ||
| 1720 | eoud_flipped[y][DR] = 1; | ||
| 1721 | eoud_flipped[y][FR] = 1; | ||
| 1722 | eoud_flipped[y][FL] = 1; | ||
| 1723 | eoud_flipped[y][BL] = 1; | ||
| 1724 | eoud_flipped[y][BR] = 1; | ||
| 1725 | |||
| 1726 | coud_flipped[x][UFR] = 2; | ||
| 1727 | coud_flipped[x][UFL] = 1; | ||
| 1728 | coud_flipped[x][UBR] = 1; | ||
| 1729 | coud_flipped[x][UBL] = 2; | ||
| 1730 | coud_flipped[x][DFR] = 1; | ||
| 1731 | coud_flipped[x][DFL] = 2; | ||
| 1732 | coud_flipped[x][DBR] = 2; | ||
| 1733 | coud_flipped[x][DBL] = 1; | ||
| 1734 | |||
| 1735 | corl_flipped[U][UFR] = 1; | ||
| 1736 | corl_flipped[U][UFL] = 2; | ||
| 1737 | corl_flipped[U][UBL] = 1; | ||
| 1738 | corl_flipped[U][UBR] = 2; | ||
| 1739 | |||
| 1740 | corl_flipped[y][UFR] = 1; | ||
| 1741 | corl_flipped[y][UFL] = 2; | ||
| 1742 | corl_flipped[y][UBL] = 1; | ||
| 1743 | corl_flipped[y][UBR] = 2; | ||
| 1744 | corl_flipped[y][DFR] = 2; | ||
| 1745 | corl_flipped[y][DFL] = 1; | ||
| 1746 | corl_flipped[y][DBL] = 2; | ||
| 1747 | corl_flipped[y][DBR] = 1; | ||
| 1748 | |||
| 1749 | cofb_flipped[U][UFR] = 2; | ||
| 1750 | cofb_flipped[U][UFL] = 1; | ||
| 1751 | cofb_flipped[U][UBL] = 2; | ||
| 1752 | cofb_flipped[U][UBR] = 1; | ||
| 1753 | |||
| 1754 | cofb_flipped[x][UFR] = 1; | ||
| 1755 | cofb_flipped[x][UFL] = 2; | ||
| 1756 | cofb_flipped[x][UBL] = 1; | ||
| 1757 | cofb_flipped[x][UBR] = 2; | ||
| 1758 | cofb_flipped[x][DFR] = 2; | ||
| 1759 | cofb_flipped[x][DFL] = 1; | ||
| 1760 | cofb_flipped[x][DBL] = 2; | ||
| 1761 | cofb_flipped[x][DBR] = 1; | ||
| 1762 | |||
| 1763 | cofb_flipped[y][UFR] = 2; | ||
| 1764 | cofb_flipped[y][UFL] = 1; | ||
| 1765 | cofb_flipped[y][UBL] = 2; | ||
| 1766 | cofb_flipped[y][UBR] = 1; | ||
| 1767 | cofb_flipped[y][DFR] = 1; | ||
| 1768 | cofb_flipped[y][DFL] = 2; | ||
| 1769 | cofb_flipped[y][DBL] = 1; | ||
| 1770 | cofb_flipped[y][DBR] = 2; | ||
| 1771 | |||
| 1772 | /* Equivalent moves ***********/ | ||
| 1773 | equiv_alg[NULLMOVE] = new_alg(""); | ||
| 1774 | |||
| 1775 | equiv_alg[U] = new_alg(" U "); | ||
| 1776 | equiv_alg[U2] = new_alg(" UU "); | ||
| 1777 | equiv_alg[U3] = new_alg(" UUU "); | ||
| 1778 | equiv_alg[D] = new_alg(" xx U xx "); | ||
| 1779 | equiv_alg[D2] = new_alg(" xx UU xx "); | ||
| 1780 | equiv_alg[D3] = new_alg(" xx UUU xx "); | ||
| 1781 | equiv_alg[R] = new_alg(" yx U xxxyyy "); | ||
| 1782 | equiv_alg[R2] = new_alg(" yx UU xxxyyy "); | ||
| 1783 | equiv_alg[R3] = new_alg(" yx UUU xxxyyy "); | ||
| 1784 | equiv_alg[L] = new_alg(" yyyx U xxxy "); | ||
| 1785 | equiv_alg[L2] = new_alg(" yyyx UU xxxy "); | ||
| 1786 | equiv_alg[L3] = new_alg(" yyyx UUU xxxy "); | ||
| 1787 | equiv_alg[F] = new_alg(" x U xxx "); | ||
| 1788 | equiv_alg[F2] = new_alg(" x UU xxx "); | ||
| 1789 | equiv_alg[F3] = new_alg(" x UUU xxx "); | ||
| 1790 | equiv_alg[B] = new_alg(" xxx U x "); | ||
| 1791 | equiv_alg[B2] = new_alg(" xxx UU x "); | ||
| 1792 | equiv_alg[B3] = new_alg(" xxx UUU x "); | ||
| 1793 | |||
| 1794 | equiv_alg[Uw] = new_alg(" xx U xx y "); | ||
| 1795 | equiv_alg[Uw2] = new_alg(" xx UU xx yy "); | ||
| 1796 | equiv_alg[Uw3] = new_alg(" xx UUU xx yyy "); | ||
| 1797 | equiv_alg[Dw] = new_alg(" U yyy "); | ||
| 1798 | equiv_alg[Dw2] = new_alg(" UU yy "); | ||
| 1799 | equiv_alg[Dw3] = new_alg(" UUU y "); | ||
| 1800 | equiv_alg[Rw] = new_alg(" yyyx U xxxy x "); | ||
| 1801 | equiv_alg[Rw2] = new_alg(" yyyx UU xxxy xx "); | ||
| 1802 | equiv_alg[Rw3] = new_alg(" yyyx UUU xxxy xxx "); | ||
| 1803 | equiv_alg[Lw] = new_alg(" yx U xxxyyy xxx "); | ||
| 1804 | equiv_alg[Lw2] = new_alg(" yx UU xxxyyy xx "); | ||
| 1805 | equiv_alg[Lw3] = new_alg(" yx UUU xxxyyy x "); | ||
| 1806 | equiv_alg[Fw] = new_alg(" xxx U x yxxxyyy "); | ||
| 1807 | equiv_alg[Fw2] = new_alg(" xxx UU x yxxyyy "); | ||
| 1808 | equiv_alg[Fw3] = new_alg(" xxx UUU x yxyyy "); | ||
| 1809 | equiv_alg[Bw] = new_alg(" x U xxx yxyyy "); | ||
| 1810 | equiv_alg[Bw2] = new_alg(" x UU xxx yxxyyy "); | ||
| 1811 | equiv_alg[Bw3] = new_alg(" x UUU xxx yxxxyyy "); | ||
| 1812 | |||
| 1813 | equiv_alg[M] = new_alg(" yx U xx UUU yxyyy "); | ||
| 1814 | equiv_alg[M2] = new_alg(" yx UU xx UU xxxy "); | ||
| 1815 | equiv_alg[M3] = new_alg(" yx UUU xx U yxxxy "); | ||
| 1816 | equiv_alg[S] = new_alg(" x UUU xx U yyyx "); | ||
| 1817 | equiv_alg[S2] = new_alg(" x UU xx UU yyx "); | ||
| 1818 | equiv_alg[S3] = new_alg(" x U xx UUU yx "); | ||
| 1819 | equiv_alg[E] = new_alg(" U xx UUU xxyyy "); | ||
| 1820 | equiv_alg[E2] = new_alg(" UU xx UU xxyy "); | ||
| 1821 | equiv_alg[E3] = new_alg(" UUU xx U xxy "); | ||
| 1822 | |||
| 1823 | equiv_alg[x] = new_alg(" x "); | ||
| 1824 | equiv_alg[x2] = new_alg(" xx "); | ||
| 1825 | equiv_alg[x3] = new_alg(" xxx "); | ||
| 1826 | equiv_alg[y] = new_alg(" y "); | ||
| 1827 | equiv_alg[y2] = new_alg(" yy "); | ||
| 1828 | equiv_alg[y3] = new_alg(" yyy "); | ||
| 1829 | equiv_alg[z] = new_alg(" yyy x y "); | ||
| 1830 | equiv_alg[z2] = new_alg(" yy xx "); | ||
| 1831 | equiv_alg[z3] = new_alg(" y x yyy "); | ||
| 1832 | } | ||
| 1833 | |||
| 1834 | static void | ||
| 1835 | init_strings() | ||
| 1836 | { | ||
| 1837 | strcpy(move_string [NULLMOVE], "-" ); | ||
| 1838 | strcpy(move_string [U], "U" ); | ||
| 1839 | strcpy(move_string [U2], "U2" ); | ||
| 1840 | strcpy(move_string [U3], "U\'" ); | ||
| 1841 | strcpy(move_string [D], "D" ); | ||
| 1842 | strcpy(move_string [D2], "D2" ); | ||
| 1843 | strcpy(move_string [D3], "D\'" ); | ||
| 1844 | strcpy(move_string [R], "R" ); | ||
| 1845 | strcpy(move_string [R2], "R2" ); | ||
| 1846 | strcpy(move_string [R3], "R\'" ); | ||
| 1847 | strcpy(move_string [L], "L" ); | ||
| 1848 | strcpy(move_string [L2], "L2" ); | ||
| 1849 | strcpy(move_string [L3], "L\'" ); | ||
| 1850 | strcpy(move_string [F], "F" ); | ||
| 1851 | strcpy(move_string [F2], "F2" ); | ||
| 1852 | strcpy(move_string [F3], "F\'" ); | ||
| 1853 | strcpy(move_string [B], "B" ); | ||
| 1854 | strcpy(move_string [B2], "B2" ); | ||
| 1855 | strcpy(move_string [B3], "B\'" ); | ||
| 1856 | strcpy(move_string [Uw], "Uw" ); | ||
| 1857 | strcpy(move_string [Uw2], "Uw2" ); | ||
| 1858 | strcpy(move_string [Uw3], "Uw\'" ); | ||
| 1859 | strcpy(move_string [Dw], "Dw" ); | ||
| 1860 | strcpy(move_string [Dw2], "Dw2" ); | ||
| 1861 | strcpy(move_string [Dw3], "Dw\'" ); | ||
| 1862 | strcpy(move_string [Rw], "Rw" ); | ||
| 1863 | strcpy(move_string [Rw2], "Rw2" ); | ||
| 1864 | strcpy(move_string [Rw3], "Rw\'" ); | ||
| 1865 | strcpy(move_string [Lw], "Lw" ); | ||
| 1866 | strcpy(move_string [Lw2], "Lw2" ); | ||
| 1867 | strcpy(move_string [Lw3], "Lw\'" ); | ||
| 1868 | strcpy(move_string [Fw], "Fw" ); | ||
| 1869 | strcpy(move_string [Fw2], "Fw2" ); | ||
| 1870 | strcpy(move_string [Fw3], "Fw\'" ); | ||
| 1871 | strcpy(move_string [Bw], "Bw" ); | ||
| 1872 | strcpy(move_string [Bw2], "Bw2" ); | ||
| 1873 | strcpy(move_string [Bw3], "Bw\'" ); | ||
| 1874 | strcpy(move_string [M], "M" ); | ||
| 1875 | strcpy(move_string [M2], "M2" ); | ||
| 1876 | strcpy(move_string [M3], "M\'" ); | ||
| 1877 | strcpy(move_string [S], "S" ); | ||
| 1878 | strcpy(move_string [S2], "S2" ); | ||
| 1879 | strcpy(move_string [S3], "S\'" ); | ||
| 1880 | strcpy(move_string [E], "E" ); | ||
| 1881 | strcpy(move_string [E2], "E2" ); | ||
| 1882 | strcpy(move_string [E3], "E\'" ); | ||
| 1883 | strcpy(move_string [x], "x" ); | ||
| 1884 | strcpy(move_string [x2], "x2" ); | ||
| 1885 | strcpy(move_string [x3], "x\'" ); | ||
| 1886 | strcpy(move_string [y], "y" ); | ||
| 1887 | strcpy(move_string [y2], "y2" ); | ||
| 1888 | strcpy(move_string [y3], "y\'" ); | ||
| 1889 | strcpy(move_string [z], "z" ); | ||
| 1890 | strcpy(move_string [z2], "z2" ); | ||
| 1891 | strcpy(move_string [z3], "z\'" ); | ||
| 1892 | |||
| 1893 | strcpy(edge_string [UF], "UF" ); | ||
| 1894 | strcpy(edge_string [UL], "UL" ); | ||
| 1895 | strcpy(edge_string [UB], "UB" ); | ||
| 1896 | strcpy(edge_string [UR], "UR" ); | ||
| 1897 | strcpy(edge_string [DF], "DF" ); | ||
| 1898 | strcpy(edge_string [DL], "DL" ); | ||
| 1899 | strcpy(edge_string [DB], "DB" ); | ||
| 1900 | strcpy(edge_string [DR], "DR" ); | ||
| 1901 | strcpy(edge_string [FR], "FR" ); | ||
| 1902 | strcpy(edge_string [FL], "FL" ); | ||
| 1903 | strcpy(edge_string [BL], "BL" ); | ||
| 1904 | strcpy(edge_string [BR], "BR" ); | ||
| 1905 | |||
| 1906 | strcpy(corner_string [UFR], "UFR" ); | ||
| 1907 | strcpy(corner_string [UFL], "UFL" ); | ||
| 1908 | strcpy(corner_string [UBL], "UBL" ); | ||
| 1909 | strcpy(corner_string [UBR], "UBR" ); | ||
| 1910 | strcpy(corner_string [DFR], "DFR" ); | ||
| 1911 | strcpy(corner_string [DFL], "DFL" ); | ||
| 1912 | strcpy(corner_string [DBL], "DBL" ); | ||
| 1913 | strcpy(corner_string [DBR], "DBR" ); | ||
| 1914 | |||
| 1915 | strcpy(center_string [U_center], "U" ); | ||
| 1916 | strcpy(center_string [D_center], "D" ); | ||
| 1917 | strcpy(center_string [R_center], "R" ); | ||
| 1918 | strcpy(center_string [L_center], "L" ); | ||
| 1919 | strcpy(center_string [F_center], "F" ); | ||
| 1920 | strcpy(center_string [B_center], "B" ); | ||
| 1921 | } | ||
| 1922 | |||
| 1923 | static void | ||
| 1924 | init_trans() { | ||
| 1925 | Cube aux, cube, c[3]; | ||
| 1926 | CubeArray epcp; | ||
| 1927 | int eparr[12], eoarr[12]; | ||
| 1928 | int cparr[8], coarr[8]; | ||
| 1929 | int i; | ||
| 1930 | bool b1, b2, b3; | ||
| 1931 | uint16_t ui; | ||
| 1932 | Move mi, move; | ||
| 1933 | Trans m; | ||
| 1934 | |||
| 1935 | /* Compute sources */ | ||
| 1936 | for (i = 0; i < NTRANS; i++) { | ||
| 1937 | if (i == mirror) | ||
| 1938 | cube = (Cube){0}; | ||
| 1939 | else | ||
| 1940 | cube = apply_alg(trans_algs[i], (Cube){0}); | ||
| 1941 | |||
| 1942 | epose_source[i] = edge_slice(what_edge_at(cube, FR)); | ||
| 1943 | eposs_source[i] = edge_slice(what_edge_at(cube, UR)); | ||
| 1944 | eposm_source[i] = edge_slice(what_edge_at(cube, UF)); | ||
| 1945 | eofb_source[i] = what_center_at(cube, F_center)/2; | ||
| 1946 | eorl_source[i] = what_center_at(cube, R_center)/2; | ||
| 1947 | eoud_source[i] = what_center_at(cube, U_center)/2; | ||
| 1948 | coud_source[i] = what_center_at(cube, U_center)/2; | ||
| 1949 | cofb_source[i] = what_center_at(cube, F_center)/2; | ||
| 1950 | corl_source[i] = what_center_at(cube, R_center)/2; | ||
| 1951 | } | ||
| 1952 | |||
| 1953 | if (read_ttables_file()) | ||
| 1954 | return; | ||
| 1955 | |||
| 1956 | fprintf(stderr, "Cannot load %s, generating it\n", "ttables"); | ||
| 1957 | |||
| 1958 | /* Initialize tables */ | ||
| 1959 | for (m = 0; m < NTRANS; m++) { | ||
| 1960 | if (m == mirror) { | ||
| 1961 | memcpy(eparr, ep_mirror, 12 * sizeof(int)); | ||
| 1962 | memcpy(cparr, cp_mirror, 8 * sizeof(int)); | ||
| 1963 | } else { | ||
| 1964 | epcp = (CubeArray){ .ep = eparr, .cp = cparr }; | ||
| 1965 | cube = apply_alg(trans_algs[m], (Cube){0}); | ||
| 1966 | cube_to_arrays(cube, &epcp, pf_epcp); | ||
| 1967 | } | ||
| 1968 | |||
| 1969 | for (ui = 0; ui < FACTORIAL12/FACTORIAL8; ui++) { | ||
| 1970 | c[0] = admissible_ep((Cube){ .epose = ui }, pf_e); | ||
| 1971 | c[1] = admissible_ep((Cube){ .eposs = ui }, pf_s); | ||
| 1972 | c[2] = admissible_ep((Cube){ .eposm = ui }, pf_m); | ||
| 1973 | |||
| 1974 | cube = rotate_via_compose(m,c[epose_source[m]],pf_ep); | ||
| 1975 | epose_ttable[m][ui] = cube.epose; | ||
| 1976 | |||
| 1977 | cube = rotate_via_compose(m,c[eposs_source[m]],pf_ep); | ||
| 1978 | eposs_ttable[m][ui] = cube.eposs; | ||
| 1979 | |||
| 1980 | cube = rotate_via_compose(m,c[eposm_source[m]],pf_ep); | ||
| 1981 | eposm_ttable[m][ui] = cube.eposm; | ||
| 1982 | } | ||
| 1983 | for (ui = 0; ui < POW2TO11; ui++ ) { | ||
| 1984 | int_to_sum_zero_array(ui, 2, 12, eoarr); | ||
| 1985 | apply_permutation(eparr, eoarr, 12); | ||
| 1986 | eo_ttable[m][ui] = digit_array_to_int(eoarr, 11, 2); | ||
| 1987 | } | ||
| 1988 | for (ui = 0; ui < POW3TO7; ui++) { | ||
| 1989 | int_to_sum_zero_array(ui, 3, 8, coarr); | ||
| 1990 | apply_permutation(cparr, coarr, 8); | ||
| 1991 | co_ttable[m][ui] = digit_array_to_int(coarr, 7, 3); | ||
| 1992 | if (m == mirror) | ||
| 1993 | co_ttable[m][ui] = | ||
| 1994 | invert_digits(co_ttable[m][ui], 3, 7); | ||
| 1995 | } | ||
| 1996 | for (ui = 0; ui < FACTORIAL8; ui++) { | ||
| 1997 | cube = (Cube){ .cp = ui }; | ||
| 1998 | cube = rotate_via_compose(m, cube, pf_cp); | ||
| 1999 | cp_ttable[m][ui] = cube.cp; | ||
| 2000 | } | ||
| 2001 | for (ui = 0; ui < FACTORIAL6; ui++) { | ||
| 2002 | cube = (Cube){ .cpos = ui }; | ||
| 2003 | cube = rotate_via_compose(m, cube, pf_cpos); | ||
| 2004 | cpos_ttable[m][ui] = cube.cpos; | ||
| 2005 | } | ||
| 2006 | for (mi = 0; mi < NMOVES; mi++) { | ||
| 2007 | if (m == mirror) { | ||
| 2008 | b1 = (mi >= U && mi <= Bw3); | ||
| 2009 | b2 = (mi >= S && mi <= E3); | ||
| 2010 | b3 = (mi >= x && mi <= z3); | ||
| 2011 | if (b1 || b2 || b3) | ||
| 2012 | moves_ttable[m][mi] = | ||
| 2013 | inverse_move_aux[mi]; | ||
| 2014 | else | ||
| 2015 | moves_ttable[m][mi] = mi; | ||
| 2016 | |||
| 2017 | if ((mi-1)/3==(R-1)/3 || (mi-1)/3==(Rw-1)/3) | ||
| 2018 | moves_ttable[m][mi] += 3; | ||
| 2019 | if ((mi-1)/3==(L-1)/3 || (mi-1)/3==(L2-1)/3) | ||
| 2020 | moves_ttable[m][mi] -= 3; | ||
| 2021 | } else { | ||
| 2022 | aux = apply_trans(m, apply_move(mi,(Cube){0})); | ||
| 2023 | for (move = 0; move < NMOVES; move++) { | ||
| 2024 | cube = apply_move( | ||
| 2025 | inverse_move_aux[move], aux); | ||
| 2026 | if (is_solved(cube, false)) | ||
| 2027 | moves_ttable[m][mi] = move; | ||
| 2028 | } | ||
| 2029 | } | ||
| 2030 | } | ||
| 2031 | } | ||
| 2032 | |||
| 2033 | if (!write_ttables_file()) | ||
| 2034 | fprintf(stderr, "Error writing ttables\n"); | ||
| 2035 | } | ||
| 2036 | |||
| 2037 | static void | ||
| 2038 | init_trans_aux() | ||
| 2039 | { | ||
| 2040 | ep_mirror[UF] = UF; | ||
| 2041 | ep_mirror[UL] = UR; | ||
| 2042 | ep_mirror[UB] = UB; | ||
| 2043 | ep_mirror[UR] = UL; | ||
| 2044 | ep_mirror[DF] = DF; | ||
| 2045 | ep_mirror[DL] = DR; | ||
| 2046 | ep_mirror[DB] = DB; | ||
| 2047 | ep_mirror[DR] = DL; | ||
| 2048 | ep_mirror[FR] = FL; | ||
| 2049 | ep_mirror[FL] = FR; | ||
| 2050 | ep_mirror[BR] = BL; | ||
| 2051 | ep_mirror[BL] = BR; | ||
| 2052 | |||
| 2053 | cp_mirror[UFR] = UFL; | ||
| 2054 | cp_mirror[UFL] = UFR; | ||
| 2055 | cp_mirror[UBL] = UBR; | ||
| 2056 | cp_mirror[UBR] = UBL; | ||
| 2057 | cp_mirror[DFR] = DFL; | ||
| 2058 | cp_mirror[DFL] = DFR; | ||
| 2059 | cp_mirror[DBL] = DBR; | ||
| 2060 | cp_mirror[DBR] = DBL; | ||
| 2061 | |||
| 2062 | cpos_mirror[U_center] = U_center; | ||
| 2063 | cpos_mirror[D_center] = D_center; | ||
| 2064 | cpos_mirror[R_center] = L_center; | ||
| 2065 | cpos_mirror[L_center] = R_center; | ||
| 2066 | cpos_mirror[F_center] = F_center; | ||
| 2067 | cpos_mirror[B_center] = B_center; | ||
| 2068 | |||
| 2069 | /* Is there a more elegant way? */ | ||
| 2070 | trans_algs[uf] = new_alg(""); | ||
| 2071 | trans_algs[ur] = new_alg("y"); | ||
| 2072 | trans_algs[ub] = new_alg("y2"); | ||
| 2073 | trans_algs[ul] = new_alg("y3"); | ||
| 2074 | |||
| 2075 | trans_algs[df] = new_alg("z2"); | ||
| 2076 | trans_algs[dr] = new_alg("y z2"); | ||
| 2077 | trans_algs[db] = new_alg("x2"); | ||
| 2078 | trans_algs[dl] = new_alg("y3 z2"); | ||
| 2079 | |||
| 2080 | trans_algs[rf] = new_alg("z3"); | ||
| 2081 | trans_algs[rd] = new_alg("z3 y"); | ||
| 2082 | trans_algs[rb] = new_alg("z3 y2"); | ||
| 2083 | trans_algs[ru] = new_alg("z3 y3"); | ||
| 2084 | |||
| 2085 | trans_algs[lf] = new_alg("z"); | ||
| 2086 | trans_algs[ld] = new_alg("z y3"); | ||
| 2087 | trans_algs[lb] = new_alg("z y2"); | ||
| 2088 | trans_algs[lu] = new_alg("z y"); | ||
| 2089 | |||
| 2090 | trans_algs[fu] = new_alg("x y2"); | ||
| 2091 | trans_algs[fr] = new_alg("x y"); | ||
| 2092 | trans_algs[fd] = new_alg("x"); | ||
| 2093 | trans_algs[fl] = new_alg("x y3"); | ||
| 2094 | |||
| 2095 | trans_algs[bu] = new_alg("x3"); | ||
| 2096 | trans_algs[br] = new_alg("x3 y"); | ||
| 2097 | trans_algs[bd] = new_alg("x3 y2"); | ||
| 2098 | trans_algs[bl] = new_alg("x3 y3"); | ||
| 2099 | } | ||
| 2100 | |||
| 2101 | |||
| 2102 | /* Public functions implementation *******************************************/ | ||
| 2103 | |||
| 2104 | Cube | ||
| 2105 | apply_alg(Alg *alg, Cube cube) | ||
| 2106 | { | ||
| 2107 | return apply_alg_generic(alg, cube, pf_all, true); | ||
| 2108 | } | ||
| 2109 | |||
| 2110 | Cube | ||
| 2111 | apply_move(Move m, Cube cube) | ||
| 2112 | { | ||
| 2113 | return (Cube) { | ||
| 2114 | .epose = epose_mtable[m][cube.epose], | ||
| 2115 | .eposs = eposs_mtable[m][cube.eposs], | ||
| 2116 | .eposm = eposm_mtable[m][cube.eposm], | ||
| 2117 | .eofb = eofb_mtable[m][cube.eofb], | ||
| 2118 | .eorl = eorl_mtable[m][cube.eorl], | ||
| 2119 | .eoud = eoud_mtable[m][cube.eoud], | ||
| 2120 | .coud = coud_mtable[m][cube.coud], | ||
| 2121 | .cofb = cofb_mtable[m][cube.cofb], | ||
| 2122 | .corl = corl_mtable[m][cube.corl], | ||
| 2123 | .cp = cp_mtable[m][cube.cp], | ||
| 2124 | .cpos = cpos_mtable[m][cube.cpos] | ||
| 2125 | }; | ||
| 2126 | } | ||
| 2127 | |||
| 2128 | Cube | ||
| 2129 | apply_trans(Trans t, Cube cube) | ||
| 2130 | { | ||
| 2131 | uint16_t aux_epos[3] = { cube.epose, cube.eposs, cube.eposm }; | ||
| 2132 | uint16_t aux_eo[3] = { cube.eoud, cube.eorl, cube.eofb }; | ||
| 2133 | uint16_t aux_co[3] = { cube.coud, cube.corl, cube.cofb }; | ||
| 2134 | |||
| 2135 | return (Cube) { | ||
| 2136 | .epose = epose_ttable[t][aux_epos[epose_source[t]]], | ||
| 2137 | .eposs = eposs_ttable[t][aux_epos[eposs_source[t]]], | ||
| 2138 | .eposm = eposm_ttable[t][aux_epos[eposm_source[t]]], | ||
| 2139 | .eofb = eo_ttable[t][aux_eo[eofb_source[t]]], | ||
| 2140 | .eorl = eo_ttable[t][aux_eo[eorl_source[t]]], | ||
| 2141 | .eoud = eo_ttable[t][aux_eo[eoud_source[t]]], | ||
| 2142 | .coud = co_ttable[t][aux_co[coud_source[t]]], | ||
| 2143 | .corl = co_ttable[t][aux_co[corl_source[t]]], | ||
| 2144 | .cofb = co_ttable[t][aux_co[cofb_source[t]]], | ||
| 2145 | .cp = cp_ttable[t][cube.cp], | ||
| 2146 | .cpos = cpos_ttable[t][cube.cpos] | ||
| 2147 | }; | ||
| 2148 | } | ||
| 2149 | |||
| 2150 | Move | ||
| 2151 | base_move(Move m) | ||
| 2152 | { | ||
| 2153 | if (m == NULLMOVE) | ||
| 2154 | return NULLMOVE; | ||
| 2155 | else | ||
| 2156 | return m - (m-1)%3; | ||
| 2157 | } | ||
| 2158 | |||
| 2159 | Cube | ||
| 2160 | compose(Cube c2, Cube c1) | ||
| 2161 | { | ||
| 2162 | return compose_filtered(c2, c1, pf_all); | ||
| 2163 | } | ||
| 2164 | |||
| 2165 | uint64_t | ||
| 2166 | epos_dependent_cube(Cube c) | ||
| 2167 | { | ||
| 2168 | return epos_dependent_aux[c.eposs/FACTORIAL4][c.epose/FACTORIAL4]; | ||
| 2169 | } | ||
| 2170 | |||
| 2171 | bool | ||
| 2172 | equal(Cube c1, Cube c2) | ||
| 2173 | { | ||
| 2174 | return c1.eofb == c2.eofb && | ||
| 2175 | c1.epose == c2.epose && | ||
| 2176 | c1.eposs == c2.eposs && | ||
| 2177 | c1.eposm == c2.eposm && | ||
| 2178 | c1.coud == c2.coud && | ||
| 2179 | c1.cp == c2.cp && | ||
| 2180 | c1.cpos == c2.cpos; | ||
| 2181 | } | ||
| 2182 | |||
| 2183 | void | ||
| 2184 | genalgset(AlgSet *as) | ||
| 2185 | { | ||
| 2186 | uint64_t i; | ||
| 2187 | |||
| 2188 | if (as->generated) | ||
| 2189 | return; | ||
| 2190 | |||
| 2191 | /* TODO: check if memory is enough, otherwise maybe crash gracefully? */ | ||
| 2192 | as->table = malloc(as->size * sizeof(AlgList *)); | ||
| 2193 | |||
| 2194 | if (read_algset_file(as)) { | ||
| 2195 | as->generated = true; | ||
| 2196 | return; | ||
| 2197 | } | ||
| 2198 | |||
| 2199 | fprintf(stderr, "Cannot load %s, generating it\n", as->filename); | ||
| 2200 | |||
| 2201 | for (i = 0; i < as->size; i++) { | ||
| 2202 | as->table[i] = solve(as->antindex(i), as->step, &as->opts); | ||
| 2203 | fprintf(stderr, "Generated %lu / %lu cases\n", i, as->size); | ||
| 2204 | } | ||
| 2205 | |||
| 2206 | if (!write_algset_file(as)) | ||
| 2207 | fprintf(stderr, "Error writing algset file\n"); | ||
| 2208 | |||
| 2209 | as->generated = true; | ||
| 2210 | } | ||
| 2211 | |||
| 2212 | void | ||
| 2213 | genptable(PruneData *pd) | ||
| 2214 | { | ||
| 2215 | uint64_t j; | ||
| 2216 | DfsData dd = { | ||
| 2217 | .m = 0, | ||
| 2218 | .last1 = NULLMOVE, | ||
| 2219 | .last2 = NULLMOVE | ||
| 2220 | }; | ||
| 2221 | |||
| 2222 | if (pd->generated) | ||
| 2223 | return; | ||
| 2224 | |||
| 2225 | /* TODO: check if memory is enough, otherwise maybe crash gracefully? */ | ||
| 2226 | pd->ptable = malloc(ptablesize(pd) * sizeof(uint8_t)); | ||
| 2227 | |||
| 2228 | if (read_ptable_file(pd)) { | ||
| 2229 | pd->generated = true; | ||
| 2230 | return; | ||
| 2231 | } | ||
| 2232 | |||
| 2233 | fprintf(stderr, "Cannot load %s, generating it\n", pd->filename); | ||
| 2234 | |||
| 2235 | /* We use 4 bits per value, so any distance >= 15 is set to 15 */ | ||
| 2236 | for (j = 0; j < pd->size; j++) | ||
| 2237 | ptable_update(pd, j, 15); | ||
| 2238 | |||
| 2239 | moveset_to_list(pd->moveset, NULL, dd.sorted_moves); | ||
| 2240 | movelist_to_position(dd.sorted_moves, dd.move_position); | ||
| 2241 | |||
| 2242 | pd->reached = malloc(ptablesize(pd) * sizeof(uint8_t)); | ||
| 2243 | for (dd.d = 0, pd->n = 0; dd.d < 15 && pd->n < pd->size; dd.d++) { | ||
| 2244 | memset(pd->reached, 0, ptablesize(pd)*sizeof(uint8_t)); | ||
| 2245 | genptable_dfs((Cube){0}, pd, &dd); | ||
| 2246 | fprintf(stderr, "Depth %d completed, generated %lu/%lu\n", | ||
| 2247 | dd.d, pd->n, pd->size); | ||
| 2248 | } | ||
| 2249 | |||
| 2250 | if (!write_ptable_file(pd)) | ||
| 2251 | fprintf(stderr, "Error writing ptable file\n"); | ||
| 2252 | |||
| 2253 | pd->generated = true; | ||
| 2254 | free(pd->reached); | ||
| 2255 | } | ||
| 2256 | |||
| 2257 | Cube | ||
| 2258 | inverse_cube(Cube cube) | ||
| 2259 | { | ||
| 2260 | CubeArray *arr = new_cubearray(cube, pf_all); | ||
| 2261 | CubeArray *inv = new_cubearray((Cube){0}, pf_all); | ||
| 2262 | Cube ret; | ||
| 2263 | int i; | ||
| 2264 | |||
| 2265 | for (i = 0; i < 12; i++) { | ||
| 2266 | inv->ep[arr->ep[i]] = i; | ||
| 2267 | inv->eofb[arr->ep[i]] = arr->eofb[i]; | ||
| 2268 | inv->eorl[arr->ep[i]] = arr->eorl[i]; | ||
| 2269 | inv->eoud[arr->ep[i]] = arr->eoud[i]; | ||
| 2270 | } | ||
| 2271 | |||
| 2272 | for (i = 0; i < 8; i++) { | ||
| 2273 | inv->cp[arr->cp[i]] = i; | ||
| 2274 | inv->coud[arr->cp[i]] = (3 - arr->coud[i]) % 3; | ||
| 2275 | inv->corl[arr->cp[i]] = (3 - arr->corl[i]) % 3; | ||
| 2276 | inv->cofb[arr->cp[i]] = (3 - arr->cofb[i]) % 3; | ||
| 2277 | } | ||
| 2278 | |||
| 2279 | for (int i = 0; i < 6; i++) | ||
| 2280 | inv->cpos[arr->cpos[i]] = i; | ||
| 2281 | |||
| 2282 | ret = arrays_to_cube(inv, pf_all); | ||
| 2283 | free_cubearray(arr, pf_all); | ||
| 2284 | free_cubearray(inv, pf_all); | ||
| 2285 | |||
| 2286 | return ret; | ||
| 2287 | } | ||
| 2288 | |||
| 2289 | Move | ||
| 2290 | inverse_move(Move m) | ||
| 2291 | { | ||
| 2292 | return inverse_move_aux[m]; | ||
| 2293 | } | ||
| 2294 | |||
| 2295 | Trans | ||
| 2296 | inverse_trans(Trans t) | ||
| 2297 | { | ||
| 2298 | return inverse_trans_aux[t]; | ||
| 2299 | } | ||
| 2300 | |||
| 2301 | bool | ||
| 2302 | is_admissible(Cube cube) | ||
| 2303 | { | ||
| 2304 | /* TODO: this should check consistency of different orientations */ | ||
| 2305 | /* TODO: check that centers are opposite and admissible */ | ||
| 2306 | |||
| 2307 | CubeArray *a = new_cubearray(cube, pf_all); | ||
| 2308 | int parity; | ||
| 2309 | bool perm; | ||
| 2310 | |||
| 2311 | perm = is_perm(a->ep, 12) && | ||
| 2312 | is_perm(a->cp, 8) && | ||
| 2313 | is_perm(a->cpos, 6); | ||
| 2314 | parity = perm_sign(a->ep, 12) + | ||
| 2315 | perm_sign(a->cp, 8) + | ||
| 2316 | perm_sign(a->cpos, 6); | ||
| 2317 | |||
| 2318 | return perm && parity % 2 == 0; | ||
| 2319 | } | ||
| 2320 | |||
| 2321 | bool | ||
| 2322 | is_solved(Cube cube, bool reorient) | ||
| 2323 | { | ||
| 2324 | Trans i; | ||
| 2325 | |||
| 2326 | if (reorient) | ||
| 2327 | for (i = 0; i < NROTATIONS; i++) | ||
| 2328 | if (is_solved(apply_alg(trans_algs[i],cube), false)) | ||
| 2329 | return true; | ||
| 2330 | |||
| 2331 | return equal(cube, (Cube){0}); | ||
| 2332 | } | ||
| 2333 | |||
| 2334 | bool | ||
| 2335 | is_solved_block(Cube cube, Block block) | ||
| 2336 | { | ||
| 2337 | int i; | ||
| 2338 | |||
| 2339 | for (i = 0; i < 12; i++) | ||
| 2340 | if (block.edge[i] && !is_solved_edge(cube, i)) | ||
| 2341 | return false; | ||
| 2342 | for (i = 0; i < 8; i++) | ||
| 2343 | if (block.corner[i] && !is_solved_corner(cube, i)) | ||
| 2344 | return false; | ||
| 2345 | for (i = 0; i < 6; i++) | ||
| 2346 | if (block.center[i] && !is_solved_center(cube, i)) | ||
| 2347 | return false; | ||
| 2348 | |||
| 2349 | return true; | ||
| 2350 | } | ||
| 2351 | |||
| 2352 | bool | ||
| 2353 | is_solved_center(Cube cube, Center c) | ||
| 2354 | { | ||
| 2355 | return what_center_at(cube, c) == c; | ||
| 2356 | } | ||
| 2357 | |||
| 2358 | bool | ||
| 2359 | is_solved_corner(Cube cube, Corner c) | ||
| 2360 | { | ||
| 2361 | return what_corner_at(cube, c) == c && | ||
| 2362 | what_orientation_corner(cube.coud, c); | ||
| 2363 | } | ||
| 2364 | |||
| 2365 | bool | ||
| 2366 | is_solved_edge(Cube cube, Edge e) | ||
| 2367 | { | ||
| 2368 | return what_edge_at(cube, e) == e && | ||
| 2369 | what_orientation_edge(cube.eofb, e); | ||
| 2370 | } | ||
| 2371 | |||
| 2372 | int | ||
| 2373 | piece_orientation(Cube cube, int piece, char *orientation) | ||
| 2374 | { | ||
| 2375 | int arr[12], n, b; | ||
| 2376 | uint16_t x; | ||
| 2377 | |||
| 2378 | if (!strcmp(orientation, "eofb")) { | ||
| 2379 | x = cube.eofb; | ||
| 2380 | n = 12; | ||
| 2381 | b = 2; | ||
| 2382 | } else if (!strcmp(orientation, "eorl")) { | ||
| 2383 | x = cube.eorl; | ||
| 2384 | n = 12; | ||
| 2385 | b = 2; | ||
| 2386 | } else if (!strcmp(orientation, "eoud")) { | ||
| 2387 | x = cube.eoud; | ||
| 2388 | n = 12; | ||
| 2389 | b = 2; | ||
| 2390 | } else if (!strcmp(orientation, "coud")) { | ||
| 2391 | x = cube.coud; | ||
| 2392 | n = 8; | ||
| 2393 | b = 3; | ||
| 2394 | } else if (!strcmp(orientation, "corl")) { | ||
| 2395 | x = cube.corl; | ||
| 2396 | n = 8; | ||
| 2397 | b = 3; | ||
| 2398 | } else if (!strcmp(orientation, "cofb")) { | ||
| 2399 | x = cube.cofb; | ||
| 2400 | n = 8; | ||
| 2401 | b = 3; | ||
| 2402 | } else { | ||
| 2403 | return -1; | ||
| 2404 | } | ||
| 2405 | |||
| 2406 | int_to_sum_zero_array(x, b, n, arr); | ||
| 2407 | if (piece < n) | ||
| 2408 | return arr[piece]; | ||
| 2409 | |||
| 2410 | return -1; | ||
| 2411 | } | ||
| 2412 | |||
| 2413 | void | ||
| 2414 | print_cube(Cube cube) | ||
| 2415 | { | ||
| 2416 | /* | ||
| 2417 | CubeArray *arr = new_cubearray(cube, pf_all); | ||
| 2418 | |||
| 2419 | for (int i = 0; i < 12; i++) | ||
| 2420 | printf(" %s ", edge_string[arr->ep[i]]); | ||
| 2421 | printf("\n"); | ||
| 2422 | |||
| 2423 | for (int i = 0; i < 12; i++) | ||
| 2424 | printf(" %c ", arr->eofb[i] + '0'); | ||
| 2425 | printf("\n"); | ||
| 2426 | |||
| 2427 | for (int i = 0; i < 8; i++) | ||
| 2428 | printf("%s ", corner_string[arr->cp[i]]); | ||
| 2429 | printf("\n"); | ||
| 2430 | |||
| 2431 | for (int i = 0; i < 8; i++) | ||
| 2432 | printf(" %c ", arr->coud[i] + '0'); | ||
| 2433 | printf("\n"); | ||
| 2434 | |||
| 2435 | for (int i = 0; i < 6; i++) | ||
| 2436 | printf(" %s ", center_string[arr->cpos[i]]); | ||
| 2437 | printf("\n"); | ||
| 2438 | |||
| 2439 | free_cubearray(arr, pf_all); | ||
| 2440 | */ | ||
| 2441 | |||
| 2442 | for (int i = 0; i < 12; i++) | ||
| 2443 | printf(" %s ", edge_string[what_edge_at(cube, i)]); | ||
| 2444 | printf("\n"); | ||
| 2445 | |||
| 2446 | for (int i = 0; i < 12; i++) | ||
| 2447 | printf(" %d ", what_orientation_edge(cube.eofb, i)); | ||
| 2448 | printf("\n"); | ||
| 2449 | |||
| 2450 | for (int i = 0; i < 8; i++) | ||
| 2451 | printf("%s ", corner_string[what_corner_at(cube, i)]); | ||
| 2452 | printf("\n"); | ||
| 2453 | |||
| 2454 | for (int i = 0; i < 8; i++) | ||
| 2455 | printf(" %d ", what_orientation_corner(cube.coud, i)); | ||
| 2456 | printf("\n"); | ||
| 2457 | |||
| 2458 | for (int i = 0; i < 6; i++) | ||
| 2459 | printf(" %s ", center_string[what_center_at(cube, i)]); | ||
| 2460 | printf("\n"); | ||
| 2461 | |||
| 2462 | } | ||
| 2463 | |||
| 2464 | Cube | ||
| 2465 | random_cube() | ||
| 2466 | { | ||
| 2467 | CubeArray *arr = new_cubearray((Cube){0}, pf_4val); | ||
| 2468 | Cube ret; | ||
| 2469 | int ep, cp, eo, co; | ||
| 2470 | |||
| 2471 | ep = rand() % FACTORIAL12; | ||
| 2472 | cp = rand() % FACTORIAL8; | ||
| 2473 | eo = rand() % POW2TO11; | ||
| 2474 | co = rand() % POW3TO7; | ||
| 2475 | |||
| 2476 | index_to_perm(ep, 12, arr->ep); | ||
| 2477 | index_to_perm(cp, 8, arr->cp); | ||
| 2478 | int_to_sum_zero_array(eo, 2, 12, arr->eofb); | ||
| 2479 | int_to_sum_zero_array(co, 3, 8, arr->coud); | ||
| 2480 | |||
| 2481 | if (perm_sign(arr->ep, 12) != perm_sign(arr->cp, 8)) | ||
| 2482 | swap(&(arr->ep[0]), &(arr->ep[1])); | ||
| 2483 | |||
| 2484 | ret = arrays_to_cube(arr, pf_4val); | ||
| 2485 | free_cubearray(arr, pf_4val); | ||
| 2486 | |||
| 2487 | return ret; | ||
| 2488 | } | ||
| 2489 | |||
| 2490 | AlgList * | ||
| 2491 | solve(Cube cube, Step step, SolveOptions *opts) | ||
| 2492 | { | ||
| 2493 | AlgListNode *node; | ||
| 2494 | AlgList *sols = new_alglist(); | ||
| 2495 | Cube c = apply_trans(opts->pre_trans, cube); | ||
| 2496 | DfsData dd = { | ||
| 2497 | .m = 0, | ||
| 2498 | .niss = false, | ||
| 2499 | .lb = -1, | ||
| 2500 | .last1 = NULLMOVE, | ||
| 2501 | .last2 = NULLMOVE, | ||
| 2502 | .sols = sols, | ||
| 2503 | .current_alg = new_alg("") | ||
| 2504 | }; | ||
| 2505 | |||
| 2506 | if (step.ready != NULL && step.ready(c, 1) != 0) { | ||
| 2507 | fprintf(stderr, "Cube not ready for solving step\n"); | ||
| 2508 | return sols; | ||
| 2509 | } | ||
| 2510 | |||
| 2511 | moveset_to_list(step.moveset, step.check, dd.sorted_moves); | ||
| 2512 | movelist_to_position(dd.sorted_moves, dd.move_position); | ||
| 2513 | |||
| 2514 | for (dd.d = opts->min_moves; | ||
| 2515 | dd.d <= opts->max_moves && !(sols->len && opts->optimal_only); | ||
| 2516 | dd.d++) { | ||
| 2517 | if (opts->feedback) | ||
| 2518 | fprintf(stderr, | ||
| 2519 | "Found %d solutions, searching depth %d...\n", | ||
| 2520 | sols->len, dd.d); | ||
| 2521 | dfs(c, step, opts, &dd); | ||
| 2522 | } | ||
| 2523 | |||
| 2524 | for (node = sols->first; node != NULL; node = node->next) | ||
| 2525 | transform_alg(inverse_trans_aux[opts->pre_trans], node->alg); | ||
| 2526 | |||
| 2527 | free_alg(dd.current_alg); | ||
| 2528 | return sols; | ||
| 2529 | } | ||
| 2530 | |||
| 2531 | Alg * | ||
| 2532 | inverse_alg(Alg *alg) | ||
| 2533 | { | ||
| 2534 | Alg *ret = new_alg(""); | ||
| 2535 | int i; | ||
| 2536 | |||
| 2537 | for (i = alg->len-1; i >= 0; i--) | ||
| 2538 | append_move(ret, alg->move[i], alg->inv[i]); | ||
| 2539 | |||
| 2540 | return ret; | ||
| 2541 | } | ||
| 2542 | |||
| 2543 | Alg * | ||
| 2544 | new_alg(char *str) | ||
| 2545 | { | ||
| 2546 | Alg *alg = malloc(sizeof(Alg)); | ||
| 2547 | int i; | ||
| 2548 | bool niss = false; | ||
| 2549 | Move j, m; | ||
| 2550 | |||
| 2551 | alg->move = malloc(30 * sizeof(Move)); | ||
| 2552 | alg->inv = malloc(30 * sizeof(bool)); | ||
| 2553 | alg->allocated = 30; | ||
| 2554 | alg->len = 0; | ||
| 2555 | |||
| 2556 | for (i = 0; str[i]; i++) { | ||
| 2557 | if (str[i] == ' ' || str[i] == '\t' || str[i] == '\n') | ||
| 2558 | continue; | ||
| 2559 | |||
| 2560 | if (str[i] == '(' && niss) { | ||
| 2561 | fprintf(stderr, "Error reading moves: nested ( )\n"); | ||
| 2562 | return alg; | ||
| 2563 | } | ||
| 2564 | |||
| 2565 | if (str[i] == ')' && !niss) { | ||
| 2566 | fprintf(stderr, "Error reading moves: unmatched )\n"); | ||
| 2567 | return alg; | ||
| 2568 | } | ||
| 2569 | |||
| 2570 | if (str[i] == '(' || str[i] == ')') { | ||
| 2571 | niss = !niss; | ||
| 2572 | continue; | ||
| 2573 | } | ||
| 2574 | |||
| 2575 | for (j = 0; j < NMOVES; j++) { | ||
| 2576 | if (str[i] == move_string[j][0]) { | ||
| 2577 | m = j; | ||
| 2578 | if (m <= B && str[i+1]=='w') { | ||
| 2579 | m += Uw - U; | ||
| 2580 | i++; | ||
| 2581 | } | ||
| 2582 | if (str[i+1]=='2') { | ||
| 2583 | m += 1; | ||
| 2584 | i++; | ||
| 2585 | } else if (str[i+1]=='\'' || str[i+1]=='3') { | ||
| 2586 | m += 2; | ||
| 2587 | i++; | ||
| 2588 | } | ||
| 2589 | append_move(alg, m, niss); | ||
| 2590 | break; | ||
| 2591 | } | ||
| 2592 | } | ||
| 2593 | } | ||
| 2594 | |||
| 2595 | return alg; | ||
| 2596 | } | ||
| 2597 | |||
| 2598 | Alg * | ||
| 2599 | on_inverse(Alg *alg) | ||
| 2600 | { | ||
| 2601 | Alg *ret = new_alg(""); | ||
| 2602 | int i; | ||
| 2603 | |||
| 2604 | for (i = 0; i < alg->len; i++) | ||
| 2605 | append_move(ret, alg->move[i], !alg->inv[i]); | ||
| 2606 | |||
| 2607 | return ret; | ||
| 2608 | } | ||
| 2609 | |||
| 2610 | void | ||
| 2611 | print_alg(Alg *alg, bool l) | ||
| 2612 | { | ||
| 2613 | /* TODO: make it possible to print to stdout or to string */ | ||
| 2614 | /* Maybe just return a string */ | ||
| 2615 | char fill[4]; | ||
| 2616 | int i; | ||
| 2617 | bool niss = false; | ||
| 2618 | |||
| 2619 | for (i = 0; i < alg->len; i++) { | ||
| 2620 | if (!niss && alg->inv[i]) | ||
| 2621 | strcpy(fill, i == 0 ? "(" : " ("); | ||
| 2622 | if (niss && !alg->inv[i]) | ||
| 2623 | strcpy(fill, ") "); | ||
| 2624 | if (niss == alg->inv[i]) | ||
| 2625 | strcpy(fill, i == 0 ? "" : " "); | ||
| 2626 | |||
| 2627 | printf("%s%s", fill, move_string[alg->move[i]]); | ||
| 2628 | niss = alg->inv[i]; | ||
| 2629 | } | ||
| 2630 | |||
| 2631 | if (niss) | ||
| 2632 | printf(")"); | ||
| 2633 | if (l) | ||
| 2634 | printf(" (%d)", alg->len); | ||
| 2635 | |||
| 2636 | printf("\n"); | ||
| 2637 | } | ||
| 2638 | |||
| 2639 | void | ||
| 2640 | print_alglist(AlgList *al, bool l) | ||
| 2641 | { | ||
| 2642 | AlgListNode *i; | ||
| 2643 | |||
| 2644 | for (i = al->first; i != NULL; i = i->next) | ||
| 2645 | print_alg(i->alg, l); | ||
| 2646 | } | ||
| 2647 | |||
| 2648 | void | ||
| 2649 | print_ptable(PruneData *pd) | ||
| 2650 | { | ||
| 2651 | uint64_t i, a[16]; | ||
| 2652 | |||
| 2653 | for (i = 0; i < 16; i++) | ||
| 2654 | a[i] = 0; | ||
| 2655 | |||
| 2656 | if (!pd->generated) | ||
| 2657 | genptable(pd); | ||
| 2658 | |||
| 2659 | for (i = 0; i < pd->size; i++) | ||
| 2660 | a[ptableval(pd, i)]++; | ||
| 2661 | |||
| 2662 | fprintf(stderr, "Values for table %s\n", pd->filename); | ||
| 2663 | for (i = 0; i < 16; i++) | ||
| 2664 | printf("%2lu\t%10lu\n", i, a[i]); | ||
| 2665 | } | ||
| 2666 | |||
| 2667 | uint64_t | ||
| 2668 | ptablesize(PruneData *pd) | ||
| 2669 | { | ||
| 2670 | return (pd->size + 1) / 2; | ||
| 2671 | } | ||
| 2672 | |||
| 2673 | int | ||
| 2674 | ptableval(PruneData *pd, uint64_t ind) | ||
| 2675 | { | ||
| 2676 | return (ind % 2) ? pd->ptable[ind/2] / 16 : pd->ptable[ind/2] % 16; | ||
| 2677 | } | ||
| 2678 | |||
| 2679 | |||
| 2680 | Alg * | ||
| 2681 | trans_alg(Trans i) | ||
| 2682 | { | ||
| 2683 | return trans_algs[i]; | ||
| 2684 | } | ||
| 2685 | |||
| 2686 | void | ||
| 2687 | transform_alg(Trans t, Alg *alg) | ||
| 2688 | { | ||
| 2689 | int i; | ||
| 2690 | |||
| 2691 | for (i = 0; i < alg->len; i++) | ||
| 2692 | alg->move[i] = moves_ttable[t][alg->move[i]]; | ||
| 2693 | } | ||
| 2694 | |||
| 2695 | Center | ||
| 2696 | what_center_at(Cube cube, Center c) | ||
| 2697 | { | ||
| 2698 | return what_center_at_aux[cube.cpos][c]; | ||
| 2699 | } | ||
| 2700 | |||
| 2701 | Corner | ||
| 2702 | what_corner_at(Cube cube, Corner c) | ||
| 2703 | { | ||
| 2704 | return what_corner_at_aux[cube.cp][c]; | ||
| 2705 | } | ||
| 2706 | |||
| 2707 | Edge | ||
| 2708 | what_edge_at(Cube cube, Edge e) | ||
| 2709 | { | ||
| 2710 | Edge ret; | ||
| 2711 | CubeArray *arr = new_cubearray(cube, pf_ep); | ||
| 2712 | |||
| 2713 | ret = arr->ep[e]; | ||
| 2714 | |||
| 2715 | free_cubearray(arr, pf_ep); | ||
| 2716 | return ret; | ||
| 2717 | } | ||
| 2718 | |||
| 2719 | int | ||
| 2720 | what_orientation_corner(int co, Corner c) | ||
| 2721 | { | ||
| 2722 | if (c < 7) | ||
| 2723 | return (co / powint(3, c)) % 3; | ||
| 2724 | else | ||
| 2725 | return what_orientation_last_corner_aux[co]; | ||
| 2726 | } | ||
| 2727 | |||
| 2728 | int | ||
| 2729 | what_orientation_edge(int eo, Edge e) | ||
| 2730 | { | ||
| 2731 | if (e < 11) | ||
| 2732 | return (eo & (1 << e)) ? 1 : 0; | ||
| 2733 | else | ||
| 2734 | return what_orientation_last_edge_aux[eo]; | ||
| 2735 | } | ||
| 2736 | |||
| 2737 | Center | ||
| 2738 | where_is_center(Cube cube, Center c) | ||
| 2739 | { | ||
| 2740 | return where_is_center_aux[cube.cpos][c]; | ||
| 2741 | } | ||
| 2742 | |||
| 2743 | Corner | ||
| 2744 | where_is_corner(Cube cube, Corner c) | ||
| 2745 | { | ||
| 2746 | return where_is_corner_aux[cube.cp][c]; | ||
| 2747 | } | ||
| 2748 | |||
| 2749 | |||
| 2750 | void | ||
| 2751 | init() | ||
| 2752 | { | ||
| 2753 | /* Order is important! */ | ||
| 2754 | init_environment(); | ||
| 2755 | init_strings(); | ||
| 2756 | init_moves_aux(); | ||
| 2757 | init_moves(); | ||
| 2758 | init_auxtables(); | ||
| 2759 | init_trans_aux(); | ||
| 2760 | init_trans(); | ||
| 2761 | } | ||
| 2762 | |||
diff --git a/old/2021-06-23-uint16t/cube.h b/old/2021-06-23-uint16t/cube.h new file mode 100644 index 0000000..74d14cc --- /dev/null +++ b/old/2021-06-23-uint16t/cube.h | |||
| @@ -0,0 +1,87 @@ | |||
| 1 | #ifndef CUBE_H | ||
| 2 | #define CUBE_H | ||
| 3 | |||
| 4 | #include <stdio.h> | ||
| 5 | #include <stdbool.h> | ||
| 6 | #include <stdint.h> | ||
| 7 | #include <stdlib.h> | ||
| 8 | #include <string.h> | ||
| 9 | #include <time.h> | ||
| 10 | #include <unistd.h> | ||
| 11 | #include <sys/stat.h> | ||
| 12 | |||
| 13 | /* Constants and macros *****************************************************/ | ||
| 14 | |||
| 15 | #define POW2TO6 64ULL | ||
| 16 | #define POW2TO11 2048ULL | ||
| 17 | #define POW2TO12 4096ULL | ||
| 18 | #define POW3TO7 2187ULL | ||
| 19 | #define POW3TO8 6561ULL | ||
| 20 | #define FACTORIAL4 24ULL | ||
| 21 | #define FACTORIAL6 720ULL | ||
| 22 | #define FACTORIAL7 5040ULL | ||
| 23 | #define FACTORIAL8 40320ULL | ||
| 24 | #define FACTORIAL12 479001600ULL | ||
| 25 | #define BINOM12ON4 495ULL | ||
| 26 | #define BINOM8ON4 70ULL | ||
| 27 | #define MIN(a,b) (((a) < (b)) ? (a) : (b)) | ||
| 28 | #define MAX(a,b) (((a) > (b)) ? (a) : (b)) | ||
| 29 | |||
| 30 | #define NMOVES (z3+1) | ||
| 31 | #define NTRANS (mirror+1) | ||
| 32 | #define NROTATIONS (NTRANS-1) | ||
| 33 | |||
| 34 | /* Type definitions **********************************************************/ | ||
| 35 | |||
| 36 | #include "cubetypes.h" | ||
| 37 | |||
| 38 | /* Public functions **********************************************************/ | ||
| 39 | |||
| 40 | Cube apply_alg(Alg *alg, Cube cube); | ||
| 41 | Cube apply_move(Move m, Cube cube); | ||
| 42 | Cube apply_trans(Trans t, Cube cube); | ||
| 43 | bool block_solved(Cube cube, Block); | ||
| 44 | Cube compose(Cube c2, Cube c1); /* Use c2 as an alg on c1 */ | ||
| 45 | uint64_t epos_dependent_cube(Cube cube); | ||
| 46 | bool equal(Cube c1, Cube c2); | ||
| 47 | Cube inverse_cube(Cube cube); | ||
| 48 | Move inverse_move(Move m); | ||
| 49 | Trans inverse_trans(Trans t); | ||
| 50 | bool is_admissible(Cube cube); | ||
| 51 | bool is_solved(Cube cube, bool reorient); | ||
| 52 | bool is_solved_center(Cube cube, Center c); | ||
| 53 | bool is_solved_corner(Cube cube, Corner c); | ||
| 54 | bool is_solved_edge(Cube cube, Edge e); | ||
| 55 | void print_cube(Cube cube); | ||
| 56 | Cube random_cube(); | ||
| 57 | AlgList * solve(Cube cube, Step step, SolveOptions *opts); | ||
| 58 | Center what_center_at(Cube cube, Center c); | ||
| 59 | Corner what_corner_at(Cube cube, Corner c); | ||
| 60 | Edge what_edge_at(Cube cube, Edge e); | ||
| 61 | int what_orientation_corner(int co, Corner c); | ||
| 62 | int what_orientation_edge(int eo, Edge e); | ||
| 63 | Center where_is_center(Cube cube, Center c); | ||
| 64 | Corner where_is_corner(Cube cube, Corner c); | ||
| 65 | Edge where_is_edge(Cube cube, Edge e); | ||
| 66 | |||
| 67 | Move base_move(Move m); | ||
| 68 | void free_alg(Alg *alg); | ||
| 69 | void free_alglist(AlgList *l); | ||
| 70 | Alg * inverse_alg(Alg *alg); | ||
| 71 | Alg * new_alg(char *str); | ||
| 72 | Alg * on_inverse(Alg *alg); | ||
| 73 | void print_alg(Alg *alg, bool l); | ||
| 74 | void print_alglist(AlgList *al, bool l); | ||
| 75 | Alg * trans_alg(Trans i); | ||
| 76 | void transform_alg(Trans t, Alg *alg); | ||
| 77 | |||
| 78 | void genalgset(AlgSet *as); | ||
| 79 | void genptable(PruneData *pd); | ||
| 80 | void print_ptable(PruneData *pd); | ||
| 81 | uint64_t ptablesize(PruneData *pd); | ||
| 82 | int ptableval(PruneData *pd, uint64_t ind); | ||
| 83 | |||
| 84 | void init(); | ||
| 85 | |||
| 86 | #endif | ||
| 87 | |||
diff --git a/old/2021-06-23-uint16t/cubetypes.h b/old/2021-06-23-uint16t/cubetypes.h new file mode 100644 index 0000000..10bfabb --- /dev/null +++ b/old/2021-06-23-uint16t/cubetypes.h | |||
| @@ -0,0 +1,224 @@ | |||
| 1 | /* Typedefs ******************************************************************/ | ||
| 2 | |||
| 3 | typedef enum center Center; | ||
| 4 | typedef enum corner Corner; | ||
| 5 | typedef enum edge Edge; | ||
| 6 | typedef enum move Move; | ||
| 7 | typedef enum trans Trans; | ||
| 8 | |||
| 9 | typedef struct alg Alg; | ||
| 10 | typedef struct alglist AlgList; | ||
| 11 | typedef struct alglistnode AlgListNode; | ||
| 12 | typedef struct algset AlgSet; | ||
| 13 | typedef struct block Block; | ||
| 14 | typedef struct cube Cube; | ||
| 15 | typedef struct cubearray CubeArray; | ||
| 16 | typedef struct dfsdata DfsData; | ||
| 17 | typedef struct piecefilter PieceFilter; | ||
| 18 | typedef struct prunedata PruneData; | ||
| 19 | typedef struct solveoptions SolveOptions; | ||
| 20 | typedef struct step Step; | ||
| 21 | |||
| 22 | typedef Cube (*AntiIndexer) (uint64_t); | ||
| 23 | typedef int (*Checker) (Cube, int); | ||
| 24 | typedef uint64_t (*Indexer) (Cube); | ||
| 25 | typedef bool (*Moveset) (Move); | ||
| 26 | |||
| 27 | |||
| 28 | /* Enums *********************************************************************/ | ||
| 29 | |||
| 30 | enum | ||
| 31 | center | ||
| 32 | { | ||
| 33 | U_center, D_center, | ||
| 34 | R_center, L_center, | ||
| 35 | F_center, B_center | ||
| 36 | }; | ||
| 37 | |||
| 38 | enum | ||
| 39 | corner | ||
| 40 | { | ||
| 41 | UFR, UFL, UBL, UBR, | ||
| 42 | DFR, DFL, DBL, DBR | ||
| 43 | }; | ||
| 44 | |||
| 45 | enum | ||
| 46 | edge | ||
| 47 | { | ||
| 48 | UF, UL, UB, UR, | ||
| 49 | DF, DL, DB, DR, | ||
| 50 | FR, FL, BL, BR | ||
| 51 | }; | ||
| 52 | |||
| 53 | enum | ||
| 54 | move | ||
| 55 | { | ||
| 56 | NULLMOVE, | ||
| 57 | U, U2, U3, D, D2, D3, | ||
| 58 | R, R2, R3, L, L2, L3, | ||
| 59 | F, F2, F3, B, B2, B3, | ||
| 60 | Uw, Uw2, Uw3, Dw, Dw2, Dw3, | ||
| 61 | Rw, Rw2, Rw3, Lw, Lw2, Lw3, | ||
| 62 | Fw, Fw2, Fw3, Bw, Bw2, Bw3, | ||
| 63 | M, M2, M3, | ||
| 64 | S, S2, S3, | ||
| 65 | E, E2, E3, | ||
| 66 | x, x2, x3, | ||
| 67 | y, y2, y3, | ||
| 68 | z, z2, z3, | ||
| 69 | }; | ||
| 70 | |||
| 71 | enum | ||
| 72 | trans | ||
| 73 | { | ||
| 74 | uf, ur, ub, ul, | ||
| 75 | df, dr, db, dl, | ||
| 76 | rf, rd, rb, ru, | ||
| 77 | lf, ld, lb, lu, | ||
| 78 | fu, fr, fd, fl, | ||
| 79 | bu, br, bd, bl, | ||
| 80 | mirror, /* R|L */ | ||
| 81 | }; | ||
| 82 | |||
| 83 | |||
| 84 | /* Structs *******************************************************************/ | ||
| 85 | |||
| 86 | struct | ||
| 87 | alg | ||
| 88 | { | ||
| 89 | Move * move; | ||
| 90 | bool * inv; | ||
| 91 | int len; | ||
| 92 | int allocated; | ||
| 93 | }; | ||
| 94 | |||
| 95 | struct | ||
| 96 | alglist | ||
| 97 | { | ||
| 98 | AlgListNode * first; | ||
| 99 | AlgListNode * last; | ||
| 100 | int len; | ||
| 101 | }; | ||
| 102 | |||
| 103 | struct | ||
| 104 | alglistnode | ||
| 105 | { | ||
| 106 | Alg * alg; | ||
| 107 | AlgListNode * next; | ||
| 108 | }; | ||
| 109 | |||
| 110 | struct | ||
| 111 | block | ||
| 112 | { | ||
| 113 | bool edge[12]; | ||
| 114 | bool corner[8]; | ||
| 115 | bool center[6]; | ||
| 116 | }; | ||
| 117 | |||
| 118 | struct | ||
| 119 | cube | ||
| 120 | { | ||
| 121 | uint16_t epose; | ||
| 122 | uint16_t eposs; | ||
| 123 | uint16_t eposm; | ||
| 124 | uint16_t eofb; | ||
| 125 | uint16_t eorl; | ||
| 126 | uint16_t eoud; | ||
| 127 | uint16_t cp; | ||
| 128 | uint16_t coud; | ||
| 129 | uint16_t cofb; | ||
| 130 | uint16_t corl; | ||
| 131 | uint16_t cpos; | ||
| 132 | }; | ||
| 133 | |||
| 134 | struct | ||
| 135 | cubearray | ||
| 136 | { | ||
| 137 | int * ep; | ||
| 138 | int * eofb; | ||
| 139 | int * eorl; | ||
| 140 | int * eoud; | ||
| 141 | int * cp; | ||
| 142 | int * coud; | ||
| 143 | int * corl; | ||
| 144 | int * cofb; | ||
| 145 | int * cpos; | ||
| 146 | }; | ||
| 147 | |||
| 148 | struct | ||
| 149 | dfsdata | ||
| 150 | { | ||
| 151 | int d; | ||
| 152 | int m; | ||
| 153 | int lb; | ||
| 154 | bool niss; | ||
| 155 | Move last1; | ||
| 156 | Move last2; | ||
| 157 | AlgList * sols; | ||
| 158 | Alg * current_alg; | ||
| 159 | Move sorted_moves[NMOVES]; | ||
| 160 | int move_position[NMOVES]; | ||
| 161 | }; | ||
| 162 | |||
| 163 | struct | ||
| 164 | piecefilter | ||
| 165 | { | ||
| 166 | bool epose; | ||
| 167 | bool eposs; | ||
| 168 | bool eposm; | ||
| 169 | bool eofb; | ||
| 170 | bool eorl; | ||
| 171 | bool eoud; | ||
| 172 | bool cp; | ||
| 173 | bool coud; | ||
| 174 | bool cofb; | ||
| 175 | bool corl; | ||
| 176 | bool cpos; | ||
| 177 | }; | ||
| 178 | |||
| 179 | struct | ||
| 180 | prunedata | ||
| 181 | { | ||
| 182 | char * filename; | ||
| 183 | uint8_t * ptable; | ||
| 184 | uint8_t * reached; | ||
| 185 | bool generated; | ||
| 186 | uint64_t n; | ||
| 187 | uint64_t size; | ||
| 188 | Indexer index; | ||
| 189 | Moveset moveset; | ||
| 190 | }; | ||
| 191 | |||
| 192 | struct | ||
| 193 | solveoptions | ||
| 194 | { | ||
| 195 | int min_moves; | ||
| 196 | int max_moves; | ||
| 197 | int max_solutions; | ||
| 198 | bool optimal_only; | ||
| 199 | bool can_niss; | ||
| 200 | bool feedback; | ||
| 201 | Trans pre_trans; | ||
| 202 | }; | ||
| 203 | |||
| 204 | struct | ||
| 205 | step | ||
| 206 | { | ||
| 207 | Checker check; | ||
| 208 | Checker ready; | ||
| 209 | Moveset moveset; | ||
| 210 | }; | ||
| 211 | |||
| 212 | /* TODO: I put it here because it needs the definition of Step, sort it out */ | ||
| 213 | struct | ||
| 214 | algset | ||
| 215 | { | ||
| 216 | char * filename; | ||
| 217 | AlgList ** table; | ||
| 218 | bool generated; | ||
| 219 | uint64_t size; | ||
| 220 | Indexer index; | ||
| 221 | AntiIndexer antindex; | ||
| 222 | Step step; | ||
| 223 | SolveOptions opts; | ||
| 224 | }; | ||
diff --git a/old/2021-06-30-noreached/cube.c b/old/2021-06-30-noreached/cube.c new file mode 100644 index 0000000..a7d137c --- /dev/null +++ b/old/2021-06-30-noreached/cube.c | |||
| @@ -0,0 +1,3394 @@ | |||
| 1 | #include "cube.h" | ||
| 2 | |||
| 3 | /* Local functions **********************************************************/ | ||
| 4 | |||
| 5 | static Cube admissible_ep(Cube cube, PieceFilter f); | ||
| 6 | static Cube admissible_eos_from_eofbepos(Cube cube); | ||
| 7 | static bool allowed_next(Move move, DfsData *dd); | ||
| 8 | static void append_alg(AlgList *l, Alg *alg); | ||
| 9 | static void append_move(Alg *alg, Move m, bool inverse); | ||
| 10 | static Cube apply_alg_generic(Alg *alg, Cube c, PieceFilter f, bool a); | ||
| 11 | static void apply_permutation(int *perm, int *set, int n); | ||
| 12 | static Cube apply_move_cubearray(Move m, Cube cube, PieceFilter f); | ||
| 13 | static int array_ep_to_epos(int *ep, int *eps_solved); | ||
| 14 | static Cube arrays_to_cube(CubeArray *arr, PieceFilter f); | ||
| 15 | static int binomial(int n, int k); | ||
| 16 | static Cube compose_filtered(Cube c2, Cube c1, PieceFilter f); | ||
| 17 | static void cube_to_arrays(Cube cube, CubeArray *arr, PieceFilter f); | ||
| 18 | static void dfs(Cube c, Step s, SolveOptions *opts, DfsData *dd); | ||
| 19 | static void dfs_branch(Cube c, Step s, SolveOptions *opts, DfsData *dd); | ||
| 20 | static bool dfs_check_solved(SolveOptions *opts, DfsData *dd); | ||
| 21 | static void dfs_niss(Cube c, Step s, SolveOptions *opts, DfsData *dd); | ||
| 22 | static bool dfs_stop(Cube c, Step s, SolveOptions *opts, DfsData *dd); | ||
| 23 | static int digit_array_to_int(int *a, int n, int b); | ||
| 24 | static int edge_slice(Edge e); /* E=0, S=1, M=2 */ | ||
| 25 | static int epos_dependent_pos(int pos1, int pos2); | ||
| 26 | static int epos_from_arrays(int *epos, int *ep); | ||
| 27 | static void epos_to_partial_ep(int epos, int *ep, int *ss); | ||
| 28 | static int factorial(int n); | ||
| 29 | static void free_alglistnode(AlgListNode *aln); | ||
| 30 | static void free_cubearray(CubeArray *arr, PieceFilter f); | ||
| 31 | static void genptable_dfs(Cube c, PruneData *pd, DfsData *dd); | ||
| 32 | static void genptable_dfs_branch(Cube c, PruneData *pd, DfsData *dd); | ||
| 33 | static void gensym(SymData *sd); | ||
| 34 | static void index_to_perm(int p, int n, int *r); | ||
| 35 | static void index_to_subset(int s, int n, int k, int *r); | ||
| 36 | static void init_auxtables(); | ||
| 37 | static void init_cphtr_cosets(); | ||
| 38 | static void init_cphtr_left_cosets_bfs(int i, int c); | ||
| 39 | static void init_cphtr_right_cosets_color(int i, int c); | ||
| 40 | static void init_environment(); | ||
| 41 | static void init_moves(); | ||
| 42 | static void init_moves_aux(); | ||
| 43 | static void init_strings(); | ||
| 44 | static void init_symdata(); | ||
| 45 | static void init_trans(); | ||
| 46 | static void init_trans_aux(); | ||
| 47 | static void int_to_digit_array(int a, int b, int n, int *r); | ||
| 48 | static void int_to_sum_zero_array(int x, int b, int n, int *a); | ||
| 49 | static int invert_digits(int a, int b, int n); | ||
| 50 | static bool is_perm(int *a, int n); | ||
| 51 | static bool is_subset(int *a, int n, int k); | ||
| 52 | static Cube move_via_arrays(CubeArray *arr, Cube c, PieceFilter pf); | ||
| 53 | static void movelist_to_position(Move *movelist, int *position); | ||
| 54 | static void moveset_to_list(Moveset ms, Estimator f, Move *r); | ||
| 55 | static AlgList * new_alglist(); | ||
| 56 | static CubeArray * new_cubearray(Cube cube, PieceFilter f); | ||
| 57 | static int perm_sign(int *a, int n); | ||
| 58 | static int perm_to_index(int *a, int n); | ||
| 59 | static int powint(int a, int b); | ||
| 60 | static void ptable_update(PruneData *pd, Cube cube, int m); | ||
| 61 | static void realloc_alg(Alg *alg, int n); | ||
| 62 | static bool read_mtables_file(); | ||
| 63 | static bool read_ptable_file(PruneData *pd); | ||
| 64 | static bool read_symdata_file(SymData *sd); | ||
| 65 | static bool read_ttables_file(); | ||
| 66 | static Cube rotate_via_compose(Trans r, Cube c, PieceFilter f); | ||
| 67 | static int subset_to_index(int *a, int n, int k); | ||
| 68 | static void sum_arrays_mod(int *src, int *dst, int n, int m); | ||
| 69 | static void swap(int *a, int *b); | ||
| 70 | static bool write_mtables_file(); | ||
| 71 | static bool write_ptable_file(PruneData *pd); | ||
| 72 | static bool write_symdata_file(SymData *sd); | ||
| 73 | static bool write_ttables_file(); | ||
| 74 | |||
| 75 | |||
| 76 | /* All sorts of useful costants and tables **********************************/ | ||
| 77 | |||
| 78 | static char * tabledir; | ||
| 79 | |||
| 80 | static PieceFilter pf_all; | ||
| 81 | static PieceFilter pf_4val; | ||
| 82 | static PieceFilter pf_epcp; | ||
| 83 | static PieceFilter pf_cpos; | ||
| 84 | static PieceFilter pf_cp; | ||
| 85 | static PieceFilter pf_ep; | ||
| 86 | static PieceFilter pf_e; | ||
| 87 | static PieceFilter pf_s; | ||
| 88 | static PieceFilter pf_m; | ||
| 89 | static PieceFilter pf_eo; | ||
| 90 | static PieceFilter pf_co; | ||
| 91 | |||
| 92 | static int epe_solved[4]; | ||
| 93 | static int eps_solved[4]; | ||
| 94 | static int epm_solved[4]; | ||
| 95 | |||
| 96 | static char move_string[NMOVES][7]; | ||
| 97 | static char edge_string[12][7]; | ||
| 98 | static char corner_string[8][7]; | ||
| 99 | static char center_string[6][7]; | ||
| 100 | |||
| 101 | static Cube admissible_ee_aux[POW2TO11*BINOM12ON4]; | ||
| 102 | static bool commute[NMOVES][NMOVES]; | ||
| 103 | static bool possible_next[NMOVES][NMOVES][NMOVES]; | ||
| 104 | static Move inverse_move_aux[NMOVES]; | ||
| 105 | static Trans inverse_trans_aux[NTRANS]; | ||
| 106 | static int epos_dependent_aux[BINOM12ON4][BINOM12ON4]; | ||
| 107 | static int cphtr_left_cosets[FACTORIAL8]; | ||
| 108 | static int cphtr_right_cosets[FACTORIAL8]; | ||
| 109 | static int cphtr_right_rep[BINOM8ON4*6]; | ||
| 110 | static Center what_center_at_aux[FACTORIAL6][6]; | ||
| 111 | static Corner what_corner_at_aux[FACTORIAL8][8]; | ||
| 112 | static int what_orientation_last_corner_aux[POW3TO7]; | ||
| 113 | static int what_orientation_last_edge_aux[POW2TO11]; | ||
| 114 | static Center where_is_center_aux[FACTORIAL6][6]; | ||
| 115 | static Corner where_is_corner_aux[FACTORIAL8][8]; | ||
| 116 | static Edge where_is_edge_aux[3][FACTORIAL12/FACTORIAL8][12]; | ||
| 117 | |||
| 118 | static int epose_ttable[NTRANS][FACTORIAL12/FACTORIAL8]; | ||
| 119 | static int eposs_ttable[NTRANS][FACTORIAL12/FACTORIAL8]; | ||
| 120 | static int eposm_ttable[NTRANS][FACTORIAL12/FACTORIAL8]; | ||
| 121 | static int eo_ttable[NTRANS][POW2TO11]; | ||
| 122 | static int cp_ttable[NTRANS][FACTORIAL8]; | ||
| 123 | static int co_ttable[NTRANS][POW3TO7]; | ||
| 124 | static int cpos_ttable[NTRANS][FACTORIAL6]; | ||
| 125 | static Move moves_ttable[NTRANS][NMOVES]; | ||
| 126 | |||
| 127 | static int epose_mtable[NMOVES][FACTORIAL12/FACTORIAL8]; | ||
| 128 | static int eposs_mtable[NMOVES][FACTORIAL12/FACTORIAL8]; | ||
| 129 | static int eposm_mtable[NMOVES][FACTORIAL12/FACTORIAL8]; | ||
| 130 | static int eofb_mtable[NMOVES][POW2TO11]; | ||
| 131 | static int eorl_mtable[NMOVES][POW2TO11]; | ||
| 132 | static int eoud_mtable[NMOVES][POW2TO11]; | ||
| 133 | static int cp_mtable[NMOVES][FACTORIAL8]; | ||
| 134 | static int coud_mtable[NMOVES][POW3TO7]; | ||
| 135 | static int cofb_mtable[NMOVES][POW3TO7]; | ||
| 136 | static int corl_mtable[NMOVES][POW3TO7]; | ||
| 137 | static int cpos_mtable[NMOVES][FACTORIAL6]; | ||
| 138 | |||
| 139 | static uint64_t me[12]; | ||
| 140 | |||
| 141 | static int edge_cycle[NMOVES][12]; | ||
| 142 | static int corner_cycle[NMOVES][8]; | ||
| 143 | static int center_cycle[NMOVES][6]; | ||
| 144 | static int eofb_flipped[NMOVES][12]; | ||
| 145 | static int eorl_flipped[NMOVES][12]; | ||
| 146 | static int eoud_flipped[NMOVES][12]; | ||
| 147 | static int coud_flipped[NMOVES][8]; | ||
| 148 | static int corl_flipped[NMOVES][8]; | ||
| 149 | static int cofb_flipped[NMOVES][8]; | ||
| 150 | static Alg * equiv_alg[NMOVES]; | ||
| 151 | |||
| 152 | static int epose_source[NTRANS]; /* 0=epose, 1=eposs, 2=eposm */ | ||
| 153 | static int eposs_source[NTRANS]; | ||
| 154 | static int eposm_source[NTRANS]; | ||
| 155 | static int eofb_source[NTRANS]; /* 0=eoud, 1=eorl, 2=eofb */ | ||
| 156 | static int eorl_source[NTRANS]; | ||
| 157 | static int eoud_source[NTRANS]; | ||
| 158 | static int coud_source[NTRANS]; /* 0=coud, 1=corl, 2=cofb */ | ||
| 159 | static int cofb_source[NTRANS]; | ||
| 160 | static int corl_source[NTRANS]; | ||
| 161 | static int ep_mirror[12]; | ||
| 162 | static int cp_mirror[8]; | ||
| 163 | static int cpos_mirror[6]; | ||
| 164 | static Alg * rotation_algs[NROTATIONS]; | ||
| 165 | |||
| 166 | |||
| 167 | /* Symmetry data for some coordinates ****************************************/ | ||
| 168 | |||
| 169 | static Trans | ||
| 170 | trans_group_udfix[16] = { | ||
| 171 | uf, ur, ub, ul, | ||
| 172 | df, dr, db, dl, | ||
| 173 | uf_mirror, ur_mirror, ub_mirror, ul_mirror, | ||
| 174 | df_mirror, dr_mirror, db_mirror, dl_mirror, | ||
| 175 | }; | ||
| 176 | |||
| 177 | SymData | ||
| 178 | sd_coud_16 = { | ||
| 179 | .filename = "sd_coud_16", | ||
| 180 | .coord = &coord_coud, | ||
| 181 | .sym_coord = &coord_coud_sym16, | ||
| 182 | .ntrans = 16, | ||
| 183 | .trans = trans_group_udfix | ||
| 184 | }; | ||
| 185 | |||
| 186 | SymData | ||
| 187 | sd_eofbepos_16 = { | ||
| 188 | .filename = "sd_eofbepos_16", | ||
| 189 | .coord = &coord_eofbepos, | ||
| 190 | .sym_coord = &coord_eofbepos_sym16, | ||
| 191 | .ntrans = 16, | ||
| 192 | .trans = trans_group_udfix | ||
| 193 | }; | ||
| 194 | |||
| 195 | static int n_all_symdata = 2; | ||
| 196 | static SymData * all_sd[2] = { &sd_coud_16, &sd_eofbepos_16 }; | ||
| 197 | |||
| 198 | /* Coordinates and their implementation **************************************/ | ||
| 199 | |||
| 200 | static uint64_t index_eofb(Cube cube); | ||
| 201 | static uint64_t index_eofbepos(Cube cube); | ||
| 202 | static uint64_t index_coud(Cube cube); | ||
| 203 | static uint64_t index_corners(Cube cube); | ||
| 204 | static uint64_t index_cornershtr(Cube cube); | ||
| 205 | static uint64_t index_drud(Cube cube); | ||
| 206 | static uint64_t index_coud_sym16(Cube cube); | ||
| 207 | static uint64_t index_eofbepos_sym16(Cube cube); | ||
| 208 | static uint64_t index_drud_sym16(Cube cube); | ||
| 209 | static uint64_t index_khuge(Cube cube); | ||
| 210 | |||
| 211 | static Cube antindex_eofb(uint64_t ind); | ||
| 212 | static Cube antindex_eofbepos(uint64_t ind); | ||
| 213 | static Cube antindex_coud(uint64_t ind); | ||
| 214 | static Cube antindex_corners(uint64_t ind); | ||
| 215 | static Cube antindex_cornershtr(uint64_t ind); | ||
| 216 | static Cube antindex_drud(uint64_t ind); | ||
| 217 | static Cube antindex_coud_sym16(uint64_t ind); | ||
| 218 | static Cube antindex_eofbepos_sym16(uint64_t ind); | ||
| 219 | static Cube antindex_drud_sym16(uint64_t ind); | ||
| 220 | static Cube antindex_khuge(uint64_t ind); | ||
| 221 | |||
| 222 | Coordinate | ||
| 223 | coord_eofb = { | ||
| 224 | .index = index_eofb, | ||
| 225 | .cube = antindex_eofb, | ||
| 226 | .check = check_eofb, | ||
| 227 | .max = POW2TO11 | ||
| 228 | }; | ||
| 229 | |||
| 230 | Coordinate | ||
| 231 | coord_eofbepos = { | ||
| 232 | .index = index_eofbepos, | ||
| 233 | .cube = antindex_eofbepos, | ||
| 234 | .check = check_eofbepos, | ||
| 235 | .max = POW2TO11 * BINOM12ON4 | ||
| 236 | }; | ||
| 237 | |||
| 238 | Coordinate | ||
| 239 | coord_coud = { | ||
| 240 | .index = index_coud, | ||
| 241 | .cube = antindex_coud, | ||
| 242 | .check = check_coud, | ||
| 243 | .max = POW3TO7 | ||
| 244 | }; | ||
| 245 | |||
| 246 | Coordinate | ||
| 247 | coord_corners = { | ||
| 248 | .index = index_corners, | ||
| 249 | .cube = antindex_corners, | ||
| 250 | .check = check_corners, | ||
| 251 | .max = POW3TO7 * FACTORIAL8 | ||
| 252 | }; | ||
| 253 | |||
| 254 | Coordinate | ||
| 255 | coord_cornershtr = { | ||
| 256 | .index = index_cornershtr, | ||
| 257 | .cube = antindex_cornershtr, | ||
| 258 | .check = check_cornershtr, | ||
| 259 | .max = POW3TO7 * BINOM8ON4 * 6 | ||
| 260 | }; | ||
| 261 | |||
| 262 | Coordinate | ||
| 263 | coord_drud = { | ||
| 264 | .index = index_drud, | ||
| 265 | .cube = antindex_drud, | ||
| 266 | .check = check_drud, | ||
| 267 | .max = POW2TO11 * POW3TO7 * BINOM12ON4 | ||
| 268 | }; | ||
| 269 | |||
| 270 | Coordinate | ||
| 271 | coord_eofbepos_sym16 = { | ||
| 272 | .index = index_eofbepos_sym16, | ||
| 273 | .cube = antindex_eofbepos_sym16, | ||
| 274 | .check = check_eofbepos, | ||
| 275 | }; | ||
| 276 | |||
| 277 | Coordinate | ||
| 278 | coord_coud_sym16 = { | ||
| 279 | .index = index_coud_sym16, | ||
| 280 | .cube = antindex_coud_sym16, | ||
| 281 | .check = check_coud, | ||
| 282 | }; | ||
| 283 | |||
| 284 | Coordinate | ||
| 285 | coord_drud_sym16 = { | ||
| 286 | .index = index_drud_sym16, | ||
| 287 | .cube = antindex_drud_sym16, | ||
| 288 | .check = check_drud, | ||
| 289 | .max = POW3TO7 * 64430 | ||
| 290 | }; | ||
| 291 | |||
| 292 | Coordinate | ||
| 293 | coord_khuge = { | ||
| 294 | .index = index_khuge, | ||
| 295 | .cube = antindex_khuge, | ||
| 296 | .check = check_khuge, | ||
| 297 | .max = POW3TO7 * FACTORIAL4 * 64430 | ||
| 298 | }; | ||
| 299 | |||
| 300 | |||
| 301 | static uint64_t | ||
| 302 | index_eofb(Cube cube) | ||
| 303 | { | ||
| 304 | return cube.eofb; | ||
| 305 | } | ||
| 306 | |||
| 307 | static uint64_t | ||
| 308 | index_eofbepos(Cube cube) | ||
| 309 | { | ||
| 310 | return (cube.epose / FACTORIAL4) * POW2TO11 + cube.eofb; | ||
| 311 | } | ||
| 312 | |||
| 313 | static uint64_t | ||
| 314 | index_coud(Cube cube) | ||
| 315 | { | ||
| 316 | return cube.coud; | ||
| 317 | } | ||
| 318 | |||
| 319 | static uint64_t | ||
| 320 | index_corners(Cube cube) | ||
| 321 | { | ||
| 322 | return cube.coud * FACTORIAL8 + cube.cp; | ||
| 323 | } | ||
| 324 | |||
| 325 | static uint64_t | ||
| 326 | index_cornershtr(Cube cube) | ||
| 327 | { | ||
| 328 | return cube.coud * BINOM8ON4 * 6 + cphtr(cube); | ||
| 329 | } | ||
| 330 | |||
| 331 | static uint64_t | ||
| 332 | index_drud(Cube cube) | ||
| 333 | { | ||
| 334 | uint64_t a, b, c; | ||
| 335 | |||
| 336 | a = cube.eofb; | ||
| 337 | b = cube.coud; | ||
| 338 | c = cube.epose / FACTORIAL4; | ||
| 339 | |||
| 340 | b *= POW2TO11; | ||
| 341 | c *= POW2TO11 * POW3TO7; | ||
| 342 | |||
| 343 | return a + b + c; | ||
| 344 | } | ||
| 345 | |||
| 346 | static uint64_t | ||
| 347 | index_coud_sym16(Cube cube) | ||
| 348 | { | ||
| 349 | return sd_coud_16.class[index_coud(cube)]; | ||
| 350 | } | ||
| 351 | |||
| 352 | static uint64_t | ||
| 353 | index_drud_sym16(Cube cube) | ||
| 354 | { | ||
| 355 | Trans t; | ||
| 356 | Cube c; | ||
| 357 | |||
| 358 | t = sd_eofbepos_16.transtorep[index_eofbepos(cube)]; | ||
| 359 | c = apply_trans(t, cube); | ||
| 360 | |||
| 361 | return index_eofbepos_sym16(c) * POW3TO7 + c.coud; | ||
| 362 | } | ||
| 363 | |||
| 364 | static uint64_t | ||
| 365 | index_eofbepos_sym16(Cube cube) | ||
| 366 | { | ||
| 367 | return sd_eofbepos_16.class[index_eofbepos(cube)]; | ||
| 368 | } | ||
| 369 | |||
| 370 | static uint64_t | ||
| 371 | index_khuge(Cube cube) | ||
| 372 | { | ||
| 373 | Trans t; | ||
| 374 | Cube c; | ||
| 375 | uint64_t a; | ||
| 376 | |||
| 377 | t = sd_eofbepos_16.transtorep[index_eofbepos(cube)]; | ||
| 378 | c = apply_trans(t, cube); | ||
| 379 | a = (index_eofbepos_sym16(c) * 24) + (c.epose % 24); | ||
| 380 | |||
| 381 | return a * POW3TO7 + c.coud; | ||
| 382 | } | ||
| 383 | |||
| 384 | |||
| 385 | /* TODO: rename */ | ||
| 386 | static Cube | ||
| 387 | antindex_eofb(uint64_t ind) | ||
| 388 | { | ||
| 389 | return (Cube){ .eofb = ind, .eorl = ind, .eoud = ind }; | ||
| 390 | } | ||
| 391 | |||
| 392 | static Cube | ||
| 393 | antindex_eofbepos(uint64_t ind) | ||
| 394 | { | ||
| 395 | return admissible_ee_aux[ind]; | ||
| 396 | } | ||
| 397 | |||
| 398 | /* TODO: rename */ | ||
| 399 | static Cube | ||
| 400 | antindex_coud(uint64_t ind) | ||
| 401 | { | ||
| 402 | return (Cube){ .coud = ind, .corl = ind, .cofb = ind }; | ||
| 403 | } | ||
| 404 | |||
| 405 | /* TODO: admissible co for other orientations */ | ||
| 406 | static Cube | ||
| 407 | antindex_corners(uint64_t ind) | ||
| 408 | { | ||
| 409 | Cube c = {0}; | ||
| 410 | |||
| 411 | c.coud = ind / FACTORIAL8; | ||
| 412 | c.cp = ind % FACTORIAL8; | ||
| 413 | |||
| 414 | return c; | ||
| 415 | } | ||
| 416 | |||
| 417 | /* TODO: admissible co for other orientations */ | ||
| 418 | static Cube | ||
| 419 | antindex_cornershtr(uint64_t ind) | ||
| 420 | { | ||
| 421 | Cube c = anti_cphtr(ind % (BINOM8ON4 * 6)); | ||
| 422 | |||
| 423 | c.coud = ind / (BINOM8ON4 * 6); | ||
| 424 | |||
| 425 | return c; | ||
| 426 | } | ||
| 427 | |||
| 428 | /* TODO: admissible eos and cos */ | ||
| 429 | static Cube | ||
| 430 | antindex_drud(uint64_t ind) | ||
| 431 | { | ||
| 432 | Cube c = {0}; | ||
| 433 | |||
| 434 | c.eofb = ind % POW2TO11; | ||
| 435 | c.coud = (ind / POW2TO11) % POW3TO7; | ||
| 436 | c.epose = (ind % (POW2TO11 * POW3TO7)) * FACTORIAL4; | ||
| 437 | |||
| 438 | return c; | ||
| 439 | } | ||
| 440 | |||
| 441 | static Cube | ||
| 442 | antindex_coud_sym16(uint64_t ind) | ||
| 443 | { | ||
| 444 | return sd_coud_16.rep[ind]; | ||
| 445 | } | ||
| 446 | |||
| 447 | static Cube | ||
| 448 | antindex_eofbepos_sym16(uint64_t ind) | ||
| 449 | { | ||
| 450 | return sd_eofbepos_16.rep[ind]; | ||
| 451 | } | ||
| 452 | |||
| 453 | static Cube | ||
| 454 | antindex_drud_sym16(uint64_t ind) | ||
| 455 | { | ||
| 456 | Cube c; | ||
| 457 | |||
| 458 | c = sd_eofbepos_16.rep[ind/POW3TO7]; | ||
| 459 | c.coud = ind % POW3TO7; | ||
| 460 | c.cofb = c.coud; | ||
| 461 | c.corl = c.coud; | ||
| 462 | |||
| 463 | return c; | ||
| 464 | } | ||
| 465 | |||
| 466 | static Cube | ||
| 467 | antindex_khuge(uint64_t ind) | ||
| 468 | { | ||
| 469 | Cube c; | ||
| 470 | |||
| 471 | c = sd_eofbepos_16.rep[ind/(FACTORIAL4*POW3TO7)]; | ||
| 472 | c.epose = ((c.epose / 24) * 24) + ((ind/POW3TO7) % 24); | ||
| 473 | c.coud = ind % POW3TO7; | ||
| 474 | |||
| 475 | return c; | ||
| 476 | } | ||
| 477 | |||
| 478 | |||
| 479 | /* Checkers ******************************************************************/ | ||
| 480 | |||
| 481 | bool | ||
| 482 | check_centers(Cube cube) | ||
| 483 | { | ||
| 484 | return cube.cpos == 0; | ||
| 485 | } | ||
| 486 | |||
| 487 | bool | ||
| 488 | check_corners(Cube cube) | ||
| 489 | { | ||
| 490 | return cube.cp == 0 && cube.coud == 0; | ||
| 491 | } | ||
| 492 | |||
| 493 | bool | ||
| 494 | check_cornershtr(Cube cube) | ||
| 495 | { | ||
| 496 | return cube.coud == 0 && cphtr(cube) == 0; /* TODO: use array cphtrcosets*/ | ||
| 497 | } | ||
| 498 | |||
| 499 | bool | ||
| 500 | check_coud(Cube cube) | ||
| 501 | { | ||
| 502 | return cube.coud == 0; | ||
| 503 | } | ||
| 504 | |||
| 505 | bool | ||
| 506 | check_drud(Cube cube) | ||
| 507 | { | ||
| 508 | return cube.eofb == 0 && cube.eorl == 0 && cube.coud == 0; | ||
| 509 | } | ||
| 510 | |||
| 511 | bool | ||
| 512 | check_eofb(Cube cube) | ||
| 513 | { | ||
| 514 | return cube.eofb == 0; | ||
| 515 | } | ||
| 516 | |||
| 517 | bool | ||
| 518 | check_eofbepos(Cube cube) | ||
| 519 | { | ||
| 520 | return cube.eofb == 0 && cube.epose / 24 == 0; | ||
| 521 | } | ||
| 522 | |||
| 523 | bool | ||
| 524 | check_epose(Cube cube) | ||
| 525 | { | ||
| 526 | return cube.epose == 0; | ||
| 527 | } | ||
| 528 | |||
| 529 | bool | ||
| 530 | check_ep(Cube cube) | ||
| 531 | { | ||
| 532 | return cube.epose == 0 && cube.eposs == 0 && cube.eposm == 0; | ||
| 533 | } | ||
| 534 | |||
| 535 | bool | ||
| 536 | check_khuge(Cube cube) | ||
| 537 | { | ||
| 538 | return check_drud(cube) && cube.epose % 24 == 0; | ||
| 539 | } | ||
| 540 | |||
| 541 | bool | ||
| 542 | check_nothing(Cube cube) | ||
| 543 | { | ||
| 544 | return is_admissible(cube); /*TODO: maybe change?*/ | ||
| 545 | } | ||
| 546 | |||
| 547 | /* Movesets ******************************************************************/ | ||
| 548 | |||
| 549 | bool | ||
| 550 | moveset_HTM(Move m) | ||
| 551 | { | ||
| 552 | return m >= U && m <= B3; | ||
| 553 | } | ||
| 554 | |||
| 555 | bool | ||
| 556 | moveset_URF(Move m) | ||
| 557 | { | ||
| 558 | Move b = base_move(m); | ||
| 559 | |||
| 560 | return b == U || b == R || b == F; | ||
| 561 | } | ||
| 562 | |||
| 563 | |||
| 564 | /* Local functions implementation ********************************************/ | ||
| 565 | |||
| 566 | /* TODO: this should be an anti index (maybe?) */ | ||
| 567 | static Cube | ||
| 568 | admissible_ep(Cube cube, PieceFilter f) | ||
| 569 | { | ||
| 570 | CubeArray *arr = new_cubearray(cube, f); | ||
| 571 | Cube ret; | ||
| 572 | bool used[12] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; | ||
| 573 | int i, j; | ||
| 574 | |||
| 575 | for (i = 0; i < 12; i++) | ||
| 576 | if (arr->ep[i] != -1) | ||
| 577 | used[arr->ep[i]] = true; | ||
| 578 | |||
| 579 | for (i = 0, j = 0; i < 12; i++) { | ||
| 580 | for ( ; j < 11 && used[j]; j++); | ||
| 581 | if (arr->ep[i] == -1) | ||
| 582 | arr->ep[i] = j++; | ||
| 583 | } | ||
| 584 | |||
| 585 | ret = arrays_to_cube(arr, pf_ep); | ||
| 586 | free_cubearray(arr, f); | ||
| 587 | |||
| 588 | return ret; | ||
| 589 | } | ||
| 590 | |||
| 591 | static Cube | ||
| 592 | admissible_eos_from_eofbepos(Cube cube) | ||
| 593 | { | ||
| 594 | Edge e; | ||
| 595 | Cube ret; | ||
| 596 | CubeArray *arr = new_cubearray(cube, pf_all); | ||
| 597 | |||
| 598 | memcpy(arr->eorl, arr->eofb, 12 * sizeof(int)); | ||
| 599 | memcpy(arr->eoud, arr->eofb, 12 * sizeof(int)); | ||
| 600 | |||
| 601 | for (e = 0; e < 12; e++) { | ||
| 602 | if ((edge_slice(e) != 0 && edge_slice(arr->ep[e]) == 0) || | ||
| 603 | (edge_slice(e) == 0 && edge_slice(arr->ep[e]) != 0)) | ||
| 604 | arr->eorl[e] = 1 - arr->eorl[e]; | ||
| 605 | if ((edge_slice(e) != 2 && edge_slice(arr->ep[e]) == 2) || | ||
| 606 | (edge_slice(e) == 2 && edge_slice(arr->ep[e]) != 2)) | ||
| 607 | arr->eoud[e] = 1 - arr->eoud[e]; | ||
| 608 | } | ||
| 609 | |||
| 610 | ret = arrays_to_cube(arr, pf_all); | ||
| 611 | free_cubearray(arr, pf_all); | ||
| 612 | |||
| 613 | return ret; | ||
| 614 | } | ||
| 615 | |||
| 616 | static bool | ||
| 617 | allowed_next(Move move, DfsData *dd) | ||
| 618 | { | ||
| 619 | if (!possible_next[dd->last2][dd->last1][move]) | ||
| 620 | return false; | ||
| 621 | |||
| 622 | if (commute[dd->last1][move]) | ||
| 623 | return dd->move_position[dd->last1] < dd->move_position[move]; | ||
| 624 | |||
| 625 | return true; | ||
| 626 | } | ||
| 627 | |||
| 628 | static void | ||
| 629 | append_alg(AlgList *l, Alg *alg) | ||
| 630 | { | ||
| 631 | AlgListNode *node = malloc(sizeof(AlgListNode)); | ||
| 632 | int i; | ||
| 633 | |||
| 634 | node->alg = new_alg(""); | ||
| 635 | for (i = 0; i < alg->len; i++) | ||
| 636 | append_move(node->alg, alg->move[i], alg->inv[i]); | ||
| 637 | node->next = NULL; | ||
| 638 | |||
| 639 | if (++l->len == 1) | ||
| 640 | l->first = node; | ||
| 641 | else | ||
| 642 | l->last->next = node; | ||
| 643 | l->last = node; | ||
| 644 | } | ||
| 645 | |||
| 646 | static void | ||
| 647 | append_move(Alg *alg, Move m, bool inverse) | ||
| 648 | { | ||
| 649 | if (alg->len == alg->allocated) | ||
| 650 | realloc_alg(alg, 2*alg->len); | ||
| 651 | |||
| 652 | alg->move[alg->len] = m; | ||
| 653 | alg->inv [alg->len] = inverse; | ||
| 654 | alg->len++; | ||
| 655 | } | ||
| 656 | |||
| 657 | static Cube | ||
| 658 | apply_alg_generic(Alg *alg, Cube c, PieceFilter f, bool a) | ||
| 659 | { | ||
| 660 | Cube ret = {0}; | ||
| 661 | int i; | ||
| 662 | |||
| 663 | for (i = 0; i < alg->len; i++) | ||
| 664 | if (alg->inv[i]) | ||
| 665 | ret = a ? apply_move(alg->move[i], ret) : | ||
| 666 | apply_move_cubearray(alg->move[i], ret, f); | ||
| 667 | |||
| 668 | ret = compose_filtered(c, inverse_cube(ret), f); | ||
| 669 | |||
| 670 | for (i = 0; i < alg->len; i++) | ||
| 671 | if (!alg->inv[i]) | ||
| 672 | ret = a ? apply_move(alg->move[i], ret) : | ||
| 673 | apply_move_cubearray(alg->move[i], ret, f); | ||
| 674 | |||
| 675 | return ret; | ||
| 676 | } | ||
| 677 | |||
| 678 | static void | ||
| 679 | apply_permutation(int *perm, int *set, int n) | ||
| 680 | { | ||
| 681 | int *aux = malloc(n * sizeof(int)); | ||
| 682 | int i; | ||
| 683 | |||
| 684 | if (!is_perm(perm, n)) | ||
| 685 | return; | ||
| 686 | |||
| 687 | for (i = 0; i < n; i++) | ||
| 688 | aux[i] = set[perm[i]]; | ||
| 689 | |||
| 690 | memcpy(set, aux, n * sizeof(int)); | ||
| 691 | free(aux); | ||
| 692 | } | ||
| 693 | |||
| 694 | static Cube | ||
| 695 | apply_move_cubearray(Move m, Cube cube, PieceFilter f) | ||
| 696 | { | ||
| 697 | CubeArray m_arr = { | ||
| 698 | edge_cycle[m], | ||
| 699 | eofb_flipped[m], | ||
| 700 | eorl_flipped[m], | ||
| 701 | eoud_flipped[m], | ||
| 702 | corner_cycle[m], | ||
| 703 | coud_flipped[m], | ||
| 704 | corl_flipped[m], | ||
| 705 | cofb_flipped[m], | ||
| 706 | center_cycle[m] | ||
| 707 | }; | ||
| 708 | |||
| 709 | return move_via_arrays(&m_arr, cube, f); | ||
| 710 | } | ||
| 711 | |||
| 712 | static int | ||
| 713 | array_ep_to_epos(int *ep, int *ss) | ||
| 714 | { | ||
| 715 | int epos[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; | ||
| 716 | int eps[4]; | ||
| 717 | int i, j, is; | ||
| 718 | |||
| 719 | for (i = 0, is = 0; i < 12; i++) { | ||
| 720 | for (j = 0; j < 4; j++) { | ||
| 721 | if (ep[i] == ss[j]) { | ||
| 722 | eps[is++] = j; | ||
| 723 | epos[i] = 1; | ||
| 724 | } | ||
| 725 | } | ||
| 726 | } | ||
| 727 | |||
| 728 | for (i = 0; i < 4; i++) | ||
| 729 | swap(&epos[ss[i]], &epos[i+8]); | ||
| 730 | |||
| 731 | return epos_from_arrays(epos, eps); | ||
| 732 | } | ||
| 733 | |||
| 734 | static Cube | ||
| 735 | arrays_to_cube(CubeArray *arr, PieceFilter f) | ||
| 736 | { | ||
| 737 | Cube ret = {0}; | ||
| 738 | |||
| 739 | if (f.epose) | ||
| 740 | ret.epose = array_ep_to_epos(arr->ep, epe_solved); | ||
| 741 | if (f.eposs) | ||
| 742 | ret.eposs = array_ep_to_epos(arr->ep, eps_solved); | ||
| 743 | if (f.eposm) | ||
| 744 | ret.eposm = array_ep_to_epos(arr->ep, epm_solved); | ||
| 745 | if (f.eofb) | ||
| 746 | ret.eofb = digit_array_to_int(arr->eofb, 11, 2); | ||
| 747 | if (f.eorl) | ||
| 748 | ret.eorl = digit_array_to_int(arr->eorl, 11, 2); | ||
| 749 | if (f.eoud) | ||
| 750 | ret.eoud = digit_array_to_int(arr->eoud, 11, 2); | ||
| 751 | if (f.cp) | ||
| 752 | ret.cp = perm_to_index(arr->cp, 8); | ||
| 753 | if (f.coud) | ||
| 754 | ret.coud = digit_array_to_int(arr->coud, 7, 3); | ||
| 755 | if (f.corl) | ||
| 756 | ret.corl = digit_array_to_int(arr->corl, 7, 3); | ||
| 757 | if (f.cofb) | ||
| 758 | ret.cofb = digit_array_to_int(arr->cofb, 7, 3); | ||
| 759 | if (f.cpos) | ||
| 760 | ret.cpos = perm_to_index(arr->cpos, 6); | ||
| 761 | |||
| 762 | return ret; | ||
| 763 | } | ||
| 764 | |||
| 765 | static int | ||
| 766 | binomial(int n, int k) | ||
| 767 | { | ||
| 768 | if (n < 0 || k < 0 || k > n) | ||
| 769 | return 0; | ||
| 770 | |||
| 771 | return factorial(n) / (factorial(k) * factorial(n-k)); | ||
| 772 | } | ||
| 773 | |||
| 774 | static Cube | ||
| 775 | compose_filtered(Cube c2, Cube c1, PieceFilter f) | ||
| 776 | { | ||
| 777 | CubeArray *arr = new_cubearray(c2, f); | ||
| 778 | Cube ret; | ||
| 779 | |||
| 780 | ret = move_via_arrays(arr, c1, f); | ||
| 781 | free_cubearray(arr, f); | ||
| 782 | |||
| 783 | return ret; | ||
| 784 | } | ||
| 785 | |||
| 786 | static void | ||
| 787 | cube_to_arrays(Cube cube, CubeArray *arr, PieceFilter f) | ||
| 788 | { | ||
| 789 | int i; | ||
| 790 | |||
| 791 | if (f.epose || f.eposs || f.eposm) | ||
| 792 | for (i = 0; i < 12; i++) | ||
| 793 | arr->ep[i] = -1; | ||
| 794 | |||
| 795 | if (f.epose) | ||
| 796 | epos_to_partial_ep(cube.epose, arr->ep, epe_solved); | ||
| 797 | if (f.eposs) | ||
| 798 | epos_to_partial_ep(cube.eposs, arr->ep, eps_solved); | ||
| 799 | if (f.eposm) | ||
| 800 | epos_to_partial_ep(cube.eposm, arr->ep, epm_solved); | ||
| 801 | if (f.eofb) | ||
| 802 | int_to_sum_zero_array(cube.eofb, 2, 12, arr->eofb); | ||
| 803 | if (f.eorl) | ||
| 804 | int_to_sum_zero_array(cube.eorl, 2, 12, arr->eorl); | ||
| 805 | if (f.eoud) | ||
| 806 | int_to_sum_zero_array(cube.eoud, 2, 12, arr->eoud); | ||
| 807 | if (f.cp) | ||
| 808 | index_to_perm(cube.cp, 8, arr->cp); | ||
| 809 | if (f.coud) | ||
| 810 | int_to_sum_zero_array(cube.coud, 3, 8, arr->coud); | ||
| 811 | if (f.corl) | ||
| 812 | int_to_sum_zero_array(cube.corl, 3, 8, arr->corl); | ||
| 813 | if (f.cofb) | ||
| 814 | int_to_sum_zero_array(cube.cofb, 3, 8, arr->cofb); | ||
| 815 | if (f.cpos) | ||
| 816 | index_to_perm(cube.cpos, 6, arr->cpos); | ||
| 817 | } | ||
| 818 | |||
| 819 | /* | ||
| 820 | static int | ||
| 821 | cphtr_cp(int cp) | ||
| 822 | { | ||
| 823 | int i, a[8]; | ||
| 824 | |||
| 825 | index_to_perm(cp, 8, a); | ||
| 826 | |||
| 827 | for (i = 0; i < 8; i++) | ||
| 828 | if (a[i] == UFR || a[i] == UBL || a[i] == DFL || a[i] == DBR) | ||
| 829 | a[i] = 0; | ||
| 830 | else | ||
| 831 | a[i] = 1; | ||
| 832 | |||
| 833 | swap(&a[1], &a[5]); | ||
| 834 | swap(&a[3], &a[7]); | ||
| 835 | |||
| 836 | return subset_to_index(a, 8, 4); | ||
| 837 | } | ||
| 838 | */ | ||
| 839 | |||
| 840 | static void | ||
| 841 | dfs(Cube c, Step s, SolveOptions *opts, DfsData *dd) | ||
| 842 | { | ||
| 843 | if (dfs_stop(c, s, opts, dd)) | ||
| 844 | return; | ||
| 845 | |||
| 846 | if (dfs_check_solved(opts, dd)) | ||
| 847 | return; | ||
| 848 | |||
| 849 | dfs_branch(c, s, opts, dd); | ||
| 850 | |||
| 851 | if (opts->can_niss && !dd->niss) | ||
| 852 | dfs_niss(c, s, opts, dd); | ||
| 853 | } | ||
| 854 | |||
| 855 | static void | ||
| 856 | dfs_branch(Cube c, Step s, SolveOptions *opts, DfsData *dd) | ||
| 857 | { | ||
| 858 | Move m, l1 = dd->last1, l2 = dd->last2, *moves = dd->sorted_moves; | ||
| 859 | |||
| 860 | int i, maxnsol = opts->max_solutions; | ||
| 861 | |||
| 862 | for (i = 0; moves[i] != NULLMOVE && dd->sols->len < maxnsol; i++) { | ||
| 863 | m = moves[i]; | ||
| 864 | if (allowed_next(m, dd)) { | ||
| 865 | dd->last2 = dd->last1; | ||
| 866 | dd->last1 = m; | ||
| 867 | append_move(dd->current_alg, m, dd->niss); | ||
| 868 | |||
| 869 | dfs(apply_move(m, c), s, opts, dd); | ||
| 870 | |||
| 871 | dd->current_alg->len--; | ||
| 872 | dd->last2 = l2; | ||
| 873 | dd->last1 = l1; | ||
| 874 | } | ||
| 875 | } | ||
| 876 | } | ||
| 877 | |||
| 878 | static bool | ||
| 879 | dfs_check_solved(SolveOptions *opts, DfsData *dd) | ||
| 880 | { | ||
| 881 | if (dd->lb != 0) | ||
| 882 | return false; | ||
| 883 | |||
| 884 | if (dd->current_alg->len == dd->d) { | ||
| 885 | append_alg(dd->sols, dd->current_alg); | ||
| 886 | |||
| 887 | if (opts->feedback) | ||
| 888 | print_alg(dd->current_alg, false); | ||
| 889 | } | ||
| 890 | |||
| 891 | return true; | ||
| 892 | } | ||
| 893 | |||
| 894 | static void | ||
| 895 | dfs_niss(Cube c, Step s, SolveOptions *opts, DfsData *dd) | ||
| 896 | { | ||
| 897 | Move l1 = dd->last1, l2 = dd->last2; | ||
| 898 | CubeTarget ct; | ||
| 899 | |||
| 900 | ct.cube = apply_move(inverse_move(l1), (Cube){0}); | ||
| 901 | ct.target = 1; | ||
| 902 | |||
| 903 | if (dd->current_alg->len == 0 || s.estimate(ct)) { | ||
| 904 | dd->niss = true; | ||
| 905 | dd->last1 = NULLMOVE; | ||
| 906 | dd->last2 = NULLMOVE; | ||
| 907 | |||
| 908 | dfs(inverse_cube(c), s, opts, dd); | ||
| 909 | |||
| 910 | dd->last1 = l1; | ||
| 911 | dd->last2 = l2; | ||
| 912 | dd->niss = false; | ||
| 913 | } | ||
| 914 | } | ||
| 915 | |||
| 916 | static bool | ||
| 917 | dfs_stop(Cube c, Step s, SolveOptions *opts, DfsData *dd) | ||
| 918 | { | ||
| 919 | CubeTarget ct = { | ||
| 920 | .cube = c, | ||
| 921 | .target = dd->d - dd->current_alg->len | ||
| 922 | }; | ||
| 923 | |||
| 924 | if (dd->sols->len >= opts->max_solutions) | ||
| 925 | return true; | ||
| 926 | |||
| 927 | dd->lb = s.estimate(ct); | ||
| 928 | if (opts->can_niss && !dd->niss) | ||
| 929 | dd->lb = MIN(1, dd->lb); | ||
| 930 | |||
| 931 | if (dd->current_alg->len + dd->lb > dd->d) | ||
| 932 | return true; | ||
| 933 | |||
| 934 | return false; | ||
| 935 | } | ||
| 936 | |||
| 937 | static int | ||
| 938 | digit_array_to_int(int *a, int n, int b) | ||
| 939 | { | ||
| 940 | int i, ret = 0, p = 1; | ||
| 941 | |||
| 942 | for (i = 0; i < n; i++, p *= b) | ||
| 943 | ret += a[i] * p; | ||
| 944 | |||
| 945 | return ret; | ||
| 946 | } | ||
| 947 | |||
| 948 | static int | ||
| 949 | edge_slice(Edge e) { | ||
| 950 | if (e < 0 || e > 11) | ||
| 951 | return -1; | ||
| 952 | |||
| 953 | if (e == FR || e == FL || e == BL || e == BR) | ||
| 954 | return 0; | ||
| 955 | if (e == UR || e == UL || e == DR || e == DL) | ||
| 956 | return 1; | ||
| 957 | |||
| 958 | return 2; | ||
| 959 | } | ||
| 960 | |||
| 961 | static int | ||
| 962 | epos_dependent_pos(int poss, int pose) | ||
| 963 | { | ||
| 964 | int ep[12] = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}; | ||
| 965 | int ep8[8] = {0, 0, 0, 0, 0, 0, 0, 0}; | ||
| 966 | int i, j; | ||
| 967 | |||
| 968 | epos_to_partial_ep(poss*FACTORIAL4, ep, eps_solved); | ||
| 969 | epos_to_partial_ep(pose*FACTORIAL4, ep, epe_solved); | ||
| 970 | |||
| 971 | for (i = 0, j = 0; i < 12; i++) | ||
| 972 | if (edge_slice(ep[i]) != 0) | ||
| 973 | ep8[j++] = (edge_slice(ep[i]) == 1) ? 1 : 0; | ||
| 974 | |||
| 975 | swap(&ep8[1], &ep8[4]); | ||
| 976 | swap(&ep8[3], &ep8[6]); | ||
| 977 | |||
| 978 | return subset_to_index(ep8, 8, 4); | ||
| 979 | } | ||
| 980 | |||
| 981 | static int | ||
| 982 | epos_from_arrays(int *epos, int *ep) | ||
| 983 | { | ||
| 984 | return FACTORIAL4 * subset_to_index(epos,12,4) + perm_to_index(ep,4); | ||
| 985 | } | ||
| 986 | |||
| 987 | static void | ||
| 988 | epos_to_partial_ep(int epos, int *ep, int *ss) | ||
| 989 | { | ||
| 990 | int i, is, eposs[12], eps[4]; | ||
| 991 | |||
| 992 | index_to_perm(epos % FACTORIAL4, 4, eps); | ||
| 993 | index_to_subset(epos / FACTORIAL4, 12, 4, eposs); | ||
| 994 | |||
| 995 | for (i = 0; i < 4; i++) | ||
| 996 | swap(&eposs[ss[i]], &eposs[i+8]); | ||
| 997 | |||
| 998 | for (i = 0, is = 0; i < 12; i++) | ||
| 999 | if (eposs[i]) | ||
| 1000 | ep[i] = ss[eps[is++]]; | ||
| 1001 | } | ||
| 1002 | |||
| 1003 | static int | ||
| 1004 | factorial(int n) | ||
| 1005 | { | ||
| 1006 | int i, ret = 1; | ||
| 1007 | |||
| 1008 | if (n < 0) | ||
| 1009 | return 0; | ||
| 1010 | |||
| 1011 | for (i = 1; i <= n; i++) | ||
| 1012 | ret *= i; | ||
| 1013 | |||
| 1014 | return ret; | ||
| 1015 | } | ||
| 1016 | |||
| 1017 | void | ||
| 1018 | free_alg(Alg *alg) | ||
| 1019 | { | ||
| 1020 | free(alg->move); | ||
| 1021 | free(alg->inv); | ||
| 1022 | free(alg); | ||
| 1023 | } | ||
| 1024 | |||
| 1025 | void | ||
| 1026 | free_alglist(AlgList *l) | ||
| 1027 | { | ||
| 1028 | AlgListNode *aux, *i = l->first; | ||
| 1029 | |||
| 1030 | while (i != NULL) { | ||
| 1031 | aux = i->next; | ||
| 1032 | free_alglistnode(i); | ||
| 1033 | i = aux; | ||
| 1034 | } | ||
| 1035 | free(l); | ||
| 1036 | } | ||
| 1037 | |||
| 1038 | void | ||
| 1039 | free_alglistnode(AlgListNode *aln) | ||
| 1040 | { | ||
| 1041 | free_alg(aln->alg); | ||
| 1042 | free(aln); | ||
| 1043 | } | ||
| 1044 | |||
| 1045 | static void | ||
| 1046 | free_cubearray(CubeArray *arr, PieceFilter f) | ||
| 1047 | { | ||
| 1048 | if (f.epose || f.eposs || f.eposm) | ||
| 1049 | free(arr->ep); | ||
| 1050 | if (f.eofb) | ||
| 1051 | free(arr->eofb); | ||
| 1052 | if (f.eorl) | ||
| 1053 | free(arr->eorl); | ||
| 1054 | if (f.eoud) | ||
| 1055 | free(arr->eoud); | ||
| 1056 | if (f.cp) | ||
| 1057 | free(arr->cp); | ||
| 1058 | if (f.coud) | ||
| 1059 | free(arr->coud); | ||
| 1060 | if (f.corl) | ||
| 1061 | free(arr->corl); | ||
| 1062 | if (f.cofb) | ||
| 1063 | free(arr->cofb); | ||
| 1064 | if (f.cpos) | ||
| 1065 | free(arr->cpos); | ||
| 1066 | |||
| 1067 | free(arr); | ||
| 1068 | } | ||
| 1069 | |||
| 1070 | static void | ||
| 1071 | genptable_dfs(Cube c, PruneData *pd, DfsData *dd) | ||
| 1072 | { | ||
| 1073 | int oldval = ptableval(pd, c); | ||
| 1074 | |||
| 1075 | if (oldval < dd->m || pd->n == pd->coord->max || | ||
| 1076 | (dd->m != 0 && pd->coord->check(c)) ) | ||
| 1077 | return; | ||
| 1078 | |||
| 1079 | if (dd->m == dd->d) { | ||
| 1080 | if (dd->m < oldval) | ||
| 1081 | ptable_update(pd, c, dd->m); | ||
| 1082 | return; | ||
| 1083 | } | ||
| 1084 | |||
| 1085 | genptable_dfs_branch(c, pd, dd); | ||
| 1086 | } | ||
| 1087 | |||
| 1088 | static void | ||
| 1089 | genptable_dfs_branch(Cube c, PruneData *pd, DfsData *dd) | ||
| 1090 | { | ||
| 1091 | Move i, move, l1 = dd->last1, l2 = dd->last2; | ||
| 1092 | |||
| 1093 | dd->m++; | ||
| 1094 | |||
| 1095 | for (i = 0; dd->sorted_moves[i] != NULLMOVE; i++) { | ||
| 1096 | move = dd->sorted_moves[i]; | ||
| 1097 | if (allowed_next(move, dd)) { | ||
| 1098 | dd->last2 = dd->last1; | ||
| 1099 | dd->last1 = move; | ||
| 1100 | |||
| 1101 | genptable_dfs(apply_move(move, c), pd, dd); | ||
| 1102 | |||
| 1103 | dd->last2 = l2; | ||
| 1104 | dd->last1 = l1; | ||
| 1105 | } | ||
| 1106 | } | ||
| 1107 | |||
| 1108 | dd->m--; | ||
| 1109 | } | ||
| 1110 | |||
| 1111 | static void | ||
| 1112 | gensym(SymData *sd) | ||
| 1113 | { | ||
| 1114 | uint64_t i, in, nreps = 0; | ||
| 1115 | int j; | ||
| 1116 | Cube c, d; | ||
| 1117 | |||
| 1118 | if (sd->generated) | ||
| 1119 | return; | ||
| 1120 | |||
| 1121 | sd->class = malloc(sd->coord->max * sizeof(uint64_t)); | ||
| 1122 | sd->rep = malloc(sd->coord->max * sizeof(Cube)); | ||
| 1123 | sd->transtorep = malloc(sd->coord->max * sizeof(Trans)); | ||
| 1124 | |||
| 1125 | if (read_symdata_file(sd)) { | ||
| 1126 | sd->generated = true; | ||
| 1127 | return; | ||
| 1128 | } | ||
| 1129 | |||
| 1130 | fprintf(stderr, "Cannot load %s, generating it\n", sd->filename); | ||
| 1131 | |||
| 1132 | for (i = 0; i < sd->coord->max; i++) | ||
| 1133 | sd->class[i] = sd->coord->max + 1; | ||
| 1134 | |||
| 1135 | for (i = 0; i < sd->coord->max; i++) { | ||
| 1136 | if (sd->class[i] == sd->coord->max + 1) { | ||
| 1137 | c = sd->coord->cube(i); | ||
| 1138 | sd->rep[nreps] = c; | ||
| 1139 | for (j = 0; j < sd->ntrans; j++) { | ||
| 1140 | d = apply_trans(sd->trans[j], c); | ||
| 1141 | in = sd->coord->index(d); | ||
| 1142 | |||
| 1143 | if (sd->class[in] == sd->coord->max + 1) { | ||
| 1144 | sd->class[in] = nreps; | ||
| 1145 | sd->transtorep[in] = | ||
| 1146 | inverse_trans(sd->trans[j]); | ||
| 1147 | } | ||
| 1148 | } | ||
| 1149 | nreps++; | ||
| 1150 | } | ||
| 1151 | } | ||
| 1152 | |||
| 1153 | sd->sym_coord->max = nreps; | ||
| 1154 | sd->rep = realloc(sd->rep, nreps * sizeof(Cube)); | ||
| 1155 | sd->generated = true; | ||
| 1156 | |||
| 1157 | fprintf(stderr, "Found %lu classes\n", nreps); | ||
| 1158 | |||
| 1159 | if (!write_symdata_file(sd)) | ||
| 1160 | fprintf(stderr, "Error writing SymData file\n"); | ||
| 1161 | |||
| 1162 | return; | ||
| 1163 | } | ||
| 1164 | |||
| 1165 | static void | ||
| 1166 | index_to_perm(int p, int n, int *r) | ||
| 1167 | { | ||
| 1168 | int *a = malloc(n * sizeof(int)); | ||
| 1169 | int i, j, c; | ||
| 1170 | |||
| 1171 | for (i = 0; i < n; i++) | ||
| 1172 | a[i] = 0; | ||
| 1173 | |||
| 1174 | if (p < 0 || p >= factorial(n)) | ||
| 1175 | for (i = 0; i < n; i++) | ||
| 1176 | r[i] = -1; | ||
| 1177 | |||
| 1178 | for (i = 0; i < n; i++) { | ||
| 1179 | c = 0; | ||
| 1180 | j = 0; | ||
| 1181 | while (c <= p / factorial(n-i-1)) | ||
| 1182 | c += a[j++] ? 0 : 1; | ||
| 1183 | r[i] = j-1; | ||
| 1184 | a[j-1] = 1; | ||
| 1185 | p %= factorial(n-i-1); | ||
| 1186 | } | ||
| 1187 | |||
| 1188 | free(a); | ||
| 1189 | } | ||
| 1190 | |||
| 1191 | static void | ||
| 1192 | index_to_subset(int s, int n, int k, int *r) | ||
| 1193 | { | ||
| 1194 | int i, j, v; | ||
| 1195 | |||
| 1196 | if (s < 0 || s >= binomial(n, k)) { | ||
| 1197 | for (i = 0; i < n; i++) | ||
| 1198 | r[i] = -1; | ||
| 1199 | return; | ||
| 1200 | } | ||
| 1201 | |||
| 1202 | for (i = 0; i < n; i++) { | ||
| 1203 | if (k == n-i) { | ||
| 1204 | for (j = i; j < n; j++) | ||
| 1205 | r[j] = 1; | ||
| 1206 | return; | ||
| 1207 | } | ||
| 1208 | |||
| 1209 | if (k == 0) { | ||
| 1210 | for (j = i; j < n; j++) | ||
| 1211 | r[j] = 0; | ||
| 1212 | return; | ||
| 1213 | } | ||
| 1214 | |||
| 1215 | v = binomial(n-i-1, k); | ||
| 1216 | if (s >= v) { | ||
| 1217 | r[i] = 1; | ||
| 1218 | k--; | ||
| 1219 | s -= v; | ||
| 1220 | } else { | ||
| 1221 | r[i] = 0; | ||
| 1222 | } | ||
| 1223 | } | ||
| 1224 | } | ||
| 1225 | |||
| 1226 | static void | ||
| 1227 | int_to_digit_array(int a, int b, int n, int *r) | ||
| 1228 | { | ||
| 1229 | int i; | ||
| 1230 | |||
| 1231 | if (b <= 1) | ||
| 1232 | for (i = 0; i < n; i++) | ||
| 1233 | r[i] = 0; | ||
| 1234 | else | ||
| 1235 | for (i = 0; i < n; i++, a /= b) | ||
| 1236 | r[i] = a % b; | ||
| 1237 | } | ||
| 1238 | |||
| 1239 | static void | ||
| 1240 | int_to_sum_zero_array(int x, int b, int n, int *a) | ||
| 1241 | { | ||
| 1242 | int i, s = 0; | ||
| 1243 | |||
| 1244 | if (b <= 1) { | ||
| 1245 | for (i = 0; i < n; i++) | ||
| 1246 | a[i] = 0; | ||
| 1247 | } else { | ||
| 1248 | int_to_digit_array(x, b, n-1, a); | ||
| 1249 | for (i = 0; i < n - 1; i++) | ||
| 1250 | s = (s + a[i]) % b; | ||
| 1251 | a[n-1] = (b - s) % b; | ||
| 1252 | } | ||
| 1253 | } | ||
| 1254 | |||
| 1255 | static int | ||
| 1256 | invert_digits(int a, int b, int n) | ||
| 1257 | { | ||
| 1258 | int i, ret, *r = malloc(n * sizeof(int)); | ||
| 1259 | |||
| 1260 | int_to_digit_array(a, b, n, r); | ||
| 1261 | for (i = 0; i < n; i++) | ||
| 1262 | r[i] = (b-r[i]) % b; | ||
| 1263 | |||
| 1264 | ret = digit_array_to_int(r, n, b); | ||
| 1265 | free(r); | ||
| 1266 | return ret; | ||
| 1267 | } | ||
| 1268 | |||
| 1269 | static bool | ||
| 1270 | is_perm(int *a, int n) | ||
| 1271 | { | ||
| 1272 | int *aux = malloc(n * sizeof(int)); | ||
| 1273 | int i; | ||
| 1274 | |||
| 1275 | for (i = 0; i < n; i++) | ||
| 1276 | if (a[i] < 0 || a[i] >= n) | ||
| 1277 | return false; | ||
| 1278 | else | ||
| 1279 | aux[a[i]] = 1; | ||
| 1280 | |||
| 1281 | for (i = 0; i < n; i++) | ||
| 1282 | if (!aux[i]) | ||
| 1283 | return false; | ||
| 1284 | |||
| 1285 | free(aux); | ||
| 1286 | |||
| 1287 | return true; | ||
| 1288 | } | ||
| 1289 | |||
| 1290 | static bool | ||
| 1291 | is_subset(int *a, int n, int k) | ||
| 1292 | { | ||
| 1293 | int i, sum = 0; | ||
| 1294 | |||
| 1295 | for (i = 0; i < n; i++) | ||
| 1296 | sum += a[i] ? 1 : 0; | ||
| 1297 | |||
| 1298 | return sum == k; | ||
| 1299 | } | ||
| 1300 | |||
| 1301 | static Cube | ||
| 1302 | move_via_arrays(CubeArray *arr, Cube c, PieceFilter f) | ||
| 1303 | { | ||
| 1304 | CubeArray *arrc = new_cubearray(c, f); | ||
| 1305 | Cube ret; | ||
| 1306 | |||
| 1307 | if (f.epose || f.eposs || f.eposm) | ||
| 1308 | apply_permutation(arr->ep, arrc->ep, 12); | ||
| 1309 | |||
| 1310 | if (f.eofb) { | ||
| 1311 | apply_permutation(arr->ep, arrc->eofb, 12); | ||
| 1312 | sum_arrays_mod(arr->eofb, arrc->eofb, 12, 2); | ||
| 1313 | } | ||
| 1314 | |||
| 1315 | if (f.eorl) { | ||
| 1316 | apply_permutation(arr->ep, arrc->eorl, 12); | ||
| 1317 | sum_arrays_mod(arr->eorl, arrc->eorl, 12, 2); | ||
| 1318 | } | ||
| 1319 | |||
| 1320 | if (f.eoud) { | ||
| 1321 | apply_permutation(arr->ep, arrc->eoud, 12); | ||
| 1322 | sum_arrays_mod(arr->eoud, arrc->eoud, 12, 2); | ||
| 1323 | } | ||
| 1324 | |||
| 1325 | if (f.cp) | ||
| 1326 | apply_permutation(arr->cp, arrc->cp, 8); | ||
| 1327 | |||
| 1328 | if (f.coud) { | ||
| 1329 | apply_permutation(arr->cp, arrc->coud, 8); | ||
| 1330 | sum_arrays_mod(arr->coud, arrc->coud, 8, 3); | ||
| 1331 | } | ||
| 1332 | |||
| 1333 | if (f.corl) { | ||
| 1334 | apply_permutation(arr->cp, arrc->corl, 8); | ||
| 1335 | sum_arrays_mod(arr->corl, arrc->corl, 8, 3); | ||
| 1336 | } | ||
| 1337 | |||
| 1338 | if (f.cofb) { | ||
| 1339 | apply_permutation(arr->cp, arrc->cofb, 8); | ||
| 1340 | sum_arrays_mod(arr->cofb, arrc->cofb, 8, 3); | ||
| 1341 | } | ||
| 1342 | |||
| 1343 | if (f.cpos) | ||
| 1344 | apply_permutation(arr->cpos, arrc->cpos, 6); | ||
| 1345 | |||
| 1346 | ret = arrays_to_cube(arrc, f); | ||
| 1347 | free_cubearray(arrc, f); | ||
| 1348 | |||
| 1349 | return ret; | ||
| 1350 | } | ||
| 1351 | |||
| 1352 | static void | ||
| 1353 | movelist_to_position(Move *movelist, int *position) | ||
| 1354 | { | ||
| 1355 | Move m; | ||
| 1356 | |||
| 1357 | for (m = 0; m < NMOVES && movelist[m] != NULLMOVE; m++) | ||
| 1358 | position[movelist[m]] = m; | ||
| 1359 | } | ||
| 1360 | |||
| 1361 | static void | ||
| 1362 | moveset_to_list(Moveset ms, Estimator f, Move *r) | ||
| 1363 | { | ||
| 1364 | CubeTarget ct = { .target = 1 }; | ||
| 1365 | int b[NMOVES]; | ||
| 1366 | int na = 0, nb = 0; | ||
| 1367 | Move i; | ||
| 1368 | |||
| 1369 | if (ms == NULL) { | ||
| 1370 | fprintf(stderr, "Error: no moveset given\n"); | ||
| 1371 | return; | ||
| 1372 | } | ||
| 1373 | |||
| 1374 | for (i = U; i < NMOVES; i++) { | ||
| 1375 | if (ms(i)) { | ||
| 1376 | ct.cube = apply_move(i, (Cube){0}); | ||
| 1377 | if (f != NULL && f(ct)) | ||
| 1378 | r[na++] = i; | ||
| 1379 | else | ||
| 1380 | b[nb++] = i; | ||
| 1381 | } | ||
| 1382 | } | ||
| 1383 | |||
| 1384 | memcpy(r + na, b, nb * sizeof(Move)); | ||
| 1385 | r[na+nb] = NULLMOVE; | ||
| 1386 | } | ||
| 1387 | |||
| 1388 | static AlgList * | ||
| 1389 | new_alglist() | ||
| 1390 | { | ||
| 1391 | AlgList *ret = malloc(sizeof(AlgList)); | ||
| 1392 | |||
| 1393 | ret->len = 0; | ||
| 1394 | ret->first = NULL; | ||
| 1395 | ret->last = NULL; | ||
| 1396 | |||
| 1397 | return ret; | ||
| 1398 | } | ||
| 1399 | |||
| 1400 | static CubeArray * | ||
| 1401 | new_cubearray(Cube cube, PieceFilter f) | ||
| 1402 | { | ||
| 1403 | CubeArray *arr = malloc(sizeof(CubeArray)); | ||
| 1404 | |||
| 1405 | if (f.epose || f.eposs || f.eposm) | ||
| 1406 | arr->ep = malloc(12 * sizeof(int)); | ||
| 1407 | if (f.eofb) | ||
| 1408 | arr->eofb = malloc(12 * sizeof(int)); | ||
| 1409 | if (f.eorl) | ||
| 1410 | arr->eorl = malloc(12 * sizeof(int)); | ||
| 1411 | if (f.eoud) | ||
| 1412 | arr->eoud = malloc(12 * sizeof(int)); | ||
| 1413 | if (f.cp) | ||
| 1414 | arr->cp = malloc(8 * sizeof(int)); | ||
| 1415 | if (f.coud) | ||
| 1416 | arr->coud = malloc(8 * sizeof(int)); | ||
| 1417 | if (f.corl) | ||
| 1418 | arr->corl = malloc(8 * sizeof(int)); | ||
| 1419 | if (f.cofb) | ||
| 1420 | arr->cofb = malloc(8 * sizeof(int)); | ||
| 1421 | if (f.cpos) | ||
| 1422 | arr->cpos = malloc(6 * sizeof(int)); | ||
| 1423 | |||
| 1424 | cube_to_arrays(cube, arr, f); | ||
| 1425 | |||
| 1426 | return arr; | ||
| 1427 | } | ||
| 1428 | |||
| 1429 | static int | ||
| 1430 | perm_sign(int *a, int n) | ||
| 1431 | { | ||
| 1432 | int i, j, ret = 0; | ||
| 1433 | |||
| 1434 | if (!is_perm(a,n)) | ||
| 1435 | return -1; | ||
| 1436 | |||
| 1437 | for (i = 0; i < n; i++) | ||
| 1438 | for (j = i+1; j < n; j++) | ||
| 1439 | ret += (a[i] > a[j]) ? 1 : 0; | ||
| 1440 | |||
| 1441 | return ret % 2; | ||
| 1442 | } | ||
| 1443 | |||
| 1444 | static int | ||
| 1445 | perm_to_index(int *a, int n) | ||
| 1446 | { | ||
| 1447 | int i, j, c, ret = 0; | ||
| 1448 | |||
| 1449 | if (!is_perm(a, n)) | ||
| 1450 | return -1; | ||
| 1451 | |||
| 1452 | for (i = 0; i < n; i++) { | ||
| 1453 | c = 0; | ||
| 1454 | for (j = i+1; j < n; j++) | ||
| 1455 | c += (a[i] > a[j]) ? 1 : 0; | ||
| 1456 | ret += factorial(n-i-1) * c; | ||
| 1457 | } | ||
| 1458 | |||
| 1459 | return ret; | ||
| 1460 | } | ||
| 1461 | |||
| 1462 | static int | ||
| 1463 | powint(int a, int b) | ||
| 1464 | { | ||
| 1465 | if (b < 0) | ||
| 1466 | return 0; | ||
| 1467 | if (b == 0) | ||
| 1468 | return 1; | ||
| 1469 | |||
| 1470 | if (b % 2) | ||
| 1471 | return a * powint(a, b-1); | ||
| 1472 | else | ||
| 1473 | return powint(a*a, b/2); | ||
| 1474 | } | ||
| 1475 | |||
| 1476 | static void | ||
| 1477 | ptable_update(PruneData *pd, Cube cube, int n) | ||
| 1478 | { | ||
| 1479 | uint64_t ind = pd->coord->index(cube); | ||
| 1480 | uint8_t oldval2 = pd->ptable[ind/2]; | ||
| 1481 | int other = (ind % 2) ? oldval2 % 16 : oldval2 / 16; | ||
| 1482 | |||
| 1483 | pd->ptable[ind/2] = (ind % 2) ? 16*n + other : 16*other + n; | ||
| 1484 | pd->n++; | ||
| 1485 | } | ||
| 1486 | |||
| 1487 | static void | ||
| 1488 | realloc_alg(Alg *alg, int n) | ||
| 1489 | { | ||
| 1490 | if (alg == NULL) { | ||
| 1491 | fprintf(stderr, "Error: trying to reallocate NULL alg.\n"); | ||
| 1492 | return; | ||
| 1493 | } | ||
| 1494 | |||
| 1495 | if (n < alg->len) { | ||
| 1496 | fprintf(stderr, "Error: alg too long for reallocation "); | ||
| 1497 | fprintf(stderr, "(%d vs %d)\n", alg->len, n); | ||
| 1498 | return; | ||
| 1499 | } | ||
| 1500 | |||
| 1501 | if (n > 1000000) { | ||
| 1502 | fprintf(stderr, "Warning: very long alg,"); | ||
| 1503 | fprintf(stderr, "something might go wrong.\n"); | ||
| 1504 | } | ||
| 1505 | |||
| 1506 | alg->move = realloc(alg->move, n * sizeof(int)); | ||
| 1507 | alg->inv = realloc(alg->inv, n * sizeof(int)); | ||
| 1508 | alg->allocated = n; | ||
| 1509 | } | ||
| 1510 | |||
| 1511 | static bool | ||
| 1512 | read_mtables_file() | ||
| 1513 | { | ||
| 1514 | FILE *f; | ||
| 1515 | char fname[strlen(tabledir)+20]; | ||
| 1516 | int m, b = sizeof(int); | ||
| 1517 | bool r = true; | ||
| 1518 | |||
| 1519 | strcpy(fname, tabledir); | ||
| 1520 | strcat(fname, "/mtables"); | ||
| 1521 | |||
| 1522 | if ((f = fopen(fname, "rb")) == NULL) | ||
| 1523 | return false; | ||
| 1524 | |||
| 1525 | for (m = 0; m < NMOVES; m++) { | ||
| 1526 | r = r && fread(epose_mtable[m], b, me[0], f) == me[0]; | ||
| 1527 | r = r && fread(eposs_mtable[m], b, me[1], f) == me[1]; | ||
| 1528 | r = r && fread(eposm_mtable[m], b, me[2], f) == me[2]; | ||
| 1529 | r = r && fread(eofb_mtable[m], b, me[3], f) == me[3]; | ||
| 1530 | r = r && fread(eorl_mtable[m], b, me[4], f) == me[4]; | ||
| 1531 | r = r && fread(eoud_mtable[m], b, me[5], f) == me[5]; | ||
| 1532 | r = r && fread(cp_mtable[m], b, me[6], f) == me[6]; | ||
| 1533 | r = r && fread(coud_mtable[m], b, me[7], f) == me[7]; | ||
| 1534 | r = r && fread(corl_mtable[m], b, me[8], f) == me[8]; | ||
| 1535 | r = r && fread(cofb_mtable[m], b, me[9], f) == me[9]; | ||
| 1536 | r = r && fread(cpos_mtable[m], b, me[10], f) == me[10]; | ||
| 1537 | } | ||
| 1538 | |||
| 1539 | fclose(f); | ||
| 1540 | return r; | ||
| 1541 | } | ||
| 1542 | |||
| 1543 | static bool | ||
| 1544 | read_ptable_file(PruneData *pd) | ||
| 1545 | { | ||
| 1546 | FILE *f; | ||
| 1547 | char fname[strlen(tabledir)+100]; | ||
| 1548 | uint64_t r; | ||
| 1549 | |||
| 1550 | strcpy(fname, tabledir); | ||
| 1551 | strcat(fname, "/"); | ||
| 1552 | strcat(fname, pd->filename); | ||
| 1553 | |||
| 1554 | if ((f = fopen(fname, "rb")) == NULL) | ||
| 1555 | return false; | ||
| 1556 | |||
| 1557 | r = fread(pd->ptable, sizeof(uint8_t), ptablesize(pd), f); | ||
| 1558 | fclose(f); | ||
| 1559 | |||
| 1560 | return r == ptablesize(pd); | ||
| 1561 | } | ||
| 1562 | |||
| 1563 | static bool | ||
| 1564 | read_symdata_file(SymData *sd) | ||
| 1565 | { | ||
| 1566 | FILE *f; | ||
| 1567 | char fname[strlen(tabledir)+100]; | ||
| 1568 | uint64_t n = sd->coord->max, *sn = &sd->sym_coord->max; | ||
| 1569 | bool r = true; | ||
| 1570 | |||
| 1571 | strcpy(fname, tabledir); | ||
| 1572 | strcat(fname, "/"); | ||
| 1573 | strcat(fname, sd->filename); | ||
| 1574 | |||
| 1575 | if ((f = fopen(fname, "rb")) == NULL) | ||
| 1576 | return false; | ||
| 1577 | |||
| 1578 | r = r && fread(&sd->sym_coord->max, sizeof(uint64_t), 1, f) == 1; | ||
| 1579 | r = r && fread(sd->rep, sizeof(Cube), *sn, f) == *sn; | ||
| 1580 | r = r && fread(sd->class, sizeof(uint64_t), n, f) == n; | ||
| 1581 | r = r && fread(sd->transtorep, sizeof(Trans), n, f) == n; | ||
| 1582 | |||
| 1583 | fclose(f); | ||
| 1584 | return r; | ||
| 1585 | } | ||
| 1586 | |||
| 1587 | static bool | ||
| 1588 | read_ttables_file() | ||
| 1589 | { | ||
| 1590 | FILE *f; | ||
| 1591 | char fname[strlen(tabledir)+20]; | ||
| 1592 | int b = sizeof(int); | ||
| 1593 | bool r = true; | ||
| 1594 | Move m; | ||
| 1595 | |||
| 1596 | strcpy(fname, tabledir); | ||
| 1597 | strcat(fname, "/"); | ||
| 1598 | strcat(fname, "ttables"); | ||
| 1599 | |||
| 1600 | if ((f = fopen(fname, "rb")) == NULL) | ||
| 1601 | return false; | ||
| 1602 | |||
| 1603 | for (m = 0; m < NTRANS; m++) { | ||
| 1604 | r = r && fread(epose_ttable[m], b, me[0], f) == me[0]; | ||
| 1605 | r = r && fread(eposs_ttable[m], b, me[1], f) == me[1]; | ||
| 1606 | r = r && fread(eposm_ttable[m], b, me[2], f) == me[2]; | ||
| 1607 | r = r && fread(eo_ttable[m], b, me[3], f) == me[3]; | ||
| 1608 | r = r && fread(cp_ttable[m], b, me[6], f) == me[6]; | ||
| 1609 | r = r && fread(co_ttable[m], b, me[7], f) == me[7]; | ||
| 1610 | r = r && fread(cpos_ttable[m], b, me[10], f) == me[10]; | ||
| 1611 | r = r && fread(moves_ttable[m], b, me[11], f) == me[11]; | ||
| 1612 | } | ||
| 1613 | |||
| 1614 | fclose(f); | ||
| 1615 | return r; | ||
| 1616 | } | ||
| 1617 | |||
| 1618 | static Cube | ||
| 1619 | rotate_via_compose(Trans r, Cube c, PieceFilter f) | ||
| 1620 | { | ||
| 1621 | static int zero12[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; | ||
| 1622 | static int zero8[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; | ||
| 1623 | static CubeArray ma = { | ||
| 1624 | .ep = ep_mirror, | ||
| 1625 | .eofb = zero12, | ||
| 1626 | .eorl = zero12, | ||
| 1627 | .eoud = zero12, | ||
| 1628 | .cp = cp_mirror, | ||
| 1629 | .coud = zero8, | ||
| 1630 | .corl = zero8, | ||
| 1631 | .cofb = zero8, | ||
| 1632 | .cpos = cpos_mirror | ||
| 1633 | }; | ||
| 1634 | |||
| 1635 | Alg *inv = inverse_alg(rotation_algs[r % NROTATIONS]); | ||
| 1636 | Cube ret = {0}; | ||
| 1637 | |||
| 1638 | if (r >= NROTATIONS) | ||
| 1639 | ret = move_via_arrays(&ma, ret, f); | ||
| 1640 | ret = apply_alg_generic(inv, ret, f, true); | ||
| 1641 | |||
| 1642 | ret = compose_filtered(c, ret, f); | ||
| 1643 | |||
| 1644 | ret = apply_alg_generic(rotation_algs[r % NROTATIONS], ret, f, true); | ||
| 1645 | if (r >= NROTATIONS) | ||
| 1646 | ret = move_via_arrays(&ma, ret, f); | ||
| 1647 | |||
| 1648 | free_alg(inv); | ||
| 1649 | return ret; | ||
| 1650 | } | ||
| 1651 | |||
| 1652 | static int | ||
| 1653 | subset_to_index(int *a, int n, int k) | ||
| 1654 | { | ||
| 1655 | int i, ret = 0; | ||
| 1656 | |||
| 1657 | if (!is_subset(a, n, k)) | ||
| 1658 | return binomial(n, k); | ||
| 1659 | |||
| 1660 | for (i = 0; i < n; i++) { | ||
| 1661 | if (k == n-i) | ||
| 1662 | return ret; | ||
| 1663 | if (a[i]) { | ||
| 1664 | ret += binomial(n-i-1, k); | ||
| 1665 | k--; | ||
| 1666 | } | ||
| 1667 | } | ||
| 1668 | |||
| 1669 | return ret; | ||
| 1670 | } | ||
| 1671 | |||
| 1672 | static void | ||
| 1673 | sum_arrays_mod(int *src, int *dst, int n, int m) | ||
| 1674 | { | ||
| 1675 | int i; | ||
| 1676 | |||
| 1677 | for (i = 0; i < n; i++) | ||
| 1678 | dst[i] = (m <= 0) ? 0 : (src[i] + dst[i]) % m; | ||
| 1679 | } | ||
| 1680 | |||
| 1681 | static void | ||
| 1682 | swap(int *a, int *b) | ||
| 1683 | { | ||
| 1684 | int aux; | ||
| 1685 | |||
| 1686 | aux = *a; | ||
| 1687 | *a = *b; | ||
| 1688 | *b = aux; | ||
| 1689 | } | ||
| 1690 | |||
| 1691 | static bool | ||
| 1692 | write_mtables_file() | ||
| 1693 | { | ||
| 1694 | FILE *f; | ||
| 1695 | char fname[strlen(tabledir)+20]; | ||
| 1696 | int m, b = sizeof(int); | ||
| 1697 | bool r = true; | ||
| 1698 | |||
| 1699 | strcpy(fname, tabledir); | ||
| 1700 | strcat(fname, "/mtables"); | ||
| 1701 | |||
| 1702 | if ((f = fopen(fname, "wb")) == NULL) | ||
| 1703 | return false; | ||
| 1704 | |||
| 1705 | for (m = 0; m < NMOVES; m++) { | ||
| 1706 | r = r && fwrite(epose_mtable[m], b, me[0], f) == me[0]; | ||
| 1707 | r = r && fwrite(eposs_mtable[m], b, me[1], f) == me[1]; | ||
| 1708 | r = r && fwrite(eposm_mtable[m], b, me[2], f) == me[2]; | ||
| 1709 | r = r && fwrite(eofb_mtable[m], b, me[3], f) == me[3]; | ||
| 1710 | r = r && fwrite(eorl_mtable[m], b, me[4], f) == me[4]; | ||
| 1711 | r = r && fwrite(eoud_mtable[m], b, me[5], f) == me[5]; | ||
| 1712 | r = r && fwrite(cp_mtable[m], b, me[6], f) == me[6]; | ||
| 1713 | r = r && fwrite(coud_mtable[m], b, me[7], f) == me[7]; | ||
| 1714 | r = r && fwrite(corl_mtable[m], b, me[8], f) == me[8]; | ||
| 1715 | r = r && fwrite(cofb_mtable[m], b, me[9], f) == me[9]; | ||
| 1716 | r = r && fwrite(cpos_mtable[m], b, me[10], f) == me[10]; | ||
| 1717 | } | ||
| 1718 | |||
| 1719 | fclose(f); | ||
| 1720 | return r; | ||
| 1721 | } | ||
| 1722 | |||
| 1723 | static bool | ||
| 1724 | write_ptable_file(PruneData *pd) | ||
| 1725 | { | ||
| 1726 | FILE *f; | ||
| 1727 | char fname[strlen(tabledir)+100]; | ||
| 1728 | uint64_t written; | ||
| 1729 | |||
| 1730 | strcpy(fname, tabledir); | ||
| 1731 | strcat(fname, "/"); | ||
| 1732 | strcat(fname, pd->filename); | ||
| 1733 | |||
| 1734 | if ((f = fopen(fname, "wb")) == NULL) | ||
| 1735 | return false; | ||
| 1736 | |||
| 1737 | written = fwrite(pd->ptable, sizeof(uint8_t), ptablesize(pd), f); | ||
| 1738 | fclose(f); | ||
| 1739 | |||
| 1740 | return written == ptablesize(pd); | ||
| 1741 | } | ||
| 1742 | |||
| 1743 | static bool | ||
| 1744 | write_symdata_file(SymData *sd) | ||
| 1745 | { | ||
| 1746 | FILE *f; | ||
| 1747 | char fname[strlen(tabledir)+100]; | ||
| 1748 | uint64_t n = sd->coord->max, *sn = &sd->sym_coord->max; | ||
| 1749 | bool r = true; | ||
| 1750 | |||
| 1751 | strcpy(fname, tabledir); | ||
| 1752 | strcat(fname, "/"); | ||
| 1753 | strcat(fname, sd->filename); | ||
| 1754 | |||
| 1755 | if ((f = fopen(fname, "wb")) == NULL) | ||
| 1756 | return false; | ||
| 1757 | |||
| 1758 | r = r && fwrite(&sd->sym_coord->max, sizeof(uint64_t), 1, f) == 1; | ||
| 1759 | r = r && fwrite(sd->rep, sizeof(Cube), *sn, f) == *sn; | ||
| 1760 | r = r && fwrite(sd->class, sizeof(uint64_t), n, f) == n; | ||
| 1761 | r = r && fwrite(sd->transtorep, sizeof(Trans), n, f) == n; | ||
| 1762 | |||
| 1763 | fclose(f); | ||
| 1764 | return r; | ||
| 1765 | } | ||
| 1766 | |||
| 1767 | static bool | ||
| 1768 | write_ttables_file() | ||
| 1769 | { | ||
| 1770 | FILE *f; | ||
| 1771 | char fname[strlen(tabledir)+20]; | ||
| 1772 | bool r = true; | ||
| 1773 | int b = sizeof(int); | ||
| 1774 | Move m; | ||
| 1775 | |||
| 1776 | strcpy(fname, tabledir); | ||
| 1777 | strcat(fname, "/ttables"); | ||
| 1778 | |||
| 1779 | if ((f = fopen(fname, "wb")) == NULL) | ||
| 1780 | return false; | ||
| 1781 | |||
| 1782 | for (m = 0; m < NTRANS; m++) { | ||
| 1783 | r = r && fwrite(epose_ttable[m], b, me[0], f) == me[0]; | ||
| 1784 | r = r && fwrite(eposs_ttable[m], b, me[1], f) == me[1]; | ||
| 1785 | r = r && fwrite(eposm_ttable[m], b, me[2], f) == me[2]; | ||
| 1786 | r = r && fwrite(eo_ttable[m], b, me[3], f) == me[3]; | ||
| 1787 | r = r && fwrite(cp_ttable[m], b, me[6], f) == me[6]; | ||
| 1788 | r = r && fwrite(co_ttable[m], b, me[7], f) == me[7]; | ||
| 1789 | r = r && fwrite(cpos_ttable[m], b, me[10], f) == me[10]; | ||
| 1790 | r = r && fwrite(moves_ttable[m], b, me[11], f) == me[11]; | ||
| 1791 | } | ||
| 1792 | |||
| 1793 | fclose(f); | ||
| 1794 | return r; | ||
| 1795 | } | ||
| 1796 | |||
| 1797 | /* Init functions implementation *********************************************/ | ||
| 1798 | |||
| 1799 | static void | ||
| 1800 | init_auxtables() | ||
| 1801 | { | ||
| 1802 | Cube c1, c2; | ||
| 1803 | CubeArray *arr; | ||
| 1804 | uint64_t ui, uj; | ||
| 1805 | int i, j, k, auxarr[12]; | ||
| 1806 | bool cij, p1, p2; | ||
| 1807 | |||
| 1808 | for (ui = 0; ui < POW2TO11*BINOM12ON4; ui++) { | ||
| 1809 | k = (ui / POW2TO11) * 24; | ||
| 1810 | c1 = admissible_ep((Cube){ .epose = k }, pf_e); | ||
| 1811 | c1.eofb = ui % POW2TO11; | ||
| 1812 | c1 = admissible_eos_from_eofbepos(c1); | ||
| 1813 | admissible_ee_aux[ui] = c1; | ||
| 1814 | } | ||
| 1815 | |||
| 1816 | for (ui = 0; ui < FACTORIAL6; ui++) { | ||
| 1817 | arr = new_cubearray((Cube){.cpos = ui}, pf_cpos); | ||
| 1818 | for (i = 0; i < 6; i++) { | ||
| 1819 | what_center_at_aux[ui][i] = arr->cpos[i]; | ||
| 1820 | where_is_center_aux[ui][arr->cpos[i]] = i; | ||
| 1821 | } | ||
| 1822 | free_cubearray(arr, pf_cpos); | ||
| 1823 | } | ||
| 1824 | |||
| 1825 | for (ui = 0; ui < FACTORIAL8; ui++) { | ||
| 1826 | arr = new_cubearray((Cube){.cp = ui}, pf_cp); | ||
| 1827 | for (i = 0; i < 8; i++) { | ||
| 1828 | what_corner_at_aux[ui][i] = arr->cp[i]; | ||
| 1829 | where_is_corner_aux[ui][arr->cp[i]] = i; | ||
| 1830 | } | ||
| 1831 | free_cubearray(arr, pf_cp); | ||
| 1832 | } | ||
| 1833 | |||
| 1834 | for (ui = 0; ui < FACTORIAL12/FACTORIAL8; ui++) { | ||
| 1835 | arr = new_cubearray((Cube){.epose = ui}, pf_e); | ||
| 1836 | for (i = 0; i < 12; i++) | ||
| 1837 | if (edge_slice(arr->ep[i]) == 0) | ||
| 1838 | where_is_edge_aux[0][ui][arr->ep[i]] = i; | ||
| 1839 | free_cubearray(arr, pf_e); | ||
| 1840 | |||
| 1841 | arr = new_cubearray((Cube){.eposs = ui}, pf_s); | ||
| 1842 | for (i = 0; i < 12; i++) | ||
| 1843 | if (edge_slice(arr->ep[i]) == 1) | ||
| 1844 | where_is_edge_aux[1][ui][arr->ep[i]] = i; | ||
| 1845 | free_cubearray(arr, pf_s); | ||
| 1846 | |||
| 1847 | arr = new_cubearray((Cube){.eposm = ui}, pf_m); | ||
| 1848 | for (i = 0; i < 12; i++) | ||
| 1849 | if (edge_slice(arr->ep[i]) == 2) | ||
| 1850 | where_is_edge_aux[2][ui][arr->ep[i]] = i; | ||
| 1851 | free_cubearray(arr, pf_m); | ||
| 1852 | } | ||
| 1853 | |||
| 1854 | for (ui = 0; ui < POW3TO7; ui++) { | ||
| 1855 | int_to_sum_zero_array(ui, 3, 8, auxarr); | ||
| 1856 | what_orientation_last_corner_aux[ui] = auxarr[7]; | ||
| 1857 | } | ||
| 1858 | |||
| 1859 | for (ui = 0; ui < POW2TO11; ui++) { | ||
| 1860 | int_to_sum_zero_array(ui, 2, 12, auxarr); | ||
| 1861 | what_orientation_last_edge_aux[ui] = auxarr[11]; | ||
| 1862 | } | ||
| 1863 | |||
| 1864 | for (ui = 0; ui < BINOM12ON4; ui++) | ||
| 1865 | for (uj = 0; uj < BINOM12ON4; uj++) | ||
| 1866 | epos_dependent_aux[ui][uj]=epos_dependent_pos(ui, uj); | ||
| 1867 | |||
| 1868 | for (i = 0; i < NMOVES; i++) { | ||
| 1869 | for (j = 0; j < NMOVES; j++) { | ||
| 1870 | c1 = apply_move(i, apply_move(j, (Cube){0})); | ||
| 1871 | c2 = apply_move(j, apply_move(i, (Cube){0})); | ||
| 1872 | commute[i][j] = equal(c1, c2) && i && j; | ||
| 1873 | } | ||
| 1874 | } | ||
| 1875 | |||
| 1876 | for (i = 0; i < NMOVES; i++) { | ||
| 1877 | for (j = 0; j < NMOVES; j++) { | ||
| 1878 | for (k = 0; k < NMOVES; k++) { | ||
| 1879 | p1 = j && base_move(j) == base_move(k); | ||
| 1880 | p2 = i && base_move(i) == base_move(k); | ||
| 1881 | cij = commute[i][j]; | ||
| 1882 | possible_next[i][j][k] = !(p1 || (cij && p2)); | ||
| 1883 | } | ||
| 1884 | } | ||
| 1885 | } | ||
| 1886 | |||
| 1887 | for (i = 0; i < NMOVES; i++) | ||
| 1888 | inverse_move_aux[i] = i ? i + 2 - 2*((i-1)%3) : NULLMOVE; | ||
| 1889 | |||
| 1890 | /* Is there a more elegant way? */ | ||
| 1891 | inverse_trans_aux[uf] = uf; | ||
| 1892 | inverse_trans_aux[ur] = ul; | ||
| 1893 | inverse_trans_aux[ul] = ur; | ||
| 1894 | inverse_trans_aux[ub] = ub; | ||
| 1895 | |||
| 1896 | inverse_trans_aux[df] = df; | ||
| 1897 | inverse_trans_aux[dr] = dr; | ||
| 1898 | inverse_trans_aux[dl] = dl; | ||
| 1899 | inverse_trans_aux[db] = db; | ||
| 1900 | |||
| 1901 | inverse_trans_aux[rf] = lf; | ||
| 1902 | inverse_trans_aux[rd] = bl; | ||
| 1903 | inverse_trans_aux[rb] = rb; | ||
| 1904 | inverse_trans_aux[ru] = fr; | ||
| 1905 | |||
| 1906 | inverse_trans_aux[lf] = rf; | ||
| 1907 | inverse_trans_aux[ld] = br; | ||
| 1908 | inverse_trans_aux[lb] = lb; | ||
| 1909 | inverse_trans_aux[lu] = fl; | ||
| 1910 | |||
| 1911 | inverse_trans_aux[fu] = fu; | ||
| 1912 | inverse_trans_aux[fr] = ru; | ||
| 1913 | inverse_trans_aux[fd] = bu; | ||
| 1914 | inverse_trans_aux[fl] = lu; | ||
| 1915 | |||
| 1916 | inverse_trans_aux[bu] = fd; | ||
| 1917 | inverse_trans_aux[br] = ld; | ||
| 1918 | inverse_trans_aux[bd] = bd; | ||
| 1919 | inverse_trans_aux[bl] = rd; | ||
| 1920 | |||
| 1921 | inverse_trans_aux[uf_mirror] = uf_mirror; | ||
| 1922 | inverse_trans_aux[ur_mirror] = ur_mirror; | ||
| 1923 | inverse_trans_aux[ul_mirror] = ul_mirror; | ||
| 1924 | inverse_trans_aux[ub_mirror] = ub_mirror; | ||
| 1925 | |||
| 1926 | inverse_trans_aux[df_mirror] = df_mirror; | ||
| 1927 | inverse_trans_aux[dr_mirror] = dl_mirror; | ||
| 1928 | inverse_trans_aux[dl_mirror] = dr_mirror; | ||
| 1929 | inverse_trans_aux[db_mirror] = db_mirror; | ||
| 1930 | |||
| 1931 | inverse_trans_aux[rf_mirror] = rf_mirror; | ||
| 1932 | inverse_trans_aux[rd_mirror] = br_mirror; | ||
| 1933 | inverse_trans_aux[rb_mirror] = lb_mirror; | ||
| 1934 | inverse_trans_aux[ru_mirror] = fl_mirror; | ||
| 1935 | |||
| 1936 | inverse_trans_aux[lf_mirror] = lf_mirror; | ||
| 1937 | inverse_trans_aux[ld_mirror] = bl_mirror; | ||
| 1938 | inverse_trans_aux[lb_mirror] = rb_mirror; | ||
| 1939 | inverse_trans_aux[lu_mirror] = fr_mirror; | ||
| 1940 | |||
| 1941 | inverse_trans_aux[fu_mirror] = fu_mirror; | ||
| 1942 | inverse_trans_aux[fr_mirror] = lu_mirror; | ||
| 1943 | inverse_trans_aux[fd_mirror] = bu_mirror; | ||
| 1944 | inverse_trans_aux[fl_mirror] = ru_mirror; | ||
| 1945 | |||
| 1946 | inverse_trans_aux[bu_mirror] = fd_mirror; | ||
| 1947 | inverse_trans_aux[br_mirror] = rd_mirror; | ||
| 1948 | inverse_trans_aux[bd_mirror] = bd_mirror; | ||
| 1949 | inverse_trans_aux[bl_mirror] = ld_mirror; | ||
| 1950 | } | ||
| 1951 | |||
| 1952 | /* | ||
| 1953 | * There is certainly a bette way to do this, but for now I just use | ||
| 1954 | * a "graph coloring" algorithm to compute the left cosets, and I compose | ||
| 1955 | * with every possible cp to get the right cosets (it is possible that I am | ||
| 1956 | * mixing up left and right). | ||
| 1957 | * | ||
| 1958 | * For doing it better "Mathematically", we need 3 things: | ||
| 1959 | * - Checking that cp separates the orbits (UFR,UBL,DFL,DBR) and the other | ||
| 1960 | * This is easy and it is done in the commented function cphtr_cp(). | ||
| 1961 | * - Check that there is no ep/cp parity | ||
| 1962 | * - Check that we are not in the "3c" case; this is the part I don't | ||
| 1963 | * know how to do. | ||
| 1964 | */ | ||
| 1965 | static void | ||
| 1966 | init_cphtr_cosets() | ||
| 1967 | { | ||
| 1968 | unsigned int i; | ||
| 1969 | int c = 0, d = 0; | ||
| 1970 | |||
| 1971 | for (i = 0; i < FACTORIAL8; i++) { | ||
| 1972 | cphtr_left_cosets[i] = -1; | ||
| 1973 | cphtr_right_cosets[i] = -1; | ||
| 1974 | } | ||
| 1975 | |||
| 1976 | /* First we compute left cosets with a bfs */ | ||
| 1977 | for (i = 0; i < FACTORIAL8; i++) | ||
| 1978 | if (cphtr_left_cosets[i] == -1) | ||
| 1979 | init_cphtr_left_cosets_bfs(i, c++); | ||
| 1980 | |||
| 1981 | /* Then we compute right cosets using compose() */ | ||
| 1982 | for (i = 0; i < FACTORIAL8; i++) | ||
| 1983 | if (cphtr_right_cosets[i] == -1) | ||
| 1984 | init_cphtr_right_cosets_color(i, d++); | ||
| 1985 | } | ||
| 1986 | |||
| 1987 | static void | ||
| 1988 | init_cphtr_left_cosets_bfs(int i, int c) | ||
| 1989 | { | ||
| 1990 | int j, jj, k, next[FACTORIAL8], next2[FACTORIAL8], n, n2; | ||
| 1991 | Move moves[6] = {U2, D2, R2, L2, F2, B2}; | ||
| 1992 | |||
| 1993 | n = 1; | ||
| 1994 | next[0] = i; | ||
| 1995 | cphtr_left_cosets[i] = c; | ||
| 1996 | |||
| 1997 | while (n != 0) { | ||
| 1998 | for (j = 0, n2 = 0; j < n; j++) { | ||
| 1999 | for (k = 0; k < 6; k++) { | ||
| 2000 | jj = cp_mtable[moves[k]][next[j]]; | ||
| 2001 | if (cphtr_left_cosets[jj] == -1) { | ||
| 2002 | cphtr_left_cosets[jj] = c; | ||
| 2003 | next2[n2++] = jj; | ||
| 2004 | } | ||
| 2005 | } | ||
| 2006 | } | ||
| 2007 | |||
| 2008 | for (j = 0; j < n2; j++) | ||
| 2009 | next[j] = next2[j]; | ||
| 2010 | n = n2; | ||
| 2011 | } | ||
| 2012 | } | ||
| 2013 | |||
| 2014 | static void | ||
| 2015 | init_cphtr_right_cosets_color(int i, int d) | ||
| 2016 | { | ||
| 2017 | int cp; | ||
| 2018 | unsigned int j; | ||
| 2019 | |||
| 2020 | cphtr_right_rep[d] = i; | ||
| 2021 | for (j = 0; j < FACTORIAL8; j++) { | ||
| 2022 | if (cphtr_left_cosets[j] == 0) { | ||
| 2023 | /* TODO: use antindexer, it's nicer */ | ||
| 2024 | cp = compose((Cube){.cp = i}, (Cube){.cp = j}).cp; | ||
| 2025 | cphtr_right_cosets[cp] = d; | ||
| 2026 | } | ||
| 2027 | } | ||
| 2028 | } | ||
| 2029 | |||
| 2030 | static void | ||
| 2031 | init_environment() | ||
| 2032 | { | ||
| 2033 | char *nissydata = getenv("NISSYDATA"); | ||
| 2034 | char *localdata = getenv("XDG_DATA_HOME"); | ||
| 2035 | char *home = getenv("HOME"); | ||
| 2036 | bool read, write; | ||
| 2037 | |||
| 2038 | if (nissydata != NULL) { | ||
| 2039 | tabledir = malloc(strlen(nissydata) * sizeof(char) + 20); | ||
| 2040 | strcpy(tabledir, nissydata); | ||
| 2041 | } else if (localdata != NULL) { | ||
| 2042 | tabledir = malloc(strlen(localdata) * sizeof(char) + 20); | ||
| 2043 | strcpy(tabledir, localdata); | ||
| 2044 | strcat(tabledir, "/nissy"); | ||
| 2045 | } else if (home != NULL) { | ||
| 2046 | tabledir = malloc(strlen(home) * sizeof(char) + 20); | ||
| 2047 | strcpy(tabledir, home); | ||
| 2048 | strcat(tabledir, "/.nissy"); | ||
| 2049 | } | ||
| 2050 | |||
| 2051 | mkdir(tabledir, 0777); | ||
| 2052 | strcat(tabledir, "/tables"); | ||
| 2053 | mkdir(tabledir, 0777); | ||
| 2054 | |||
| 2055 | read = !access(tabledir, R_OK); | ||
| 2056 | write = !access(tabledir, W_OK); | ||
| 2057 | |||
| 2058 | if (!read) { | ||
| 2059 | fprintf(stderr, "Table files cannot be read.\n"); | ||
| 2060 | } else if (!write) { | ||
| 2061 | fprintf(stderr, "Data directory not writable: "); | ||
| 2062 | fprintf(stderr, "tables can be loaded, but not saved.\n"); | ||
| 2063 | } | ||
| 2064 | } | ||
| 2065 | |||
| 2066 | static void | ||
| 2067 | init_moves() { | ||
| 2068 | Cube c; | ||
| 2069 | CubeArray arrs; | ||
| 2070 | int i; | ||
| 2071 | unsigned int ui; | ||
| 2072 | Move m; | ||
| 2073 | |||
| 2074 | /* Generate all move cycles and flips; I do this regardless */ | ||
| 2075 | for (i = 0; i < NMOVES; i++) { | ||
| 2076 | if (i == U || i == x || i == y) | ||
| 2077 | continue; | ||
| 2078 | |||
| 2079 | c = apply_alg_generic(equiv_alg[i], (Cube){0}, pf_all, false); | ||
| 2080 | |||
| 2081 | arrs = (CubeArray) { | ||
| 2082 | edge_cycle[i], | ||
| 2083 | eofb_flipped[i], | ||
| 2084 | eorl_flipped[i], | ||
| 2085 | eoud_flipped[i], | ||
| 2086 | corner_cycle[i], | ||
| 2087 | coud_flipped[i], | ||
| 2088 | corl_flipped[i], | ||
| 2089 | cofb_flipped[i], | ||
| 2090 | center_cycle[i] | ||
| 2091 | }; | ||
| 2092 | cube_to_arrays(c, &arrs, pf_all); | ||
| 2093 | } | ||
| 2094 | |||
| 2095 | if (read_mtables_file()) | ||
| 2096 | return; | ||
| 2097 | |||
| 2098 | fprintf(stderr, "Cannot load %s, generating it\n", "mtables"); | ||
| 2099 | |||
| 2100 | /* Initialize transition tables */ | ||
| 2101 | for (m = 0; m < NMOVES; m++) { | ||
| 2102 | for (ui = 0; ui < FACTORIAL12/FACTORIAL8; ui++) { | ||
| 2103 | c = (Cube){ .epose = ui }; | ||
| 2104 | c = apply_move_cubearray(m, c, pf_e); | ||
| 2105 | epose_mtable[m][ui] = c.epose; | ||
| 2106 | |||
| 2107 | c = (Cube){ .eposs = ui }; | ||
| 2108 | c = apply_move_cubearray(m, c, pf_s); | ||
| 2109 | eposs_mtable[m][ui] = c.eposs; | ||
| 2110 | |||
| 2111 | c = (Cube){ .eposm = ui }; | ||
| 2112 | c = apply_move_cubearray(m, c, pf_m); | ||
| 2113 | eposm_mtable[m][ui] = c.eposm; | ||
| 2114 | } | ||
| 2115 | for (ui = 0; ui < POW2TO11; ui++ ) { | ||
| 2116 | c = (Cube){ .eofb = ui }; | ||
| 2117 | c = apply_move_cubearray(m, c, pf_eo); | ||
| 2118 | eofb_mtable[m][ui] = c.eofb; | ||
| 2119 | |||
| 2120 | c = (Cube){ .eorl = ui }; | ||
| 2121 | c = apply_move_cubearray(m, c, pf_eo); | ||
| 2122 | eorl_mtable[m][ui] = c.eorl; | ||
| 2123 | |||
| 2124 | c = (Cube){ .eoud = ui }; | ||
| 2125 | c = apply_move_cubearray(m, c, pf_eo); | ||
| 2126 | eoud_mtable[m][ui] = c.eoud; | ||
| 2127 | } | ||
| 2128 | for (ui = 0; ui < POW3TO7; ui++) { | ||
| 2129 | c = (Cube){ .coud = ui }; | ||
| 2130 | c = apply_move_cubearray(m, c, pf_co); | ||
| 2131 | coud_mtable[m][ui] = c.coud; | ||
| 2132 | |||
| 2133 | c = (Cube){ .corl = ui }; | ||
| 2134 | c = apply_move_cubearray(m, c, pf_co); | ||
| 2135 | corl_mtable[m][ui] = c.corl; | ||
| 2136 | |||
| 2137 | c = (Cube){ .cofb = ui }; | ||
| 2138 | c = apply_move_cubearray(m, c, pf_co); | ||
| 2139 | cofb_mtable[m][ui] = c.cofb; | ||
| 2140 | } | ||
| 2141 | for (ui = 0; ui < FACTORIAL8; ui++) { | ||
| 2142 | c = (Cube){ .cp = ui }; | ||
| 2143 | c = apply_move_cubearray(m, c, pf_cp); | ||
| 2144 | cp_mtable[m][ui] = c.cp; | ||
| 2145 | } | ||
| 2146 | for (ui = 0; ui < FACTORIAL6; ui++) { | ||
| 2147 | c = (Cube){ .cpos = ui }; | ||
| 2148 | c = apply_move_cubearray(m, c, pf_cpos); | ||
| 2149 | cpos_mtable[m][ui] = c.cpos; | ||
| 2150 | } | ||
| 2151 | } | ||
| 2152 | |||
| 2153 | if (!write_mtables_file()) | ||
| 2154 | fprintf(stderr, "Error writing mtables\n"); | ||
| 2155 | } | ||
| 2156 | |||
| 2157 | static void | ||
| 2158 | init_moves_aux() | ||
| 2159 | { | ||
| 2160 | /* Some standard PieceFilters */ | ||
| 2161 | pf_all.epose = true; | ||
| 2162 | pf_all.eposs = true; | ||
| 2163 | pf_all.eposm = true; | ||
| 2164 | pf_all.eofb = true; | ||
| 2165 | pf_all.eorl = true; | ||
| 2166 | pf_all.eoud = true; | ||
| 2167 | pf_all.cp = true; | ||
| 2168 | pf_all.cofb = true; | ||
| 2169 | pf_all.corl = true; | ||
| 2170 | pf_all.coud = true; | ||
| 2171 | pf_all.cpos = true; | ||
| 2172 | |||
| 2173 | pf_4val.epose = true; | ||
| 2174 | pf_4val.eposs = true; | ||
| 2175 | pf_4val.eposm = true; | ||
| 2176 | pf_4val.eofb = true; | ||
| 2177 | pf_4val.coud = true; | ||
| 2178 | pf_4val.cp = true; | ||
| 2179 | |||
| 2180 | pf_epcp.epose = true; | ||
| 2181 | pf_epcp.eposs = true; | ||
| 2182 | pf_epcp.eposm = true; | ||
| 2183 | pf_epcp.cp = true; | ||
| 2184 | |||
| 2185 | pf_cpos.cpos = true; | ||
| 2186 | |||
| 2187 | pf_cp.cp = true; | ||
| 2188 | |||
| 2189 | pf_ep.epose = true; | ||
| 2190 | pf_ep.eposs = true; | ||
| 2191 | pf_ep.eposm = true; | ||
| 2192 | |||
| 2193 | pf_e.epose = true; | ||
| 2194 | pf_s.eposs = true; | ||
| 2195 | pf_m.eposm = true; | ||
| 2196 | |||
| 2197 | pf_eo.eofb = true; | ||
| 2198 | pf_eo.eorl = true; | ||
| 2199 | pf_eo.eoud = true; | ||
| 2200 | |||
| 2201 | pf_co.cofb = true; | ||
| 2202 | pf_co.corl = true; | ||
| 2203 | pf_co.coud = true; | ||
| 2204 | |||
| 2205 | /* Used to convert to and from CubeArray */ | ||
| 2206 | epe_solved[0] = FR; | ||
| 2207 | epe_solved[1] = FL; | ||
| 2208 | epe_solved[2] = BL; | ||
| 2209 | epe_solved[3] = BR; | ||
| 2210 | |||
| 2211 | eps_solved[0] = UL; | ||
| 2212 | eps_solved[1] = UR; | ||
| 2213 | eps_solved[2] = DL; | ||
| 2214 | eps_solved[3] = DR; | ||
| 2215 | |||
| 2216 | epm_solved[0] = UF; | ||
| 2217 | epm_solved[1] = UB; | ||
| 2218 | epm_solved[2] = DF; | ||
| 2219 | epm_solved[3] = DB; | ||
| 2220 | |||
| 2221 | /* Table sizes, used for reading and writing files */ | ||
| 2222 | me[0] = FACTORIAL12/FACTORIAL8; | ||
| 2223 | me[1] = FACTORIAL12/FACTORIAL8; | ||
| 2224 | me[2] = FACTORIAL12/FACTORIAL8; | ||
| 2225 | me[3] = POW2TO11; | ||
| 2226 | me[4] = POW2TO11; | ||
| 2227 | me[5] = POW2TO11; | ||
| 2228 | me[6] = FACTORIAL8; | ||
| 2229 | me[7] = POW3TO7; | ||
| 2230 | me[8] = POW3TO7; | ||
| 2231 | me[9] = POW3TO7; | ||
| 2232 | me[10] = FACTORIAL6; | ||
| 2233 | me[11] = NMOVES; | ||
| 2234 | |||
| 2235 | /* Cycles *********************/ | ||
| 2236 | edge_cycle[U][UF] = UR; | ||
| 2237 | edge_cycle[U][UL] = UF; | ||
| 2238 | edge_cycle[U][UB] = UL; | ||
| 2239 | edge_cycle[U][UR] = UB; | ||
| 2240 | edge_cycle[U][DF] = DF; | ||
| 2241 | edge_cycle[U][DL] = DL; | ||
| 2242 | edge_cycle[U][DB] = DB; | ||
| 2243 | edge_cycle[U][DR] = DR; | ||
| 2244 | edge_cycle[U][FR] = FR; | ||
| 2245 | edge_cycle[U][FL] = FL; | ||
| 2246 | edge_cycle[U][BL] = BL; | ||
| 2247 | edge_cycle[U][BR] = BR; | ||
| 2248 | |||
| 2249 | edge_cycle[x][UF] = DF; | ||
| 2250 | edge_cycle[x][UL] = FL; | ||
| 2251 | edge_cycle[x][UB] = UF; | ||
| 2252 | edge_cycle[x][UR] = FR; | ||
| 2253 | edge_cycle[x][DF] = DB; | ||
| 2254 | edge_cycle[x][DL] = BL; | ||
| 2255 | edge_cycle[x][DB] = UB; | ||
| 2256 | edge_cycle[x][DR] = BR; | ||
| 2257 | edge_cycle[x][FR] = DR; | ||
| 2258 | edge_cycle[x][FL] = DL; | ||
| 2259 | edge_cycle[x][BL] = UL; | ||
| 2260 | edge_cycle[x][BR] = UR; | ||
| 2261 | |||
| 2262 | edge_cycle[y][UF] = UR; | ||
| 2263 | edge_cycle[y][UL] = UF; | ||
| 2264 | edge_cycle[y][UB] = UL; | ||
| 2265 | edge_cycle[y][UR] = UB; | ||
| 2266 | edge_cycle[y][DF] = DR; | ||
| 2267 | edge_cycle[y][DL] = DF; | ||
| 2268 | edge_cycle[y][DB] = DL; | ||
| 2269 | edge_cycle[y][DR] = DB; | ||
| 2270 | edge_cycle[y][FR] = BR; | ||
| 2271 | edge_cycle[y][FL] = FR; | ||
| 2272 | edge_cycle[y][BL] = FL; | ||
| 2273 | edge_cycle[y][BR] = BL; | ||
| 2274 | |||
| 2275 | corner_cycle[U][UFR] = UBR; | ||
| 2276 | corner_cycle[U][UFL] = UFR; | ||
| 2277 | corner_cycle[U][UBL] = UFL; | ||
| 2278 | corner_cycle[U][UBR] = UBL; | ||
| 2279 | corner_cycle[U][DFR] = DFR; | ||
| 2280 | corner_cycle[U][DFL] = DFL; | ||
| 2281 | corner_cycle[U][DBL] = DBL; | ||
| 2282 | corner_cycle[U][DBR] = DBR; | ||
| 2283 | |||
| 2284 | corner_cycle[x][UFR] = DFR; | ||
| 2285 | corner_cycle[x][UFL] = DFL; | ||
| 2286 | corner_cycle[x][UBL] = UFL; | ||
| 2287 | corner_cycle[x][UBR] = UFR; | ||
| 2288 | corner_cycle[x][DFR] = DBR; | ||
| 2289 | corner_cycle[x][DFL] = DBL; | ||
| 2290 | corner_cycle[x][DBL] = UBL; | ||
| 2291 | corner_cycle[x][DBR] = UBR; | ||
| 2292 | |||
| 2293 | corner_cycle[y][UFR] = UBR; | ||
| 2294 | corner_cycle[y][UFL] = UFR; | ||
| 2295 | corner_cycle[y][UBL] = UFL; | ||
| 2296 | corner_cycle[y][UBR] = UBL; | ||
| 2297 | corner_cycle[y][DFR] = DBR; | ||
| 2298 | corner_cycle[y][DFL] = DFR; | ||
| 2299 | corner_cycle[y][DBL] = DFL; | ||
| 2300 | corner_cycle[y][DBR] = DBL; | ||
| 2301 | |||
| 2302 | center_cycle[U][U_center] = U_center; | ||
| 2303 | center_cycle[U][D_center] = D_center; | ||
| 2304 | center_cycle[U][R_center] = R_center; | ||
| 2305 | center_cycle[U][L_center] = L_center; | ||
| 2306 | center_cycle[U][F_center] = F_center; | ||
| 2307 | center_cycle[U][B_center] = B_center; | ||
| 2308 | |||
| 2309 | center_cycle[x][U_center] = F_center; | ||
| 2310 | center_cycle[x][D_center] = B_center; | ||
| 2311 | center_cycle[x][R_center] = R_center; | ||
| 2312 | center_cycle[x][L_center] = L_center; | ||
| 2313 | center_cycle[x][F_center] = D_center; | ||
| 2314 | center_cycle[x][B_center] = U_center; | ||
| 2315 | |||
| 2316 | center_cycle[y][U_center] = U_center; | ||
| 2317 | center_cycle[y][D_center] = D_center; | ||
| 2318 | center_cycle[y][R_center] = B_center; | ||
| 2319 | center_cycle[y][L_center] = F_center; | ||
| 2320 | center_cycle[y][F_center] = R_center; | ||
| 2321 | center_cycle[y][B_center] = L_center; | ||
| 2322 | |||
| 2323 | /* Flipped pieces *************/ | ||
| 2324 | eofb_flipped[x][UF] = 1; | ||
| 2325 | eofb_flipped[x][UB] = 1; | ||
| 2326 | eofb_flipped[x][DF] = 1; | ||
| 2327 | eofb_flipped[x][DB] = 1; | ||
| 2328 | |||
| 2329 | eofb_flipped[y][FR] = 1; | ||
| 2330 | eofb_flipped[y][FL] = 1; | ||
| 2331 | eofb_flipped[y][BL] = 1; | ||
| 2332 | eofb_flipped[y][BR] = 1; | ||
| 2333 | |||
| 2334 | eorl_flipped[x][UF] = 1; | ||
| 2335 | eorl_flipped[x][UL] = 1; | ||
| 2336 | eorl_flipped[x][UB] = 1; | ||
| 2337 | eorl_flipped[x][UR] = 1; | ||
| 2338 | eorl_flipped[x][DF] = 1; | ||
| 2339 | eorl_flipped[x][DL] = 1; | ||
| 2340 | eorl_flipped[x][DB] = 1; | ||
| 2341 | eorl_flipped[x][DR] = 1; | ||
| 2342 | eorl_flipped[x][FR] = 1; | ||
| 2343 | eorl_flipped[x][FL] = 1; | ||
| 2344 | eorl_flipped[x][BL] = 1; | ||
| 2345 | eorl_flipped[x][BR] = 1; | ||
| 2346 | |||
| 2347 | eorl_flipped[y][FR] = 1; | ||
| 2348 | eorl_flipped[y][FL] = 1; | ||
| 2349 | eorl_flipped[y][BL] = 1; | ||
| 2350 | eorl_flipped[y][BR] = 1; | ||
| 2351 | |||
| 2352 | eoud_flipped[U][UF] = 1; | ||
| 2353 | eoud_flipped[U][UL] = 1; | ||
| 2354 | eoud_flipped[U][UB] = 1; | ||
| 2355 | eoud_flipped[U][UR] = 1; | ||
| 2356 | |||
| 2357 | eoud_flipped[x][UF] = 1; | ||
| 2358 | eoud_flipped[x][UB] = 1; | ||
| 2359 | eoud_flipped[x][DF] = 1; | ||
| 2360 | eoud_flipped[x][DB] = 1; | ||
| 2361 | |||
| 2362 | eoud_flipped[y][UF] = 1; | ||
| 2363 | eoud_flipped[y][UL] = 1; | ||
| 2364 | eoud_flipped[y][UB] = 1; | ||
| 2365 | eoud_flipped[y][UR] = 1; | ||
| 2366 | eoud_flipped[y][DF] = 1; | ||
| 2367 | eoud_flipped[y][DL] = 1; | ||
| 2368 | eoud_flipped[y][DB] = 1; | ||
| 2369 | eoud_flipped[y][DR] = 1; | ||
| 2370 | eoud_flipped[y][FR] = 1; | ||
| 2371 | eoud_flipped[y][FL] = 1; | ||
| 2372 | eoud_flipped[y][BL] = 1; | ||
| 2373 | eoud_flipped[y][BR] = 1; | ||
| 2374 | |||
| 2375 | coud_flipped[x][UFR] = 2; | ||
| 2376 | coud_flipped[x][UFL] = 1; | ||
| 2377 | coud_flipped[x][UBR] = 1; | ||
| 2378 | coud_flipped[x][UBL] = 2; | ||
| 2379 | coud_flipped[x][DFR] = 1; | ||
| 2380 | coud_flipped[x][DFL] = 2; | ||
| 2381 | coud_flipped[x][DBR] = 2; | ||
| 2382 | coud_flipped[x][DBL] = 1; | ||
| 2383 | |||
| 2384 | corl_flipped[U][UFR] = 1; | ||
| 2385 | corl_flipped[U][UFL] = 2; | ||
| 2386 | corl_flipped[U][UBL] = 1; | ||
| 2387 | corl_flipped[U][UBR] = 2; | ||
| 2388 | |||
| 2389 | corl_flipped[y][UFR] = 1; | ||
| 2390 | corl_flipped[y][UFL] = 2; | ||
| 2391 | corl_flipped[y][UBL] = 1; | ||
| 2392 | corl_flipped[y][UBR] = 2; | ||
| 2393 | corl_flipped[y][DFR] = 2; | ||
| 2394 | corl_flipped[y][DFL] = 1; | ||
| 2395 | corl_flipped[y][DBL] = 2; | ||
| 2396 | corl_flipped[y][DBR] = 1; | ||
| 2397 | |||
| 2398 | cofb_flipped[U][UFR] = 2; | ||
| 2399 | cofb_flipped[U][UFL] = 1; | ||
| 2400 | cofb_flipped[U][UBL] = 2; | ||
| 2401 | cofb_flipped[U][UBR] = 1; | ||
| 2402 | |||
| 2403 | cofb_flipped[x][UFR] = 1; | ||
| 2404 | cofb_flipped[x][UFL] = 2; | ||
| 2405 | cofb_flipped[x][UBL] = 1; | ||
| 2406 | cofb_flipped[x][UBR] = 2; | ||
| 2407 | cofb_flipped[x][DFR] = 2; | ||
| 2408 | cofb_flipped[x][DFL] = 1; | ||
| 2409 | cofb_flipped[x][DBL] = 2; | ||
| 2410 | cofb_flipped[x][DBR] = 1; | ||
| 2411 | |||
| 2412 | cofb_flipped[y][UFR] = 2; | ||
| 2413 | cofb_flipped[y][UFL] = 1; | ||
| 2414 | cofb_flipped[y][UBL] = 2; | ||
| 2415 | cofb_flipped[y][UBR] = 1; | ||
| 2416 | cofb_flipped[y][DFR] = 1; | ||
| 2417 | cofb_flipped[y][DFL] = 2; | ||
| 2418 | cofb_flipped[y][DBL] = 1; | ||
| 2419 | cofb_flipped[y][DBR] = 2; | ||
| 2420 | |||
| 2421 | /* Equivalent moves ***********/ | ||
| 2422 | equiv_alg[NULLMOVE] = new_alg(""); | ||
| 2423 | |||
| 2424 | equiv_alg[U] = new_alg(" U "); | ||
| 2425 | equiv_alg[U2] = new_alg(" UU "); | ||
| 2426 | equiv_alg[U3] = new_alg(" UUU "); | ||
| 2427 | equiv_alg[D] = new_alg(" xx U xx "); | ||
| 2428 | equiv_alg[D2] = new_alg(" xx UU xx "); | ||
| 2429 | equiv_alg[D3] = new_alg(" xx UUU xx "); | ||
| 2430 | equiv_alg[R] = new_alg(" yx U xxxyyy "); | ||
| 2431 | equiv_alg[R2] = new_alg(" yx UU xxxyyy "); | ||
| 2432 | equiv_alg[R3] = new_alg(" yx UUU xxxyyy "); | ||
| 2433 | equiv_alg[L] = new_alg(" yyyx U xxxy "); | ||
| 2434 | equiv_alg[L2] = new_alg(" yyyx UU xxxy "); | ||
| 2435 | equiv_alg[L3] = new_alg(" yyyx UUU xxxy "); | ||
| 2436 | equiv_alg[F] = new_alg(" x U xxx "); | ||
| 2437 | equiv_alg[F2] = new_alg(" x UU xxx "); | ||
| 2438 | equiv_alg[F3] = new_alg(" x UUU xxx "); | ||
| 2439 | equiv_alg[B] = new_alg(" xxx U x "); | ||
| 2440 | equiv_alg[B2] = new_alg(" xxx UU x "); | ||
| 2441 | equiv_alg[B3] = new_alg(" xxx UUU x "); | ||
| 2442 | |||
| 2443 | equiv_alg[Uw] = new_alg(" xx U xx y "); | ||
| 2444 | equiv_alg[Uw2] = new_alg(" xx UU xx yy "); | ||
| 2445 | equiv_alg[Uw3] = new_alg(" xx UUU xx yyy "); | ||
| 2446 | equiv_alg[Dw] = new_alg(" U yyy "); | ||
| 2447 | equiv_alg[Dw2] = new_alg(" UU yy "); | ||
| 2448 | equiv_alg[Dw3] = new_alg(" UUU y "); | ||
| 2449 | equiv_alg[Rw] = new_alg(" yyyx U xxxy x "); | ||
| 2450 | equiv_alg[Rw2] = new_alg(" yyyx UU xxxy xx "); | ||
| 2451 | equiv_alg[Rw3] = new_alg(" yyyx UUU xxxy xxx "); | ||
| 2452 | equiv_alg[Lw] = new_alg(" yx U xxxyyy xxx "); | ||
| 2453 | equiv_alg[Lw2] = new_alg(" yx UU xxxyyy xx "); | ||
| 2454 | equiv_alg[Lw3] = new_alg(" yx UUU xxxyyy x "); | ||
| 2455 | equiv_alg[Fw] = new_alg(" xxx U x yxxxyyy "); | ||
| 2456 | equiv_alg[Fw2] = new_alg(" xxx UU x yxxyyy "); | ||
| 2457 | equiv_alg[Fw3] = new_alg(" xxx UUU x yxyyy "); | ||
| 2458 | equiv_alg[Bw] = new_alg(" x U xxx yxyyy "); | ||
| 2459 | equiv_alg[Bw2] = new_alg(" x UU xxx yxxyyy "); | ||
| 2460 | equiv_alg[Bw3] = new_alg(" x UUU xxx yxxxyyy "); | ||
| 2461 | |||
| 2462 | equiv_alg[M] = new_alg(" yx U xx UUU yxyyy "); | ||
| 2463 | equiv_alg[M2] = new_alg(" yx UU xx UU xxxy "); | ||
| 2464 | equiv_alg[M3] = new_alg(" yx UUU xx U yxxxy "); | ||
| 2465 | equiv_alg[S] = new_alg(" x UUU xx U yyyx "); | ||
| 2466 | equiv_alg[S2] = new_alg(" x UU xx UU yyx "); | ||
| 2467 | equiv_alg[S3] = new_alg(" x U xx UUU yx "); | ||
| 2468 | equiv_alg[E] = new_alg(" U xx UUU xxyyy "); | ||
| 2469 | equiv_alg[E2] = new_alg(" UU xx UU xxyy "); | ||
| 2470 | equiv_alg[E3] = new_alg(" UUU xx U xxy "); | ||
| 2471 | |||
| 2472 | equiv_alg[x] = new_alg(" x "); | ||
| 2473 | equiv_alg[x2] = new_alg(" xx "); | ||
| 2474 | equiv_alg[x3] = new_alg(" xxx "); | ||
| 2475 | equiv_alg[y] = new_alg(" y "); | ||
| 2476 | equiv_alg[y2] = new_alg(" yy "); | ||
| 2477 | equiv_alg[y3] = new_alg(" yyy "); | ||
| 2478 | equiv_alg[z] = new_alg(" yyy x y "); | ||
| 2479 | equiv_alg[z2] = new_alg(" yy xx "); | ||
| 2480 | equiv_alg[z3] = new_alg(" y x yyy "); | ||
| 2481 | } | ||
| 2482 | |||
| 2483 | static void | ||
| 2484 | init_strings() | ||
| 2485 | { | ||
| 2486 | strcpy(move_string [NULLMOVE], "-" ); | ||
| 2487 | strcpy(move_string [U], "U" ); | ||
| 2488 | strcpy(move_string [U2], "U2" ); | ||
| 2489 | strcpy(move_string [U3], "U\'" ); | ||
| 2490 | strcpy(move_string [D], "D" ); | ||
| 2491 | strcpy(move_string [D2], "D2" ); | ||
| 2492 | strcpy(move_string [D3], "D\'" ); | ||
| 2493 | strcpy(move_string [R], "R" ); | ||
| 2494 | strcpy(move_string [R2], "R2" ); | ||
| 2495 | strcpy(move_string [R3], "R\'" ); | ||
| 2496 | strcpy(move_string [L], "L" ); | ||
| 2497 | strcpy(move_string [L2], "L2" ); | ||
| 2498 | strcpy(move_string [L3], "L\'" ); | ||
| 2499 | strcpy(move_string [F], "F" ); | ||
| 2500 | strcpy(move_string [F2], "F2" ); | ||
| 2501 | strcpy(move_string [F3], "F\'" ); | ||
| 2502 | strcpy(move_string [B], "B" ); | ||
| 2503 | strcpy(move_string [B2], "B2" ); | ||
| 2504 | strcpy(move_string [B3], "B\'" ); | ||
| 2505 | strcpy(move_string [Uw], "Uw" ); | ||
| 2506 | strcpy(move_string [Uw2], "Uw2" ); | ||
| 2507 | strcpy(move_string [Uw3], "Uw\'" ); | ||
| 2508 | strcpy(move_string [Dw], "Dw" ); | ||
| 2509 | strcpy(move_string [Dw2], "Dw2" ); | ||
| 2510 | strcpy(move_string [Dw3], "Dw\'" ); | ||
| 2511 | strcpy(move_string [Rw], "Rw" ); | ||
| 2512 | strcpy(move_string [Rw2], "Rw2" ); | ||
| 2513 | strcpy(move_string [Rw3], "Rw\'" ); | ||
| 2514 | strcpy(move_string [Lw], "Lw" ); | ||
| 2515 | strcpy(move_string [Lw2], "Lw2" ); | ||
| 2516 | strcpy(move_string [Lw3], "Lw\'" ); | ||
| 2517 | strcpy(move_string [Fw], "Fw" ); | ||
| 2518 | strcpy(move_string [Fw2], "Fw2" ); | ||
| 2519 | strcpy(move_string [Fw3], "Fw\'" ); | ||
| 2520 | strcpy(move_string [Bw], "Bw" ); | ||
| 2521 | strcpy(move_string [Bw2], "Bw2" ); | ||
| 2522 | strcpy(move_string [Bw3], "Bw\'" ); | ||
| 2523 | strcpy(move_string [M], "M" ); | ||
| 2524 | strcpy(move_string [M2], "M2" ); | ||
| 2525 | strcpy(move_string [M3], "M\'" ); | ||
| 2526 | strcpy(move_string [S], "S" ); | ||
| 2527 | strcpy(move_string [S2], "S2" ); | ||
| 2528 | strcpy(move_string [S3], "S\'" ); | ||
| 2529 | strcpy(move_string [E], "E" ); | ||
| 2530 | strcpy(move_string [E2], "E2" ); | ||
| 2531 | strcpy(move_string [E3], "E\'" ); | ||
| 2532 | strcpy(move_string [x], "x" ); | ||
| 2533 | strcpy(move_string [x2], "x2" ); | ||
| 2534 | strcpy(move_string [x3], "x\'" ); | ||
| 2535 | strcpy(move_string [y], "y" ); | ||
| 2536 | strcpy(move_string [y2], "y2" ); | ||
| 2537 | strcpy(move_string [y3], "y\'" ); | ||
| 2538 | strcpy(move_string [z], "z" ); | ||
| 2539 | strcpy(move_string [z2], "z2" ); | ||
| 2540 | strcpy(move_string [z3], "z\'" ); | ||
| 2541 | |||
| 2542 | strcpy(edge_string [UF], "UF" ); | ||
| 2543 | strcpy(edge_string [UL], "UL" ); | ||
| 2544 | strcpy(edge_string [UB], "UB" ); | ||
| 2545 | strcpy(edge_string [UR], "UR" ); | ||
| 2546 | strcpy(edge_string [DF], "DF" ); | ||
| 2547 | strcpy(edge_string [DL], "DL" ); | ||
| 2548 | strcpy(edge_string [DB], "DB" ); | ||
| 2549 | strcpy(edge_string [DR], "DR" ); | ||
| 2550 | strcpy(edge_string [FR], "FR" ); | ||
| 2551 | strcpy(edge_string [FL], "FL" ); | ||
| 2552 | strcpy(edge_string [BL], "BL" ); | ||
| 2553 | strcpy(edge_string [BR], "BR" ); | ||
| 2554 | |||
| 2555 | strcpy(corner_string [UFR], "UFR" ); | ||
| 2556 | strcpy(corner_string [UFL], "UFL" ); | ||
| 2557 | strcpy(corner_string [UBL], "UBL" ); | ||
| 2558 | strcpy(corner_string [UBR], "UBR" ); | ||
| 2559 | strcpy(corner_string [DFR], "DFR" ); | ||
| 2560 | strcpy(corner_string [DFL], "DFL" ); | ||
| 2561 | strcpy(corner_string [DBL], "DBL" ); | ||
| 2562 | strcpy(corner_string [DBR], "DBR" ); | ||
| 2563 | |||
| 2564 | strcpy(center_string [U_center], "U" ); | ||
| 2565 | strcpy(center_string [D_center], "D" ); | ||
| 2566 | strcpy(center_string [R_center], "R" ); | ||
| 2567 | strcpy(center_string [L_center], "L" ); | ||
| 2568 | strcpy(center_string [F_center], "F" ); | ||
| 2569 | strcpy(center_string [B_center], "B" ); | ||
| 2570 | } | ||
| 2571 | |||
| 2572 | static void | ||
| 2573 | init_symdata() | ||
| 2574 | { | ||
| 2575 | int i; | ||
| 2576 | |||
| 2577 | for (i = 0; i < n_all_symdata; i++) | ||
| 2578 | gensym(all_sd[i]); | ||
| 2579 | } | ||
| 2580 | |||
| 2581 | static void | ||
| 2582 | init_trans() { | ||
| 2583 | Cube aux, cube, mirr, c[3]; | ||
| 2584 | CubeArray epcp; | ||
| 2585 | int i, eparr[12], eoarr[12], cparr[8], coarr[8]; | ||
| 2586 | unsigned int ui; | ||
| 2587 | Move mi, move; | ||
| 2588 | Trans m; | ||
| 2589 | |||
| 2590 | /* Compute sources */ | ||
| 2591 | for (i = 0; i < NTRANS; i++) { | ||
| 2592 | cube = apply_alg(rotation_algs[i % NROTATIONS], (Cube){0}); | ||
| 2593 | |||
| 2594 | epose_source[i] = edge_slice(what_edge_at(cube, FR)); | ||
| 2595 | eposs_source[i] = edge_slice(what_edge_at(cube, UR)); | ||
| 2596 | eposm_source[i] = edge_slice(what_edge_at(cube, UF)); | ||
| 2597 | eofb_source[i] = what_center_at(cube, F_center)/2; | ||
| 2598 | eorl_source[i] = what_center_at(cube, R_center)/2; | ||
| 2599 | eoud_source[i] = what_center_at(cube, U_center)/2; | ||
| 2600 | coud_source[i] = what_center_at(cube, U_center)/2; | ||
| 2601 | cofb_source[i] = what_center_at(cube, F_center)/2; | ||
| 2602 | corl_source[i] = what_center_at(cube, R_center)/2; | ||
| 2603 | } | ||
| 2604 | |||
| 2605 | if (read_ttables_file()) | ||
| 2606 | return; | ||
| 2607 | |||
| 2608 | fprintf(stderr, "Cannot load %s, generating it\n", "ttables"); | ||
| 2609 | |||
| 2610 | /* Initialize tables */ | ||
| 2611 | for (m = 0; m < NTRANS; m++) { | ||
| 2612 | epcp = (CubeArray){ .ep = eparr, .cp = cparr }; | ||
| 2613 | cube = apply_alg(rotation_algs[m % NROTATIONS], (Cube){0}); | ||
| 2614 | cube_to_arrays(cube, &epcp, pf_epcp); | ||
| 2615 | if (m >= NROTATIONS) { | ||
| 2616 | apply_permutation(ep_mirror, eparr, 12); | ||
| 2617 | apply_permutation(cp_mirror, cparr, 8); | ||
| 2618 | } | ||
| 2619 | |||
| 2620 | for (ui = 0; ui < FACTORIAL12/FACTORIAL8; ui++) { | ||
| 2621 | c[0] = admissible_ep((Cube){ .epose = ui }, pf_e); | ||
| 2622 | c[1] = admissible_ep((Cube){ .eposs = ui }, pf_s); | ||
| 2623 | c[2] = admissible_ep((Cube){ .eposm = ui }, pf_m); | ||
| 2624 | |||
| 2625 | cube = rotate_via_compose(m,c[epose_source[m]],pf_ep); | ||
| 2626 | epose_ttable[m][ui] = cube.epose; | ||
| 2627 | |||
| 2628 | cube = rotate_via_compose(m,c[eposs_source[m]],pf_ep); | ||
| 2629 | eposs_ttable[m][ui] = cube.eposs; | ||
| 2630 | |||
| 2631 | cube = rotate_via_compose(m,c[eposm_source[m]],pf_ep); | ||
| 2632 | eposm_ttable[m][ui] = cube.eposm; | ||
| 2633 | } | ||
| 2634 | for (ui = 0; ui < POW2TO11; ui++ ) { | ||
| 2635 | int_to_sum_zero_array(ui, 2, 12, eoarr); | ||
| 2636 | apply_permutation(eparr, eoarr, 12); | ||
| 2637 | eo_ttable[m][ui] = digit_array_to_int(eoarr, 11, 2); | ||
| 2638 | } | ||
| 2639 | for (ui = 0; ui < POW3TO7; ui++) { | ||
| 2640 | int_to_sum_zero_array(ui, 3, 8, coarr); | ||
| 2641 | apply_permutation(cparr, coarr, 8); | ||
| 2642 | co_ttable[m][ui] = digit_array_to_int(coarr, 7, 3); | ||
| 2643 | if (m >= NROTATIONS) | ||
| 2644 | co_ttable[m][ui] = | ||
| 2645 | invert_digits(co_ttable[m][ui], 3, 7); | ||
| 2646 | } | ||
| 2647 | for (ui = 0; ui < FACTORIAL8; ui++) { | ||
| 2648 | cube = (Cube){ .cp = ui }; | ||
| 2649 | cube = rotate_via_compose(m, cube, pf_cp); | ||
| 2650 | cp_ttable[m][ui] = cube.cp; | ||
| 2651 | } | ||
| 2652 | for (ui = 0; ui < FACTORIAL6; ui++) { | ||
| 2653 | cube = (Cube){ .cpos = ui }; | ||
| 2654 | cube = rotate_via_compose(m, cube, pf_cpos); | ||
| 2655 | cpos_ttable[m][ui] = cube.cpos; | ||
| 2656 | } | ||
| 2657 | for (mi = 0; mi < NMOVES; mi++) { | ||
| 2658 | aux = apply_trans(m, apply_move(mi, (Cube){0})); | ||
| 2659 | for (move = 0; move < NMOVES; move++) { | ||
| 2660 | cube = apply_move(inverse_move_aux[move], aux); | ||
| 2661 | mirr = apply_trans(uf_mirror, cube); | ||
| 2662 | if (is_solved(cube, false) || | ||
| 2663 | is_solved(mirr, false)) | ||
| 2664 | moves_ttable[m][mi] = move; | ||
| 2665 | } | ||
| 2666 | } | ||
| 2667 | } | ||
| 2668 | |||
| 2669 | if (!write_ttables_file()) | ||
| 2670 | fprintf(stderr, "Error writing ttables\n"); | ||
| 2671 | } | ||
| 2672 | |||
| 2673 | static void | ||
| 2674 | init_trans_aux() | ||
| 2675 | { | ||
| 2676 | ep_mirror[UF] = UF; | ||
| 2677 | ep_mirror[UL] = UR; | ||
| 2678 | ep_mirror[UB] = UB; | ||
| 2679 | ep_mirror[UR] = UL; | ||
| 2680 | ep_mirror[DF] = DF; | ||
| 2681 | ep_mirror[DL] = DR; | ||
| 2682 | ep_mirror[DB] = DB; | ||
| 2683 | ep_mirror[DR] = DL; | ||
| 2684 | ep_mirror[FR] = FL; | ||
| 2685 | ep_mirror[FL] = FR; | ||
| 2686 | ep_mirror[BR] = BL; | ||
| 2687 | ep_mirror[BL] = BR; | ||
| 2688 | |||
| 2689 | cp_mirror[UFR] = UFL; | ||
| 2690 | cp_mirror[UFL] = UFR; | ||
| 2691 | cp_mirror[UBL] = UBR; | ||
| 2692 | cp_mirror[UBR] = UBL; | ||
| 2693 | cp_mirror[DFR] = DFL; | ||
| 2694 | cp_mirror[DFL] = DFR; | ||
| 2695 | cp_mirror[DBL] = DBR; | ||
| 2696 | cp_mirror[DBR] = DBL; | ||
| 2697 | |||
| 2698 | cpos_mirror[U_center] = U_center; | ||
| 2699 | cpos_mirror[D_center] = D_center; | ||
| 2700 | cpos_mirror[R_center] = L_center; | ||
| 2701 | cpos_mirror[L_center] = R_center; | ||
| 2702 | cpos_mirror[F_center] = F_center; | ||
| 2703 | cpos_mirror[B_center] = B_center; | ||
| 2704 | |||
| 2705 | /* Is there a more elegant way? */ | ||
| 2706 | rotation_algs[uf] = new_alg(""); | ||
| 2707 | rotation_algs[ur] = new_alg("y"); | ||
| 2708 | rotation_algs[ub] = new_alg("y2"); | ||
| 2709 | rotation_algs[ul] = new_alg("y3"); | ||
| 2710 | |||
| 2711 | rotation_algs[df] = new_alg("z2"); | ||
| 2712 | rotation_algs[dr] = new_alg("y z2"); | ||
| 2713 | rotation_algs[db] = new_alg("x2"); | ||
| 2714 | rotation_algs[dl] = new_alg("y3 z2"); | ||
| 2715 | |||
| 2716 | rotation_algs[rf] = new_alg("z3"); | ||
| 2717 | rotation_algs[rd] = new_alg("z3 y"); | ||
| 2718 | rotation_algs[rb] = new_alg("z3 y2"); | ||
| 2719 | rotation_algs[ru] = new_alg("z3 y3"); | ||
| 2720 | |||
| 2721 | rotation_algs[lf] = new_alg("z"); | ||
| 2722 | rotation_algs[ld] = new_alg("z y3"); | ||
| 2723 | rotation_algs[lb] = new_alg("z y2"); | ||
| 2724 | rotation_algs[lu] = new_alg("z y"); | ||
| 2725 | |||
| 2726 | rotation_algs[fu] = new_alg("x y2"); | ||
| 2727 | rotation_algs[fr] = new_alg("x y"); | ||
| 2728 | rotation_algs[fd] = new_alg("x"); | ||
| 2729 | rotation_algs[fl] = new_alg("x y3"); | ||
| 2730 | |||
| 2731 | rotation_algs[bu] = new_alg("x3"); | ||
| 2732 | rotation_algs[br] = new_alg("x3 y"); | ||
| 2733 | rotation_algs[bd] = new_alg("x3 y2"); | ||
| 2734 | rotation_algs[bl] = new_alg("x3 y3"); | ||
| 2735 | } | ||
| 2736 | |||
| 2737 | |||
| 2738 | /* Public functions implementation *******************************************/ | ||
| 2739 | |||
| 2740 | Cube | ||
| 2741 | apply_alg(Alg *alg, Cube cube) | ||
| 2742 | { | ||
| 2743 | return apply_alg_generic(alg, cube, pf_all, true); | ||
| 2744 | } | ||
| 2745 | |||
| 2746 | Cube | ||
| 2747 | apply_move(Move m, Cube cube) | ||
| 2748 | { | ||
| 2749 | return (Cube) { | ||
| 2750 | .epose = epose_mtable[m][cube.epose], | ||
| 2751 | .eposs = eposs_mtable[m][cube.eposs], | ||
| 2752 | .eposm = eposm_mtable[m][cube.eposm], | ||
| 2753 | .eofb = eofb_mtable[m][cube.eofb], | ||
| 2754 | .eorl = eorl_mtable[m][cube.eorl], | ||
| 2755 | .eoud = eoud_mtable[m][cube.eoud], | ||
| 2756 | .coud = coud_mtable[m][cube.coud], | ||
| 2757 | .cofb = cofb_mtable[m][cube.cofb], | ||
| 2758 | .corl = corl_mtable[m][cube.corl], | ||
| 2759 | .cp = cp_mtable[m][cube.cp], | ||
| 2760 | .cpos = cpos_mtable[m][cube.cpos] | ||
| 2761 | }; | ||
| 2762 | } | ||
| 2763 | |||
| 2764 | |||
| 2765 | Cube | ||
| 2766 | apply_trans(Trans t, Cube cube) | ||
| 2767 | { | ||
| 2768 | int aux_epos[3] = { cube.epose, cube.eposs, cube.eposm }; | ||
| 2769 | int aux_eo[3] = { cube.eoud, cube.eorl, cube.eofb }; | ||
| 2770 | int aux_co[3] = { cube.coud, cube.corl, cube.cofb }; | ||
| 2771 | |||
| 2772 | return (Cube) { | ||
| 2773 | .epose = epose_ttable[t][aux_epos[epose_source[t]]], | ||
| 2774 | .eposs = eposs_ttable[t][aux_epos[eposs_source[t]]], | ||
| 2775 | .eposm = eposm_ttable[t][aux_epos[eposm_source[t]]], | ||
| 2776 | .eofb = eo_ttable[t][aux_eo[eofb_source[t]]], | ||
| 2777 | .eorl = eo_ttable[t][aux_eo[eorl_source[t]]], | ||
| 2778 | .eoud = eo_ttable[t][aux_eo[eoud_source[t]]], | ||
| 2779 | .coud = co_ttable[t][aux_co[coud_source[t]]], | ||
| 2780 | .corl = co_ttable[t][aux_co[corl_source[t]]], | ||
| 2781 | .cofb = co_ttable[t][aux_co[cofb_source[t]]], | ||
| 2782 | .cp = cp_ttable[t][cube.cp], | ||
| 2783 | .cpos = cpos_ttable[t][cube.cpos] | ||
| 2784 | }; | ||
| 2785 | } | ||
| 2786 | |||
| 2787 | Move | ||
| 2788 | base_move(Move m) | ||
| 2789 | { | ||
| 2790 | if (m == NULLMOVE) | ||
| 2791 | return NULLMOVE; | ||
| 2792 | else | ||
| 2793 | return m - (m-1)%3; | ||
| 2794 | } | ||
| 2795 | |||
| 2796 | Cube | ||
| 2797 | compose(Cube c2, Cube c1) | ||
| 2798 | { | ||
| 2799 | return compose_filtered(c2, c1, pf_all); | ||
| 2800 | } | ||
| 2801 | |||
| 2802 | /*TODO maybe move the next two */ | ||
| 2803 | uint64_t | ||
| 2804 | cphtr(Cube cube) | ||
| 2805 | { | ||
| 2806 | return cphtr_right_cosets[cube.cp]; | ||
| 2807 | } | ||
| 2808 | |||
| 2809 | Cube | ||
| 2810 | anti_cphtr(uint64_t ind) | ||
| 2811 | { | ||
| 2812 | return (Cube) { .cp = cphtr_right_rep[ind] }; | ||
| 2813 | } | ||
| 2814 | |||
| 2815 | uint64_t | ||
| 2816 | epos_dependent(Cube c) | ||
| 2817 | { | ||
| 2818 | return epos_dependent_aux[c.eposs/FACTORIAL4][c.epose/FACTORIAL4]; | ||
| 2819 | } | ||
| 2820 | |||
| 2821 | bool | ||
| 2822 | equal(Cube c1, Cube c2) | ||
| 2823 | { | ||
| 2824 | return c1.eofb == c2.eofb && | ||
| 2825 | c1.epose == c2.epose && | ||
| 2826 | c1.eposs == c2.eposs && | ||
| 2827 | c1.eposm == c2.eposm && | ||
| 2828 | c1.coud == c2.coud && | ||
| 2829 | c1.cp == c2.cp && | ||
| 2830 | c1.cpos == c2.cpos; | ||
| 2831 | } | ||
| 2832 | |||
| 2833 | void | ||
| 2834 | genptable(PruneData *pd) | ||
| 2835 | { | ||
| 2836 | Cube cube; | ||
| 2837 | uint64_t j, oldn = 0; | ||
| 2838 | DfsData dd = { | ||
| 2839 | .m = 0, | ||
| 2840 | .last1 = NULLMOVE, | ||
| 2841 | .last2 = NULLMOVE | ||
| 2842 | }; | ||
| 2843 | |||
| 2844 | if (pd->generated) | ||
| 2845 | return; | ||
| 2846 | |||
| 2847 | /* TODO: check if memory is enough, otherwise maybe crash gracefully? */ | ||
| 2848 | pd->ptable = malloc(ptablesize(pd) * sizeof(uint8_t)); | ||
| 2849 | |||
| 2850 | if (read_ptable_file(pd)) { | ||
| 2851 | pd->generated = true; | ||
| 2852 | return; | ||
| 2853 | } | ||
| 2854 | |||
| 2855 | fprintf(stderr, "Cannot load %s, generating it\n", pd->filename); | ||
| 2856 | |||
| 2857 | /* We use 4 bits per value, so any distance >= 15 is set to 15 */ | ||
| 2858 | for (j = 0; j < pd->coord->max; j++) | ||
| 2859 | ptable_update(pd, pd->coord->cube(j), 15); | ||
| 2860 | |||
| 2861 | moveset_to_list(pd->moveset, NULL, dd.sorted_moves); | ||
| 2862 | movelist_to_position(dd.sorted_moves, dd.move_position); | ||
| 2863 | |||
| 2864 | for (dd.d = 0, pd->n = 0; dd.d < 15 && pd->n < pd->coord->max; dd.d++) { | ||
| 2865 | for (j = 0; j < pd->coord->max; j++) { | ||
| 2866 | cube = pd->coord->cube(j); | ||
| 2867 | if (pd->coord->check(cube)) | ||
| 2868 | genptable_dfs(cube, pd, &dd); | ||
| 2869 | } | ||
| 2870 | fprintf(stderr, "Depth %d done, generated %lu\t(%lu/%lu)\n", | ||
| 2871 | dd.d, pd->n-oldn, pd->n, pd->coord->max); | ||
| 2872 | oldn = pd->n; | ||
| 2873 | } | ||
| 2874 | |||
| 2875 | if (!write_ptable_file(pd)) | ||
| 2876 | fprintf(stderr, "Error writing ptable file\n"); | ||
| 2877 | |||
| 2878 | pd->generated = true; | ||
| 2879 | } | ||
| 2880 | |||
| 2881 | Cube | ||
| 2882 | inverse_cube(Cube cube) | ||
| 2883 | { | ||
| 2884 | CubeArray *arr = new_cubearray(cube, pf_all); | ||
| 2885 | CubeArray *inv = new_cubearray((Cube){0}, pf_all); | ||
| 2886 | Cube ret; | ||
| 2887 | int i; | ||
| 2888 | |||
| 2889 | for (i = 0; i < 12; i++) { | ||
| 2890 | inv->ep[arr->ep[i]] = i; | ||
| 2891 | inv->eofb[arr->ep[i]] = arr->eofb[i]; | ||
| 2892 | inv->eorl[arr->ep[i]] = arr->eorl[i]; | ||
| 2893 | inv->eoud[arr->ep[i]] = arr->eoud[i]; | ||
| 2894 | } | ||
| 2895 | |||
| 2896 | for (i = 0; i < 8; i++) { | ||
| 2897 | inv->cp[arr->cp[i]] = i; | ||
| 2898 | inv->coud[arr->cp[i]] = (3 - arr->coud[i]) % 3; | ||
| 2899 | inv->corl[arr->cp[i]] = (3 - arr->corl[i]) % 3; | ||
| 2900 | inv->cofb[arr->cp[i]] = (3 - arr->cofb[i]) % 3; | ||
| 2901 | } | ||
| 2902 | |||
| 2903 | for (int i = 0; i < 6; i++) | ||
| 2904 | inv->cpos[arr->cpos[i]] = i; | ||
| 2905 | |||
| 2906 | ret = arrays_to_cube(inv, pf_all); | ||
| 2907 | free_cubearray(arr, pf_all); | ||
| 2908 | free_cubearray(inv, pf_all); | ||
| 2909 | |||
| 2910 | return ret; | ||
| 2911 | } | ||
| 2912 | |||
| 2913 | Move | ||
| 2914 | inverse_move(Move m) | ||
| 2915 | { | ||
| 2916 | return inverse_move_aux[m]; | ||
| 2917 | } | ||
| 2918 | |||
| 2919 | Trans | ||
| 2920 | inverse_trans(Trans t) | ||
| 2921 | { | ||
| 2922 | return inverse_trans_aux[t]; | ||
| 2923 | } | ||
| 2924 | |||
| 2925 | bool | ||
| 2926 | is_admissible(Cube cube) | ||
| 2927 | { | ||
| 2928 | /* TODO: this should check consistency of different orientations */ | ||
| 2929 | /* TODO: check that centers are opposite and admissible */ | ||
| 2930 | |||
| 2931 | CubeArray *a = new_cubearray(cube, pf_all); | ||
| 2932 | int parity; | ||
| 2933 | bool perm; | ||
| 2934 | |||
| 2935 | perm = is_perm(a->ep, 12) && | ||
| 2936 | is_perm(a->cp, 8) && | ||
| 2937 | is_perm(a->cpos, 6); | ||
| 2938 | parity = perm_sign(a->ep, 12) + | ||
| 2939 | perm_sign(a->cp, 8) + | ||
| 2940 | perm_sign(a->cpos, 6); | ||
| 2941 | |||
| 2942 | return perm && parity % 2 == 0; | ||
| 2943 | } | ||
| 2944 | |||
| 2945 | bool | ||
| 2946 | is_solved(Cube cube, bool reorient) | ||
| 2947 | { | ||
| 2948 | int i; | ||
| 2949 | |||
| 2950 | if (reorient) { | ||
| 2951 | for (i = 0; i < NROTATIONS; i++) | ||
| 2952 | if (is_solved(apply_alg(rotation_algs[i], cube),false)) | ||
| 2953 | return true; | ||
| 2954 | return false; | ||
| 2955 | } else { | ||
| 2956 | return equal(cube, (Cube){0}); | ||
| 2957 | } | ||
| 2958 | } | ||
| 2959 | |||
| 2960 | bool | ||
| 2961 | is_solved_block(Cube cube, Block block) | ||
| 2962 | { | ||
| 2963 | int i; | ||
| 2964 | |||
| 2965 | for (i = 0; i < 12; i++) | ||
| 2966 | if (block.edge[i] && !is_solved_edge(cube, i)) | ||
| 2967 | return false; | ||
| 2968 | for (i = 0; i < 8; i++) | ||
| 2969 | if (block.corner[i] && !is_solved_corner(cube, i)) | ||
| 2970 | return false; | ||
| 2971 | for (i = 0; i < 6; i++) | ||
| 2972 | if (block.center[i] && !is_solved_center(cube, i)) | ||
| 2973 | return false; | ||
| 2974 | |||
| 2975 | return true; | ||
| 2976 | } | ||
| 2977 | |||
| 2978 | bool | ||
| 2979 | is_solved_center(Cube cube, Center c) | ||
| 2980 | { | ||
| 2981 | return what_center_at(cube, c) == c; | ||
| 2982 | } | ||
| 2983 | |||
| 2984 | bool | ||
| 2985 | is_solved_corner(Cube cube, Corner c) | ||
| 2986 | { | ||
| 2987 | return what_corner_at(cube, c) == c && | ||
| 2988 | what_orientation_corner(cube.coud, c); | ||
| 2989 | } | ||
| 2990 | |||
| 2991 | bool | ||
| 2992 | is_solved_edge(Cube cube, Edge e) | ||
| 2993 | { | ||
| 2994 | return what_edge_at(cube, e) == e && | ||
| 2995 | what_orientation_edge(cube.eofb, e); | ||
| 2996 | } | ||
| 2997 | |||
| 2998 | int | ||
| 2999 | piece_orientation(Cube cube, int piece, char *orientation) | ||
| 3000 | { | ||
| 3001 | int arr[12], n, b, x; | ||
| 3002 | |||
| 3003 | if (!strcmp(orientation, "eofb")) { | ||
| 3004 | x = cube.eofb; | ||
| 3005 | n = 12; | ||
| 3006 | b = 2; | ||
| 3007 | } else if (!strcmp(orientation, "eorl")) { | ||
| 3008 | x = cube.eorl; | ||
| 3009 | n = 12; | ||
| 3010 | b = 2; | ||
| 3011 | } else if (!strcmp(orientation, "eoud")) { | ||
| 3012 | x = cube.eoud; | ||
| 3013 | n = 12; | ||
| 3014 | b = 2; | ||
| 3015 | } else if (!strcmp(orientation, "coud")) { | ||
| 3016 | x = cube.coud; | ||
| 3017 | n = 8; | ||
| 3018 | b = 3; | ||
| 3019 | } else if (!strcmp(orientation, "corl")) { | ||
| 3020 | x = cube.corl; | ||
| 3021 | n = 8; | ||
| 3022 | b = 3; | ||
| 3023 | } else if (!strcmp(orientation, "cofb")) { | ||
| 3024 | x = cube.cofb; | ||
| 3025 | n = 8; | ||
| 3026 | b = 3; | ||
| 3027 | } else { | ||
| 3028 | return -1; | ||
| 3029 | } | ||
| 3030 | |||
| 3031 | int_to_sum_zero_array(x, b, n, arr); | ||
| 3032 | if (piece < n) | ||
| 3033 | return arr[piece]; | ||
| 3034 | |||
| 3035 | return -1; | ||
| 3036 | } | ||
| 3037 | |||
| 3038 | void | ||
| 3039 | print_cube(Cube cube) | ||
| 3040 | { | ||
| 3041 | /* | ||
| 3042 | CubeArray *arr = new_cubearray(cube, pf_all); | ||
| 3043 | |||
| 3044 | for (int i = 0; i < 12; i++) | ||
| 3045 | printf(" %s ", edge_string[arr->ep[i]]); | ||
| 3046 | printf("\n"); | ||
| 3047 | |||
| 3048 | for (int i = 0; i < 12; i++) | ||
| 3049 | printf(" %c ", arr->eofb[i] + '0'); | ||
| 3050 | printf("\n"); | ||
| 3051 | |||
| 3052 | for (int i = 0; i < 8; i++) | ||
| 3053 | printf("%s ", corner_string[arr->cp[i]]); | ||
| 3054 | printf("\n"); | ||
| 3055 | |||
| 3056 | for (int i = 0; i < 8; i++) | ||
| 3057 | printf(" %c ", arr->coud[i] + '0'); | ||
| 3058 | printf("\n"); | ||
| 3059 | |||
| 3060 | for (int i = 0; i < 6; i++) | ||
| 3061 | printf(" %s ", center_string[arr->cpos[i]]); | ||
| 3062 | printf("\n"); | ||
| 3063 | |||
| 3064 | free_cubearray(arr, pf_all); | ||
| 3065 | */ | ||
| 3066 | |||
| 3067 | for (int i = 0; i < 12; i++) | ||
| 3068 | printf(" %s ", edge_string[what_edge_at(cube, i)]); | ||
| 3069 | printf("\n"); | ||
| 3070 | |||
| 3071 | for (int i = 0; i < 12; i++) | ||
| 3072 | printf(" %d ", what_orientation_edge(cube.eofb, i)); | ||
| 3073 | printf("\n"); | ||
| 3074 | |||
| 3075 | for (int i = 0; i < 8; i++) | ||
| 3076 | printf("%s ", corner_string[what_corner_at(cube, i)]); | ||
| 3077 | printf("\n"); | ||
| 3078 | |||
| 3079 | for (int i = 0; i < 8; i++) | ||
| 3080 | printf(" %d ", what_orientation_corner(cube.coud, i)); | ||
| 3081 | printf("\n"); | ||
| 3082 | |||
| 3083 | for (int i = 0; i < 6; i++) | ||
| 3084 | printf(" %s ", center_string[what_center_at(cube, i)]); | ||
| 3085 | printf("\n"); | ||
| 3086 | |||
| 3087 | } | ||
| 3088 | |||
| 3089 | Cube | ||
| 3090 | random_cube() | ||
| 3091 | { | ||
| 3092 | CubeArray *arr = new_cubearray((Cube){0}, pf_4val); | ||
| 3093 | Cube ret; | ||
| 3094 | int ep, cp, eo, co; | ||
| 3095 | |||
| 3096 | ep = rand() % FACTORIAL12; | ||
| 3097 | cp = rand() % FACTORIAL8; | ||
| 3098 | eo = rand() % POW2TO11; | ||
| 3099 | co = rand() % POW3TO7; | ||
| 3100 | |||
| 3101 | index_to_perm(ep, 12, arr->ep); | ||
| 3102 | index_to_perm(cp, 8, arr->cp); | ||
| 3103 | int_to_sum_zero_array(eo, 2, 12, arr->eofb); | ||
| 3104 | int_to_sum_zero_array(co, 3, 8, arr->coud); | ||
| 3105 | |||
| 3106 | if (perm_sign(arr->ep, 12) != perm_sign(arr->cp, 8)) | ||
| 3107 | swap(&(arr->ep[0]), &(arr->ep[1])); | ||
| 3108 | |||
| 3109 | ret = arrays_to_cube(arr, pf_4val); | ||
| 3110 | free_cubearray(arr, pf_4val); | ||
| 3111 | |||
| 3112 | return ret; | ||
| 3113 | } | ||
| 3114 | |||
| 3115 | /* TODO: clean pre_trans or put it back */ | ||
| 3116 | AlgList * | ||
| 3117 | solve(Cube cube, Step step, SolveOptions *opts) | ||
| 3118 | { | ||
| 3119 | /*AlgListNode *node;*/ | ||
| 3120 | AlgList *sols = new_alglist(); | ||
| 3121 | /*Cube c = apply_trans(opts->pre_trans, cube);*/ | ||
| 3122 | DfsData dd = { | ||
| 3123 | .m = 0, | ||
| 3124 | .niss = false, | ||
| 3125 | .lb = -1, | ||
| 3126 | .last1 = NULLMOVE, | ||
| 3127 | .last2 = NULLMOVE, | ||
| 3128 | .sols = sols, | ||
| 3129 | .current_alg = new_alg("") | ||
| 3130 | }; | ||
| 3131 | |||
| 3132 | if (step.ready != NULL && !step.ready(cube)) { | ||
| 3133 | fprintf(stderr, "Cube not ready for solving step\n"); | ||
| 3134 | return sols; | ||
| 3135 | } | ||
| 3136 | |||
| 3137 | moveset_to_list(step.moveset, step.estimate, dd.sorted_moves); | ||
| 3138 | movelist_to_position(dd.sorted_moves, dd.move_position); | ||
| 3139 | |||
| 3140 | for (dd.d = opts->min_moves; | ||
| 3141 | dd.d <= opts->max_moves && !(sols->len && opts->optimal_only); | ||
| 3142 | dd.d++) { | ||
| 3143 | if (opts->feedback) | ||
| 3144 | fprintf(stderr, | ||
| 3145 | "Found %d solutions, searching depth %d...\n", | ||
| 3146 | sols->len, dd.d); | ||
| 3147 | dfs(cube, step, opts, &dd); | ||
| 3148 | } | ||
| 3149 | |||
| 3150 | /* | ||
| 3151 | for (node = sols->first; node != NULL; node = node->next) | ||
| 3152 | transform_alg(inverse_trans(opts->pre_trans), node->alg); | ||
| 3153 | */ | ||
| 3154 | |||
| 3155 | free_alg(dd.current_alg); | ||
| 3156 | return sols; | ||
| 3157 | } | ||
| 3158 | |||
| 3159 | Alg * | ||
| 3160 | inverse_alg(Alg *alg) | ||
| 3161 | { | ||
| 3162 | Alg *ret = new_alg(""); | ||
| 3163 | int i; | ||
| 3164 | |||
| 3165 | for (i = alg->len-1; i >= 0; i--) | ||
| 3166 | append_move(ret, inverse_move(alg->move[i]), alg->inv[i]); | ||
| 3167 | |||
| 3168 | return ret; | ||
| 3169 | } | ||
| 3170 | |||
| 3171 | Alg * | ||
| 3172 | new_alg(char *str) | ||
| 3173 | { | ||
| 3174 | Alg *alg = malloc(sizeof(Alg)); | ||
| 3175 | int i; | ||
| 3176 | bool niss = false; | ||
| 3177 | Move j, m; | ||
| 3178 | |||
| 3179 | alg->move = malloc(30 * sizeof(Move)); | ||
| 3180 | alg->inv = malloc(30 * sizeof(bool)); | ||
| 3181 | alg->allocated = 30; | ||
| 3182 | alg->len = 0; | ||
| 3183 | |||
| 3184 | for (i = 0; str[i]; i++) { | ||
| 3185 | if (str[i] == ' ' || str[i] == '\t' || str[i] == '\n') | ||
| 3186 | continue; | ||
| 3187 | |||
| 3188 | if (str[i] == '(' && niss) { | ||
| 3189 | fprintf(stderr, "Error reading moves: nested ( )\n"); | ||
| 3190 | return alg; | ||
| 3191 | } | ||
| 3192 | |||
| 3193 | if (str[i] == ')' && !niss) { | ||
| 3194 | fprintf(stderr, "Error reading moves: unmatched )\n"); | ||
| 3195 | return alg; | ||
| 3196 | } | ||
| 3197 | |||
| 3198 | if (str[i] == '(' || str[i] == ')') { | ||
| 3199 | niss = !niss; | ||
| 3200 | continue; | ||
| 3201 | } | ||
| 3202 | |||
| 3203 | for (j = 0; j < NMOVES; j++) { | ||
| 3204 | if (str[i] == move_string[j][0]) { | ||
| 3205 | m = j; | ||
| 3206 | if (m <= B && str[i+1]=='w') { | ||
| 3207 | m += Uw - U; | ||
| 3208 | i++; | ||
| 3209 | } | ||
| 3210 | if (str[i+1]=='2') { | ||
| 3211 | m += 1; | ||
| 3212 | i++; | ||
| 3213 | } else if (str[i+1]=='\'' || str[i+1]=='3') { | ||
| 3214 | m += 2; | ||
| 3215 | i++; | ||
| 3216 | } | ||
| 3217 | append_move(alg, m, niss); | ||
| 3218 | break; | ||
| 3219 | } | ||
| 3220 | } | ||
| 3221 | } | ||
| 3222 | |||
| 3223 | return alg; | ||
| 3224 | } | ||
| 3225 | |||
| 3226 | Alg * | ||
| 3227 | on_inverse(Alg *alg) | ||
| 3228 | { | ||
| 3229 | Alg *ret = new_alg(""); | ||
| 3230 | int i; | ||
| 3231 | |||
| 3232 | for (i = 0; i < alg->len; i++) | ||
| 3233 | append_move(ret, alg->move[i], !alg->inv[i]); | ||
| 3234 | |||
| 3235 | return ret; | ||
| 3236 | } | ||
| 3237 | |||
| 3238 | void | ||
| 3239 | print_alg(Alg *alg, bool l) | ||
| 3240 | { | ||
| 3241 | /* TODO: make it possible to print to stdout or to string */ | ||
| 3242 | /* Maybe just return a string */ | ||
| 3243 | char fill[4]; | ||
| 3244 | int i; | ||
| 3245 | bool niss = false; | ||
| 3246 | |||
| 3247 | for (i = 0; i < alg->len; i++) { | ||
| 3248 | if (!niss && alg->inv[i]) | ||
| 3249 | strcpy(fill, i == 0 ? "(" : " ("); | ||
| 3250 | if (niss && !alg->inv[i]) | ||
| 3251 | strcpy(fill, ") "); | ||
| 3252 | if (niss == alg->inv[i]) | ||
| 3253 | strcpy(fill, i == 0 ? "" : " "); | ||
| 3254 | |||
| 3255 | printf("%s%s", fill, move_string[alg->move[i]]); | ||
| 3256 | niss = alg->inv[i]; | ||
| 3257 | } | ||
| 3258 | |||
| 3259 | if (niss) | ||
| 3260 | printf(")"); | ||
| 3261 | if (l) | ||
| 3262 | printf(" (%d)", alg->len); | ||
| 3263 | |||
| 3264 | printf("\n"); | ||
| 3265 | } | ||
| 3266 | |||
| 3267 | void | ||
| 3268 | print_alglist(AlgList *al, bool l) | ||
| 3269 | { | ||
| 3270 | AlgListNode *i; | ||
| 3271 | |||
| 3272 | for (i = al->first; i != NULL; i = i->next) | ||
| 3273 | print_alg(i->alg, l); | ||
| 3274 | } | ||
| 3275 | |||
| 3276 | void | ||
| 3277 | print_ptable(PruneData *pd) | ||
| 3278 | { | ||
| 3279 | uint64_t i, a[16]; | ||
| 3280 | |||
| 3281 | for (i = 0; i < 16; i++) | ||
| 3282 | a[i] = 0; | ||
| 3283 | |||
| 3284 | if (!pd->generated) | ||
| 3285 | genptable(pd); | ||
| 3286 | |||
| 3287 | for (i = 0; i < pd->coord->max; i++) | ||
| 3288 | a[ptableval(pd, pd->coord->cube(i))]++; | ||
| 3289 | |||
| 3290 | fprintf(stderr, "Values for table %s\n", pd->filename); | ||
| 3291 | for (i = 0; i < 16; i++) | ||
| 3292 | printf("%2lu\t%10lu\n", i, a[i]); | ||
| 3293 | } | ||
| 3294 | |||
| 3295 | uint64_t | ||
| 3296 | ptablesize(PruneData *pd) | ||
| 3297 | { | ||
| 3298 | return (pd->coord->max + 1) / 2; | ||
| 3299 | } | ||
| 3300 | |||
| 3301 | int | ||
| 3302 | ptableval(PruneData *pd, Cube cube) | ||
| 3303 | { | ||
| 3304 | uint64_t ind = pd->coord->index(cube); | ||
| 3305 | |||
| 3306 | return (ind % 2) ? pd->ptable[ind/2] / 16 : pd->ptable[ind/2] % 16; | ||
| 3307 | } | ||
| 3308 | |||
| 3309 | |||
| 3310 | Alg * | ||
| 3311 | rotation_alg(Trans i) | ||
| 3312 | { | ||
| 3313 | return rotation_algs[i % NROTATIONS]; | ||
| 3314 | } | ||
| 3315 | |||
| 3316 | void | ||
| 3317 | transform_alg(Trans t, Alg *alg) | ||
| 3318 | { | ||
| 3319 | int i; | ||
| 3320 | |||
| 3321 | for (i = 0; i < alg->len; i++) | ||
| 3322 | alg->move[i] = moves_ttable[t][alg->move[i]]; | ||
| 3323 | } | ||
| 3324 | |||
| 3325 | Center | ||
| 3326 | what_center_at(Cube cube, Center c) | ||
| 3327 | { | ||
| 3328 | return what_center_at_aux[cube.cpos][c]; | ||
| 3329 | } | ||
| 3330 | |||
| 3331 | Corner | ||
| 3332 | what_corner_at(Cube cube, Corner c) | ||
| 3333 | { | ||
| 3334 | return what_corner_at_aux[cube.cp][c]; | ||
| 3335 | } | ||
| 3336 | |||
| 3337 | Edge | ||
| 3338 | what_edge_at(Cube cube, Edge e) | ||
| 3339 | { | ||
| 3340 | Edge ret; | ||
| 3341 | CubeArray *arr = new_cubearray(cube, pf_ep); | ||
| 3342 | |||
| 3343 | ret = arr->ep[e]; | ||
| 3344 | |||
| 3345 | free_cubearray(arr, pf_ep); | ||
| 3346 | return ret; | ||
| 3347 | } | ||
| 3348 | |||
| 3349 | int | ||
| 3350 | what_orientation_corner(int co, Corner c) | ||
| 3351 | { | ||
| 3352 | if (c < 7) | ||
| 3353 | return (co / powint(3, c)) % 3; | ||
| 3354 | else | ||
| 3355 | return what_orientation_last_corner_aux[co]; | ||
| 3356 | } | ||
| 3357 | |||
| 3358 | int | ||
| 3359 | what_orientation_edge(int eo, Edge e) | ||
| 3360 | { | ||
| 3361 | if (e < 11) | ||
| 3362 | return (eo & (1 << e)) ? 1 : 0; | ||
| 3363 | else | ||
| 3364 | return what_orientation_last_edge_aux[eo]; | ||
| 3365 | } | ||
| 3366 | |||
| 3367 | Center | ||
| 3368 | where_is_center(Cube cube, Center c) | ||
| 3369 | { | ||
| 3370 | return where_is_center_aux[cube.cpos][c]; | ||
| 3371 | } | ||
| 3372 | |||
| 3373 | Corner | ||
| 3374 | where_is_corner(Cube cube, Corner c) | ||
| 3375 | { | ||
| 3376 | return where_is_corner_aux[cube.cp][c]; | ||
| 3377 | } | ||
| 3378 | |||
| 3379 | |||
| 3380 | void | ||
| 3381 | init() | ||
| 3382 | { | ||
| 3383 | /* Order is important! */ | ||
| 3384 | init_environment(); | ||
| 3385 | init_strings(); | ||
| 3386 | init_moves_aux(); | ||
| 3387 | init_moves(); | ||
| 3388 | init_auxtables(); | ||
| 3389 | init_cphtr_cosets(); | ||
| 3390 | init_trans_aux(); | ||
| 3391 | init_trans(); | ||
| 3392 | init_symdata(); | ||
| 3393 | } | ||
| 3394 | |||
diff --git a/old/2021-06-30-noreached/cube.h b/old/2021-06-30-noreached/cube.h new file mode 100644 index 0000000..ffbcd86 --- /dev/null +++ b/old/2021-06-30-noreached/cube.h | |||
| @@ -0,0 +1,90 @@ | |||
| 1 | #ifndef CUBE_H | ||
| 2 | #define CUBE_H | ||
| 3 | |||
| 4 | #include <stdio.h> | ||
| 5 | #include <stdbool.h> | ||
| 6 | #include <stdint.h> | ||
| 7 | #include <stdlib.h> | ||
| 8 | #include <string.h> | ||
| 9 | #include <time.h> | ||
| 10 | #include <unistd.h> | ||
| 11 | #include <sys/stat.h> | ||
| 12 | |||
| 13 | #include "macros.h" | ||
| 14 | #include "cubetypes.h" | ||
| 15 | |||
| 16 | extern Coordinate coord_eofb; | ||
| 17 | extern Coordinate coord_eofbepos; | ||
| 18 | extern Coordinate coord_coud; | ||
| 19 | extern Coordinate coord_corners; | ||
| 20 | extern Coordinate coord_cornershtr; | ||
| 21 | extern Coordinate coord_drud; | ||
| 22 | extern Coordinate coord_coud_sym16; | ||
| 23 | extern Coordinate coord_eofbepos_sym16; | ||
| 24 | extern Coordinate coord_drud_sym16; | ||
| 25 | extern Coordinate coord_khuge; | ||
| 26 | |||
| 27 | Cube apply_alg(Alg *alg, Cube cube); | ||
| 28 | Cube apply_move(Move m, Cube cube); | ||
| 29 | Cube apply_trans(Trans t, Cube cube); | ||
| 30 | bool block_solved(Cube cube, Block); | ||
| 31 | Cube compose(Cube c2, Cube c1); /* Use c2 as an alg on c1 */ | ||
| 32 | uint64_t cphtr(Cube cube); /* TODO: rename (something with cosets) */ | ||
| 33 | Cube anti_cphtr(uint64_t ind); /*TODO also this */ | ||
| 34 | uint64_t epos_dependent(Cube cube); /* TODO: rename and turn into an indexer */ | ||
| 35 | bool equal(Cube c1, Cube c2); | ||
| 36 | Cube inverse_cube(Cube cube); | ||
| 37 | Move inverse_move(Move m); | ||
| 38 | Trans inverse_trans(Trans t); | ||
| 39 | bool is_admissible(Cube cube); | ||
| 40 | bool is_solved(Cube cube, bool reorient); | ||
| 41 | bool is_solved_center(Cube cube, Center c); | ||
| 42 | bool is_solved_corner(Cube cube, Corner c); | ||
| 43 | bool is_solved_edge(Cube cube, Edge e); | ||
| 44 | void print_cube(Cube cube); | ||
| 45 | Cube random_cube(); | ||
| 46 | AlgList * solve(Cube cube, Step step, SolveOptions *opts); | ||
| 47 | Center what_center_at(Cube cube, Center c); | ||
| 48 | Corner what_corner_at(Cube cube, Corner c); | ||
| 49 | Edge what_edge_at(Cube cube, Edge e); | ||
| 50 | int what_orientation_corner(int co, Corner c); | ||
| 51 | int what_orientation_edge(int eo, Edge e); | ||
| 52 | Center where_is_center(Cube cube, Center c); | ||
| 53 | Corner where_is_corner(Cube cube, Corner c); | ||
| 54 | Edge where_is_edge(Cube cube, Edge e); | ||
| 55 | |||
| 56 | bool check_centers(Cube cube); | ||
| 57 | bool check_corners(Cube cube); | ||
| 58 | bool check_cornershtr(Cube cube); | ||
| 59 | bool check_coud(Cube cube); | ||
| 60 | bool check_drud(Cube cube); | ||
| 61 | bool check_eofb(Cube cube); | ||
| 62 | bool check_eofbepos(Cube cube); | ||
| 63 | bool check_epose(Cube cube); | ||
| 64 | bool check_ep(Cube cube); | ||
| 65 | bool check_khuge(Cube cube); | ||
| 66 | bool check_nothing(Cube cube); | ||
| 67 | |||
| 68 | bool moveset_HTM(Move m); | ||
| 69 | bool moveset_URF(Move m); | ||
| 70 | |||
| 71 | Move base_move(Move m); | ||
| 72 | void free_alg(Alg *alg); | ||
| 73 | void free_alglist(AlgList *l); | ||
| 74 | Alg * inverse_alg(Alg *alg); | ||
| 75 | Alg * new_alg(char *str); | ||
| 76 | Alg * on_inverse(Alg *alg); | ||
| 77 | void print_alg(Alg *alg, bool l); | ||
| 78 | void print_alglist(AlgList *al, bool l); | ||
| 79 | Alg * rotation_alg(Trans i); | ||
| 80 | void transform_alg(Trans t, Alg *alg); | ||
| 81 | |||
| 82 | void genptable(PruneData *pd); | ||
| 83 | void print_ptable(PruneData *pd); | ||
| 84 | uint64_t ptablesize(PruneData *pd); | ||
| 85 | int ptableval(PruneData *pd, Cube cube); | ||
| 86 | |||
| 87 | void init(); | ||
| 88 | |||
| 89 | #endif | ||
| 90 | |||
diff --git a/old/2021-06-30-noreached/cubetypes.h b/old/2021-06-30-noreached/cubetypes.h new file mode 100644 index 0000000..a324985 --- /dev/null +++ b/old/2021-06-30-noreached/cubetypes.h | |||
| @@ -0,0 +1,250 @@ | |||
| 1 | #ifndef CUBETYPES_H | ||
| 2 | #define CUBETYPES_H | ||
| 3 | |||
| 4 | /* Typedefs ******************************************************************/ | ||
| 5 | |||
| 6 | typedef enum center Center; | ||
| 7 | typedef enum corner Corner; | ||
| 8 | typedef enum edge Edge; | ||
| 9 | typedef enum move Move; | ||
| 10 | typedef enum trans Trans; | ||
| 11 | |||
| 12 | typedef struct alg Alg; | ||
| 13 | typedef struct alglist AlgList; | ||
| 14 | typedef struct alglistnode AlgListNode; | ||
| 15 | typedef struct block Block; | ||
| 16 | typedef struct coordinate Coordinate; | ||
| 17 | typedef struct cube Cube; | ||
| 18 | typedef struct cubearray CubeArray; | ||
| 19 | typedef struct cubetarget CubeTarget; | ||
| 20 | typedef struct dfsdata DfsData; | ||
| 21 | typedef struct piecefilter PieceFilter; | ||
| 22 | typedef struct prunedata PruneData; | ||
| 23 | typedef struct solveoptions SolveOptions; | ||
| 24 | typedef struct step Step; | ||
| 25 | typedef struct symdata SymData; | ||
| 26 | |||
| 27 | typedef Cube (*AntiIndexer) (uint64_t); | ||
| 28 | typedef bool (*Checker) (Cube); | ||
| 29 | typedef int (*Estimator) (CubeTarget); | ||
| 30 | typedef uint64_t (*Indexer) (Cube); | ||
| 31 | typedef bool (*Moveset) (Move); | ||
| 32 | |||
| 33 | |||
| 34 | /* Enums *********************************************************************/ | ||
| 35 | |||
| 36 | enum | ||
| 37 | center | ||
| 38 | { | ||
| 39 | U_center, D_center, | ||
| 40 | R_center, L_center, | ||
| 41 | F_center, B_center | ||
| 42 | }; | ||
| 43 | |||
| 44 | enum | ||
| 45 | corner | ||
| 46 | { | ||
| 47 | UFR, UFL, UBL, UBR, | ||
| 48 | DFR, DFL, DBL, DBR | ||
| 49 | }; | ||
| 50 | |||
| 51 | enum | ||
| 52 | edge | ||
| 53 | { | ||
| 54 | UF, UL, UB, UR, | ||
| 55 | DF, DL, DB, DR, | ||
| 56 | FR, FL, BL, BR | ||
| 57 | }; | ||
| 58 | |||
| 59 | enum | ||
| 60 | move | ||
| 61 | { | ||
| 62 | NULLMOVE, | ||
| 63 | U, U2, U3, D, D2, D3, | ||
| 64 | R, R2, R3, L, L2, L3, | ||
| 65 | F, F2, F3, B, B2, B3, | ||
| 66 | Uw, Uw2, Uw3, Dw, Dw2, Dw3, | ||
| 67 | Rw, Rw2, Rw3, Lw, Lw2, Lw3, | ||
| 68 | Fw, Fw2, Fw3, Bw, Bw2, Bw3, | ||
| 69 | M, M2, M3, | ||
| 70 | S, S2, S3, | ||
| 71 | E, E2, E3, | ||
| 72 | x, x2, x3, | ||
| 73 | y, y2, y3, | ||
| 74 | z, z2, z3, | ||
| 75 | }; | ||
| 76 | |||
| 77 | enum | ||
| 78 | trans | ||
| 79 | { | ||
| 80 | uf, ur, ub, ul, | ||
| 81 | df, dr, db, dl, | ||
| 82 | rf, rd, rb, ru, | ||
| 83 | lf, ld, lb, lu, | ||
| 84 | fu, fr, fd, fl, | ||
| 85 | bu, br, bd, bl, | ||
| 86 | uf_mirror, ur_mirror, ub_mirror, ul_mirror, | ||
| 87 | df_mirror, dr_mirror, db_mirror, dl_mirror, | ||
| 88 | rf_mirror, rd_mirror, rb_mirror, ru_mirror, | ||
| 89 | lf_mirror, ld_mirror, lb_mirror, lu_mirror, | ||
| 90 | fu_mirror, fr_mirror, fd_mirror, fl_mirror, | ||
| 91 | bu_mirror, br_mirror, bd_mirror, bl_mirror, | ||
| 92 | }; | ||
| 93 | |||
| 94 | |||
| 95 | /* Structs *******************************************************************/ | ||
| 96 | |||
| 97 | struct | ||
| 98 | alg | ||
| 99 | { | ||
| 100 | Move * move; | ||
| 101 | bool * inv; | ||
| 102 | int len; | ||
| 103 | int allocated; | ||
| 104 | }; | ||
| 105 | |||
| 106 | struct | ||
| 107 | alglist | ||
| 108 | { | ||
| 109 | AlgListNode * first; | ||
| 110 | AlgListNode * last; | ||
| 111 | int len; | ||
| 112 | }; | ||
| 113 | |||
| 114 | struct | ||
| 115 | alglistnode | ||
| 116 | { | ||
| 117 | Alg * alg; | ||
| 118 | AlgListNode * next; | ||
| 119 | }; | ||
| 120 | |||
| 121 | struct | ||
| 122 | block | ||
| 123 | { | ||
| 124 | bool edge[12]; | ||
| 125 | bool corner[8]; | ||
| 126 | bool center[6]; | ||
| 127 | }; | ||
| 128 | |||
| 129 | struct | ||
| 130 | coordinate | ||
| 131 | { | ||
| 132 | Indexer index; | ||
| 133 | AntiIndexer cube; | ||
| 134 | Checker check; | ||
| 135 | uint64_t max; | ||
| 136 | }; | ||
| 137 | |||
| 138 | struct | ||
| 139 | cube | ||
| 140 | { | ||
| 141 | int epose; | ||
| 142 | int eposs; | ||
| 143 | int eposm; | ||
| 144 | int eofb; | ||
| 145 | int eorl; | ||
| 146 | int eoud; | ||
| 147 | int cp; | ||
| 148 | int coud; | ||
| 149 | int cofb; | ||
| 150 | int corl; | ||
| 151 | int cpos; | ||
| 152 | }; | ||
| 153 | |||
| 154 | struct | ||
| 155 | cubearray | ||
| 156 | { | ||
| 157 | int * ep; | ||
| 158 | int * eofb; | ||
| 159 | int * eorl; | ||
| 160 | int * eoud; | ||
| 161 | int * cp; | ||
| 162 | int * coud; | ||
| 163 | int * corl; | ||
| 164 | int * cofb; | ||
| 165 | int * cpos; | ||
| 166 | }; | ||
| 167 | |||
| 168 | struct | ||
| 169 | cubetarget | ||
| 170 | { | ||
| 171 | Cube cube; | ||
| 172 | int target; | ||
| 173 | }; | ||
| 174 | |||
| 175 | struct | ||
| 176 | dfsdata | ||
| 177 | { | ||
| 178 | int d; | ||
| 179 | int m; | ||
| 180 | int lb; | ||
| 181 | bool niss; | ||
| 182 | Move last1; | ||
| 183 | Move last2; | ||
| 184 | AlgList * sols; | ||
| 185 | Alg * current_alg; | ||
| 186 | Move sorted_moves[NMOVES]; | ||
| 187 | int move_position[NMOVES]; | ||
| 188 | }; | ||
| 189 | |||
| 190 | struct | ||
| 191 | piecefilter | ||
| 192 | { | ||
| 193 | bool epose; | ||
| 194 | bool eposs; | ||
| 195 | bool eposm; | ||
| 196 | bool eofb; | ||
| 197 | bool eorl; | ||
| 198 | bool eoud; | ||
| 199 | bool cp; | ||
| 200 | bool coud; | ||
| 201 | bool cofb; | ||
| 202 | bool corl; | ||
| 203 | bool cpos; | ||
| 204 | }; | ||
| 205 | |||
| 206 | struct | ||
| 207 | prunedata | ||
| 208 | { | ||
| 209 | char * filename; | ||
| 210 | uint8_t * ptable; | ||
| 211 | bool generated; | ||
| 212 | uint64_t n; | ||
| 213 | Coordinate * coord; | ||
| 214 | Moveset moveset; | ||
| 215 | }; | ||
| 216 | |||
| 217 | struct | ||
| 218 | solveoptions | ||
| 219 | { | ||
| 220 | int min_moves; | ||
| 221 | int max_moves; | ||
| 222 | int max_solutions; | ||
| 223 | bool optimal_only; | ||
| 224 | bool can_niss; | ||
| 225 | bool feedback; | ||
| 226 | }; | ||
| 227 | |||
| 228 | struct | ||
| 229 | step | ||
| 230 | { | ||
| 231 | Estimator estimate; | ||
| 232 | Checker ready; | ||
| 233 | Moveset moveset; | ||
| 234 | }; | ||
| 235 | |||
| 236 | struct | ||
| 237 | symdata | ||
| 238 | { | ||
| 239 | char * filename; | ||
| 240 | bool generated; | ||
| 241 | Coordinate * coord; | ||
| 242 | Coordinate * sym_coord; | ||
| 243 | int ntrans; | ||
| 244 | Trans * trans; | ||
| 245 | uint64_t * class; | ||
| 246 | Cube * rep; | ||
| 247 | Trans * transtorep; | ||
| 248 | }; | ||
| 249 | |||
| 250 | #endif | ||
diff --git a/old/2021-06-30-noreached/macros.h b/old/2021-06-30-noreached/macros.h new file mode 100644 index 0000000..af3bca1 --- /dev/null +++ b/old/2021-06-30-noreached/macros.h | |||
| @@ -0,0 +1,23 @@ | |||
| 1 | #ifndef MACROS_H | ||
| 2 | #define MACROS_H | ||
| 3 | |||
| 4 | #define POW2TO6 64ULL | ||
| 5 | #define POW2TO11 2048ULL | ||
| 6 | #define POW2TO12 4096ULL | ||
| 7 | #define POW3TO7 2187ULL | ||
| 8 | #define POW3TO8 6561ULL | ||
| 9 | #define FACTORIAL4 24ULL | ||
| 10 | #define FACTORIAL6 720ULL | ||
| 11 | #define FACTORIAL7 5040ULL | ||
| 12 | #define FACTORIAL8 40320ULL | ||
| 13 | #define FACTORIAL12 479001600ULL | ||
| 14 | #define BINOM12ON4 495ULL | ||
| 15 | #define BINOM8ON4 70ULL | ||
| 16 | #define MIN(a,b) (((a) < (b)) ? (a) : (b)) | ||
| 17 | #define MAX(a,b) (((a) > (b)) ? (a) : (b)) | ||
| 18 | |||
| 19 | #define NMOVES (z3+1) | ||
| 20 | #define NTRANS 48 | ||
| 21 | #define NROTATIONS 24 | ||
| 22 | |||
| 23 | #endif | ||
diff --git a/old/2021-06-30-noreached/main.c b/old/2021-06-30-noreached/main.c new file mode 100644 index 0000000..1ebd917 --- /dev/null +++ b/old/2021-06-30-noreached/main.c | |||
| @@ -0,0 +1,80 @@ | |||
| 1 | #include <stdio.h> | ||
| 2 | #include "cube.h" | ||
| 3 | #include "steps.h" | ||
| 4 | |||
| 5 | int main() { | ||
| 6 | Alg *algo; | ||
| 7 | AlgList *sols; | ||
| 8 | Cube cube; | ||
| 9 | SolveOptions opts; | ||
| 10 | char line[1000]; | ||
| 11 | int i, ns = 2; | ||
| 12 | /* Move m;*/ | ||
| 13 | /* int nrand = 10000, sum1, sum2, sum3;*/ | ||
| 14 | |||
| 15 | Step *stps[20] = {&drud_HTM, &optimal_HTM}; | ||
| 16 | char sss[30][30] = {"DR on UD", "Optimal solve"}; | ||
| 17 | |||
| 18 | opts = (SolveOptions) { | ||
| 19 | .min_moves = 0, | ||
| 20 | .max_moves = 20, | ||
| 21 | .optimal_only = true, | ||
| 22 | .max_solutions = 1, | ||
| 23 | .can_niss = false, | ||
| 24 | .feedback = true, | ||
| 25 | }; | ||
| 26 | |||
| 27 | init(); | ||
| 28 | |||
| 29 | /* | ||
| 30 | srand(time(NULL)); | ||
| 31 | sum1 = 0; | ||
| 32 | sum2 = 0; | ||
| 33 | sum3 = 0; | ||
| 34 | for (i = 0; i < nrand; i++) { | ||
| 35 | cube = random_cube(); | ||
| 36 | sum1 += drud_HTM.check(cube, 20); | ||
| 37 | sum2 += optimal_HTM.check(cube, 20); | ||
| 38 | sum3 += cornershtreofb_HTM.check(cube, 20); | ||
| 39 | } | ||
| 40 | printf("Average drud pruning: %lf\n", ((double)sum1) / ((double) nrand)); | ||
| 41 | printf("Average corners htr pruning: %lf\n", ((double)sum2) / ((double) nrand)); | ||
| 42 | printf("Average corners htr + eofb pruning: %lf\n", ((double)sum3) / ((double) nrand)); | ||
| 43 | */ | ||
| 44 | |||
| 45 | /* | ||
| 46 | for (m = U; m <= B3; m++) { | ||
| 47 | printf("Class eofbepos after %d: ", m); | ||
| 48 | printf("%lu\n", coord_khuge.index(apply_move(m,(Cube){0}))); | ||
| 49 | } | ||
| 50 | */ | ||
| 51 | |||
| 52 | printf("Welcome to nissy 2.0! Insert a scramble:\n"); | ||
| 53 | |||
| 54 | if (fgets(line, 1000, stdin) != NULL) { | ||
| 55 | algo = new_alg(line); | ||
| 56 | cube = apply_alg(algo, (Cube){0}); | ||
| 57 | |||
| 58 | print_alg(inverse_alg(algo), false); | ||
| 59 | /* | ||
| 60 | printf("After rb_mirror:\n"); | ||
| 61 | cube = apply_trans(rb_mirror, cube); | ||
| 62 | print_cube(cube); | ||
| 63 | printf("Going back:\n"); | ||
| 64 | cube = apply_trans(inverse_trans(rb_mirror), cube); | ||
| 65 | */ | ||
| 66 | |||
| 67 | print_cube(cube); | ||
| 68 | |||
| 69 | for (i = 0; i < ns; i++) { | ||
| 70 | sols = solve(cube, *stps[i], &opts); | ||
| 71 | printf("%s: %d solutions found:\n", sss[i], sols->len); | ||
| 72 | print_alglist(sols, true); | ||
| 73 | free_alglist(sols); | ||
| 74 | } | ||
| 75 | free_alg(algo); | ||
| 76 | } | ||
| 77 | |||
| 78 | return 0; | ||
| 79 | } | ||
| 80 | |||
diff --git a/old/2021-06-30-noreached/steps.c b/old/2021-06-30-noreached/steps.c new file mode 100644 index 0000000..91e7f00 --- /dev/null +++ b/old/2021-06-30-noreached/steps.c | |||
| @@ -0,0 +1,307 @@ | |||
| 1 | #include "steps.h" | ||
| 2 | |||
| 3 | /* Standard checkers (return lower bound) ************************************/ | ||
| 4 | |||
| 5 | static int estimate_eofb_HTM(CubeTarget ct); | ||
| 6 | static int estimate_coud_HTM(CubeTarget ct); | ||
| 7 | static int estimate_coud_URF(CubeTarget ct); | ||
| 8 | static int estimate_corners_HTM(CubeTarget ct); | ||
| 9 | static int estimate_cornershtr_HTM(CubeTarget ct); | ||
| 10 | static int estimate_corners_URF(CubeTarget ct); | ||
| 11 | static int estimate_cornershtr_URF(CubeTarget ct); | ||
| 12 | static int estimate_drud_HTM(CubeTarget ct); | ||
| 13 | static int estimate_optimal_HTM(CubeTarget ct); | ||
| 14 | |||
| 15 | /* Steps *********************************************************************/ | ||
| 16 | |||
| 17 | Step | ||
| 18 | eofb_HTM = { | ||
| 19 | .estimate = estimate_eofb_HTM, | ||
| 20 | .ready = check_centers, | ||
| 21 | .moveset = moveset_HTM | ||
| 22 | }; | ||
| 23 | |||
| 24 | Step | ||
| 25 | coud_HTM = { | ||
| 26 | .estimate = estimate_coud_HTM, | ||
| 27 | .ready = check_centers, | ||
| 28 | .moveset = moveset_HTM | ||
| 29 | }; | ||
| 30 | |||
| 31 | Step | ||
| 32 | coud_URF = { | ||
| 33 | .estimate = estimate_coud_URF, | ||
| 34 | .ready = check_nothing, | ||
| 35 | .moveset = moveset_URF | ||
| 36 | }; | ||
| 37 | |||
| 38 | Step | ||
| 39 | corners_HTM = { | ||
| 40 | .estimate = estimate_corners_HTM, | ||
| 41 | .ready = check_centers, | ||
| 42 | .moveset = moveset_HTM | ||
| 43 | }; | ||
| 44 | |||
| 45 | Step | ||
| 46 | cornershtr_HTM = { | ||
| 47 | .estimate = estimate_cornershtr_HTM, | ||
| 48 | .ready = check_centers, | ||
| 49 | .moveset = moveset_HTM | ||
| 50 | }; | ||
| 51 | |||
| 52 | Step | ||
| 53 | cornershtr_URF = { | ||
| 54 | .estimate = estimate_cornershtr_URF, | ||
| 55 | .ready = check_nothing, | ||
| 56 | .moveset = moveset_URF | ||
| 57 | }; | ||
| 58 | |||
| 59 | Step | ||
| 60 | corners_URF = { | ||
| 61 | .estimate = estimate_corners_URF, | ||
| 62 | .ready = check_nothing, | ||
| 63 | .moveset = moveset_URF | ||
| 64 | }; | ||
| 65 | |||
| 66 | Step | ||
| 67 | drud_HTM = { | ||
| 68 | .estimate = estimate_drud_HTM, | ||
| 69 | .ready = check_centers, | ||
| 70 | .moveset = moveset_HTM | ||
| 71 | }; | ||
| 72 | |||
| 73 | Step | ||
| 74 | optimal_HTM = { | ||
| 75 | .estimate = estimate_optimal_HTM, | ||
| 76 | .ready = check_centers, | ||
| 77 | .moveset = moveset_HTM | ||
| 78 | }; | ||
| 79 | |||
| 80 | |||
| 81 | /* Pruning tables ************************************************************/ | ||
| 82 | |||
| 83 | PruneData | ||
| 84 | pd_eofb_HTM = { | ||
| 85 | .filename = "ptable_eofb_HTM", | ||
| 86 | .coord = &coord_eofb, | ||
| 87 | .moveset = moveset_HTM | ||
| 88 | }; | ||
| 89 | |||
| 90 | PruneData | ||
| 91 | pd_coud_HTM = { | ||
| 92 | .filename = "ptable_coud_HTM", | ||
| 93 | .coord = &coord_coud, | ||
| 94 | .moveset = moveset_HTM | ||
| 95 | }; | ||
| 96 | |||
| 97 | PruneData | ||
| 98 | pd_cornershtr_HTM = { | ||
| 99 | .filename = "ptable_cornershtr_withcosets_HTM", | ||
| 100 | .coord = &coord_cornershtr, | ||
| 101 | .moveset = moveset_HTM | ||
| 102 | }; | ||
| 103 | |||
| 104 | PruneData | ||
| 105 | pd_corners_HTM = { | ||
| 106 | .filename = "ptable_corners_HTM", | ||
| 107 | .coord = &coord_corners, | ||
| 108 | .moveset = moveset_HTM | ||
| 109 | }; | ||
| 110 | |||
| 111 | PruneData | ||
| 112 | pd_drud_HTM = { | ||
| 113 | .filename = "ptable_drud_HTM", | ||
| 114 | .coord = &coord_drud, | ||
| 115 | .moveset = moveset_HTM | ||
| 116 | }; | ||
| 117 | |||
| 118 | PruneData | ||
| 119 | pd_drud_sym16_HTM = { | ||
| 120 | .filename = "ptable_drud_sym16_HTM", | ||
| 121 | .coord = &coord_drud_sym16, | ||
| 122 | .moveset = moveset_HTM, | ||
| 123 | }; | ||
| 124 | |||
| 125 | PruneData | ||
| 126 | pd_khuge_HTM = { | ||
| 127 | .filename = "ptable_khuge_HTM", | ||
| 128 | .coord = &coord_khuge, | ||
| 129 | .moveset = moveset_HTM | ||
| 130 | }; | ||
| 131 | |||
| 132 | |||
| 133 | /* Standard checkers (return lower bound) ************************************/ | ||
| 134 | |||
| 135 | static int | ||
| 136 | estimate_eofb_HTM(CubeTarget ct) | ||
| 137 | { | ||
| 138 | if (!pd_eofb_HTM.generated) | ||
| 139 | genptable(&pd_eofb_HTM); | ||
| 140 | |||
| 141 | return ptableval(&pd_eofb_HTM, ct.cube); | ||
| 142 | } | ||
| 143 | |||
| 144 | static int | ||
| 145 | estimate_coud_HTM(CubeTarget ct) | ||
| 146 | { | ||
| 147 | if (!pd_coud_HTM.generated) | ||
| 148 | genptable(&pd_coud_HTM); | ||
| 149 | |||
| 150 | return ptableval(&pd_coud_HTM, ct.cube); | ||
| 151 | } | ||
| 152 | |||
| 153 | static int | ||
| 154 | estimate_coud_URF(CubeTarget ct) | ||
| 155 | { | ||
| 156 | /* TODO: I can improve this by checking first the orientation of | ||
| 157 | * the corner in DBL and use that as a reference */ | ||
| 158 | |||
| 159 | CubeTarget ct2 = {.cube = apply_move(z, ct.cube), .target = ct.target}; | ||
| 160 | CubeTarget ct3 = {.cube = apply_move(x, ct.cube), .target = ct.target}; | ||
| 161 | |||
| 162 | int ud = estimate_coud_HTM(ct); | ||
| 163 | int rl = estimate_coud_HTM(ct2); | ||
| 164 | int fb = estimate_coud_HTM(ct3); | ||
| 165 | |||
| 166 | return MIN(ud, MIN(rl, fb)); | ||
| 167 | } | ||
| 168 | |||
| 169 | static int | ||
| 170 | estimate_corners_HTM(CubeTarget ct) | ||
| 171 | { | ||
| 172 | if (!pd_corners_HTM.generated) | ||
| 173 | genptable(&pd_corners_HTM); | ||
| 174 | |||
| 175 | return ptableval(&pd_corners_HTM, ct.cube); | ||
| 176 | } | ||
| 177 | |||
| 178 | static int | ||
| 179 | estimate_cornershtr_HTM(CubeTarget ct) | ||
| 180 | { | ||
| 181 | if (!pd_cornershtr_HTM.generated) | ||
| 182 | genptable(&pd_cornershtr_HTM); | ||
| 183 | |||
| 184 | return ptableval(&pd_cornershtr_HTM, ct.cube); | ||
| 185 | } | ||
| 186 | |||
| 187 | static int | ||
| 188 | estimate_cornershtr_URF(CubeTarget ct) | ||
| 189 | { | ||
| 190 | /* TODO: I can improve this by checking first the corner in DBL | ||
| 191 | * and use that as a reference */ | ||
| 192 | |||
| 193 | int c, ret = 15; | ||
| 194 | Trans i; | ||
| 195 | |||
| 196 | for (i = 0; i < NROTATIONS; i++) { | ||
| 197 | ct.cube = apply_alg(rotation_alg(i), ct.cube); | ||
| 198 | c = estimate_cornershtr_HTM(ct); | ||
| 199 | ret = MIN(ret, c); | ||
| 200 | } | ||
| 201 | |||
| 202 | return ret; | ||
| 203 | } | ||
| 204 | |||
| 205 | static int | ||
| 206 | estimate_corners_URF(CubeTarget ct) | ||
| 207 | { | ||
| 208 | /* TODO: I can improve this by checking first the corner in DBL | ||
| 209 | * and use that as a reference */ | ||
| 210 | |||
| 211 | int c, ret = 15; | ||
| 212 | Trans i; | ||
| 213 | |||
| 214 | for (i = 0; i < NROTATIONS; i++) { | ||
| 215 | ct.cube = apply_alg(rotation_alg(i), ct.cube); | ||
| 216 | c = estimate_corners_HTM(ct); | ||
| 217 | ret = MIN(ret, c); | ||
| 218 | } | ||
| 219 | |||
| 220 | return ret; | ||
| 221 | } | ||
| 222 | |||
| 223 | static int | ||
| 224 | estimate_drud_HTM(CubeTarget ct) | ||
| 225 | { | ||
| 226 | /* | ||
| 227 | if (!pd_drud_HTM.generated) | ||
| 228 | genptable(&pd_drud_HTM); | ||
| 229 | |||
| 230 | return ptableval(&pd_drud_HTM, ct.cube); | ||
| 231 | */ | ||
| 232 | |||
| 233 | if (!pd_drud_sym16_HTM.generated) | ||
| 234 | genptable(&pd_drud_sym16_HTM); | ||
| 235 | |||
| 236 | return ptableval(&pd_drud_sym16_HTM, ct.cube); | ||
| 237 | } | ||
| 238 | |||
| 239 | /* TODO: if lucky, remove this */ | ||
| 240 | /* | ||
| 241 | static int | ||
| 242 | estimate_optimal_HTM(CubeTarget ct) | ||
| 243 | { | ||
| 244 | static Trans t1 = { .rot = rf, .mirror = false }; | ||
| 245 | static Trans t2 = { .rot = bd, .mirror = false }; | ||
| 246 | int dr1, dr2, dr3, cor, ret; | ||
| 247 | Cube cube = ct.cube; | ||
| 248 | |||
| 249 | dr1 = estimate_drud_HTM(ct); | ||
| 250 | cor = estimate_corners_HTM(ct); | ||
| 251 | ret = MAX(dr1, cor); | ||
| 252 | |||
| 253 | if (ret > ct.target) | ||
| 254 | return ret; | ||
| 255 | |||
| 256 | ct.cube = apply_trans(t1, cube); | ||
| 257 | dr2 = estimate_drud_HTM(ct); | ||
| 258 | ret = MAX(ret, dr2); | ||
| 259 | |||
| 260 | if (ret > ct.target) | ||
| 261 | return ret; | ||
| 262 | |||
| 263 | ct.cube = apply_trans(t2, cube); | ||
| 264 | dr3 = estimate_drud_HTM(ct); | ||
| 265 | |||
| 266 | if (dr1 == dr2 && dr2 == dr3 && dr1 != 0) | ||
| 267 | dr3++; | ||
| 268 | |||
| 269 | ret = MAX(ret, dr3); | ||
| 270 | |||
| 271 | if (ret == 0) | ||
| 272 | return check_ep(cube) ? 0 : 6; | ||
| 273 | |||
| 274 | return ret; | ||
| 275 | } | ||
| 276 | */ | ||
| 277 | |||
| 278 | static int | ||
| 279 | estimate_optimal_HTM(CubeTarget ct) | ||
| 280 | { | ||
| 281 | static Trans t2 = rf, t3 = bd; | ||
| 282 | |||
| 283 | int dr1, dr2, dr3, cor, ret; | ||
| 284 | Cube cube = ct.cube; | ||
| 285 | |||
| 286 | if (!pd_khuge_HTM.generated) | ||
| 287 | genptable(&pd_khuge_HTM); | ||
| 288 | |||
| 289 | dr1 = ptableval(&pd_khuge_HTM, cube); | ||
| 290 | cor = estimate_corners_HTM(ct); | ||
| 291 | ret = MAX(dr1, cor); | ||
| 292 | |||
| 293 | if (ret > ct.target) | ||
| 294 | return ret; | ||
| 295 | |||
| 296 | cube = apply_trans(t2, ct.cube); | ||
| 297 | dr2 = ptableval(&pd_khuge_HTM, cube); | ||
| 298 | ret = MAX(ret, dr2); | ||
| 299 | |||
| 300 | if (ret > ct.target) | ||
| 301 | return ret; | ||
| 302 | |||
| 303 | cube = apply_trans(t3, ct.cube); | ||
| 304 | dr3 = ptableval(&pd_khuge_HTM, cube); | ||
| 305 | |||
| 306 | return MAX(ret, dr3); | ||
| 307 | } | ||
diff --git a/old/2021-06-30-noreached/steps.h b/old/2021-06-30-noreached/steps.h new file mode 100644 index 0000000..81ae11c --- /dev/null +++ b/old/2021-06-30-noreached/steps.h | |||
| @@ -0,0 +1,24 @@ | |||
| 1 | #ifndef STEPS_H | ||
| 2 | #define STEPS_H | ||
| 3 | |||
| 4 | #include "cube.h" | ||
| 5 | |||
| 6 | extern Step eofb_HTM; | ||
| 7 | extern Step coud_HTM; | ||
| 8 | extern Step coud_URF; | ||
| 9 | extern Step corners_HTM; | ||
| 10 | extern Step cornershtr_HTM; | ||
| 11 | extern Step corners_URF; | ||
| 12 | extern Step cornershtr_URF; | ||
| 13 | extern Step drud_HTM; | ||
| 14 | extern Step optimal_HTM; | ||
| 15 | |||
| 16 | extern PruneData pd_eofb_HTM; | ||
| 17 | extern PruneData pd_coud_HTM; | ||
| 18 | extern PruneData pd_corners_HTM; | ||
| 19 | extern PruneData pd_cornershtr_HTM; | ||
| 20 | extern PruneData pd_cornershtreofb_HTM; | ||
| 21 | extern PruneData pd_drud_HTM; | ||
| 22 | extern PruneData pd_khuge_HTM; | ||
| 23 | |||
| 24 | #endif | ||
diff --git a/old/2021-06-30-reached/cube.c b/old/2021-06-30-reached/cube.c new file mode 100644 index 0000000..e490589 --- /dev/null +++ b/old/2021-06-30-reached/cube.c | |||
| @@ -0,0 +1,3419 @@ | |||
| 1 | #include "cube.h" | ||
| 2 | |||
| 3 | /* Local functions **********************************************************/ | ||
| 4 | |||
| 5 | static Cube admissible_ep(Cube cube, PieceFilter f); | ||
| 6 | static Cube admissible_eos_from_eofbepos(Cube cube); | ||
| 7 | static bool allowed_next(Move move, DfsData *dd); | ||
| 8 | static void append_alg(AlgList *l, Alg *alg); | ||
| 9 | static void append_move(Alg *alg, Move m, bool inverse); | ||
| 10 | static Cube apply_alg_generic(Alg *alg, Cube c, PieceFilter f, bool a); | ||
| 11 | static void apply_permutation(int *perm, int *set, int n); | ||
| 12 | static Cube apply_move_cubearray(Move m, Cube cube, PieceFilter f); | ||
| 13 | static int array_ep_to_epos(int *ep, int *eps_solved); | ||
| 14 | static Cube arrays_to_cube(CubeArray *arr, PieceFilter f); | ||
| 15 | static int binomial(int n, int k); | ||
| 16 | static Cube compose_filtered(Cube c2, Cube c1, PieceFilter f); | ||
| 17 | static void cube_to_arrays(Cube cube, CubeArray *arr, PieceFilter f); | ||
| 18 | static void dfs(Cube c, Step s, SolveOptions *opts, DfsData *dd); | ||
| 19 | static void dfs_branch(Cube c, Step s, SolveOptions *opts, DfsData *dd); | ||
| 20 | static bool dfs_check_solved(SolveOptions *opts, DfsData *dd); | ||
| 21 | static void dfs_niss(Cube c, Step s, SolveOptions *opts, DfsData *dd); | ||
| 22 | static bool dfs_stop(Cube c, Step s, SolveOptions *opts, DfsData *dd); | ||
| 23 | static int digit_array_to_int(int *a, int n, int b); | ||
| 24 | static int edge_slice(Edge e); /* E=0, S=1, M=2 */ | ||
| 25 | static int epos_dependent_pos(int pos1, int pos2); | ||
| 26 | static int epos_from_arrays(int *epos, int *ep); | ||
| 27 | static void epos_to_partial_ep(int epos, int *ep, int *ss); | ||
| 28 | static int factorial(int n); | ||
| 29 | static void free_alglistnode(AlgListNode *aln); | ||
| 30 | static void free_cubearray(CubeArray *arr, PieceFilter f); | ||
| 31 | static void genptable_dfs(Cube c, PruneData *pd, DfsData *dd); | ||
| 32 | static void genptable_dfs_branch(Cube c, PruneData *pd, DfsData *dd); | ||
| 33 | static void gensym(SymData *sd); | ||
| 34 | static void index_to_perm(int p, int n, int *r); | ||
| 35 | static void index_to_subset(int s, int n, int k, int *r); | ||
| 36 | static void init_auxtables(); | ||
| 37 | static void init_cphtr_cosets(); | ||
| 38 | static void init_cphtr_left_cosets_bfs(int i, int c); | ||
| 39 | static void init_cphtr_right_cosets_color(int i, int c); | ||
| 40 | static void init_environment(); | ||
| 41 | static void init_moves(); | ||
| 42 | static void init_moves_aux(); | ||
| 43 | static void init_strings(); | ||
| 44 | static void init_symdata(); | ||
| 45 | static void init_trans(); | ||
| 46 | static void init_trans_aux(); | ||
| 47 | static void int_to_digit_array(int a, int b, int n, int *r); | ||
| 48 | static void int_to_sum_zero_array(int x, int b, int n, int *a); | ||
| 49 | static int invert_digits(int a, int b, int n); | ||
| 50 | static bool is_perm(int *a, int n); | ||
| 51 | static bool is_subset(int *a, int n, int k); | ||
| 52 | static Cube move_via_arrays(CubeArray *arr, Cube c, PieceFilter pf); | ||
| 53 | static void movelist_to_position(Move *movelist, int *position); | ||
| 54 | static void moveset_to_list(Moveset ms, Estimator f, Move *r); | ||
| 55 | static AlgList * new_alglist(); | ||
| 56 | static CubeArray * new_cubearray(Cube cube, PieceFilter f); | ||
| 57 | static int perm_sign(int *a, int n); | ||
| 58 | static int perm_to_index(int *a, int n); | ||
| 59 | static int powint(int a, int b); | ||
| 60 | static bool ptable_has_reached(PruneData *pd, Cube cube); | ||
| 61 | static void ptable_set_reached(PruneData *pd, Cube cube); | ||
| 62 | static void ptable_update(PruneData *pd, Cube cube, int m); | ||
| 63 | static void realloc_alg(Alg *alg, int n); | ||
| 64 | static bool read_mtables_file(); | ||
| 65 | static bool read_ptable_file(PruneData *pd); | ||
| 66 | static bool read_symdata_file(SymData *sd); | ||
| 67 | static bool read_ttables_file(); | ||
| 68 | static Cube rotate_via_compose(Trans r, Cube c, PieceFilter f); | ||
| 69 | static int subset_to_index(int *a, int n, int k); | ||
| 70 | static void sum_arrays_mod(int *src, int *dst, int n, int m); | ||
| 71 | static void swap(int *a, int *b); | ||
| 72 | static bool write_mtables_file(); | ||
| 73 | static bool write_ptable_file(PruneData *pd); | ||
| 74 | static bool write_symdata_file(SymData *sd); | ||
| 75 | static bool write_ttables_file(); | ||
| 76 | |||
| 77 | |||
| 78 | /* All sorts of useful costants and tables **********************************/ | ||
| 79 | |||
| 80 | static char * tabledir; | ||
| 81 | |||
| 82 | static PieceFilter pf_all; | ||
| 83 | static PieceFilter pf_4val; | ||
| 84 | static PieceFilter pf_epcp; | ||
| 85 | static PieceFilter pf_cpos; | ||
| 86 | static PieceFilter pf_cp; | ||
| 87 | static PieceFilter pf_ep; | ||
| 88 | static PieceFilter pf_e; | ||
| 89 | static PieceFilter pf_s; | ||
| 90 | static PieceFilter pf_m; | ||
| 91 | static PieceFilter pf_eo; | ||
| 92 | static PieceFilter pf_co; | ||
| 93 | |||
| 94 | static int epe_solved[4]; | ||
| 95 | static int eps_solved[4]; | ||
| 96 | static int epm_solved[4]; | ||
| 97 | |||
| 98 | static char move_string[NMOVES][7]; | ||
| 99 | static char edge_string[12][7]; | ||
| 100 | static char corner_string[8][7]; | ||
| 101 | static char center_string[6][7]; | ||
| 102 | |||
| 103 | static Cube admissible_ee_aux[POW2TO11*BINOM12ON4]; | ||
| 104 | static bool commute[NMOVES][NMOVES]; | ||
| 105 | static bool possible_next[NMOVES][NMOVES][NMOVES]; | ||
| 106 | static Move inverse_move_aux[NMOVES]; | ||
| 107 | static Trans inverse_trans_aux[NTRANS]; | ||
| 108 | static int epos_dependent_aux[BINOM12ON4][BINOM12ON4]; | ||
| 109 | static int cphtr_left_cosets[FACTORIAL8]; | ||
| 110 | static int cphtr_right_cosets[FACTORIAL8]; | ||
| 111 | static int cphtr_right_rep[BINOM8ON4*6]; | ||
| 112 | static Center what_center_at_aux[FACTORIAL6][6]; | ||
| 113 | static Corner what_corner_at_aux[FACTORIAL8][8]; | ||
| 114 | static int what_orientation_last_corner_aux[POW3TO7]; | ||
| 115 | static int what_orientation_last_edge_aux[POW2TO11]; | ||
| 116 | static Center where_is_center_aux[FACTORIAL6][6]; | ||
| 117 | static Corner where_is_corner_aux[FACTORIAL8][8]; | ||
| 118 | static Edge where_is_edge_aux[3][FACTORIAL12/FACTORIAL8][12]; | ||
| 119 | |||
| 120 | static int epose_ttable[NTRANS][FACTORIAL12/FACTORIAL8]; | ||
| 121 | static int eposs_ttable[NTRANS][FACTORIAL12/FACTORIAL8]; | ||
| 122 | static int eposm_ttable[NTRANS][FACTORIAL12/FACTORIAL8]; | ||
| 123 | static int eo_ttable[NTRANS][POW2TO11]; | ||
| 124 | static int cp_ttable[NTRANS][FACTORIAL8]; | ||
| 125 | static int co_ttable[NTRANS][POW3TO7]; | ||
| 126 | static int cpos_ttable[NTRANS][FACTORIAL6]; | ||
| 127 | static Move moves_ttable[NTRANS][NMOVES]; | ||
| 128 | |||
| 129 | static int epose_mtable[NMOVES][FACTORIAL12/FACTORIAL8]; | ||
| 130 | static int eposs_mtable[NMOVES][FACTORIAL12/FACTORIAL8]; | ||
| 131 | static int eposm_mtable[NMOVES][FACTORIAL12/FACTORIAL8]; | ||
| 132 | static int eofb_mtable[NMOVES][POW2TO11]; | ||
| 133 | static int eorl_mtable[NMOVES][POW2TO11]; | ||
| 134 | static int eoud_mtable[NMOVES][POW2TO11]; | ||
| 135 | static int cp_mtable[NMOVES][FACTORIAL8]; | ||
| 136 | static int coud_mtable[NMOVES][POW3TO7]; | ||
| 137 | static int cofb_mtable[NMOVES][POW3TO7]; | ||
| 138 | static int corl_mtable[NMOVES][POW3TO7]; | ||
| 139 | static int cpos_mtable[NMOVES][FACTORIAL6]; | ||
| 140 | |||
| 141 | static uint64_t me[12]; | ||
| 142 | |||
| 143 | static int edge_cycle[NMOVES][12]; | ||
| 144 | static int corner_cycle[NMOVES][8]; | ||
| 145 | static int center_cycle[NMOVES][6]; | ||
| 146 | static int eofb_flipped[NMOVES][12]; | ||
| 147 | static int eorl_flipped[NMOVES][12]; | ||
| 148 | static int eoud_flipped[NMOVES][12]; | ||
| 149 | static int coud_flipped[NMOVES][8]; | ||
| 150 | static int corl_flipped[NMOVES][8]; | ||
| 151 | static int cofb_flipped[NMOVES][8]; | ||
| 152 | static Alg * equiv_alg[NMOVES]; | ||
| 153 | |||
| 154 | static int epose_source[NTRANS]; /* 0=epose, 1=eposs, 2=eposm */ | ||
| 155 | static int eposs_source[NTRANS]; | ||
| 156 | static int eposm_source[NTRANS]; | ||
| 157 | static int eofb_source[NTRANS]; /* 0=eoud, 1=eorl, 2=eofb */ | ||
| 158 | static int eorl_source[NTRANS]; | ||
| 159 | static int eoud_source[NTRANS]; | ||
| 160 | static int coud_source[NTRANS]; /* 0=coud, 1=corl, 2=cofb */ | ||
| 161 | static int cofb_source[NTRANS]; | ||
| 162 | static int corl_source[NTRANS]; | ||
| 163 | static int ep_mirror[12]; | ||
| 164 | static int cp_mirror[8]; | ||
| 165 | static int cpos_mirror[6]; | ||
| 166 | static Alg * rotation_algs[NROTATIONS]; | ||
| 167 | |||
| 168 | |||
| 169 | /* Symmetry data for some coordinates ****************************************/ | ||
| 170 | |||
| 171 | static Trans | ||
| 172 | trans_group_udfix[16] = { | ||
| 173 | uf, ur, ub, ul, | ||
| 174 | df, dr, db, dl, | ||
| 175 | uf_mirror, ur_mirror, ub_mirror, ul_mirror, | ||
| 176 | df_mirror, dr_mirror, db_mirror, dl_mirror, | ||
| 177 | }; | ||
| 178 | |||
| 179 | SymData | ||
| 180 | sd_coud_16 = { | ||
| 181 | .filename = "sd_coud_16", | ||
| 182 | .coord = &coord_coud, | ||
| 183 | .sym_coord = &coord_coud_sym16, | ||
| 184 | .ntrans = 16, | ||
| 185 | .trans = trans_group_udfix | ||
| 186 | }; | ||
| 187 | |||
| 188 | SymData | ||
| 189 | sd_eofbepos_16 = { | ||
| 190 | .filename = "sd_eofbepos_16", | ||
| 191 | .coord = &coord_eofbepos, | ||
| 192 | .sym_coord = &coord_eofbepos_sym16, | ||
| 193 | .ntrans = 16, | ||
| 194 | .trans = trans_group_udfix | ||
| 195 | }; | ||
| 196 | |||
| 197 | static int n_all_symdata = 2; | ||
| 198 | static SymData * all_sd[2] = { &sd_coud_16, &sd_eofbepos_16 }; | ||
| 199 | |||
| 200 | /* Coordinates and their implementation **************************************/ | ||
| 201 | |||
| 202 | static uint64_t index_eofb(Cube cube); | ||
| 203 | static uint64_t index_eofbepos(Cube cube); | ||
| 204 | static uint64_t index_coud(Cube cube); | ||
| 205 | static uint64_t index_corners(Cube cube); | ||
| 206 | static uint64_t index_cornershtr(Cube cube); | ||
| 207 | static uint64_t index_drud(Cube cube); | ||
| 208 | static uint64_t index_coud_sym16(Cube cube); | ||
| 209 | static uint64_t index_eofbepos_sym16(Cube cube); | ||
| 210 | static uint64_t index_drud_sym16(Cube cube); | ||
| 211 | static uint64_t index_khuge(Cube cube); | ||
| 212 | |||
| 213 | static Cube antindex_eofb(uint64_t ind); | ||
| 214 | static Cube antindex_eofbepos(uint64_t ind); | ||
| 215 | static Cube antindex_coud(uint64_t ind); | ||
| 216 | static Cube antindex_corners(uint64_t ind); | ||
| 217 | static Cube antindex_cornershtr(uint64_t ind); | ||
| 218 | static Cube antindex_drud(uint64_t ind); | ||
| 219 | static Cube antindex_coud_sym16(uint64_t ind); | ||
| 220 | static Cube antindex_eofbepos_sym16(uint64_t ind); | ||
| 221 | static Cube antindex_drud_sym16(uint64_t ind); | ||
| 222 | static Cube antindex_khuge(uint64_t ind); | ||
| 223 | |||
| 224 | Coordinate | ||
| 225 | coord_eofb = { | ||
| 226 | .index = index_eofb, | ||
| 227 | .cube = antindex_eofb, | ||
| 228 | .check = check_eofb, | ||
| 229 | .max = POW2TO11 | ||
| 230 | }; | ||
| 231 | |||
| 232 | Coordinate | ||
| 233 | coord_eofbepos = { | ||
| 234 | .index = index_eofbepos, | ||
| 235 | .cube = antindex_eofbepos, | ||
| 236 | .check = check_eofbepos, | ||
| 237 | .max = POW2TO11 * BINOM12ON4 | ||
| 238 | }; | ||
| 239 | |||
| 240 | Coordinate | ||
| 241 | coord_coud = { | ||
| 242 | .index = index_coud, | ||
| 243 | .cube = antindex_coud, | ||
| 244 | .check = check_coud, | ||
| 245 | .max = POW3TO7 | ||
| 246 | }; | ||
| 247 | |||
| 248 | Coordinate | ||
| 249 | coord_corners = { | ||
| 250 | .index = index_corners, | ||
| 251 | .cube = antindex_corners, | ||
| 252 | .check = check_corners, | ||
| 253 | .max = POW3TO7 * FACTORIAL8 | ||
| 254 | }; | ||
| 255 | |||
| 256 | Coordinate | ||
| 257 | coord_cornershtr = { | ||
| 258 | .index = index_cornershtr, | ||
| 259 | .cube = antindex_cornershtr, | ||
| 260 | .check = check_cornershtr, | ||
| 261 | .max = POW3TO7 * BINOM8ON4 * 6 | ||
| 262 | }; | ||
| 263 | |||
| 264 | Coordinate | ||
| 265 | coord_drud = { | ||
| 266 | .index = index_drud, | ||
| 267 | .cube = antindex_drud, | ||
| 268 | .check = check_drud, | ||
| 269 | .max = POW2TO11 * POW3TO7 * BINOM12ON4 | ||
| 270 | }; | ||
| 271 | |||
| 272 | Coordinate | ||
| 273 | coord_eofbepos_sym16 = { | ||
| 274 | .index = index_eofbepos_sym16, | ||
| 275 | .cube = antindex_eofbepos_sym16, | ||
| 276 | .check = check_eofbepos, | ||
| 277 | }; | ||
| 278 | |||
| 279 | Coordinate | ||
| 280 | coord_coud_sym16 = { | ||
| 281 | .index = index_coud_sym16, | ||
| 282 | .cube = antindex_coud_sym16, | ||
| 283 | .check = check_coud, | ||
| 284 | }; | ||
| 285 | |||
| 286 | Coordinate | ||
| 287 | coord_drud_sym16 = { | ||
| 288 | .index = index_drud_sym16, | ||
| 289 | .cube = antindex_drud_sym16, | ||
| 290 | .check = check_drud, | ||
| 291 | .max = POW3TO7 * 64430 | ||
| 292 | }; | ||
| 293 | |||
| 294 | Coordinate | ||
| 295 | coord_khuge = { | ||
| 296 | .index = index_khuge, | ||
| 297 | .cube = antindex_khuge, | ||
| 298 | .check = check_khuge, | ||
| 299 | .max = POW3TO7 * FACTORIAL4 * 64430 | ||
| 300 | }; | ||
| 301 | |||
| 302 | |||
| 303 | static uint64_t | ||
| 304 | index_eofb(Cube cube) | ||
| 305 | { | ||
| 306 | return cube.eofb; | ||
| 307 | } | ||
| 308 | |||
| 309 | static uint64_t | ||
| 310 | index_eofbepos(Cube cube) | ||
| 311 | { | ||
| 312 | return (cube.epose / FACTORIAL4) * POW2TO11 + cube.eofb; | ||
| 313 | } | ||
| 314 | |||
| 315 | static uint64_t | ||
| 316 | index_coud(Cube cube) | ||
| 317 | { | ||
| 318 | return cube.coud; | ||
| 319 | } | ||
| 320 | |||
| 321 | static uint64_t | ||
| 322 | index_corners(Cube cube) | ||
| 323 | { | ||
| 324 | return cube.coud * FACTORIAL8 + cube.cp; | ||
| 325 | } | ||
| 326 | |||
| 327 | static uint64_t | ||
| 328 | index_cornershtr(Cube cube) | ||
| 329 | { | ||
| 330 | return cube.coud * BINOM8ON4 * 6 + cphtr(cube); | ||
| 331 | } | ||
| 332 | |||
| 333 | static uint64_t | ||
| 334 | index_drud(Cube cube) | ||
| 335 | { | ||
| 336 | uint64_t a, b, c; | ||
| 337 | |||
| 338 | a = cube.eofb; | ||
| 339 | b = cube.coud; | ||
| 340 | c = cube.epose / FACTORIAL4; | ||
| 341 | |||
| 342 | b *= POW2TO11; | ||
| 343 | c *= POW2TO11 * POW3TO7; | ||
| 344 | |||
| 345 | return a + b + c; | ||
| 346 | } | ||
| 347 | |||
| 348 | static uint64_t | ||
| 349 | index_coud_sym16(Cube cube) | ||
| 350 | { | ||
| 351 | return sd_coud_16.class[index_coud(cube)]; | ||
| 352 | } | ||
| 353 | |||
| 354 | static uint64_t | ||
| 355 | index_drud_sym16(Cube cube) | ||
| 356 | { | ||
| 357 | Trans t; | ||
| 358 | Cube c; | ||
| 359 | |||
| 360 | t = sd_eofbepos_16.transtorep[index_eofbepos(cube)]; | ||
| 361 | c = apply_trans(t, cube); | ||
| 362 | |||
| 363 | return index_eofbepos_sym16(c) * POW3TO7 + c.coud; | ||
| 364 | } | ||
| 365 | |||
| 366 | static uint64_t | ||
| 367 | index_eofbepos_sym16(Cube cube) | ||
| 368 | { | ||
| 369 | return sd_eofbepos_16.class[index_eofbepos(cube)]; | ||
| 370 | } | ||
| 371 | |||
| 372 | static uint64_t | ||
| 373 | index_khuge(Cube cube) | ||
| 374 | { | ||
| 375 | Trans t; | ||
| 376 | Cube c; | ||
| 377 | uint64_t a; | ||
| 378 | |||
| 379 | t = sd_eofbepos_16.transtorep[index_eofbepos(cube)]; | ||
| 380 | c = apply_trans(t, cube); | ||
| 381 | a = (index_eofbepos_sym16(c) * 24) + (c.epose % 24); | ||
| 382 | |||
| 383 | return a * POW3TO7 + c.coud; | ||
| 384 | } | ||
| 385 | |||
| 386 | |||
| 387 | /* TODO: rename */ | ||
| 388 | static Cube | ||
| 389 | antindex_eofb(uint64_t ind) | ||
| 390 | { | ||
| 391 | return (Cube){ .eofb = ind, .eorl = ind, .eoud = ind }; | ||
| 392 | } | ||
| 393 | |||
| 394 | static Cube | ||
| 395 | antindex_eofbepos(uint64_t ind) | ||
| 396 | { | ||
| 397 | return admissible_ee_aux[ind]; | ||
| 398 | } | ||
| 399 | |||
| 400 | /* TODO: rename */ | ||
| 401 | static Cube | ||
| 402 | antindex_coud(uint64_t ind) | ||
| 403 | { | ||
| 404 | return (Cube){ .coud = ind, .corl = ind, .cofb = ind }; | ||
| 405 | } | ||
| 406 | |||
| 407 | /* TODO: admissible co for other orientations */ | ||
| 408 | static Cube | ||
| 409 | antindex_corners(uint64_t ind) | ||
| 410 | { | ||
| 411 | Cube c = {0}; | ||
| 412 | |||
| 413 | c.coud = ind / FACTORIAL8; | ||
| 414 | c.cp = ind % FACTORIAL8; | ||
| 415 | |||
| 416 | return c; | ||
| 417 | } | ||
| 418 | |||
| 419 | /* TODO: admissible co for other orientations */ | ||
| 420 | static Cube | ||
| 421 | antindex_cornershtr(uint64_t ind) | ||
| 422 | { | ||
| 423 | Cube c = anti_cphtr(ind % (BINOM8ON4 * 6)); | ||
| 424 | |||
| 425 | c.coud = ind / (BINOM8ON4 * 6); | ||
| 426 | |||
| 427 | return c; | ||
| 428 | } | ||
| 429 | |||
| 430 | /* TODO: admissible eos and cos */ | ||
| 431 | static Cube | ||
| 432 | antindex_drud(uint64_t ind) | ||
| 433 | { | ||
| 434 | Cube c = {0}; | ||
| 435 | |||
| 436 | c.eofb = ind % POW2TO11; | ||
| 437 | c.coud = (ind / POW2TO11) % POW3TO7; | ||
| 438 | c.epose = (ind % (POW2TO11 * POW3TO7)) * FACTORIAL4; | ||
| 439 | |||
| 440 | return c; | ||
| 441 | } | ||
| 442 | |||
| 443 | static Cube | ||
| 444 | antindex_coud_sym16(uint64_t ind) | ||
| 445 | { | ||
| 446 | return sd_coud_16.rep[ind]; | ||
| 447 | } | ||
| 448 | |||
| 449 | static Cube | ||
| 450 | antindex_eofbepos_sym16(uint64_t ind) | ||
| 451 | { | ||
| 452 | return sd_eofbepos_16.rep[ind]; | ||
| 453 | } | ||
| 454 | |||
| 455 | static Cube | ||
| 456 | antindex_drud_sym16(uint64_t ind) | ||
| 457 | { | ||
| 458 | Cube c; | ||
| 459 | |||
| 460 | c = sd_eofbepos_16.rep[ind/POW3TO7]; | ||
| 461 | c.coud = ind % POW3TO7; | ||
| 462 | c.cofb = c.coud; | ||
| 463 | c.corl = c.coud; | ||
| 464 | |||
| 465 | return c; | ||
| 466 | } | ||
| 467 | |||
| 468 | static Cube | ||
| 469 | antindex_khuge(uint64_t ind) | ||
| 470 | { | ||
| 471 | Cube c; | ||
| 472 | |||
| 473 | c = sd_eofbepos_16.rep[ind/(FACTORIAL4*POW3TO7)]; | ||
| 474 | c.epose = ((c.epose / 24) * 24) + ((ind/POW3TO7) % 24); | ||
| 475 | c.coud = ind % POW3TO7; | ||
| 476 | |||
| 477 | return c; | ||
| 478 | } | ||
| 479 | |||
| 480 | |||
| 481 | /* Checkers ******************************************************************/ | ||
| 482 | |||
| 483 | bool | ||
| 484 | check_centers(Cube cube) | ||
| 485 | { | ||
| 486 | return cube.cpos == 0; | ||
| 487 | } | ||
| 488 | |||
| 489 | bool | ||
| 490 | check_corners(Cube cube) | ||
| 491 | { | ||
| 492 | return cube.cp == 0 && cube.coud == 0; | ||
| 493 | } | ||
| 494 | |||
| 495 | bool | ||
| 496 | check_cornershtr(Cube cube) | ||
| 497 | { | ||
| 498 | return cube.coud == 0 && cphtr(cube) == 0; /* TODO: use array cphtrcosets*/ | ||
| 499 | } | ||
| 500 | |||
| 501 | bool | ||
| 502 | check_coud(Cube cube) | ||
| 503 | { | ||
| 504 | return cube.coud == 0; | ||
| 505 | } | ||
| 506 | |||
| 507 | bool | ||
| 508 | check_drud(Cube cube) | ||
| 509 | { | ||
| 510 | return cube.eofb == 0 && cube.eorl == 0 && cube.coud == 0; | ||
| 511 | } | ||
| 512 | |||
| 513 | bool | ||
| 514 | check_eofb(Cube cube) | ||
| 515 | { | ||
| 516 | return cube.eofb == 0; | ||
| 517 | } | ||
| 518 | |||
| 519 | bool | ||
| 520 | check_eofbepos(Cube cube) | ||
| 521 | { | ||
| 522 | return cube.eofb == 0 && cube.epose / 24 == 0; | ||
| 523 | } | ||
| 524 | |||
| 525 | bool | ||
| 526 | check_epose(Cube cube) | ||
| 527 | { | ||
| 528 | return cube.epose == 0; | ||
| 529 | } | ||
| 530 | |||
| 531 | bool | ||
| 532 | check_ep(Cube cube) | ||
| 533 | { | ||
| 534 | return cube.epose == 0 && cube.eposs == 0 && cube.eposm == 0; | ||
| 535 | } | ||
| 536 | |||
| 537 | bool | ||
| 538 | check_khuge(Cube cube) | ||
| 539 | { | ||
| 540 | return check_drud(cube) && cube.epose % 24 == 0; | ||
| 541 | } | ||
| 542 | |||
| 543 | bool | ||
| 544 | check_nothing(Cube cube) | ||
| 545 | { | ||
| 546 | return is_admissible(cube); /*TODO: maybe change?*/ | ||
| 547 | } | ||
| 548 | |||
| 549 | /* Movesets ******************************************************************/ | ||
| 550 | |||
| 551 | bool | ||
| 552 | moveset_HTM(Move m) | ||
| 553 | { | ||
| 554 | return m >= U && m <= B3; | ||
| 555 | } | ||
| 556 | |||
| 557 | bool | ||
| 558 | moveset_URF(Move m) | ||
| 559 | { | ||
| 560 | Move b = base_move(m); | ||
| 561 | |||
| 562 | return b == U || b == R || b == F; | ||
| 563 | } | ||
| 564 | |||
| 565 | |||
| 566 | /* Local functions implementation ********************************************/ | ||
| 567 | |||
| 568 | /* TODO: this should be an anti index (maybe?) */ | ||
| 569 | static Cube | ||
| 570 | admissible_ep(Cube cube, PieceFilter f) | ||
| 571 | { | ||
| 572 | CubeArray *arr = new_cubearray(cube, f); | ||
| 573 | Cube ret; | ||
| 574 | bool used[12] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; | ||
| 575 | int i, j; | ||
| 576 | |||
| 577 | for (i = 0; i < 12; i++) | ||
| 578 | if (arr->ep[i] != -1) | ||
| 579 | used[arr->ep[i]] = true; | ||
| 580 | |||
| 581 | for (i = 0, j = 0; i < 12; i++) { | ||
| 582 | for ( ; j < 11 && used[j]; j++); | ||
| 583 | if (arr->ep[i] == -1) | ||
| 584 | arr->ep[i] = j++; | ||
| 585 | } | ||
| 586 | |||
| 587 | ret = arrays_to_cube(arr, pf_ep); | ||
| 588 | free_cubearray(arr, f); | ||
| 589 | |||
| 590 | return ret; | ||
| 591 | } | ||
| 592 | |||
| 593 | static Cube | ||
| 594 | admissible_eos_from_eofbepos(Cube cube) | ||
| 595 | { | ||
| 596 | Edge e; | ||
| 597 | Cube ret; | ||
| 598 | CubeArray *arr = new_cubearray(cube, pf_all); | ||
| 599 | |||
| 600 | memcpy(arr->eorl, arr->eofb, 12 * sizeof(int)); | ||
| 601 | memcpy(arr->eoud, arr->eofb, 12 * sizeof(int)); | ||
| 602 | |||
| 603 | for (e = 0; e < 12; e++) { | ||
| 604 | if ((edge_slice(e) != 0 && edge_slice(arr->ep[e]) == 0) || | ||
| 605 | (edge_slice(e) == 0 && edge_slice(arr->ep[e]) != 0)) | ||
| 606 | arr->eorl[e] = 1 - arr->eorl[e]; | ||
| 607 | if ((edge_slice(e) != 2 && edge_slice(arr->ep[e]) == 2) || | ||
| 608 | (edge_slice(e) == 2 && edge_slice(arr->ep[e]) != 2)) | ||
| 609 | arr->eoud[e] = 1 - arr->eoud[e]; | ||
| 610 | } | ||
| 611 | |||
| 612 | ret = arrays_to_cube(arr, pf_all); | ||
| 613 | free_cubearray(arr, pf_all); | ||
| 614 | |||
| 615 | return ret; | ||
| 616 | } | ||
| 617 | |||
| 618 | static bool | ||
| 619 | allowed_next(Move move, DfsData *dd) | ||
| 620 | { | ||
| 621 | if (!possible_next[dd->last2][dd->last1][move]) | ||
| 622 | return false; | ||
| 623 | |||
| 624 | if (commute[dd->last1][move]) | ||
| 625 | return dd->move_position[dd->last1] < dd->move_position[move]; | ||
| 626 | |||
| 627 | return true; | ||
| 628 | } | ||
| 629 | |||
| 630 | static void | ||
| 631 | append_alg(AlgList *l, Alg *alg) | ||
| 632 | { | ||
| 633 | AlgListNode *node = malloc(sizeof(AlgListNode)); | ||
| 634 | int i; | ||
| 635 | |||
| 636 | node->alg = new_alg(""); | ||
| 637 | for (i = 0; i < alg->len; i++) | ||
| 638 | append_move(node->alg, alg->move[i], alg->inv[i]); | ||
| 639 | node->next = NULL; | ||
| 640 | |||
| 641 | if (++l->len == 1) | ||
| 642 | l->first = node; | ||
| 643 | else | ||
| 644 | l->last->next = node; | ||
| 645 | l->last = node; | ||
| 646 | } | ||
| 647 | |||
| 648 | static void | ||
| 649 | append_move(Alg *alg, Move m, bool inverse) | ||
| 650 | { | ||
| 651 | if (alg->len == alg->allocated) | ||
| 652 | realloc_alg(alg, 2*alg->len); | ||
| 653 | |||
| 654 | alg->move[alg->len] = m; | ||
| 655 | alg->inv [alg->len] = inverse; | ||
| 656 | alg->len++; | ||
| 657 | } | ||
| 658 | |||
| 659 | static Cube | ||
| 660 | apply_alg_generic(Alg *alg, Cube c, PieceFilter f, bool a) | ||
| 661 | { | ||
| 662 | Cube ret = {0}; | ||
| 663 | int i; | ||
| 664 | |||
| 665 | for (i = 0; i < alg->len; i++) | ||
| 666 | if (alg->inv[i]) | ||
| 667 | ret = a ? apply_move(alg->move[i], ret) : | ||
| 668 | apply_move_cubearray(alg->move[i], ret, f); | ||
| 669 | |||
| 670 | ret = compose_filtered(c, inverse_cube(ret), f); | ||
| 671 | |||
| 672 | for (i = 0; i < alg->len; i++) | ||
| 673 | if (!alg->inv[i]) | ||
| 674 | ret = a ? apply_move(alg->move[i], ret) : | ||
| 675 | apply_move_cubearray(alg->move[i], ret, f); | ||
| 676 | |||
| 677 | return ret; | ||
| 678 | } | ||
| 679 | |||
| 680 | static void | ||
| 681 | apply_permutation(int *perm, int *set, int n) | ||
| 682 | { | ||
| 683 | int *aux = malloc(n * sizeof(int)); | ||
| 684 | int i; | ||
| 685 | |||
| 686 | if (!is_perm(perm, n)) | ||
| 687 | return; | ||
| 688 | |||
| 689 | for (i = 0; i < n; i++) | ||
| 690 | aux[i] = set[perm[i]]; | ||
| 691 | |||
| 692 | memcpy(set, aux, n * sizeof(int)); | ||
| 693 | free(aux); | ||
| 694 | } | ||
| 695 | |||
| 696 | static Cube | ||
| 697 | apply_move_cubearray(Move m, Cube cube, PieceFilter f) | ||
| 698 | { | ||
| 699 | CubeArray m_arr = { | ||
| 700 | edge_cycle[m], | ||
| 701 | eofb_flipped[m], | ||
| 702 | eorl_flipped[m], | ||
| 703 | eoud_flipped[m], | ||
| 704 | corner_cycle[m], | ||
| 705 | coud_flipped[m], | ||
| 706 | corl_flipped[m], | ||
| 707 | cofb_flipped[m], | ||
| 708 | center_cycle[m] | ||
| 709 | }; | ||
| 710 | |||
| 711 | return move_via_arrays(&m_arr, cube, f); | ||
| 712 | } | ||
| 713 | |||
| 714 | static int | ||
| 715 | array_ep_to_epos(int *ep, int *ss) | ||
| 716 | { | ||
| 717 | int epos[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; | ||
| 718 | int eps[4]; | ||
| 719 | int i, j, is; | ||
| 720 | |||
| 721 | for (i = 0, is = 0; i < 12; i++) { | ||
| 722 | for (j = 0; j < 4; j++) { | ||
| 723 | if (ep[i] == ss[j]) { | ||
| 724 | eps[is++] = j; | ||
| 725 | epos[i] = 1; | ||
| 726 | } | ||
| 727 | } | ||
| 728 | } | ||
| 729 | |||
| 730 | for (i = 0; i < 4; i++) | ||
| 731 | swap(&epos[ss[i]], &epos[i+8]); | ||
| 732 | |||
| 733 | return epos_from_arrays(epos, eps); | ||
| 734 | } | ||
| 735 | |||
| 736 | static Cube | ||
| 737 | arrays_to_cube(CubeArray *arr, PieceFilter f) | ||
| 738 | { | ||
| 739 | Cube ret = {0}; | ||
| 740 | |||
| 741 | if (f.epose) | ||
| 742 | ret.epose = array_ep_to_epos(arr->ep, epe_solved); | ||
| 743 | if (f.eposs) | ||
| 744 | ret.eposs = array_ep_to_epos(arr->ep, eps_solved); | ||
| 745 | if (f.eposm) | ||
| 746 | ret.eposm = array_ep_to_epos(arr->ep, epm_solved); | ||
| 747 | if (f.eofb) | ||
| 748 | ret.eofb = digit_array_to_int(arr->eofb, 11, 2); | ||
| 749 | if (f.eorl) | ||
| 750 | ret.eorl = digit_array_to_int(arr->eorl, 11, 2); | ||
| 751 | if (f.eoud) | ||
| 752 | ret.eoud = digit_array_to_int(arr->eoud, 11, 2); | ||
| 753 | if (f.cp) | ||
| 754 | ret.cp = perm_to_index(arr->cp, 8); | ||
| 755 | if (f.coud) | ||
| 756 | ret.coud = digit_array_to_int(arr->coud, 7, 3); | ||
| 757 | if (f.corl) | ||
| 758 | ret.corl = digit_array_to_int(arr->corl, 7, 3); | ||
| 759 | if (f.cofb) | ||
| 760 | ret.cofb = digit_array_to_int(arr->cofb, 7, 3); | ||
| 761 | if (f.cpos) | ||
| 762 | ret.cpos = perm_to_index(arr->cpos, 6); | ||
| 763 | |||
| 764 | return ret; | ||
| 765 | } | ||
| 766 | |||
| 767 | static int | ||
| 768 | binomial(int n, int k) | ||
| 769 | { | ||
| 770 | if (n < 0 || k < 0 || k > n) | ||
| 771 | return 0; | ||
| 772 | |||
| 773 | return factorial(n) / (factorial(k) * factorial(n-k)); | ||
| 774 | } | ||
| 775 | |||
| 776 | static Cube | ||
| 777 | compose_filtered(Cube c2, Cube c1, PieceFilter f) | ||
| 778 | { | ||
| 779 | CubeArray *arr = new_cubearray(c2, f); | ||
| 780 | Cube ret; | ||
| 781 | |||
| 782 | ret = move_via_arrays(arr, c1, f); | ||
| 783 | free_cubearray(arr, f); | ||
| 784 | |||
| 785 | return ret; | ||
| 786 | } | ||
| 787 | |||
| 788 | static void | ||
| 789 | cube_to_arrays(Cube cube, CubeArray *arr, PieceFilter f) | ||
| 790 | { | ||
| 791 | int i; | ||
| 792 | |||
| 793 | if (f.epose || f.eposs || f.eposm) | ||
| 794 | for (i = 0; i < 12; i++) | ||
| 795 | arr->ep[i] = -1; | ||
| 796 | |||
| 797 | if (f.epose) | ||
| 798 | epos_to_partial_ep(cube.epose, arr->ep, epe_solved); | ||
| 799 | if (f.eposs) | ||
| 800 | epos_to_partial_ep(cube.eposs, arr->ep, eps_solved); | ||
| 801 | if (f.eposm) | ||
| 802 | epos_to_partial_ep(cube.eposm, arr->ep, epm_solved); | ||
| 803 | if (f.eofb) | ||
| 804 | int_to_sum_zero_array(cube.eofb, 2, 12, arr->eofb); | ||
| 805 | if (f.eorl) | ||
| 806 | int_to_sum_zero_array(cube.eorl, 2, 12, arr->eorl); | ||
| 807 | if (f.eoud) | ||
| 808 | int_to_sum_zero_array(cube.eoud, 2, 12, arr->eoud); | ||
| 809 | if (f.cp) | ||
| 810 | index_to_perm(cube.cp, 8, arr->cp); | ||
| 811 | if (f.coud) | ||
| 812 | int_to_sum_zero_array(cube.coud, 3, 8, arr->coud); | ||
| 813 | if (f.corl) | ||
| 814 | int_to_sum_zero_array(cube.corl, 3, 8, arr->corl); | ||
| 815 | if (f.cofb) | ||
| 816 | int_to_sum_zero_array(cube.cofb, 3, 8, arr->cofb); | ||
| 817 | if (f.cpos) | ||
| 818 | index_to_perm(cube.cpos, 6, arr->cpos); | ||
| 819 | } | ||
| 820 | |||
| 821 | /* | ||
| 822 | static int | ||
| 823 | cphtr_cp(int cp) | ||
| 824 | { | ||
| 825 | int i, a[8]; | ||
| 826 | |||
| 827 | index_to_perm(cp, 8, a); | ||
| 828 | |||
| 829 | for (i = 0; i < 8; i++) | ||
| 830 | if (a[i] == UFR || a[i] == UBL || a[i] == DFL || a[i] == DBR) | ||
| 831 | a[i] = 0; | ||
| 832 | else | ||
| 833 | a[i] = 1; | ||
| 834 | |||
| 835 | swap(&a[1], &a[5]); | ||
| 836 | swap(&a[3], &a[7]); | ||
| 837 | |||
| 838 | return subset_to_index(a, 8, 4); | ||
| 839 | } | ||
| 840 | */ | ||
| 841 | |||
| 842 | static void | ||
| 843 | dfs(Cube c, Step s, SolveOptions *opts, DfsData *dd) | ||
| 844 | { | ||
| 845 | if (dfs_stop(c, s, opts, dd)) | ||
| 846 | return; | ||
| 847 | |||
| 848 | if (dfs_check_solved(opts, dd)) | ||
| 849 | return; | ||
| 850 | |||
| 851 | dfs_branch(c, s, opts, dd); | ||
| 852 | |||
| 853 | if (opts->can_niss && !dd->niss) | ||
| 854 | dfs_niss(c, s, opts, dd); | ||
| 855 | } | ||
| 856 | |||
| 857 | static void | ||
| 858 | dfs_branch(Cube c, Step s, SolveOptions *opts, DfsData *dd) | ||
| 859 | { | ||
| 860 | Move m, l1 = dd->last1, l2 = dd->last2, *moves = dd->sorted_moves; | ||
| 861 | |||
| 862 | int i, maxnsol = opts->max_solutions; | ||
| 863 | |||
| 864 | for (i = 0; moves[i] != NULLMOVE && dd->sols->len < maxnsol; i++) { | ||
| 865 | m = moves[i]; | ||
| 866 | if (allowed_next(m, dd)) { | ||
| 867 | dd->last2 = dd->last1; | ||
| 868 | dd->last1 = m; | ||
| 869 | append_move(dd->current_alg, m, dd->niss); | ||
| 870 | |||
| 871 | dfs(apply_move(m, c), s, opts, dd); | ||
| 872 | |||
| 873 | dd->current_alg->len--; | ||
| 874 | dd->last2 = l2; | ||
| 875 | dd->last1 = l1; | ||
| 876 | } | ||
| 877 | } | ||
| 878 | } | ||
| 879 | |||
| 880 | static bool | ||
| 881 | dfs_check_solved(SolveOptions *opts, DfsData *dd) | ||
| 882 | { | ||
| 883 | if (dd->lb != 0) | ||
| 884 | return false; | ||
| 885 | |||
| 886 | if (dd->current_alg->len == dd->d) { | ||
| 887 | append_alg(dd->sols, dd->current_alg); | ||
| 888 | |||
| 889 | if (opts->feedback) | ||
| 890 | print_alg(dd->current_alg, false); | ||
| 891 | } | ||
| 892 | |||
| 893 | return true; | ||
| 894 | } | ||
| 895 | |||
| 896 | static void | ||
| 897 | dfs_niss(Cube c, Step s, SolveOptions *opts, DfsData *dd) | ||
| 898 | { | ||
| 899 | Move l1 = dd->last1, l2 = dd->last2; | ||
| 900 | CubeTarget ct; | ||
| 901 | |||
| 902 | ct.cube = apply_move(inverse_move(l1), (Cube){0}); | ||
| 903 | ct.target = 1; | ||
| 904 | |||
| 905 | if (dd->current_alg->len == 0 || s.estimate(ct)) { | ||
| 906 | dd->niss = true; | ||
| 907 | dd->last1 = NULLMOVE; | ||
| 908 | dd->last2 = NULLMOVE; | ||
| 909 | |||
| 910 | dfs(inverse_cube(c), s, opts, dd); | ||
| 911 | |||
| 912 | dd->last1 = l1; | ||
| 913 | dd->last2 = l2; | ||
| 914 | dd->niss = false; | ||
| 915 | } | ||
| 916 | } | ||
| 917 | |||
| 918 | static bool | ||
| 919 | dfs_stop(Cube c, Step s, SolveOptions *opts, DfsData *dd) | ||
| 920 | { | ||
| 921 | CubeTarget ct = { | ||
| 922 | .cube = c, | ||
| 923 | .target = dd->d - dd->current_alg->len | ||
| 924 | }; | ||
| 925 | |||
| 926 | if (dd->sols->len >= opts->max_solutions) | ||
| 927 | return true; | ||
| 928 | |||
| 929 | dd->lb = s.estimate(ct); | ||
| 930 | if (opts->can_niss && !dd->niss) | ||
| 931 | dd->lb = MIN(1, dd->lb); | ||
| 932 | |||
| 933 | if (dd->current_alg->len + dd->lb > dd->d) | ||
| 934 | return true; | ||
| 935 | |||
| 936 | return false; | ||
| 937 | } | ||
| 938 | |||
| 939 | static int | ||
| 940 | digit_array_to_int(int *a, int n, int b) | ||
| 941 | { | ||
| 942 | int i, ret = 0, p = 1; | ||
| 943 | |||
| 944 | for (i = 0; i < n; i++, p *= b) | ||
| 945 | ret += a[i] * p; | ||
| 946 | |||
| 947 | return ret; | ||
| 948 | } | ||
| 949 | |||
| 950 | static int | ||
| 951 | edge_slice(Edge e) { | ||
| 952 | if (e < 0 || e > 11) | ||
| 953 | return -1; | ||
| 954 | |||
| 955 | if (e == FR || e == FL || e == BL || e == BR) | ||
| 956 | return 0; | ||
| 957 | if (e == UR || e == UL || e == DR || e == DL) | ||
| 958 | return 1; | ||
| 959 | |||
| 960 | return 2; | ||
| 961 | } | ||
| 962 | |||
| 963 | static int | ||
| 964 | epos_dependent_pos(int poss, int pose) | ||
| 965 | { | ||
| 966 | int ep[12] = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}; | ||
| 967 | int ep8[8] = {0, 0, 0, 0, 0, 0, 0, 0}; | ||
| 968 | int i, j; | ||
| 969 | |||
| 970 | epos_to_partial_ep(poss*FACTORIAL4, ep, eps_solved); | ||
| 971 | epos_to_partial_ep(pose*FACTORIAL4, ep, epe_solved); | ||
| 972 | |||
| 973 | for (i = 0, j = 0; i < 12; i++) | ||
| 974 | if (edge_slice(ep[i]) != 0) | ||
| 975 | ep8[j++] = (edge_slice(ep[i]) == 1) ? 1 : 0; | ||
| 976 | |||
| 977 | swap(&ep8[1], &ep8[4]); | ||
| 978 | swap(&ep8[3], &ep8[6]); | ||
| 979 | |||
| 980 | return subset_to_index(ep8, 8, 4); | ||
| 981 | } | ||
| 982 | |||
| 983 | static int | ||
| 984 | epos_from_arrays(int *epos, int *ep) | ||
| 985 | { | ||
| 986 | return FACTORIAL4 * subset_to_index(epos,12,4) + perm_to_index(ep,4); | ||
| 987 | } | ||
| 988 | |||
| 989 | static void | ||
| 990 | epos_to_partial_ep(int epos, int *ep, int *ss) | ||
| 991 | { | ||
| 992 | int i, is, eposs[12], eps[4]; | ||
| 993 | |||
| 994 | index_to_perm(epos % FACTORIAL4, 4, eps); | ||
| 995 | index_to_subset(epos / FACTORIAL4, 12, 4, eposs); | ||
| 996 | |||
| 997 | for (i = 0; i < 4; i++) | ||
| 998 | swap(&eposs[ss[i]], &eposs[i+8]); | ||
| 999 | |||
| 1000 | for (i = 0, is = 0; i < 12; i++) | ||
| 1001 | if (eposs[i]) | ||
| 1002 | ep[i] = ss[eps[is++]]; | ||
| 1003 | } | ||
| 1004 | |||
| 1005 | static int | ||
| 1006 | factorial(int n) | ||
| 1007 | { | ||
| 1008 | int i, ret = 1; | ||
| 1009 | |||
| 1010 | if (n < 0) | ||
| 1011 | return 0; | ||
| 1012 | |||
| 1013 | for (i = 1; i <= n; i++) | ||
| 1014 | ret *= i; | ||
| 1015 | |||
| 1016 | return ret; | ||
| 1017 | } | ||
| 1018 | |||
| 1019 | void | ||
| 1020 | free_alg(Alg *alg) | ||
| 1021 | { | ||
| 1022 | free(alg->move); | ||
| 1023 | free(alg->inv); | ||
| 1024 | free(alg); | ||
| 1025 | } | ||
| 1026 | |||
| 1027 | void | ||
| 1028 | free_alglist(AlgList *l) | ||
| 1029 | { | ||
| 1030 | AlgListNode *aux, *i = l->first; | ||
| 1031 | |||
| 1032 | while (i != NULL) { | ||
| 1033 | aux = i->next; | ||
| 1034 | free_alglistnode(i); | ||
| 1035 | i = aux; | ||
| 1036 | } | ||
| 1037 | free(l); | ||
| 1038 | } | ||
| 1039 | |||
| 1040 | void | ||
| 1041 | free_alglistnode(AlgListNode *aln) | ||
| 1042 | { | ||
| 1043 | free_alg(aln->alg); | ||
| 1044 | free(aln); | ||
| 1045 | } | ||
| 1046 | |||
| 1047 | static void | ||
| 1048 | free_cubearray(CubeArray *arr, PieceFilter f) | ||
| 1049 | { | ||
| 1050 | if (f.epose || f.eposs || f.eposm) | ||
| 1051 | free(arr->ep); | ||
| 1052 | if (f.eofb) | ||
| 1053 | free(arr->eofb); | ||
| 1054 | if (f.eorl) | ||
| 1055 | free(arr->eorl); | ||
| 1056 | if (f.eoud) | ||
| 1057 | free(arr->eoud); | ||
| 1058 | if (f.cp) | ||
| 1059 | free(arr->cp); | ||
| 1060 | if (f.coud) | ||
| 1061 | free(arr->coud); | ||
| 1062 | if (f.corl) | ||
| 1063 | free(arr->corl); | ||
| 1064 | if (f.cofb) | ||
| 1065 | free(arr->cofb); | ||
| 1066 | if (f.cpos) | ||
| 1067 | free(arr->cpos); | ||
| 1068 | |||
| 1069 | free(arr); | ||
| 1070 | } | ||
| 1071 | |||
| 1072 | static void | ||
| 1073 | genptable_dfs(Cube c, PruneData *pd, DfsData *dd) | ||
| 1074 | { | ||
| 1075 | int oldval = ptableval(pd, c); | ||
| 1076 | |||
| 1077 | if (oldval < dd->m || ptable_has_reached(pd, c) || | ||
| 1078 | pd->n == pd->coord->max || (dd->m != 0 && pd->coord->check(c)) ) | ||
| 1079 | return; | ||
| 1080 | |||
| 1081 | /*ptable_set_reached(pd, c);*/ | ||
| 1082 | |||
| 1083 | if (dd->m == dd->d) { | ||
| 1084 | if (dd->m < oldval) | ||
| 1085 | ptable_update(pd, c, dd->m); | ||
| 1086 | return; | ||
| 1087 | } | ||
| 1088 | |||
| 1089 | genptable_dfs_branch(c, pd, dd); | ||
| 1090 | } | ||
| 1091 | |||
| 1092 | static void | ||
| 1093 | genptable_dfs_branch(Cube c, PruneData *pd, DfsData *dd) | ||
| 1094 | { | ||
| 1095 | Move i, move, l1 = dd->last1, l2 = dd->last2; | ||
| 1096 | |||
| 1097 | dd->m++; | ||
| 1098 | |||
| 1099 | for (i = 0; dd->sorted_moves[i] != NULLMOVE; i++) { | ||
| 1100 | move = dd->sorted_moves[i]; | ||
| 1101 | if (allowed_next(move, dd)) { | ||
| 1102 | dd->last2 = dd->last1; | ||
| 1103 | dd->last1 = move; | ||
| 1104 | |||
| 1105 | genptable_dfs(apply_move(move, c), pd, dd); | ||
| 1106 | |||
| 1107 | dd->last2 = l2; | ||
| 1108 | dd->last1 = l1; | ||
| 1109 | } | ||
| 1110 | } | ||
| 1111 | |||
| 1112 | dd->m--; | ||
| 1113 | } | ||
| 1114 | |||
| 1115 | static void | ||
| 1116 | gensym(SymData *sd) | ||
| 1117 | { | ||
| 1118 | uint64_t i, in, nreps = 0; | ||
| 1119 | int j; | ||
| 1120 | Cube c, d; | ||
| 1121 | |||
| 1122 | if (sd->generated) | ||
| 1123 | return; | ||
| 1124 | |||
| 1125 | sd->class = malloc(sd->coord->max * sizeof(uint64_t)); | ||
| 1126 | sd->rep = malloc(sd->coord->max * sizeof(Cube)); | ||
| 1127 | sd->transtorep = malloc(sd->coord->max * sizeof(Trans)); | ||
| 1128 | |||
| 1129 | if (read_symdata_file(sd)) { | ||
| 1130 | sd->generated = true; | ||
| 1131 | return; | ||
| 1132 | } | ||
| 1133 | |||
| 1134 | fprintf(stderr, "Cannot load %s, generating it\n", sd->filename); | ||
| 1135 | |||
| 1136 | for (i = 0; i < sd->coord->max; i++) | ||
| 1137 | sd->class[i] = sd->coord->max + 1; | ||
| 1138 | |||
| 1139 | for (i = 0; i < sd->coord->max; i++) { | ||
| 1140 | if (sd->class[i] == sd->coord->max + 1) { | ||
| 1141 | c = sd->coord->cube(i); | ||
| 1142 | sd->rep[nreps] = c; | ||
| 1143 | for (j = 0; j < sd->ntrans; j++) { | ||
| 1144 | d = apply_trans(sd->trans[j], c); | ||
| 1145 | in = sd->coord->index(d); | ||
| 1146 | |||
| 1147 | if (sd->class[in] == sd->coord->max + 1) { | ||
| 1148 | sd->class[in] = nreps; | ||
| 1149 | sd->transtorep[in] = | ||
| 1150 | inverse_trans(sd->trans[j]); | ||
| 1151 | } | ||
| 1152 | } | ||
| 1153 | nreps++; | ||
| 1154 | } | ||
| 1155 | } | ||
| 1156 | |||
| 1157 | sd->sym_coord->max = nreps; | ||
| 1158 | sd->rep = realloc(sd->rep, nreps * sizeof(Cube)); | ||
| 1159 | sd->generated = true; | ||
| 1160 | |||
| 1161 | fprintf(stderr, "Found %lu classes\n", nreps); | ||
| 1162 | |||
| 1163 | if (!write_symdata_file(sd)) | ||
| 1164 | fprintf(stderr, "Error writing SymData file\n"); | ||
| 1165 | |||
| 1166 | return; | ||
| 1167 | } | ||
| 1168 | |||
| 1169 | static void | ||
| 1170 | index_to_perm(int p, int n, int *r) | ||
| 1171 | { | ||
| 1172 | int *a = malloc(n * sizeof(int)); | ||
| 1173 | int i, j, c; | ||
| 1174 | |||
| 1175 | for (i = 0; i < n; i++) | ||
| 1176 | a[i] = 0; | ||
| 1177 | |||
| 1178 | if (p < 0 || p >= factorial(n)) | ||
| 1179 | for (i = 0; i < n; i++) | ||
| 1180 | r[i] = -1; | ||
| 1181 | |||
| 1182 | for (i = 0; i < n; i++) { | ||
| 1183 | c = 0; | ||
| 1184 | j = 0; | ||
| 1185 | while (c <= p / factorial(n-i-1)) | ||
| 1186 | c += a[j++] ? 0 : 1; | ||
| 1187 | r[i] = j-1; | ||
| 1188 | a[j-1] = 1; | ||
| 1189 | p %= factorial(n-i-1); | ||
| 1190 | } | ||
| 1191 | |||
| 1192 | free(a); | ||
| 1193 | } | ||
| 1194 | |||
| 1195 | static void | ||
| 1196 | index_to_subset(int s, int n, int k, int *r) | ||
| 1197 | { | ||
| 1198 | int i, j, v; | ||
| 1199 | |||
| 1200 | if (s < 0 || s >= binomial(n, k)) { | ||
| 1201 | for (i = 0; i < n; i++) | ||
| 1202 | r[i] = -1; | ||
| 1203 | return; | ||
| 1204 | } | ||
| 1205 | |||
| 1206 | for (i = 0; i < n; i++) { | ||
| 1207 | if (k == n-i) { | ||
| 1208 | for (j = i; j < n; j++) | ||
| 1209 | r[j] = 1; | ||
| 1210 | return; | ||
| 1211 | } | ||
| 1212 | |||
| 1213 | if (k == 0) { | ||
| 1214 | for (j = i; j < n; j++) | ||
| 1215 | r[j] = 0; | ||
| 1216 | return; | ||
| 1217 | } | ||
| 1218 | |||
| 1219 | v = binomial(n-i-1, k); | ||
| 1220 | if (s >= v) { | ||
| 1221 | r[i] = 1; | ||
| 1222 | k--; | ||
| 1223 | s -= v; | ||
| 1224 | } else { | ||
| 1225 | r[i] = 0; | ||
| 1226 | } | ||
| 1227 | } | ||
| 1228 | } | ||
| 1229 | |||
| 1230 | static void | ||
| 1231 | int_to_digit_array(int a, int b, int n, int *r) | ||
| 1232 | { | ||
| 1233 | int i; | ||
| 1234 | |||
| 1235 | if (b <= 1) | ||
| 1236 | for (i = 0; i < n; i++) | ||
| 1237 | r[i] = 0; | ||
| 1238 | else | ||
| 1239 | for (i = 0; i < n; i++, a /= b) | ||
| 1240 | r[i] = a % b; | ||
| 1241 | } | ||
| 1242 | |||
| 1243 | static void | ||
| 1244 | int_to_sum_zero_array(int x, int b, int n, int *a) | ||
| 1245 | { | ||
| 1246 | int i, s = 0; | ||
| 1247 | |||
| 1248 | if (b <= 1) { | ||
| 1249 | for (i = 0; i < n; i++) | ||
| 1250 | a[i] = 0; | ||
| 1251 | } else { | ||
| 1252 | int_to_digit_array(x, b, n-1, a); | ||
| 1253 | for (i = 0; i < n - 1; i++) | ||
| 1254 | s = (s + a[i]) % b; | ||
| 1255 | a[n-1] = (b - s) % b; | ||
| 1256 | } | ||
| 1257 | } | ||
| 1258 | |||
| 1259 | static int | ||
| 1260 | invert_digits(int a, int b, int n) | ||
| 1261 | { | ||
| 1262 | int i, ret, *r = malloc(n * sizeof(int)); | ||
| 1263 | |||
| 1264 | int_to_digit_array(a, b, n, r); | ||
| 1265 | for (i = 0; i < n; i++) | ||
| 1266 | r[i] = (b-r[i]) % b; | ||
| 1267 | |||
| 1268 | ret = digit_array_to_int(r, n, b); | ||
| 1269 | free(r); | ||
| 1270 | return ret; | ||
| 1271 | } | ||
| 1272 | |||
| 1273 | static bool | ||
| 1274 | is_perm(int *a, int n) | ||
| 1275 | { | ||
| 1276 | int *aux = malloc(n * sizeof(int)); | ||
| 1277 | int i; | ||
| 1278 | |||
| 1279 | for (i = 0; i < n; i++) | ||
| 1280 | if (a[i] < 0 || a[i] >= n) | ||
| 1281 | return false; | ||
| 1282 | else | ||
| 1283 | aux[a[i]] = 1; | ||
| 1284 | |||
| 1285 | for (i = 0; i < n; i++) | ||
| 1286 | if (!aux[i]) | ||
| 1287 | return false; | ||
| 1288 | |||
| 1289 | free(aux); | ||
| 1290 | |||
| 1291 | return true; | ||
| 1292 | } | ||
| 1293 | |||
| 1294 | static bool | ||
| 1295 | is_subset(int *a, int n, int k) | ||
| 1296 | { | ||
| 1297 | int i, sum = 0; | ||
| 1298 | |||
| 1299 | for (i = 0; i < n; i++) | ||
| 1300 | sum += a[i] ? 1 : 0; | ||
| 1301 | |||
| 1302 | return sum == k; | ||
| 1303 | } | ||
| 1304 | |||
| 1305 | static Cube | ||
| 1306 | move_via_arrays(CubeArray *arr, Cube c, PieceFilter f) | ||
| 1307 | { | ||
| 1308 | CubeArray *arrc = new_cubearray(c, f); | ||
| 1309 | Cube ret; | ||
| 1310 | |||
| 1311 | if (f.epose || f.eposs || f.eposm) | ||
| 1312 | apply_permutation(arr->ep, arrc->ep, 12); | ||
| 1313 | |||
| 1314 | if (f.eofb) { | ||
| 1315 | apply_permutation(arr->ep, arrc->eofb, 12); | ||
| 1316 | sum_arrays_mod(arr->eofb, arrc->eofb, 12, 2); | ||
| 1317 | } | ||
| 1318 | |||
| 1319 | if (f.eorl) { | ||
| 1320 | apply_permutation(arr->ep, arrc->eorl, 12); | ||
| 1321 | sum_arrays_mod(arr->eorl, arrc->eorl, 12, 2); | ||
| 1322 | } | ||
| 1323 | |||
| 1324 | if (f.eoud) { | ||
| 1325 | apply_permutation(arr->ep, arrc->eoud, 12); | ||
| 1326 | sum_arrays_mod(arr->eoud, arrc->eoud, 12, 2); | ||
| 1327 | } | ||
| 1328 | |||
| 1329 | if (f.cp) | ||
| 1330 | apply_permutation(arr->cp, arrc->cp, 8); | ||
| 1331 | |||
| 1332 | if (f.coud) { | ||
| 1333 | apply_permutation(arr->cp, arrc->coud, 8); | ||
| 1334 | sum_arrays_mod(arr->coud, arrc->coud, 8, 3); | ||
| 1335 | } | ||
| 1336 | |||
| 1337 | if (f.corl) { | ||
| 1338 | apply_permutation(arr->cp, arrc->corl, 8); | ||
| 1339 | sum_arrays_mod(arr->corl, arrc->corl, 8, 3); | ||
| 1340 | } | ||
| 1341 | |||
| 1342 | if (f.cofb) { | ||
| 1343 | apply_permutation(arr->cp, arrc->cofb, 8); | ||
| 1344 | sum_arrays_mod(arr->cofb, arrc->cofb, 8, 3); | ||
| 1345 | } | ||
| 1346 | |||
| 1347 | if (f.cpos) | ||
| 1348 | apply_permutation(arr->cpos, arrc->cpos, 6); | ||
| 1349 | |||
| 1350 | ret = arrays_to_cube(arrc, f); | ||
| 1351 | free_cubearray(arrc, f); | ||
| 1352 | |||
| 1353 | return ret; | ||
| 1354 | } | ||
| 1355 | |||
| 1356 | static void | ||
| 1357 | movelist_to_position(Move *movelist, int *position) | ||
| 1358 | { | ||
| 1359 | Move m; | ||
| 1360 | |||
| 1361 | for (m = 0; m < NMOVES && movelist[m] != NULLMOVE; m++) | ||
| 1362 | position[movelist[m]] = m; | ||
| 1363 | } | ||
| 1364 | |||
| 1365 | static void | ||
| 1366 | moveset_to_list(Moveset ms, Estimator f, Move *r) | ||
| 1367 | { | ||
| 1368 | CubeTarget ct = { .target = 1 }; | ||
| 1369 | int b[NMOVES]; | ||
| 1370 | int na = 0, nb = 0; | ||
| 1371 | Move i; | ||
| 1372 | |||
| 1373 | if (ms == NULL) { | ||
| 1374 | fprintf(stderr, "Error: no moveset given\n"); | ||
| 1375 | return; | ||
| 1376 | } | ||
| 1377 | |||
| 1378 | for (i = U; i < NMOVES; i++) { | ||
| 1379 | if (ms(i)) { | ||
| 1380 | ct.cube = apply_move(i, (Cube){0}); | ||
| 1381 | if (f != NULL && f(ct)) | ||
| 1382 | r[na++] = i; | ||
| 1383 | else | ||
| 1384 | b[nb++] = i; | ||
| 1385 | } | ||
| 1386 | } | ||
| 1387 | |||
| 1388 | memcpy(r + na, b, nb * sizeof(Move)); | ||
| 1389 | r[na+nb] = NULLMOVE; | ||
| 1390 | } | ||
| 1391 | |||
| 1392 | static AlgList * | ||
| 1393 | new_alglist() | ||
| 1394 | { | ||
| 1395 | AlgList *ret = malloc(sizeof(AlgList)); | ||
| 1396 | |||
| 1397 | ret->len = 0; | ||
| 1398 | ret->first = NULL; | ||
| 1399 | ret->last = NULL; | ||
| 1400 | |||
| 1401 | return ret; | ||
| 1402 | } | ||
| 1403 | |||
| 1404 | static CubeArray * | ||
| 1405 | new_cubearray(Cube cube, PieceFilter f) | ||
| 1406 | { | ||
| 1407 | CubeArray *arr = malloc(sizeof(CubeArray)); | ||
| 1408 | |||
| 1409 | if (f.epose || f.eposs || f.eposm) | ||
| 1410 | arr->ep = malloc(12 * sizeof(int)); | ||
| 1411 | if (f.eofb) | ||
| 1412 | arr->eofb = malloc(12 * sizeof(int)); | ||
| 1413 | if (f.eorl) | ||
| 1414 | arr->eorl = malloc(12 * sizeof(int)); | ||
| 1415 | if (f.eoud) | ||
| 1416 | arr->eoud = malloc(12 * sizeof(int)); | ||
| 1417 | if (f.cp) | ||
| 1418 | arr->cp = malloc(8 * sizeof(int)); | ||
| 1419 | if (f.coud) | ||
| 1420 | arr->coud = malloc(8 * sizeof(int)); | ||
| 1421 | if (f.corl) | ||
| 1422 | arr->corl = malloc(8 * sizeof(int)); | ||
| 1423 | if (f.cofb) | ||
| 1424 | arr->cofb = malloc(8 * sizeof(int)); | ||
| 1425 | if (f.cpos) | ||
| 1426 | arr->cpos = malloc(6 * sizeof(int)); | ||
| 1427 | |||
| 1428 | cube_to_arrays(cube, arr, f); | ||
| 1429 | |||
| 1430 | return arr; | ||
| 1431 | } | ||
| 1432 | |||
| 1433 | static int | ||
| 1434 | perm_sign(int *a, int n) | ||
| 1435 | { | ||
| 1436 | int i, j, ret = 0; | ||
| 1437 | |||
| 1438 | if (!is_perm(a,n)) | ||
| 1439 | return -1; | ||
| 1440 | |||
| 1441 | for (i = 0; i < n; i++) | ||
| 1442 | for (j = i+1; j < n; j++) | ||
| 1443 | ret += (a[i] > a[j]) ? 1 : 0; | ||
| 1444 | |||
| 1445 | return ret % 2; | ||
| 1446 | } | ||
| 1447 | |||
| 1448 | static int | ||
| 1449 | perm_to_index(int *a, int n) | ||
| 1450 | { | ||
| 1451 | int i, j, c, ret = 0; | ||
| 1452 | |||
| 1453 | if (!is_perm(a, n)) | ||
| 1454 | return -1; | ||
| 1455 | |||
| 1456 | for (i = 0; i < n; i++) { | ||
| 1457 | c = 0; | ||
| 1458 | for (j = i+1; j < n; j++) | ||
| 1459 | c += (a[i] > a[j]) ? 1 : 0; | ||
| 1460 | ret += factorial(n-i-1) * c; | ||
| 1461 | } | ||
| 1462 | |||
| 1463 | return ret; | ||
| 1464 | } | ||
| 1465 | |||
| 1466 | static int | ||
| 1467 | powint(int a, int b) | ||
| 1468 | { | ||
| 1469 | if (b < 0) | ||
| 1470 | return 0; | ||
| 1471 | if (b == 0) | ||
| 1472 | return 1; | ||
| 1473 | |||
| 1474 | if (b % 2) | ||
| 1475 | return a * powint(a, b-1); | ||
| 1476 | else | ||
| 1477 | return powint(a*a, b/2); | ||
| 1478 | } | ||
| 1479 | |||
| 1480 | static bool | ||
| 1481 | ptable_has_reached(PruneData *pd, Cube cube) | ||
| 1482 | { | ||
| 1483 | uint64_t ind = pd->coord->index(cube); | ||
| 1484 | |||
| 1485 | return (ind % 2) ? pd->reached[ind/2] / 16 : pd->reached[ind/2] % 16; | ||
| 1486 | } | ||
| 1487 | |||
| 1488 | static void | ||
| 1489 | ptable_set_reached(PruneData *pd, Cube cube) | ||
| 1490 | { | ||
| 1491 | uint64_t ind = pd->coord->index(cube); | ||
| 1492 | uint8_t oldval2 = pd->reached[ind/2]; | ||
| 1493 | int other = (ind % 2) ? oldval2 % 16 : oldval2 / 16; | ||
| 1494 | |||
| 1495 | pd->reached[ind/2] = (ind % 2) ? 16 + other : 16*other + 1; | ||
| 1496 | } | ||
| 1497 | |||
| 1498 | static void | ||
| 1499 | ptable_update(PruneData *pd, Cube cube, int n) | ||
| 1500 | { | ||
| 1501 | uint64_t ind = pd->coord->index(cube); | ||
| 1502 | uint8_t oldval2 = pd->ptable[ind/2]; | ||
| 1503 | int other = (ind % 2) ? oldval2 % 16 : oldval2 / 16; | ||
| 1504 | |||
| 1505 | pd->ptable[ind/2] = (ind % 2) ? 16*n + other : 16*other + n; | ||
| 1506 | pd->n++; | ||
| 1507 | } | ||
| 1508 | |||
| 1509 | static void | ||
| 1510 | realloc_alg(Alg *alg, int n) | ||
| 1511 | { | ||
| 1512 | if (alg == NULL) { | ||
| 1513 | fprintf(stderr, "Error: trying to reallocate NULL alg.\n"); | ||
| 1514 | return; | ||
| 1515 | } | ||
| 1516 | |||
| 1517 | if (n < alg->len) { | ||
| 1518 | fprintf(stderr, "Error: alg too long for reallocation "); | ||
| 1519 | fprintf(stderr, "(%d vs %d)\n", alg->len, n); | ||
| 1520 | return; | ||
| 1521 | } | ||
| 1522 | |||
| 1523 | if (n > 1000000) { | ||
| 1524 | fprintf(stderr, "Warning: very long alg,"); | ||
| 1525 | fprintf(stderr, "something might go wrong.\n"); | ||
| 1526 | } | ||
| 1527 | |||
| 1528 | alg->move = realloc(alg->move, n * sizeof(int)); | ||
| 1529 | alg->inv = realloc(alg->inv, n * sizeof(int)); | ||
| 1530 | alg->allocated = n; | ||
| 1531 | } | ||
| 1532 | |||
| 1533 | static bool | ||
| 1534 | read_mtables_file() | ||
| 1535 | { | ||
| 1536 | FILE *f; | ||
| 1537 | char fname[strlen(tabledir)+20]; | ||
| 1538 | int m, b = sizeof(int); | ||
| 1539 | bool r = true; | ||
| 1540 | |||
| 1541 | strcpy(fname, tabledir); | ||
| 1542 | strcat(fname, "/mtables"); | ||
| 1543 | |||
| 1544 | if ((f = fopen(fname, "rb")) == NULL) | ||
| 1545 | return false; | ||
| 1546 | |||
| 1547 | for (m = 0; m < NMOVES; m++) { | ||
| 1548 | r = r && fread(epose_mtable[m], b, me[0], f) == me[0]; | ||
| 1549 | r = r && fread(eposs_mtable[m], b, me[1], f) == me[1]; | ||
| 1550 | r = r && fread(eposm_mtable[m], b, me[2], f) == me[2]; | ||
| 1551 | r = r && fread(eofb_mtable[m], b, me[3], f) == me[3]; | ||
| 1552 | r = r && fread(eorl_mtable[m], b, me[4], f) == me[4]; | ||
| 1553 | r = r && fread(eoud_mtable[m], b, me[5], f) == me[5]; | ||
| 1554 | r = r && fread(cp_mtable[m], b, me[6], f) == me[6]; | ||
| 1555 | r = r && fread(coud_mtable[m], b, me[7], f) == me[7]; | ||
| 1556 | r = r && fread(corl_mtable[m], b, me[8], f) == me[8]; | ||
| 1557 | r = r && fread(cofb_mtable[m], b, me[9], f) == me[9]; | ||
| 1558 | r = r && fread(cpos_mtable[m], b, me[10], f) == me[10]; | ||
| 1559 | } | ||
| 1560 | |||
| 1561 | fclose(f); | ||
| 1562 | return r; | ||
| 1563 | } | ||
| 1564 | |||
| 1565 | static bool | ||
| 1566 | read_ptable_file(PruneData *pd) | ||
| 1567 | { | ||
| 1568 | FILE *f; | ||
| 1569 | char fname[strlen(tabledir)+100]; | ||
| 1570 | uint64_t r; | ||
| 1571 | |||
| 1572 | strcpy(fname, tabledir); | ||
| 1573 | strcat(fname, "/"); | ||
| 1574 | strcat(fname, pd->filename); | ||
| 1575 | |||
| 1576 | if ((f = fopen(fname, "rb")) == NULL) | ||
| 1577 | return false; | ||
| 1578 | |||
| 1579 | r = fread(pd->ptable, sizeof(uint8_t), ptablesize(pd), f); | ||
| 1580 | fclose(f); | ||
| 1581 | |||
| 1582 | return r == ptablesize(pd); | ||
| 1583 | } | ||
| 1584 | |||
| 1585 | static bool | ||
| 1586 | read_symdata_file(SymData *sd) | ||
| 1587 | { | ||
| 1588 | FILE *f; | ||
| 1589 | char fname[strlen(tabledir)+100]; | ||
| 1590 | uint64_t n = sd->coord->max, *sn = &sd->sym_coord->max; | ||
| 1591 | bool r = true; | ||
| 1592 | |||
| 1593 | strcpy(fname, tabledir); | ||
| 1594 | strcat(fname, "/"); | ||
| 1595 | strcat(fname, sd->filename); | ||
| 1596 | |||
| 1597 | if ((f = fopen(fname, "rb")) == NULL) | ||
| 1598 | return false; | ||
| 1599 | |||
| 1600 | r = r && fread(&sd->sym_coord->max, sizeof(uint64_t), 1, f) == 1; | ||
| 1601 | r = r && fread(sd->rep, sizeof(Cube), *sn, f) == *sn; | ||
| 1602 | r = r && fread(sd->class, sizeof(uint64_t), n, f) == n; | ||
| 1603 | r = r && fread(sd->transtorep, sizeof(Trans), n, f) == n; | ||
| 1604 | |||
| 1605 | fclose(f); | ||
| 1606 | return r; | ||
| 1607 | } | ||
| 1608 | |||
| 1609 | static bool | ||
| 1610 | read_ttables_file() | ||
| 1611 | { | ||
| 1612 | FILE *f; | ||
| 1613 | char fname[strlen(tabledir)+20]; | ||
| 1614 | int b = sizeof(int); | ||
| 1615 | bool r = true; | ||
| 1616 | Move m; | ||
| 1617 | |||
| 1618 | strcpy(fname, tabledir); | ||
| 1619 | strcat(fname, "/"); | ||
| 1620 | strcat(fname, "ttables"); | ||
| 1621 | |||
| 1622 | if ((f = fopen(fname, "rb")) == NULL) | ||
| 1623 | return false; | ||
| 1624 | |||
| 1625 | for (m = 0; m < NTRANS; m++) { | ||
| 1626 | r = r && fread(epose_ttable[m], b, me[0], f) == me[0]; | ||
| 1627 | r = r && fread(eposs_ttable[m], b, me[1], f) == me[1]; | ||
| 1628 | r = r && fread(eposm_ttable[m], b, me[2], f) == me[2]; | ||
| 1629 | r = r && fread(eo_ttable[m], b, me[3], f) == me[3]; | ||
| 1630 | r = r && fread(cp_ttable[m], b, me[6], f) == me[6]; | ||
| 1631 | r = r && fread(co_ttable[m], b, me[7], f) == me[7]; | ||
| 1632 | r = r && fread(cpos_ttable[m], b, me[10], f) == me[10]; | ||
| 1633 | r = r && fread(moves_ttable[m], b, me[11], f) == me[11]; | ||
| 1634 | } | ||
| 1635 | |||
| 1636 | fclose(f); | ||
| 1637 | return r; | ||
| 1638 | } | ||
| 1639 | |||
| 1640 | static Cube | ||
| 1641 | rotate_via_compose(Trans r, Cube c, PieceFilter f) | ||
| 1642 | { | ||
| 1643 | static int zero12[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; | ||
| 1644 | static int zero8[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; | ||
| 1645 | static CubeArray ma = { | ||
| 1646 | .ep = ep_mirror, | ||
| 1647 | .eofb = zero12, | ||
| 1648 | .eorl = zero12, | ||
| 1649 | .eoud = zero12, | ||
| 1650 | .cp = cp_mirror, | ||
| 1651 | .coud = zero8, | ||
| 1652 | .corl = zero8, | ||
| 1653 | .cofb = zero8, | ||
| 1654 | .cpos = cpos_mirror | ||
| 1655 | }; | ||
| 1656 | |||
| 1657 | Alg *inv = inverse_alg(rotation_algs[r % NROTATIONS]); | ||
| 1658 | Cube ret = {0}; | ||
| 1659 | |||
| 1660 | if (r >= NROTATIONS) | ||
| 1661 | ret = move_via_arrays(&ma, ret, f); | ||
| 1662 | ret = apply_alg_generic(inv, ret, f, true); | ||
| 1663 | |||
| 1664 | ret = compose_filtered(c, ret, f); | ||
| 1665 | |||
| 1666 | ret = apply_alg_generic(rotation_algs[r % NROTATIONS], ret, f, true); | ||
| 1667 | if (r >= NROTATIONS) | ||
| 1668 | ret = move_via_arrays(&ma, ret, f); | ||
| 1669 | |||
| 1670 | free_alg(inv); | ||
| 1671 | return ret; | ||
| 1672 | } | ||
| 1673 | |||
| 1674 | static int | ||
| 1675 | subset_to_index(int *a, int n, int k) | ||
| 1676 | { | ||
| 1677 | int i, ret = 0; | ||
| 1678 | |||
| 1679 | if (!is_subset(a, n, k)) | ||
| 1680 | return binomial(n, k); | ||
| 1681 | |||
| 1682 | for (i = 0; i < n; i++) { | ||
| 1683 | if (k == n-i) | ||
| 1684 | return ret; | ||
| 1685 | if (a[i]) { | ||
| 1686 | ret += binomial(n-i-1, k); | ||
| 1687 | k--; | ||
| 1688 | } | ||
| 1689 | } | ||
| 1690 | |||
| 1691 | return ret; | ||
| 1692 | } | ||
| 1693 | |||
| 1694 | static void | ||
| 1695 | sum_arrays_mod(int *src, int *dst, int n, int m) | ||
| 1696 | { | ||
| 1697 | int i; | ||
| 1698 | |||
| 1699 | for (i = 0; i < n; i++) | ||
| 1700 | dst[i] = (m <= 0) ? 0 : (src[i] + dst[i]) % m; | ||
| 1701 | } | ||
| 1702 | |||
| 1703 | static void | ||
| 1704 | swap(int *a, int *b) | ||
| 1705 | { | ||
| 1706 | int aux; | ||
| 1707 | |||
| 1708 | aux = *a; | ||
| 1709 | *a = *b; | ||
| 1710 | *b = aux; | ||
| 1711 | } | ||
| 1712 | |||
| 1713 | static bool | ||
| 1714 | write_mtables_file() | ||
| 1715 | { | ||
| 1716 | FILE *f; | ||
| 1717 | char fname[strlen(tabledir)+20]; | ||
| 1718 | int m, b = sizeof(int); | ||
| 1719 | bool r = true; | ||
| 1720 | |||
| 1721 | strcpy(fname, tabledir); | ||
| 1722 | strcat(fname, "/mtables"); | ||
| 1723 | |||
| 1724 | if ((f = fopen(fname, "wb")) == NULL) | ||
| 1725 | return false; | ||
| 1726 | |||
| 1727 | for (m = 0; m < NMOVES; m++) { | ||
| 1728 | r = r && fwrite(epose_mtable[m], b, me[0], f) == me[0]; | ||
| 1729 | r = r && fwrite(eposs_mtable[m], b, me[1], f) == me[1]; | ||
| 1730 | r = r && fwrite(eposm_mtable[m], b, me[2], f) == me[2]; | ||
| 1731 | r = r && fwrite(eofb_mtable[m], b, me[3], f) == me[3]; | ||
| 1732 | r = r && fwrite(eorl_mtable[m], b, me[4], f) == me[4]; | ||
| 1733 | r = r && fwrite(eoud_mtable[m], b, me[5], f) == me[5]; | ||
| 1734 | r = r && fwrite(cp_mtable[m], b, me[6], f) == me[6]; | ||
| 1735 | r = r && fwrite(coud_mtable[m], b, me[7], f) == me[7]; | ||
| 1736 | r = r && fwrite(corl_mtable[m], b, me[8], f) == me[8]; | ||
| 1737 | r = r && fwrite(cofb_mtable[m], b, me[9], f) == me[9]; | ||
| 1738 | r = r && fwrite(cpos_mtable[m], b, me[10], f) == me[10]; | ||
| 1739 | } | ||
| 1740 | |||
| 1741 | fclose(f); | ||
| 1742 | return r; | ||
| 1743 | } | ||
| 1744 | |||
| 1745 | static bool | ||
| 1746 | write_ptable_file(PruneData *pd) | ||
| 1747 | { | ||
| 1748 | FILE *f; | ||
| 1749 | char fname[strlen(tabledir)+100]; | ||
| 1750 | uint64_t written; | ||
| 1751 | |||
| 1752 | strcpy(fname, tabledir); | ||
| 1753 | strcat(fname, "/"); | ||
| 1754 | strcat(fname, pd->filename); | ||
| 1755 | |||
| 1756 | if ((f = fopen(fname, "wb")) == NULL) | ||
| 1757 | return false; | ||
| 1758 | |||
| 1759 | written = fwrite(pd->ptable, sizeof(uint8_t), ptablesize(pd), f); | ||
| 1760 | fclose(f); | ||
| 1761 | |||
| 1762 | return written == ptablesize(pd); | ||
| 1763 | } | ||
| 1764 | |||
| 1765 | static bool | ||
| 1766 | write_symdata_file(SymData *sd) | ||
| 1767 | { | ||
| 1768 | FILE *f; | ||
| 1769 | char fname[strlen(tabledir)+100]; | ||
| 1770 | uint64_t n = sd->coord->max, *sn = &sd->sym_coord->max; | ||
| 1771 | bool r = true; | ||
| 1772 | |||
| 1773 | strcpy(fname, tabledir); | ||
| 1774 | strcat(fname, "/"); | ||
| 1775 | strcat(fname, sd->filename); | ||
| 1776 | |||
| 1777 | if ((f = fopen(fname, "wb")) == NULL) | ||
| 1778 | return false; | ||
| 1779 | |||
| 1780 | r = r && fwrite(&sd->sym_coord->max, sizeof(uint64_t), 1, f) == 1; | ||
| 1781 | r = r && fwrite(sd->rep, sizeof(Cube), *sn, f) == *sn; | ||
| 1782 | r = r && fwrite(sd->class, sizeof(uint64_t), n, f) == n; | ||
| 1783 | r = r && fwrite(sd->transtorep, sizeof(Trans), n, f) == n; | ||
| 1784 | |||
| 1785 | fclose(f); | ||
| 1786 | return r; | ||
| 1787 | } | ||
| 1788 | |||
| 1789 | static bool | ||
| 1790 | write_ttables_file() | ||
| 1791 | { | ||
| 1792 | FILE *f; | ||
| 1793 | char fname[strlen(tabledir)+20]; | ||
| 1794 | bool r = true; | ||
| 1795 | int b = sizeof(int); | ||
| 1796 | Move m; | ||
| 1797 | |||
| 1798 | strcpy(fname, tabledir); | ||
| 1799 | strcat(fname, "/ttables"); | ||
| 1800 | |||
| 1801 | if ((f = fopen(fname, "wb")) == NULL) | ||
| 1802 | return false; | ||
| 1803 | |||
| 1804 | for (m = 0; m < NTRANS; m++) { | ||
| 1805 | r = r && fwrite(epose_ttable[m], b, me[0], f) == me[0]; | ||
| 1806 | r = r && fwrite(eposs_ttable[m], b, me[1], f) == me[1]; | ||
| 1807 | r = r && fwrite(eposm_ttable[m], b, me[2], f) == me[2]; | ||
| 1808 | r = r && fwrite(eo_ttable[m], b, me[3], f) == me[3]; | ||
| 1809 | r = r && fwrite(cp_ttable[m], b, me[6], f) == me[6]; | ||
| 1810 | r = r && fwrite(co_ttable[m], b, me[7], f) == me[7]; | ||
| 1811 | r = r && fwrite(cpos_ttable[m], b, me[10], f) == me[10]; | ||
| 1812 | r = r && fwrite(moves_ttable[m], b, me[11], f) == me[11]; | ||
| 1813 | } | ||
| 1814 | |||
| 1815 | fclose(f); | ||
| 1816 | return r; | ||
| 1817 | } | ||
| 1818 | |||
| 1819 | /* Init functions implementation *********************************************/ | ||
| 1820 | |||
| 1821 | static void | ||
| 1822 | init_auxtables() | ||
| 1823 | { | ||
| 1824 | Cube c1, c2; | ||
| 1825 | CubeArray *arr; | ||
| 1826 | uint64_t ui, uj; | ||
| 1827 | int i, j, k, auxarr[12]; | ||
| 1828 | bool cij, p1, p2; | ||
| 1829 | |||
| 1830 | for (ui = 0; ui < POW2TO11*BINOM12ON4; ui++) { | ||
| 1831 | k = (ui / POW2TO11) * 24; | ||
| 1832 | c1 = admissible_ep((Cube){ .epose = k }, pf_e); | ||
| 1833 | c1.eofb = ui % POW2TO11; | ||
| 1834 | c1 = admissible_eos_from_eofbepos(c1); | ||
| 1835 | admissible_ee_aux[ui] = c1; | ||
| 1836 | } | ||
| 1837 | |||
| 1838 | for (ui = 0; ui < FACTORIAL6; ui++) { | ||
| 1839 | arr = new_cubearray((Cube){.cpos = ui}, pf_cpos); | ||
| 1840 | for (i = 0; i < 6; i++) { | ||
| 1841 | what_center_at_aux[ui][i] = arr->cpos[i]; | ||
| 1842 | where_is_center_aux[ui][arr->cpos[i]] = i; | ||
| 1843 | } | ||
| 1844 | free_cubearray(arr, pf_cpos); | ||
| 1845 | } | ||
| 1846 | |||
| 1847 | for (ui = 0; ui < FACTORIAL8; ui++) { | ||
| 1848 | arr = new_cubearray((Cube){.cp = ui}, pf_cp); | ||
| 1849 | for (i = 0; i < 8; i++) { | ||
| 1850 | what_corner_at_aux[ui][i] = arr->cp[i]; | ||
| 1851 | where_is_corner_aux[ui][arr->cp[i]] = i; | ||
| 1852 | } | ||
| 1853 | free_cubearray(arr, pf_cp); | ||
| 1854 | } | ||
| 1855 | |||
| 1856 | for (ui = 0; ui < FACTORIAL12/FACTORIAL8; ui++) { | ||
| 1857 | arr = new_cubearray((Cube){.epose = ui}, pf_e); | ||
| 1858 | for (i = 0; i < 12; i++) | ||
| 1859 | if (edge_slice(arr->ep[i]) == 0) | ||
| 1860 | where_is_edge_aux[0][ui][arr->ep[i]] = i; | ||
| 1861 | free_cubearray(arr, pf_e); | ||
| 1862 | |||
| 1863 | arr = new_cubearray((Cube){.eposs = ui}, pf_s); | ||
| 1864 | for (i = 0; i < 12; i++) | ||
| 1865 | if (edge_slice(arr->ep[i]) == 1) | ||
| 1866 | where_is_edge_aux[1][ui][arr->ep[i]] = i; | ||
| 1867 | free_cubearray(arr, pf_s); | ||
| 1868 | |||
| 1869 | arr = new_cubearray((Cube){.eposm = ui}, pf_m); | ||
| 1870 | for (i = 0; i < 12; i++) | ||
| 1871 | if (edge_slice(arr->ep[i]) == 2) | ||
| 1872 | where_is_edge_aux[2][ui][arr->ep[i]] = i; | ||
| 1873 | free_cubearray(arr, pf_m); | ||
| 1874 | } | ||
| 1875 | |||
| 1876 | for (ui = 0; ui < POW3TO7; ui++) { | ||
| 1877 | int_to_sum_zero_array(ui, 3, 8, auxarr); | ||
| 1878 | what_orientation_last_corner_aux[ui] = auxarr[7]; | ||
| 1879 | } | ||
| 1880 | |||
| 1881 | for (ui = 0; ui < POW2TO11; ui++) { | ||
| 1882 | int_to_sum_zero_array(ui, 2, 12, auxarr); | ||
| 1883 | what_orientation_last_edge_aux[ui] = auxarr[11]; | ||
| 1884 | } | ||
| 1885 | |||
| 1886 | for (ui = 0; ui < BINOM12ON4; ui++) | ||
| 1887 | for (uj = 0; uj < BINOM12ON4; uj++) | ||
| 1888 | epos_dependent_aux[ui][uj]=epos_dependent_pos(ui, uj); | ||
| 1889 | |||
| 1890 | for (i = 0; i < NMOVES; i++) { | ||
| 1891 | for (j = 0; j < NMOVES; j++) { | ||
| 1892 | c1 = apply_move(i, apply_move(j, (Cube){0})); | ||
| 1893 | c2 = apply_move(j, apply_move(i, (Cube){0})); | ||
| 1894 | commute[i][j] = equal(c1, c2) && i && j; | ||
| 1895 | } | ||
| 1896 | } | ||
| 1897 | |||
| 1898 | for (i = 0; i < NMOVES; i++) { | ||
| 1899 | for (j = 0; j < NMOVES; j++) { | ||
| 1900 | for (k = 0; k < NMOVES; k++) { | ||
| 1901 | p1 = j && base_move(j) == base_move(k); | ||
| 1902 | p2 = i && base_move(i) == base_move(k); | ||
| 1903 | cij = commute[i][j]; | ||
| 1904 | possible_next[i][j][k] = !(p1 || (cij && p2)); | ||
| 1905 | } | ||
| 1906 | } | ||
| 1907 | } | ||
| 1908 | |||
| 1909 | for (i = 0; i < NMOVES; i++) | ||
| 1910 | inverse_move_aux[i] = i ? i + 2 - 2*((i-1)%3) : NULLMOVE; | ||
| 1911 | |||
| 1912 | /* Is there a more elegant way? */ | ||
| 1913 | inverse_trans_aux[uf] = uf; | ||
| 1914 | inverse_trans_aux[ur] = ul; | ||
| 1915 | inverse_trans_aux[ul] = ur; | ||
| 1916 | inverse_trans_aux[ub] = ub; | ||
| 1917 | |||
| 1918 | inverse_trans_aux[df] = df; | ||
| 1919 | inverse_trans_aux[dr] = dr; | ||
| 1920 | inverse_trans_aux[dl] = dl; | ||
| 1921 | inverse_trans_aux[db] = db; | ||
| 1922 | |||
| 1923 | inverse_trans_aux[rf] = lf; | ||
| 1924 | inverse_trans_aux[rd] = bl; | ||
| 1925 | inverse_trans_aux[rb] = rb; | ||
| 1926 | inverse_trans_aux[ru] = fr; | ||
| 1927 | |||
| 1928 | inverse_trans_aux[lf] = rf; | ||
| 1929 | inverse_trans_aux[ld] = br; | ||
| 1930 | inverse_trans_aux[lb] = lb; | ||
| 1931 | inverse_trans_aux[lu] = fl; | ||
| 1932 | |||
| 1933 | inverse_trans_aux[fu] = fu; | ||
| 1934 | inverse_trans_aux[fr] = ru; | ||
| 1935 | inverse_trans_aux[fd] = bu; | ||
| 1936 | inverse_trans_aux[fl] = lu; | ||
| 1937 | |||
| 1938 | inverse_trans_aux[bu] = fd; | ||
| 1939 | inverse_trans_aux[br] = ld; | ||
| 1940 | inverse_trans_aux[bd] = bd; | ||
| 1941 | inverse_trans_aux[bl] = rd; | ||
| 1942 | |||
| 1943 | inverse_trans_aux[uf_mirror] = uf_mirror; | ||
| 1944 | inverse_trans_aux[ur_mirror] = ur_mirror; | ||
| 1945 | inverse_trans_aux[ul_mirror] = ul_mirror; | ||
| 1946 | inverse_trans_aux[ub_mirror] = ub_mirror; | ||
| 1947 | |||
| 1948 | inverse_trans_aux[df_mirror] = df_mirror; | ||
| 1949 | inverse_trans_aux[dr_mirror] = dl_mirror; | ||
| 1950 | inverse_trans_aux[dl_mirror] = dr_mirror; | ||
| 1951 | inverse_trans_aux[db_mirror] = db_mirror; | ||
| 1952 | |||
| 1953 | inverse_trans_aux[rf_mirror] = rf_mirror; | ||
| 1954 | inverse_trans_aux[rd_mirror] = br_mirror; | ||
| 1955 | inverse_trans_aux[rb_mirror] = lb_mirror; | ||
| 1956 | inverse_trans_aux[ru_mirror] = fl_mirror; | ||
| 1957 | |||
| 1958 | inverse_trans_aux[lf_mirror] = lf_mirror; | ||
| 1959 | inverse_trans_aux[ld_mirror] = bl_mirror; | ||
| 1960 | inverse_trans_aux[lb_mirror] = rb_mirror; | ||
| 1961 | inverse_trans_aux[lu_mirror] = fr_mirror; | ||
| 1962 | |||
| 1963 | inverse_trans_aux[fu_mirror] = fu_mirror; | ||
| 1964 | inverse_trans_aux[fr_mirror] = lu_mirror; | ||
| 1965 | inverse_trans_aux[fd_mirror] = bu_mirror; | ||
| 1966 | inverse_trans_aux[fl_mirror] = ru_mirror; | ||
| 1967 | |||
| 1968 | inverse_trans_aux[bu_mirror] = fd_mirror; | ||
| 1969 | inverse_trans_aux[br_mirror] = rd_mirror; | ||
| 1970 | inverse_trans_aux[bd_mirror] = bd_mirror; | ||
| 1971 | inverse_trans_aux[bl_mirror] = ld_mirror; | ||
| 1972 | } | ||
| 1973 | |||
| 1974 | /* | ||
| 1975 | * There is certainly a bette way to do this, but for now I just use | ||
| 1976 | * a "graph coloring" algorithm to compute the left cosets, and I compose | ||
| 1977 | * with every possible cp to get the right cosets (it is possible that I am | ||
| 1978 | * mixing up left and right). | ||
| 1979 | * | ||
| 1980 | * For doing it better "Mathematically", we need 3 things: | ||
| 1981 | * - Checking that cp separates the orbits (UFR,UBL,DFL,DBR) and the other | ||
| 1982 | * This is easy and it is done in the commented function cphtr_cp(). | ||
| 1983 | * - Check that there is no ep/cp parity | ||
| 1984 | * - Check that we are not in the "3c" case; this is the part I don't | ||
| 1985 | * know how to do. | ||
| 1986 | */ | ||
| 1987 | static void | ||
| 1988 | init_cphtr_cosets() | ||
| 1989 | { | ||
| 1990 | unsigned int i; | ||
| 1991 | int c = 0, d = 0; | ||
| 1992 | |||
| 1993 | for (i = 0; i < FACTORIAL8; i++) { | ||
| 1994 | cphtr_left_cosets[i] = -1; | ||
| 1995 | cphtr_right_cosets[i] = -1; | ||
| 1996 | } | ||
| 1997 | |||
| 1998 | /* First we compute left cosets with a bfs */ | ||
| 1999 | for (i = 0; i < FACTORIAL8; i++) | ||
| 2000 | if (cphtr_left_cosets[i] == -1) | ||
| 2001 | init_cphtr_left_cosets_bfs(i, c++); | ||
| 2002 | |||
| 2003 | /* Then we compute right cosets using compose() */ | ||
| 2004 | for (i = 0; i < FACTORIAL8; i++) | ||
| 2005 | if (cphtr_right_cosets[i] == -1) | ||
| 2006 | init_cphtr_right_cosets_color(i, d++); | ||
| 2007 | } | ||
| 2008 | |||
| 2009 | static void | ||
| 2010 | init_cphtr_left_cosets_bfs(int i, int c) | ||
| 2011 | { | ||
| 2012 | int j, jj, k, next[FACTORIAL8], next2[FACTORIAL8], n, n2; | ||
| 2013 | Move moves[6] = {U2, D2, R2, L2, F2, B2}; | ||
| 2014 | |||
| 2015 | n = 1; | ||
| 2016 | next[0] = i; | ||
| 2017 | cphtr_left_cosets[i] = c; | ||
| 2018 | |||
| 2019 | while (n != 0) { | ||
| 2020 | for (j = 0, n2 = 0; j < n; j++) { | ||
| 2021 | for (k = 0; k < 6; k++) { | ||
| 2022 | jj = cp_mtable[moves[k]][next[j]]; | ||
| 2023 | if (cphtr_left_cosets[jj] == -1) { | ||
| 2024 | cphtr_left_cosets[jj] = c; | ||
| 2025 | next2[n2++] = jj; | ||
| 2026 | } | ||
| 2027 | } | ||
| 2028 | } | ||
| 2029 | |||
| 2030 | for (j = 0; j < n2; j++) | ||
| 2031 | next[j] = next2[j]; | ||
| 2032 | n = n2; | ||
| 2033 | } | ||
| 2034 | } | ||
| 2035 | |||
| 2036 | static void | ||
| 2037 | init_cphtr_right_cosets_color(int i, int d) | ||
| 2038 | { | ||
| 2039 | int cp; | ||
| 2040 | unsigned int j; | ||
| 2041 | |||
| 2042 | cphtr_right_rep[d] = i; | ||
| 2043 | for (j = 0; j < FACTORIAL8; j++) { | ||
| 2044 | if (cphtr_left_cosets[j] == 0) { | ||
| 2045 | /* TODO: use antindexer, it's nicer */ | ||
| 2046 | cp = compose((Cube){.cp = i}, (Cube){.cp = j}).cp; | ||
| 2047 | cphtr_right_cosets[cp] = d; | ||
| 2048 | } | ||
| 2049 | } | ||
| 2050 | } | ||
| 2051 | |||
| 2052 | static void | ||
| 2053 | init_environment() | ||
| 2054 | { | ||
| 2055 | char *nissydata = getenv("NISSYDATA"); | ||
| 2056 | char *localdata = getenv("XDG_DATA_HOME"); | ||
| 2057 | char *home = getenv("HOME"); | ||
| 2058 | bool read, write; | ||
| 2059 | |||
| 2060 | if (nissydata != NULL) { | ||
| 2061 | tabledir = malloc(strlen(nissydata) * sizeof(char) + 20); | ||
| 2062 | strcpy(tabledir, nissydata); | ||
| 2063 | } else if (localdata != NULL) { | ||
| 2064 | tabledir = malloc(strlen(localdata) * sizeof(char) + 20); | ||
| 2065 | strcpy(tabledir, localdata); | ||
| 2066 | strcat(tabledir, "/nissy"); | ||
| 2067 | } else if (home != NULL) { | ||
| 2068 | tabledir = malloc(strlen(home) * sizeof(char) + 20); | ||
| 2069 | strcpy(tabledir, home); | ||
| 2070 | strcat(tabledir, "/.nissy"); | ||
| 2071 | } | ||
| 2072 | |||
| 2073 | mkdir(tabledir, 0777); | ||
| 2074 | strcat(tabledir, "/tables"); | ||
| 2075 | mkdir(tabledir, 0777); | ||
| 2076 | |||
| 2077 | read = !access(tabledir, R_OK); | ||
| 2078 | write = !access(tabledir, W_OK); | ||
| 2079 | |||
| 2080 | if (!read) { | ||
| 2081 | fprintf(stderr, "Table files cannot be read.\n"); | ||
| 2082 | } else if (!write) { | ||
| 2083 | fprintf(stderr, "Data directory not writable: "); | ||
| 2084 | fprintf(stderr, "tables can be loaded, but not saved.\n"); | ||
| 2085 | } | ||
| 2086 | } | ||
| 2087 | |||
| 2088 | static void | ||
| 2089 | init_moves() { | ||
| 2090 | Cube c; | ||
| 2091 | CubeArray arrs; | ||
| 2092 | int i; | ||
| 2093 | unsigned int ui; | ||
| 2094 | Move m; | ||
| 2095 | |||
| 2096 | /* Generate all move cycles and flips; I do this regardless */ | ||
| 2097 | for (i = 0; i < NMOVES; i++) { | ||
| 2098 | if (i == U || i == x || i == y) | ||
| 2099 | continue; | ||
| 2100 | |||
| 2101 | c = apply_alg_generic(equiv_alg[i], (Cube){0}, pf_all, false); | ||
| 2102 | |||
| 2103 | arrs = (CubeArray) { | ||
| 2104 | edge_cycle[i], | ||
| 2105 | eofb_flipped[i], | ||
| 2106 | eorl_flipped[i], | ||
| 2107 | eoud_flipped[i], | ||
| 2108 | corner_cycle[i], | ||
| 2109 | coud_flipped[i], | ||
| 2110 | corl_flipped[i], | ||
| 2111 | cofb_flipped[i], | ||
| 2112 | center_cycle[i] | ||
| 2113 | }; | ||
| 2114 | cube_to_arrays(c, &arrs, pf_all); | ||
| 2115 | } | ||
| 2116 | |||
| 2117 | if (read_mtables_file()) | ||
| 2118 | return; | ||
| 2119 | |||
| 2120 | fprintf(stderr, "Cannot load %s, generating it\n", "mtables"); | ||
| 2121 | |||
| 2122 | /* Initialize transition tables */ | ||
| 2123 | for (m = 0; m < NMOVES; m++) { | ||
| 2124 | for (ui = 0; ui < FACTORIAL12/FACTORIAL8; ui++) { | ||
| 2125 | c = (Cube){ .epose = ui }; | ||
| 2126 | c = apply_move_cubearray(m, c, pf_e); | ||
| 2127 | epose_mtable[m][ui] = c.epose; | ||
| 2128 | |||
| 2129 | c = (Cube){ .eposs = ui }; | ||
| 2130 | c = apply_move_cubearray(m, c, pf_s); | ||
| 2131 | eposs_mtable[m][ui] = c.eposs; | ||
| 2132 | |||
| 2133 | c = (Cube){ .eposm = ui }; | ||
| 2134 | c = apply_move_cubearray(m, c, pf_m); | ||
| 2135 | eposm_mtable[m][ui] = c.eposm; | ||
| 2136 | } | ||
| 2137 | for (ui = 0; ui < POW2TO11; ui++ ) { | ||
| 2138 | c = (Cube){ .eofb = ui }; | ||
| 2139 | c = apply_move_cubearray(m, c, pf_eo); | ||
| 2140 | eofb_mtable[m][ui] = c.eofb; | ||
| 2141 | |||
| 2142 | c = (Cube){ .eorl = ui }; | ||
| 2143 | c = apply_move_cubearray(m, c, pf_eo); | ||
| 2144 | eorl_mtable[m][ui] = c.eorl; | ||
| 2145 | |||
| 2146 | c = (Cube){ .eoud = ui }; | ||
| 2147 | c = apply_move_cubearray(m, c, pf_eo); | ||
| 2148 | eoud_mtable[m][ui] = c.eoud; | ||
| 2149 | } | ||
| 2150 | for (ui = 0; ui < POW3TO7; ui++) { | ||
| 2151 | c = (Cube){ .coud = ui }; | ||
| 2152 | c = apply_move_cubearray(m, c, pf_co); | ||
| 2153 | coud_mtable[m][ui] = c.coud; | ||
| 2154 | |||
| 2155 | c = (Cube){ .corl = ui }; | ||
| 2156 | c = apply_move_cubearray(m, c, pf_co); | ||
| 2157 | corl_mtable[m][ui] = c.corl; | ||
| 2158 | |||
| 2159 | c = (Cube){ .cofb = ui }; | ||
| 2160 | c = apply_move_cubearray(m, c, pf_co); | ||
| 2161 | cofb_mtable[m][ui] = c.cofb; | ||
| 2162 | } | ||
| 2163 | for (ui = 0; ui < FACTORIAL8; ui++) { | ||
| 2164 | c = (Cube){ .cp = ui }; | ||
| 2165 | c = apply_move_cubearray(m, c, pf_cp); | ||
| 2166 | cp_mtable[m][ui] = c.cp; | ||
| 2167 | } | ||
| 2168 | for (ui = 0; ui < FACTORIAL6; ui++) { | ||
| 2169 | c = (Cube){ .cpos = ui }; | ||
| 2170 | c = apply_move_cubearray(m, c, pf_cpos); | ||
| 2171 | cpos_mtable[m][ui] = c.cpos; | ||
| 2172 | } | ||
| 2173 | } | ||
| 2174 | |||
| 2175 | if (!write_mtables_file()) | ||
| 2176 | fprintf(stderr, "Error writing mtables\n"); | ||
| 2177 | } | ||
| 2178 | |||
| 2179 | static void | ||
| 2180 | init_moves_aux() | ||
| 2181 | { | ||
| 2182 | /* Some standard PieceFilters */ | ||
| 2183 | pf_all.epose = true; | ||
| 2184 | pf_all.eposs = true; | ||
| 2185 | pf_all.eposm = true; | ||
| 2186 | pf_all.eofb = true; | ||
| 2187 | pf_all.eorl = true; | ||
| 2188 | pf_all.eoud = true; | ||
| 2189 | pf_all.cp = true; | ||
| 2190 | pf_all.cofb = true; | ||
| 2191 | pf_all.corl = true; | ||
| 2192 | pf_all.coud = true; | ||
| 2193 | pf_all.cpos = true; | ||
| 2194 | |||
| 2195 | pf_4val.epose = true; | ||
| 2196 | pf_4val.eposs = true; | ||
| 2197 | pf_4val.eposm = true; | ||
| 2198 | pf_4val.eofb = true; | ||
| 2199 | pf_4val.coud = true; | ||
| 2200 | pf_4val.cp = true; | ||
| 2201 | |||
| 2202 | pf_epcp.epose = true; | ||
| 2203 | pf_epcp.eposs = true; | ||
| 2204 | pf_epcp.eposm = true; | ||
| 2205 | pf_epcp.cp = true; | ||
| 2206 | |||
| 2207 | pf_cpos.cpos = true; | ||
| 2208 | |||
| 2209 | pf_cp.cp = true; | ||
| 2210 | |||
| 2211 | pf_ep.epose = true; | ||
| 2212 | pf_ep.eposs = true; | ||
| 2213 | pf_ep.eposm = true; | ||
| 2214 | |||
| 2215 | pf_e.epose = true; | ||
| 2216 | pf_s.eposs = true; | ||
| 2217 | pf_m.eposm = true; | ||
| 2218 | |||
| 2219 | pf_eo.eofb = true; | ||
| 2220 | pf_eo.eorl = true; | ||
| 2221 | pf_eo.eoud = true; | ||
| 2222 | |||
| 2223 | pf_co.cofb = true; | ||
| 2224 | pf_co.corl = true; | ||
| 2225 | pf_co.coud = true; | ||
| 2226 | |||
| 2227 | /* Used to convert to and from CubeArray */ | ||
| 2228 | epe_solved[0] = FR; | ||
| 2229 | epe_solved[1] = FL; | ||
| 2230 | epe_solved[2] = BL; | ||
| 2231 | epe_solved[3] = BR; | ||
| 2232 | |||
| 2233 | eps_solved[0] = UL; | ||
| 2234 | eps_solved[1] = UR; | ||
| 2235 | eps_solved[2] = DL; | ||
| 2236 | eps_solved[3] = DR; | ||
| 2237 | |||
| 2238 | epm_solved[0] = UF; | ||
| 2239 | epm_solved[1] = UB; | ||
| 2240 | epm_solved[2] = DF; | ||
| 2241 | epm_solved[3] = DB; | ||
| 2242 | |||
| 2243 | /* Table sizes, used for reading and writing files */ | ||
| 2244 | me[0] = FACTORIAL12/FACTORIAL8; | ||
| 2245 | me[1] = FACTORIAL12/FACTORIAL8; | ||
| 2246 | me[2] = FACTORIAL12/FACTORIAL8; | ||
| 2247 | me[3] = POW2TO11; | ||
| 2248 | me[4] = POW2TO11; | ||
| 2249 | me[5] = POW2TO11; | ||
| 2250 | me[6] = FACTORIAL8; | ||
| 2251 | me[7] = POW3TO7; | ||
| 2252 | me[8] = POW3TO7; | ||
| 2253 | me[9] = POW3TO7; | ||
| 2254 | me[10] = FACTORIAL6; | ||
| 2255 | me[11] = NMOVES; | ||
| 2256 | |||
| 2257 | /* Cycles *********************/ | ||
| 2258 | edge_cycle[U][UF] = UR; | ||
| 2259 | edge_cycle[U][UL] = UF; | ||
| 2260 | edge_cycle[U][UB] = UL; | ||
| 2261 | edge_cycle[U][UR] = UB; | ||
| 2262 | edge_cycle[U][DF] = DF; | ||
| 2263 | edge_cycle[U][DL] = DL; | ||
| 2264 | edge_cycle[U][DB] = DB; | ||
| 2265 | edge_cycle[U][DR] = DR; | ||
| 2266 | edge_cycle[U][FR] = FR; | ||
| 2267 | edge_cycle[U][FL] = FL; | ||
| 2268 | edge_cycle[U][BL] = BL; | ||
| 2269 | edge_cycle[U][BR] = BR; | ||
| 2270 | |||
| 2271 | edge_cycle[x][UF] = DF; | ||
| 2272 | edge_cycle[x][UL] = FL; | ||
| 2273 | edge_cycle[x][UB] = UF; | ||
| 2274 | edge_cycle[x][UR] = FR; | ||
| 2275 | edge_cycle[x][DF] = DB; | ||
| 2276 | edge_cycle[x][DL] = BL; | ||
| 2277 | edge_cycle[x][DB] = UB; | ||
| 2278 | edge_cycle[x][DR] = BR; | ||
| 2279 | edge_cycle[x][FR] = DR; | ||
| 2280 | edge_cycle[x][FL] = DL; | ||
| 2281 | edge_cycle[x][BL] = UL; | ||
| 2282 | edge_cycle[x][BR] = UR; | ||
| 2283 | |||
| 2284 | edge_cycle[y][UF] = UR; | ||
| 2285 | edge_cycle[y][UL] = UF; | ||
| 2286 | edge_cycle[y][UB] = UL; | ||
| 2287 | edge_cycle[y][UR] = UB; | ||
| 2288 | edge_cycle[y][DF] = DR; | ||
| 2289 | edge_cycle[y][DL] = DF; | ||
| 2290 | edge_cycle[y][DB] = DL; | ||
| 2291 | edge_cycle[y][DR] = DB; | ||
| 2292 | edge_cycle[y][FR] = BR; | ||
| 2293 | edge_cycle[y][FL] = FR; | ||
| 2294 | edge_cycle[y][BL] = FL; | ||
| 2295 | edge_cycle[y][BR] = BL; | ||
| 2296 | |||
| 2297 | corner_cycle[U][UFR] = UBR; | ||
| 2298 | corner_cycle[U][UFL] = UFR; | ||
| 2299 | corner_cycle[U][UBL] = UFL; | ||
| 2300 | corner_cycle[U][UBR] = UBL; | ||
| 2301 | corner_cycle[U][DFR] = DFR; | ||
| 2302 | corner_cycle[U][DFL] = DFL; | ||
| 2303 | corner_cycle[U][DBL] = DBL; | ||
| 2304 | corner_cycle[U][DBR] = DBR; | ||
| 2305 | |||
| 2306 | corner_cycle[x][UFR] = DFR; | ||
| 2307 | corner_cycle[x][UFL] = DFL; | ||
| 2308 | corner_cycle[x][UBL] = UFL; | ||
| 2309 | corner_cycle[x][UBR] = UFR; | ||
| 2310 | corner_cycle[x][DFR] = DBR; | ||
| 2311 | corner_cycle[x][DFL] = DBL; | ||
| 2312 | corner_cycle[x][DBL] = UBL; | ||
| 2313 | corner_cycle[x][DBR] = UBR; | ||
| 2314 | |||
| 2315 | corner_cycle[y][UFR] = UBR; | ||
| 2316 | corner_cycle[y][UFL] = UFR; | ||
| 2317 | corner_cycle[y][UBL] = UFL; | ||
| 2318 | corner_cycle[y][UBR] = UBL; | ||
| 2319 | corner_cycle[y][DFR] = DBR; | ||
| 2320 | corner_cycle[y][DFL] = DFR; | ||
| 2321 | corner_cycle[y][DBL] = DFL; | ||
| 2322 | corner_cycle[y][DBR] = DBL; | ||
| 2323 | |||
| 2324 | center_cycle[U][U_center] = U_center; | ||
| 2325 | center_cycle[U][D_center] = D_center; | ||
| 2326 | center_cycle[U][R_center] = R_center; | ||
| 2327 | center_cycle[U][L_center] = L_center; | ||
| 2328 | center_cycle[U][F_center] = F_center; | ||
| 2329 | center_cycle[U][B_center] = B_center; | ||
| 2330 | |||
| 2331 | center_cycle[x][U_center] = F_center; | ||
| 2332 | center_cycle[x][D_center] = B_center; | ||
| 2333 | center_cycle[x][R_center] = R_center; | ||
| 2334 | center_cycle[x][L_center] = L_center; | ||
| 2335 | center_cycle[x][F_center] = D_center; | ||
| 2336 | center_cycle[x][B_center] = U_center; | ||
| 2337 | |||
| 2338 | center_cycle[y][U_center] = U_center; | ||
| 2339 | center_cycle[y][D_center] = D_center; | ||
| 2340 | center_cycle[y][R_center] = B_center; | ||
| 2341 | center_cycle[y][L_center] = F_center; | ||
| 2342 | center_cycle[y][F_center] = R_center; | ||
| 2343 | center_cycle[y][B_center] = L_center; | ||
| 2344 | |||
| 2345 | /* Flipped pieces *************/ | ||
| 2346 | eofb_flipped[x][UF] = 1; | ||
| 2347 | eofb_flipped[x][UB] = 1; | ||
| 2348 | eofb_flipped[x][DF] = 1; | ||
| 2349 | eofb_flipped[x][DB] = 1; | ||
| 2350 | |||
| 2351 | eofb_flipped[y][FR] = 1; | ||
| 2352 | eofb_flipped[y][FL] = 1; | ||
| 2353 | eofb_flipped[y][BL] = 1; | ||
| 2354 | eofb_flipped[y][BR] = 1; | ||
| 2355 | |||
| 2356 | eorl_flipped[x][UF] = 1; | ||
| 2357 | eorl_flipped[x][UL] = 1; | ||
| 2358 | eorl_flipped[x][UB] = 1; | ||
| 2359 | eorl_flipped[x][UR] = 1; | ||
| 2360 | eorl_flipped[x][DF] = 1; | ||
| 2361 | eorl_flipped[x][DL] = 1; | ||
| 2362 | eorl_flipped[x][DB] = 1; | ||
| 2363 | eorl_flipped[x][DR] = 1; | ||
| 2364 | eorl_flipped[x][FR] = 1; | ||
| 2365 | eorl_flipped[x][FL] = 1; | ||
| 2366 | eorl_flipped[x][BL] = 1; | ||
| 2367 | eorl_flipped[x][BR] = 1; | ||
| 2368 | |||
| 2369 | eorl_flipped[y][FR] = 1; | ||
| 2370 | eorl_flipped[y][FL] = 1; | ||
| 2371 | eorl_flipped[y][BL] = 1; | ||
| 2372 | eorl_flipped[y][BR] = 1; | ||
| 2373 | |||
| 2374 | eoud_flipped[U][UF] = 1; | ||
| 2375 | eoud_flipped[U][UL] = 1; | ||
| 2376 | eoud_flipped[U][UB] = 1; | ||
| 2377 | eoud_flipped[U][UR] = 1; | ||
| 2378 | |||
| 2379 | eoud_flipped[x][UF] = 1; | ||
| 2380 | eoud_flipped[x][UB] = 1; | ||
| 2381 | eoud_flipped[x][DF] = 1; | ||
| 2382 | eoud_flipped[x][DB] = 1; | ||
| 2383 | |||
| 2384 | eoud_flipped[y][UF] = 1; | ||
| 2385 | eoud_flipped[y][UL] = 1; | ||
| 2386 | eoud_flipped[y][UB] = 1; | ||
| 2387 | eoud_flipped[y][UR] = 1; | ||
| 2388 | eoud_flipped[y][DF] = 1; | ||
| 2389 | eoud_flipped[y][DL] = 1; | ||
| 2390 | eoud_flipped[y][DB] = 1; | ||
| 2391 | eoud_flipped[y][DR] = 1; | ||
| 2392 | eoud_flipped[y][FR] = 1; | ||
| 2393 | eoud_flipped[y][FL] = 1; | ||
| 2394 | eoud_flipped[y][BL] = 1; | ||
| 2395 | eoud_flipped[y][BR] = 1; | ||
| 2396 | |||
| 2397 | coud_flipped[x][UFR] = 2; | ||
| 2398 | coud_flipped[x][UFL] = 1; | ||
| 2399 | coud_flipped[x][UBR] = 1; | ||
| 2400 | coud_flipped[x][UBL] = 2; | ||
| 2401 | coud_flipped[x][DFR] = 1; | ||
| 2402 | coud_flipped[x][DFL] = 2; | ||
| 2403 | coud_flipped[x][DBR] = 2; | ||
| 2404 | coud_flipped[x][DBL] = 1; | ||
| 2405 | |||
| 2406 | corl_flipped[U][UFR] = 1; | ||
| 2407 | corl_flipped[U][UFL] = 2; | ||
| 2408 | corl_flipped[U][UBL] = 1; | ||
| 2409 | corl_flipped[U][UBR] = 2; | ||
| 2410 | |||
| 2411 | corl_flipped[y][UFR] = 1; | ||
| 2412 | corl_flipped[y][UFL] = 2; | ||
| 2413 | corl_flipped[y][UBL] = 1; | ||
| 2414 | corl_flipped[y][UBR] = 2; | ||
| 2415 | corl_flipped[y][DFR] = 2; | ||
| 2416 | corl_flipped[y][DFL] = 1; | ||
| 2417 | corl_flipped[y][DBL] = 2; | ||
| 2418 | corl_flipped[y][DBR] = 1; | ||
| 2419 | |||
| 2420 | cofb_flipped[U][UFR] = 2; | ||
| 2421 | cofb_flipped[U][UFL] = 1; | ||
| 2422 | cofb_flipped[U][UBL] = 2; | ||
| 2423 | cofb_flipped[U][UBR] = 1; | ||
| 2424 | |||
| 2425 | cofb_flipped[x][UFR] = 1; | ||
| 2426 | cofb_flipped[x][UFL] = 2; | ||
| 2427 | cofb_flipped[x][UBL] = 1; | ||
| 2428 | cofb_flipped[x][UBR] = 2; | ||
| 2429 | cofb_flipped[x][DFR] = 2; | ||
| 2430 | cofb_flipped[x][DFL] = 1; | ||
| 2431 | cofb_flipped[x][DBL] = 2; | ||
| 2432 | cofb_flipped[x][DBR] = 1; | ||
| 2433 | |||
| 2434 | cofb_flipped[y][UFR] = 2; | ||
| 2435 | cofb_flipped[y][UFL] = 1; | ||
| 2436 | cofb_flipped[y][UBL] = 2; | ||
| 2437 | cofb_flipped[y][UBR] = 1; | ||
| 2438 | cofb_flipped[y][DFR] = 1; | ||
| 2439 | cofb_flipped[y][DFL] = 2; | ||
| 2440 | cofb_flipped[y][DBL] = 1; | ||
| 2441 | cofb_flipped[y][DBR] = 2; | ||
| 2442 | |||
| 2443 | /* Equivalent moves ***********/ | ||
| 2444 | equiv_alg[NULLMOVE] = new_alg(""); | ||
| 2445 | |||
| 2446 | equiv_alg[U] = new_alg(" U "); | ||
| 2447 | equiv_alg[U2] = new_alg(" UU "); | ||
| 2448 | equiv_alg[U3] = new_alg(" UUU "); | ||
| 2449 | equiv_alg[D] = new_alg(" xx U xx "); | ||
| 2450 | equiv_alg[D2] = new_alg(" xx UU xx "); | ||
| 2451 | equiv_alg[D3] = new_alg(" xx UUU xx "); | ||
| 2452 | equiv_alg[R] = new_alg(" yx U xxxyyy "); | ||
| 2453 | equiv_alg[R2] = new_alg(" yx UU xxxyyy "); | ||
| 2454 | equiv_alg[R3] = new_alg(" yx UUU xxxyyy "); | ||
| 2455 | equiv_alg[L] = new_alg(" yyyx U xxxy "); | ||
| 2456 | equiv_alg[L2] = new_alg(" yyyx UU xxxy "); | ||
| 2457 | equiv_alg[L3] = new_alg(" yyyx UUU xxxy "); | ||
| 2458 | equiv_alg[F] = new_alg(" x U xxx "); | ||
| 2459 | equiv_alg[F2] = new_alg(" x UU xxx "); | ||
| 2460 | equiv_alg[F3] = new_alg(" x UUU xxx "); | ||
| 2461 | equiv_alg[B] = new_alg(" xxx U x "); | ||
| 2462 | equiv_alg[B2] = new_alg(" xxx UU x "); | ||
| 2463 | equiv_alg[B3] = new_alg(" xxx UUU x "); | ||
| 2464 | |||
| 2465 | equiv_alg[Uw] = new_alg(" xx U xx y "); | ||
| 2466 | equiv_alg[Uw2] = new_alg(" xx UU xx yy "); | ||
| 2467 | equiv_alg[Uw3] = new_alg(" xx UUU xx yyy "); | ||
| 2468 | equiv_alg[Dw] = new_alg(" U yyy "); | ||
| 2469 | equiv_alg[Dw2] = new_alg(" UU yy "); | ||
| 2470 | equiv_alg[Dw3] = new_alg(" UUU y "); | ||
| 2471 | equiv_alg[Rw] = new_alg(" yyyx U xxxy x "); | ||
| 2472 | equiv_alg[Rw2] = new_alg(" yyyx UU xxxy xx "); | ||
| 2473 | equiv_alg[Rw3] = new_alg(" yyyx UUU xxxy xxx "); | ||
| 2474 | equiv_alg[Lw] = new_alg(" yx U xxxyyy xxx "); | ||
| 2475 | equiv_alg[Lw2] = new_alg(" yx UU xxxyyy xx "); | ||
| 2476 | equiv_alg[Lw3] = new_alg(" yx UUU xxxyyy x "); | ||
| 2477 | equiv_alg[Fw] = new_alg(" xxx U x yxxxyyy "); | ||
| 2478 | equiv_alg[Fw2] = new_alg(" xxx UU x yxxyyy "); | ||
| 2479 | equiv_alg[Fw3] = new_alg(" xxx UUU x yxyyy "); | ||
| 2480 | equiv_alg[Bw] = new_alg(" x U xxx yxyyy "); | ||
| 2481 | equiv_alg[Bw2] = new_alg(" x UU xxx yxxyyy "); | ||
| 2482 | equiv_alg[Bw3] = new_alg(" x UUU xxx yxxxyyy "); | ||
| 2483 | |||
| 2484 | equiv_alg[M] = new_alg(" yx U xx UUU yxyyy "); | ||
| 2485 | equiv_alg[M2] = new_alg(" yx UU xx UU xxxy "); | ||
| 2486 | equiv_alg[M3] = new_alg(" yx UUU xx U yxxxy "); | ||
| 2487 | equiv_alg[S] = new_alg(" x UUU xx U yyyx "); | ||
| 2488 | equiv_alg[S2] = new_alg(" x UU xx UU yyx "); | ||
| 2489 | equiv_alg[S3] = new_alg(" x U xx UUU yx "); | ||
| 2490 | equiv_alg[E] = new_alg(" U xx UUU xxyyy "); | ||
| 2491 | equiv_alg[E2] = new_alg(" UU xx UU xxyy "); | ||
| 2492 | equiv_alg[E3] = new_alg(" UUU xx U xxy "); | ||
| 2493 | |||
| 2494 | equiv_alg[x] = new_alg(" x "); | ||
| 2495 | equiv_alg[x2] = new_alg(" xx "); | ||
| 2496 | equiv_alg[x3] = new_alg(" xxx "); | ||
| 2497 | equiv_alg[y] = new_alg(" y "); | ||
| 2498 | equiv_alg[y2] = new_alg(" yy "); | ||
| 2499 | equiv_alg[y3] = new_alg(" yyy "); | ||
| 2500 | equiv_alg[z] = new_alg(" yyy x y "); | ||
| 2501 | equiv_alg[z2] = new_alg(" yy xx "); | ||
| 2502 | equiv_alg[z3] = new_alg(" y x yyy "); | ||
| 2503 | } | ||
| 2504 | |||
| 2505 | static void | ||
| 2506 | init_strings() | ||
| 2507 | { | ||
| 2508 | strcpy(move_string [NULLMOVE], "-" ); | ||
| 2509 | strcpy(move_string [U], "U" ); | ||
| 2510 | strcpy(move_string [U2], "U2" ); | ||
| 2511 | strcpy(move_string [U3], "U\'" ); | ||
| 2512 | strcpy(move_string [D], "D" ); | ||
| 2513 | strcpy(move_string [D2], "D2" ); | ||
| 2514 | strcpy(move_string [D3], "D\'" ); | ||
| 2515 | strcpy(move_string [R], "R" ); | ||
| 2516 | strcpy(move_string [R2], "R2" ); | ||
| 2517 | strcpy(move_string [R3], "R\'" ); | ||
| 2518 | strcpy(move_string [L], "L" ); | ||
| 2519 | strcpy(move_string [L2], "L2" ); | ||
| 2520 | strcpy(move_string [L3], "L\'" ); | ||
| 2521 | strcpy(move_string [F], "F" ); | ||
| 2522 | strcpy(move_string [F2], "F2" ); | ||
| 2523 | strcpy(move_string [F3], "F\'" ); | ||
| 2524 | strcpy(move_string [B], "B" ); | ||
| 2525 | strcpy(move_string [B2], "B2" ); | ||
| 2526 | strcpy(move_string [B3], "B\'" ); | ||
| 2527 | strcpy(move_string [Uw], "Uw" ); | ||
| 2528 | strcpy(move_string [Uw2], "Uw2" ); | ||
| 2529 | strcpy(move_string [Uw3], "Uw\'" ); | ||
| 2530 | strcpy(move_string [Dw], "Dw" ); | ||
| 2531 | strcpy(move_string [Dw2], "Dw2" ); | ||
| 2532 | strcpy(move_string [Dw3], "Dw\'" ); | ||
| 2533 | strcpy(move_string [Rw], "Rw" ); | ||
| 2534 | strcpy(move_string [Rw2], "Rw2" ); | ||
| 2535 | strcpy(move_string [Rw3], "Rw\'" ); | ||
| 2536 | strcpy(move_string [Lw], "Lw" ); | ||
| 2537 | strcpy(move_string [Lw2], "Lw2" ); | ||
| 2538 | strcpy(move_string [Lw3], "Lw\'" ); | ||
| 2539 | strcpy(move_string [Fw], "Fw" ); | ||
| 2540 | strcpy(move_string [Fw2], "Fw2" ); | ||
| 2541 | strcpy(move_string [Fw3], "Fw\'" ); | ||
| 2542 | strcpy(move_string [Bw], "Bw" ); | ||
| 2543 | strcpy(move_string [Bw2], "Bw2" ); | ||
| 2544 | strcpy(move_string [Bw3], "Bw\'" ); | ||
| 2545 | strcpy(move_string [M], "M" ); | ||
| 2546 | strcpy(move_string [M2], "M2" ); | ||
| 2547 | strcpy(move_string [M3], "M\'" ); | ||
| 2548 | strcpy(move_string [S], "S" ); | ||
| 2549 | strcpy(move_string [S2], "S2" ); | ||
| 2550 | strcpy(move_string [S3], "S\'" ); | ||
| 2551 | strcpy(move_string [E], "E" ); | ||
| 2552 | strcpy(move_string [E2], "E2" ); | ||
| 2553 | strcpy(move_string [E3], "E\'" ); | ||
| 2554 | strcpy(move_string [x], "x" ); | ||
| 2555 | strcpy(move_string [x2], "x2" ); | ||
| 2556 | strcpy(move_string [x3], "x\'" ); | ||
| 2557 | strcpy(move_string [y], "y" ); | ||
| 2558 | strcpy(move_string [y2], "y2" ); | ||
| 2559 | strcpy(move_string [y3], "y\'" ); | ||
| 2560 | strcpy(move_string [z], "z" ); | ||
| 2561 | strcpy(move_string [z2], "z2" ); | ||
| 2562 | strcpy(move_string [z3], "z\'" ); | ||
| 2563 | |||
| 2564 | strcpy(edge_string [UF], "UF" ); | ||
| 2565 | strcpy(edge_string [UL], "UL" ); | ||
| 2566 | strcpy(edge_string [UB], "UB" ); | ||
| 2567 | strcpy(edge_string [UR], "UR" ); | ||
| 2568 | strcpy(edge_string [DF], "DF" ); | ||
| 2569 | strcpy(edge_string [DL], "DL" ); | ||
| 2570 | strcpy(edge_string [DB], "DB" ); | ||
| 2571 | strcpy(edge_string [DR], "DR" ); | ||
| 2572 | strcpy(edge_string [FR], "FR" ); | ||
| 2573 | strcpy(edge_string [FL], "FL" ); | ||
| 2574 | strcpy(edge_string [BL], "BL" ); | ||
| 2575 | strcpy(edge_string [BR], "BR" ); | ||
| 2576 | |||
| 2577 | strcpy(corner_string [UFR], "UFR" ); | ||
| 2578 | strcpy(corner_string [UFL], "UFL" ); | ||
| 2579 | strcpy(corner_string [UBL], "UBL" ); | ||
| 2580 | strcpy(corner_string [UBR], "UBR" ); | ||
| 2581 | strcpy(corner_string [DFR], "DFR" ); | ||
| 2582 | strcpy(corner_string [DFL], "DFL" ); | ||
| 2583 | strcpy(corner_string [DBL], "DBL" ); | ||
| 2584 | strcpy(corner_string [DBR], "DBR" ); | ||
| 2585 | |||
| 2586 | strcpy(center_string [U_center], "U" ); | ||
| 2587 | strcpy(center_string [D_center], "D" ); | ||
| 2588 | strcpy(center_string [R_center], "R" ); | ||
| 2589 | strcpy(center_string [L_center], "L" ); | ||
| 2590 | strcpy(center_string [F_center], "F" ); | ||
| 2591 | strcpy(center_string [B_center], "B" ); | ||
| 2592 | } | ||
| 2593 | |||
| 2594 | static void | ||
| 2595 | init_symdata() | ||
| 2596 | { | ||
| 2597 | int i; | ||
| 2598 | |||
| 2599 | for (i = 0; i < n_all_symdata; i++) | ||
| 2600 | gensym(all_sd[i]); | ||
| 2601 | } | ||
| 2602 | |||
| 2603 | static void | ||
| 2604 | init_trans() { | ||
| 2605 | Cube aux, cube, mirr, c[3]; | ||
| 2606 | CubeArray epcp; | ||
| 2607 | int i, eparr[12], eoarr[12], cparr[8], coarr[8]; | ||
| 2608 | unsigned int ui; | ||
| 2609 | Move mi, move; | ||
| 2610 | Trans m; | ||
| 2611 | |||
| 2612 | /* Compute sources */ | ||
| 2613 | for (i = 0; i < NTRANS; i++) { | ||
| 2614 | cube = apply_alg(rotation_algs[i % NROTATIONS], (Cube){0}); | ||
| 2615 | |||
| 2616 | epose_source[i] = edge_slice(what_edge_at(cube, FR)); | ||
| 2617 | eposs_source[i] = edge_slice(what_edge_at(cube, UR)); | ||
| 2618 | eposm_source[i] = edge_slice(what_edge_at(cube, UF)); | ||
| 2619 | eofb_source[i] = what_center_at(cube, F_center)/2; | ||
| 2620 | eorl_source[i] = what_center_at(cube, R_center)/2; | ||
| 2621 | eoud_source[i] = what_center_at(cube, U_center)/2; | ||
| 2622 | coud_source[i] = what_center_at(cube, U_center)/2; | ||
| 2623 | cofb_source[i] = what_center_at(cube, F_center)/2; | ||
| 2624 | corl_source[i] = what_center_at(cube, R_center)/2; | ||
| 2625 | } | ||
| 2626 | |||
| 2627 | if (read_ttables_file()) | ||
| 2628 | return; | ||
| 2629 | |||
| 2630 | fprintf(stderr, "Cannot load %s, generating it\n", "ttables"); | ||
| 2631 | |||
| 2632 | /* Initialize tables */ | ||
| 2633 | for (m = 0; m < NTRANS; m++) { | ||
| 2634 | epcp = (CubeArray){ .ep = eparr, .cp = cparr }; | ||
| 2635 | cube = apply_alg(rotation_algs[m % NROTATIONS], (Cube){0}); | ||
| 2636 | cube_to_arrays(cube, &epcp, pf_epcp); | ||
| 2637 | if (m >= NROTATIONS) { | ||
| 2638 | apply_permutation(ep_mirror, eparr, 12); | ||
| 2639 | apply_permutation(cp_mirror, cparr, 8); | ||
| 2640 | } | ||
| 2641 | |||
| 2642 | for (ui = 0; ui < FACTORIAL12/FACTORIAL8; ui++) { | ||
| 2643 | c[0] = admissible_ep((Cube){ .epose = ui }, pf_e); | ||
| 2644 | c[1] = admissible_ep((Cube){ .eposs = ui }, pf_s); | ||
| 2645 | c[2] = admissible_ep((Cube){ .eposm = ui }, pf_m); | ||
| 2646 | |||
| 2647 | cube = rotate_via_compose(m,c[epose_source[m]],pf_ep); | ||
| 2648 | epose_ttable[m][ui] = cube.epose; | ||
| 2649 | |||
| 2650 | cube = rotate_via_compose(m,c[eposs_source[m]],pf_ep); | ||
| 2651 | eposs_ttable[m][ui] = cube.eposs; | ||
| 2652 | |||
| 2653 | cube = rotate_via_compose(m,c[eposm_source[m]],pf_ep); | ||
| 2654 | eposm_ttable[m][ui] = cube.eposm; | ||
| 2655 | } | ||
| 2656 | for (ui = 0; ui < POW2TO11; ui++ ) { | ||
| 2657 | int_to_sum_zero_array(ui, 2, 12, eoarr); | ||
| 2658 | apply_permutation(eparr, eoarr, 12); | ||
| 2659 | eo_ttable[m][ui] = digit_array_to_int(eoarr, 11, 2); | ||
| 2660 | } | ||
| 2661 | for (ui = 0; ui < POW3TO7; ui++) { | ||
| 2662 | int_to_sum_zero_array(ui, 3, 8, coarr); | ||
| 2663 | apply_permutation(cparr, coarr, 8); | ||
| 2664 | co_ttable[m][ui] = digit_array_to_int(coarr, 7, 3); | ||
| 2665 | if (m >= NROTATIONS) | ||
| 2666 | co_ttable[m][ui] = | ||
| 2667 | invert_digits(co_ttable[m][ui], 3, 7); | ||
| 2668 | } | ||
| 2669 | for (ui = 0; ui < FACTORIAL8; ui++) { | ||
| 2670 | cube = (Cube){ .cp = ui }; | ||
| 2671 | cube = rotate_via_compose(m, cube, pf_cp); | ||
| 2672 | cp_ttable[m][ui] = cube.cp; | ||
| 2673 | } | ||
| 2674 | for (ui = 0; ui < FACTORIAL6; ui++) { | ||
| 2675 | cube = (Cube){ .cpos = ui }; | ||
| 2676 | cube = rotate_via_compose(m, cube, pf_cpos); | ||
| 2677 | cpos_ttable[m][ui] = cube.cpos; | ||
| 2678 | } | ||
| 2679 | for (mi = 0; mi < NMOVES; mi++) { | ||
| 2680 | aux = apply_trans(m, apply_move(mi, (Cube){0})); | ||
| 2681 | for (move = 0; move < NMOVES; move++) { | ||
| 2682 | cube = apply_move(inverse_move_aux[move], aux); | ||
| 2683 | mirr = apply_trans(uf_mirror, cube); | ||
| 2684 | if (is_solved(cube, false) || | ||
| 2685 | is_solved(mirr, false)) | ||
| 2686 | moves_ttable[m][mi] = move; | ||
| 2687 | } | ||
| 2688 | } | ||
| 2689 | } | ||
| 2690 | |||
| 2691 | if (!write_ttables_file()) | ||
| 2692 | fprintf(stderr, "Error writing ttables\n"); | ||
| 2693 | } | ||
| 2694 | |||
| 2695 | static void | ||
| 2696 | init_trans_aux() | ||
| 2697 | { | ||
| 2698 | ep_mirror[UF] = UF; | ||
| 2699 | ep_mirror[UL] = UR; | ||
| 2700 | ep_mirror[UB] = UB; | ||
| 2701 | ep_mirror[UR] = UL; | ||
| 2702 | ep_mirror[DF] = DF; | ||
| 2703 | ep_mirror[DL] = DR; | ||
| 2704 | ep_mirror[DB] = DB; | ||
| 2705 | ep_mirror[DR] = DL; | ||
| 2706 | ep_mirror[FR] = FL; | ||
| 2707 | ep_mirror[FL] = FR; | ||
| 2708 | ep_mirror[BR] = BL; | ||
| 2709 | ep_mirror[BL] = BR; | ||
| 2710 | |||
| 2711 | cp_mirror[UFR] = UFL; | ||
| 2712 | cp_mirror[UFL] = UFR; | ||
| 2713 | cp_mirror[UBL] = UBR; | ||
| 2714 | cp_mirror[UBR] = UBL; | ||
| 2715 | cp_mirror[DFR] = DFL; | ||
| 2716 | cp_mirror[DFL] = DFR; | ||
| 2717 | cp_mirror[DBL] = DBR; | ||
| 2718 | cp_mirror[DBR] = DBL; | ||
| 2719 | |||
| 2720 | cpos_mirror[U_center] = U_center; | ||
| 2721 | cpos_mirror[D_center] = D_center; | ||
| 2722 | cpos_mirror[R_center] = L_center; | ||
| 2723 | cpos_mirror[L_center] = R_center; | ||
| 2724 | cpos_mirror[F_center] = F_center; | ||
| 2725 | cpos_mirror[B_center] = B_center; | ||
| 2726 | |||
| 2727 | /* Is there a more elegant way? */ | ||
| 2728 | rotation_algs[uf] = new_alg(""); | ||
| 2729 | rotation_algs[ur] = new_alg("y"); | ||
| 2730 | rotation_algs[ub] = new_alg("y2"); | ||
| 2731 | rotation_algs[ul] = new_alg("y3"); | ||
| 2732 | |||
| 2733 | rotation_algs[df] = new_alg("z2"); | ||
| 2734 | rotation_algs[dr] = new_alg("y z2"); | ||
| 2735 | rotation_algs[db] = new_alg("x2"); | ||
| 2736 | rotation_algs[dl] = new_alg("y3 z2"); | ||
| 2737 | |||
| 2738 | rotation_algs[rf] = new_alg("z3"); | ||
| 2739 | rotation_algs[rd] = new_alg("z3 y"); | ||
| 2740 | rotation_algs[rb] = new_alg("z3 y2"); | ||
| 2741 | rotation_algs[ru] = new_alg("z3 y3"); | ||
| 2742 | |||
| 2743 | rotation_algs[lf] = new_alg("z"); | ||
| 2744 | rotation_algs[ld] = new_alg("z y3"); | ||
| 2745 | rotation_algs[lb] = new_alg("z y2"); | ||
| 2746 | rotation_algs[lu] = new_alg("z y"); | ||
| 2747 | |||
| 2748 | rotation_algs[fu] = new_alg("x y2"); | ||
| 2749 | rotation_algs[fr] = new_alg("x y"); | ||
| 2750 | rotation_algs[fd] = new_alg("x"); | ||
| 2751 | rotation_algs[fl] = new_alg("x y3"); | ||
| 2752 | |||
| 2753 | rotation_algs[bu] = new_alg("x3"); | ||
| 2754 | rotation_algs[br] = new_alg("x3 y"); | ||
| 2755 | rotation_algs[bd] = new_alg("x3 y2"); | ||
| 2756 | rotation_algs[bl] = new_alg("x3 y3"); | ||
| 2757 | } | ||
| 2758 | |||
| 2759 | |||
| 2760 | /* Public functions implementation *******************************************/ | ||
| 2761 | |||
| 2762 | Cube | ||
| 2763 | apply_alg(Alg *alg, Cube cube) | ||
| 2764 | { | ||
| 2765 | return apply_alg_generic(alg, cube, pf_all, true); | ||
| 2766 | } | ||
| 2767 | |||
| 2768 | Cube | ||
| 2769 | apply_move(Move m, Cube cube) | ||
| 2770 | { | ||
| 2771 | return (Cube) { | ||
| 2772 | .epose = epose_mtable[m][cube.epose], | ||
| 2773 | .eposs = eposs_mtable[m][cube.eposs], | ||
| 2774 | .eposm = eposm_mtable[m][cube.eposm], | ||
| 2775 | .eofb = eofb_mtable[m][cube.eofb], | ||
| 2776 | .eorl = eorl_mtable[m][cube.eorl], | ||
| 2777 | .eoud = eoud_mtable[m][cube.eoud], | ||
| 2778 | .coud = coud_mtable[m][cube.coud], | ||
| 2779 | .cofb = cofb_mtable[m][cube.cofb], | ||
| 2780 | .corl = corl_mtable[m][cube.corl], | ||
| 2781 | .cp = cp_mtable[m][cube.cp], | ||
| 2782 | .cpos = cpos_mtable[m][cube.cpos] | ||
| 2783 | }; | ||
| 2784 | } | ||
| 2785 | |||
| 2786 | |||
| 2787 | Cube | ||
| 2788 | apply_trans(Trans t, Cube cube) | ||
| 2789 | { | ||
| 2790 | int aux_epos[3] = { cube.epose, cube.eposs, cube.eposm }; | ||
| 2791 | int aux_eo[3] = { cube.eoud, cube.eorl, cube.eofb }; | ||
| 2792 | int aux_co[3] = { cube.coud, cube.corl, cube.cofb }; | ||
| 2793 | |||
| 2794 | return (Cube) { | ||
| 2795 | .epose = epose_ttable[t][aux_epos[epose_source[t]]], | ||
| 2796 | .eposs = eposs_ttable[t][aux_epos[eposs_source[t]]], | ||
| 2797 | .eposm = eposm_ttable[t][aux_epos[eposm_source[t]]], | ||
| 2798 | .eofb = eo_ttable[t][aux_eo[eofb_source[t]]], | ||
| 2799 | .eorl = eo_ttable[t][aux_eo[eorl_source[t]]], | ||
| 2800 | .eoud = eo_ttable[t][aux_eo[eoud_source[t]]], | ||
| 2801 | .coud = co_ttable[t][aux_co[coud_source[t]]], | ||
| 2802 | .corl = co_ttable[t][aux_co[corl_source[t]]], | ||
| 2803 | .cofb = co_ttable[t][aux_co[cofb_source[t]]], | ||
| 2804 | .cp = cp_ttable[t][cube.cp], | ||
| 2805 | .cpos = cpos_ttable[t][cube.cpos] | ||
| 2806 | }; | ||
| 2807 | } | ||
| 2808 | |||
| 2809 | Move | ||
| 2810 | base_move(Move m) | ||
| 2811 | { | ||
| 2812 | if (m == NULLMOVE) | ||
| 2813 | return NULLMOVE; | ||
| 2814 | else | ||
| 2815 | return m - (m-1)%3; | ||
| 2816 | } | ||
| 2817 | |||
| 2818 | Cube | ||
| 2819 | compose(Cube c2, Cube c1) | ||
| 2820 | { | ||
| 2821 | return compose_filtered(c2, c1, pf_all); | ||
| 2822 | } | ||
| 2823 | |||
| 2824 | /*TODO maybe move the next two */ | ||
| 2825 | uint64_t | ||
| 2826 | cphtr(Cube cube) | ||
| 2827 | { | ||
| 2828 | return cphtr_right_cosets[cube.cp]; | ||
| 2829 | } | ||
| 2830 | |||
| 2831 | Cube | ||
| 2832 | anti_cphtr(uint64_t ind) | ||
| 2833 | { | ||
| 2834 | return (Cube) { .cp = cphtr_right_rep[ind] }; | ||
| 2835 | } | ||
| 2836 | |||
| 2837 | uint64_t | ||
| 2838 | epos_dependent(Cube c) | ||
| 2839 | { | ||
| 2840 | return epos_dependent_aux[c.eposs/FACTORIAL4][c.epose/FACTORIAL4]; | ||
| 2841 | } | ||
| 2842 | |||
| 2843 | bool | ||
| 2844 | equal(Cube c1, Cube c2) | ||
| 2845 | { | ||
| 2846 | return c1.eofb == c2.eofb && | ||
| 2847 | c1.epose == c2.epose && | ||
| 2848 | c1.eposs == c2.eposs && | ||
| 2849 | c1.eposm == c2.eposm && | ||
| 2850 | c1.coud == c2.coud && | ||
| 2851 | c1.cp == c2.cp && | ||
| 2852 | c1.cpos == c2.cpos; | ||
| 2853 | } | ||
| 2854 | |||
| 2855 | void | ||
| 2856 | genptable(PruneData *pd) | ||
| 2857 | { | ||
| 2858 | Cube cube; | ||
| 2859 | uint64_t j, oldn = 0; | ||
| 2860 | DfsData dd = { | ||
| 2861 | .m = 0, | ||
| 2862 | .last1 = NULLMOVE, | ||
| 2863 | .last2 = NULLMOVE | ||
| 2864 | }; | ||
| 2865 | |||
| 2866 | if (pd->generated) | ||
| 2867 | return; | ||
| 2868 | |||
| 2869 | /* TODO: check if memory is enough, otherwise maybe crash gracefully? */ | ||
| 2870 | pd->ptable = malloc(ptablesize(pd) * sizeof(uint8_t)); | ||
| 2871 | |||
| 2872 | if (read_ptable_file(pd)) { | ||
| 2873 | pd->generated = true; | ||
| 2874 | return; | ||
| 2875 | } | ||
| 2876 | |||
| 2877 | fprintf(stderr, "Cannot load %s, generating it\n", pd->filename); | ||
| 2878 | |||
| 2879 | /* We use 4 bits per value, so any distance >= 15 is set to 15 */ | ||
| 2880 | for (j = 0; j < pd->coord->max; j++) | ||
| 2881 | ptable_update(pd, pd->coord->cube(j), 15); | ||
| 2882 | |||
| 2883 | moveset_to_list(pd->moveset, NULL, dd.sorted_moves); | ||
| 2884 | movelist_to_position(dd.sorted_moves, dd.move_position); | ||
| 2885 | |||
| 2886 | pd->reached = malloc(ptablesize(pd) * sizeof(uint8_t)); | ||
| 2887 | for (dd.d = 0, pd->n = 0; dd.d < 15 && pd->n < pd->coord->max; dd.d++) { | ||
| 2888 | memset(pd->reached, 0, ptablesize(pd)*sizeof(uint8_t)); | ||
| 2889 | for (j = 0; j < pd->coord->max; j++) { | ||
| 2890 | cube = pd->coord->cube(j); | ||
| 2891 | if (pd->coord->check(cube)) | ||
| 2892 | genptable_dfs(cube, pd, &dd); | ||
| 2893 | } | ||
| 2894 | fprintf(stderr, "Depth %d done, generated %lu\t(%lu/%lu)\n", | ||
| 2895 | dd.d, pd->n-oldn, pd->n, pd->coord->max); | ||
| 2896 | oldn = pd->n; | ||
| 2897 | } | ||
| 2898 | |||
| 2899 | if (!write_ptable_file(pd)) | ||
| 2900 | fprintf(stderr, "Error writing ptable file\n"); | ||
| 2901 | |||
| 2902 | pd->generated = true; | ||
| 2903 | free(pd->reached); | ||
| 2904 | } | ||
| 2905 | |||
| 2906 | Cube | ||
| 2907 | inverse_cube(Cube cube) | ||
| 2908 | { | ||
| 2909 | CubeArray *arr = new_cubearray(cube, pf_all); | ||
| 2910 | CubeArray *inv = new_cubearray((Cube){0}, pf_all); | ||
| 2911 | Cube ret; | ||
| 2912 | int i; | ||
| 2913 | |||
| 2914 | for (i = 0; i < 12; i++) { | ||
| 2915 | inv->ep[arr->ep[i]] = i; | ||
| 2916 | inv->eofb[arr->ep[i]] = arr->eofb[i]; | ||
| 2917 | inv->eorl[arr->ep[i]] = arr->eorl[i]; | ||
| 2918 | inv->eoud[arr->ep[i]] = arr->eoud[i]; | ||
| 2919 | } | ||
| 2920 | |||
| 2921 | for (i = 0; i < 8; i++) { | ||
| 2922 | inv->cp[arr->cp[i]] = i; | ||
| 2923 | inv->coud[arr->cp[i]] = (3 - arr->coud[i]) % 3; | ||
| 2924 | inv->corl[arr->cp[i]] = (3 - arr->corl[i]) % 3; | ||
| 2925 | inv->cofb[arr->cp[i]] = (3 - arr->cofb[i]) % 3; | ||
| 2926 | } | ||
| 2927 | |||
| 2928 | for (int i = 0; i < 6; i++) | ||
| 2929 | inv->cpos[arr->cpos[i]] = i; | ||
| 2930 | |||
| 2931 | ret = arrays_to_cube(inv, pf_all); | ||
| 2932 | free_cubearray(arr, pf_all); | ||
| 2933 | free_cubearray(inv, pf_all); | ||
| 2934 | |||
| 2935 | return ret; | ||
| 2936 | } | ||
| 2937 | |||
| 2938 | Move | ||
| 2939 | inverse_move(Move m) | ||
| 2940 | { | ||
| 2941 | return inverse_move_aux[m]; | ||
| 2942 | } | ||
| 2943 | |||
| 2944 | Trans | ||
| 2945 | inverse_trans(Trans t) | ||
| 2946 | { | ||
| 2947 | return inverse_trans_aux[t]; | ||
| 2948 | } | ||
| 2949 | |||
| 2950 | bool | ||
| 2951 | is_admissible(Cube cube) | ||
| 2952 | { | ||
| 2953 | /* TODO: this should check consistency of different orientations */ | ||
| 2954 | /* TODO: check that centers are opposite and admissible */ | ||
| 2955 | |||
| 2956 | CubeArray *a = new_cubearray(cube, pf_all); | ||
| 2957 | int parity; | ||
| 2958 | bool perm; | ||
| 2959 | |||
| 2960 | perm = is_perm(a->ep, 12) && | ||
| 2961 | is_perm(a->cp, 8) && | ||
| 2962 | is_perm(a->cpos, 6); | ||
| 2963 | parity = perm_sign(a->ep, 12) + | ||
| 2964 | perm_sign(a->cp, 8) + | ||
| 2965 | perm_sign(a->cpos, 6); | ||
| 2966 | |||
| 2967 | return perm && parity % 2 == 0; | ||
| 2968 | } | ||
| 2969 | |||
| 2970 | bool | ||
| 2971 | is_solved(Cube cube, bool reorient) | ||
| 2972 | { | ||
| 2973 | int i; | ||
| 2974 | |||
| 2975 | if (reorient) { | ||
| 2976 | for (i = 0; i < NROTATIONS; i++) | ||
| 2977 | if (is_solved(apply_alg(rotation_algs[i], cube),false)) | ||
| 2978 | return true; | ||
| 2979 | return false; | ||
| 2980 | } else { | ||
| 2981 | return equal(cube, (Cube){0}); | ||
| 2982 | } | ||
| 2983 | } | ||
| 2984 | |||
| 2985 | bool | ||
| 2986 | is_solved_block(Cube cube, Block block) | ||
| 2987 | { | ||
| 2988 | int i; | ||
| 2989 | |||
| 2990 | for (i = 0; i < 12; i++) | ||
| 2991 | if (block.edge[i] && !is_solved_edge(cube, i)) | ||
| 2992 | return false; | ||
| 2993 | for (i = 0; i < 8; i++) | ||
| 2994 | if (block.corner[i] && !is_solved_corner(cube, i)) | ||
| 2995 | return false; | ||
| 2996 | for (i = 0; i < 6; i++) | ||
| 2997 | if (block.center[i] && !is_solved_center(cube, i)) | ||
| 2998 | return false; | ||
| 2999 | |||
| 3000 | return true; | ||
| 3001 | } | ||
| 3002 | |||
| 3003 | bool | ||
| 3004 | is_solved_center(Cube cube, Center c) | ||
| 3005 | { | ||
| 3006 | return what_center_at(cube, c) == c; | ||
| 3007 | } | ||
| 3008 | |||
| 3009 | bool | ||
| 3010 | is_solved_corner(Cube cube, Corner c) | ||
| 3011 | { | ||
| 3012 | return what_corner_at(cube, c) == c && | ||
| 3013 | what_orientation_corner(cube.coud, c); | ||
| 3014 | } | ||
| 3015 | |||
| 3016 | bool | ||
| 3017 | is_solved_edge(Cube cube, Edge e) | ||
| 3018 | { | ||
| 3019 | return what_edge_at(cube, e) == e && | ||
| 3020 | what_orientation_edge(cube.eofb, e); | ||
| 3021 | } | ||
| 3022 | |||
| 3023 | int | ||
| 3024 | piece_orientation(Cube cube, int piece, char *orientation) | ||
| 3025 | { | ||
| 3026 | int arr[12], n, b, x; | ||
| 3027 | |||
| 3028 | if (!strcmp(orientation, "eofb")) { | ||
| 3029 | x = cube.eofb; | ||
| 3030 | n = 12; | ||
| 3031 | b = 2; | ||
| 3032 | } else if (!strcmp(orientation, "eorl")) { | ||
| 3033 | x = cube.eorl; | ||
| 3034 | n = 12; | ||
| 3035 | b = 2; | ||
| 3036 | } else if (!strcmp(orientation, "eoud")) { | ||
| 3037 | x = cube.eoud; | ||
| 3038 | n = 12; | ||
| 3039 | b = 2; | ||
| 3040 | } else if (!strcmp(orientation, "coud")) { | ||
| 3041 | x = cube.coud; | ||
| 3042 | n = 8; | ||
| 3043 | b = 3; | ||
| 3044 | } else if (!strcmp(orientation, "corl")) { | ||
| 3045 | x = cube.corl; | ||
| 3046 | n = 8; | ||
| 3047 | b = 3; | ||
| 3048 | } else if (!strcmp(orientation, "cofb")) { | ||
| 3049 | x = cube.cofb; | ||
| 3050 | n = 8; | ||
| 3051 | b = 3; | ||
| 3052 | } else { | ||
| 3053 | return -1; | ||
| 3054 | } | ||
| 3055 | |||
| 3056 | int_to_sum_zero_array(x, b, n, arr); | ||
| 3057 | if (piece < n) | ||
| 3058 | return arr[piece]; | ||
| 3059 | |||
| 3060 | return -1; | ||
| 3061 | } | ||
| 3062 | |||
| 3063 | void | ||
| 3064 | print_cube(Cube cube) | ||
| 3065 | { | ||
| 3066 | /* | ||
| 3067 | CubeArray *arr = new_cubearray(cube, pf_all); | ||
| 3068 | |||
| 3069 | for (int i = 0; i < 12; i++) | ||
| 3070 | printf(" %s ", edge_string[arr->ep[i]]); | ||
| 3071 | printf("\n"); | ||
| 3072 | |||
| 3073 | for (int i = 0; i < 12; i++) | ||
| 3074 | printf(" %c ", arr->eofb[i] + '0'); | ||
| 3075 | printf("\n"); | ||
| 3076 | |||
| 3077 | for (int i = 0; i < 8; i++) | ||
| 3078 | printf("%s ", corner_string[arr->cp[i]]); | ||
| 3079 | printf("\n"); | ||
| 3080 | |||
| 3081 | for (int i = 0; i < 8; i++) | ||
| 3082 | printf(" %c ", arr->coud[i] + '0'); | ||
| 3083 | printf("\n"); | ||
| 3084 | |||
| 3085 | for (int i = 0; i < 6; i++) | ||
| 3086 | printf(" %s ", center_string[arr->cpos[i]]); | ||
| 3087 | printf("\n"); | ||
| 3088 | |||
| 3089 | free_cubearray(arr, pf_all); | ||
| 3090 | */ | ||
| 3091 | |||
| 3092 | for (int i = 0; i < 12; i++) | ||
| 3093 | printf(" %s ", edge_string[what_edge_at(cube, i)]); | ||
| 3094 | printf("\n"); | ||
| 3095 | |||
| 3096 | for (int i = 0; i < 12; i++) | ||
| 3097 | printf(" %d ", what_orientation_edge(cube.eofb, i)); | ||
| 3098 | printf("\n"); | ||
| 3099 | |||
| 3100 | for (int i = 0; i < 8; i++) | ||
| 3101 | printf("%s ", corner_string[what_corner_at(cube, i)]); | ||
| 3102 | printf("\n"); | ||
| 3103 | |||
| 3104 | for (int i = 0; i < 8; i++) | ||
| 3105 | printf(" %d ", what_orientation_corner(cube.coud, i)); | ||
| 3106 | printf("\n"); | ||
| 3107 | |||
| 3108 | for (int i = 0; i < 6; i++) | ||
| 3109 | printf(" %s ", center_string[what_center_at(cube, i)]); | ||
| 3110 | printf("\n"); | ||
| 3111 | |||
| 3112 | } | ||
| 3113 | |||
| 3114 | Cube | ||
| 3115 | random_cube() | ||
| 3116 | { | ||
| 3117 | CubeArray *arr = new_cubearray((Cube){0}, pf_4val); | ||
| 3118 | Cube ret; | ||
| 3119 | int ep, cp, eo, co; | ||
| 3120 | |||
| 3121 | ep = rand() % FACTORIAL12; | ||
| 3122 | cp = rand() % FACTORIAL8; | ||
| 3123 | eo = rand() % POW2TO11; | ||
| 3124 | co = rand() % POW3TO7; | ||
| 3125 | |||
| 3126 | index_to_perm(ep, 12, arr->ep); | ||
| 3127 | index_to_perm(cp, 8, arr->cp); | ||
| 3128 | int_to_sum_zero_array(eo, 2, 12, arr->eofb); | ||
| 3129 | int_to_sum_zero_array(co, 3, 8, arr->coud); | ||
| 3130 | |||
| 3131 | if (perm_sign(arr->ep, 12) != perm_sign(arr->cp, 8)) | ||
| 3132 | swap(&(arr->ep[0]), &(arr->ep[1])); | ||
| 3133 | |||
| 3134 | ret = arrays_to_cube(arr, pf_4val); | ||
| 3135 | free_cubearray(arr, pf_4val); | ||
| 3136 | |||
| 3137 | return ret; | ||
| 3138 | } | ||
| 3139 | |||
| 3140 | /* TODO: clean pre_trans or put it back */ | ||
| 3141 | AlgList * | ||
| 3142 | solve(Cube cube, Step step, SolveOptions *opts) | ||
| 3143 | { | ||
| 3144 | /*AlgListNode *node;*/ | ||
| 3145 | AlgList *sols = new_alglist(); | ||
| 3146 | /*Cube c = apply_trans(opts->pre_trans, cube);*/ | ||
| 3147 | DfsData dd = { | ||
| 3148 | .m = 0, | ||
| 3149 | .niss = false, | ||
| 3150 | .lb = -1, | ||
| 3151 | .last1 = NULLMOVE, | ||
| 3152 | .last2 = NULLMOVE, | ||
| 3153 | .sols = sols, | ||
| 3154 | .current_alg = new_alg("") | ||
| 3155 | }; | ||
| 3156 | |||
| 3157 | if (step.ready != NULL && !step.ready(cube)) { | ||
| 3158 | fprintf(stderr, "Cube not ready for solving step\n"); | ||
| 3159 | return sols; | ||
| 3160 | } | ||
| 3161 | |||
| 3162 | moveset_to_list(step.moveset, step.estimate, dd.sorted_moves); | ||
| 3163 | movelist_to_position(dd.sorted_moves, dd.move_position); | ||
| 3164 | |||
| 3165 | for (dd.d = opts->min_moves; | ||
| 3166 | dd.d <= opts->max_moves && !(sols->len && opts->optimal_only); | ||
| 3167 | dd.d++) { | ||
| 3168 | if (opts->feedback) | ||
| 3169 | fprintf(stderr, | ||
| 3170 | "Found %d solutions, searching depth %d...\n", | ||
| 3171 | sols->len, dd.d); | ||
| 3172 | dfs(cube, step, opts, &dd); | ||
| 3173 | } | ||
| 3174 | |||
| 3175 | /* | ||
| 3176 | for (node = sols->first; node != NULL; node = node->next) | ||
| 3177 | transform_alg(inverse_trans(opts->pre_trans), node->alg); | ||
| 3178 | */ | ||
| 3179 | |||
| 3180 | free_alg(dd.current_alg); | ||
| 3181 | return sols; | ||
| 3182 | } | ||
| 3183 | |||
| 3184 | Alg * | ||
| 3185 | inverse_alg(Alg *alg) | ||
| 3186 | { | ||
| 3187 | Alg *ret = new_alg(""); | ||
| 3188 | int i; | ||
| 3189 | |||
| 3190 | for (i = alg->len-1; i >= 0; i--) | ||
| 3191 | append_move(ret, inverse_move(alg->move[i]), alg->inv[i]); | ||
| 3192 | |||
| 3193 | return ret; | ||
| 3194 | } | ||
| 3195 | |||
| 3196 | Alg * | ||
| 3197 | new_alg(char *str) | ||
| 3198 | { | ||
| 3199 | Alg *alg = malloc(sizeof(Alg)); | ||
| 3200 | int i; | ||
| 3201 | bool niss = false; | ||
| 3202 | Move j, m; | ||
| 3203 | |||
| 3204 | alg->move = malloc(30 * sizeof(Move)); | ||
| 3205 | alg->inv = malloc(30 * sizeof(bool)); | ||
| 3206 | alg->allocated = 30; | ||
| 3207 | alg->len = 0; | ||
| 3208 | |||
| 3209 | for (i = 0; str[i]; i++) { | ||
| 3210 | if (str[i] == ' ' || str[i] == '\t' || str[i] == '\n') | ||
| 3211 | continue; | ||
| 3212 | |||
| 3213 | if (str[i] == '(' && niss) { | ||
| 3214 | fprintf(stderr, "Error reading moves: nested ( )\n"); | ||
| 3215 | return alg; | ||
| 3216 | } | ||
| 3217 | |||
| 3218 | if (str[i] == ')' && !niss) { | ||
| 3219 | fprintf(stderr, "Error reading moves: unmatched )\n"); | ||
| 3220 | return alg; | ||
| 3221 | } | ||
| 3222 | |||
| 3223 | if (str[i] == '(' || str[i] == ')') { | ||
| 3224 | niss = !niss; | ||
| 3225 | continue; | ||
| 3226 | } | ||
| 3227 | |||
| 3228 | for (j = 0; j < NMOVES; j++) { | ||
| 3229 | if (str[i] == move_string[j][0]) { | ||
| 3230 | m = j; | ||
| 3231 | if (m <= B && str[i+1]=='w') { | ||
| 3232 | m += Uw - U; | ||
| 3233 | i++; | ||
| 3234 | } | ||
| 3235 | if (str[i+1]=='2') { | ||
| 3236 | m += 1; | ||
| 3237 | i++; | ||
| 3238 | } else if (str[i+1]=='\'' || str[i+1]=='3') { | ||
| 3239 | m += 2; | ||
| 3240 | i++; | ||
| 3241 | } | ||
| 3242 | append_move(alg, m, niss); | ||
| 3243 | break; | ||
| 3244 | } | ||
| 3245 | } | ||
| 3246 | } | ||
| 3247 | |||
| 3248 | return alg; | ||
| 3249 | } | ||
| 3250 | |||
| 3251 | Alg * | ||
| 3252 | on_inverse(Alg *alg) | ||
| 3253 | { | ||
| 3254 | Alg *ret = new_alg(""); | ||
| 3255 | int i; | ||
| 3256 | |||
| 3257 | for (i = 0; i < alg->len; i++) | ||
| 3258 | append_move(ret, alg->move[i], !alg->inv[i]); | ||
| 3259 | |||
| 3260 | return ret; | ||
| 3261 | } | ||
| 3262 | |||
| 3263 | void | ||
| 3264 | print_alg(Alg *alg, bool l) | ||
| 3265 | { | ||
| 3266 | /* TODO: make it possible to print to stdout or to string */ | ||
| 3267 | /* Maybe just return a string */ | ||
| 3268 | char fill[4]; | ||
| 3269 | int i; | ||
| 3270 | bool niss = false; | ||
| 3271 | |||
| 3272 | for (i = 0; i < alg->len; i++) { | ||
| 3273 | if (!niss && alg->inv[i]) | ||
| 3274 | strcpy(fill, i == 0 ? "(" : " ("); | ||
| 3275 | if (niss && !alg->inv[i]) | ||
| 3276 | strcpy(fill, ") "); | ||
| 3277 | if (niss == alg->inv[i]) | ||
| 3278 | strcpy(fill, i == 0 ? "" : " "); | ||
| 3279 | |||
| 3280 | printf("%s%s", fill, move_string[alg->move[i]]); | ||
| 3281 | niss = alg->inv[i]; | ||
| 3282 | } | ||
| 3283 | |||
| 3284 | if (niss) | ||
| 3285 | printf(")"); | ||
| 3286 | if (l) | ||
| 3287 | printf(" (%d)", alg->len); | ||
| 3288 | |||
| 3289 | printf("\n"); | ||
| 3290 | } | ||
| 3291 | |||
| 3292 | void | ||
| 3293 | print_alglist(AlgList *al, bool l) | ||
| 3294 | { | ||
| 3295 | AlgListNode *i; | ||
| 3296 | |||
| 3297 | for (i = al->first; i != NULL; i = i->next) | ||
| 3298 | print_alg(i->alg, l); | ||
| 3299 | } | ||
| 3300 | |||
| 3301 | void | ||
| 3302 | print_ptable(PruneData *pd) | ||
| 3303 | { | ||
| 3304 | uint64_t i, a[16]; | ||
| 3305 | |||
| 3306 | for (i = 0; i < 16; i++) | ||
| 3307 | a[i] = 0; | ||
| 3308 | |||
| 3309 | if (!pd->generated) | ||
| 3310 | genptable(pd); | ||
| 3311 | |||
| 3312 | for (i = 0; i < pd->coord->max; i++) | ||
| 3313 | a[ptableval(pd, pd->coord->cube(i))]++; | ||
| 3314 | |||
| 3315 | fprintf(stderr, "Values for table %s\n", pd->filename); | ||
| 3316 | for (i = 0; i < 16; i++) | ||
| 3317 | printf("%2lu\t%10lu\n", i, a[i]); | ||
| 3318 | } | ||
| 3319 | |||
| 3320 | uint64_t | ||
| 3321 | ptablesize(PruneData *pd) | ||
| 3322 | { | ||
| 3323 | return (pd->coord->max + 1) / 2; | ||
| 3324 | } | ||
| 3325 | |||
| 3326 | int | ||
| 3327 | ptableval(PruneData *pd, Cube cube) | ||
| 3328 | { | ||
| 3329 | uint64_t ind = pd->coord->index(cube); | ||
| 3330 | |||
| 3331 | return (ind % 2) ? pd->ptable[ind/2] / 16 : pd->ptable[ind/2] % 16; | ||
| 3332 | } | ||
| 3333 | |||
| 3334 | |||
| 3335 | Alg * | ||
| 3336 | rotation_alg(Trans i) | ||
| 3337 | { | ||
| 3338 | return rotation_algs[i % NROTATIONS]; | ||
| 3339 | } | ||
| 3340 | |||
| 3341 | void | ||
| 3342 | transform_alg(Trans t, Alg *alg) | ||
| 3343 | { | ||
| 3344 | int i; | ||
| 3345 | |||
| 3346 | for (i = 0; i < alg->len; i++) | ||
| 3347 | alg->move[i] = moves_ttable[t][alg->move[i]]; | ||
| 3348 | } | ||
| 3349 | |||
| 3350 | Center | ||
| 3351 | what_center_at(Cube cube, Center c) | ||
| 3352 | { | ||
| 3353 | return what_center_at_aux[cube.cpos][c]; | ||
| 3354 | } | ||
| 3355 | |||
| 3356 | Corner | ||
| 3357 | what_corner_at(Cube cube, Corner c) | ||
| 3358 | { | ||
| 3359 | return what_corner_at_aux[cube.cp][c]; | ||
| 3360 | } | ||
| 3361 | |||
| 3362 | Edge | ||
| 3363 | what_edge_at(Cube cube, Edge e) | ||
| 3364 | { | ||
| 3365 | Edge ret; | ||
| 3366 | CubeArray *arr = new_cubearray(cube, pf_ep); | ||
| 3367 | |||
| 3368 | ret = arr->ep[e]; | ||
| 3369 | |||
| 3370 | free_cubearray(arr, pf_ep); | ||
| 3371 | return ret; | ||
| 3372 | } | ||
| 3373 | |||
| 3374 | int | ||
| 3375 | what_orientation_corner(int co, Corner c) | ||
| 3376 | { | ||
| 3377 | if (c < 7) | ||
| 3378 | return (co / powint(3, c)) % 3; | ||
| 3379 | else | ||
| 3380 | return what_orientation_last_corner_aux[co]; | ||
| 3381 | } | ||
| 3382 | |||
| 3383 | int | ||
| 3384 | what_orientation_edge(int eo, Edge e) | ||
| 3385 | { | ||
| 3386 | if (e < 11) | ||
| 3387 | return (eo & (1 << e)) ? 1 : 0; | ||
| 3388 | else | ||
| 3389 | return what_orientation_last_edge_aux[eo]; | ||
| 3390 | } | ||
| 3391 | |||
| 3392 | Center | ||
| 3393 | where_is_center(Cube cube, Center c) | ||
| 3394 | { | ||
| 3395 | return where_is_center_aux[cube.cpos][c]; | ||
| 3396 | } | ||
| 3397 | |||
| 3398 | Corner | ||
| 3399 | where_is_corner(Cube cube, Corner c) | ||
| 3400 | { | ||
| 3401 | return where_is_corner_aux[cube.cp][c]; | ||
| 3402 | } | ||
| 3403 | |||
| 3404 | |||
| 3405 | void | ||
| 3406 | init() | ||
| 3407 | { | ||
| 3408 | /* Order is important! */ | ||
| 3409 | init_environment(); | ||
| 3410 | init_strings(); | ||
| 3411 | init_moves_aux(); | ||
| 3412 | init_moves(); | ||
| 3413 | init_auxtables(); | ||
| 3414 | init_cphtr_cosets(); | ||
| 3415 | init_trans_aux(); | ||
| 3416 | init_trans(); | ||
| 3417 | init_symdata(); | ||
| 3418 | } | ||
| 3419 | |||
diff --git a/old/2021-06-30-reached/cube.h b/old/2021-06-30-reached/cube.h new file mode 100644 index 0000000..ffbcd86 --- /dev/null +++ b/old/2021-06-30-reached/cube.h | |||
| @@ -0,0 +1,90 @@ | |||
| 1 | #ifndef CUBE_H | ||
| 2 | #define CUBE_H | ||
| 3 | |||
| 4 | #include <stdio.h> | ||
| 5 | #include <stdbool.h> | ||
| 6 | #include <stdint.h> | ||
| 7 | #include <stdlib.h> | ||
| 8 | #include <string.h> | ||
| 9 | #include <time.h> | ||
| 10 | #include <unistd.h> | ||
| 11 | #include <sys/stat.h> | ||
| 12 | |||
| 13 | #include "macros.h" | ||
| 14 | #include "cubetypes.h" | ||
| 15 | |||
| 16 | extern Coordinate coord_eofb; | ||
| 17 | extern Coordinate coord_eofbepos; | ||
| 18 | extern Coordinate coord_coud; | ||
| 19 | extern Coordinate coord_corners; | ||
| 20 | extern Coordinate coord_cornershtr; | ||
| 21 | extern Coordinate coord_drud; | ||
| 22 | extern Coordinate coord_coud_sym16; | ||
| 23 | extern Coordinate coord_eofbepos_sym16; | ||
| 24 | extern Coordinate coord_drud_sym16; | ||
| 25 | extern Coordinate coord_khuge; | ||
| 26 | |||
| 27 | Cube apply_alg(Alg *alg, Cube cube); | ||
| 28 | Cube apply_move(Move m, Cube cube); | ||
| 29 | Cube apply_trans(Trans t, Cube cube); | ||
| 30 | bool block_solved(Cube cube, Block); | ||
| 31 | Cube compose(Cube c2, Cube c1); /* Use c2 as an alg on c1 */ | ||
| 32 | uint64_t cphtr(Cube cube); /* TODO: rename (something with cosets) */ | ||
| 33 | Cube anti_cphtr(uint64_t ind); /*TODO also this */ | ||
| 34 | uint64_t epos_dependent(Cube cube); /* TODO: rename and turn into an indexer */ | ||
| 35 | bool equal(Cube c1, Cube c2); | ||
| 36 | Cube inverse_cube(Cube cube); | ||
| 37 | Move inverse_move(Move m); | ||
| 38 | Trans inverse_trans(Trans t); | ||
| 39 | bool is_admissible(Cube cube); | ||
| 40 | bool is_solved(Cube cube, bool reorient); | ||
| 41 | bool is_solved_center(Cube cube, Center c); | ||
| 42 | bool is_solved_corner(Cube cube, Corner c); | ||
| 43 | bool is_solved_edge(Cube cube, Edge e); | ||
| 44 | void print_cube(Cube cube); | ||
| 45 | Cube random_cube(); | ||
| 46 | AlgList * solve(Cube cube, Step step, SolveOptions *opts); | ||
| 47 | Center what_center_at(Cube cube, Center c); | ||
| 48 | Corner what_corner_at(Cube cube, Corner c); | ||
| 49 | Edge what_edge_at(Cube cube, Edge e); | ||
| 50 | int what_orientation_corner(int co, Corner c); | ||
| 51 | int what_orientation_edge(int eo, Edge e); | ||
| 52 | Center where_is_center(Cube cube, Center c); | ||
| 53 | Corner where_is_corner(Cube cube, Corner c); | ||
| 54 | Edge where_is_edge(Cube cube, Edge e); | ||
| 55 | |||
| 56 | bool check_centers(Cube cube); | ||
| 57 | bool check_corners(Cube cube); | ||
| 58 | bool check_cornershtr(Cube cube); | ||
| 59 | bool check_coud(Cube cube); | ||
| 60 | bool check_drud(Cube cube); | ||
| 61 | bool check_eofb(Cube cube); | ||
| 62 | bool check_eofbepos(Cube cube); | ||
| 63 | bool check_epose(Cube cube); | ||
| 64 | bool check_ep(Cube cube); | ||
| 65 | bool check_khuge(Cube cube); | ||
| 66 | bool check_nothing(Cube cube); | ||
| 67 | |||
| 68 | bool moveset_HTM(Move m); | ||
| 69 | bool moveset_URF(Move m); | ||
| 70 | |||
| 71 | Move base_move(Move m); | ||
| 72 | void free_alg(Alg *alg); | ||
| 73 | void free_alglist(AlgList *l); | ||
| 74 | Alg * inverse_alg(Alg *alg); | ||
| 75 | Alg * new_alg(char *str); | ||
| 76 | Alg * on_inverse(Alg *alg); | ||
| 77 | void print_alg(Alg *alg, bool l); | ||
| 78 | void print_alglist(AlgList *al, bool l); | ||
| 79 | Alg * rotation_alg(Trans i); | ||
| 80 | void transform_alg(Trans t, Alg *alg); | ||
| 81 | |||
| 82 | void genptable(PruneData *pd); | ||
| 83 | void print_ptable(PruneData *pd); | ||
| 84 | uint64_t ptablesize(PruneData *pd); | ||
| 85 | int ptableval(PruneData *pd, Cube cube); | ||
| 86 | |||
| 87 | void init(); | ||
| 88 | |||
| 89 | #endif | ||
| 90 | |||
diff --git a/old/2021-06-30-reached/cubetypes.h b/old/2021-06-30-reached/cubetypes.h new file mode 100644 index 0000000..0a7961d --- /dev/null +++ b/old/2021-06-30-reached/cubetypes.h | |||
| @@ -0,0 +1,251 @@ | |||
| 1 | #ifndef CUBETYPES_H | ||
| 2 | #define CUBETYPES_H | ||
| 3 | |||
| 4 | /* Typedefs ******************************************************************/ | ||
| 5 | |||
| 6 | typedef enum center Center; | ||
| 7 | typedef enum corner Corner; | ||
| 8 | typedef enum edge Edge; | ||
| 9 | typedef enum move Move; | ||
| 10 | typedef enum trans Trans; | ||
| 11 | |||
| 12 | typedef struct alg Alg; | ||
| 13 | typedef struct alglist AlgList; | ||
| 14 | typedef struct alglistnode AlgListNode; | ||
| 15 | typedef struct block Block; | ||
| 16 | typedef struct coordinate Coordinate; | ||
| 17 | typedef struct cube Cube; | ||
| 18 | typedef struct cubearray CubeArray; | ||
| 19 | typedef struct cubetarget CubeTarget; | ||
| 20 | typedef struct dfsdata DfsData; | ||
| 21 | typedef struct piecefilter PieceFilter; | ||
| 22 | typedef struct prunedata PruneData; | ||
| 23 | typedef struct solveoptions SolveOptions; | ||
| 24 | typedef struct step Step; | ||
| 25 | typedef struct symdata SymData; | ||
| 26 | |||
| 27 | typedef Cube (*AntiIndexer) (uint64_t); | ||
| 28 | typedef bool (*Checker) (Cube); | ||
| 29 | typedef int (*Estimator) (CubeTarget); | ||
| 30 | typedef uint64_t (*Indexer) (Cube); | ||
| 31 | typedef bool (*Moveset) (Move); | ||
| 32 | |||
| 33 | |||
| 34 | /* Enums *********************************************************************/ | ||
| 35 | |||
| 36 | enum | ||
| 37 | center | ||
| 38 | { | ||
| 39 | U_center, D_center, | ||
| 40 | R_center, L_center, | ||
| 41 | F_center, B_center | ||
| 42 | }; | ||
| 43 | |||
| 44 | enum | ||
| 45 | corner | ||
| 46 | { | ||
| 47 | UFR, UFL, UBL, UBR, | ||
| 48 | DFR, DFL, DBL, DBR | ||
| 49 | }; | ||
| 50 | |||
| 51 | enum | ||
| 52 | edge | ||
| 53 | { | ||
| 54 | UF, UL, UB, UR, | ||
| 55 | DF, DL, DB, DR, | ||
| 56 | FR, FL, BL, BR | ||
| 57 | }; | ||
| 58 | |||
| 59 | enum | ||
| 60 | move | ||
| 61 | { | ||
| 62 | NULLMOVE, | ||
| 63 | U, U2, U3, D, D2, D3, | ||
| 64 | R, R2, R3, L, L2, L3, | ||
| 65 | F, F2, F3, B, B2, B3, | ||
| 66 | Uw, Uw2, Uw3, Dw, Dw2, Dw3, | ||
| 67 | Rw, Rw2, Rw3, Lw, Lw2, Lw3, | ||
| 68 | Fw, Fw2, Fw3, Bw, Bw2, Bw3, | ||
| 69 | M, M2, M3, | ||
| 70 | S, S2, S3, | ||
| 71 | E, E2, E3, | ||
| 72 | x, x2, x3, | ||
| 73 | y, y2, y3, | ||
| 74 | z, z2, z3, | ||
| 75 | }; | ||
| 76 | |||
| 77 | enum | ||
| 78 | trans | ||
| 79 | { | ||
| 80 | uf, ur, ub, ul, | ||
| 81 | df, dr, db, dl, | ||
| 82 | rf, rd, rb, ru, | ||
| 83 | lf, ld, lb, lu, | ||
| 84 | fu, fr, fd, fl, | ||
| 85 | bu, br, bd, bl, | ||
| 86 | uf_mirror, ur_mirror, ub_mirror, ul_mirror, | ||
| 87 | df_mirror, dr_mirror, db_mirror, dl_mirror, | ||
| 88 | rf_mirror, rd_mirror, rb_mirror, ru_mirror, | ||
| 89 | lf_mirror, ld_mirror, lb_mirror, lu_mirror, | ||
| 90 | fu_mirror, fr_mirror, fd_mirror, fl_mirror, | ||
| 91 | bu_mirror, br_mirror, bd_mirror, bl_mirror, | ||
| 92 | }; | ||
| 93 | |||
| 94 | |||
| 95 | /* Structs *******************************************************************/ | ||
| 96 | |||
| 97 | struct | ||
| 98 | alg | ||
| 99 | { | ||
| 100 | Move * move; | ||
| 101 | bool * inv; | ||
| 102 | int len; | ||
| 103 | int allocated; | ||
| 104 | }; | ||
| 105 | |||
| 106 | struct | ||
| 107 | alglist | ||
| 108 | { | ||
| 109 | AlgListNode * first; | ||
| 110 | AlgListNode * last; | ||
| 111 | int len; | ||
| 112 | }; | ||
| 113 | |||
| 114 | struct | ||
| 115 | alglistnode | ||
| 116 | { | ||
| 117 | Alg * alg; | ||
| 118 | AlgListNode * next; | ||
| 119 | }; | ||
| 120 | |||
| 121 | struct | ||
| 122 | block | ||
| 123 | { | ||
| 124 | bool edge[12]; | ||
| 125 | bool corner[8]; | ||
| 126 | bool center[6]; | ||
| 127 | }; | ||
| 128 | |||
| 129 | struct | ||
| 130 | coordinate | ||
| 131 | { | ||
| 132 | Indexer index; | ||
| 133 | AntiIndexer cube; | ||
| 134 | Checker check; | ||
| 135 | uint64_t max; | ||
| 136 | }; | ||
| 137 | |||
| 138 | struct | ||
| 139 | cube | ||
| 140 | { | ||
| 141 | int epose; | ||
| 142 | int eposs; | ||
| 143 | int eposm; | ||
| 144 | int eofb; | ||
| 145 | int eorl; | ||
| 146 | int eoud; | ||
| 147 | int cp; | ||
| 148 | int coud; | ||
| 149 | int cofb; | ||
| 150 | int corl; | ||
| 151 | int cpos; | ||
| 152 | }; | ||
| 153 | |||
| 154 | struct | ||
| 155 | cubearray | ||
| 156 | { | ||
| 157 | int * ep; | ||
| 158 | int * eofb; | ||
| 159 | int * eorl; | ||
| 160 | int * eoud; | ||
| 161 | int * cp; | ||
| 162 | int * coud; | ||
| 163 | int * corl; | ||
| 164 | int * cofb; | ||
| 165 | int * cpos; | ||
| 166 | }; | ||
| 167 | |||
| 168 | struct | ||
| 169 | cubetarget | ||
| 170 | { | ||
| 171 | Cube cube; | ||
| 172 | int target; | ||
| 173 | }; | ||
| 174 | |||
| 175 | struct | ||
| 176 | dfsdata | ||
| 177 | { | ||
| 178 | int d; | ||
| 179 | int m; | ||
| 180 | int lb; | ||
| 181 | bool niss; | ||
| 182 | Move last1; | ||
| 183 | Move last2; | ||
| 184 | AlgList * sols; | ||
| 185 | Alg * current_alg; | ||
| 186 | Move sorted_moves[NMOVES]; | ||
| 187 | int move_position[NMOVES]; | ||
| 188 | }; | ||
| 189 | |||
| 190 | struct | ||
| 191 | piecefilter | ||
| 192 | { | ||
| 193 | bool epose; | ||
| 194 | bool eposs; | ||
| 195 | bool eposm; | ||
| 196 | bool eofb; | ||
| 197 | bool eorl; | ||
| 198 | bool eoud; | ||
| 199 | bool cp; | ||
| 200 | bool coud; | ||
| 201 | bool cofb; | ||
| 202 | bool corl; | ||
| 203 | bool cpos; | ||
| 204 | }; | ||
| 205 | |||
| 206 | struct | ||
| 207 | prunedata | ||
| 208 | { | ||
| 209 | char * filename; | ||
| 210 | uint8_t * ptable; | ||
| 211 | uint8_t * reached; | ||
| 212 | bool generated; | ||
| 213 | uint64_t n; | ||
| 214 | Coordinate * coord; | ||
| 215 | Moveset moveset; | ||
| 216 | }; | ||
| 217 | |||
| 218 | struct | ||
| 219 | solveoptions | ||
| 220 | { | ||
| 221 | int min_moves; | ||
| 222 | int max_moves; | ||
| 223 | int max_solutions; | ||
| 224 | bool optimal_only; | ||
| 225 | bool can_niss; | ||
| 226 | bool feedback; | ||
| 227 | }; | ||
| 228 | |||
| 229 | struct | ||
| 230 | step | ||
| 231 | { | ||
| 232 | Estimator estimate; | ||
| 233 | Checker ready; | ||
| 234 | Moveset moveset; | ||
| 235 | }; | ||
| 236 | |||
| 237 | struct | ||
| 238 | symdata | ||
| 239 | { | ||
| 240 | char * filename; | ||
| 241 | bool generated; | ||
| 242 | Coordinate * coord; | ||
| 243 | Coordinate * sym_coord; | ||
| 244 | int ntrans; | ||
| 245 | Trans * trans; | ||
| 246 | uint64_t * class; | ||
| 247 | Cube * rep; | ||
| 248 | Trans * transtorep; | ||
| 249 | }; | ||
| 250 | |||
| 251 | #endif | ||
diff --git a/old/2021-06-30-reached/macros.h b/old/2021-06-30-reached/macros.h new file mode 100644 index 0000000..af3bca1 --- /dev/null +++ b/old/2021-06-30-reached/macros.h | |||
| @@ -0,0 +1,23 @@ | |||
| 1 | #ifndef MACROS_H | ||
| 2 | #define MACROS_H | ||
| 3 | |||
| 4 | #define POW2TO6 64ULL | ||
| 5 | #define POW2TO11 2048ULL | ||
| 6 | #define POW2TO12 4096ULL | ||
| 7 | #define POW3TO7 2187ULL | ||
| 8 | #define POW3TO8 6561ULL | ||
| 9 | #define FACTORIAL4 24ULL | ||
| 10 | #define FACTORIAL6 720ULL | ||
| 11 | #define FACTORIAL7 5040ULL | ||
| 12 | #define FACTORIAL8 40320ULL | ||
| 13 | #define FACTORIAL12 479001600ULL | ||
| 14 | #define BINOM12ON4 495ULL | ||
| 15 | #define BINOM8ON4 70ULL | ||
| 16 | #define MIN(a,b) (((a) < (b)) ? (a) : (b)) | ||
| 17 | #define MAX(a,b) (((a) > (b)) ? (a) : (b)) | ||
| 18 | |||
| 19 | #define NMOVES (z3+1) | ||
| 20 | #define NTRANS 48 | ||
| 21 | #define NROTATIONS 24 | ||
| 22 | |||
| 23 | #endif | ||
diff --git a/old/2021-06-30-reached/main.c b/old/2021-06-30-reached/main.c new file mode 100644 index 0000000..1ebd917 --- /dev/null +++ b/old/2021-06-30-reached/main.c | |||
| @@ -0,0 +1,80 @@ | |||
| 1 | #include <stdio.h> | ||
| 2 | #include "cube.h" | ||
| 3 | #include "steps.h" | ||
| 4 | |||
| 5 | int main() { | ||
| 6 | Alg *algo; | ||
| 7 | AlgList *sols; | ||
| 8 | Cube cube; | ||
| 9 | SolveOptions opts; | ||
| 10 | char line[1000]; | ||
| 11 | int i, ns = 2; | ||
| 12 | /* Move m;*/ | ||
| 13 | /* int nrand = 10000, sum1, sum2, sum3;*/ | ||
| 14 | |||
| 15 | Step *stps[20] = {&drud_HTM, &optimal_HTM}; | ||
| 16 | char sss[30][30] = {"DR on UD", "Optimal solve"}; | ||
| 17 | |||
| 18 | opts = (SolveOptions) { | ||
| 19 | .min_moves = 0, | ||
| 20 | .max_moves = 20, | ||
| 21 | .optimal_only = true, | ||
| 22 | .max_solutions = 1, | ||
| 23 | .can_niss = false, | ||
| 24 | .feedback = true, | ||
| 25 | }; | ||
| 26 | |||
| 27 | init(); | ||
| 28 | |||
| 29 | /* | ||
| 30 | srand(time(NULL)); | ||
| 31 | sum1 = 0; | ||
| 32 | sum2 = 0; | ||
| 33 | sum3 = 0; | ||
| 34 | for (i = 0; i < nrand; i++) { | ||
| 35 | cube = random_cube(); | ||
| 36 | sum1 += drud_HTM.check(cube, 20); | ||
| 37 | sum2 += optimal_HTM.check(cube, 20); | ||
| 38 | sum3 += cornershtreofb_HTM.check(cube, 20); | ||
| 39 | } | ||
| 40 | printf("Average drud pruning: %lf\n", ((double)sum1) / ((double) nrand)); | ||
| 41 | printf("Average corners htr pruning: %lf\n", ((double)sum2) / ((double) nrand)); | ||
| 42 | printf("Average corners htr + eofb pruning: %lf\n", ((double)sum3) / ((double) nrand)); | ||
| 43 | */ | ||
| 44 | |||
| 45 | /* | ||
| 46 | for (m = U; m <= B3; m++) { | ||
| 47 | printf("Class eofbepos after %d: ", m); | ||
| 48 | printf("%lu\n", coord_khuge.index(apply_move(m,(Cube){0}))); | ||
| 49 | } | ||
| 50 | */ | ||
| 51 | |||
| 52 | printf("Welcome to nissy 2.0! Insert a scramble:\n"); | ||
| 53 | |||
| 54 | if (fgets(line, 1000, stdin) != NULL) { | ||
| 55 | algo = new_alg(line); | ||
| 56 | cube = apply_alg(algo, (Cube){0}); | ||
| 57 | |||
| 58 | print_alg(inverse_alg(algo), false); | ||
| 59 | /* | ||
| 60 | printf("After rb_mirror:\n"); | ||
| 61 | cube = apply_trans(rb_mirror, cube); | ||
| 62 | print_cube(cube); | ||
| 63 | printf("Going back:\n"); | ||
| 64 | cube = apply_trans(inverse_trans(rb_mirror), cube); | ||
| 65 | */ | ||
| 66 | |||
| 67 | print_cube(cube); | ||
| 68 | |||
| 69 | for (i = 0; i < ns; i++) { | ||
| 70 | sols = solve(cube, *stps[i], &opts); | ||
| 71 | printf("%s: %d solutions found:\n", sss[i], sols->len); | ||
| 72 | print_alglist(sols, true); | ||
| 73 | free_alglist(sols); | ||
| 74 | } | ||
| 75 | free_alg(algo); | ||
| 76 | } | ||
| 77 | |||
| 78 | return 0; | ||
| 79 | } | ||
| 80 | |||
diff --git a/old/2021-06-30-reached/steps.c b/old/2021-06-30-reached/steps.c new file mode 100644 index 0000000..bc833cb --- /dev/null +++ b/old/2021-06-30-reached/steps.c | |||
| @@ -0,0 +1,307 @@ | |||
| 1 | #include "steps.h" | ||
| 2 | |||
| 3 | /* Standard checkers (return lower bound) ************************************/ | ||
| 4 | |||
| 5 | static int estimate_eofb_HTM(CubeTarget ct); | ||
| 6 | static int estimate_coud_HTM(CubeTarget ct); | ||
| 7 | static int estimate_coud_URF(CubeTarget ct); | ||
| 8 | static int estimate_corners_HTM(CubeTarget ct); | ||
| 9 | static int estimate_cornershtr_HTM(CubeTarget ct); | ||
| 10 | static int estimate_corners_URF(CubeTarget ct); | ||
| 11 | static int estimate_cornershtr_URF(CubeTarget ct); | ||
| 12 | static int estimate_drud_HTM(CubeTarget ct); | ||
| 13 | static int estimate_optimal_HTM(CubeTarget ct); | ||
| 14 | |||
| 15 | /* Steps *********************************************************************/ | ||
| 16 | |||
| 17 | Step | ||
| 18 | eofb_HTM = { | ||
| 19 | .estimate = estimate_eofb_HTM, | ||
| 20 | .ready = check_centers, | ||
| 21 | .moveset = moveset_HTM | ||
| 22 | }; | ||
| 23 | |||
| 24 | Step | ||
| 25 | coud_HTM = { | ||
| 26 | .estimate = estimate_coud_HTM, | ||
| 27 | .ready = check_centers, | ||
| 28 | .moveset = moveset_HTM | ||
| 29 | }; | ||
| 30 | |||
| 31 | Step | ||
| 32 | coud_URF = { | ||
| 33 | .estimate = estimate_coud_URF, | ||
| 34 | .ready = check_nothing, | ||
| 35 | .moveset = moveset_URF | ||
| 36 | }; | ||
| 37 | |||
| 38 | Step | ||
| 39 | corners_HTM = { | ||
| 40 | .estimate = estimate_corners_HTM, | ||
| 41 | .ready = check_centers, | ||
| 42 | .moveset = moveset_HTM | ||
| 43 | }; | ||
| 44 | |||
| 45 | Step | ||
| 46 | cornershtr_HTM = { | ||
| 47 | .estimate = estimate_cornershtr_HTM, | ||
| 48 | .ready = check_centers, | ||
| 49 | .moveset = moveset_HTM | ||
| 50 | }; | ||
| 51 | |||
| 52 | Step | ||
| 53 | cornershtr_URF = { | ||
| 54 | .estimate = estimate_cornershtr_URF, | ||
| 55 | .ready = check_nothing, | ||
| 56 | .moveset = moveset_URF | ||
| 57 | }; | ||
| 58 | |||
| 59 | Step | ||
| 60 | corners_URF = { | ||
| 61 | .estimate = estimate_corners_URF, | ||
| 62 | .ready = check_nothing, | ||
| 63 | .moveset = moveset_URF | ||
| 64 | }; | ||
| 65 | |||
| 66 | Step | ||
| 67 | drud_HTM = { | ||
| 68 | .estimate = estimate_drud_HTM, | ||
| 69 | .ready = check_centers, | ||
| 70 | .moveset = moveset_HTM | ||
| 71 | }; | ||
| 72 | |||
| 73 | Step | ||
| 74 | optimal_HTM = { | ||
| 75 | .estimate = estimate_optimal_HTM, | ||
| 76 | .ready = check_centers, | ||
| 77 | .moveset = moveset_HTM | ||
| 78 | }; | ||
| 79 | |||
| 80 | |||
| 81 | /* Pruning tables ************************************************************/ | ||
| 82 | |||
| 83 | PruneData | ||
| 84 | pd_eofb_HTM = { | ||
| 85 | .filename = "ptable_eofb_HTM", | ||
| 86 | .coord = &coord_eofb, | ||
| 87 | .moveset = moveset_HTM | ||
| 88 | }; | ||
| 89 | |||
| 90 | PruneData | ||
| 91 | pd_coud_HTM = { | ||
| 92 | .filename = "ptable_coud_HTM", | ||
| 93 | .coord = &coord_coud, | ||
| 94 | .moveset = moveset_HTM | ||
| 95 | }; | ||
| 96 | |||
| 97 | PruneData | ||
| 98 | pd_cornershtr_HTM = { | ||
| 99 | .filename = "ptable_cornershtr_withcosets_HTM", | ||
| 100 | .coord = &coord_cornershtr, | ||
| 101 | .moveset = moveset_HTM | ||
| 102 | }; | ||
| 103 | |||
| 104 | PruneData | ||
| 105 | pd_corners_HTM = { | ||
| 106 | .filename = "ptable_corners_HTM", | ||
| 107 | .coord = &coord_corners, | ||
| 108 | .moveset = moveset_HTM | ||
| 109 | }; | ||
| 110 | |||
| 111 | PruneData | ||
| 112 | pd_drud_HTM = { | ||
| 113 | .filename = "ptable_drud_HTM", | ||
| 114 | .coord = &coord_drud, | ||
| 115 | .moveset = moveset_HTM | ||
| 116 | }; | ||
| 117 | |||
| 118 | PruneData | ||
| 119 | pd_drud_sym16_HTM = { | ||
| 120 | .filename = "pd_drud_sym16_HTM", | ||
| 121 | .coord = &coord_drud_sym16, | ||
| 122 | .moveset = moveset_HTM, | ||
| 123 | }; | ||
| 124 | |||
| 125 | PruneData | ||
| 126 | pd_khuge_HTM = { | ||
| 127 | .filename = "pd_khuge_HTM", | ||
| 128 | .coord = &coord_khuge, | ||
| 129 | .moveset = moveset_HTM | ||
| 130 | }; | ||
| 131 | |||
| 132 | |||
| 133 | /* Standard checkers (return lower bound) ************************************/ | ||
| 134 | |||
| 135 | static int | ||
| 136 | estimate_eofb_HTM(CubeTarget ct) | ||
| 137 | { | ||
| 138 | if (!pd_eofb_HTM.generated) | ||
| 139 | genptable(&pd_eofb_HTM); | ||
| 140 | |||
| 141 | return ptableval(&pd_eofb_HTM, ct.cube); | ||
| 142 | } | ||
| 143 | |||
| 144 | static int | ||
| 145 | estimate_coud_HTM(CubeTarget ct) | ||
| 146 | { | ||
| 147 | if (!pd_coud_HTM.generated) | ||
| 148 | genptable(&pd_coud_HTM); | ||
| 149 | |||
| 150 | return ptableval(&pd_coud_HTM, ct.cube); | ||
| 151 | } | ||
| 152 | |||
| 153 | static int | ||
| 154 | estimate_coud_URF(CubeTarget ct) | ||
| 155 | { | ||
| 156 | /* TODO: I can improve this by checking first the orientation of | ||
| 157 | * the corner in DBL and use that as a reference */ | ||
| 158 | |||
| 159 | CubeTarget ct2 = {.cube = apply_move(z, ct.cube), .target = ct.target}; | ||
| 160 | CubeTarget ct3 = {.cube = apply_move(x, ct.cube), .target = ct.target}; | ||
| 161 | |||
| 162 | int ud = estimate_coud_HTM(ct); | ||
| 163 | int rl = estimate_coud_HTM(ct2); | ||
| 164 | int fb = estimate_coud_HTM(ct3); | ||
| 165 | |||
| 166 | return MIN(ud, MIN(rl, fb)); | ||
| 167 | } | ||
| 168 | |||
| 169 | static int | ||
| 170 | estimate_corners_HTM(CubeTarget ct) | ||
| 171 | { | ||
| 172 | if (!pd_corners_HTM.generated) | ||
| 173 | genptable(&pd_corners_HTM); | ||
| 174 | |||
| 175 | return ptableval(&pd_corners_HTM, ct.cube); | ||
| 176 | } | ||
| 177 | |||
| 178 | static int | ||
| 179 | estimate_cornershtr_HTM(CubeTarget ct) | ||
| 180 | { | ||
| 181 | if (!pd_cornershtr_HTM.generated) | ||
| 182 | genptable(&pd_cornershtr_HTM); | ||
| 183 | |||
| 184 | return ptableval(&pd_cornershtr_HTM, ct.cube); | ||
| 185 | } | ||
| 186 | |||
| 187 | static int | ||
| 188 | estimate_cornershtr_URF(CubeTarget ct) | ||
| 189 | { | ||
| 190 | /* TODO: I can improve this by checking first the corner in DBL | ||
| 191 | * and use that as a reference */ | ||
| 192 | |||
| 193 | int c, ret = 15; | ||
| 194 | Trans i; | ||
| 195 | |||
| 196 | for (i = 0; i < NROTATIONS; i++) { | ||
| 197 | ct.cube = apply_alg(rotation_alg(i), ct.cube); | ||
| 198 | c = estimate_cornershtr_HTM(ct); | ||
| 199 | ret = MIN(ret, c); | ||
| 200 | } | ||
| 201 | |||
| 202 | return ret; | ||
| 203 | } | ||
| 204 | |||
| 205 | static int | ||
| 206 | estimate_corners_URF(CubeTarget ct) | ||
| 207 | { | ||
| 208 | /* TODO: I can improve this by checking first the corner in DBL | ||
| 209 | * and use that as a reference */ | ||
| 210 | |||
| 211 | int c, ret = 15; | ||
| 212 | Trans i; | ||
| 213 | |||
| 214 | for (i = 0; i < NROTATIONS; i++) { | ||
| 215 | ct.cube = apply_alg(rotation_alg(i), ct.cube); | ||
| 216 | c = estimate_corners_HTM(ct); | ||
| 217 | ret = MIN(ret, c); | ||
| 218 | } | ||
| 219 | |||
| 220 | return ret; | ||
| 221 | } | ||
| 222 | |||
| 223 | static int | ||
| 224 | estimate_drud_HTM(CubeTarget ct) | ||
| 225 | { | ||
| 226 | /* | ||
| 227 | if (!pd_drud_HTM.generated) | ||
| 228 | genptable(&pd_drud_HTM); | ||
| 229 | |||
| 230 | return ptableval(&pd_drud_HTM, ct.cube); | ||
| 231 | */ | ||
| 232 | |||
| 233 | if (!pd_drud_sym16_HTM.generated) | ||
| 234 | genptable(&pd_drud_sym16_HTM); | ||
| 235 | |||
| 236 | return ptableval(&pd_drud_sym16_HTM, ct.cube); | ||
| 237 | } | ||
| 238 | |||
| 239 | /* TODO: if lucky, remove this */ | ||
| 240 | /* | ||
| 241 | static int | ||
| 242 | estimate_optimal_HTM(CubeTarget ct) | ||
| 243 | { | ||
| 244 | static Trans t1 = { .rot = rf, .mirror = false }; | ||
| 245 | static Trans t2 = { .rot = bd, .mirror = false }; | ||
| 246 | int dr1, dr2, dr3, cor, ret; | ||
| 247 | Cube cube = ct.cube; | ||
| 248 | |||
| 249 | dr1 = estimate_drud_HTM(ct); | ||
| 250 | cor = estimate_corners_HTM(ct); | ||
| 251 | ret = MAX(dr1, cor); | ||
| 252 | |||
| 253 | if (ret > ct.target) | ||
| 254 | return ret; | ||
| 255 | |||
| 256 | ct.cube = apply_trans(t1, cube); | ||
| 257 | dr2 = estimate_drud_HTM(ct); | ||
| 258 | ret = MAX(ret, dr2); | ||
| 259 | |||
| 260 | if (ret > ct.target) | ||
| 261 | return ret; | ||
| 262 | |||
| 263 | ct.cube = apply_trans(t2, cube); | ||
| 264 | dr3 = estimate_drud_HTM(ct); | ||
| 265 | |||
| 266 | if (dr1 == dr2 && dr2 == dr3 && dr1 != 0) | ||
| 267 | dr3++; | ||
| 268 | |||
| 269 | ret = MAX(ret, dr3); | ||
| 270 | |||
| 271 | if (ret == 0) | ||
| 272 | return check_ep(cube) ? 0 : 6; | ||
| 273 | |||
| 274 | return ret; | ||
| 275 | } | ||
| 276 | */ | ||
| 277 | |||
| 278 | static int | ||
| 279 | estimate_optimal_HTM(CubeTarget ct) | ||
| 280 | { | ||
| 281 | static Trans t2 = rf, t3 = bd; | ||
| 282 | |||
| 283 | int dr1, dr2, dr3, cor, ret; | ||
| 284 | Cube cube = ct.cube; | ||
| 285 | |||
| 286 | if (!pd_khuge_HTM.generated) | ||
| 287 | genptable(&pd_khuge_HTM); | ||
| 288 | |||
| 289 | dr1 = ptableval(&pd_khuge_HTM, cube); | ||
| 290 | cor = estimate_corners_HTM(ct); | ||
| 291 | ret = MAX(dr1, cor); | ||
| 292 | |||
| 293 | if (ret > ct.target) | ||
| 294 | return ret; | ||
| 295 | |||
| 296 | cube = apply_trans(t2, ct.cube); | ||
| 297 | dr2 = ptableval(&pd_khuge_HTM, cube); | ||
| 298 | ret = MAX(ret, dr2); | ||
| 299 | |||
| 300 | if (ret > ct.target) | ||
| 301 | return ret; | ||
| 302 | |||
| 303 | cube = apply_trans(t3, ct.cube); | ||
| 304 | dr3 = ptableval(&pd_khuge_HTM, cube); | ||
| 305 | |||
| 306 | return MAX(ret, dr3); | ||
| 307 | } | ||
diff --git a/old/2021-06-30-reached/steps.h b/old/2021-06-30-reached/steps.h new file mode 100644 index 0000000..81ae11c --- /dev/null +++ b/old/2021-06-30-reached/steps.h | |||
| @@ -0,0 +1,24 @@ | |||
| 1 | #ifndef STEPS_H | ||
| 2 | #define STEPS_H | ||
| 3 | |||
| 4 | #include "cube.h" | ||
| 5 | |||
| 6 | extern Step eofb_HTM; | ||
| 7 | extern Step coud_HTM; | ||
| 8 | extern Step coud_URF; | ||
| 9 | extern Step corners_HTM; | ||
| 10 | extern Step cornershtr_HTM; | ||
| 11 | extern Step corners_URF; | ||
| 12 | extern Step cornershtr_URF; | ||
| 13 | extern Step drud_HTM; | ||
| 14 | extern Step optimal_HTM; | ||
| 15 | |||
| 16 | extern PruneData pd_eofb_HTM; | ||
| 17 | extern PruneData pd_coud_HTM; | ||
| 18 | extern PruneData pd_corners_HTM; | ||
| 19 | extern PruneData pd_cornershtr_HTM; | ||
| 20 | extern PruneData pd_cornershtreofb_HTM; | ||
| 21 | extern PruneData pd_drud_HTM; | ||
| 22 | extern PruneData pd_khuge_HTM; | ||
| 23 | |||
| 24 | #endif | ||
diff --git a/old/2021-07-02-genptable-dfs/cube.c b/old/2021-07-02-genptable-dfs/cube.c new file mode 100644 index 0000000..a7d137c --- /dev/null +++ b/old/2021-07-02-genptable-dfs/cube.c | |||
| @@ -0,0 +1,3394 @@ | |||
| 1 | #include "cube.h" | ||
| 2 | |||
| 3 | /* Local functions **********************************************************/ | ||
| 4 | |||
| 5 | static Cube admissible_ep(Cube cube, PieceFilter f); | ||
| 6 | static Cube admissible_eos_from_eofbepos(Cube cube); | ||
| 7 | static bool allowed_next(Move move, DfsData *dd); | ||
| 8 | static void append_alg(AlgList *l, Alg *alg); | ||
| 9 | static void append_move(Alg *alg, Move m, bool inverse); | ||
| 10 | static Cube apply_alg_generic(Alg *alg, Cube c, PieceFilter f, bool a); | ||
| 11 | static void apply_permutation(int *perm, int *set, int n); | ||
| 12 | static Cube apply_move_cubearray(Move m, Cube cube, PieceFilter f); | ||
| 13 | static int array_ep_to_epos(int *ep, int *eps_solved); | ||
| 14 | static Cube arrays_to_cube(CubeArray *arr, PieceFilter f); | ||
| 15 | static int binomial(int n, int k); | ||
| 16 | static Cube compose_filtered(Cube c2, Cube c1, PieceFilter f); | ||
| 17 | static void cube_to_arrays(Cube cube, CubeArray *arr, PieceFilter f); | ||
| 18 | static void dfs(Cube c, Step s, SolveOptions *opts, DfsData *dd); | ||
| 19 | static void dfs_branch(Cube c, Step s, SolveOptions *opts, DfsData *dd); | ||
| 20 | static bool dfs_check_solved(SolveOptions *opts, DfsData *dd); | ||
| 21 | static void dfs_niss(Cube c, Step s, SolveOptions *opts, DfsData *dd); | ||
| 22 | static bool dfs_stop(Cube c, Step s, SolveOptions *opts, DfsData *dd); | ||
| 23 | static int digit_array_to_int(int *a, int n, int b); | ||
| 24 | static int edge_slice(Edge e); /* E=0, S=1, M=2 */ | ||
| 25 | static int epos_dependent_pos(int pos1, int pos2); | ||
| 26 | static int epos_from_arrays(int *epos, int *ep); | ||
| 27 | static void epos_to_partial_ep(int epos, int *ep, int *ss); | ||
| 28 | static int factorial(int n); | ||
| 29 | static void free_alglistnode(AlgListNode *aln); | ||
| 30 | static void free_cubearray(CubeArray *arr, PieceFilter f); | ||
| 31 | static void genptable_dfs(Cube c, PruneData *pd, DfsData *dd); | ||
| 32 | static void genptable_dfs_branch(Cube c, PruneData *pd, DfsData *dd); | ||
| 33 | static void gensym(SymData *sd); | ||
| 34 | static void index_to_perm(int p, int n, int *r); | ||
| 35 | static void index_to_subset(int s, int n, int k, int *r); | ||
| 36 | static void init_auxtables(); | ||
| 37 | static void init_cphtr_cosets(); | ||
| 38 | static void init_cphtr_left_cosets_bfs(int i, int c); | ||
| 39 | static void init_cphtr_right_cosets_color(int i, int c); | ||
| 40 | static void init_environment(); | ||
| 41 | static void init_moves(); | ||
| 42 | static void init_moves_aux(); | ||
| 43 | static void init_strings(); | ||
| 44 | static void init_symdata(); | ||
| 45 | static void init_trans(); | ||
| 46 | static void init_trans_aux(); | ||
| 47 | static void int_to_digit_array(int a, int b, int n, int *r); | ||
| 48 | static void int_to_sum_zero_array(int x, int b, int n, int *a); | ||
| 49 | static int invert_digits(int a, int b, int n); | ||
| 50 | static bool is_perm(int *a, int n); | ||
| 51 | static bool is_subset(int *a, int n, int k); | ||
| 52 | static Cube move_via_arrays(CubeArray *arr, Cube c, PieceFilter pf); | ||
| 53 | static void movelist_to_position(Move *movelist, int *position); | ||
| 54 | static void moveset_to_list(Moveset ms, Estimator f, Move *r); | ||
| 55 | static AlgList * new_alglist(); | ||
| 56 | static CubeArray * new_cubearray(Cube cube, PieceFilter f); | ||
| 57 | static int perm_sign(int *a, int n); | ||
| 58 | static int perm_to_index(int *a, int n); | ||
| 59 | static int powint(int a, int b); | ||
| 60 | static void ptable_update(PruneData *pd, Cube cube, int m); | ||
| 61 | static void realloc_alg(Alg *alg, int n); | ||
| 62 | static bool read_mtables_file(); | ||
| 63 | static bool read_ptable_file(PruneData *pd); | ||
| 64 | static bool read_symdata_file(SymData *sd); | ||
| 65 | static bool read_ttables_file(); | ||
| 66 | static Cube rotate_via_compose(Trans r, Cube c, PieceFilter f); | ||
| 67 | static int subset_to_index(int *a, int n, int k); | ||
| 68 | static void sum_arrays_mod(int *src, int *dst, int n, int m); | ||
| 69 | static void swap(int *a, int *b); | ||
| 70 | static bool write_mtables_file(); | ||
| 71 | static bool write_ptable_file(PruneData *pd); | ||
| 72 | static bool write_symdata_file(SymData *sd); | ||
| 73 | static bool write_ttables_file(); | ||
| 74 | |||
| 75 | |||
| 76 | /* All sorts of useful costants and tables **********************************/ | ||
| 77 | |||
| 78 | static char * tabledir; | ||
| 79 | |||
| 80 | static PieceFilter pf_all; | ||
| 81 | static PieceFilter pf_4val; | ||
| 82 | static PieceFilter pf_epcp; | ||
| 83 | static PieceFilter pf_cpos; | ||
| 84 | static PieceFilter pf_cp; | ||
| 85 | static PieceFilter pf_ep; | ||
| 86 | static PieceFilter pf_e; | ||
| 87 | static PieceFilter pf_s; | ||
| 88 | static PieceFilter pf_m; | ||
| 89 | static PieceFilter pf_eo; | ||
| 90 | static PieceFilter pf_co; | ||
| 91 | |||
| 92 | static int epe_solved[4]; | ||
| 93 | static int eps_solved[4]; | ||
| 94 | static int epm_solved[4]; | ||
| 95 | |||
| 96 | static char move_string[NMOVES][7]; | ||
| 97 | static char edge_string[12][7]; | ||
| 98 | static char corner_string[8][7]; | ||
| 99 | static char center_string[6][7]; | ||
| 100 | |||
| 101 | static Cube admissible_ee_aux[POW2TO11*BINOM12ON4]; | ||
| 102 | static bool commute[NMOVES][NMOVES]; | ||
| 103 | static bool possible_next[NMOVES][NMOVES][NMOVES]; | ||
| 104 | static Move inverse_move_aux[NMOVES]; | ||
| 105 | static Trans inverse_trans_aux[NTRANS]; | ||
| 106 | static int epos_dependent_aux[BINOM12ON4][BINOM12ON4]; | ||
| 107 | static int cphtr_left_cosets[FACTORIAL8]; | ||
| 108 | static int cphtr_right_cosets[FACTORIAL8]; | ||
| 109 | static int cphtr_right_rep[BINOM8ON4*6]; | ||
| 110 | static Center what_center_at_aux[FACTORIAL6][6]; | ||
| 111 | static Corner what_corner_at_aux[FACTORIAL8][8]; | ||
| 112 | static int what_orientation_last_corner_aux[POW3TO7]; | ||
| 113 | static int what_orientation_last_edge_aux[POW2TO11]; | ||
| 114 | static Center where_is_center_aux[FACTORIAL6][6]; | ||
| 115 | static Corner where_is_corner_aux[FACTORIAL8][8]; | ||
| 116 | static Edge where_is_edge_aux[3][FACTORIAL12/FACTORIAL8][12]; | ||
| 117 | |||
| 118 | static int epose_ttable[NTRANS][FACTORIAL12/FACTORIAL8]; | ||
| 119 | static int eposs_ttable[NTRANS][FACTORIAL12/FACTORIAL8]; | ||
| 120 | static int eposm_ttable[NTRANS][FACTORIAL12/FACTORIAL8]; | ||
| 121 | static int eo_ttable[NTRANS][POW2TO11]; | ||
| 122 | static int cp_ttable[NTRANS][FACTORIAL8]; | ||
| 123 | static int co_ttable[NTRANS][POW3TO7]; | ||
| 124 | static int cpos_ttable[NTRANS][FACTORIAL6]; | ||
| 125 | static Move moves_ttable[NTRANS][NMOVES]; | ||
| 126 | |||
| 127 | static int epose_mtable[NMOVES][FACTORIAL12/FACTORIAL8]; | ||
| 128 | static int eposs_mtable[NMOVES][FACTORIAL12/FACTORIAL8]; | ||
| 129 | static int eposm_mtable[NMOVES][FACTORIAL12/FACTORIAL8]; | ||
| 130 | static int eofb_mtable[NMOVES][POW2TO11]; | ||
| 131 | static int eorl_mtable[NMOVES][POW2TO11]; | ||
| 132 | static int eoud_mtable[NMOVES][POW2TO11]; | ||
| 133 | static int cp_mtable[NMOVES][FACTORIAL8]; | ||
| 134 | static int coud_mtable[NMOVES][POW3TO7]; | ||
| 135 | static int cofb_mtable[NMOVES][POW3TO7]; | ||
| 136 | static int corl_mtable[NMOVES][POW3TO7]; | ||
| 137 | static int cpos_mtable[NMOVES][FACTORIAL6]; | ||
| 138 | |||
| 139 | static uint64_t me[12]; | ||
| 140 | |||
| 141 | static int edge_cycle[NMOVES][12]; | ||
| 142 | static int corner_cycle[NMOVES][8]; | ||
| 143 | static int center_cycle[NMOVES][6]; | ||
| 144 | static int eofb_flipped[NMOVES][12]; | ||
| 145 | static int eorl_flipped[NMOVES][12]; | ||
| 146 | static int eoud_flipped[NMOVES][12]; | ||
| 147 | static int coud_flipped[NMOVES][8]; | ||
| 148 | static int corl_flipped[NMOVES][8]; | ||
| 149 | static int cofb_flipped[NMOVES][8]; | ||
| 150 | static Alg * equiv_alg[NMOVES]; | ||
| 151 | |||
| 152 | static int epose_source[NTRANS]; /* 0=epose, 1=eposs, 2=eposm */ | ||
| 153 | static int eposs_source[NTRANS]; | ||
| 154 | static int eposm_source[NTRANS]; | ||
| 155 | static int eofb_source[NTRANS]; /* 0=eoud, 1=eorl, 2=eofb */ | ||
| 156 | static int eorl_source[NTRANS]; | ||
| 157 | static int eoud_source[NTRANS]; | ||
| 158 | static int coud_source[NTRANS]; /* 0=coud, 1=corl, 2=cofb */ | ||
| 159 | static int cofb_source[NTRANS]; | ||
| 160 | static int corl_source[NTRANS]; | ||
| 161 | static int ep_mirror[12]; | ||
| 162 | static int cp_mirror[8]; | ||
| 163 | static int cpos_mirror[6]; | ||
| 164 | static Alg * rotation_algs[NROTATIONS]; | ||
| 165 | |||
| 166 | |||
| 167 | /* Symmetry data for some coordinates ****************************************/ | ||
| 168 | |||
| 169 | static Trans | ||
| 170 | trans_group_udfix[16] = { | ||
| 171 | uf, ur, ub, ul, | ||
| 172 | df, dr, db, dl, | ||
| 173 | uf_mirror, ur_mirror, ub_mirror, ul_mirror, | ||
| 174 | df_mirror, dr_mirror, db_mirror, dl_mirror, | ||
| 175 | }; | ||
| 176 | |||
| 177 | SymData | ||
| 178 | sd_coud_16 = { | ||
| 179 | .filename = "sd_coud_16", | ||
| 180 | .coord = &coord_coud, | ||
| 181 | .sym_coord = &coord_coud_sym16, | ||
| 182 | .ntrans = 16, | ||
| 183 | .trans = trans_group_udfix | ||
| 184 | }; | ||
| 185 | |||
| 186 | SymData | ||
| 187 | sd_eofbepos_16 = { | ||
| 188 | .filename = "sd_eofbepos_16", | ||
| 189 | .coord = &coord_eofbepos, | ||
| 190 | .sym_coord = &coord_eofbepos_sym16, | ||
| 191 | .ntrans = 16, | ||
| 192 | .trans = trans_group_udfix | ||
| 193 | }; | ||
| 194 | |||
| 195 | static int n_all_symdata = 2; | ||
| 196 | static SymData * all_sd[2] = { &sd_coud_16, &sd_eofbepos_16 }; | ||
| 197 | |||
| 198 | /* Coordinates and their implementation **************************************/ | ||
| 199 | |||
| 200 | static uint64_t index_eofb(Cube cube); | ||
| 201 | static uint64_t index_eofbepos(Cube cube); | ||
| 202 | static uint64_t index_coud(Cube cube); | ||
| 203 | static uint64_t index_corners(Cube cube); | ||
| 204 | static uint64_t index_cornershtr(Cube cube); | ||
| 205 | static uint64_t index_drud(Cube cube); | ||
| 206 | static uint64_t index_coud_sym16(Cube cube); | ||
| 207 | static uint64_t index_eofbepos_sym16(Cube cube); | ||
| 208 | static uint64_t index_drud_sym16(Cube cube); | ||
| 209 | static uint64_t index_khuge(Cube cube); | ||
| 210 | |||
| 211 | static Cube antindex_eofb(uint64_t ind); | ||
| 212 | static Cube antindex_eofbepos(uint64_t ind); | ||
| 213 | static Cube antindex_coud(uint64_t ind); | ||
| 214 | static Cube antindex_corners(uint64_t ind); | ||
| 215 | static Cube antindex_cornershtr(uint64_t ind); | ||
| 216 | static Cube antindex_drud(uint64_t ind); | ||
| 217 | static Cube antindex_coud_sym16(uint64_t ind); | ||
| 218 | static Cube antindex_eofbepos_sym16(uint64_t ind); | ||
| 219 | static Cube antindex_drud_sym16(uint64_t ind); | ||
| 220 | static Cube antindex_khuge(uint64_t ind); | ||
| 221 | |||
| 222 | Coordinate | ||
| 223 | coord_eofb = { | ||
| 224 | .index = index_eofb, | ||
| 225 | .cube = antindex_eofb, | ||
| 226 | .check = check_eofb, | ||
| 227 | .max = POW2TO11 | ||
| 228 | }; | ||
| 229 | |||
| 230 | Coordinate | ||
| 231 | coord_eofbepos = { | ||
| 232 | .index = index_eofbepos, | ||
| 233 | .cube = antindex_eofbepos, | ||
| 234 | .check = check_eofbepos, | ||
| 235 | .max = POW2TO11 * BINOM12ON4 | ||
| 236 | }; | ||
| 237 | |||
| 238 | Coordinate | ||
| 239 | coord_coud = { | ||
| 240 | .index = index_coud, | ||
| 241 | .cube = antindex_coud, | ||
| 242 | .check = check_coud, | ||
| 243 | .max = POW3TO7 | ||
| 244 | }; | ||
| 245 | |||
| 246 | Coordinate | ||
| 247 | coord_corners = { | ||
| 248 | .index = index_corners, | ||
| 249 | .cube = antindex_corners, | ||
| 250 | .check = check_corners, | ||
| 251 | .max = POW3TO7 * FACTORIAL8 | ||
| 252 | }; | ||
| 253 | |||
| 254 | Coordinate | ||
| 255 | coord_cornershtr = { | ||
| 256 | .index = index_cornershtr, | ||
| 257 | .cube = antindex_cornershtr, | ||
| 258 | .check = check_cornershtr, | ||
| 259 | .max = POW3TO7 * BINOM8ON4 * 6 | ||
| 260 | }; | ||
| 261 | |||
| 262 | Coordinate | ||
| 263 | coord_drud = { | ||
| 264 | .index = index_drud, | ||
| 265 | .cube = antindex_drud, | ||
| 266 | .check = check_drud, | ||
| 267 | .max = POW2TO11 * POW3TO7 * BINOM12ON4 | ||
| 268 | }; | ||
| 269 | |||
| 270 | Coordinate | ||
| 271 | coord_eofbepos_sym16 = { | ||
| 272 | .index = index_eofbepos_sym16, | ||
| 273 | .cube = antindex_eofbepos_sym16, | ||
| 274 | .check = check_eofbepos, | ||
| 275 | }; | ||
| 276 | |||
| 277 | Coordinate | ||
| 278 | coord_coud_sym16 = { | ||
| 279 | .index = index_coud_sym16, | ||
| 280 | .cube = antindex_coud_sym16, | ||
| 281 | .check = check_coud, | ||
| 282 | }; | ||
| 283 | |||
| 284 | Coordinate | ||
| 285 | coord_drud_sym16 = { | ||
| 286 | .index = index_drud_sym16, | ||
| 287 | .cube = antindex_drud_sym16, | ||
| 288 | .check = check_drud, | ||
| 289 | .max = POW3TO7 * 64430 | ||
| 290 | }; | ||
| 291 | |||
| 292 | Coordinate | ||
| 293 | coord_khuge = { | ||
| 294 | .index = index_khuge, | ||
| 295 | .cube = antindex_khuge, | ||
| 296 | .check = check_khuge, | ||
| 297 | .max = POW3TO7 * FACTORIAL4 * 64430 | ||
| 298 | }; | ||
| 299 | |||
| 300 | |||
| 301 | static uint64_t | ||
| 302 | index_eofb(Cube cube) | ||
| 303 | { | ||
| 304 | return cube.eofb; | ||
| 305 | } | ||
| 306 | |||
| 307 | static uint64_t | ||
| 308 | index_eofbepos(Cube cube) | ||
| 309 | { | ||
| 310 | return (cube.epose / FACTORIAL4) * POW2TO11 + cube.eofb; | ||
| 311 | } | ||
| 312 | |||
| 313 | static uint64_t | ||
| 314 | index_coud(Cube cube) | ||
| 315 | { | ||
| 316 | return cube.coud; | ||
| 317 | } | ||
| 318 | |||
| 319 | static uint64_t | ||
| 320 | index_corners(Cube cube) | ||
| 321 | { | ||
| 322 | return cube.coud * FACTORIAL8 + cube.cp; | ||
| 323 | } | ||
| 324 | |||
| 325 | static uint64_t | ||
| 326 | index_cornershtr(Cube cube) | ||
| 327 | { | ||
| 328 | return cube.coud * BINOM8ON4 * 6 + cphtr(cube); | ||
| 329 | } | ||
| 330 | |||
| 331 | static uint64_t | ||
| 332 | index_drud(Cube cube) | ||
| 333 | { | ||
| 334 | uint64_t a, b, c; | ||
| 335 | |||
| 336 | a = cube.eofb; | ||
| 337 | b = cube.coud; | ||
| 338 | c = cube.epose / FACTORIAL4; | ||
| 339 | |||
| 340 | b *= POW2TO11; | ||
| 341 | c *= POW2TO11 * POW3TO7; | ||
| 342 | |||
| 343 | return a + b + c; | ||
| 344 | } | ||
| 345 | |||
| 346 | static uint64_t | ||
| 347 | index_coud_sym16(Cube cube) | ||
| 348 | { | ||
| 349 | return sd_coud_16.class[index_coud(cube)]; | ||
| 350 | } | ||
| 351 | |||
| 352 | static uint64_t | ||
| 353 | index_drud_sym16(Cube cube) | ||
| 354 | { | ||
| 355 | Trans t; | ||
| 356 | Cube c; | ||
| 357 | |||
| 358 | t = sd_eofbepos_16.transtorep[index_eofbepos(cube)]; | ||
| 359 | c = apply_trans(t, cube); | ||
| 360 | |||
| 361 | return index_eofbepos_sym16(c) * POW3TO7 + c.coud; | ||
| 362 | } | ||
| 363 | |||
| 364 | static uint64_t | ||
| 365 | index_eofbepos_sym16(Cube cube) | ||
| 366 | { | ||
| 367 | return sd_eofbepos_16.class[index_eofbepos(cube)]; | ||
| 368 | } | ||
| 369 | |||
| 370 | static uint64_t | ||
| 371 | index_khuge(Cube cube) | ||
| 372 | { | ||
| 373 | Trans t; | ||
| 374 | Cube c; | ||
| 375 | uint64_t a; | ||
| 376 | |||
| 377 | t = sd_eofbepos_16.transtorep[index_eofbepos(cube)]; | ||
| 378 | c = apply_trans(t, cube); | ||
| 379 | a = (index_eofbepos_sym16(c) * 24) + (c.epose % 24); | ||
| 380 | |||
| 381 | return a * POW3TO7 + c.coud; | ||
| 382 | } | ||
| 383 | |||
| 384 | |||
| 385 | /* TODO: rename */ | ||
| 386 | static Cube | ||
| 387 | antindex_eofb(uint64_t ind) | ||
| 388 | { | ||
| 389 | return (Cube){ .eofb = ind, .eorl = ind, .eoud = ind }; | ||
| 390 | } | ||
| 391 | |||
| 392 | static Cube | ||
| 393 | antindex_eofbepos(uint64_t ind) | ||
| 394 | { | ||
| 395 | return admissible_ee_aux[ind]; | ||
| 396 | } | ||
| 397 | |||
| 398 | /* TODO: rename */ | ||
| 399 | static Cube | ||
| 400 | antindex_coud(uint64_t ind) | ||
| 401 | { | ||
| 402 | return (Cube){ .coud = ind, .corl = ind, .cofb = ind }; | ||
| 403 | } | ||
| 404 | |||
| 405 | /* TODO: admissible co for other orientations */ | ||
| 406 | static Cube | ||
| 407 | antindex_corners(uint64_t ind) | ||
| 408 | { | ||
| 409 | Cube c = {0}; | ||
| 410 | |||
| 411 | c.coud = ind / FACTORIAL8; | ||
| 412 | c.cp = ind % FACTORIAL8; | ||
| 413 | |||
| 414 | return c; | ||
| 415 | } | ||
| 416 | |||
| 417 | /* TODO: admissible co for other orientations */ | ||
| 418 | static Cube | ||
| 419 | antindex_cornershtr(uint64_t ind) | ||
| 420 | { | ||
| 421 | Cube c = anti_cphtr(ind % (BINOM8ON4 * 6)); | ||
| 422 | |||
| 423 | c.coud = ind / (BINOM8ON4 * 6); | ||
| 424 | |||
| 425 | return c; | ||
| 426 | } | ||
| 427 | |||
| 428 | /* TODO: admissible eos and cos */ | ||
| 429 | static Cube | ||
| 430 | antindex_drud(uint64_t ind) | ||
| 431 | { | ||
| 432 | Cube c = {0}; | ||
| 433 | |||
| 434 | c.eofb = ind % POW2TO11; | ||
| 435 | c.coud = (ind / POW2TO11) % POW3TO7; | ||
| 436 | c.epose = (ind % (POW2TO11 * POW3TO7)) * FACTORIAL4; | ||
| 437 | |||
| 438 | return c; | ||
| 439 | } | ||
| 440 | |||
| 441 | static Cube | ||
| 442 | antindex_coud_sym16(uint64_t ind) | ||
| 443 | { | ||
| 444 | return sd_coud_16.rep[ind]; | ||
| 445 | } | ||
| 446 | |||
| 447 | static Cube | ||
| 448 | antindex_eofbepos_sym16(uint64_t ind) | ||
| 449 | { | ||
| 450 | return sd_eofbepos_16.rep[ind]; | ||
| 451 | } | ||
| 452 | |||
| 453 | static Cube | ||
| 454 | antindex_drud_sym16(uint64_t ind) | ||
| 455 | { | ||
| 456 | Cube c; | ||
| 457 | |||
| 458 | c = sd_eofbepos_16.rep[ind/POW3TO7]; | ||
| 459 | c.coud = ind % POW3TO7; | ||
| 460 | c.cofb = c.coud; | ||
| 461 | c.corl = c.coud; | ||
| 462 | |||
| 463 | return c; | ||
| 464 | } | ||
| 465 | |||
| 466 | static Cube | ||
| 467 | antindex_khuge(uint64_t ind) | ||
| 468 | { | ||
| 469 | Cube c; | ||
| 470 | |||
| 471 | c = sd_eofbepos_16.rep[ind/(FACTORIAL4*POW3TO7)]; | ||
| 472 | c.epose = ((c.epose / 24) * 24) + ((ind/POW3TO7) % 24); | ||
| 473 | c.coud = ind % POW3TO7; | ||
| 474 | |||
| 475 | return c; | ||
| 476 | } | ||
| 477 | |||
| 478 | |||
| 479 | /* Checkers ******************************************************************/ | ||
| 480 | |||
| 481 | bool | ||
| 482 | check_centers(Cube cube) | ||
| 483 | { | ||
| 484 | return cube.cpos == 0; | ||
| 485 | } | ||
| 486 | |||
| 487 | bool | ||
| 488 | check_corners(Cube cube) | ||
| 489 | { | ||
| 490 | return cube.cp == 0 && cube.coud == 0; | ||
| 491 | } | ||
| 492 | |||
| 493 | bool | ||
| 494 | check_cornershtr(Cube cube) | ||
| 495 | { | ||
| 496 | return cube.coud == 0 && cphtr(cube) == 0; /* TODO: use array cphtrcosets*/ | ||
| 497 | } | ||
| 498 | |||
| 499 | bool | ||
| 500 | check_coud(Cube cube) | ||
| 501 | { | ||
| 502 | return cube.coud == 0; | ||
| 503 | } | ||
| 504 | |||
| 505 | bool | ||
| 506 | check_drud(Cube cube) | ||
| 507 | { | ||
| 508 | return cube.eofb == 0 && cube.eorl == 0 && cube.coud == 0; | ||
| 509 | } | ||
| 510 | |||
| 511 | bool | ||
| 512 | check_eofb(Cube cube) | ||
| 513 | { | ||
| 514 | return cube.eofb == 0; | ||
| 515 | } | ||
| 516 | |||
| 517 | bool | ||
| 518 | check_eofbepos(Cube cube) | ||
| 519 | { | ||
| 520 | return cube.eofb == 0 && cube.epose / 24 == 0; | ||
| 521 | } | ||
| 522 | |||
| 523 | bool | ||
| 524 | check_epose(Cube cube) | ||
| 525 | { | ||
| 526 | return cube.epose == 0; | ||
| 527 | } | ||
| 528 | |||
| 529 | bool | ||
| 530 | check_ep(Cube cube) | ||
| 531 | { | ||
| 532 | return cube.epose == 0 && cube.eposs == 0 && cube.eposm == 0; | ||
| 533 | } | ||
| 534 | |||
| 535 | bool | ||
| 536 | check_khuge(Cube cube) | ||
| 537 | { | ||
| 538 | return check_drud(cube) && cube.epose % 24 == 0; | ||
| 539 | } | ||
| 540 | |||
| 541 | bool | ||
| 542 | check_nothing(Cube cube) | ||
| 543 | { | ||
| 544 | return is_admissible(cube); /*TODO: maybe change?*/ | ||
| 545 | } | ||
| 546 | |||
| 547 | /* Movesets ******************************************************************/ | ||
| 548 | |||
| 549 | bool | ||
| 550 | moveset_HTM(Move m) | ||
| 551 | { | ||
| 552 | return m >= U && m <= B3; | ||
| 553 | } | ||
| 554 | |||
| 555 | bool | ||
| 556 | moveset_URF(Move m) | ||
| 557 | { | ||
| 558 | Move b = base_move(m); | ||
| 559 | |||
| 560 | return b == U || b == R || b == F; | ||
| 561 | } | ||
| 562 | |||
| 563 | |||
| 564 | /* Local functions implementation ********************************************/ | ||
| 565 | |||
| 566 | /* TODO: this should be an anti index (maybe?) */ | ||
| 567 | static Cube | ||
| 568 | admissible_ep(Cube cube, PieceFilter f) | ||
| 569 | { | ||
| 570 | CubeArray *arr = new_cubearray(cube, f); | ||
| 571 | Cube ret; | ||
| 572 | bool used[12] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; | ||
| 573 | int i, j; | ||
| 574 | |||
| 575 | for (i = 0; i < 12; i++) | ||
| 576 | if (arr->ep[i] != -1) | ||
| 577 | used[arr->ep[i]] = true; | ||
| 578 | |||
| 579 | for (i = 0, j = 0; i < 12; i++) { | ||
| 580 | for ( ; j < 11 && used[j]; j++); | ||
| 581 | if (arr->ep[i] == -1) | ||
| 582 | arr->ep[i] = j++; | ||
| 583 | } | ||
| 584 | |||
| 585 | ret = arrays_to_cube(arr, pf_ep); | ||
| 586 | free_cubearray(arr, f); | ||
| 587 | |||
| 588 | return ret; | ||
| 589 | } | ||
| 590 | |||
| 591 | static Cube | ||
| 592 | admissible_eos_from_eofbepos(Cube cube) | ||
| 593 | { | ||
| 594 | Edge e; | ||
| 595 | Cube ret; | ||
| 596 | CubeArray *arr = new_cubearray(cube, pf_all); | ||
| 597 | |||
| 598 | memcpy(arr->eorl, arr->eofb, 12 * sizeof(int)); | ||
| 599 | memcpy(arr->eoud, arr->eofb, 12 * sizeof(int)); | ||
| 600 | |||
| 601 | for (e = 0; e < 12; e++) { | ||
| 602 | if ((edge_slice(e) != 0 && edge_slice(arr->ep[e]) == 0) || | ||
| 603 | (edge_slice(e) == 0 && edge_slice(arr->ep[e]) != 0)) | ||
| 604 | arr->eorl[e] = 1 - arr->eorl[e]; | ||
| 605 | if ((edge_slice(e) != 2 && edge_slice(arr->ep[e]) == 2) || | ||
| 606 | (edge_slice(e) == 2 && edge_slice(arr->ep[e]) != 2)) | ||
| 607 | arr->eoud[e] = 1 - arr->eoud[e]; | ||
| 608 | } | ||
| 609 | |||
| 610 | ret = arrays_to_cube(arr, pf_all); | ||
| 611 | free_cubearray(arr, pf_all); | ||
| 612 | |||
| 613 | return ret; | ||
| 614 | } | ||
| 615 | |||
| 616 | static bool | ||
| 617 | allowed_next(Move move, DfsData *dd) | ||
| 618 | { | ||
| 619 | if (!possible_next[dd->last2][dd->last1][move]) | ||
| 620 | return false; | ||
| 621 | |||
| 622 | if (commute[dd->last1][move]) | ||
| 623 | return dd->move_position[dd->last1] < dd->move_position[move]; | ||
| 624 | |||
| 625 | return true; | ||
| 626 | } | ||
| 627 | |||
| 628 | static void | ||
| 629 | append_alg(AlgList *l, Alg *alg) | ||
| 630 | { | ||
| 631 | AlgListNode *node = malloc(sizeof(AlgListNode)); | ||
| 632 | int i; | ||
| 633 | |||
| 634 | node->alg = new_alg(""); | ||
| 635 | for (i = 0; i < alg->len; i++) | ||
| 636 | append_move(node->alg, alg->move[i], alg->inv[i]); | ||
| 637 | node->next = NULL; | ||
| 638 | |||
| 639 | if (++l->len == 1) | ||
| 640 | l->first = node; | ||
| 641 | else | ||
| 642 | l->last->next = node; | ||
| 643 | l->last = node; | ||
| 644 | } | ||
| 645 | |||
| 646 | static void | ||
| 647 | append_move(Alg *alg, Move m, bool inverse) | ||
| 648 | { | ||
| 649 | if (alg->len == alg->allocated) | ||
| 650 | realloc_alg(alg, 2*alg->len); | ||
| 651 | |||
| 652 | alg->move[alg->len] = m; | ||
| 653 | alg->inv [alg->len] = inverse; | ||
| 654 | alg->len++; | ||
| 655 | } | ||
| 656 | |||
| 657 | static Cube | ||
| 658 | apply_alg_generic(Alg *alg, Cube c, PieceFilter f, bool a) | ||
| 659 | { | ||
| 660 | Cube ret = {0}; | ||
| 661 | int i; | ||
| 662 | |||
| 663 | for (i = 0; i < alg->len; i++) | ||
| 664 | if (alg->inv[i]) | ||
| 665 | ret = a ? apply_move(alg->move[i], ret) : | ||
| 666 | apply_move_cubearray(alg->move[i], ret, f); | ||
| 667 | |||
| 668 | ret = compose_filtered(c, inverse_cube(ret), f); | ||
| 669 | |||
| 670 | for (i = 0; i < alg->len; i++) | ||
| 671 | if (!alg->inv[i]) | ||
| 672 | ret = a ? apply_move(alg->move[i], ret) : | ||
| 673 | apply_move_cubearray(alg->move[i], ret, f); | ||
| 674 | |||
| 675 | return ret; | ||
| 676 | } | ||
| 677 | |||
| 678 | static void | ||
| 679 | apply_permutation(int *perm, int *set, int n) | ||
| 680 | { | ||
| 681 | int *aux = malloc(n * sizeof(int)); | ||
| 682 | int i; | ||
| 683 | |||
| 684 | if (!is_perm(perm, n)) | ||
| 685 | return; | ||
| 686 | |||
| 687 | for (i = 0; i < n; i++) | ||
| 688 | aux[i] = set[perm[i]]; | ||
| 689 | |||
| 690 | memcpy(set, aux, n * sizeof(int)); | ||
| 691 | free(aux); | ||
| 692 | } | ||
| 693 | |||
| 694 | static Cube | ||
| 695 | apply_move_cubearray(Move m, Cube cube, PieceFilter f) | ||
| 696 | { | ||
| 697 | CubeArray m_arr = { | ||
| 698 | edge_cycle[m], | ||
| 699 | eofb_flipped[m], | ||
| 700 | eorl_flipped[m], | ||
| 701 | eoud_flipped[m], | ||
| 702 | corner_cycle[m], | ||
| 703 | coud_flipped[m], | ||
| 704 | corl_flipped[m], | ||
| 705 | cofb_flipped[m], | ||
| 706 | center_cycle[m] | ||
| 707 | }; | ||
| 708 | |||
| 709 | return move_via_arrays(&m_arr, cube, f); | ||
| 710 | } | ||
| 711 | |||
| 712 | static int | ||
| 713 | array_ep_to_epos(int *ep, int *ss) | ||
| 714 | { | ||
| 715 | int epos[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; | ||
| 716 | int eps[4]; | ||
| 717 | int i, j, is; | ||
| 718 | |||
| 719 | for (i = 0, is = 0; i < 12; i++) { | ||
| 720 | for (j = 0; j < 4; j++) { | ||
| 721 | if (ep[i] == ss[j]) { | ||
| 722 | eps[is++] = j; | ||
| 723 | epos[i] = 1; | ||
| 724 | } | ||
| 725 | } | ||
| 726 | } | ||
| 727 | |||
| 728 | for (i = 0; i < 4; i++) | ||
| 729 | swap(&epos[ss[i]], &epos[i+8]); | ||
| 730 | |||
| 731 | return epos_from_arrays(epos, eps); | ||
| 732 | } | ||
| 733 | |||
| 734 | static Cube | ||
| 735 | arrays_to_cube(CubeArray *arr, PieceFilter f) | ||
| 736 | { | ||
| 737 | Cube ret = {0}; | ||
| 738 | |||
| 739 | if (f.epose) | ||
| 740 | ret.epose = array_ep_to_epos(arr->ep, epe_solved); | ||
| 741 | if (f.eposs) | ||
| 742 | ret.eposs = array_ep_to_epos(arr->ep, eps_solved); | ||
| 743 | if (f.eposm) | ||
| 744 | ret.eposm = array_ep_to_epos(arr->ep, epm_solved); | ||
| 745 | if (f.eofb) | ||
| 746 | ret.eofb = digit_array_to_int(arr->eofb, 11, 2); | ||
| 747 | if (f.eorl) | ||
| 748 | ret.eorl = digit_array_to_int(arr->eorl, 11, 2); | ||
| 749 | if (f.eoud) | ||
| 750 | ret.eoud = digit_array_to_int(arr->eoud, 11, 2); | ||
| 751 | if (f.cp) | ||
| 752 | ret.cp = perm_to_index(arr->cp, 8); | ||
| 753 | if (f.coud) | ||
| 754 | ret.coud = digit_array_to_int(arr->coud, 7, 3); | ||
| 755 | if (f.corl) | ||
| 756 | ret.corl = digit_array_to_int(arr->corl, 7, 3); | ||
| 757 | if (f.cofb) | ||
| 758 | ret.cofb = digit_array_to_int(arr->cofb, 7, 3); | ||
| 759 | if (f.cpos) | ||
| 760 | ret.cpos = perm_to_index(arr->cpos, 6); | ||
| 761 | |||
| 762 | return ret; | ||
| 763 | } | ||
| 764 | |||
| 765 | static int | ||
| 766 | binomial(int n, int k) | ||
| 767 | { | ||
| 768 | if (n < 0 || k < 0 || k > n) | ||
| 769 | return 0; | ||
| 770 | |||
| 771 | return factorial(n) / (factorial(k) * factorial(n-k)); | ||
| 772 | } | ||
| 773 | |||
| 774 | static Cube | ||
| 775 | compose_filtered(Cube c2, Cube c1, PieceFilter f) | ||
| 776 | { | ||
| 777 | CubeArray *arr = new_cubearray(c2, f); | ||
| 778 | Cube ret; | ||
| 779 | |||
| 780 | ret = move_via_arrays(arr, c1, f); | ||
| 781 | free_cubearray(arr, f); | ||
| 782 | |||
| 783 | return ret; | ||
| 784 | } | ||
| 785 | |||
| 786 | static void | ||
| 787 | cube_to_arrays(Cube cube, CubeArray *arr, PieceFilter f) | ||
| 788 | { | ||
| 789 | int i; | ||
| 790 | |||
| 791 | if (f.epose || f.eposs || f.eposm) | ||
| 792 | for (i = 0; i < 12; i++) | ||
| 793 | arr->ep[i] = -1; | ||
| 794 | |||
| 795 | if (f.epose) | ||
| 796 | epos_to_partial_ep(cube.epose, arr->ep, epe_solved); | ||
| 797 | if (f.eposs) | ||
| 798 | epos_to_partial_ep(cube.eposs, arr->ep, eps_solved); | ||
| 799 | if (f.eposm) | ||
| 800 | epos_to_partial_ep(cube.eposm, arr->ep, epm_solved); | ||
| 801 | if (f.eofb) | ||
| 802 | int_to_sum_zero_array(cube.eofb, 2, 12, arr->eofb); | ||
| 803 | if (f.eorl) | ||
| 804 | int_to_sum_zero_array(cube.eorl, 2, 12, arr->eorl); | ||
| 805 | if (f.eoud) | ||
| 806 | int_to_sum_zero_array(cube.eoud, 2, 12, arr->eoud); | ||
| 807 | if (f.cp) | ||
| 808 | index_to_perm(cube.cp, 8, arr->cp); | ||
| 809 | if (f.coud) | ||
| 810 | int_to_sum_zero_array(cube.coud, 3, 8, arr->coud); | ||
| 811 | if (f.corl) | ||
| 812 | int_to_sum_zero_array(cube.corl, 3, 8, arr->corl); | ||
| 813 | if (f.cofb) | ||
| 814 | int_to_sum_zero_array(cube.cofb, 3, 8, arr->cofb); | ||
| 815 | if (f.cpos) | ||
| 816 | index_to_perm(cube.cpos, 6, arr->cpos); | ||
| 817 | } | ||
| 818 | |||
| 819 | /* | ||
| 820 | static int | ||
| 821 | cphtr_cp(int cp) | ||
| 822 | { | ||
| 823 | int i, a[8]; | ||
| 824 | |||
| 825 | index_to_perm(cp, 8, a); | ||
| 826 | |||
| 827 | for (i = 0; i < 8; i++) | ||
| 828 | if (a[i] == UFR || a[i] == UBL || a[i] == DFL || a[i] == DBR) | ||
| 829 | a[i] = 0; | ||
| 830 | else | ||
| 831 | a[i] = 1; | ||
| 832 | |||
| 833 | swap(&a[1], &a[5]); | ||
| 834 | swap(&a[3], &a[7]); | ||
| 835 | |||
| 836 | return subset_to_index(a, 8, 4); | ||
| 837 | } | ||
| 838 | */ | ||
| 839 | |||
| 840 | static void | ||
| 841 | dfs(Cube c, Step s, SolveOptions *opts, DfsData *dd) | ||
| 842 | { | ||
| 843 | if (dfs_stop(c, s, opts, dd)) | ||
| 844 | return; | ||
| 845 | |||
| 846 | if (dfs_check_solved(opts, dd)) | ||
| 847 | return; | ||
| 848 | |||
| 849 | dfs_branch(c, s, opts, dd); | ||
| 850 | |||
| 851 | if (opts->can_niss && !dd->niss) | ||
| 852 | dfs_niss(c, s, opts, dd); | ||
| 853 | } | ||
| 854 | |||
| 855 | static void | ||
| 856 | dfs_branch(Cube c, Step s, SolveOptions *opts, DfsData *dd) | ||
| 857 | { | ||
| 858 | Move m, l1 = dd->last1, l2 = dd->last2, *moves = dd->sorted_moves; | ||
| 859 | |||
| 860 | int i, maxnsol = opts->max_solutions; | ||
| 861 | |||
| 862 | for (i = 0; moves[i] != NULLMOVE && dd->sols->len < maxnsol; i++) { | ||
| 863 | m = moves[i]; | ||
| 864 | if (allowed_next(m, dd)) { | ||
| 865 | dd->last2 = dd->last1; | ||
| 866 | dd->last1 = m; | ||
| 867 | append_move(dd->current_alg, m, dd->niss); | ||
| 868 | |||
| 869 | dfs(apply_move(m, c), s, opts, dd); | ||
| 870 | |||
| 871 | dd->current_alg->len--; | ||
| 872 | dd->last2 = l2; | ||
| 873 | dd->last1 = l1; | ||
| 874 | } | ||
| 875 | } | ||
| 876 | } | ||
| 877 | |||
| 878 | static bool | ||
| 879 | dfs_check_solved(SolveOptions *opts, DfsData *dd) | ||
| 880 | { | ||
| 881 | if (dd->lb != 0) | ||
| 882 | return false; | ||
| 883 | |||
| 884 | if (dd->current_alg->len == dd->d) { | ||
| 885 | append_alg(dd->sols, dd->current_alg); | ||
| 886 | |||
| 887 | if (opts->feedback) | ||
| 888 | print_alg(dd->current_alg, false); | ||
| 889 | } | ||
| 890 | |||
| 891 | return true; | ||
| 892 | } | ||
| 893 | |||
| 894 | static void | ||
| 895 | dfs_niss(Cube c, Step s, SolveOptions *opts, DfsData *dd) | ||
| 896 | { | ||
| 897 | Move l1 = dd->last1, l2 = dd->last2; | ||
| 898 | CubeTarget ct; | ||
| 899 | |||
| 900 | ct.cube = apply_move(inverse_move(l1), (Cube){0}); | ||
| 901 | ct.target = 1; | ||
| 902 | |||
| 903 | if (dd->current_alg->len == 0 || s.estimate(ct)) { | ||
| 904 | dd->niss = true; | ||
| 905 | dd->last1 = NULLMOVE; | ||
| 906 | dd->last2 = NULLMOVE; | ||
| 907 | |||
| 908 | dfs(inverse_cube(c), s, opts, dd); | ||
| 909 | |||
| 910 | dd->last1 = l1; | ||
| 911 | dd->last2 = l2; | ||
| 912 | dd->niss = false; | ||
| 913 | } | ||
| 914 | } | ||
| 915 | |||
| 916 | static bool | ||
| 917 | dfs_stop(Cube c, Step s, SolveOptions *opts, DfsData *dd) | ||
| 918 | { | ||
| 919 | CubeTarget ct = { | ||
| 920 | .cube = c, | ||
| 921 | .target = dd->d - dd->current_alg->len | ||
| 922 | }; | ||
| 923 | |||
| 924 | if (dd->sols->len >= opts->max_solutions) | ||
| 925 | return true; | ||
| 926 | |||
| 927 | dd->lb = s.estimate(ct); | ||
| 928 | if (opts->can_niss && !dd->niss) | ||
| 929 | dd->lb = MIN(1, dd->lb); | ||
| 930 | |||
| 931 | if (dd->current_alg->len + dd->lb > dd->d) | ||
| 932 | return true; | ||
| 933 | |||
| 934 | return false; | ||
| 935 | } | ||
| 936 | |||
| 937 | static int | ||
| 938 | digit_array_to_int(int *a, int n, int b) | ||
| 939 | { | ||
| 940 | int i, ret = 0, p = 1; | ||
| 941 | |||
| 942 | for (i = 0; i < n; i++, p *= b) | ||
| 943 | ret += a[i] * p; | ||
| 944 | |||
| 945 | return ret; | ||
| 946 | } | ||
| 947 | |||
| 948 | static int | ||
| 949 | edge_slice(Edge e) { | ||
| 950 | if (e < 0 || e > 11) | ||
| 951 | return -1; | ||
| 952 | |||
| 953 | if (e == FR || e == FL || e == BL || e == BR) | ||
| 954 | return 0; | ||
| 955 | if (e == UR || e == UL || e == DR || e == DL) | ||
| 956 | return 1; | ||
| 957 | |||
| 958 | return 2; | ||
| 959 | } | ||
| 960 | |||
| 961 | static int | ||
| 962 | epos_dependent_pos(int poss, int pose) | ||
| 963 | { | ||
| 964 | int ep[12] = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}; | ||
| 965 | int ep8[8] = {0, 0, 0, 0, 0, 0, 0, 0}; | ||
| 966 | int i, j; | ||
| 967 | |||
| 968 | epos_to_partial_ep(poss*FACTORIAL4, ep, eps_solved); | ||
| 969 | epos_to_partial_ep(pose*FACTORIAL4, ep, epe_solved); | ||
| 970 | |||
| 971 | for (i = 0, j = 0; i < 12; i++) | ||
| 972 | if (edge_slice(ep[i]) != 0) | ||
| 973 | ep8[j++] = (edge_slice(ep[i]) == 1) ? 1 : 0; | ||
| 974 | |||
| 975 | swap(&ep8[1], &ep8[4]); | ||
| 976 | swap(&ep8[3], &ep8[6]); | ||
| 977 | |||
| 978 | return subset_to_index(ep8, 8, 4); | ||
| 979 | } | ||
| 980 | |||
| 981 | static int | ||
| 982 | epos_from_arrays(int *epos, int *ep) | ||
| 983 | { | ||
| 984 | return FACTORIAL4 * subset_to_index(epos,12,4) + perm_to_index(ep,4); | ||
| 985 | } | ||
| 986 | |||
| 987 | static void | ||
| 988 | epos_to_partial_ep(int epos, int *ep, int *ss) | ||
| 989 | { | ||
| 990 | int i, is, eposs[12], eps[4]; | ||
| 991 | |||
| 992 | index_to_perm(epos % FACTORIAL4, 4, eps); | ||
| 993 | index_to_subset(epos / FACTORIAL4, 12, 4, eposs); | ||
| 994 | |||
| 995 | for (i = 0; i < 4; i++) | ||
| 996 | swap(&eposs[ss[i]], &eposs[i+8]); | ||
| 997 | |||
| 998 | for (i = 0, is = 0; i < 12; i++) | ||
| 999 | if (eposs[i]) | ||
| 1000 | ep[i] = ss[eps[is++]]; | ||
| 1001 | } | ||
| 1002 | |||
| 1003 | static int | ||
| 1004 | factorial(int n) | ||
| 1005 | { | ||
| 1006 | int i, ret = 1; | ||
| 1007 | |||
| 1008 | if (n < 0) | ||
| 1009 | return 0; | ||
| 1010 | |||
| 1011 | for (i = 1; i <= n; i++) | ||
| 1012 | ret *= i; | ||
| 1013 | |||
| 1014 | return ret; | ||
| 1015 | } | ||
| 1016 | |||
| 1017 | void | ||
| 1018 | free_alg(Alg *alg) | ||
| 1019 | { | ||
| 1020 | free(alg->move); | ||
| 1021 | free(alg->inv); | ||
| 1022 | free(alg); | ||
| 1023 | } | ||
| 1024 | |||
| 1025 | void | ||
| 1026 | free_alglist(AlgList *l) | ||
| 1027 | { | ||
| 1028 | AlgListNode *aux, *i = l->first; | ||
| 1029 | |||
| 1030 | while (i != NULL) { | ||
| 1031 | aux = i->next; | ||
| 1032 | free_alglistnode(i); | ||
| 1033 | i = aux; | ||
| 1034 | } | ||
| 1035 | free(l); | ||
| 1036 | } | ||
| 1037 | |||
| 1038 | void | ||
| 1039 | free_alglistnode(AlgListNode *aln) | ||
| 1040 | { | ||
| 1041 | free_alg(aln->alg); | ||
| 1042 | free(aln); | ||
| 1043 | } | ||
| 1044 | |||
| 1045 | static void | ||
| 1046 | free_cubearray(CubeArray *arr, PieceFilter f) | ||
| 1047 | { | ||
| 1048 | if (f.epose || f.eposs || f.eposm) | ||
| 1049 | free(arr->ep); | ||
| 1050 | if (f.eofb) | ||
| 1051 | free(arr->eofb); | ||
| 1052 | if (f.eorl) | ||
| 1053 | free(arr->eorl); | ||
| 1054 | if (f.eoud) | ||
| 1055 | free(arr->eoud); | ||
| 1056 | if (f.cp) | ||
| 1057 | free(arr->cp); | ||
| 1058 | if (f.coud) | ||
| 1059 | free(arr->coud); | ||
| 1060 | if (f.corl) | ||
| 1061 | free(arr->corl); | ||
| 1062 | if (f.cofb) | ||
| 1063 | free(arr->cofb); | ||
| 1064 | if (f.cpos) | ||
| 1065 | free(arr->cpos); | ||
| 1066 | |||
| 1067 | free(arr); | ||
| 1068 | } | ||
| 1069 | |||
| 1070 | static void | ||
| 1071 | genptable_dfs(Cube c, PruneData *pd, DfsData *dd) | ||
| 1072 | { | ||
| 1073 | int oldval = ptableval(pd, c); | ||
| 1074 | |||
| 1075 | if (oldval < dd->m || pd->n == pd->coord->max || | ||
| 1076 | (dd->m != 0 && pd->coord->check(c)) ) | ||
| 1077 | return; | ||
| 1078 | |||
| 1079 | if (dd->m == dd->d) { | ||
| 1080 | if (dd->m < oldval) | ||
| 1081 | ptable_update(pd, c, dd->m); | ||
| 1082 | return; | ||
| 1083 | } | ||
| 1084 | |||
| 1085 | genptable_dfs_branch(c, pd, dd); | ||
| 1086 | } | ||
| 1087 | |||
| 1088 | static void | ||
| 1089 | genptable_dfs_branch(Cube c, PruneData *pd, DfsData *dd) | ||
| 1090 | { | ||
| 1091 | Move i, move, l1 = dd->last1, l2 = dd->last2; | ||
| 1092 | |||
| 1093 | dd->m++; | ||
| 1094 | |||
| 1095 | for (i = 0; dd->sorted_moves[i] != NULLMOVE; i++) { | ||
| 1096 | move = dd->sorted_moves[i]; | ||
| 1097 | if (allowed_next(move, dd)) { | ||
| 1098 | dd->last2 = dd->last1; | ||
| 1099 | dd->last1 = move; | ||
| 1100 | |||
| 1101 | genptable_dfs(apply_move(move, c), pd, dd); | ||
| 1102 | |||
| 1103 | dd->last2 = l2; | ||
| 1104 | dd->last1 = l1; | ||
| 1105 | } | ||
| 1106 | } | ||
| 1107 | |||
| 1108 | dd->m--; | ||
| 1109 | } | ||
| 1110 | |||
| 1111 | static void | ||
| 1112 | gensym(SymData *sd) | ||
| 1113 | { | ||
| 1114 | uint64_t i, in, nreps = 0; | ||
| 1115 | int j; | ||
| 1116 | Cube c, d; | ||
| 1117 | |||
| 1118 | if (sd->generated) | ||
| 1119 | return; | ||
| 1120 | |||
| 1121 | sd->class = malloc(sd->coord->max * sizeof(uint64_t)); | ||
| 1122 | sd->rep = malloc(sd->coord->max * sizeof(Cube)); | ||
| 1123 | sd->transtorep = malloc(sd->coord->max * sizeof(Trans)); | ||
| 1124 | |||
| 1125 | if (read_symdata_file(sd)) { | ||
| 1126 | sd->generated = true; | ||
| 1127 | return; | ||
| 1128 | } | ||
| 1129 | |||
| 1130 | fprintf(stderr, "Cannot load %s, generating it\n", sd->filename); | ||
| 1131 | |||
| 1132 | for (i = 0; i < sd->coord->max; i++) | ||
| 1133 | sd->class[i] = sd->coord->max + 1; | ||
| 1134 | |||
| 1135 | for (i = 0; i < sd->coord->max; i++) { | ||
| 1136 | if (sd->class[i] == sd->coord->max + 1) { | ||
| 1137 | c = sd->coord->cube(i); | ||
| 1138 | sd->rep[nreps] = c; | ||
| 1139 | for (j = 0; j < sd->ntrans; j++) { | ||
| 1140 | d = apply_trans(sd->trans[j], c); | ||
| 1141 | in = sd->coord->index(d); | ||
| 1142 | |||
| 1143 | if (sd->class[in] == sd->coord->max + 1) { | ||
| 1144 | sd->class[in] = nreps; | ||
| 1145 | sd->transtorep[in] = | ||
| 1146 | inverse_trans(sd->trans[j]); | ||
| 1147 | } | ||
| 1148 | } | ||
| 1149 | nreps++; | ||
| 1150 | } | ||
| 1151 | } | ||
| 1152 | |||
| 1153 | sd->sym_coord->max = nreps; | ||
| 1154 | sd->rep = realloc(sd->rep, nreps * sizeof(Cube)); | ||
| 1155 | sd->generated = true; | ||
| 1156 | |||
| 1157 | fprintf(stderr, "Found %lu classes\n", nreps); | ||
| 1158 | |||
| 1159 | if (!write_symdata_file(sd)) | ||
| 1160 | fprintf(stderr, "Error writing SymData file\n"); | ||
| 1161 | |||
| 1162 | return; | ||
| 1163 | } | ||
| 1164 | |||
| 1165 | static void | ||
| 1166 | index_to_perm(int p, int n, int *r) | ||
| 1167 | { | ||
| 1168 | int *a = malloc(n * sizeof(int)); | ||
| 1169 | int i, j, c; | ||
| 1170 | |||
| 1171 | for (i = 0; i < n; i++) | ||
| 1172 | a[i] = 0; | ||
| 1173 | |||
| 1174 | if (p < 0 || p >= factorial(n)) | ||
| 1175 | for (i = 0; i < n; i++) | ||
| 1176 | r[i] = -1; | ||
| 1177 | |||
| 1178 | for (i = 0; i < n; i++) { | ||
| 1179 | c = 0; | ||
| 1180 | j = 0; | ||
| 1181 | while (c <= p / factorial(n-i-1)) | ||
| 1182 | c += a[j++] ? 0 : 1; | ||
| 1183 | r[i] = j-1; | ||
| 1184 | a[j-1] = 1; | ||
| 1185 | p %= factorial(n-i-1); | ||
| 1186 | } | ||
| 1187 | |||
| 1188 | free(a); | ||
| 1189 | } | ||
| 1190 | |||
| 1191 | static void | ||
| 1192 | index_to_subset(int s, int n, int k, int *r) | ||
| 1193 | { | ||
| 1194 | int i, j, v; | ||
| 1195 | |||
| 1196 | if (s < 0 || s >= binomial(n, k)) { | ||
| 1197 | for (i = 0; i < n; i++) | ||
| 1198 | r[i] = -1; | ||
| 1199 | return; | ||
| 1200 | } | ||
| 1201 | |||
| 1202 | for (i = 0; i < n; i++) { | ||
| 1203 | if (k == n-i) { | ||
| 1204 | for (j = i; j < n; j++) | ||
| 1205 | r[j] = 1; | ||
| 1206 | return; | ||
| 1207 | } | ||
| 1208 | |||
| 1209 | if (k == 0) { | ||
| 1210 | for (j = i; j < n; j++) | ||
| 1211 | r[j] = 0; | ||
| 1212 | return; | ||
| 1213 | } | ||
| 1214 | |||
| 1215 | v = binomial(n-i-1, k); | ||
| 1216 | if (s >= v) { | ||
| 1217 | r[i] = 1; | ||
| 1218 | k--; | ||
| 1219 | s -= v; | ||
| 1220 | } else { | ||
| 1221 | r[i] = 0; | ||
| 1222 | } | ||
| 1223 | } | ||
| 1224 | } | ||
| 1225 | |||
| 1226 | static void | ||
| 1227 | int_to_digit_array(int a, int b, int n, int *r) | ||
| 1228 | { | ||
| 1229 | int i; | ||
| 1230 | |||
| 1231 | if (b <= 1) | ||
| 1232 | for (i = 0; i < n; i++) | ||
| 1233 | r[i] = 0; | ||
| 1234 | else | ||
| 1235 | for (i = 0; i < n; i++, a /= b) | ||
| 1236 | r[i] = a % b; | ||
| 1237 | } | ||
| 1238 | |||
| 1239 | static void | ||
| 1240 | int_to_sum_zero_array(int x, int b, int n, int *a) | ||
| 1241 | { | ||
| 1242 | int i, s = 0; | ||
| 1243 | |||
| 1244 | if (b <= 1) { | ||
| 1245 | for (i = 0; i < n; i++) | ||
| 1246 | a[i] = 0; | ||
| 1247 | } else { | ||
| 1248 | int_to_digit_array(x, b, n-1, a); | ||
| 1249 | for (i = 0; i < n - 1; i++) | ||
| 1250 | s = (s + a[i]) % b; | ||
| 1251 | a[n-1] = (b - s) % b; | ||
| 1252 | } | ||
| 1253 | } | ||
| 1254 | |||
| 1255 | static int | ||
| 1256 | invert_digits(int a, int b, int n) | ||
| 1257 | { | ||
| 1258 | int i, ret, *r = malloc(n * sizeof(int)); | ||
| 1259 | |||
| 1260 | int_to_digit_array(a, b, n, r); | ||
| 1261 | for (i = 0; i < n; i++) | ||
| 1262 | r[i] = (b-r[i]) % b; | ||
| 1263 | |||
| 1264 | ret = digit_array_to_int(r, n, b); | ||
| 1265 | free(r); | ||
| 1266 | return ret; | ||
| 1267 | } | ||
| 1268 | |||
| 1269 | static bool | ||
| 1270 | is_perm(int *a, int n) | ||
| 1271 | { | ||
| 1272 | int *aux = malloc(n * sizeof(int)); | ||
| 1273 | int i; | ||
| 1274 | |||
| 1275 | for (i = 0; i < n; i++) | ||
| 1276 | if (a[i] < 0 || a[i] >= n) | ||
| 1277 | return false; | ||
| 1278 | else | ||
| 1279 | aux[a[i]] = 1; | ||
| 1280 | |||
| 1281 | for (i = 0; i < n; i++) | ||
| 1282 | if (!aux[i]) | ||
| 1283 | return false; | ||
| 1284 | |||
| 1285 | free(aux); | ||
| 1286 | |||
| 1287 | return true; | ||
| 1288 | } | ||
| 1289 | |||
| 1290 | static bool | ||
| 1291 | is_subset(int *a, int n, int k) | ||
| 1292 | { | ||
| 1293 | int i, sum = 0; | ||
| 1294 | |||
| 1295 | for (i = 0; i < n; i++) | ||
| 1296 | sum += a[i] ? 1 : 0; | ||
| 1297 | |||
| 1298 | return sum == k; | ||
| 1299 | } | ||
| 1300 | |||
| 1301 | static Cube | ||
| 1302 | move_via_arrays(CubeArray *arr, Cube c, PieceFilter f) | ||
| 1303 | { | ||
| 1304 | CubeArray *arrc = new_cubearray(c, f); | ||
| 1305 | Cube ret; | ||
| 1306 | |||
| 1307 | if (f.epose || f.eposs || f.eposm) | ||
| 1308 | apply_permutation(arr->ep, arrc->ep, 12); | ||
| 1309 | |||
| 1310 | if (f.eofb) { | ||
| 1311 | apply_permutation(arr->ep, arrc->eofb, 12); | ||
| 1312 | sum_arrays_mod(arr->eofb, arrc->eofb, 12, 2); | ||
| 1313 | } | ||
| 1314 | |||
| 1315 | if (f.eorl) { | ||
| 1316 | apply_permutation(arr->ep, arrc->eorl, 12); | ||
| 1317 | sum_arrays_mod(arr->eorl, arrc->eorl, 12, 2); | ||
| 1318 | } | ||
| 1319 | |||
| 1320 | if (f.eoud) { | ||
| 1321 | apply_permutation(arr->ep, arrc->eoud, 12); | ||
| 1322 | sum_arrays_mod(arr->eoud, arrc->eoud, 12, 2); | ||
| 1323 | } | ||
| 1324 | |||
| 1325 | if (f.cp) | ||
| 1326 | apply_permutation(arr->cp, arrc->cp, 8); | ||
| 1327 | |||
| 1328 | if (f.coud) { | ||
| 1329 | apply_permutation(arr->cp, arrc->coud, 8); | ||
| 1330 | sum_arrays_mod(arr->coud, arrc->coud, 8, 3); | ||
| 1331 | } | ||
| 1332 | |||
| 1333 | if (f.corl) { | ||
| 1334 | apply_permutation(arr->cp, arrc->corl, 8); | ||
| 1335 | sum_arrays_mod(arr->corl, arrc->corl, 8, 3); | ||
| 1336 | } | ||
| 1337 | |||
| 1338 | if (f.cofb) { | ||
| 1339 | apply_permutation(arr->cp, arrc->cofb, 8); | ||
| 1340 | sum_arrays_mod(arr->cofb, arrc->cofb, 8, 3); | ||
| 1341 | } | ||
| 1342 | |||
| 1343 | if (f.cpos) | ||
| 1344 | apply_permutation(arr->cpos, arrc->cpos, 6); | ||
| 1345 | |||
| 1346 | ret = arrays_to_cube(arrc, f); | ||
| 1347 | free_cubearray(arrc, f); | ||
| 1348 | |||
| 1349 | return ret; | ||
| 1350 | } | ||
| 1351 | |||
| 1352 | static void | ||
| 1353 | movelist_to_position(Move *movelist, int *position) | ||
| 1354 | { | ||
| 1355 | Move m; | ||
| 1356 | |||
| 1357 | for (m = 0; m < NMOVES && movelist[m] != NULLMOVE; m++) | ||
| 1358 | position[movelist[m]] = m; | ||
| 1359 | } | ||
| 1360 | |||
| 1361 | static void | ||
| 1362 | moveset_to_list(Moveset ms, Estimator f, Move *r) | ||
| 1363 | { | ||
| 1364 | CubeTarget ct = { .target = 1 }; | ||
| 1365 | int b[NMOVES]; | ||
| 1366 | int na = 0, nb = 0; | ||
| 1367 | Move i; | ||
| 1368 | |||
| 1369 | if (ms == NULL) { | ||
| 1370 | fprintf(stderr, "Error: no moveset given\n"); | ||
| 1371 | return; | ||
| 1372 | } | ||
| 1373 | |||
| 1374 | for (i = U; i < NMOVES; i++) { | ||
| 1375 | if (ms(i)) { | ||
| 1376 | ct.cube = apply_move(i, (Cube){0}); | ||
| 1377 | if (f != NULL && f(ct)) | ||
| 1378 | r[na++] = i; | ||
| 1379 | else | ||
| 1380 | b[nb++] = i; | ||
| 1381 | } | ||
| 1382 | } | ||
| 1383 | |||
| 1384 | memcpy(r + na, b, nb * sizeof(Move)); | ||
| 1385 | r[na+nb] = NULLMOVE; | ||
| 1386 | } | ||
| 1387 | |||
| 1388 | static AlgList * | ||
| 1389 | new_alglist() | ||
| 1390 | { | ||
| 1391 | AlgList *ret = malloc(sizeof(AlgList)); | ||
| 1392 | |||
| 1393 | ret->len = 0; | ||
| 1394 | ret->first = NULL; | ||
| 1395 | ret->last = NULL; | ||
| 1396 | |||
| 1397 | return ret; | ||
| 1398 | } | ||
| 1399 | |||
| 1400 | static CubeArray * | ||
| 1401 | new_cubearray(Cube cube, PieceFilter f) | ||
| 1402 | { | ||
| 1403 | CubeArray *arr = malloc(sizeof(CubeArray)); | ||
| 1404 | |||
| 1405 | if (f.epose || f.eposs || f.eposm) | ||
| 1406 | arr->ep = malloc(12 * sizeof(int)); | ||
| 1407 | if (f.eofb) | ||
| 1408 | arr->eofb = malloc(12 * sizeof(int)); | ||
| 1409 | if (f.eorl) | ||
| 1410 | arr->eorl = malloc(12 * sizeof(int)); | ||
| 1411 | if (f.eoud) | ||
| 1412 | arr->eoud = malloc(12 * sizeof(int)); | ||
| 1413 | if (f.cp) | ||
| 1414 | arr->cp = malloc(8 * sizeof(int)); | ||
| 1415 | if (f.coud) | ||
| 1416 | arr->coud = malloc(8 * sizeof(int)); | ||
| 1417 | if (f.corl) | ||
| 1418 | arr->corl = malloc(8 * sizeof(int)); | ||
| 1419 | if (f.cofb) | ||
| 1420 | arr->cofb = malloc(8 * sizeof(int)); | ||
| 1421 | if (f.cpos) | ||
| 1422 | arr->cpos = malloc(6 * sizeof(int)); | ||
| 1423 | |||
| 1424 | cube_to_arrays(cube, arr, f); | ||
| 1425 | |||
| 1426 | return arr; | ||
| 1427 | } | ||
| 1428 | |||
| 1429 | static int | ||
| 1430 | perm_sign(int *a, int n) | ||
| 1431 | { | ||
| 1432 | int i, j, ret = 0; | ||
| 1433 | |||
| 1434 | if (!is_perm(a,n)) | ||
| 1435 | return -1; | ||
| 1436 | |||
| 1437 | for (i = 0; i < n; i++) | ||
| 1438 | for (j = i+1; j < n; j++) | ||
| 1439 | ret += (a[i] > a[j]) ? 1 : 0; | ||
| 1440 | |||
| 1441 | return ret % 2; | ||
| 1442 | } | ||
| 1443 | |||
| 1444 | static int | ||
| 1445 | perm_to_index(int *a, int n) | ||
| 1446 | { | ||
| 1447 | int i, j, c, ret = 0; | ||
| 1448 | |||
| 1449 | if (!is_perm(a, n)) | ||
| 1450 | return -1; | ||
| 1451 | |||
| 1452 | for (i = 0; i < n; i++) { | ||
| 1453 | c = 0; | ||
| 1454 | for (j = i+1; j < n; j++) | ||
| 1455 | c += (a[i] > a[j]) ? 1 : 0; | ||
| 1456 | ret += factorial(n-i-1) * c; | ||
| 1457 | } | ||
| 1458 | |||
| 1459 | return ret; | ||
| 1460 | } | ||
| 1461 | |||
| 1462 | static int | ||
| 1463 | powint(int a, int b) | ||
| 1464 | { | ||
| 1465 | if (b < 0) | ||
| 1466 | return 0; | ||
| 1467 | if (b == 0) | ||
| 1468 | return 1; | ||
| 1469 | |||
| 1470 | if (b % 2) | ||
| 1471 | return a * powint(a, b-1); | ||
| 1472 | else | ||
| 1473 | return powint(a*a, b/2); | ||
| 1474 | } | ||
| 1475 | |||
| 1476 | static void | ||
| 1477 | ptable_update(PruneData *pd, Cube cube, int n) | ||
| 1478 | { | ||
| 1479 | uint64_t ind = pd->coord->index(cube); | ||
| 1480 | uint8_t oldval2 = pd->ptable[ind/2]; | ||
| 1481 | int other = (ind % 2) ? oldval2 % 16 : oldval2 / 16; | ||
| 1482 | |||
| 1483 | pd->ptable[ind/2] = (ind % 2) ? 16*n + other : 16*other + n; | ||
| 1484 | pd->n++; | ||
| 1485 | } | ||
| 1486 | |||
| 1487 | static void | ||
| 1488 | realloc_alg(Alg *alg, int n) | ||
| 1489 | { | ||
| 1490 | if (alg == NULL) { | ||
| 1491 | fprintf(stderr, "Error: trying to reallocate NULL alg.\n"); | ||
| 1492 | return; | ||
| 1493 | } | ||
| 1494 | |||
| 1495 | if (n < alg->len) { | ||
| 1496 | fprintf(stderr, "Error: alg too long for reallocation "); | ||
| 1497 | fprintf(stderr, "(%d vs %d)\n", alg->len, n); | ||
| 1498 | return; | ||
| 1499 | } | ||
| 1500 | |||
| 1501 | if (n > 1000000) { | ||
| 1502 | fprintf(stderr, "Warning: very long alg,"); | ||
| 1503 | fprintf(stderr, "something might go wrong.\n"); | ||
| 1504 | } | ||
| 1505 | |||
| 1506 | alg->move = realloc(alg->move, n * sizeof(int)); | ||
| 1507 | alg->inv = realloc(alg->inv, n * sizeof(int)); | ||
| 1508 | alg->allocated = n; | ||
| 1509 | } | ||
| 1510 | |||
| 1511 | static bool | ||
| 1512 | read_mtables_file() | ||
| 1513 | { | ||
| 1514 | FILE *f; | ||
| 1515 | char fname[strlen(tabledir)+20]; | ||
| 1516 | int m, b = sizeof(int); | ||
| 1517 | bool r = true; | ||
| 1518 | |||
| 1519 | strcpy(fname, tabledir); | ||
| 1520 | strcat(fname, "/mtables"); | ||
| 1521 | |||
| 1522 | if ((f = fopen(fname, "rb")) == NULL) | ||
| 1523 | return false; | ||
| 1524 | |||
| 1525 | for (m = 0; m < NMOVES; m++) { | ||
| 1526 | r = r && fread(epose_mtable[m], b, me[0], f) == me[0]; | ||
| 1527 | r = r && fread(eposs_mtable[m], b, me[1], f) == me[1]; | ||
| 1528 | r = r && fread(eposm_mtable[m], b, me[2], f) == me[2]; | ||
| 1529 | r = r && fread(eofb_mtable[m], b, me[3], f) == me[3]; | ||
| 1530 | r = r && fread(eorl_mtable[m], b, me[4], f) == me[4]; | ||
| 1531 | r = r && fread(eoud_mtable[m], b, me[5], f) == me[5]; | ||
| 1532 | r = r && fread(cp_mtable[m], b, me[6], f) == me[6]; | ||
| 1533 | r = r && fread(coud_mtable[m], b, me[7], f) == me[7]; | ||
| 1534 | r = r && fread(corl_mtable[m], b, me[8], f) == me[8]; | ||
| 1535 | r = r && fread(cofb_mtable[m], b, me[9], f) == me[9]; | ||
| 1536 | r = r && fread(cpos_mtable[m], b, me[10], f) == me[10]; | ||
| 1537 | } | ||
| 1538 | |||
| 1539 | fclose(f); | ||
| 1540 | return r; | ||
| 1541 | } | ||
| 1542 | |||
| 1543 | static bool | ||
| 1544 | read_ptable_file(PruneData *pd) | ||
| 1545 | { | ||
| 1546 | FILE *f; | ||
| 1547 | char fname[strlen(tabledir)+100]; | ||
| 1548 | uint64_t r; | ||
| 1549 | |||
| 1550 | strcpy(fname, tabledir); | ||
| 1551 | strcat(fname, "/"); | ||
| 1552 | strcat(fname, pd->filename); | ||
| 1553 | |||
| 1554 | if ((f = fopen(fname, "rb")) == NULL) | ||
| 1555 | return false; | ||
| 1556 | |||
| 1557 | r = fread(pd->ptable, sizeof(uint8_t), ptablesize(pd), f); | ||
| 1558 | fclose(f); | ||
| 1559 | |||
| 1560 | return r == ptablesize(pd); | ||
| 1561 | } | ||
| 1562 | |||
| 1563 | static bool | ||
| 1564 | read_symdata_file(SymData *sd) | ||
| 1565 | { | ||
| 1566 | FILE *f; | ||
| 1567 | char fname[strlen(tabledir)+100]; | ||
| 1568 | uint64_t n = sd->coord->max, *sn = &sd->sym_coord->max; | ||
| 1569 | bool r = true; | ||
| 1570 | |||
| 1571 | strcpy(fname, tabledir); | ||
| 1572 | strcat(fname, "/"); | ||
| 1573 | strcat(fname, sd->filename); | ||
| 1574 | |||
| 1575 | if ((f = fopen(fname, "rb")) == NULL) | ||
| 1576 | return false; | ||
| 1577 | |||
| 1578 | r = r && fread(&sd->sym_coord->max, sizeof(uint64_t), 1, f) == 1; | ||
| 1579 | r = r && fread(sd->rep, sizeof(Cube), *sn, f) == *sn; | ||
| 1580 | r = r && fread(sd->class, sizeof(uint64_t), n, f) == n; | ||
| 1581 | r = r && fread(sd->transtorep, sizeof(Trans), n, f) == n; | ||
| 1582 | |||
| 1583 | fclose(f); | ||
| 1584 | return r; | ||
| 1585 | } | ||
| 1586 | |||
| 1587 | static bool | ||
| 1588 | read_ttables_file() | ||
| 1589 | { | ||
| 1590 | FILE *f; | ||
| 1591 | char fname[strlen(tabledir)+20]; | ||
| 1592 | int b = sizeof(int); | ||
| 1593 | bool r = true; | ||
| 1594 | Move m; | ||
| 1595 | |||
| 1596 | strcpy(fname, tabledir); | ||
| 1597 | strcat(fname, "/"); | ||
| 1598 | strcat(fname, "ttables"); | ||
| 1599 | |||
| 1600 | if ((f = fopen(fname, "rb")) == NULL) | ||
| 1601 | return false; | ||
| 1602 | |||
| 1603 | for (m = 0; m < NTRANS; m++) { | ||
| 1604 | r = r && fread(epose_ttable[m], b, me[0], f) == me[0]; | ||
| 1605 | r = r && fread(eposs_ttable[m], b, me[1], f) == me[1]; | ||
| 1606 | r = r && fread(eposm_ttable[m], b, me[2], f) == me[2]; | ||
| 1607 | r = r && fread(eo_ttable[m], b, me[3], f) == me[3]; | ||
| 1608 | r = r && fread(cp_ttable[m], b, me[6], f) == me[6]; | ||
| 1609 | r = r && fread(co_ttable[m], b, me[7], f) == me[7]; | ||
| 1610 | r = r && fread(cpos_ttable[m], b, me[10], f) == me[10]; | ||
| 1611 | r = r && fread(moves_ttable[m], b, me[11], f) == me[11]; | ||
| 1612 | } | ||
| 1613 | |||
| 1614 | fclose(f); | ||
| 1615 | return r; | ||
| 1616 | } | ||
| 1617 | |||
| 1618 | static Cube | ||
| 1619 | rotate_via_compose(Trans r, Cube c, PieceFilter f) | ||
| 1620 | { | ||
| 1621 | static int zero12[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; | ||
| 1622 | static int zero8[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; | ||
| 1623 | static CubeArray ma = { | ||
| 1624 | .ep = ep_mirror, | ||
| 1625 | .eofb = zero12, | ||
| 1626 | .eorl = zero12, | ||
| 1627 | .eoud = zero12, | ||
| 1628 | .cp = cp_mirror, | ||
| 1629 | .coud = zero8, | ||
| 1630 | .corl = zero8, | ||
| 1631 | .cofb = zero8, | ||
| 1632 | .cpos = cpos_mirror | ||
| 1633 | }; | ||
| 1634 | |||
| 1635 | Alg *inv = inverse_alg(rotation_algs[r % NROTATIONS]); | ||
| 1636 | Cube ret = {0}; | ||
| 1637 | |||
| 1638 | if (r >= NROTATIONS) | ||
| 1639 | ret = move_via_arrays(&ma, ret, f); | ||
| 1640 | ret = apply_alg_generic(inv, ret, f, true); | ||
| 1641 | |||
| 1642 | ret = compose_filtered(c, ret, f); | ||
| 1643 | |||
| 1644 | ret = apply_alg_generic(rotation_algs[r % NROTATIONS], ret, f, true); | ||
| 1645 | if (r >= NROTATIONS) | ||
| 1646 | ret = move_via_arrays(&ma, ret, f); | ||
| 1647 | |||
| 1648 | free_alg(inv); | ||
| 1649 | return ret; | ||
| 1650 | } | ||
| 1651 | |||
| 1652 | static int | ||
| 1653 | subset_to_index(int *a, int n, int k) | ||
| 1654 | { | ||
| 1655 | int i, ret = 0; | ||
| 1656 | |||
| 1657 | if (!is_subset(a, n, k)) | ||
| 1658 | return binomial(n, k); | ||
| 1659 | |||
| 1660 | for (i = 0; i < n; i++) { | ||
| 1661 | if (k == n-i) | ||
| 1662 | return ret; | ||
| 1663 | if (a[i]) { | ||
| 1664 | ret += binomial(n-i-1, k); | ||
| 1665 | k--; | ||
| 1666 | } | ||
| 1667 | } | ||
| 1668 | |||
| 1669 | return ret; | ||
| 1670 | } | ||
| 1671 | |||
| 1672 | static void | ||
| 1673 | sum_arrays_mod(int *src, int *dst, int n, int m) | ||
| 1674 | { | ||
| 1675 | int i; | ||
| 1676 | |||
| 1677 | for (i = 0; i < n; i++) | ||
| 1678 | dst[i] = (m <= 0) ? 0 : (src[i] + dst[i]) % m; | ||
| 1679 | } | ||
| 1680 | |||
| 1681 | static void | ||
| 1682 | swap(int *a, int *b) | ||
| 1683 | { | ||
| 1684 | int aux; | ||
| 1685 | |||
| 1686 | aux = *a; | ||
| 1687 | *a = *b; | ||
| 1688 | *b = aux; | ||
| 1689 | } | ||
| 1690 | |||
| 1691 | static bool | ||
| 1692 | write_mtables_file() | ||
| 1693 | { | ||
| 1694 | FILE *f; | ||
| 1695 | char fname[strlen(tabledir)+20]; | ||
| 1696 | int m, b = sizeof(int); | ||
| 1697 | bool r = true; | ||
| 1698 | |||
| 1699 | strcpy(fname, tabledir); | ||
| 1700 | strcat(fname, "/mtables"); | ||
| 1701 | |||
| 1702 | if ((f = fopen(fname, "wb")) == NULL) | ||
| 1703 | return false; | ||
| 1704 | |||
| 1705 | for (m = 0; m < NMOVES; m++) { | ||
| 1706 | r = r && fwrite(epose_mtable[m], b, me[0], f) == me[0]; | ||
| 1707 | r = r && fwrite(eposs_mtable[m], b, me[1], f) == me[1]; | ||
| 1708 | r = r && fwrite(eposm_mtable[m], b, me[2], f) == me[2]; | ||
| 1709 | r = r && fwrite(eofb_mtable[m], b, me[3], f) == me[3]; | ||
| 1710 | r = r && fwrite(eorl_mtable[m], b, me[4], f) == me[4]; | ||
| 1711 | r = r && fwrite(eoud_mtable[m], b, me[5], f) == me[5]; | ||
| 1712 | r = r && fwrite(cp_mtable[m], b, me[6], f) == me[6]; | ||
| 1713 | r = r && fwrite(coud_mtable[m], b, me[7], f) == me[7]; | ||
| 1714 | r = r && fwrite(corl_mtable[m], b, me[8], f) == me[8]; | ||
| 1715 | r = r && fwrite(cofb_mtable[m], b, me[9], f) == me[9]; | ||
| 1716 | r = r && fwrite(cpos_mtable[m], b, me[10], f) == me[10]; | ||
| 1717 | } | ||
| 1718 | |||
| 1719 | fclose(f); | ||
| 1720 | return r; | ||
| 1721 | } | ||
| 1722 | |||
| 1723 | static bool | ||
| 1724 | write_ptable_file(PruneData *pd) | ||
| 1725 | { | ||
| 1726 | FILE *f; | ||
| 1727 | char fname[strlen(tabledir)+100]; | ||
| 1728 | uint64_t written; | ||
| 1729 | |||
| 1730 | strcpy(fname, tabledir); | ||
| 1731 | strcat(fname, "/"); | ||
| 1732 | strcat(fname, pd->filename); | ||
| 1733 | |||
| 1734 | if ((f = fopen(fname, "wb")) == NULL) | ||
| 1735 | return false; | ||
| 1736 | |||
| 1737 | written = fwrite(pd->ptable, sizeof(uint8_t), ptablesize(pd), f); | ||
| 1738 | fclose(f); | ||
| 1739 | |||
| 1740 | return written == ptablesize(pd); | ||
| 1741 | } | ||
| 1742 | |||
| 1743 | static bool | ||
| 1744 | write_symdata_file(SymData *sd) | ||
| 1745 | { | ||
| 1746 | FILE *f; | ||
| 1747 | char fname[strlen(tabledir)+100]; | ||
| 1748 | uint64_t n = sd->coord->max, *sn = &sd->sym_coord->max; | ||
| 1749 | bool r = true; | ||
| 1750 | |||
| 1751 | strcpy(fname, tabledir); | ||
| 1752 | strcat(fname, "/"); | ||
| 1753 | strcat(fname, sd->filename); | ||
| 1754 | |||
| 1755 | if ((f = fopen(fname, "wb")) == NULL) | ||
| 1756 | return false; | ||
| 1757 | |||
| 1758 | r = r && fwrite(&sd->sym_coord->max, sizeof(uint64_t), 1, f) == 1; | ||
| 1759 | r = r && fwrite(sd->rep, sizeof(Cube), *sn, f) == *sn; | ||
| 1760 | r = r && fwrite(sd->class, sizeof(uint64_t), n, f) == n; | ||
| 1761 | r = r && fwrite(sd->transtorep, sizeof(Trans), n, f) == n; | ||
| 1762 | |||
| 1763 | fclose(f); | ||
| 1764 | return r; | ||
| 1765 | } | ||
| 1766 | |||
| 1767 | static bool | ||
| 1768 | write_ttables_file() | ||
| 1769 | { | ||
| 1770 | FILE *f; | ||
| 1771 | char fname[strlen(tabledir)+20]; | ||
| 1772 | bool r = true; | ||
| 1773 | int b = sizeof(int); | ||
| 1774 | Move m; | ||
| 1775 | |||
| 1776 | strcpy(fname, tabledir); | ||
| 1777 | strcat(fname, "/ttables"); | ||
| 1778 | |||
| 1779 | if ((f = fopen(fname, "wb")) == NULL) | ||
| 1780 | return false; | ||
| 1781 | |||
| 1782 | for (m = 0; m < NTRANS; m++) { | ||
| 1783 | r = r && fwrite(epose_ttable[m], b, me[0], f) == me[0]; | ||
| 1784 | r = r && fwrite(eposs_ttable[m], b, me[1], f) == me[1]; | ||
| 1785 | r = r && fwrite(eposm_ttable[m], b, me[2], f) == me[2]; | ||
| 1786 | r = r && fwrite(eo_ttable[m], b, me[3], f) == me[3]; | ||
| 1787 | r = r && fwrite(cp_ttable[m], b, me[6], f) == me[6]; | ||
| 1788 | r = r && fwrite(co_ttable[m], b, me[7], f) == me[7]; | ||
| 1789 | r = r && fwrite(cpos_ttable[m], b, me[10], f) == me[10]; | ||
| 1790 | r = r && fwrite(moves_ttable[m], b, me[11], f) == me[11]; | ||
| 1791 | } | ||
| 1792 | |||
| 1793 | fclose(f); | ||
| 1794 | return r; | ||
| 1795 | } | ||
| 1796 | |||
| 1797 | /* Init functions implementation *********************************************/ | ||
| 1798 | |||
| 1799 | static void | ||
| 1800 | init_auxtables() | ||
| 1801 | { | ||
| 1802 | Cube c1, c2; | ||
| 1803 | CubeArray *arr; | ||
| 1804 | uint64_t ui, uj; | ||
| 1805 | int i, j, k, auxarr[12]; | ||
| 1806 | bool cij, p1, p2; | ||
| 1807 | |||
| 1808 | for (ui = 0; ui < POW2TO11*BINOM12ON4; ui++) { | ||
| 1809 | k = (ui / POW2TO11) * 24; | ||
| 1810 | c1 = admissible_ep((Cube){ .epose = k }, pf_e); | ||
| 1811 | c1.eofb = ui % POW2TO11; | ||
| 1812 | c1 = admissible_eos_from_eofbepos(c1); | ||
| 1813 | admissible_ee_aux[ui] = c1; | ||
| 1814 | } | ||
| 1815 | |||
| 1816 | for (ui = 0; ui < FACTORIAL6; ui++) { | ||
| 1817 | arr = new_cubearray((Cube){.cpos = ui}, pf_cpos); | ||
| 1818 | for (i = 0; i < 6; i++) { | ||
| 1819 | what_center_at_aux[ui][i] = arr->cpos[i]; | ||
| 1820 | where_is_center_aux[ui][arr->cpos[i]] = i; | ||
| 1821 | } | ||
| 1822 | free_cubearray(arr, pf_cpos); | ||
| 1823 | } | ||
| 1824 | |||
| 1825 | for (ui = 0; ui < FACTORIAL8; ui++) { | ||
| 1826 | arr = new_cubearray((Cube){.cp = ui}, pf_cp); | ||
| 1827 | for (i = 0; i < 8; i++) { | ||
| 1828 | what_corner_at_aux[ui][i] = arr->cp[i]; | ||
| 1829 | where_is_corner_aux[ui][arr->cp[i]] = i; | ||
| 1830 | } | ||
| 1831 | free_cubearray(arr, pf_cp); | ||
| 1832 | } | ||
| 1833 | |||
| 1834 | for (ui = 0; ui < FACTORIAL12/FACTORIAL8; ui++) { | ||
| 1835 | arr = new_cubearray((Cube){.epose = ui}, pf_e); | ||
| 1836 | for (i = 0; i < 12; i++) | ||
| 1837 | if (edge_slice(arr->ep[i]) == 0) | ||
| 1838 | where_is_edge_aux[0][ui][arr->ep[i]] = i; | ||
| 1839 | free_cubearray(arr, pf_e); | ||
| 1840 | |||
| 1841 | arr = new_cubearray((Cube){.eposs = ui}, pf_s); | ||
| 1842 | for (i = 0; i < 12; i++) | ||
| 1843 | if (edge_slice(arr->ep[i]) == 1) | ||
| 1844 | where_is_edge_aux[1][ui][arr->ep[i]] = i; | ||
| 1845 | free_cubearray(arr, pf_s); | ||
| 1846 | |||
| 1847 | arr = new_cubearray((Cube){.eposm = ui}, pf_m); | ||
| 1848 | for (i = 0; i < 12; i++) | ||
| 1849 | if (edge_slice(arr->ep[i]) == 2) | ||
| 1850 | where_is_edge_aux[2][ui][arr->ep[i]] = i; | ||
| 1851 | free_cubearray(arr, pf_m); | ||
| 1852 | } | ||
| 1853 | |||
| 1854 | for (ui = 0; ui < POW3TO7; ui++) { | ||
| 1855 | int_to_sum_zero_array(ui, 3, 8, auxarr); | ||
| 1856 | what_orientation_last_corner_aux[ui] = auxarr[7]; | ||
| 1857 | } | ||
| 1858 | |||
| 1859 | for (ui = 0; ui < POW2TO11; ui++) { | ||
| 1860 | int_to_sum_zero_array(ui, 2, 12, auxarr); | ||
| 1861 | what_orientation_last_edge_aux[ui] = auxarr[11]; | ||
| 1862 | } | ||
| 1863 | |||
| 1864 | for (ui = 0; ui < BINOM12ON4; ui++) | ||
| 1865 | for (uj = 0; uj < BINOM12ON4; uj++) | ||
| 1866 | epos_dependent_aux[ui][uj]=epos_dependent_pos(ui, uj); | ||
| 1867 | |||
| 1868 | for (i = 0; i < NMOVES; i++) { | ||
| 1869 | for (j = 0; j < NMOVES; j++) { | ||
| 1870 | c1 = apply_move(i, apply_move(j, (Cube){0})); | ||
| 1871 | c2 = apply_move(j, apply_move(i, (Cube){0})); | ||
| 1872 | commute[i][j] = equal(c1, c2) && i && j; | ||
| 1873 | } | ||
| 1874 | } | ||
| 1875 | |||
| 1876 | for (i = 0; i < NMOVES; i++) { | ||
| 1877 | for (j = 0; j < NMOVES; j++) { | ||
| 1878 | for (k = 0; k < NMOVES; k++) { | ||
| 1879 | p1 = j && base_move(j) == base_move(k); | ||
| 1880 | p2 = i && base_move(i) == base_move(k); | ||
| 1881 | cij = commute[i][j]; | ||
| 1882 | possible_next[i][j][k] = !(p1 || (cij && p2)); | ||
| 1883 | } | ||
| 1884 | } | ||
| 1885 | } | ||
| 1886 | |||
| 1887 | for (i = 0; i < NMOVES; i++) | ||
| 1888 | inverse_move_aux[i] = i ? i + 2 - 2*((i-1)%3) : NULLMOVE; | ||
| 1889 | |||
| 1890 | /* Is there a more elegant way? */ | ||
| 1891 | inverse_trans_aux[uf] = uf; | ||
| 1892 | inverse_trans_aux[ur] = ul; | ||
| 1893 | inverse_trans_aux[ul] = ur; | ||
| 1894 | inverse_trans_aux[ub] = ub; | ||
| 1895 | |||
| 1896 | inverse_trans_aux[df] = df; | ||
| 1897 | inverse_trans_aux[dr] = dr; | ||
| 1898 | inverse_trans_aux[dl] = dl; | ||
| 1899 | inverse_trans_aux[db] = db; | ||
| 1900 | |||
| 1901 | inverse_trans_aux[rf] = lf; | ||
| 1902 | inverse_trans_aux[rd] = bl; | ||
| 1903 | inverse_trans_aux[rb] = rb; | ||
| 1904 | inverse_trans_aux[ru] = fr; | ||
| 1905 | |||
| 1906 | inverse_trans_aux[lf] = rf; | ||
| 1907 | inverse_trans_aux[ld] = br; | ||
| 1908 | inverse_trans_aux[lb] = lb; | ||
| 1909 | inverse_trans_aux[lu] = fl; | ||
| 1910 | |||
| 1911 | inverse_trans_aux[fu] = fu; | ||
| 1912 | inverse_trans_aux[fr] = ru; | ||
| 1913 | inverse_trans_aux[fd] = bu; | ||
| 1914 | inverse_trans_aux[fl] = lu; | ||
| 1915 | |||
| 1916 | inverse_trans_aux[bu] = fd; | ||
| 1917 | inverse_trans_aux[br] = ld; | ||
| 1918 | inverse_trans_aux[bd] = bd; | ||
| 1919 | inverse_trans_aux[bl] = rd; | ||
| 1920 | |||
| 1921 | inverse_trans_aux[uf_mirror] = uf_mirror; | ||
| 1922 | inverse_trans_aux[ur_mirror] = ur_mirror; | ||
| 1923 | inverse_trans_aux[ul_mirror] = ul_mirror; | ||
| 1924 | inverse_trans_aux[ub_mirror] = ub_mirror; | ||
| 1925 | |||
| 1926 | inverse_trans_aux[df_mirror] = df_mirror; | ||
| 1927 | inverse_trans_aux[dr_mirror] = dl_mirror; | ||
| 1928 | inverse_trans_aux[dl_mirror] = dr_mirror; | ||
| 1929 | inverse_trans_aux[db_mirror] = db_mirror; | ||
| 1930 | |||
| 1931 | inverse_trans_aux[rf_mirror] = rf_mirror; | ||
| 1932 | inverse_trans_aux[rd_mirror] = br_mirror; | ||
| 1933 | inverse_trans_aux[rb_mirror] = lb_mirror; | ||
| 1934 | inverse_trans_aux[ru_mirror] = fl_mirror; | ||
| 1935 | |||
| 1936 | inverse_trans_aux[lf_mirror] = lf_mirror; | ||
| 1937 | inverse_trans_aux[ld_mirror] = bl_mirror; | ||
| 1938 | inverse_trans_aux[lb_mirror] = rb_mirror; | ||
| 1939 | inverse_trans_aux[lu_mirror] = fr_mirror; | ||
| 1940 | |||
| 1941 | inverse_trans_aux[fu_mirror] = fu_mirror; | ||
| 1942 | inverse_trans_aux[fr_mirror] = lu_mirror; | ||
| 1943 | inverse_trans_aux[fd_mirror] = bu_mirror; | ||
| 1944 | inverse_trans_aux[fl_mirror] = ru_mirror; | ||
| 1945 | |||
| 1946 | inverse_trans_aux[bu_mirror] = fd_mirror; | ||
| 1947 | inverse_trans_aux[br_mirror] = rd_mirror; | ||
| 1948 | inverse_trans_aux[bd_mirror] = bd_mirror; | ||
| 1949 | inverse_trans_aux[bl_mirror] = ld_mirror; | ||
| 1950 | } | ||
| 1951 | |||
| 1952 | /* | ||
| 1953 | * There is certainly a bette way to do this, but for now I just use | ||
| 1954 | * a "graph coloring" algorithm to compute the left cosets, and I compose | ||
| 1955 | * with every possible cp to get the right cosets (it is possible that I am | ||
| 1956 | * mixing up left and right). | ||
| 1957 | * | ||
| 1958 | * For doing it better "Mathematically", we need 3 things: | ||
| 1959 | * - Checking that cp separates the orbits (UFR,UBL,DFL,DBR) and the other | ||
| 1960 | * This is easy and it is done in the commented function cphtr_cp(). | ||
| 1961 | * - Check that there is no ep/cp parity | ||
| 1962 | * - Check that we are not in the "3c" case; this is the part I don't | ||
| 1963 | * know how to do. | ||
| 1964 | */ | ||
| 1965 | static void | ||
| 1966 | init_cphtr_cosets() | ||
| 1967 | { | ||
| 1968 | unsigned int i; | ||
| 1969 | int c = 0, d = 0; | ||
| 1970 | |||
| 1971 | for (i = 0; i < FACTORIAL8; i++) { | ||
| 1972 | cphtr_left_cosets[i] = -1; | ||
| 1973 | cphtr_right_cosets[i] = -1; | ||
| 1974 | } | ||
| 1975 | |||
| 1976 | /* First we compute left cosets with a bfs */ | ||
| 1977 | for (i = 0; i < FACTORIAL8; i++) | ||
| 1978 | if (cphtr_left_cosets[i] == -1) | ||
| 1979 | init_cphtr_left_cosets_bfs(i, c++); | ||
| 1980 | |||
| 1981 | /* Then we compute right cosets using compose() */ | ||
| 1982 | for (i = 0; i < FACTORIAL8; i++) | ||
| 1983 | if (cphtr_right_cosets[i] == -1) | ||
| 1984 | init_cphtr_right_cosets_color(i, d++); | ||
| 1985 | } | ||
| 1986 | |||
| 1987 | static void | ||
| 1988 | init_cphtr_left_cosets_bfs(int i, int c) | ||
| 1989 | { | ||
| 1990 | int j, jj, k, next[FACTORIAL8], next2[FACTORIAL8], n, n2; | ||
| 1991 | Move moves[6] = {U2, D2, R2, L2, F2, B2}; | ||
| 1992 | |||
| 1993 | n = 1; | ||
| 1994 | next[0] = i; | ||
| 1995 | cphtr_left_cosets[i] = c; | ||
| 1996 | |||
| 1997 | while (n != 0) { | ||
| 1998 | for (j = 0, n2 = 0; j < n; j++) { | ||
| 1999 | for (k = 0; k < 6; k++) { | ||
| 2000 | jj = cp_mtable[moves[k]][next[j]]; | ||
| 2001 | if (cphtr_left_cosets[jj] == -1) { | ||
| 2002 | cphtr_left_cosets[jj] = c; | ||
| 2003 | next2[n2++] = jj; | ||
| 2004 | } | ||
| 2005 | } | ||
| 2006 | } | ||
| 2007 | |||
| 2008 | for (j = 0; j < n2; j++) | ||
| 2009 | next[j] = next2[j]; | ||
| 2010 | n = n2; | ||
| 2011 | } | ||
| 2012 | } | ||
| 2013 | |||
| 2014 | static void | ||
| 2015 | init_cphtr_right_cosets_color(int i, int d) | ||
| 2016 | { | ||
| 2017 | int cp; | ||
| 2018 | unsigned int j; | ||
| 2019 | |||
| 2020 | cphtr_right_rep[d] = i; | ||
| 2021 | for (j = 0; j < FACTORIAL8; j++) { | ||
| 2022 | if (cphtr_left_cosets[j] == 0) { | ||
| 2023 | /* TODO: use antindexer, it's nicer */ | ||
| 2024 | cp = compose((Cube){.cp = i}, (Cube){.cp = j}).cp; | ||
| 2025 | cphtr_right_cosets[cp] = d; | ||
| 2026 | } | ||
| 2027 | } | ||
| 2028 | } | ||
| 2029 | |||
| 2030 | static void | ||
| 2031 | init_environment() | ||
| 2032 | { | ||
| 2033 | char *nissydata = getenv("NISSYDATA"); | ||
| 2034 | char *localdata = getenv("XDG_DATA_HOME"); | ||
| 2035 | char *home = getenv("HOME"); | ||
| 2036 | bool read, write; | ||
| 2037 | |||
| 2038 | if (nissydata != NULL) { | ||
| 2039 | tabledir = malloc(strlen(nissydata) * sizeof(char) + 20); | ||
| 2040 | strcpy(tabledir, nissydata); | ||
| 2041 | } else if (localdata != NULL) { | ||
| 2042 | tabledir = malloc(strlen(localdata) * sizeof(char) + 20); | ||
| 2043 | strcpy(tabledir, localdata); | ||
| 2044 | strcat(tabledir, "/nissy"); | ||
| 2045 | } else if (home != NULL) { | ||
| 2046 | tabledir = malloc(strlen(home) * sizeof(char) + 20); | ||
| 2047 | strcpy(tabledir, home); | ||
| 2048 | strcat(tabledir, "/.nissy"); | ||
| 2049 | } | ||
| 2050 | |||
| 2051 | mkdir(tabledir, 0777); | ||
| 2052 | strcat(tabledir, "/tables"); | ||
| 2053 | mkdir(tabledir, 0777); | ||
| 2054 | |||
| 2055 | read = !access(tabledir, R_OK); | ||
| 2056 | write = !access(tabledir, W_OK); | ||
| 2057 | |||
| 2058 | if (!read) { | ||
| 2059 | fprintf(stderr, "Table files cannot be read.\n"); | ||
| 2060 | } else if (!write) { | ||
| 2061 | fprintf(stderr, "Data directory not writable: "); | ||
| 2062 | fprintf(stderr, "tables can be loaded, but not saved.\n"); | ||
| 2063 | } | ||
| 2064 | } | ||
| 2065 | |||
| 2066 | static void | ||
| 2067 | init_moves() { | ||
| 2068 | Cube c; | ||
| 2069 | CubeArray arrs; | ||
| 2070 | int i; | ||
| 2071 | unsigned int ui; | ||
| 2072 | Move m; | ||
| 2073 | |||
| 2074 | /* Generate all move cycles and flips; I do this regardless */ | ||
| 2075 | for (i = 0; i < NMOVES; i++) { | ||
| 2076 | if (i == U || i == x || i == y) | ||
| 2077 | continue; | ||
| 2078 | |||
| 2079 | c = apply_alg_generic(equiv_alg[i], (Cube){0}, pf_all, false); | ||
| 2080 | |||
| 2081 | arrs = (CubeArray) { | ||
| 2082 | edge_cycle[i], | ||
| 2083 | eofb_flipped[i], | ||
| 2084 | eorl_flipped[i], | ||
| 2085 | eoud_flipped[i], | ||
| 2086 | corner_cycle[i], | ||
| 2087 | coud_flipped[i], | ||
| 2088 | corl_flipped[i], | ||
| 2089 | cofb_flipped[i], | ||
| 2090 | center_cycle[i] | ||
| 2091 | }; | ||
| 2092 | cube_to_arrays(c, &arrs, pf_all); | ||
| 2093 | } | ||
| 2094 | |||
| 2095 | if (read_mtables_file()) | ||
| 2096 | return; | ||
| 2097 | |||
| 2098 | fprintf(stderr, "Cannot load %s, generating it\n", "mtables"); | ||
| 2099 | |||
| 2100 | /* Initialize transition tables */ | ||
| 2101 | for (m = 0; m < NMOVES; m++) { | ||
| 2102 | for (ui = 0; ui < FACTORIAL12/FACTORIAL8; ui++) { | ||
| 2103 | c = (Cube){ .epose = ui }; | ||
| 2104 | c = apply_move_cubearray(m, c, pf_e); | ||
| 2105 | epose_mtable[m][ui] = c.epose; | ||
| 2106 | |||
| 2107 | c = (Cube){ .eposs = ui }; | ||
| 2108 | c = apply_move_cubearray(m, c, pf_s); | ||
| 2109 | eposs_mtable[m][ui] = c.eposs; | ||
| 2110 | |||
| 2111 | c = (Cube){ .eposm = ui }; | ||
| 2112 | c = apply_move_cubearray(m, c, pf_m); | ||
| 2113 | eposm_mtable[m][ui] = c.eposm; | ||
| 2114 | } | ||
| 2115 | for (ui = 0; ui < POW2TO11; ui++ ) { | ||
| 2116 | c = (Cube){ .eofb = ui }; | ||
| 2117 | c = apply_move_cubearray(m, c, pf_eo); | ||
| 2118 | eofb_mtable[m][ui] = c.eofb; | ||
| 2119 | |||
| 2120 | c = (Cube){ .eorl = ui }; | ||
| 2121 | c = apply_move_cubearray(m, c, pf_eo); | ||
| 2122 | eorl_mtable[m][ui] = c.eorl; | ||
| 2123 | |||
| 2124 | c = (Cube){ .eoud = ui }; | ||
| 2125 | c = apply_move_cubearray(m, c, pf_eo); | ||
| 2126 | eoud_mtable[m][ui] = c.eoud; | ||
| 2127 | } | ||
| 2128 | for (ui = 0; ui < POW3TO7; ui++) { | ||
| 2129 | c = (Cube){ .coud = ui }; | ||
| 2130 | c = apply_move_cubearray(m, c, pf_co); | ||
| 2131 | coud_mtable[m][ui] = c.coud; | ||
| 2132 | |||
| 2133 | c = (Cube){ .corl = ui }; | ||
| 2134 | c = apply_move_cubearray(m, c, pf_co); | ||
| 2135 | corl_mtable[m][ui] = c.corl; | ||
| 2136 | |||
| 2137 | c = (Cube){ .cofb = ui }; | ||
| 2138 | c = apply_move_cubearray(m, c, pf_co); | ||
| 2139 | cofb_mtable[m][ui] = c.cofb; | ||
| 2140 | } | ||
| 2141 | for (ui = 0; ui < FACTORIAL8; ui++) { | ||
| 2142 | c = (Cube){ .cp = ui }; | ||
| 2143 | c = apply_move_cubearray(m, c, pf_cp); | ||
| 2144 | cp_mtable[m][ui] = c.cp; | ||
| 2145 | } | ||
| 2146 | for (ui = 0; ui < FACTORIAL6; ui++) { | ||
| 2147 | c = (Cube){ .cpos = ui }; | ||
| 2148 | c = apply_move_cubearray(m, c, pf_cpos); | ||
| 2149 | cpos_mtable[m][ui] = c.cpos; | ||
| 2150 | } | ||
| 2151 | } | ||
| 2152 | |||
| 2153 | if (!write_mtables_file()) | ||
| 2154 | fprintf(stderr, "Error writing mtables\n"); | ||
| 2155 | } | ||
| 2156 | |||
| 2157 | static void | ||
| 2158 | init_moves_aux() | ||
| 2159 | { | ||
| 2160 | /* Some standard PieceFilters */ | ||
| 2161 | pf_all.epose = true; | ||
| 2162 | pf_all.eposs = true; | ||
| 2163 | pf_all.eposm = true; | ||
| 2164 | pf_all.eofb = true; | ||
| 2165 | pf_all.eorl = true; | ||
| 2166 | pf_all.eoud = true; | ||
| 2167 | pf_all.cp = true; | ||
| 2168 | pf_all.cofb = true; | ||
| 2169 | pf_all.corl = true; | ||
| 2170 | pf_all.coud = true; | ||
| 2171 | pf_all.cpos = true; | ||
| 2172 | |||
| 2173 | pf_4val.epose = true; | ||
| 2174 | pf_4val.eposs = true; | ||
| 2175 | pf_4val.eposm = true; | ||
| 2176 | pf_4val.eofb = true; | ||
| 2177 | pf_4val.coud = true; | ||
| 2178 | pf_4val.cp = true; | ||
| 2179 | |||
| 2180 | pf_epcp.epose = true; | ||
| 2181 | pf_epcp.eposs = true; | ||
| 2182 | pf_epcp.eposm = true; | ||
| 2183 | pf_epcp.cp = true; | ||
| 2184 | |||
| 2185 | pf_cpos.cpos = true; | ||
| 2186 | |||
| 2187 | pf_cp.cp = true; | ||
| 2188 | |||
| 2189 | pf_ep.epose = true; | ||
| 2190 | pf_ep.eposs = true; | ||
| 2191 | pf_ep.eposm = true; | ||
| 2192 | |||
| 2193 | pf_e.epose = true; | ||
| 2194 | pf_s.eposs = true; | ||
| 2195 | pf_m.eposm = true; | ||
| 2196 | |||
| 2197 | pf_eo.eofb = true; | ||
| 2198 | pf_eo.eorl = true; | ||
| 2199 | pf_eo.eoud = true; | ||
| 2200 | |||
| 2201 | pf_co.cofb = true; | ||
| 2202 | pf_co.corl = true; | ||
| 2203 | pf_co.coud = true; | ||
| 2204 | |||
| 2205 | /* Used to convert to and from CubeArray */ | ||
| 2206 | epe_solved[0] = FR; | ||
| 2207 | epe_solved[1] = FL; | ||
| 2208 | epe_solved[2] = BL; | ||
| 2209 | epe_solved[3] = BR; | ||
| 2210 | |||
| 2211 | eps_solved[0] = UL; | ||
| 2212 | eps_solved[1] = UR; | ||
| 2213 | eps_solved[2] = DL; | ||
| 2214 | eps_solved[3] = DR; | ||
| 2215 | |||
| 2216 | epm_solved[0] = UF; | ||
| 2217 | epm_solved[1] = UB; | ||
| 2218 | epm_solved[2] = DF; | ||
| 2219 | epm_solved[3] = DB; | ||
| 2220 | |||
| 2221 | /* Table sizes, used for reading and writing files */ | ||
| 2222 | me[0] = FACTORIAL12/FACTORIAL8; | ||
| 2223 | me[1] = FACTORIAL12/FACTORIAL8; | ||
| 2224 | me[2] = FACTORIAL12/FACTORIAL8; | ||
| 2225 | me[3] = POW2TO11; | ||
| 2226 | me[4] = POW2TO11; | ||
| 2227 | me[5] = POW2TO11; | ||
| 2228 | me[6] = FACTORIAL8; | ||
| 2229 | me[7] = POW3TO7; | ||
| 2230 | me[8] = POW3TO7; | ||
| 2231 | me[9] = POW3TO7; | ||
| 2232 | me[10] = FACTORIAL6; | ||
| 2233 | me[11] = NMOVES; | ||
| 2234 | |||
| 2235 | /* Cycles *********************/ | ||
| 2236 | edge_cycle[U][UF] = UR; | ||
| 2237 | edge_cycle[U][UL] = UF; | ||
| 2238 | edge_cycle[U][UB] = UL; | ||
| 2239 | edge_cycle[U][UR] = UB; | ||
| 2240 | edge_cycle[U][DF] = DF; | ||
| 2241 | edge_cycle[U][DL] = DL; | ||
| 2242 | edge_cycle[U][DB] = DB; | ||
| 2243 | edge_cycle[U][DR] = DR; | ||
| 2244 | edge_cycle[U][FR] = FR; | ||
| 2245 | edge_cycle[U][FL] = FL; | ||
| 2246 | edge_cycle[U][BL] = BL; | ||
| 2247 | edge_cycle[U][BR] = BR; | ||
| 2248 | |||
| 2249 | edge_cycle[x][UF] = DF; | ||
| 2250 | edge_cycle[x][UL] = FL; | ||
| 2251 | edge_cycle[x][UB] = UF; | ||
| 2252 | edge_cycle[x][UR] = FR; | ||
| 2253 | edge_cycle[x][DF] = DB; | ||
| 2254 | edge_cycle[x][DL] = BL; | ||
| 2255 | edge_cycle[x][DB] = UB; | ||
| 2256 | edge_cycle[x][DR] = BR; | ||
| 2257 | edge_cycle[x][FR] = DR; | ||
| 2258 | edge_cycle[x][FL] = DL; | ||
| 2259 | edge_cycle[x][BL] = UL; | ||
| 2260 | edge_cycle[x][BR] = UR; | ||
| 2261 | |||
| 2262 | edge_cycle[y][UF] = UR; | ||
| 2263 | edge_cycle[y][UL] = UF; | ||
| 2264 | edge_cycle[y][UB] = UL; | ||
| 2265 | edge_cycle[y][UR] = UB; | ||
| 2266 | edge_cycle[y][DF] = DR; | ||
| 2267 | edge_cycle[y][DL] = DF; | ||
| 2268 | edge_cycle[y][DB] = DL; | ||
| 2269 | edge_cycle[y][DR] = DB; | ||
| 2270 | edge_cycle[y][FR] = BR; | ||
| 2271 | edge_cycle[y][FL] = FR; | ||
| 2272 | edge_cycle[y][BL] = FL; | ||
| 2273 | edge_cycle[y][BR] = BL; | ||
| 2274 | |||
| 2275 | corner_cycle[U][UFR] = UBR; | ||
| 2276 | corner_cycle[U][UFL] = UFR; | ||
| 2277 | corner_cycle[U][UBL] = UFL; | ||
| 2278 | corner_cycle[U][UBR] = UBL; | ||
| 2279 | corner_cycle[U][DFR] = DFR; | ||
| 2280 | corner_cycle[U][DFL] = DFL; | ||
| 2281 | corner_cycle[U][DBL] = DBL; | ||
| 2282 | corner_cycle[U][DBR] = DBR; | ||
| 2283 | |||
| 2284 | corner_cycle[x][UFR] = DFR; | ||
| 2285 | corner_cycle[x][UFL] = DFL; | ||
| 2286 | corner_cycle[x][UBL] = UFL; | ||
| 2287 | corner_cycle[x][UBR] = UFR; | ||
| 2288 | corner_cycle[x][DFR] = DBR; | ||
| 2289 | corner_cycle[x][DFL] = DBL; | ||
| 2290 | corner_cycle[x][DBL] = UBL; | ||
| 2291 | corner_cycle[x][DBR] = UBR; | ||
| 2292 | |||
| 2293 | corner_cycle[y][UFR] = UBR; | ||
| 2294 | corner_cycle[y][UFL] = UFR; | ||
| 2295 | corner_cycle[y][UBL] = UFL; | ||
| 2296 | corner_cycle[y][UBR] = UBL; | ||
| 2297 | corner_cycle[y][DFR] = DBR; | ||
| 2298 | corner_cycle[y][DFL] = DFR; | ||
| 2299 | corner_cycle[y][DBL] = DFL; | ||
| 2300 | corner_cycle[y][DBR] = DBL; | ||
| 2301 | |||
| 2302 | center_cycle[U][U_center] = U_center; | ||
| 2303 | center_cycle[U][D_center] = D_center; | ||
| 2304 | center_cycle[U][R_center] = R_center; | ||
| 2305 | center_cycle[U][L_center] = L_center; | ||
| 2306 | center_cycle[U][F_center] = F_center; | ||
| 2307 | center_cycle[U][B_center] = B_center; | ||
| 2308 | |||
| 2309 | center_cycle[x][U_center] = F_center; | ||
| 2310 | center_cycle[x][D_center] = B_center; | ||
| 2311 | center_cycle[x][R_center] = R_center; | ||
| 2312 | center_cycle[x][L_center] = L_center; | ||
| 2313 | center_cycle[x][F_center] = D_center; | ||
| 2314 | center_cycle[x][B_center] = U_center; | ||
| 2315 | |||
| 2316 | center_cycle[y][U_center] = U_center; | ||
| 2317 | center_cycle[y][D_center] = D_center; | ||
| 2318 | center_cycle[y][R_center] = B_center; | ||
| 2319 | center_cycle[y][L_center] = F_center; | ||
| 2320 | center_cycle[y][F_center] = R_center; | ||
| 2321 | center_cycle[y][B_center] = L_center; | ||
| 2322 | |||
| 2323 | /* Flipped pieces *************/ | ||
| 2324 | eofb_flipped[x][UF] = 1; | ||
| 2325 | eofb_flipped[x][UB] = 1; | ||
| 2326 | eofb_flipped[x][DF] = 1; | ||
| 2327 | eofb_flipped[x][DB] = 1; | ||
| 2328 | |||
| 2329 | eofb_flipped[y][FR] = 1; | ||
| 2330 | eofb_flipped[y][FL] = 1; | ||
| 2331 | eofb_flipped[y][BL] = 1; | ||
| 2332 | eofb_flipped[y][BR] = 1; | ||
| 2333 | |||
| 2334 | eorl_flipped[x][UF] = 1; | ||
| 2335 | eorl_flipped[x][UL] = 1; | ||
| 2336 | eorl_flipped[x][UB] = 1; | ||
| 2337 | eorl_flipped[x][UR] = 1; | ||
| 2338 | eorl_flipped[x][DF] = 1; | ||
| 2339 | eorl_flipped[x][DL] = 1; | ||
| 2340 | eorl_flipped[x][DB] = 1; | ||
| 2341 | eorl_flipped[x][DR] = 1; | ||
| 2342 | eorl_flipped[x][FR] = 1; | ||
| 2343 | eorl_flipped[x][FL] = 1; | ||
| 2344 | eorl_flipped[x][BL] = 1; | ||
| 2345 | eorl_flipped[x][BR] = 1; | ||
| 2346 | |||
| 2347 | eorl_flipped[y][FR] = 1; | ||
| 2348 | eorl_flipped[y][FL] = 1; | ||
| 2349 | eorl_flipped[y][BL] = 1; | ||
| 2350 | eorl_flipped[y][BR] = 1; | ||
| 2351 | |||
| 2352 | eoud_flipped[U][UF] = 1; | ||
| 2353 | eoud_flipped[U][UL] = 1; | ||
| 2354 | eoud_flipped[U][UB] = 1; | ||
| 2355 | eoud_flipped[U][UR] = 1; | ||
| 2356 | |||
| 2357 | eoud_flipped[x][UF] = 1; | ||
| 2358 | eoud_flipped[x][UB] = 1; | ||
| 2359 | eoud_flipped[x][DF] = 1; | ||
| 2360 | eoud_flipped[x][DB] = 1; | ||
| 2361 | |||
| 2362 | eoud_flipped[y][UF] = 1; | ||
| 2363 | eoud_flipped[y][UL] = 1; | ||
| 2364 | eoud_flipped[y][UB] = 1; | ||
| 2365 | eoud_flipped[y][UR] = 1; | ||
| 2366 | eoud_flipped[y][DF] = 1; | ||
| 2367 | eoud_flipped[y][DL] = 1; | ||
| 2368 | eoud_flipped[y][DB] = 1; | ||
| 2369 | eoud_flipped[y][DR] = 1; | ||
| 2370 | eoud_flipped[y][FR] = 1; | ||
| 2371 | eoud_flipped[y][FL] = 1; | ||
| 2372 | eoud_flipped[y][BL] = 1; | ||
| 2373 | eoud_flipped[y][BR] = 1; | ||
| 2374 | |||
| 2375 | coud_flipped[x][UFR] = 2; | ||
| 2376 | coud_flipped[x][UFL] = 1; | ||
| 2377 | coud_flipped[x][UBR] = 1; | ||
| 2378 | coud_flipped[x][UBL] = 2; | ||
| 2379 | coud_flipped[x][DFR] = 1; | ||
| 2380 | coud_flipped[x][DFL] = 2; | ||
| 2381 | coud_flipped[x][DBR] = 2; | ||
| 2382 | coud_flipped[x][DBL] = 1; | ||
| 2383 | |||
| 2384 | corl_flipped[U][UFR] = 1; | ||
| 2385 | corl_flipped[U][UFL] = 2; | ||
| 2386 | corl_flipped[U][UBL] = 1; | ||
| 2387 | corl_flipped[U][UBR] = 2; | ||
| 2388 | |||
| 2389 | corl_flipped[y][UFR] = 1; | ||
| 2390 | corl_flipped[y][UFL] = 2; | ||
| 2391 | corl_flipped[y][UBL] = 1; | ||
| 2392 | corl_flipped[y][UBR] = 2; | ||
| 2393 | corl_flipped[y][DFR] = 2; | ||
| 2394 | corl_flipped[y][DFL] = 1; | ||
| 2395 | corl_flipped[y][DBL] = 2; | ||
| 2396 | corl_flipped[y][DBR] = 1; | ||
| 2397 | |||
| 2398 | cofb_flipped[U][UFR] = 2; | ||
| 2399 | cofb_flipped[U][UFL] = 1; | ||
| 2400 | cofb_flipped[U][UBL] = 2; | ||
| 2401 | cofb_flipped[U][UBR] = 1; | ||
| 2402 | |||
| 2403 | cofb_flipped[x][UFR] = 1; | ||
| 2404 | cofb_flipped[x][UFL] = 2; | ||
| 2405 | cofb_flipped[x][UBL] = 1; | ||
| 2406 | cofb_flipped[x][UBR] = 2; | ||
| 2407 | cofb_flipped[x][DFR] = 2; | ||
| 2408 | cofb_flipped[x][DFL] = 1; | ||
| 2409 | cofb_flipped[x][DBL] = 2; | ||
| 2410 | cofb_flipped[x][DBR] = 1; | ||
| 2411 | |||
| 2412 | cofb_flipped[y][UFR] = 2; | ||
| 2413 | cofb_flipped[y][UFL] = 1; | ||
| 2414 | cofb_flipped[y][UBL] = 2; | ||
| 2415 | cofb_flipped[y][UBR] = 1; | ||
| 2416 | cofb_flipped[y][DFR] = 1; | ||
| 2417 | cofb_flipped[y][DFL] = 2; | ||
| 2418 | cofb_flipped[y][DBL] = 1; | ||
| 2419 | cofb_flipped[y][DBR] = 2; | ||
| 2420 | |||
| 2421 | /* Equivalent moves ***********/ | ||
| 2422 | equiv_alg[NULLMOVE] = new_alg(""); | ||
| 2423 | |||
| 2424 | equiv_alg[U] = new_alg(" U "); | ||
| 2425 | equiv_alg[U2] = new_alg(" UU "); | ||
| 2426 | equiv_alg[U3] = new_alg(" UUU "); | ||
| 2427 | equiv_alg[D] = new_alg(" xx U xx "); | ||
| 2428 | equiv_alg[D2] = new_alg(" xx UU xx "); | ||
| 2429 | equiv_alg[D3] = new_alg(" xx UUU xx "); | ||
| 2430 | equiv_alg[R] = new_alg(" yx U xxxyyy "); | ||
| 2431 | equiv_alg[R2] = new_alg(" yx UU xxxyyy "); | ||
| 2432 | equiv_alg[R3] = new_alg(" yx UUU xxxyyy "); | ||
| 2433 | equiv_alg[L] = new_alg(" yyyx U xxxy "); | ||
| 2434 | equiv_alg[L2] = new_alg(" yyyx UU xxxy "); | ||
| 2435 | equiv_alg[L3] = new_alg(" yyyx UUU xxxy "); | ||
| 2436 | equiv_alg[F] = new_alg(" x U xxx "); | ||
| 2437 | equiv_alg[F2] = new_alg(" x UU xxx "); | ||
| 2438 | equiv_alg[F3] = new_alg(" x UUU xxx "); | ||
| 2439 | equiv_alg[B] = new_alg(" xxx U x "); | ||
| 2440 | equiv_alg[B2] = new_alg(" xxx UU x "); | ||
| 2441 | equiv_alg[B3] = new_alg(" xxx UUU x "); | ||
| 2442 | |||
| 2443 | equiv_alg[Uw] = new_alg(" xx U xx y "); | ||
| 2444 | equiv_alg[Uw2] = new_alg(" xx UU xx yy "); | ||
| 2445 | equiv_alg[Uw3] = new_alg(" xx UUU xx yyy "); | ||
| 2446 | equiv_alg[Dw] = new_alg(" U yyy "); | ||
| 2447 | equiv_alg[Dw2] = new_alg(" UU yy "); | ||
| 2448 | equiv_alg[Dw3] = new_alg(" UUU y "); | ||
| 2449 | equiv_alg[Rw] = new_alg(" yyyx U xxxy x "); | ||
| 2450 | equiv_alg[Rw2] = new_alg(" yyyx UU xxxy xx "); | ||
| 2451 | equiv_alg[Rw3] = new_alg(" yyyx UUU xxxy xxx "); | ||
| 2452 | equiv_alg[Lw] = new_alg(" yx U xxxyyy xxx "); | ||
| 2453 | equiv_alg[Lw2] = new_alg(" yx UU xxxyyy xx "); | ||
| 2454 | equiv_alg[Lw3] = new_alg(" yx UUU xxxyyy x "); | ||
| 2455 | equiv_alg[Fw] = new_alg(" xxx U x yxxxyyy "); | ||
| 2456 | equiv_alg[Fw2] = new_alg(" xxx UU x yxxyyy "); | ||
| 2457 | equiv_alg[Fw3] = new_alg(" xxx UUU x yxyyy "); | ||
| 2458 | equiv_alg[Bw] = new_alg(" x U xxx yxyyy "); | ||
| 2459 | equiv_alg[Bw2] = new_alg(" x UU xxx yxxyyy "); | ||
| 2460 | equiv_alg[Bw3] = new_alg(" x UUU xxx yxxxyyy "); | ||
| 2461 | |||
| 2462 | equiv_alg[M] = new_alg(" yx U xx UUU yxyyy "); | ||
| 2463 | equiv_alg[M2] = new_alg(" yx UU xx UU xxxy "); | ||
| 2464 | equiv_alg[M3] = new_alg(" yx UUU xx U yxxxy "); | ||
| 2465 | equiv_alg[S] = new_alg(" x UUU xx U yyyx "); | ||
| 2466 | equiv_alg[S2] = new_alg(" x UU xx UU yyx "); | ||
| 2467 | equiv_alg[S3] = new_alg(" x U xx UUU yx "); | ||
| 2468 | equiv_alg[E] = new_alg(" U xx UUU xxyyy "); | ||
| 2469 | equiv_alg[E2] = new_alg(" UU xx UU xxyy "); | ||
| 2470 | equiv_alg[E3] = new_alg(" UUU xx U xxy "); | ||
| 2471 | |||
| 2472 | equiv_alg[x] = new_alg(" x "); | ||
| 2473 | equiv_alg[x2] = new_alg(" xx "); | ||
| 2474 | equiv_alg[x3] = new_alg(" xxx "); | ||
| 2475 | equiv_alg[y] = new_alg(" y "); | ||
| 2476 | equiv_alg[y2] = new_alg(" yy "); | ||
| 2477 | equiv_alg[y3] = new_alg(" yyy "); | ||
| 2478 | equiv_alg[z] = new_alg(" yyy x y "); | ||
| 2479 | equiv_alg[z2] = new_alg(" yy xx "); | ||
| 2480 | equiv_alg[z3] = new_alg(" y x yyy "); | ||
| 2481 | } | ||
| 2482 | |||
| 2483 | static void | ||
| 2484 | init_strings() | ||
| 2485 | { | ||
| 2486 | strcpy(move_string [NULLMOVE], "-" ); | ||
| 2487 | strcpy(move_string [U], "U" ); | ||
| 2488 | strcpy(move_string [U2], "U2" ); | ||
| 2489 | strcpy(move_string [U3], "U\'" ); | ||
| 2490 | strcpy(move_string [D], "D" ); | ||
| 2491 | strcpy(move_string [D2], "D2" ); | ||
| 2492 | strcpy(move_string [D3], "D\'" ); | ||
| 2493 | strcpy(move_string [R], "R" ); | ||
| 2494 | strcpy(move_string [R2], "R2" ); | ||
| 2495 | strcpy(move_string [R3], "R\'" ); | ||
| 2496 | strcpy(move_string [L], "L" ); | ||
| 2497 | strcpy(move_string [L2], "L2" ); | ||
| 2498 | strcpy(move_string [L3], "L\'" ); | ||
| 2499 | strcpy(move_string [F], "F" ); | ||
| 2500 | strcpy(move_string [F2], "F2" ); | ||
| 2501 | strcpy(move_string [F3], "F\'" ); | ||
| 2502 | strcpy(move_string [B], "B" ); | ||
| 2503 | strcpy(move_string [B2], "B2" ); | ||
| 2504 | strcpy(move_string [B3], "B\'" ); | ||
| 2505 | strcpy(move_string [Uw], "Uw" ); | ||
| 2506 | strcpy(move_string [Uw2], "Uw2" ); | ||
| 2507 | strcpy(move_string [Uw3], "Uw\'" ); | ||
| 2508 | strcpy(move_string [Dw], "Dw" ); | ||
| 2509 | strcpy(move_string [Dw2], "Dw2" ); | ||
| 2510 | strcpy(move_string [Dw3], "Dw\'" ); | ||
| 2511 | strcpy(move_string [Rw], "Rw" ); | ||
| 2512 | strcpy(move_string [Rw2], "Rw2" ); | ||
| 2513 | strcpy(move_string [Rw3], "Rw\'" ); | ||
| 2514 | strcpy(move_string [Lw], "Lw" ); | ||
| 2515 | strcpy(move_string [Lw2], "Lw2" ); | ||
| 2516 | strcpy(move_string [Lw3], "Lw\'" ); | ||
| 2517 | strcpy(move_string [Fw], "Fw" ); | ||
| 2518 | strcpy(move_string [Fw2], "Fw2" ); | ||
| 2519 | strcpy(move_string [Fw3], "Fw\'" ); | ||
| 2520 | strcpy(move_string [Bw], "Bw" ); | ||
| 2521 | strcpy(move_string [Bw2], "Bw2" ); | ||
| 2522 | strcpy(move_string [Bw3], "Bw\'" ); | ||
| 2523 | strcpy(move_string [M], "M" ); | ||
| 2524 | strcpy(move_string [M2], "M2" ); | ||
| 2525 | strcpy(move_string [M3], "M\'" ); | ||
| 2526 | strcpy(move_string [S], "S" ); | ||
| 2527 | strcpy(move_string [S2], "S2" ); | ||
| 2528 | strcpy(move_string [S3], "S\'" ); | ||
| 2529 | strcpy(move_string [E], "E" ); | ||
| 2530 | strcpy(move_string [E2], "E2" ); | ||
| 2531 | strcpy(move_string [E3], "E\'" ); | ||
| 2532 | strcpy(move_string [x], "x" ); | ||
| 2533 | strcpy(move_string [x2], "x2" ); | ||
| 2534 | strcpy(move_string [x3], "x\'" ); | ||
| 2535 | strcpy(move_string [y], "y" ); | ||
| 2536 | strcpy(move_string [y2], "y2" ); | ||
| 2537 | strcpy(move_string [y3], "y\'" ); | ||
| 2538 | strcpy(move_string [z], "z" ); | ||
| 2539 | strcpy(move_string [z2], "z2" ); | ||
| 2540 | strcpy(move_string [z3], "z\'" ); | ||
| 2541 | |||
| 2542 | strcpy(edge_string [UF], "UF" ); | ||
| 2543 | strcpy(edge_string [UL], "UL" ); | ||
| 2544 | strcpy(edge_string [UB], "UB" ); | ||
| 2545 | strcpy(edge_string [UR], "UR" ); | ||
| 2546 | strcpy(edge_string [DF], "DF" ); | ||
| 2547 | strcpy(edge_string [DL], "DL" ); | ||
| 2548 | strcpy(edge_string [DB], "DB" ); | ||
| 2549 | strcpy(edge_string [DR], "DR" ); | ||
| 2550 | strcpy(edge_string [FR], "FR" ); | ||
| 2551 | strcpy(edge_string [FL], "FL" ); | ||
| 2552 | strcpy(edge_string [BL], "BL" ); | ||
| 2553 | strcpy(edge_string [BR], "BR" ); | ||
| 2554 | |||
| 2555 | strcpy(corner_string [UFR], "UFR" ); | ||
| 2556 | strcpy(corner_string [UFL], "UFL" ); | ||
| 2557 | strcpy(corner_string [UBL], "UBL" ); | ||
| 2558 | strcpy(corner_string [UBR], "UBR" ); | ||
| 2559 | strcpy(corner_string [DFR], "DFR" ); | ||
| 2560 | strcpy(corner_string [DFL], "DFL" ); | ||
| 2561 | strcpy(corner_string [DBL], "DBL" ); | ||
| 2562 | strcpy(corner_string [DBR], "DBR" ); | ||
| 2563 | |||
| 2564 | strcpy(center_string [U_center], "U" ); | ||
| 2565 | strcpy(center_string [D_center], "D" ); | ||
| 2566 | strcpy(center_string [R_center], "R" ); | ||
| 2567 | strcpy(center_string [L_center], "L" ); | ||
| 2568 | strcpy(center_string [F_center], "F" ); | ||
| 2569 | strcpy(center_string [B_center], "B" ); | ||
| 2570 | } | ||
| 2571 | |||
| 2572 | static void | ||
| 2573 | init_symdata() | ||
| 2574 | { | ||
| 2575 | int i; | ||
| 2576 | |||
| 2577 | for (i = 0; i < n_all_symdata; i++) | ||
| 2578 | gensym(all_sd[i]); | ||
| 2579 | } | ||
| 2580 | |||
| 2581 | static void | ||
| 2582 | init_trans() { | ||
| 2583 | Cube aux, cube, mirr, c[3]; | ||
| 2584 | CubeArray epcp; | ||
| 2585 | int i, eparr[12], eoarr[12], cparr[8], coarr[8]; | ||
| 2586 | unsigned int ui; | ||
| 2587 | Move mi, move; | ||
| 2588 | Trans m; | ||
| 2589 | |||
| 2590 | /* Compute sources */ | ||
| 2591 | for (i = 0; i < NTRANS; i++) { | ||
| 2592 | cube = apply_alg(rotation_algs[i % NROTATIONS], (Cube){0}); | ||
| 2593 | |||
| 2594 | epose_source[i] = edge_slice(what_edge_at(cube, FR)); | ||
| 2595 | eposs_source[i] = edge_slice(what_edge_at(cube, UR)); | ||
| 2596 | eposm_source[i] = edge_slice(what_edge_at(cube, UF)); | ||
| 2597 | eofb_source[i] = what_center_at(cube, F_center)/2; | ||
| 2598 | eorl_source[i] = what_center_at(cube, R_center)/2; | ||
| 2599 | eoud_source[i] = what_center_at(cube, U_center)/2; | ||
| 2600 | coud_source[i] = what_center_at(cube, U_center)/2; | ||
| 2601 | cofb_source[i] = what_center_at(cube, F_center)/2; | ||
| 2602 | corl_source[i] = what_center_at(cube, R_center)/2; | ||
| 2603 | } | ||
| 2604 | |||
| 2605 | if (read_ttables_file()) | ||
| 2606 | return; | ||
| 2607 | |||
| 2608 | fprintf(stderr, "Cannot load %s, generating it\n", "ttables"); | ||
| 2609 | |||
| 2610 | /* Initialize tables */ | ||
| 2611 | for (m = 0; m < NTRANS; m++) { | ||
| 2612 | epcp = (CubeArray){ .ep = eparr, .cp = cparr }; | ||
| 2613 | cube = apply_alg(rotation_algs[m % NROTATIONS], (Cube){0}); | ||
| 2614 | cube_to_arrays(cube, &epcp, pf_epcp); | ||
| 2615 | if (m >= NROTATIONS) { | ||
| 2616 | apply_permutation(ep_mirror, eparr, 12); | ||
| 2617 | apply_permutation(cp_mirror, cparr, 8); | ||
| 2618 | } | ||
| 2619 | |||
| 2620 | for (ui = 0; ui < FACTORIAL12/FACTORIAL8; ui++) { | ||
| 2621 | c[0] = admissible_ep((Cube){ .epose = ui }, pf_e); | ||
| 2622 | c[1] = admissible_ep((Cube){ .eposs = ui }, pf_s); | ||
| 2623 | c[2] = admissible_ep((Cube){ .eposm = ui }, pf_m); | ||
| 2624 | |||
| 2625 | cube = rotate_via_compose(m,c[epose_source[m]],pf_ep); | ||
| 2626 | epose_ttable[m][ui] = cube.epose; | ||
| 2627 | |||
| 2628 | cube = rotate_via_compose(m,c[eposs_source[m]],pf_ep); | ||
| 2629 | eposs_ttable[m][ui] = cube.eposs; | ||
| 2630 | |||
| 2631 | cube = rotate_via_compose(m,c[eposm_source[m]],pf_ep); | ||
| 2632 | eposm_ttable[m][ui] = cube.eposm; | ||
| 2633 | } | ||
| 2634 | for (ui = 0; ui < POW2TO11; ui++ ) { | ||
| 2635 | int_to_sum_zero_array(ui, 2, 12, eoarr); | ||
| 2636 | apply_permutation(eparr, eoarr, 12); | ||
| 2637 | eo_ttable[m][ui] = digit_array_to_int(eoarr, 11, 2); | ||
| 2638 | } | ||
| 2639 | for (ui = 0; ui < POW3TO7; ui++) { | ||
| 2640 | int_to_sum_zero_array(ui, 3, 8, coarr); | ||
| 2641 | apply_permutation(cparr, coarr, 8); | ||
| 2642 | co_ttable[m][ui] = digit_array_to_int(coarr, 7, 3); | ||
| 2643 | if (m >= NROTATIONS) | ||
| 2644 | co_ttable[m][ui] = | ||
| 2645 | invert_digits(co_ttable[m][ui], 3, 7); | ||
| 2646 | } | ||
| 2647 | for (ui = 0; ui < FACTORIAL8; ui++) { | ||
| 2648 | cube = (Cube){ .cp = ui }; | ||
| 2649 | cube = rotate_via_compose(m, cube, pf_cp); | ||
| 2650 | cp_ttable[m][ui] = cube.cp; | ||
| 2651 | } | ||
| 2652 | for (ui = 0; ui < FACTORIAL6; ui++) { | ||
| 2653 | cube = (Cube){ .cpos = ui }; | ||
| 2654 | cube = rotate_via_compose(m, cube, pf_cpos); | ||
| 2655 | cpos_ttable[m][ui] = cube.cpos; | ||
| 2656 | } | ||
| 2657 | for (mi = 0; mi < NMOVES; mi++) { | ||
| 2658 | aux = apply_trans(m, apply_move(mi, (Cube){0})); | ||
| 2659 | for (move = 0; move < NMOVES; move++) { | ||
| 2660 | cube = apply_move(inverse_move_aux[move], aux); | ||
| 2661 | mirr = apply_trans(uf_mirror, cube); | ||
| 2662 | if (is_solved(cube, false) || | ||
| 2663 | is_solved(mirr, false)) | ||
| 2664 | moves_ttable[m][mi] = move; | ||
| 2665 | } | ||
| 2666 | } | ||
| 2667 | } | ||
| 2668 | |||
| 2669 | if (!write_ttables_file()) | ||
| 2670 | fprintf(stderr, "Error writing ttables\n"); | ||
| 2671 | } | ||
| 2672 | |||
| 2673 | static void | ||
| 2674 | init_trans_aux() | ||
| 2675 | { | ||
| 2676 | ep_mirror[UF] = UF; | ||
| 2677 | ep_mirror[UL] = UR; | ||
| 2678 | ep_mirror[UB] = UB; | ||
| 2679 | ep_mirror[UR] = UL; | ||
| 2680 | ep_mirror[DF] = DF; | ||
| 2681 | ep_mirror[DL] = DR; | ||
| 2682 | ep_mirror[DB] = DB; | ||
| 2683 | ep_mirror[DR] = DL; | ||
| 2684 | ep_mirror[FR] = FL; | ||
| 2685 | ep_mirror[FL] = FR; | ||
| 2686 | ep_mirror[BR] = BL; | ||
| 2687 | ep_mirror[BL] = BR; | ||
| 2688 | |||
| 2689 | cp_mirror[UFR] = UFL; | ||
| 2690 | cp_mirror[UFL] = UFR; | ||
| 2691 | cp_mirror[UBL] = UBR; | ||
| 2692 | cp_mirror[UBR] = UBL; | ||
| 2693 | cp_mirror[DFR] = DFL; | ||
| 2694 | cp_mirror[DFL] = DFR; | ||
| 2695 | cp_mirror[DBL] = DBR; | ||
| 2696 | cp_mirror[DBR] = DBL; | ||
| 2697 | |||
| 2698 | cpos_mirror[U_center] = U_center; | ||
| 2699 | cpos_mirror[D_center] = D_center; | ||
| 2700 | cpos_mirror[R_center] = L_center; | ||
| 2701 | cpos_mirror[L_center] = R_center; | ||
| 2702 | cpos_mirror[F_center] = F_center; | ||
| 2703 | cpos_mirror[B_center] = B_center; | ||
| 2704 | |||
| 2705 | /* Is there a more elegant way? */ | ||
| 2706 | rotation_algs[uf] = new_alg(""); | ||
| 2707 | rotation_algs[ur] = new_alg("y"); | ||
| 2708 | rotation_algs[ub] = new_alg("y2"); | ||
| 2709 | rotation_algs[ul] = new_alg("y3"); | ||
| 2710 | |||
| 2711 | rotation_algs[df] = new_alg("z2"); | ||
| 2712 | rotation_algs[dr] = new_alg("y z2"); | ||
| 2713 | rotation_algs[db] = new_alg("x2"); | ||
| 2714 | rotation_algs[dl] = new_alg("y3 z2"); | ||
| 2715 | |||
| 2716 | rotation_algs[rf] = new_alg("z3"); | ||
| 2717 | rotation_algs[rd] = new_alg("z3 y"); | ||
| 2718 | rotation_algs[rb] = new_alg("z3 y2"); | ||
| 2719 | rotation_algs[ru] = new_alg("z3 y3"); | ||
| 2720 | |||
| 2721 | rotation_algs[lf] = new_alg("z"); | ||
| 2722 | rotation_algs[ld] = new_alg("z y3"); | ||
| 2723 | rotation_algs[lb] = new_alg("z y2"); | ||
| 2724 | rotation_algs[lu] = new_alg("z y"); | ||
| 2725 | |||
| 2726 | rotation_algs[fu] = new_alg("x y2"); | ||
| 2727 | rotation_algs[fr] = new_alg("x y"); | ||
| 2728 | rotation_algs[fd] = new_alg("x"); | ||
| 2729 | rotation_algs[fl] = new_alg("x y3"); | ||
| 2730 | |||
| 2731 | rotation_algs[bu] = new_alg("x3"); | ||
| 2732 | rotation_algs[br] = new_alg("x3 y"); | ||
| 2733 | rotation_algs[bd] = new_alg("x3 y2"); | ||
| 2734 | rotation_algs[bl] = new_alg("x3 y3"); | ||
| 2735 | } | ||
| 2736 | |||
| 2737 | |||
| 2738 | /* Public functions implementation *******************************************/ | ||
| 2739 | |||
| 2740 | Cube | ||
| 2741 | apply_alg(Alg *alg, Cube cube) | ||
| 2742 | { | ||
| 2743 | return apply_alg_generic(alg, cube, pf_all, true); | ||
| 2744 | } | ||
| 2745 | |||
| 2746 | Cube | ||
| 2747 | apply_move(Move m, Cube cube) | ||
| 2748 | { | ||
| 2749 | return (Cube) { | ||
| 2750 | .epose = epose_mtable[m][cube.epose], | ||
| 2751 | .eposs = eposs_mtable[m][cube.eposs], | ||
| 2752 | .eposm = eposm_mtable[m][cube.eposm], | ||
| 2753 | .eofb = eofb_mtable[m][cube.eofb], | ||
| 2754 | .eorl = eorl_mtable[m][cube.eorl], | ||
| 2755 | .eoud = eoud_mtable[m][cube.eoud], | ||
| 2756 | .coud = coud_mtable[m][cube.coud], | ||
| 2757 | .cofb = cofb_mtable[m][cube.cofb], | ||
| 2758 | .corl = corl_mtable[m][cube.corl], | ||
| 2759 | .cp = cp_mtable[m][cube.cp], | ||
| 2760 | .cpos = cpos_mtable[m][cube.cpos] | ||
| 2761 | }; | ||
| 2762 | } | ||
| 2763 | |||
| 2764 | |||
| 2765 | Cube | ||
| 2766 | apply_trans(Trans t, Cube cube) | ||
| 2767 | { | ||
| 2768 | int aux_epos[3] = { cube.epose, cube.eposs, cube.eposm }; | ||
| 2769 | int aux_eo[3] = { cube.eoud, cube.eorl, cube.eofb }; | ||
| 2770 | int aux_co[3] = { cube.coud, cube.corl, cube.cofb }; | ||
| 2771 | |||
| 2772 | return (Cube) { | ||
| 2773 | .epose = epose_ttable[t][aux_epos[epose_source[t]]], | ||
| 2774 | .eposs = eposs_ttable[t][aux_epos[eposs_source[t]]], | ||
| 2775 | .eposm = eposm_ttable[t][aux_epos[eposm_source[t]]], | ||
| 2776 | .eofb = eo_ttable[t][aux_eo[eofb_source[t]]], | ||
| 2777 | .eorl = eo_ttable[t][aux_eo[eorl_source[t]]], | ||
| 2778 | .eoud = eo_ttable[t][aux_eo[eoud_source[t]]], | ||
| 2779 | .coud = co_ttable[t][aux_co[coud_source[t]]], | ||
| 2780 | .corl = co_ttable[t][aux_co[corl_source[t]]], | ||
| 2781 | .cofb = co_ttable[t][aux_co[cofb_source[t]]], | ||
| 2782 | .cp = cp_ttable[t][cube.cp], | ||
| 2783 | .cpos = cpos_ttable[t][cube.cpos] | ||
| 2784 | }; | ||
| 2785 | } | ||
| 2786 | |||
| 2787 | Move | ||
| 2788 | base_move(Move m) | ||
| 2789 | { | ||
| 2790 | if (m == NULLMOVE) | ||
| 2791 | return NULLMOVE; | ||
| 2792 | else | ||
| 2793 | return m - (m-1)%3; | ||
| 2794 | } | ||
| 2795 | |||
| 2796 | Cube | ||
| 2797 | compose(Cube c2, Cube c1) | ||
| 2798 | { | ||
| 2799 | return compose_filtered(c2, c1, pf_all); | ||
| 2800 | } | ||
| 2801 | |||
| 2802 | /*TODO maybe move the next two */ | ||
| 2803 | uint64_t | ||
| 2804 | cphtr(Cube cube) | ||
| 2805 | { | ||
| 2806 | return cphtr_right_cosets[cube.cp]; | ||
| 2807 | } | ||
| 2808 | |||
| 2809 | Cube | ||
| 2810 | anti_cphtr(uint64_t ind) | ||
| 2811 | { | ||
| 2812 | return (Cube) { .cp = cphtr_right_rep[ind] }; | ||
| 2813 | } | ||
| 2814 | |||
| 2815 | uint64_t | ||
| 2816 | epos_dependent(Cube c) | ||
| 2817 | { | ||
| 2818 | return epos_dependent_aux[c.eposs/FACTORIAL4][c.epose/FACTORIAL4]; | ||
| 2819 | } | ||
| 2820 | |||
| 2821 | bool | ||
| 2822 | equal(Cube c1, Cube c2) | ||
| 2823 | { | ||
| 2824 | return c1.eofb == c2.eofb && | ||
| 2825 | c1.epose == c2.epose && | ||
| 2826 | c1.eposs == c2.eposs && | ||
| 2827 | c1.eposm == c2.eposm && | ||
| 2828 | c1.coud == c2.coud && | ||
| 2829 | c1.cp == c2.cp && | ||
| 2830 | c1.cpos == c2.cpos; | ||
| 2831 | } | ||
| 2832 | |||
| 2833 | void | ||
| 2834 | genptable(PruneData *pd) | ||
| 2835 | { | ||
| 2836 | Cube cube; | ||
| 2837 | uint64_t j, oldn = 0; | ||
| 2838 | DfsData dd = { | ||
| 2839 | .m = 0, | ||
| 2840 | .last1 = NULLMOVE, | ||
| 2841 | .last2 = NULLMOVE | ||
| 2842 | }; | ||
| 2843 | |||
| 2844 | if (pd->generated) | ||
| 2845 | return; | ||
| 2846 | |||
| 2847 | /* TODO: check if memory is enough, otherwise maybe crash gracefully? */ | ||
| 2848 | pd->ptable = malloc(ptablesize(pd) * sizeof(uint8_t)); | ||
| 2849 | |||
| 2850 | if (read_ptable_file(pd)) { | ||
| 2851 | pd->generated = true; | ||
| 2852 | return; | ||
| 2853 | } | ||
| 2854 | |||
| 2855 | fprintf(stderr, "Cannot load %s, generating it\n", pd->filename); | ||
| 2856 | |||
| 2857 | /* We use 4 bits per value, so any distance >= 15 is set to 15 */ | ||
| 2858 | for (j = 0; j < pd->coord->max; j++) | ||
| 2859 | ptable_update(pd, pd->coord->cube(j), 15); | ||
| 2860 | |||
| 2861 | moveset_to_list(pd->moveset, NULL, dd.sorted_moves); | ||
| 2862 | movelist_to_position(dd.sorted_moves, dd.move_position); | ||
| 2863 | |||
| 2864 | for (dd.d = 0, pd->n = 0; dd.d < 15 && pd->n < pd->coord->max; dd.d++) { | ||
| 2865 | for (j = 0; j < pd->coord->max; j++) { | ||
| 2866 | cube = pd->coord->cube(j); | ||
| 2867 | if (pd->coord->check(cube)) | ||
| 2868 | genptable_dfs(cube, pd, &dd); | ||
| 2869 | } | ||
| 2870 | fprintf(stderr, "Depth %d done, generated %lu\t(%lu/%lu)\n", | ||
| 2871 | dd.d, pd->n-oldn, pd->n, pd->coord->max); | ||
| 2872 | oldn = pd->n; | ||
| 2873 | } | ||
| 2874 | |||
| 2875 | if (!write_ptable_file(pd)) | ||
| 2876 | fprintf(stderr, "Error writing ptable file\n"); | ||
| 2877 | |||
| 2878 | pd->generated = true; | ||
| 2879 | } | ||
| 2880 | |||
| 2881 | Cube | ||
| 2882 | inverse_cube(Cube cube) | ||
| 2883 | { | ||
| 2884 | CubeArray *arr = new_cubearray(cube, pf_all); | ||
| 2885 | CubeArray *inv = new_cubearray((Cube){0}, pf_all); | ||
| 2886 | Cube ret; | ||
| 2887 | int i; | ||
| 2888 | |||
| 2889 | for (i = 0; i < 12; i++) { | ||
| 2890 | inv->ep[arr->ep[i]] = i; | ||
| 2891 | inv->eofb[arr->ep[i]] = arr->eofb[i]; | ||
| 2892 | inv->eorl[arr->ep[i]] = arr->eorl[i]; | ||
| 2893 | inv->eoud[arr->ep[i]] = arr->eoud[i]; | ||
| 2894 | } | ||
| 2895 | |||
| 2896 | for (i = 0; i < 8; i++) { | ||
| 2897 | inv->cp[arr->cp[i]] = i; | ||
| 2898 | inv->coud[arr->cp[i]] = (3 - arr->coud[i]) % 3; | ||
| 2899 | inv->corl[arr->cp[i]] = (3 - arr->corl[i]) % 3; | ||
| 2900 | inv->cofb[arr->cp[i]] = (3 - arr->cofb[i]) % 3; | ||
| 2901 | } | ||
| 2902 | |||
| 2903 | for (int i = 0; i < 6; i++) | ||
| 2904 | inv->cpos[arr->cpos[i]] = i; | ||
| 2905 | |||
| 2906 | ret = arrays_to_cube(inv, pf_all); | ||
| 2907 | free_cubearray(arr, pf_all); | ||
| 2908 | free_cubearray(inv, pf_all); | ||
| 2909 | |||
| 2910 | return ret; | ||
| 2911 | } | ||
| 2912 | |||
| 2913 | Move | ||
| 2914 | inverse_move(Move m) | ||
| 2915 | { | ||
| 2916 | return inverse_move_aux[m]; | ||
| 2917 | } | ||
| 2918 | |||
| 2919 | Trans | ||
| 2920 | inverse_trans(Trans t) | ||
| 2921 | { | ||
| 2922 | return inverse_trans_aux[t]; | ||
| 2923 | } | ||
| 2924 | |||
| 2925 | bool | ||
| 2926 | is_admissible(Cube cube) | ||
| 2927 | { | ||
| 2928 | /* TODO: this should check consistency of different orientations */ | ||
| 2929 | /* TODO: check that centers are opposite and admissible */ | ||
| 2930 | |||
| 2931 | CubeArray *a = new_cubearray(cube, pf_all); | ||
| 2932 | int parity; | ||
| 2933 | bool perm; | ||
| 2934 | |||
| 2935 | perm = is_perm(a->ep, 12) && | ||
| 2936 | is_perm(a->cp, 8) && | ||
| 2937 | is_perm(a->cpos, 6); | ||
| 2938 | parity = perm_sign(a->ep, 12) + | ||
| 2939 | perm_sign(a->cp, 8) + | ||
| 2940 | perm_sign(a->cpos, 6); | ||
| 2941 | |||
| 2942 | return perm && parity % 2 == 0; | ||
| 2943 | } | ||
| 2944 | |||
| 2945 | bool | ||
| 2946 | is_solved(Cube cube, bool reorient) | ||
| 2947 | { | ||
| 2948 | int i; | ||
| 2949 | |||
| 2950 | if (reorient) { | ||
| 2951 | for (i = 0; i < NROTATIONS; i++) | ||
| 2952 | if (is_solved(apply_alg(rotation_algs[i], cube),false)) | ||
| 2953 | return true; | ||
| 2954 | return false; | ||
| 2955 | } else { | ||
| 2956 | return equal(cube, (Cube){0}); | ||
| 2957 | } | ||
| 2958 | } | ||
| 2959 | |||
| 2960 | bool | ||
| 2961 | is_solved_block(Cube cube, Block block) | ||
| 2962 | { | ||
| 2963 | int i; | ||
| 2964 | |||
| 2965 | for (i = 0; i < 12; i++) | ||
| 2966 | if (block.edge[i] && !is_solved_edge(cube, i)) | ||
| 2967 | return false; | ||
| 2968 | for (i = 0; i < 8; i++) | ||
| 2969 | if (block.corner[i] && !is_solved_corner(cube, i)) | ||
| 2970 | return false; | ||
| 2971 | for (i = 0; i < 6; i++) | ||
| 2972 | if (block.center[i] && !is_solved_center(cube, i)) | ||
| 2973 | return false; | ||
| 2974 | |||
| 2975 | return true; | ||
| 2976 | } | ||
| 2977 | |||
| 2978 | bool | ||
| 2979 | is_solved_center(Cube cube, Center c) | ||
| 2980 | { | ||
| 2981 | return what_center_at(cube, c) == c; | ||
| 2982 | } | ||
| 2983 | |||
| 2984 | bool | ||
| 2985 | is_solved_corner(Cube cube, Corner c) | ||
| 2986 | { | ||
| 2987 | return what_corner_at(cube, c) == c && | ||
| 2988 | what_orientation_corner(cube.coud, c); | ||
| 2989 | } | ||
| 2990 | |||
| 2991 | bool | ||
| 2992 | is_solved_edge(Cube cube, Edge e) | ||
| 2993 | { | ||
| 2994 | return what_edge_at(cube, e) == e && | ||
| 2995 | what_orientation_edge(cube.eofb, e); | ||
| 2996 | } | ||
| 2997 | |||
| 2998 | int | ||
| 2999 | piece_orientation(Cube cube, int piece, char *orientation) | ||
| 3000 | { | ||
| 3001 | int arr[12], n, b, x; | ||
| 3002 | |||
| 3003 | if (!strcmp(orientation, "eofb")) { | ||
| 3004 | x = cube.eofb; | ||
| 3005 | n = 12; | ||
| 3006 | b = 2; | ||
| 3007 | } else if (!strcmp(orientation, "eorl")) { | ||
| 3008 | x = cube.eorl; | ||
| 3009 | n = 12; | ||
| 3010 | b = 2; | ||
| 3011 | } else if (!strcmp(orientation, "eoud")) { | ||
| 3012 | x = cube.eoud; | ||
| 3013 | n = 12; | ||
| 3014 | b = 2; | ||
| 3015 | } else if (!strcmp(orientation, "coud")) { | ||
| 3016 | x = cube.coud; | ||
| 3017 | n = 8; | ||
| 3018 | b = 3; | ||
| 3019 | } else if (!strcmp(orientation, "corl")) { | ||
| 3020 | x = cube.corl; | ||
| 3021 | n = 8; | ||
| 3022 | b = 3; | ||
| 3023 | } else if (!strcmp(orientation, "cofb")) { | ||
| 3024 | x = cube.cofb; | ||
| 3025 | n = 8; | ||
| 3026 | b = 3; | ||
| 3027 | } else { | ||
| 3028 | return -1; | ||
| 3029 | } | ||
| 3030 | |||
| 3031 | int_to_sum_zero_array(x, b, n, arr); | ||
| 3032 | if (piece < n) | ||
| 3033 | return arr[piece]; | ||
| 3034 | |||
| 3035 | return -1; | ||
| 3036 | } | ||
| 3037 | |||
| 3038 | void | ||
| 3039 | print_cube(Cube cube) | ||
| 3040 | { | ||
| 3041 | /* | ||
| 3042 | CubeArray *arr = new_cubearray(cube, pf_all); | ||
| 3043 | |||
| 3044 | for (int i = 0; i < 12; i++) | ||
| 3045 | printf(" %s ", edge_string[arr->ep[i]]); | ||
| 3046 | printf("\n"); | ||
| 3047 | |||
| 3048 | for (int i = 0; i < 12; i++) | ||
| 3049 | printf(" %c ", arr->eofb[i] + '0'); | ||
| 3050 | printf("\n"); | ||
| 3051 | |||
| 3052 | for (int i = 0; i < 8; i++) | ||
| 3053 | printf("%s ", corner_string[arr->cp[i]]); | ||
| 3054 | printf("\n"); | ||
| 3055 | |||
| 3056 | for (int i = 0; i < 8; i++) | ||
| 3057 | printf(" %c ", arr->coud[i] + '0'); | ||
| 3058 | printf("\n"); | ||
| 3059 | |||
| 3060 | for (int i = 0; i < 6; i++) | ||
| 3061 | printf(" %s ", center_string[arr->cpos[i]]); | ||
| 3062 | printf("\n"); | ||
| 3063 | |||
| 3064 | free_cubearray(arr, pf_all); | ||
| 3065 | */ | ||
| 3066 | |||
| 3067 | for (int i = 0; i < 12; i++) | ||
| 3068 | printf(" %s ", edge_string[what_edge_at(cube, i)]); | ||
| 3069 | printf("\n"); | ||
| 3070 | |||
| 3071 | for (int i = 0; i < 12; i++) | ||
| 3072 | printf(" %d ", what_orientation_edge(cube.eofb, i)); | ||
| 3073 | printf("\n"); | ||
| 3074 | |||
| 3075 | for (int i = 0; i < 8; i++) | ||
| 3076 | printf("%s ", corner_string[what_corner_at(cube, i)]); | ||
| 3077 | printf("\n"); | ||
| 3078 | |||
| 3079 | for (int i = 0; i < 8; i++) | ||
| 3080 | printf(" %d ", what_orientation_corner(cube.coud, i)); | ||
| 3081 | printf("\n"); | ||
| 3082 | |||
| 3083 | for (int i = 0; i < 6; i++) | ||
| 3084 | printf(" %s ", center_string[what_center_at(cube, i)]); | ||
| 3085 | printf("\n"); | ||
| 3086 | |||
| 3087 | } | ||
| 3088 | |||
| 3089 | Cube | ||
| 3090 | random_cube() | ||
| 3091 | { | ||
| 3092 | CubeArray *arr = new_cubearray((Cube){0}, pf_4val); | ||
| 3093 | Cube ret; | ||
| 3094 | int ep, cp, eo, co; | ||
| 3095 | |||
| 3096 | ep = rand() % FACTORIAL12; | ||
| 3097 | cp = rand() % FACTORIAL8; | ||
| 3098 | eo = rand() % POW2TO11; | ||
| 3099 | co = rand() % POW3TO7; | ||
| 3100 | |||
| 3101 | index_to_perm(ep, 12, arr->ep); | ||
| 3102 | index_to_perm(cp, 8, arr->cp); | ||
| 3103 | int_to_sum_zero_array(eo, 2, 12, arr->eofb); | ||
| 3104 | int_to_sum_zero_array(co, 3, 8, arr->coud); | ||
| 3105 | |||
| 3106 | if (perm_sign(arr->ep, 12) != perm_sign(arr->cp, 8)) | ||
| 3107 | swap(&(arr->ep[0]), &(arr->ep[1])); | ||
| 3108 | |||
| 3109 | ret = arrays_to_cube(arr, pf_4val); | ||
| 3110 | free_cubearray(arr, pf_4val); | ||
| 3111 | |||
| 3112 | return ret; | ||
| 3113 | } | ||
| 3114 | |||
| 3115 | /* TODO: clean pre_trans or put it back */ | ||
| 3116 | AlgList * | ||
| 3117 | solve(Cube cube, Step step, SolveOptions *opts) | ||
| 3118 | { | ||
| 3119 | /*AlgListNode *node;*/ | ||
| 3120 | AlgList *sols = new_alglist(); | ||
| 3121 | /*Cube c = apply_trans(opts->pre_trans, cube);*/ | ||
| 3122 | DfsData dd = { | ||
| 3123 | .m = 0, | ||
| 3124 | .niss = false, | ||
| 3125 | .lb = -1, | ||
| 3126 | .last1 = NULLMOVE, | ||
| 3127 | .last2 = NULLMOVE, | ||
| 3128 | .sols = sols, | ||
| 3129 | .current_alg = new_alg("") | ||
| 3130 | }; | ||
| 3131 | |||
| 3132 | if (step.ready != NULL && !step.ready(cube)) { | ||
| 3133 | fprintf(stderr, "Cube not ready for solving step\n"); | ||
| 3134 | return sols; | ||
| 3135 | } | ||
| 3136 | |||
| 3137 | moveset_to_list(step.moveset, step.estimate, dd.sorted_moves); | ||
| 3138 | movelist_to_position(dd.sorted_moves, dd.move_position); | ||
| 3139 | |||
| 3140 | for (dd.d = opts->min_moves; | ||
| 3141 | dd.d <= opts->max_moves && !(sols->len && opts->optimal_only); | ||
| 3142 | dd.d++) { | ||
| 3143 | if (opts->feedback) | ||
| 3144 | fprintf(stderr, | ||
| 3145 | "Found %d solutions, searching depth %d...\n", | ||
| 3146 | sols->len, dd.d); | ||
| 3147 | dfs(cube, step, opts, &dd); | ||
| 3148 | } | ||
| 3149 | |||
| 3150 | /* | ||
| 3151 | for (node = sols->first; node != NULL; node = node->next) | ||
| 3152 | transform_alg(inverse_trans(opts->pre_trans), node->alg); | ||
| 3153 | */ | ||
| 3154 | |||
| 3155 | free_alg(dd.current_alg); | ||
| 3156 | return sols; | ||
| 3157 | } | ||
| 3158 | |||
| 3159 | Alg * | ||
| 3160 | inverse_alg(Alg *alg) | ||
| 3161 | { | ||
| 3162 | Alg *ret = new_alg(""); | ||
| 3163 | int i; | ||
| 3164 | |||
| 3165 | for (i = alg->len-1; i >= 0; i--) | ||
| 3166 | append_move(ret, inverse_move(alg->move[i]), alg->inv[i]); | ||
| 3167 | |||
| 3168 | return ret; | ||
| 3169 | } | ||
| 3170 | |||
| 3171 | Alg * | ||
| 3172 | new_alg(char *str) | ||
| 3173 | { | ||
| 3174 | Alg *alg = malloc(sizeof(Alg)); | ||
| 3175 | int i; | ||
| 3176 | bool niss = false; | ||
| 3177 | Move j, m; | ||
| 3178 | |||
| 3179 | alg->move = malloc(30 * sizeof(Move)); | ||
| 3180 | alg->inv = malloc(30 * sizeof(bool)); | ||
| 3181 | alg->allocated = 30; | ||
| 3182 | alg->len = 0; | ||
| 3183 | |||
| 3184 | for (i = 0; str[i]; i++) { | ||
| 3185 | if (str[i] == ' ' || str[i] == '\t' || str[i] == '\n') | ||
| 3186 | continue; | ||
| 3187 | |||
| 3188 | if (str[i] == '(' && niss) { | ||
| 3189 | fprintf(stderr, "Error reading moves: nested ( )\n"); | ||
| 3190 | return alg; | ||
| 3191 | } | ||
| 3192 | |||
| 3193 | if (str[i] == ')' && !niss) { | ||
| 3194 | fprintf(stderr, "Error reading moves: unmatched )\n"); | ||
| 3195 | return alg; | ||
| 3196 | } | ||
| 3197 | |||
| 3198 | if (str[i] == '(' || str[i] == ')') { | ||
| 3199 | niss = !niss; | ||
| 3200 | continue; | ||
| 3201 | } | ||
| 3202 | |||
| 3203 | for (j = 0; j < NMOVES; j++) { | ||
| 3204 | if (str[i] == move_string[j][0]) { | ||
| 3205 | m = j; | ||
| 3206 | if (m <= B && str[i+1]=='w') { | ||
| 3207 | m += Uw - U; | ||
| 3208 | i++; | ||
| 3209 | } | ||
| 3210 | if (str[i+1]=='2') { | ||
| 3211 | m += 1; | ||
| 3212 | i++; | ||
| 3213 | } else if (str[i+1]=='\'' || str[i+1]=='3') { | ||
| 3214 | m += 2; | ||
| 3215 | i++; | ||
| 3216 | } | ||
| 3217 | append_move(alg, m, niss); | ||
| 3218 | break; | ||
| 3219 | } | ||
| 3220 | } | ||
| 3221 | } | ||
| 3222 | |||
| 3223 | return alg; | ||
| 3224 | } | ||
| 3225 | |||
| 3226 | Alg * | ||
| 3227 | on_inverse(Alg *alg) | ||
| 3228 | { | ||
| 3229 | Alg *ret = new_alg(""); | ||
| 3230 | int i; | ||
| 3231 | |||
| 3232 | for (i = 0; i < alg->len; i++) | ||
| 3233 | append_move(ret, alg->move[i], !alg->inv[i]); | ||
| 3234 | |||
| 3235 | return ret; | ||
| 3236 | } | ||
| 3237 | |||
| 3238 | void | ||
| 3239 | print_alg(Alg *alg, bool l) | ||
| 3240 | { | ||
| 3241 | /* TODO: make it possible to print to stdout or to string */ | ||
| 3242 | /* Maybe just return a string */ | ||
| 3243 | char fill[4]; | ||
| 3244 | int i; | ||
| 3245 | bool niss = false; | ||
| 3246 | |||
| 3247 | for (i = 0; i < alg->len; i++) { | ||
| 3248 | if (!niss && alg->inv[i]) | ||
| 3249 | strcpy(fill, i == 0 ? "(" : " ("); | ||
| 3250 | if (niss && !alg->inv[i]) | ||
| 3251 | strcpy(fill, ") "); | ||
| 3252 | if (niss == alg->inv[i]) | ||
| 3253 | strcpy(fill, i == 0 ? "" : " "); | ||
| 3254 | |||
| 3255 | printf("%s%s", fill, move_string[alg->move[i]]); | ||
| 3256 | niss = alg->inv[i]; | ||
| 3257 | } | ||
| 3258 | |||
| 3259 | if (niss) | ||
| 3260 | printf(")"); | ||
| 3261 | if (l) | ||
| 3262 | printf(" (%d)", alg->len); | ||
| 3263 | |||
| 3264 | printf("\n"); | ||
| 3265 | } | ||
| 3266 | |||
| 3267 | void | ||
| 3268 | print_alglist(AlgList *al, bool l) | ||
| 3269 | { | ||
| 3270 | AlgListNode *i; | ||
| 3271 | |||
| 3272 | for (i = al->first; i != NULL; i = i->next) | ||
| 3273 | print_alg(i->alg, l); | ||
| 3274 | } | ||
| 3275 | |||
| 3276 | void | ||
| 3277 | print_ptable(PruneData *pd) | ||
| 3278 | { | ||
| 3279 | uint64_t i, a[16]; | ||
| 3280 | |||
| 3281 | for (i = 0; i < 16; i++) | ||
| 3282 | a[i] = 0; | ||
| 3283 | |||
| 3284 | if (!pd->generated) | ||
| 3285 | genptable(pd); | ||
| 3286 | |||
| 3287 | for (i = 0; i < pd->coord->max; i++) | ||
| 3288 | a[ptableval(pd, pd->coord->cube(i))]++; | ||
| 3289 | |||
| 3290 | fprintf(stderr, "Values for table %s\n", pd->filename); | ||
| 3291 | for (i = 0; i < 16; i++) | ||
| 3292 | printf("%2lu\t%10lu\n", i, a[i]); | ||
| 3293 | } | ||
| 3294 | |||
| 3295 | uint64_t | ||
| 3296 | ptablesize(PruneData *pd) | ||
| 3297 | { | ||
| 3298 | return (pd->coord->max + 1) / 2; | ||
| 3299 | } | ||
| 3300 | |||
| 3301 | int | ||
| 3302 | ptableval(PruneData *pd, Cube cube) | ||
| 3303 | { | ||
| 3304 | uint64_t ind = pd->coord->index(cube); | ||
| 3305 | |||
| 3306 | return (ind % 2) ? pd->ptable[ind/2] / 16 : pd->ptable[ind/2] % 16; | ||
| 3307 | } | ||
| 3308 | |||
| 3309 | |||
| 3310 | Alg * | ||
| 3311 | rotation_alg(Trans i) | ||
| 3312 | { | ||
| 3313 | return rotation_algs[i % NROTATIONS]; | ||
| 3314 | } | ||
| 3315 | |||
| 3316 | void | ||
| 3317 | transform_alg(Trans t, Alg *alg) | ||
| 3318 | { | ||
| 3319 | int i; | ||
| 3320 | |||
| 3321 | for (i = 0; i < alg->len; i++) | ||
| 3322 | alg->move[i] = moves_ttable[t][alg->move[i]]; | ||
| 3323 | } | ||
| 3324 | |||
| 3325 | Center | ||
| 3326 | what_center_at(Cube cube, Center c) | ||
| 3327 | { | ||
| 3328 | return what_center_at_aux[cube.cpos][c]; | ||
| 3329 | } | ||
| 3330 | |||
| 3331 | Corner | ||
| 3332 | what_corner_at(Cube cube, Corner c) | ||
| 3333 | { | ||
| 3334 | return what_corner_at_aux[cube.cp][c]; | ||
| 3335 | } | ||
| 3336 | |||
| 3337 | Edge | ||
| 3338 | what_edge_at(Cube cube, Edge e) | ||
| 3339 | { | ||
| 3340 | Edge ret; | ||
| 3341 | CubeArray *arr = new_cubearray(cube, pf_ep); | ||
| 3342 | |||
| 3343 | ret = arr->ep[e]; | ||
| 3344 | |||
| 3345 | free_cubearray(arr, pf_ep); | ||
| 3346 | return ret; | ||
| 3347 | } | ||
| 3348 | |||
| 3349 | int | ||
| 3350 | what_orientation_corner(int co, Corner c) | ||
| 3351 | { | ||
| 3352 | if (c < 7) | ||
| 3353 | return (co / powint(3, c)) % 3; | ||
| 3354 | else | ||
| 3355 | return what_orientation_last_corner_aux[co]; | ||
| 3356 | } | ||
| 3357 | |||
| 3358 | int | ||
| 3359 | what_orientation_edge(int eo, Edge e) | ||
| 3360 | { | ||
| 3361 | if (e < 11) | ||
| 3362 | return (eo & (1 << e)) ? 1 : 0; | ||
| 3363 | else | ||
| 3364 | return what_orientation_last_edge_aux[eo]; | ||
| 3365 | } | ||
| 3366 | |||
| 3367 | Center | ||
| 3368 | where_is_center(Cube cube, Center c) | ||
| 3369 | { | ||
| 3370 | return where_is_center_aux[cube.cpos][c]; | ||
| 3371 | } | ||
| 3372 | |||
| 3373 | Corner | ||
| 3374 | where_is_corner(Cube cube, Corner c) | ||
| 3375 | { | ||
| 3376 | return where_is_corner_aux[cube.cp][c]; | ||
| 3377 | } | ||
| 3378 | |||
| 3379 | |||
| 3380 | void | ||
| 3381 | init() | ||
| 3382 | { | ||
| 3383 | /* Order is important! */ | ||
| 3384 | init_environment(); | ||
| 3385 | init_strings(); | ||
| 3386 | init_moves_aux(); | ||
| 3387 | init_moves(); | ||
| 3388 | init_auxtables(); | ||
| 3389 | init_cphtr_cosets(); | ||
| 3390 | init_trans_aux(); | ||
| 3391 | init_trans(); | ||
| 3392 | init_symdata(); | ||
| 3393 | } | ||
| 3394 | |||
diff --git a/old/2021-07-02-genptable-dfs/cube.h b/old/2021-07-02-genptable-dfs/cube.h new file mode 100644 index 0000000..ffbcd86 --- /dev/null +++ b/old/2021-07-02-genptable-dfs/cube.h | |||
| @@ -0,0 +1,90 @@ | |||
| 1 | #ifndef CUBE_H | ||
| 2 | #define CUBE_H | ||
| 3 | |||
| 4 | #include <stdio.h> | ||
| 5 | #include <stdbool.h> | ||
| 6 | #include <stdint.h> | ||
| 7 | #include <stdlib.h> | ||
| 8 | #include <string.h> | ||
| 9 | #include <time.h> | ||
| 10 | #include <unistd.h> | ||
| 11 | #include <sys/stat.h> | ||
| 12 | |||
| 13 | #include "macros.h" | ||
| 14 | #include "cubetypes.h" | ||
| 15 | |||
| 16 | extern Coordinate coord_eofb; | ||
| 17 | extern Coordinate coord_eofbepos; | ||
| 18 | extern Coordinate coord_coud; | ||
| 19 | extern Coordinate coord_corners; | ||
| 20 | extern Coordinate coord_cornershtr; | ||
| 21 | extern Coordinate coord_drud; | ||
| 22 | extern Coordinate coord_coud_sym16; | ||
| 23 | extern Coordinate coord_eofbepos_sym16; | ||
| 24 | extern Coordinate coord_drud_sym16; | ||
| 25 | extern Coordinate coord_khuge; | ||
| 26 | |||
| 27 | Cube apply_alg(Alg *alg, Cube cube); | ||
| 28 | Cube apply_move(Move m, Cube cube); | ||
| 29 | Cube apply_trans(Trans t, Cube cube); | ||
| 30 | bool block_solved(Cube cube, Block); | ||
| 31 | Cube compose(Cube c2, Cube c1); /* Use c2 as an alg on c1 */ | ||
| 32 | uint64_t cphtr(Cube cube); /* TODO: rename (something with cosets) */ | ||
| 33 | Cube anti_cphtr(uint64_t ind); /*TODO also this */ | ||
| 34 | uint64_t epos_dependent(Cube cube); /* TODO: rename and turn into an indexer */ | ||
| 35 | bool equal(Cube c1, Cube c2); | ||
| 36 | Cube inverse_cube(Cube cube); | ||
| 37 | Move inverse_move(Move m); | ||
| 38 | Trans inverse_trans(Trans t); | ||
| 39 | bool is_admissible(Cube cube); | ||
| 40 | bool is_solved(Cube cube, bool reorient); | ||
| 41 | bool is_solved_center(Cube cube, Center c); | ||
| 42 | bool is_solved_corner(Cube cube, Corner c); | ||
| 43 | bool is_solved_edge(Cube cube, Edge e); | ||
| 44 | void print_cube(Cube cube); | ||
| 45 | Cube random_cube(); | ||
| 46 | AlgList * solve(Cube cube, Step step, SolveOptions *opts); | ||
| 47 | Center what_center_at(Cube cube, Center c); | ||
| 48 | Corner what_corner_at(Cube cube, Corner c); | ||
| 49 | Edge what_edge_at(Cube cube, Edge e); | ||
| 50 | int what_orientation_corner(int co, Corner c); | ||
| 51 | int what_orientation_edge(int eo, Edge e); | ||
| 52 | Center where_is_center(Cube cube, Center c); | ||
| 53 | Corner where_is_corner(Cube cube, Corner c); | ||
| 54 | Edge where_is_edge(Cube cube, Edge e); | ||
| 55 | |||
| 56 | bool check_centers(Cube cube); | ||
| 57 | bool check_corners(Cube cube); | ||
| 58 | bool check_cornershtr(Cube cube); | ||
| 59 | bool check_coud(Cube cube); | ||
| 60 | bool check_drud(Cube cube); | ||
| 61 | bool check_eofb(Cube cube); | ||
| 62 | bool check_eofbepos(Cube cube); | ||
| 63 | bool check_epose(Cube cube); | ||
| 64 | bool check_ep(Cube cube); | ||
| 65 | bool check_khuge(Cube cube); | ||
| 66 | bool check_nothing(Cube cube); | ||
| 67 | |||
| 68 | bool moveset_HTM(Move m); | ||
| 69 | bool moveset_URF(Move m); | ||
| 70 | |||
| 71 | Move base_move(Move m); | ||
| 72 | void free_alg(Alg *alg); | ||
| 73 | void free_alglist(AlgList *l); | ||
| 74 | Alg * inverse_alg(Alg *alg); | ||
| 75 | Alg * new_alg(char *str); | ||
| 76 | Alg * on_inverse(Alg *alg); | ||
| 77 | void print_alg(Alg *alg, bool l); | ||
| 78 | void print_alglist(AlgList *al, bool l); | ||
| 79 | Alg * rotation_alg(Trans i); | ||
| 80 | void transform_alg(Trans t, Alg *alg); | ||
| 81 | |||
| 82 | void genptable(PruneData *pd); | ||
| 83 | void print_ptable(PruneData *pd); | ||
| 84 | uint64_t ptablesize(PruneData *pd); | ||
| 85 | int ptableval(PruneData *pd, Cube cube); | ||
| 86 | |||
| 87 | void init(); | ||
| 88 | |||
| 89 | #endif | ||
| 90 | |||
diff --git a/old/2021-07-02-genptable-dfs/cubetypes.h b/old/2021-07-02-genptable-dfs/cubetypes.h new file mode 100644 index 0000000..a324985 --- /dev/null +++ b/old/2021-07-02-genptable-dfs/cubetypes.h | |||
| @@ -0,0 +1,250 @@ | |||
| 1 | #ifndef CUBETYPES_H | ||
| 2 | #define CUBETYPES_H | ||
| 3 | |||
| 4 | /* Typedefs ******************************************************************/ | ||
| 5 | |||
| 6 | typedef enum center Center; | ||
| 7 | typedef enum corner Corner; | ||
| 8 | typedef enum edge Edge; | ||
| 9 | typedef enum move Move; | ||
| 10 | typedef enum trans Trans; | ||
| 11 | |||
| 12 | typedef struct alg Alg; | ||
| 13 | typedef struct alglist AlgList; | ||
| 14 | typedef struct alglistnode AlgListNode; | ||
| 15 | typedef struct block Block; | ||
| 16 | typedef struct coordinate Coordinate; | ||
| 17 | typedef struct cube Cube; | ||
| 18 | typedef struct cubearray CubeArray; | ||
| 19 | typedef struct cubetarget CubeTarget; | ||
| 20 | typedef struct dfsdata DfsData; | ||
| 21 | typedef struct piecefilter PieceFilter; | ||
| 22 | typedef struct prunedata PruneData; | ||
| 23 | typedef struct solveoptions SolveOptions; | ||
| 24 | typedef struct step Step; | ||
| 25 | typedef struct symdata SymData; | ||
| 26 | |||
| 27 | typedef Cube (*AntiIndexer) (uint64_t); | ||
| 28 | typedef bool (*Checker) (Cube); | ||
| 29 | typedef int (*Estimator) (CubeTarget); | ||
| 30 | typedef uint64_t (*Indexer) (Cube); | ||
| 31 | typedef bool (*Moveset) (Move); | ||
| 32 | |||
| 33 | |||
| 34 | /* Enums *********************************************************************/ | ||
| 35 | |||
| 36 | enum | ||
| 37 | center | ||
| 38 | { | ||
| 39 | U_center, D_center, | ||
| 40 | R_center, L_center, | ||
| 41 | F_center, B_center | ||
| 42 | }; | ||
| 43 | |||
| 44 | enum | ||
| 45 | corner | ||
| 46 | { | ||
| 47 | UFR, UFL, UBL, UBR, | ||
| 48 | DFR, DFL, DBL, DBR | ||
| 49 | }; | ||
| 50 | |||
| 51 | enum | ||
| 52 | edge | ||
| 53 | { | ||
| 54 | UF, UL, UB, UR, | ||
| 55 | DF, DL, DB, DR, | ||
| 56 | FR, FL, BL, BR | ||
| 57 | }; | ||
| 58 | |||
| 59 | enum | ||
| 60 | move | ||
| 61 | { | ||
| 62 | NULLMOVE, | ||
| 63 | U, U2, U3, D, D2, D3, | ||
| 64 | R, R2, R3, L, L2, L3, | ||
| 65 | F, F2, F3, B, B2, B3, | ||
| 66 | Uw, Uw2, Uw3, Dw, Dw2, Dw3, | ||
| 67 | Rw, Rw2, Rw3, Lw, Lw2, Lw3, | ||
| 68 | Fw, Fw2, Fw3, Bw, Bw2, Bw3, | ||
| 69 | M, M2, M3, | ||
| 70 | S, S2, S3, | ||
| 71 | E, E2, E3, | ||
| 72 | x, x2, x3, | ||
| 73 | y, y2, y3, | ||
| 74 | z, z2, z3, | ||
| 75 | }; | ||
| 76 | |||
| 77 | enum | ||
| 78 | trans | ||
| 79 | { | ||
| 80 | uf, ur, ub, ul, | ||
| 81 | df, dr, db, dl, | ||
| 82 | rf, rd, rb, ru, | ||
| 83 | lf, ld, lb, lu, | ||
| 84 | fu, fr, fd, fl, | ||
| 85 | bu, br, bd, bl, | ||
| 86 | uf_mirror, ur_mirror, ub_mirror, ul_mirror, | ||
| 87 | df_mirror, dr_mirror, db_mirror, dl_mirror, | ||
| 88 | rf_mirror, rd_mirror, rb_mirror, ru_mirror, | ||
| 89 | lf_mirror, ld_mirror, lb_mirror, lu_mirror, | ||
| 90 | fu_mirror, fr_mirror, fd_mirror, fl_mirror, | ||
| 91 | bu_mirror, br_mirror, bd_mirror, bl_mirror, | ||
| 92 | }; | ||
| 93 | |||
| 94 | |||
| 95 | /* Structs *******************************************************************/ | ||
| 96 | |||
| 97 | struct | ||
| 98 | alg | ||
| 99 | { | ||
| 100 | Move * move; | ||
| 101 | bool * inv; | ||
| 102 | int len; | ||
| 103 | int allocated; | ||
| 104 | }; | ||
| 105 | |||
| 106 | struct | ||
| 107 | alglist | ||
| 108 | { | ||
| 109 | AlgListNode * first; | ||
| 110 | AlgListNode * last; | ||
| 111 | int len; | ||
| 112 | }; | ||
| 113 | |||
| 114 | struct | ||
| 115 | alglistnode | ||
| 116 | { | ||
| 117 | Alg * alg; | ||
| 118 | AlgListNode * next; | ||
| 119 | }; | ||
| 120 | |||
| 121 | struct | ||
| 122 | block | ||
| 123 | { | ||
| 124 | bool edge[12]; | ||
| 125 | bool corner[8]; | ||
| 126 | bool center[6]; | ||
| 127 | }; | ||
| 128 | |||
| 129 | struct | ||
| 130 | coordinate | ||
| 131 | { | ||
| 132 | Indexer index; | ||
| 133 | AntiIndexer cube; | ||
| 134 | Checker check; | ||
| 135 | uint64_t max; | ||
| 136 | }; | ||
| 137 | |||
| 138 | struct | ||
| 139 | cube | ||
| 140 | { | ||
| 141 | int epose; | ||
| 142 | int eposs; | ||
| 143 | int eposm; | ||
| 144 | int eofb; | ||
| 145 | int eorl; | ||
| 146 | int eoud; | ||
| 147 | int cp; | ||
| 148 | int coud; | ||
| 149 | int cofb; | ||
| 150 | int corl; | ||
| 151 | int cpos; | ||
| 152 | }; | ||
| 153 | |||
| 154 | struct | ||
| 155 | cubearray | ||
| 156 | { | ||
| 157 | int * ep; | ||
| 158 | int * eofb; | ||
| 159 | int * eorl; | ||
| 160 | int * eoud; | ||
| 161 | int * cp; | ||
| 162 | int * coud; | ||
| 163 | int * corl; | ||
| 164 | int * cofb; | ||
| 165 | int * cpos; | ||
| 166 | }; | ||
| 167 | |||
| 168 | struct | ||
| 169 | cubetarget | ||
| 170 | { | ||
| 171 | Cube cube; | ||
| 172 | int target; | ||
| 173 | }; | ||
| 174 | |||
| 175 | struct | ||
| 176 | dfsdata | ||
| 177 | { | ||
| 178 | int d; | ||
| 179 | int m; | ||
| 180 | int lb; | ||
| 181 | bool niss; | ||
| 182 | Move last1; | ||
| 183 | Move last2; | ||
| 184 | AlgList * sols; | ||
| 185 | Alg * current_alg; | ||
| 186 | Move sorted_moves[NMOVES]; | ||
| 187 | int move_position[NMOVES]; | ||
| 188 | }; | ||
| 189 | |||
| 190 | struct | ||
| 191 | piecefilter | ||
| 192 | { | ||
| 193 | bool epose; | ||
| 194 | bool eposs; | ||
| 195 | bool eposm; | ||
| 196 | bool eofb; | ||
| 197 | bool eorl; | ||
| 198 | bool eoud; | ||
| 199 | bool cp; | ||
| 200 | bool coud; | ||
| 201 | bool cofb; | ||
| 202 | bool corl; | ||
| 203 | bool cpos; | ||
| 204 | }; | ||
| 205 | |||
| 206 | struct | ||
| 207 | prunedata | ||
| 208 | { | ||
| 209 | char * filename; | ||
| 210 | uint8_t * ptable; | ||
| 211 | bool generated; | ||
| 212 | uint64_t n; | ||
| 213 | Coordinate * coord; | ||
| 214 | Moveset moveset; | ||
| 215 | }; | ||
| 216 | |||
| 217 | struct | ||
| 218 | solveoptions | ||
| 219 | { | ||
| 220 | int min_moves; | ||
| 221 | int max_moves; | ||
| 222 | int max_solutions; | ||
| 223 | bool optimal_only; | ||
| 224 | bool can_niss; | ||
| 225 | bool feedback; | ||
| 226 | }; | ||
| 227 | |||
| 228 | struct | ||
| 229 | step | ||
| 230 | { | ||
| 231 | Estimator estimate; | ||
| 232 | Checker ready; | ||
| 233 | Moveset moveset; | ||
| 234 | }; | ||
| 235 | |||
| 236 | struct | ||
| 237 | symdata | ||
| 238 | { | ||
| 239 | char * filename; | ||
| 240 | bool generated; | ||
| 241 | Coordinate * coord; | ||
| 242 | Coordinate * sym_coord; | ||
| 243 | int ntrans; | ||
| 244 | Trans * trans; | ||
| 245 | uint64_t * class; | ||
| 246 | Cube * rep; | ||
| 247 | Trans * transtorep; | ||
| 248 | }; | ||
| 249 | |||
| 250 | #endif | ||
diff --git a/old/2021-07-02-genptable-dfs/macros.h b/old/2021-07-02-genptable-dfs/macros.h new file mode 100644 index 0000000..af3bca1 --- /dev/null +++ b/old/2021-07-02-genptable-dfs/macros.h | |||
| @@ -0,0 +1,23 @@ | |||
| 1 | #ifndef MACROS_H | ||
| 2 | #define MACROS_H | ||
| 3 | |||
| 4 | #define POW2TO6 64ULL | ||
| 5 | #define POW2TO11 2048ULL | ||
| 6 | #define POW2TO12 4096ULL | ||
| 7 | #define POW3TO7 2187ULL | ||
| 8 | #define POW3TO8 6561ULL | ||
| 9 | #define FACTORIAL4 24ULL | ||
| 10 | #define FACTORIAL6 720ULL | ||
| 11 | #define FACTORIAL7 5040ULL | ||
| 12 | #define FACTORIAL8 40320ULL | ||
| 13 | #define FACTORIAL12 479001600ULL | ||
| 14 | #define BINOM12ON4 495ULL | ||
| 15 | #define BINOM8ON4 70ULL | ||
| 16 | #define MIN(a,b) (((a) < (b)) ? (a) : (b)) | ||
| 17 | #define MAX(a,b) (((a) > (b)) ? (a) : (b)) | ||
| 18 | |||
| 19 | #define NMOVES (z3+1) | ||
| 20 | #define NTRANS 48 | ||
| 21 | #define NROTATIONS 24 | ||
| 22 | |||
| 23 | #endif | ||
diff --git a/old/2021-07-02-genptable-dfs/main.c b/old/2021-07-02-genptable-dfs/main.c new file mode 100644 index 0000000..1ebd917 --- /dev/null +++ b/old/2021-07-02-genptable-dfs/main.c | |||
| @@ -0,0 +1,80 @@ | |||
| 1 | #include <stdio.h> | ||
| 2 | #include "cube.h" | ||
| 3 | #include "steps.h" | ||
| 4 | |||
| 5 | int main() { | ||
| 6 | Alg *algo; | ||
| 7 | AlgList *sols; | ||
| 8 | Cube cube; | ||
| 9 | SolveOptions opts; | ||
| 10 | char line[1000]; | ||
| 11 | int i, ns = 2; | ||
| 12 | /* Move m;*/ | ||
| 13 | /* int nrand = 10000, sum1, sum2, sum3;*/ | ||
| 14 | |||
| 15 | Step *stps[20] = {&drud_HTM, &optimal_HTM}; | ||
| 16 | char sss[30][30] = {"DR on UD", "Optimal solve"}; | ||
| 17 | |||
| 18 | opts = (SolveOptions) { | ||
| 19 | .min_moves = 0, | ||
| 20 | .max_moves = 20, | ||
| 21 | .optimal_only = true, | ||
| 22 | .max_solutions = 1, | ||
| 23 | .can_niss = false, | ||
| 24 | .feedback = true, | ||
| 25 | }; | ||
| 26 | |||
| 27 | init(); | ||
| 28 | |||
| 29 | /* | ||
| 30 | srand(time(NULL)); | ||
| 31 | sum1 = 0; | ||
| 32 | sum2 = 0; | ||
| 33 | sum3 = 0; | ||
| 34 | for (i = 0; i < nrand; i++) { | ||
| 35 | cube = random_cube(); | ||
| 36 | sum1 += drud_HTM.check(cube, 20); | ||
| 37 | sum2 += optimal_HTM.check(cube, 20); | ||
| 38 | sum3 += cornershtreofb_HTM.check(cube, 20); | ||
| 39 | } | ||
| 40 | printf("Average drud pruning: %lf\n", ((double)sum1) / ((double) nrand)); | ||
| 41 | printf("Average corners htr pruning: %lf\n", ((double)sum2) / ((double) nrand)); | ||
| 42 | printf("Average corners htr + eofb pruning: %lf\n", ((double)sum3) / ((double) nrand)); | ||
| 43 | */ | ||
| 44 | |||
| 45 | /* | ||
| 46 | for (m = U; m <= B3; m++) { | ||
| 47 | printf("Class eofbepos after %d: ", m); | ||
| 48 | printf("%lu\n", coord_khuge.index(apply_move(m,(Cube){0}))); | ||
| 49 | } | ||
| 50 | */ | ||
| 51 | |||
| 52 | printf("Welcome to nissy 2.0! Insert a scramble:\n"); | ||
| 53 | |||
| 54 | if (fgets(line, 1000, stdin) != NULL) { | ||
| 55 | algo = new_alg(line); | ||
| 56 | cube = apply_alg(algo, (Cube){0}); | ||
| 57 | |||
| 58 | print_alg(inverse_alg(algo), false); | ||
| 59 | /* | ||
| 60 | printf("After rb_mirror:\n"); | ||
| 61 | cube = apply_trans(rb_mirror, cube); | ||
| 62 | print_cube(cube); | ||
| 63 | printf("Going back:\n"); | ||
| 64 | cube = apply_trans(inverse_trans(rb_mirror), cube); | ||
| 65 | */ | ||
| 66 | |||
| 67 | print_cube(cube); | ||
| 68 | |||
| 69 | for (i = 0; i < ns; i++) { | ||
| 70 | sols = solve(cube, *stps[i], &opts); | ||
| 71 | printf("%s: %d solutions found:\n", sss[i], sols->len); | ||
| 72 | print_alglist(sols, true); | ||
| 73 | free_alglist(sols); | ||
| 74 | } | ||
| 75 | free_alg(algo); | ||
| 76 | } | ||
| 77 | |||
| 78 | return 0; | ||
| 79 | } | ||
| 80 | |||
diff --git a/old/2021-07-02-genptable-dfs/steps.c b/old/2021-07-02-genptable-dfs/steps.c new file mode 100644 index 0000000..91e7f00 --- /dev/null +++ b/old/2021-07-02-genptable-dfs/steps.c | |||
| @@ -0,0 +1,307 @@ | |||
| 1 | #include "steps.h" | ||
| 2 | |||
| 3 | /* Standard checkers (return lower bound) ************************************/ | ||
| 4 | |||
| 5 | static int estimate_eofb_HTM(CubeTarget ct); | ||
| 6 | static int estimate_coud_HTM(CubeTarget ct); | ||
| 7 | static int estimate_coud_URF(CubeTarget ct); | ||
| 8 | static int estimate_corners_HTM(CubeTarget ct); | ||
| 9 | static int estimate_cornershtr_HTM(CubeTarget ct); | ||
| 10 | static int estimate_corners_URF(CubeTarget ct); | ||
| 11 | static int estimate_cornershtr_URF(CubeTarget ct); | ||
| 12 | static int estimate_drud_HTM(CubeTarget ct); | ||
| 13 | static int estimate_optimal_HTM(CubeTarget ct); | ||
| 14 | |||
| 15 | /* Steps *********************************************************************/ | ||
| 16 | |||
| 17 | Step | ||
| 18 | eofb_HTM = { | ||
| 19 | .estimate = estimate_eofb_HTM, | ||
| 20 | .ready = check_centers, | ||
| 21 | .moveset = moveset_HTM | ||
| 22 | }; | ||
| 23 | |||
| 24 | Step | ||
| 25 | coud_HTM = { | ||
| 26 | .estimate = estimate_coud_HTM, | ||
| 27 | .ready = check_centers, | ||
| 28 | .moveset = moveset_HTM | ||
| 29 | }; | ||
| 30 | |||
| 31 | Step | ||
| 32 | coud_URF = { | ||
| 33 | .estimate = estimate_coud_URF, | ||
| 34 | .ready = check_nothing, | ||
| 35 | .moveset = moveset_URF | ||
| 36 | }; | ||
| 37 | |||
| 38 | Step | ||
| 39 | corners_HTM = { | ||
| 40 | .estimate = estimate_corners_HTM, | ||
| 41 | .ready = check_centers, | ||
| 42 | .moveset = moveset_HTM | ||
| 43 | }; | ||
| 44 | |||
| 45 | Step | ||
| 46 | cornershtr_HTM = { | ||
| 47 | .estimate = estimate_cornershtr_HTM, | ||
| 48 | .ready = check_centers, | ||
| 49 | .moveset = moveset_HTM | ||
| 50 | }; | ||
| 51 | |||
| 52 | Step | ||
| 53 | cornershtr_URF = { | ||
| 54 | .estimate = estimate_cornershtr_URF, | ||
| 55 | .ready = check_nothing, | ||
| 56 | .moveset = moveset_URF | ||
| 57 | }; | ||
| 58 | |||
| 59 | Step | ||
| 60 | corners_URF = { | ||
| 61 | .estimate = estimate_corners_URF, | ||
| 62 | .ready = check_nothing, | ||
| 63 | .moveset = moveset_URF | ||
| 64 | }; | ||
| 65 | |||
| 66 | Step | ||
| 67 | drud_HTM = { | ||
| 68 | .estimate = estimate_drud_HTM, | ||
| 69 | .ready = check_centers, | ||
| 70 | .moveset = moveset_HTM | ||
| 71 | }; | ||
| 72 | |||
| 73 | Step | ||
| 74 | optimal_HTM = { | ||
| 75 | .estimate = estimate_optimal_HTM, | ||
| 76 | .ready = check_centers, | ||
| 77 | .moveset = moveset_HTM | ||
| 78 | }; | ||
| 79 | |||
| 80 | |||
| 81 | /* Pruning tables ************************************************************/ | ||
| 82 | |||
| 83 | PruneData | ||
| 84 | pd_eofb_HTM = { | ||
| 85 | .filename = "ptable_eofb_HTM", | ||
| 86 | .coord = &coord_eofb, | ||
| 87 | .moveset = moveset_HTM | ||
| 88 | }; | ||
| 89 | |||
| 90 | PruneData | ||
| 91 | pd_coud_HTM = { | ||
| 92 | .filename = "ptable_coud_HTM", | ||
| 93 | .coord = &coord_coud, | ||
| 94 | .moveset = moveset_HTM | ||
| 95 | }; | ||
| 96 | |||
| 97 | PruneData | ||
| 98 | pd_cornershtr_HTM = { | ||
| 99 | .filename = "ptable_cornershtr_withcosets_HTM", | ||
| 100 | .coord = &coord_cornershtr, | ||
| 101 | .moveset = moveset_HTM | ||
| 102 | }; | ||
| 103 | |||
| 104 | PruneData | ||
| 105 | pd_corners_HTM = { | ||
| 106 | .filename = "ptable_corners_HTM", | ||
| 107 | .coord = &coord_corners, | ||
| 108 | .moveset = moveset_HTM | ||
| 109 | }; | ||
| 110 | |||
| 111 | PruneData | ||
| 112 | pd_drud_HTM = { | ||
| 113 | .filename = "ptable_drud_HTM", | ||
| 114 | .coord = &coord_drud, | ||
| 115 | .moveset = moveset_HTM | ||
| 116 | }; | ||
| 117 | |||
| 118 | PruneData | ||
| 119 | pd_drud_sym16_HTM = { | ||
| 120 | .filename = "ptable_drud_sym16_HTM", | ||
| 121 | .coord = &coord_drud_sym16, | ||
| 122 | .moveset = moveset_HTM, | ||
| 123 | }; | ||
| 124 | |||
| 125 | PruneData | ||
| 126 | pd_khuge_HTM = { | ||
| 127 | .filename = "ptable_khuge_HTM", | ||
| 128 | .coord = &coord_khuge, | ||
| 129 | .moveset = moveset_HTM | ||
| 130 | }; | ||
| 131 | |||
| 132 | |||
| 133 | /* Standard checkers (return lower bound) ************************************/ | ||
| 134 | |||
| 135 | static int | ||
| 136 | estimate_eofb_HTM(CubeTarget ct) | ||
| 137 | { | ||
| 138 | if (!pd_eofb_HTM.generated) | ||
| 139 | genptable(&pd_eofb_HTM); | ||
| 140 | |||
| 141 | return ptableval(&pd_eofb_HTM, ct.cube); | ||
| 142 | } | ||
| 143 | |||
| 144 | static int | ||
| 145 | estimate_coud_HTM(CubeTarget ct) | ||
| 146 | { | ||
| 147 | if (!pd_coud_HTM.generated) | ||
| 148 | genptable(&pd_coud_HTM); | ||
| 149 | |||
| 150 | return ptableval(&pd_coud_HTM, ct.cube); | ||
| 151 | } | ||
| 152 | |||
| 153 | static int | ||
| 154 | estimate_coud_URF(CubeTarget ct) | ||
| 155 | { | ||
| 156 | /* TODO: I can improve this by checking first the orientation of | ||
| 157 | * the corner in DBL and use that as a reference */ | ||
| 158 | |||
| 159 | CubeTarget ct2 = {.cube = apply_move(z, ct.cube), .target = ct.target}; | ||
| 160 | CubeTarget ct3 = {.cube = apply_move(x, ct.cube), .target = ct.target}; | ||
| 161 | |||
| 162 | int ud = estimate_coud_HTM(ct); | ||
| 163 | int rl = estimate_coud_HTM(ct2); | ||
| 164 | int fb = estimate_coud_HTM(ct3); | ||
| 165 | |||
| 166 | return MIN(ud, MIN(rl, fb)); | ||
| 167 | } | ||
| 168 | |||
| 169 | static int | ||
| 170 | estimate_corners_HTM(CubeTarget ct) | ||
| 171 | { | ||
| 172 | if (!pd_corners_HTM.generated) | ||
| 173 | genptable(&pd_corners_HTM); | ||
| 174 | |||
| 175 | return ptableval(&pd_corners_HTM, ct.cube); | ||
| 176 | } | ||
| 177 | |||
| 178 | static int | ||
| 179 | estimate_cornershtr_HTM(CubeTarget ct) | ||
| 180 | { | ||
| 181 | if (!pd_cornershtr_HTM.generated) | ||
| 182 | genptable(&pd_cornershtr_HTM); | ||
| 183 | |||
| 184 | return ptableval(&pd_cornershtr_HTM, ct.cube); | ||
| 185 | } | ||
| 186 | |||
| 187 | static int | ||
| 188 | estimate_cornershtr_URF(CubeTarget ct) | ||
| 189 | { | ||
| 190 | /* TODO: I can improve this by checking first the corner in DBL | ||
| 191 | * and use that as a reference */ | ||
| 192 | |||
| 193 | int c, ret = 15; | ||
| 194 | Trans i; | ||
| 195 | |||
| 196 | for (i = 0; i < NROTATIONS; i++) { | ||
| 197 | ct.cube = apply_alg(rotation_alg(i), ct.cube); | ||
| 198 | c = estimate_cornershtr_HTM(ct); | ||
| 199 | ret = MIN(ret, c); | ||
| 200 | } | ||
| 201 | |||
| 202 | return ret; | ||
| 203 | } | ||
| 204 | |||
| 205 | static int | ||
| 206 | estimate_corners_URF(CubeTarget ct) | ||
| 207 | { | ||
| 208 | /* TODO: I can improve this by checking first the corner in DBL | ||
| 209 | * and use that as a reference */ | ||
| 210 | |||
| 211 | int c, ret = 15; | ||
| 212 | Trans i; | ||
| 213 | |||
| 214 | for (i = 0; i < NROTATIONS; i++) { | ||
| 215 | ct.cube = apply_alg(rotation_alg(i), ct.cube); | ||
| 216 | c = estimate_corners_HTM(ct); | ||
| 217 | ret = MIN(ret, c); | ||
| 218 | } | ||
| 219 | |||
| 220 | return ret; | ||
| 221 | } | ||
| 222 | |||
| 223 | static int | ||
| 224 | estimate_drud_HTM(CubeTarget ct) | ||
| 225 | { | ||
| 226 | /* | ||
| 227 | if (!pd_drud_HTM.generated) | ||
| 228 | genptable(&pd_drud_HTM); | ||
| 229 | |||
| 230 | return ptableval(&pd_drud_HTM, ct.cube); | ||
| 231 | */ | ||
| 232 | |||
| 233 | if (!pd_drud_sym16_HTM.generated) | ||
| 234 | genptable(&pd_drud_sym16_HTM); | ||
| 235 | |||
| 236 | return ptableval(&pd_drud_sym16_HTM, ct.cube); | ||
| 237 | } | ||
| 238 | |||
| 239 | /* TODO: if lucky, remove this */ | ||
| 240 | /* | ||
| 241 | static int | ||
| 242 | estimate_optimal_HTM(CubeTarget ct) | ||
| 243 | { | ||
| 244 | static Trans t1 = { .rot = rf, .mirror = false }; | ||
| 245 | static Trans t2 = { .rot = bd, .mirror = false }; | ||
| 246 | int dr1, dr2, dr3, cor, ret; | ||
| 247 | Cube cube = ct.cube; | ||
| 248 | |||
| 249 | dr1 = estimate_drud_HTM(ct); | ||
| 250 | cor = estimate_corners_HTM(ct); | ||
| 251 | ret = MAX(dr1, cor); | ||
| 252 | |||
| 253 | if (ret > ct.target) | ||
| 254 | return ret; | ||
| 255 | |||
| 256 | ct.cube = apply_trans(t1, cube); | ||
| 257 | dr2 = estimate_drud_HTM(ct); | ||
| 258 | ret = MAX(ret, dr2); | ||
| 259 | |||
| 260 | if (ret > ct.target) | ||
| 261 | return ret; | ||
| 262 | |||
| 263 | ct.cube = apply_trans(t2, cube); | ||
| 264 | dr3 = estimate_drud_HTM(ct); | ||
| 265 | |||
| 266 | if (dr1 == dr2 && dr2 == dr3 && dr1 != 0) | ||
| 267 | dr3++; | ||
| 268 | |||
| 269 | ret = MAX(ret, dr3); | ||
| 270 | |||
| 271 | if (ret == 0) | ||
| 272 | return check_ep(cube) ? 0 : 6; | ||
| 273 | |||
| 274 | return ret; | ||
| 275 | } | ||
| 276 | */ | ||
| 277 | |||
| 278 | static int | ||
| 279 | estimate_optimal_HTM(CubeTarget ct) | ||
| 280 | { | ||
| 281 | static Trans t2 = rf, t3 = bd; | ||
| 282 | |||
| 283 | int dr1, dr2, dr3, cor, ret; | ||
| 284 | Cube cube = ct.cube; | ||
| 285 | |||
| 286 | if (!pd_khuge_HTM.generated) | ||
| 287 | genptable(&pd_khuge_HTM); | ||
| 288 | |||
| 289 | dr1 = ptableval(&pd_khuge_HTM, cube); | ||
| 290 | cor = estimate_corners_HTM(ct); | ||
| 291 | ret = MAX(dr1, cor); | ||
| 292 | |||
| 293 | if (ret > ct.target) | ||
| 294 | return ret; | ||
| 295 | |||
| 296 | cube = apply_trans(t2, ct.cube); | ||
| 297 | dr2 = ptableval(&pd_khuge_HTM, cube); | ||
| 298 | ret = MAX(ret, dr2); | ||
| 299 | |||
| 300 | if (ret > ct.target) | ||
| 301 | return ret; | ||
| 302 | |||
| 303 | cube = apply_trans(t3, ct.cube); | ||
| 304 | dr3 = ptableval(&pd_khuge_HTM, cube); | ||
| 305 | |||
| 306 | return MAX(ret, dr3); | ||
| 307 | } | ||
diff --git a/old/2021-07-02-genptable-dfs/steps.h b/old/2021-07-02-genptable-dfs/steps.h new file mode 100644 index 0000000..81ae11c --- /dev/null +++ b/old/2021-07-02-genptable-dfs/steps.h | |||
| @@ -0,0 +1,24 @@ | |||
| 1 | #ifndef STEPS_H | ||
| 2 | #define STEPS_H | ||
| 3 | |||
| 4 | #include "cube.h" | ||
| 5 | |||
| 6 | extern Step eofb_HTM; | ||
| 7 | extern Step coud_HTM; | ||
| 8 | extern Step coud_URF; | ||
| 9 | extern Step corners_HTM; | ||
| 10 | extern Step cornershtr_HTM; | ||
| 11 | extern Step corners_URF; | ||
| 12 | extern Step cornershtr_URF; | ||
| 13 | extern Step drud_HTM; | ||
| 14 | extern Step optimal_HTM; | ||
| 15 | |||
| 16 | extern PruneData pd_eofb_HTM; | ||
| 17 | extern PruneData pd_coud_HTM; | ||
| 18 | extern PruneData pd_corners_HTM; | ||
| 19 | extern PruneData pd_cornershtr_HTM; | ||
| 20 | extern PruneData pd_cornershtreofb_HTM; | ||
| 21 | extern PruneData pd_drud_HTM; | ||
| 22 | extern PruneData pd_khuge_HTM; | ||
| 23 | |||
| 24 | #endif | ||
diff --git a/old/2021-07-15-almostbeforerefactor/README b/old/2021-07-15-almostbeforerefactor/README new file mode 100644 index 0000000..e306a9e --- /dev/null +++ b/old/2021-07-15-almostbeforerefactor/README | |||
| @@ -0,0 +1,3 @@ | |||
| 1 | I started refactorig (splitting code into more files) before realizing I had no backup of | ||
| 2 | the fast version that works. | ||
| 3 | Take some stuff from alg.h back into cube.h, remove alg.* ad it should be ok. | ||
diff --git a/old/2021-07-15-almostbeforerefactor/alg.c b/old/2021-07-15-almostbeforerefactor/alg.c new file mode 100644 index 0000000..a3f8a19 --- /dev/null +++ b/old/2021-07-15-almostbeforerefactor/alg.c | |||
| @@ -0,0 +1,3388 @@ | |||
| 1 | #include "alg.h" | ||
| 2 | |||
| 3 | /* Local functions **********************************************************/ | ||
| 4 | |||
| 5 | static Cube admissible_ep(Cube cube, PieceFilter f); | ||
| 6 | static Cube admissible_eos_from_eofbepos(Cube cube); | ||
| 7 | static bool allowed_next(Move move, DfsData *dd); | ||
| 8 | static void append_alg(AlgList *l, Alg *alg); | ||
| 9 | static void append_move(Alg *alg, Move m, bool inverse); | ||
| 10 | static Cube apply_alg_generic(Alg *alg, Cube c, PieceFilter f, bool a); | ||
| 11 | static void apply_permutation(int *perm, int *set, int n); | ||
| 12 | static Cube apply_move_cubearray(Move m, Cube cube, PieceFilter f); | ||
| 13 | static int array_ep_to_epos(int *ep, int *eps_solved); | ||
| 14 | static Cube arrays_to_cube(CubeArray *arr, PieceFilter f); | ||
| 15 | static int binomial(int n, int k); | ||
| 16 | static Cube compose_filtered(Cube c2, Cube c1, PieceFilter f); | ||
| 17 | static void cube_to_arrays(Cube cube, CubeArray *arr, PieceFilter f); | ||
| 18 | static void dfs(Cube c, Step s, SolveOptions *opts, DfsData *dd); | ||
| 19 | static void dfs_branch(Cube c, Step s, SolveOptions *opts, DfsData *dd); | ||
| 20 | static bool dfs_check_solved(SolveOptions *opts, DfsData *dd); | ||
| 21 | static void dfs_niss(Cube c, Step s, SolveOptions *opts, DfsData *dd); | ||
| 22 | static bool dfs_stop(Cube c, Step s, SolveOptions *opts, DfsData *dd); | ||
| 23 | static int digit_array_to_int(int *a, int n, int b); | ||
| 24 | static int edge_slice(Edge e); /* E=0, S=1, M=2 */ | ||
| 25 | static int epos_dependent_pos(int pos1, int pos2); | ||
| 26 | static int epos_from_arrays(int *epos, int *ep); | ||
| 27 | static void epos_to_partial_ep(int epos, int *ep, int *ss); | ||
| 28 | static int factorial(int n); | ||
| 29 | static void free_alglistnode(AlgListNode *aln); | ||
| 30 | static void free_cubearray(CubeArray *arr, PieceFilter f); | ||
| 31 | static void genptable_bfs(PruneData *pd, int d, Move *ms); | ||
| 32 | static void genptable_branch(PruneData *pd, uint64_t i, int d, Move *m); | ||
| 33 | static void gensym(SymData *sd); | ||
| 34 | static void index_to_perm(int p, int n, int *r); | ||
| 35 | static void index_to_subset(int s, int n, int k, int *r); | ||
| 36 | static void init_auxtables(); | ||
| 37 | static void init_cphtr_cosets(); | ||
| 38 | static void init_cphtr_left_cosets_bfs(int i, int c); | ||
| 39 | static void init_cphtr_right_cosets_color(int i, int c); | ||
| 40 | static void init_environment(); | ||
| 41 | static void init_moves(); | ||
| 42 | static void init_moves_aux(); | ||
| 43 | static void init_strings(); | ||
| 44 | static void init_symdata(); | ||
| 45 | static void init_trans(); | ||
| 46 | static void init_trans_aux(); | ||
| 47 | static void int_to_digit_array(int a, int b, int n, int *r); | ||
| 48 | static void int_to_sum_zero_array(int x, int b, int n, int *a); | ||
| 49 | static int invert_digits(int a, int b, int n); | ||
| 50 | static bool is_perm(int *a, int n); | ||
| 51 | static bool is_subset(int *a, int n, int k); | ||
| 52 | static Cube move_via_arrays(CubeArray *arr, Cube c, PieceFilter pf); | ||
| 53 | static void movelist_to_position(Move *movelist, int *position); | ||
| 54 | static void moveset_to_list(Moveset ms, Estimator f, Move *r); | ||
| 55 | static AlgList * new_alglist(); | ||
| 56 | static CubeArray * new_cubearray(Cube cube, PieceFilter f); | ||
| 57 | static int perm_sign(int *a, int n); | ||
| 58 | static int perm_to_index(int *a, int n); | ||
| 59 | static int powint(int a, int b); | ||
| 60 | static void ptable_update(PruneData *pd, Cube cube, int m); | ||
| 61 | static int ptableval_index(PruneData *pd, uint64_t ind); | ||
| 62 | static void realloc_alg(Alg *alg, int n); | ||
| 63 | static bool read_mtables_file(); | ||
| 64 | static bool read_ptable_file(PruneData *pd); | ||
| 65 | static bool read_symdata_file(SymData *sd); | ||
| 66 | static bool read_ttables_file(); | ||
| 67 | static Cube rotate_via_compose(Trans r, Cube c, PieceFilter f); | ||
| 68 | static int subset_to_index(int *a, int n, int k); | ||
| 69 | static void sum_arrays_mod(int *src, int *dst, int n, int m); | ||
| 70 | static void swap(int *a, int *b); | ||
| 71 | static bool write_mtables_file(); | ||
| 72 | static bool write_ptable_file(PruneData *pd); | ||
| 73 | static bool write_symdata_file(SymData *sd); | ||
| 74 | static bool write_ttables_file(); | ||
| 75 | |||
| 76 | |||
| 77 | /* All sorts of useful costants and tables **********************************/ | ||
| 78 | |||
| 79 | static char * tabledir; | ||
| 80 | |||
| 81 | static PieceFilter pf_all; | ||
| 82 | static PieceFilter pf_4val; | ||
| 83 | static PieceFilter pf_epcp; | ||
| 84 | static PieceFilter pf_cpos; | ||
| 85 | static PieceFilter pf_cp; | ||
| 86 | static PieceFilter pf_ep; | ||
| 87 | static PieceFilter pf_e; | ||
| 88 | static PieceFilter pf_s; | ||
| 89 | static PieceFilter pf_m; | ||
| 90 | static PieceFilter pf_eo; | ||
| 91 | static PieceFilter pf_co; | ||
| 92 | |||
| 93 | static int epe_solved[4]; | ||
| 94 | static int eps_solved[4]; | ||
| 95 | static int epm_solved[4]; | ||
| 96 | |||
| 97 | static char move_string[NMOVES][7]; | ||
| 98 | static char edge_string[12][7]; | ||
| 99 | static char corner_string[8][7]; | ||
| 100 | static char center_string[6][7]; | ||
| 101 | |||
| 102 | static Cube admissible_ee_aux[POW2TO11*BINOM12ON4]; | ||
| 103 | static bool commute[NMOVES][NMOVES]; | ||
| 104 | static bool possible_next[NMOVES][NMOVES][NMOVES]; | ||
| 105 | static Move inverse_move_aux[NMOVES]; | ||
| 106 | static Trans inverse_trans_aux[NTRANS]; | ||
| 107 | static int epos_dependent_aux[BINOM12ON4][BINOM12ON4]; | ||
| 108 | static int cphtr_left_cosets[FACTORIAL8]; | ||
| 109 | static int cphtr_right_cosets[FACTORIAL8]; | ||
| 110 | static int cphtr_right_rep[BINOM8ON4*6]; | ||
| 111 | static Center what_center_at_aux[FACTORIAL6][6]; | ||
| 112 | static Corner what_corner_at_aux[FACTORIAL8][8]; | ||
| 113 | static int what_orientation_last_corner_aux[POW3TO7]; | ||
| 114 | static int what_orientation_last_edge_aux[POW2TO11]; | ||
| 115 | static Center where_is_center_aux[FACTORIAL6][6]; | ||
| 116 | static Corner where_is_corner_aux[FACTORIAL8][8]; | ||
| 117 | static Edge where_is_edge_aux[3][FACTORIAL12/FACTORIAL8][12]; | ||
| 118 | |||
| 119 | static int epose_ttable[NTRANS][FACTORIAL12/FACTORIAL8]; | ||
| 120 | static int eposs_ttable[NTRANS][FACTORIAL12/FACTORIAL8]; | ||
| 121 | static int eposm_ttable[NTRANS][FACTORIAL12/FACTORIAL8]; | ||
| 122 | static int eo_ttable[NTRANS][POW2TO11]; | ||
| 123 | static int cp_ttable[NTRANS][FACTORIAL8]; | ||
| 124 | static int co_ttable[NTRANS][POW3TO7]; | ||
| 125 | static int cpos_ttable[NTRANS][FACTORIAL6]; | ||
| 126 | static Move moves_ttable[NTRANS][NMOVES]; | ||
| 127 | |||
| 128 | static int epose_mtable[NMOVES][FACTORIAL12/FACTORIAL8]; | ||
| 129 | static int eposs_mtable[NMOVES][FACTORIAL12/FACTORIAL8]; | ||
| 130 | static int eposm_mtable[NMOVES][FACTORIAL12/FACTORIAL8]; | ||
| 131 | static int eofb_mtable[NMOVES][POW2TO11]; | ||
| 132 | static int eorl_mtable[NMOVES][POW2TO11]; | ||
| 133 | static int eoud_mtable[NMOVES][POW2TO11]; | ||
| 134 | static int cp_mtable[NMOVES][FACTORIAL8]; | ||
| 135 | static int coud_mtable[NMOVES][POW3TO7]; | ||
| 136 | static int cofb_mtable[NMOVES][POW3TO7]; | ||
| 137 | static int corl_mtable[NMOVES][POW3TO7]; | ||
| 138 | static int cpos_mtable[NMOVES][FACTORIAL6]; | ||
| 139 | |||
| 140 | static uint64_t me[12]; | ||
| 141 | |||
| 142 | static int edge_cycle[NMOVES][12]; | ||
| 143 | static int corner_cycle[NMOVES][8]; | ||
| 144 | static int center_cycle[NMOVES][6]; | ||
| 145 | static int eofb_flipped[NMOVES][12]; | ||
| 146 | static int eorl_flipped[NMOVES][12]; | ||
| 147 | static int eoud_flipped[NMOVES][12]; | ||
| 148 | static int coud_flipped[NMOVES][8]; | ||
| 149 | static int corl_flipped[NMOVES][8]; | ||
| 150 | static int cofb_flipped[NMOVES][8]; | ||
| 151 | static Alg * equiv_alg[NMOVES]; | ||
| 152 | |||
| 153 | static int epose_source[NTRANS]; /* 0=epose, 1=eposs, 2=eposm */ | ||
| 154 | static int eposs_source[NTRANS]; | ||
| 155 | static int eposm_source[NTRANS]; | ||
| 156 | static int eofb_source[NTRANS]; /* 0=eoud, 1=eorl, 2=eofb */ | ||
| 157 | static int eorl_source[NTRANS]; | ||
| 158 | static int eoud_source[NTRANS]; | ||
| 159 | static int coud_source[NTRANS]; /* 0=coud, 1=corl, 2=cofb */ | ||
| 160 | static int cofb_source[NTRANS]; | ||
| 161 | static int corl_source[NTRANS]; | ||
| 162 | static int ep_mirror[12]; | ||
| 163 | static int cp_mirror[8]; | ||
| 164 | static int cpos_mirror[6]; | ||
| 165 | static Alg * rotation_algs[NROTATIONS]; | ||
| 166 | |||
| 167 | |||
| 168 | /* Symmetry data for some coordinates ****************************************/ | ||
| 169 | |||
| 170 | Trans | ||
| 171 | trans_group_trivial[1] = { uf }; | ||
| 172 | |||
| 173 | Trans | ||
| 174 | trans_group_udfix[16] = { | ||
| 175 | uf, ur, ub, ul, | ||
| 176 | df, dr, db, dl, | ||
| 177 | uf_mirror, ur_mirror, ub_mirror, ul_mirror, | ||
| 178 | df_mirror, dr_mirror, db_mirror, dl_mirror, | ||
| 179 | }; | ||
| 180 | |||
| 181 | SymData | ||
| 182 | sd_coud_16 = { | ||
| 183 | .filename = "sd_coud_16", | ||
| 184 | .coord = &coord_coud, | ||
| 185 | .sym_coord = &coord_coud_sym16, | ||
| 186 | .ntrans = 16, | ||
| 187 | .trans = trans_group_udfix | ||
| 188 | }; | ||
| 189 | |||
| 190 | SymData | ||
| 191 | sd_eofbepos_16 = { | ||
| 192 | .filename = "sd_eofbepos_16", | ||
| 193 | .coord = &coord_eofbepos, | ||
| 194 | .sym_coord = &coord_eofbepos_sym16, | ||
| 195 | .ntrans = 16, | ||
| 196 | .trans = trans_group_udfix | ||
| 197 | }; | ||
| 198 | |||
| 199 | static int n_all_symdata = 2; | ||
| 200 | static SymData * all_sd[2] = { &sd_coud_16, &sd_eofbepos_16 }; | ||
| 201 | |||
| 202 | /* Coordinates and their implementation **************************************/ | ||
| 203 | |||
| 204 | static uint64_t index_eofb(Cube cube); | ||
| 205 | static uint64_t index_eofbepos(Cube cube); | ||
| 206 | static uint64_t index_coud(Cube cube); | ||
| 207 | static uint64_t index_corners(Cube cube); | ||
| 208 | static uint64_t index_cornershtr(Cube cube); | ||
| 209 | static uint64_t index_drud(Cube cube); | ||
| 210 | static uint64_t index_coud_sym16(Cube cube); | ||
| 211 | static uint64_t index_eofbepos_sym16(Cube cube); | ||
| 212 | static uint64_t index_drud_sym16(Cube cube); | ||
| 213 | static uint64_t index_khuge(Cube cube); | ||
| 214 | |||
| 215 | static Cube antindex_eofb(uint64_t ind); | ||
| 216 | static Cube antindex_eofbepos(uint64_t ind); | ||
| 217 | static Cube antindex_coud(uint64_t ind); | ||
| 218 | static Cube antindex_corners(uint64_t ind); | ||
| 219 | static Cube antindex_cornershtr(uint64_t ind); | ||
| 220 | static Cube antindex_drud(uint64_t ind); | ||
| 221 | static Cube antindex_coud_sym16(uint64_t ind); | ||
| 222 | static Cube antindex_eofbepos_sym16(uint64_t ind); | ||
| 223 | static Cube antindex_drud_sym16(uint64_t ind); | ||
| 224 | static Cube antindex_khuge(uint64_t ind); | ||
| 225 | |||
| 226 | Coordinate | ||
| 227 | coord_eofb = { | ||
| 228 | .index = index_eofb, | ||
| 229 | .cube = antindex_eofb, | ||
| 230 | .check = check_eofb, | ||
| 231 | .max = POW2TO11 | ||
| 232 | }; | ||
| 233 | |||
| 234 | Coordinate | ||
| 235 | coord_eofbepos = { | ||
| 236 | .index = index_eofbepos, | ||
| 237 | .cube = antindex_eofbepos, | ||
| 238 | .check = check_eofbepos, | ||
| 239 | .max = POW2TO11 * BINOM12ON4 | ||
| 240 | }; | ||
| 241 | |||
| 242 | Coordinate | ||
| 243 | coord_coud = { | ||
| 244 | .index = index_coud, | ||
| 245 | .cube = antindex_coud, | ||
| 246 | .check = check_coud, | ||
| 247 | .max = POW3TO7 | ||
| 248 | }; | ||
| 249 | |||
| 250 | Coordinate | ||
| 251 | coord_corners = { | ||
| 252 | .index = index_corners, | ||
| 253 | .cube = antindex_corners, | ||
| 254 | .check = check_corners, | ||
| 255 | .max = POW3TO7 * FACTORIAL8 | ||
| 256 | }; | ||
| 257 | |||
| 258 | Coordinate | ||
| 259 | coord_cornershtr = { | ||
| 260 | .index = index_cornershtr, | ||
| 261 | .cube = antindex_cornershtr, | ||
| 262 | .check = check_cornershtr, | ||
| 263 | .max = POW3TO7 * BINOM8ON4 * 6 | ||
| 264 | }; | ||
| 265 | |||
| 266 | Coordinate | ||
| 267 | coord_drud = { | ||
| 268 | .index = index_drud, | ||
| 269 | .cube = antindex_drud, | ||
| 270 | .check = check_drud, | ||
| 271 | .max = POW2TO11 * POW3TO7 * BINOM12ON4 | ||
| 272 | }; | ||
| 273 | |||
| 274 | Coordinate | ||
| 275 | coord_eofbepos_sym16 = { | ||
| 276 | .index = index_eofbepos_sym16, | ||
| 277 | .cube = antindex_eofbepos_sym16, | ||
| 278 | .check = check_eofbepos, | ||
| 279 | }; | ||
| 280 | |||
| 281 | Coordinate | ||
| 282 | coord_coud_sym16 = { | ||
| 283 | .index = index_coud_sym16, | ||
| 284 | .cube = antindex_coud_sym16, | ||
| 285 | .check = check_coud, | ||
| 286 | }; | ||
| 287 | |||
| 288 | Coordinate | ||
| 289 | coord_drud_sym16 = { | ||
| 290 | .index = index_drud_sym16, | ||
| 291 | .cube = antindex_drud_sym16, | ||
| 292 | .check = check_drud, | ||
| 293 | .max = POW3TO7 * 64430 | ||
| 294 | }; | ||
| 295 | |||
| 296 | Coordinate | ||
| 297 | coord_khuge = { | ||
| 298 | .index = index_khuge, | ||
| 299 | .cube = antindex_khuge, | ||
| 300 | .check = check_khuge, | ||
| 301 | .max = POW3TO7 * FACTORIAL4 * 64430 | ||
| 302 | }; | ||
| 303 | |||
| 304 | |||
| 305 | static uint64_t | ||
| 306 | index_eofb(Cube cube) | ||
| 307 | { | ||
| 308 | return cube.eofb; | ||
| 309 | } | ||
| 310 | |||
| 311 | static uint64_t | ||
| 312 | index_eofbepos(Cube cube) | ||
| 313 | { | ||
| 314 | return (cube.epose / FACTORIAL4) * POW2TO11 + cube.eofb; | ||
| 315 | } | ||
| 316 | |||
| 317 | static uint64_t | ||
| 318 | index_coud(Cube cube) | ||
| 319 | { | ||
| 320 | return cube.coud; | ||
| 321 | } | ||
| 322 | |||
| 323 | static uint64_t | ||
| 324 | index_corners(Cube cube) | ||
| 325 | { | ||
| 326 | return cube.coud * FACTORIAL8 + cube.cp; | ||
| 327 | } | ||
| 328 | |||
| 329 | static uint64_t | ||
| 330 | index_cornershtr(Cube cube) | ||
| 331 | { | ||
| 332 | return cube.coud * BINOM8ON4 * 6 + cphtr(cube); | ||
| 333 | } | ||
| 334 | |||
| 335 | static uint64_t | ||
| 336 | index_drud(Cube cube) | ||
| 337 | { | ||
| 338 | uint64_t a, b, c; | ||
| 339 | |||
| 340 | a = cube.eofb; | ||
| 341 | b = cube.coud; | ||
| 342 | c = cube.epose / FACTORIAL4; | ||
| 343 | |||
| 344 | b *= POW2TO11; | ||
| 345 | c *= POW2TO11 * POW3TO7; | ||
| 346 | |||
| 347 | return a + b + c; | ||
| 348 | } | ||
| 349 | |||
| 350 | static uint64_t | ||
| 351 | index_coud_sym16(Cube cube) | ||
| 352 | { | ||
| 353 | return sd_coud_16.class[index_coud(cube)]; | ||
| 354 | } | ||
| 355 | |||
| 356 | static uint64_t | ||
| 357 | index_drud_sym16(Cube cube) | ||
| 358 | { | ||
| 359 | Trans t; | ||
| 360 | Cube c; | ||
| 361 | |||
| 362 | t = sd_eofbepos_16.transtorep[index_eofbepos(cube)]; | ||
| 363 | c = apply_trans(t, cube); | ||
| 364 | |||
| 365 | return index_eofbepos_sym16(c) * POW3TO7 + c.coud; | ||
| 366 | } | ||
| 367 | |||
| 368 | static uint64_t | ||
| 369 | index_eofbepos_sym16(Cube cube) | ||
| 370 | { | ||
| 371 | return sd_eofbepos_16.class[index_eofbepos(cube)]; | ||
| 372 | } | ||
| 373 | |||
| 374 | static uint64_t | ||
| 375 | index_khuge(Cube cube) | ||
| 376 | { | ||
| 377 | Trans t; | ||
| 378 | Cube c; | ||
| 379 | uint64_t a; | ||
| 380 | |||
| 381 | t = sd_eofbepos_16.transtorep[index_eofbepos(cube)]; | ||
| 382 | c = apply_trans(t, cube); | ||
| 383 | a = (index_eofbepos_sym16(c) * 24) + (c.epose % 24); | ||
| 384 | |||
| 385 | return a * POW3TO7 + c.coud; | ||
| 386 | } | ||
| 387 | |||
| 388 | |||
| 389 | /* TODO: rename */ | ||
| 390 | static Cube | ||
| 391 | antindex_eofb(uint64_t ind) | ||
| 392 | { | ||
| 393 | return (Cube){ .eofb = ind, .eorl = ind, .eoud = ind }; | ||
| 394 | } | ||
| 395 | |||
| 396 | static Cube | ||
| 397 | antindex_eofbepos(uint64_t ind) | ||
| 398 | { | ||
| 399 | return admissible_ee_aux[ind]; | ||
| 400 | } | ||
| 401 | |||
| 402 | /* TODO: rename */ | ||
| 403 | static Cube | ||
| 404 | antindex_coud(uint64_t ind) | ||
| 405 | { | ||
| 406 | return (Cube){ .coud = ind, .corl = ind, .cofb = ind }; | ||
| 407 | } | ||
| 408 | |||
| 409 | /* TODO: admissible co for other orientations */ | ||
| 410 | static Cube | ||
| 411 | antindex_corners(uint64_t ind) | ||
| 412 | { | ||
| 413 | Cube c = {0}; | ||
| 414 | |||
| 415 | c.coud = ind / FACTORIAL8; | ||
| 416 | c.cp = ind % FACTORIAL8; | ||
| 417 | |||
| 418 | return c; | ||
| 419 | } | ||
| 420 | |||
| 421 | /* TODO: admissible co for other orientations */ | ||
| 422 | static Cube | ||
| 423 | antindex_cornershtr(uint64_t ind) | ||
| 424 | { | ||
| 425 | Cube c = anti_cphtr(ind % (BINOM8ON4 * 6)); | ||
| 426 | |||
| 427 | c.coud = ind / (BINOM8ON4 * 6); | ||
| 428 | |||
| 429 | return c; | ||
| 430 | } | ||
| 431 | |||
| 432 | /* TODO: admissible eos and cos */ | ||
| 433 | /* DONE: temporary fix, make it better */ | ||
| 434 | static Cube | ||
| 435 | antindex_drud(uint64_t ind) | ||
| 436 | { | ||
| 437 | uint64_t epos, eofb; | ||
| 438 | Cube c; | ||
| 439 | |||
| 440 | eofb = ind % POW2TO11; | ||
| 441 | epos = ind / (POW2TO11 * POW3TO7); | ||
| 442 | c = admissible_ee_aux[eofb + POW2TO11 * epos]; | ||
| 443 | |||
| 444 | c.coud = (ind / POW2TO11) % POW3TO7; | ||
| 445 | c.corl = c.coud; | ||
| 446 | c.cofb = c.coud; | ||
| 447 | |||
| 448 | return c; | ||
| 449 | } | ||
| 450 | |||
| 451 | static Cube | ||
| 452 | antindex_coud_sym16(uint64_t ind) | ||
| 453 | { | ||
| 454 | return sd_coud_16.rep[ind]; | ||
| 455 | } | ||
| 456 | |||
| 457 | static Cube | ||
| 458 | antindex_eofbepos_sym16(uint64_t ind) | ||
| 459 | { | ||
| 460 | return sd_eofbepos_16.rep[ind]; | ||
| 461 | } | ||
| 462 | |||
| 463 | static Cube | ||
| 464 | antindex_drud_sym16(uint64_t ind) | ||
| 465 | { | ||
| 466 | Cube c; | ||
| 467 | |||
| 468 | c = sd_eofbepos_16.rep[ind/POW3TO7]; | ||
| 469 | c.coud = ind % POW3TO7; | ||
| 470 | c.cofb = c.coud; | ||
| 471 | c.corl = c.coud; | ||
| 472 | |||
| 473 | return c; | ||
| 474 | } | ||
| 475 | |||
| 476 | static Cube | ||
| 477 | antindex_khuge(uint64_t ind) | ||
| 478 | { | ||
| 479 | Cube c; | ||
| 480 | |||
| 481 | c = sd_eofbepos_16.rep[ind/(FACTORIAL4*POW3TO7)]; | ||
| 482 | c.epose = ((c.epose / 24) * 24) + ((ind/POW3TO7) % 24); | ||
| 483 | c.coud = ind % POW3TO7; | ||
| 484 | |||
| 485 | return c; | ||
| 486 | } | ||
| 487 | |||
| 488 | |||
| 489 | /* Checkers ******************************************************************/ | ||
| 490 | |||
| 491 | bool | ||
| 492 | check_centers(Cube cube) | ||
| 493 | { | ||
| 494 | return cube.cpos == 0; | ||
| 495 | } | ||
| 496 | |||
| 497 | bool | ||
| 498 | check_corners(Cube cube) | ||
| 499 | { | ||
| 500 | return cube.cp == 0 && cube.coud == 0; | ||
| 501 | } | ||
| 502 | |||
| 503 | bool | ||
| 504 | check_cornershtr(Cube cube) | ||
| 505 | { | ||
| 506 | return cube.coud == 0 && cphtr(cube) == 0; /* TODO: use array cphtrcosets*/ | ||
| 507 | } | ||
| 508 | |||
| 509 | bool | ||
| 510 | check_coud(Cube cube) | ||
| 511 | { | ||
| 512 | return cube.coud == 0; | ||
| 513 | } | ||
| 514 | |||
| 515 | bool | ||
| 516 | check_drud(Cube cube) | ||
| 517 | { | ||
| 518 | return cube.eofb == 0 && cube.eorl == 0 && cube.coud == 0; | ||
| 519 | } | ||
| 520 | |||
| 521 | bool | ||
| 522 | check_eofb(Cube cube) | ||
| 523 | { | ||
| 524 | return cube.eofb == 0; | ||
| 525 | } | ||
| 526 | |||
| 527 | bool | ||
| 528 | check_eofbepos(Cube cube) | ||
| 529 | { | ||
| 530 | return cube.eofb == 0 && cube.epose / 24 == 0; | ||
| 531 | } | ||
| 532 | |||
| 533 | bool | ||
| 534 | check_epose(Cube cube) | ||
| 535 | { | ||
| 536 | return cube.epose == 0; | ||
| 537 | } | ||
| 538 | |||
| 539 | bool | ||
| 540 | check_ep(Cube cube) | ||
| 541 | { | ||
| 542 | return cube.epose == 0 && cube.eposs == 0 && cube.eposm == 0; | ||
| 543 | } | ||
| 544 | |||
| 545 | bool | ||
| 546 | check_khuge(Cube cube) | ||
| 547 | { | ||
| 548 | return check_drud(cube) && cube.epose % 24 == 0; | ||
| 549 | } | ||
| 550 | |||
| 551 | bool | ||
| 552 | check_nothing(Cube cube) | ||
| 553 | { | ||
| 554 | return is_admissible(cube); /*TODO: maybe change?*/ | ||
| 555 | } | ||
| 556 | |||
| 557 | /* Movesets ******************************************************************/ | ||
| 558 | |||
| 559 | bool | ||
| 560 | moveset_HTM(Move m) | ||
| 561 | { | ||
| 562 | return m >= U && m <= B3; | ||
| 563 | } | ||
| 564 | |||
| 565 | bool | ||
| 566 | moveset_URF(Move m) | ||
| 567 | { | ||
| 568 | Move b = base_move(m); | ||
| 569 | |||
| 570 | return b == U || b == R || b == F; | ||
| 571 | } | ||
| 572 | |||
| 573 | |||
| 574 | /* Local functions implementation ********************************************/ | ||
| 575 | |||
| 576 | /* TODO: this should be an anti index (maybe?) */ | ||
| 577 | static Cube | ||
| 578 | admissible_ep(Cube cube, PieceFilter f) | ||
| 579 | { | ||
| 580 | CubeArray *arr = new_cubearray(cube, f); | ||
| 581 | Cube ret; | ||
| 582 | bool used[12] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; | ||
| 583 | int i, j; | ||
| 584 | |||
| 585 | for (i = 0; i < 12; i++) | ||
| 586 | if (arr->ep[i] != -1) | ||
| 587 | used[arr->ep[i]] = true; | ||
| 588 | |||
| 589 | for (i = 0, j = 0; i < 12; i++) { | ||
| 590 | for ( ; j < 11 && used[j]; j++); | ||
| 591 | if (arr->ep[i] == -1) | ||
| 592 | arr->ep[i] = j++; | ||
| 593 | } | ||
| 594 | |||
| 595 | ret = arrays_to_cube(arr, pf_ep); | ||
| 596 | free_cubearray(arr, f); | ||
| 597 | |||
| 598 | return ret; | ||
| 599 | } | ||
| 600 | |||
| 601 | static Cube | ||
| 602 | admissible_eos_from_eofbepos(Cube cube) | ||
| 603 | { | ||
| 604 | Edge e; | ||
| 605 | Cube ret; | ||
| 606 | CubeArray *arr = new_cubearray(cube, pf_all); | ||
| 607 | |||
| 608 | memcpy(arr->eorl, arr->eofb, 12 * sizeof(int)); | ||
| 609 | memcpy(arr->eoud, arr->eofb, 12 * sizeof(int)); | ||
| 610 | |||
| 611 | for (e = 0; e < 12; e++) { | ||
| 612 | if ((edge_slice(e) != 0 && edge_slice(arr->ep[e]) == 0) || | ||
| 613 | (edge_slice(e) == 0 && edge_slice(arr->ep[e]) != 0)) | ||
| 614 | arr->eorl[e] = 1 - arr->eorl[e]; | ||
| 615 | if ((edge_slice(e) != 2 && edge_slice(arr->ep[e]) == 2) || | ||
| 616 | (edge_slice(e) == 2 && edge_slice(arr->ep[e]) != 2)) | ||
| 617 | arr->eoud[e] = 1 - arr->eoud[e]; | ||
| 618 | } | ||
| 619 | |||
| 620 | ret = arrays_to_cube(arr, pf_all); | ||
| 621 | free_cubearray(arr, pf_all); | ||
| 622 | |||
| 623 | return ret; | ||
| 624 | } | ||
| 625 | |||
| 626 | static bool | ||
| 627 | allowed_next(Move move, DfsData *dd) | ||
| 628 | { | ||
| 629 | if (!possible_next[dd->last2][dd->last1][move]) | ||
| 630 | return false; | ||
| 631 | |||
| 632 | if (commute[dd->last1][move]) | ||
| 633 | return dd->move_position[dd->last1] < dd->move_position[move]; | ||
| 634 | |||
| 635 | return true; | ||
| 636 | } | ||
| 637 | |||
| 638 | static void | ||
| 639 | append_alg(AlgList *l, Alg *alg) | ||
| 640 | { | ||
| 641 | AlgListNode *node = malloc(sizeof(AlgListNode)); | ||
| 642 | int i; | ||
| 643 | |||
| 644 | node->alg = new_alg(""); | ||
| 645 | for (i = 0; i < alg->len; i++) | ||
| 646 | append_move(node->alg, alg->move[i], alg->inv[i]); | ||
| 647 | node->next = NULL; | ||
| 648 | |||
| 649 | if (++l->len == 1) | ||
| 650 | l->first = node; | ||
| 651 | else | ||
| 652 | l->last->next = node; | ||
| 653 | l->last = node; | ||
| 654 | } | ||
| 655 | |||
| 656 | static void | ||
| 657 | append_move(Alg *alg, Move m, bool inverse) | ||
| 658 | { | ||
| 659 | if (alg->len == alg->allocated) | ||
| 660 | realloc_alg(alg, 2*alg->len); | ||
| 661 | |||
| 662 | alg->move[alg->len] = m; | ||
| 663 | alg->inv [alg->len] = inverse; | ||
| 664 | alg->len++; | ||
| 665 | } | ||
| 666 | |||
| 667 | static Cube | ||
| 668 | apply_alg_generic(Alg *alg, Cube c, PieceFilter f, bool a) | ||
| 669 | { | ||
| 670 | Cube ret = {0}; | ||
| 671 | int i; | ||
| 672 | |||
| 673 | for (i = 0; i < alg->len; i++) | ||
| 674 | if (alg->inv[i]) | ||
| 675 | ret = a ? apply_move(alg->move[i], ret) : | ||
| 676 | apply_move_cubearray(alg->move[i], ret, f); | ||
| 677 | |||
| 678 | ret = compose_filtered(c, inverse_cube(ret), f); | ||
| 679 | |||
| 680 | for (i = 0; i < alg->len; i++) | ||
| 681 | if (!alg->inv[i]) | ||
| 682 | ret = a ? apply_move(alg->move[i], ret) : | ||
| 683 | apply_move_cubearray(alg->move[i], ret, f); | ||
| 684 | |||
| 685 | return ret; | ||
| 686 | } | ||
| 687 | |||
| 688 | static void | ||
| 689 | apply_permutation(int *perm, int *set, int n) | ||
| 690 | { | ||
| 691 | int *aux = malloc(n * sizeof(int)); | ||
| 692 | int i; | ||
| 693 | |||
| 694 | if (!is_perm(perm, n)) | ||
| 695 | return; | ||
| 696 | |||
| 697 | for (i = 0; i < n; i++) | ||
| 698 | aux[i] = set[perm[i]]; | ||
| 699 | |||
| 700 | memcpy(set, aux, n * sizeof(int)); | ||
| 701 | free(aux); | ||
| 702 | } | ||
| 703 | |||
| 704 | static Cube | ||
| 705 | apply_move_cubearray(Move m, Cube cube, PieceFilter f) | ||
| 706 | { | ||
| 707 | CubeArray m_arr = { | ||
| 708 | edge_cycle[m], | ||
| 709 | eofb_flipped[m], | ||
| 710 | eorl_flipped[m], | ||
| 711 | eoud_flipped[m], | ||
| 712 | corner_cycle[m], | ||
| 713 | coud_flipped[m], | ||
| 714 | corl_flipped[m], | ||
| 715 | cofb_flipped[m], | ||
| 716 | center_cycle[m] | ||
| 717 | }; | ||
| 718 | |||
| 719 | return move_via_arrays(&m_arr, cube, f); | ||
| 720 | } | ||
| 721 | |||
| 722 | static int | ||
| 723 | array_ep_to_epos(int *ep, int *ss) | ||
| 724 | { | ||
| 725 | int epos[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; | ||
| 726 | int eps[4]; | ||
| 727 | int i, j, is; | ||
| 728 | |||
| 729 | for (i = 0, is = 0; i < 12; i++) { | ||
| 730 | for (j = 0; j < 4; j++) { | ||
| 731 | if (ep[i] == ss[j]) { | ||
| 732 | eps[is++] = j; | ||
| 733 | epos[i] = 1; | ||
| 734 | } | ||
| 735 | } | ||
| 736 | } | ||
| 737 | |||
| 738 | for (i = 0; i < 4; i++) | ||
| 739 | swap(&epos[ss[i]], &epos[i+8]); | ||
| 740 | |||
| 741 | return epos_from_arrays(epos, eps); | ||
| 742 | } | ||
| 743 | |||
| 744 | static Cube | ||
| 745 | arrays_to_cube(CubeArray *arr, PieceFilter f) | ||
| 746 | { | ||
| 747 | Cube ret = {0}; | ||
| 748 | |||
| 749 | if (f.epose) | ||
| 750 | ret.epose = array_ep_to_epos(arr->ep, epe_solved); | ||
| 751 | if (f.eposs) | ||
| 752 | ret.eposs = array_ep_to_epos(arr->ep, eps_solved); | ||
| 753 | if (f.eposm) | ||
| 754 | ret.eposm = array_ep_to_epos(arr->ep, epm_solved); | ||
| 755 | if (f.eofb) | ||
| 756 | ret.eofb = digit_array_to_int(arr->eofb, 11, 2); | ||
| 757 | if (f.eorl) | ||
| 758 | ret.eorl = digit_array_to_int(arr->eorl, 11, 2); | ||
| 759 | if (f.eoud) | ||
| 760 | ret.eoud = digit_array_to_int(arr->eoud, 11, 2); | ||
| 761 | if (f.cp) | ||
| 762 | ret.cp = perm_to_index(arr->cp, 8); | ||
| 763 | if (f.coud) | ||
| 764 | ret.coud = digit_array_to_int(arr->coud, 7, 3); | ||
| 765 | if (f.corl) | ||
| 766 | ret.corl = digit_array_to_int(arr->corl, 7, 3); | ||
| 767 | if (f.cofb) | ||
| 768 | ret.cofb = digit_array_to_int(arr->cofb, 7, 3); | ||
| 769 | if (f.cpos) | ||
| 770 | ret.cpos = perm_to_index(arr->cpos, 6); | ||
| 771 | |||
| 772 | return ret; | ||
| 773 | } | ||
| 774 | |||
| 775 | static int | ||
| 776 | binomial(int n, int k) | ||
| 777 | { | ||
| 778 | if (n < 0 || k < 0 || k > n) | ||
| 779 | return 0; | ||
| 780 | |||
| 781 | return factorial(n) / (factorial(k) * factorial(n-k)); | ||
| 782 | } | ||
| 783 | |||
| 784 | static Cube | ||
| 785 | compose_filtered(Cube c2, Cube c1, PieceFilter f) | ||
| 786 | { | ||
| 787 | CubeArray *arr = new_cubearray(c2, f); | ||
| 788 | Cube ret; | ||
| 789 | |||
| 790 | ret = move_via_arrays(arr, c1, f); | ||
| 791 | free_cubearray(arr, f); | ||
| 792 | |||
| 793 | return ret; | ||
| 794 | } | ||
| 795 | |||
| 796 | static void | ||
| 797 | cube_to_arrays(Cube cube, CubeArray *arr, PieceFilter f) | ||
| 798 | { | ||
| 799 | int i; | ||
| 800 | |||
| 801 | if (f.epose || f.eposs || f.eposm) | ||
| 802 | for (i = 0; i < 12; i++) | ||
| 803 | arr->ep[i] = -1; | ||
| 804 | |||
| 805 | if (f.epose) | ||
| 806 | epos_to_partial_ep(cube.epose, arr->ep, epe_solved); | ||
| 807 | if (f.eposs) | ||
| 808 | epos_to_partial_ep(cube.eposs, arr->ep, eps_solved); | ||
| 809 | if (f.eposm) | ||
| 810 | epos_to_partial_ep(cube.eposm, arr->ep, epm_solved); | ||
| 811 | if (f.eofb) | ||
| 812 | int_to_sum_zero_array(cube.eofb, 2, 12, arr->eofb); | ||
| 813 | if (f.eorl) | ||
| 814 | int_to_sum_zero_array(cube.eorl, 2, 12, arr->eorl); | ||
| 815 | if (f.eoud) | ||
| 816 | int_to_sum_zero_array(cube.eoud, 2, 12, arr->eoud); | ||
| 817 | if (f.cp) | ||
| 818 | index_to_perm(cube.cp, 8, arr->cp); | ||
| 819 | if (f.coud) | ||
| 820 | int_to_sum_zero_array(cube.coud, 3, 8, arr->coud); | ||
| 821 | if (f.corl) | ||
| 822 | int_to_sum_zero_array(cube.corl, 3, 8, arr->corl); | ||
| 823 | if (f.cofb) | ||
| 824 | int_to_sum_zero_array(cube.cofb, 3, 8, arr->cofb); | ||
| 825 | if (f.cpos) | ||
| 826 | index_to_perm(cube.cpos, 6, arr->cpos); | ||
| 827 | } | ||
| 828 | |||
| 829 | /* | ||
| 830 | static int | ||
| 831 | cphtr_cp(int cp) | ||
| 832 | { | ||
| 833 | int i, a[8]; | ||
| 834 | |||
| 835 | index_to_perm(cp, 8, a); | ||
| 836 | |||
| 837 | for (i = 0; i < 8; i++) | ||
| 838 | if (a[i] == UFR || a[i] == UBL || a[i] == DFL || a[i] == DBR) | ||
| 839 | a[i] = 0; | ||
| 840 | else | ||
| 841 | a[i] = 1; | ||
| 842 | |||
| 843 | swap(&a[1], &a[5]); | ||
| 844 | swap(&a[3], &a[7]); | ||
| 845 | |||
| 846 | return subset_to_index(a, 8, 4); | ||
| 847 | } | ||
| 848 | */ | ||
| 849 | |||
| 850 | static void | ||
| 851 | dfs(Cube c, Step s, SolveOptions *opts, DfsData *dd) | ||
| 852 | { | ||
| 853 | if (dfs_stop(c, s, opts, dd)) | ||
| 854 | return; | ||
| 855 | |||
| 856 | if (dfs_check_solved(opts, dd)) | ||
| 857 | return; | ||
| 858 | |||
| 859 | dfs_branch(c, s, opts, dd); | ||
| 860 | |||
| 861 | if (opts->can_niss && !dd->niss) | ||
| 862 | dfs_niss(c, s, opts, dd); | ||
| 863 | } | ||
| 864 | |||
| 865 | static void | ||
| 866 | dfs_branch(Cube c, Step s, SolveOptions *opts, DfsData *dd) | ||
| 867 | { | ||
| 868 | Move m, l1 = dd->last1, l2 = dd->last2, *moves = dd->sorted_moves; | ||
| 869 | |||
| 870 | int i, maxnsol = opts->max_solutions; | ||
| 871 | |||
| 872 | for (i = 0; moves[i] != NULLMOVE && dd->sols->len < maxnsol; i++) { | ||
| 873 | m = moves[i]; | ||
| 874 | if (allowed_next(m, dd)) { | ||
| 875 | dd->last2 = dd->last1; | ||
| 876 | dd->last1 = m; | ||
| 877 | append_move(dd->current_alg, m, dd->niss); | ||
| 878 | |||
| 879 | dfs(apply_move(m, c), s, opts, dd); | ||
| 880 | |||
| 881 | dd->current_alg->len--; | ||
| 882 | dd->last2 = l2; | ||
| 883 | dd->last1 = l1; | ||
| 884 | } | ||
| 885 | } | ||
| 886 | } | ||
| 887 | |||
| 888 | static bool | ||
| 889 | dfs_check_solved(SolveOptions *opts, DfsData *dd) | ||
| 890 | { | ||
| 891 | if (dd->lb != 0) | ||
| 892 | return false; | ||
| 893 | |||
| 894 | if (dd->current_alg->len == dd->d) { | ||
| 895 | append_alg(dd->sols, dd->current_alg); | ||
| 896 | |||
| 897 | if (opts->feedback) | ||
| 898 | print_alg(dd->current_alg, false); | ||
| 899 | } | ||
| 900 | |||
| 901 | return true; | ||
| 902 | } | ||
| 903 | |||
| 904 | static void | ||
| 905 | dfs_niss(Cube c, Step s, SolveOptions *opts, DfsData *dd) | ||
| 906 | { | ||
| 907 | Move l1 = dd->last1, l2 = dd->last2; | ||
| 908 | CubeTarget ct; | ||
| 909 | |||
| 910 | ct.cube = apply_move(inverse_move(l1), (Cube){0}); | ||
| 911 | ct.target = 1; | ||
| 912 | |||
| 913 | if (dd->current_alg->len == 0 || s.estimate(ct)) { | ||
| 914 | dd->niss = true; | ||
| 915 | dd->last1 = NULLMOVE; | ||
| 916 | dd->last2 = NULLMOVE; | ||
| 917 | |||
| 918 | dfs(inverse_cube(c), s, opts, dd); | ||
| 919 | |||
| 920 | dd->last1 = l1; | ||
| 921 | dd->last2 = l2; | ||
| 922 | dd->niss = false; | ||
| 923 | } | ||
| 924 | } | ||
| 925 | |||
| 926 | static bool | ||
| 927 | dfs_stop(Cube c, Step s, SolveOptions *opts, DfsData *dd) | ||
| 928 | { | ||
| 929 | CubeTarget ct = { | ||
| 930 | .cube = c, | ||
| 931 | .target = dd->d - dd->current_alg->len | ||
| 932 | }; | ||
| 933 | |||
| 934 | if (dd->sols->len >= opts->max_solutions) | ||
| 935 | return true; | ||
| 936 | |||
| 937 | dd->lb = s.estimate(ct); | ||
| 938 | if (opts->can_niss && !dd->niss) | ||
| 939 | dd->lb = MIN(1, dd->lb); | ||
| 940 | |||
| 941 | if (dd->current_alg->len + dd->lb > dd->d) | ||
| 942 | return true; | ||
| 943 | |||
| 944 | return false; | ||
| 945 | } | ||
| 946 | |||
| 947 | static int | ||
| 948 | digit_array_to_int(int *a, int n, int b) | ||
| 949 | { | ||
| 950 | int i, ret = 0, p = 1; | ||
| 951 | |||
| 952 | for (i = 0; i < n; i++, p *= b) | ||
| 953 | ret += a[i] * p; | ||
| 954 | |||
| 955 | return ret; | ||
| 956 | } | ||
| 957 | |||
| 958 | static int | ||
| 959 | edge_slice(Edge e) { | ||
| 960 | if (e < 0 || e > 11) | ||
| 961 | return -1; | ||
| 962 | |||
| 963 | if (e == FR || e == FL || e == BL || e == BR) | ||
| 964 | return 0; | ||
| 965 | if (e == UR || e == UL || e == DR || e == DL) | ||
| 966 | return 1; | ||
| 967 | |||
| 968 | return 2; | ||
| 969 | } | ||
| 970 | |||
| 971 | static int | ||
| 972 | epos_dependent_pos(int poss, int pose) | ||
| 973 | { | ||
| 974 | int ep[12] = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}; | ||
| 975 | int ep8[8] = {0, 0, 0, 0, 0, 0, 0, 0}; | ||
| 976 | int i, j; | ||
| 977 | |||
| 978 | epos_to_partial_ep(poss*FACTORIAL4, ep, eps_solved); | ||
| 979 | epos_to_partial_ep(pose*FACTORIAL4, ep, epe_solved); | ||
| 980 | |||
| 981 | for (i = 0, j = 0; i < 12; i++) | ||
| 982 | if (edge_slice(ep[i]) != 0) | ||
| 983 | ep8[j++] = (edge_slice(ep[i]) == 1) ? 1 : 0; | ||
| 984 | |||
| 985 | swap(&ep8[1], &ep8[4]); | ||
| 986 | swap(&ep8[3], &ep8[6]); | ||
| 987 | |||
| 988 | return subset_to_index(ep8, 8, 4); | ||
| 989 | } | ||
| 990 | |||
| 991 | static int | ||
| 992 | epos_from_arrays(int *epos, int *ep) | ||
| 993 | { | ||
| 994 | return FACTORIAL4 * subset_to_index(epos,12,4) + perm_to_index(ep,4); | ||
| 995 | } | ||
| 996 | |||
| 997 | static void | ||
| 998 | epos_to_partial_ep(int epos, int *ep, int *ss) | ||
| 999 | { | ||
| 1000 | int i, is, eposs[12], eps[4]; | ||
| 1001 | |||
| 1002 | index_to_perm(epos % FACTORIAL4, 4, eps); | ||
| 1003 | index_to_subset(epos / FACTORIAL4, 12, 4, eposs); | ||
| 1004 | |||
| 1005 | for (i = 0; i < 4; i++) | ||
| 1006 | swap(&eposs[ss[i]], &eposs[i+8]); | ||
| 1007 | |||
| 1008 | for (i = 0, is = 0; i < 12; i++) | ||
| 1009 | if (eposs[i]) | ||
| 1010 | ep[i] = ss[eps[is++]]; | ||
| 1011 | } | ||
| 1012 | |||
| 1013 | static int | ||
| 1014 | factorial(int n) | ||
| 1015 | { | ||
| 1016 | int i, ret = 1; | ||
| 1017 | |||
| 1018 | if (n < 0) | ||
| 1019 | return 0; | ||
| 1020 | |||
| 1021 | for (i = 1; i <= n; i++) | ||
| 1022 | ret *= i; | ||
| 1023 | |||
| 1024 | return ret; | ||
| 1025 | } | ||
| 1026 | |||
| 1027 | void | ||
| 1028 | free_alg(Alg *alg) | ||
| 1029 | { | ||
| 1030 | free(alg->move); | ||
| 1031 | free(alg->inv); | ||
| 1032 | free(alg); | ||
| 1033 | } | ||
| 1034 | |||
| 1035 | void | ||
| 1036 | free_alglist(AlgList *l) | ||
| 1037 | { | ||
| 1038 | AlgListNode *aux, *i = l->first; | ||
| 1039 | |||
| 1040 | while (i != NULL) { | ||
| 1041 | aux = i->next; | ||
| 1042 | free_alglistnode(i); | ||
| 1043 | i = aux; | ||
| 1044 | } | ||
| 1045 | free(l); | ||
| 1046 | } | ||
| 1047 | |||
| 1048 | void | ||
| 1049 | free_alglistnode(AlgListNode *aln) | ||
| 1050 | { | ||
| 1051 | free_alg(aln->alg); | ||
| 1052 | free(aln); | ||
| 1053 | } | ||
| 1054 | |||
| 1055 | static void | ||
| 1056 | free_cubearray(CubeArray *arr, PieceFilter f) | ||
| 1057 | { | ||
| 1058 | if (f.epose || f.eposs || f.eposm) | ||
| 1059 | free(arr->ep); | ||
| 1060 | if (f.eofb) | ||
| 1061 | free(arr->eofb); | ||
| 1062 | if (f.eorl) | ||
| 1063 | free(arr->eorl); | ||
| 1064 | if (f.eoud) | ||
| 1065 | free(arr->eoud); | ||
| 1066 | if (f.cp) | ||
| 1067 | free(arr->cp); | ||
| 1068 | if (f.coud) | ||
| 1069 | free(arr->coud); | ||
| 1070 | if (f.corl) | ||
| 1071 | free(arr->corl); | ||
| 1072 | if (f.cofb) | ||
| 1073 | free(arr->cofb); | ||
| 1074 | if (f.cpos) | ||
| 1075 | free(arr->cpos); | ||
| 1076 | |||
| 1077 | free(arr); | ||
| 1078 | } | ||
| 1079 | |||
| 1080 | static void | ||
| 1081 | genptable_bfs(PruneData *pd, int d, Move *ms) | ||
| 1082 | { | ||
| 1083 | uint64_t i; | ||
| 1084 | |||
| 1085 | for (i = 0; i < pd->coord->max; i++) | ||
| 1086 | if (ptableval_index(pd, i) == d) | ||
| 1087 | genptable_branch(pd, i, d, ms); | ||
| 1088 | } | ||
| 1089 | |||
| 1090 | static void | ||
| 1091 | genptable_branch(PruneData *pd, uint64_t ind, int d, Move *ms) | ||
| 1092 | { | ||
| 1093 | int i, j; | ||
| 1094 | Cube cc, c; | ||
| 1095 | |||
| 1096 | |||
| 1097 | for (i = 0; i < pd->ntrans; i++) { | ||
| 1098 | c = apply_trans(pd->trans[i], pd->coord->cube(ind)); | ||
| 1099 | for (j = 0; ms[j] != NULLMOVE; j++) { | ||
| 1100 | cc = apply_move(ms[j], c); | ||
| 1101 | if (ptableval(pd, cc) > d+1) | ||
| 1102 | ptable_update(pd, cc, d+1); | ||
| 1103 | } | ||
| 1104 | } | ||
| 1105 | } | ||
| 1106 | |||
| 1107 | static void | ||
| 1108 | gensym(SymData *sd) | ||
| 1109 | { | ||
| 1110 | uint64_t i, in, nreps = 0; | ||
| 1111 | int j; | ||
| 1112 | Cube c, d; | ||
| 1113 | |||
| 1114 | if (sd->generated) | ||
| 1115 | return; | ||
| 1116 | |||
| 1117 | sd->class = malloc(sd->coord->max * sizeof(uint64_t)); | ||
| 1118 | sd->rep = malloc(sd->coord->max * sizeof(Cube)); | ||
| 1119 | sd->transtorep = malloc(sd->coord->max * sizeof(Trans)); | ||
| 1120 | |||
| 1121 | if (read_symdata_file(sd)) { | ||
| 1122 | sd->generated = true; | ||
| 1123 | return; | ||
| 1124 | } | ||
| 1125 | |||
| 1126 | fprintf(stderr, "Cannot load %s, generating it\n", sd->filename); | ||
| 1127 | |||
| 1128 | for (i = 0; i < sd->coord->max; i++) | ||
| 1129 | sd->class[i] = sd->coord->max + 1; | ||
| 1130 | |||
| 1131 | for (i = 0; i < sd->coord->max; i++) { | ||
| 1132 | if (sd->class[i] == sd->coord->max + 1) { | ||
| 1133 | c = sd->coord->cube(i); | ||
| 1134 | sd->rep[nreps] = c; | ||
| 1135 | for (j = 0; j < sd->ntrans; j++) { | ||
| 1136 | d = apply_trans(sd->trans[j], c); | ||
| 1137 | in = sd->coord->index(d); | ||
| 1138 | |||
| 1139 | if (sd->class[in] == sd->coord->max + 1) { | ||
| 1140 | sd->class[in] = nreps; | ||
| 1141 | sd->transtorep[in] = | ||
| 1142 | inverse_trans(sd->trans[j]); | ||
| 1143 | } | ||
| 1144 | } | ||
| 1145 | nreps++; | ||
| 1146 | } | ||
| 1147 | } | ||
| 1148 | |||
| 1149 | sd->sym_coord->max = nreps; | ||
| 1150 | sd->rep = realloc(sd->rep, nreps * sizeof(Cube)); | ||
| 1151 | sd->generated = true; | ||
| 1152 | |||
| 1153 | fprintf(stderr, "Found %lu classes\n", nreps); | ||
| 1154 | |||
| 1155 | if (!write_symdata_file(sd)) | ||
| 1156 | fprintf(stderr, "Error writing SymData file\n"); | ||
| 1157 | |||
| 1158 | return; | ||
| 1159 | } | ||
| 1160 | |||
| 1161 | static void | ||
| 1162 | index_to_perm(int p, int n, int *r) | ||
| 1163 | { | ||
| 1164 | int *a = malloc(n * sizeof(int)); | ||
| 1165 | int i, j, c; | ||
| 1166 | |||
| 1167 | for (i = 0; i < n; i++) | ||
| 1168 | a[i] = 0; | ||
| 1169 | |||
| 1170 | if (p < 0 || p >= factorial(n)) | ||
| 1171 | for (i = 0; i < n; i++) | ||
| 1172 | r[i] = -1; | ||
| 1173 | |||
| 1174 | for (i = 0; i < n; i++) { | ||
| 1175 | c = 0; | ||
| 1176 | j = 0; | ||
| 1177 | while (c <= p / factorial(n-i-1)) | ||
| 1178 | c += a[j++] ? 0 : 1; | ||
| 1179 | r[i] = j-1; | ||
| 1180 | a[j-1] = 1; | ||
| 1181 | p %= factorial(n-i-1); | ||
| 1182 | } | ||
| 1183 | |||
| 1184 | free(a); | ||
| 1185 | } | ||
| 1186 | |||
| 1187 | static void | ||
| 1188 | index_to_subset(int s, int n, int k, int *r) | ||
| 1189 | { | ||
| 1190 | int i, j, v; | ||
| 1191 | |||
| 1192 | if (s < 0 || s >= binomial(n, k)) { | ||
| 1193 | for (i = 0; i < n; i++) | ||
| 1194 | r[i] = -1; | ||
| 1195 | return; | ||
| 1196 | } | ||
| 1197 | |||
| 1198 | for (i = 0; i < n; i++) { | ||
| 1199 | if (k == n-i) { | ||
| 1200 | for (j = i; j < n; j++) | ||
| 1201 | r[j] = 1; | ||
| 1202 | return; | ||
| 1203 | } | ||
| 1204 | |||
| 1205 | if (k == 0) { | ||
| 1206 | for (j = i; j < n; j++) | ||
| 1207 | r[j] = 0; | ||
| 1208 | return; | ||
| 1209 | } | ||
| 1210 | |||
| 1211 | v = binomial(n-i-1, k); | ||
| 1212 | if (s >= v) { | ||
| 1213 | r[i] = 1; | ||
| 1214 | k--; | ||
| 1215 | s -= v; | ||
| 1216 | } else { | ||
| 1217 | r[i] = 0; | ||
| 1218 | } | ||
| 1219 | } | ||
| 1220 | } | ||
| 1221 | |||
| 1222 | static void | ||
| 1223 | int_to_digit_array(int a, int b, int n, int *r) | ||
| 1224 | { | ||
| 1225 | int i; | ||
| 1226 | |||
| 1227 | if (b <= 1) | ||
| 1228 | for (i = 0; i < n; i++) | ||
| 1229 | r[i] = 0; | ||
| 1230 | else | ||
| 1231 | for (i = 0; i < n; i++, a /= b) | ||
| 1232 | r[i] = a % b; | ||
| 1233 | } | ||
| 1234 | |||
| 1235 | static void | ||
| 1236 | int_to_sum_zero_array(int x, int b, int n, int *a) | ||
| 1237 | { | ||
| 1238 | int i, s = 0; | ||
| 1239 | |||
| 1240 | if (b <= 1) { | ||
| 1241 | for (i = 0; i < n; i++) | ||
| 1242 | a[i] = 0; | ||
| 1243 | } else { | ||
| 1244 | int_to_digit_array(x, b, n-1, a); | ||
| 1245 | for (i = 0; i < n - 1; i++) | ||
| 1246 | s = (s + a[i]) % b; | ||
| 1247 | a[n-1] = (b - s) % b; | ||
| 1248 | } | ||
| 1249 | } | ||
| 1250 | |||
| 1251 | static int | ||
| 1252 | invert_digits(int a, int b, int n) | ||
| 1253 | { | ||
| 1254 | int i, ret, *r = malloc(n * sizeof(int)); | ||
| 1255 | |||
| 1256 | int_to_digit_array(a, b, n, r); | ||
| 1257 | for (i = 0; i < n; i++) | ||
| 1258 | r[i] = (b-r[i]) % b; | ||
| 1259 | |||
| 1260 | ret = digit_array_to_int(r, n, b); | ||
| 1261 | free(r); | ||
| 1262 | return ret; | ||
| 1263 | } | ||
| 1264 | |||
| 1265 | static bool | ||
| 1266 | is_perm(int *a, int n) | ||
| 1267 | { | ||
| 1268 | int *aux = malloc(n * sizeof(int)); | ||
| 1269 | int i; | ||
| 1270 | |||
| 1271 | for (i = 0; i < n; i++) | ||
| 1272 | if (a[i] < 0 || a[i] >= n) | ||
| 1273 | return false; | ||
| 1274 | else | ||
| 1275 | aux[a[i]] = 1; | ||
| 1276 | |||
| 1277 | for (i = 0; i < n; i++) | ||
| 1278 | if (!aux[i]) | ||
| 1279 | return false; | ||
| 1280 | |||
| 1281 | free(aux); | ||
| 1282 | |||
| 1283 | return true; | ||
| 1284 | } | ||
| 1285 | |||
| 1286 | static bool | ||
| 1287 | is_subset(int *a, int n, int k) | ||
| 1288 | { | ||
| 1289 | int i, sum = 0; | ||
| 1290 | |||
| 1291 | for (i = 0; i < n; i++) | ||
| 1292 | sum += a[i] ? 1 : 0; | ||
| 1293 | |||
| 1294 | return sum == k; | ||
| 1295 | } | ||
| 1296 | |||
| 1297 | static Cube | ||
| 1298 | move_via_arrays(CubeArray *arr, Cube c, PieceFilter f) | ||
| 1299 | { | ||
| 1300 | CubeArray *arrc = new_cubearray(c, f); | ||
| 1301 | Cube ret; | ||
| 1302 | |||
| 1303 | if (f.epose || f.eposs || f.eposm) | ||
| 1304 | apply_permutation(arr->ep, arrc->ep, 12); | ||
| 1305 | |||
| 1306 | if (f.eofb) { | ||
| 1307 | apply_permutation(arr->ep, arrc->eofb, 12); | ||
| 1308 | sum_arrays_mod(arr->eofb, arrc->eofb, 12, 2); | ||
| 1309 | } | ||
| 1310 | |||
| 1311 | if (f.eorl) { | ||
| 1312 | apply_permutation(arr->ep, arrc->eorl, 12); | ||
| 1313 | sum_arrays_mod(arr->eorl, arrc->eorl, 12, 2); | ||
| 1314 | } | ||
| 1315 | |||
| 1316 | if (f.eoud) { | ||
| 1317 | apply_permutation(arr->ep, arrc->eoud, 12); | ||
| 1318 | sum_arrays_mod(arr->eoud, arrc->eoud, 12, 2); | ||
| 1319 | } | ||
| 1320 | |||
| 1321 | if (f.cp) | ||
| 1322 | apply_permutation(arr->cp, arrc->cp, 8); | ||
| 1323 | |||
| 1324 | if (f.coud) { | ||
| 1325 | apply_permutation(arr->cp, arrc->coud, 8); | ||
| 1326 | sum_arrays_mod(arr->coud, arrc->coud, 8, 3); | ||
| 1327 | } | ||
| 1328 | |||
| 1329 | if (f.corl) { | ||
| 1330 | apply_permutation(arr->cp, arrc->corl, 8); | ||
| 1331 | sum_arrays_mod(arr->corl, arrc->corl, 8, 3); | ||
| 1332 | } | ||
| 1333 | |||
| 1334 | if (f.cofb) { | ||
| 1335 | apply_permutation(arr->cp, arrc->cofb, 8); | ||
| 1336 | sum_arrays_mod(arr->cofb, arrc->cofb, 8, 3); | ||
| 1337 | } | ||
| 1338 | |||
| 1339 | if (f.cpos) | ||
| 1340 | apply_permutation(arr->cpos, arrc->cpos, 6); | ||
| 1341 | |||
| 1342 | ret = arrays_to_cube(arrc, f); | ||
| 1343 | free_cubearray(arrc, f); | ||
| 1344 | |||
| 1345 | return ret; | ||
| 1346 | } | ||
| 1347 | |||
| 1348 | static void | ||
| 1349 | movelist_to_position(Move *movelist, int *position) | ||
| 1350 | { | ||
| 1351 | Move m; | ||
| 1352 | |||
| 1353 | for (m = 0; m < NMOVES && movelist[m] != NULLMOVE; m++) | ||
| 1354 | position[movelist[m]] = m; | ||
| 1355 | } | ||
| 1356 | |||
| 1357 | static void | ||
| 1358 | moveset_to_list(Moveset ms, Estimator f, Move *r) | ||
| 1359 | { | ||
| 1360 | CubeTarget ct = { .target = 1 }; | ||
| 1361 | int b[NMOVES]; | ||
| 1362 | int na = 0, nb = 0; | ||
| 1363 | Move i; | ||
| 1364 | |||
| 1365 | if (ms == NULL) { | ||
| 1366 | fprintf(stderr, "Error: no moveset given\n"); | ||
| 1367 | return; | ||
| 1368 | } | ||
| 1369 | |||
| 1370 | for (i = U; i < NMOVES; i++) { | ||
| 1371 | if (ms(i)) { | ||
| 1372 | ct.cube = apply_move(i, (Cube){0}); | ||
| 1373 | if (f != NULL && f(ct)) | ||
| 1374 | r[na++] = i; | ||
| 1375 | else | ||
| 1376 | b[nb++] = i; | ||
| 1377 | } | ||
| 1378 | } | ||
| 1379 | |||
| 1380 | memcpy(r + na, b, nb * sizeof(Move)); | ||
| 1381 | r[na+nb] = NULLMOVE; | ||
| 1382 | } | ||
| 1383 | |||
| 1384 | static AlgList * | ||
| 1385 | new_alglist() | ||
| 1386 | { | ||
| 1387 | AlgList *ret = malloc(sizeof(AlgList)); | ||
| 1388 | |||
| 1389 | ret->len = 0; | ||
| 1390 | ret->first = NULL; | ||
| 1391 | ret->last = NULL; | ||
| 1392 | |||
| 1393 | return ret; | ||
| 1394 | } | ||
| 1395 | |||
| 1396 | static CubeArray * | ||
| 1397 | new_cubearray(Cube cube, PieceFilter f) | ||
| 1398 | { | ||
| 1399 | CubeArray *arr = malloc(sizeof(CubeArray)); | ||
| 1400 | |||
| 1401 | if (f.epose || f.eposs || f.eposm) | ||
| 1402 | arr->ep = malloc(12 * sizeof(int)); | ||
| 1403 | if (f.eofb) | ||
| 1404 | arr->eofb = malloc(12 * sizeof(int)); | ||
| 1405 | if (f.eorl) | ||
| 1406 | arr->eorl = malloc(12 * sizeof(int)); | ||
| 1407 | if (f.eoud) | ||
| 1408 | arr->eoud = malloc(12 * sizeof(int)); | ||
| 1409 | if (f.cp) | ||
| 1410 | arr->cp = malloc(8 * sizeof(int)); | ||
| 1411 | if (f.coud) | ||
| 1412 | arr->coud = malloc(8 * sizeof(int)); | ||
| 1413 | if (f.corl) | ||
| 1414 | arr->corl = malloc(8 * sizeof(int)); | ||
| 1415 | if (f.cofb) | ||
| 1416 | arr->cofb = malloc(8 * sizeof(int)); | ||
| 1417 | if (f.cpos) | ||
| 1418 | arr->cpos = malloc(6 * sizeof(int)); | ||
| 1419 | |||
| 1420 | cube_to_arrays(cube, arr, f); | ||
| 1421 | |||
| 1422 | return arr; | ||
| 1423 | } | ||
| 1424 | |||
| 1425 | static int | ||
| 1426 | perm_sign(int *a, int n) | ||
| 1427 | { | ||
| 1428 | int i, j, ret = 0; | ||
| 1429 | |||
| 1430 | if (!is_perm(a,n)) | ||
| 1431 | return -1; | ||
| 1432 | |||
| 1433 | for (i = 0; i < n; i++) | ||
| 1434 | for (j = i+1; j < n; j++) | ||
| 1435 | ret += (a[i] > a[j]) ? 1 : 0; | ||
| 1436 | |||
| 1437 | return ret % 2; | ||
| 1438 | } | ||
| 1439 | |||
| 1440 | static int | ||
| 1441 | perm_to_index(int *a, int n) | ||
| 1442 | { | ||
| 1443 | int i, j, c, ret = 0; | ||
| 1444 | |||
| 1445 | if (!is_perm(a, n)) | ||
| 1446 | return -1; | ||
| 1447 | |||
| 1448 | for (i = 0; i < n; i++) { | ||
| 1449 | c = 0; | ||
| 1450 | for (j = i+1; j < n; j++) | ||
| 1451 | c += (a[i] > a[j]) ? 1 : 0; | ||
| 1452 | ret += factorial(n-i-1) * c; | ||
| 1453 | } | ||
| 1454 | |||
| 1455 | return ret; | ||
| 1456 | } | ||
| 1457 | |||
| 1458 | static int | ||
| 1459 | powint(int a, int b) | ||
| 1460 | { | ||
| 1461 | if (b < 0) | ||
| 1462 | return 0; | ||
| 1463 | if (b == 0) | ||
| 1464 | return 1; | ||
| 1465 | |||
| 1466 | if (b % 2) | ||
| 1467 | return a * powint(a, b-1); | ||
| 1468 | else | ||
| 1469 | return powint(a*a, b/2); | ||
| 1470 | } | ||
| 1471 | |||
| 1472 | static void | ||
| 1473 | ptable_update(PruneData *pd, Cube cube, int n) | ||
| 1474 | { | ||
| 1475 | uint64_t ind = pd->coord->index(cube); | ||
| 1476 | uint8_t oldval2 = pd->ptable[ind/2]; | ||
| 1477 | int other = (ind % 2) ? oldval2 % 16 : oldval2 / 16; | ||
| 1478 | |||
| 1479 | pd->ptable[ind/2] = (ind % 2) ? 16*n + other : 16*other + n; | ||
| 1480 | pd->n++; | ||
| 1481 | } | ||
| 1482 | |||
| 1483 | static int | ||
| 1484 | ptableval_index(PruneData *pd, uint64_t ind) | ||
| 1485 | { | ||
| 1486 | return (ind % 2) ? pd->ptable[ind/2] / 16 : pd->ptable[ind/2] % 16; | ||
| 1487 | } | ||
| 1488 | |||
| 1489 | static void | ||
| 1490 | realloc_alg(Alg *alg, int n) | ||
| 1491 | { | ||
| 1492 | if (alg == NULL) { | ||
| 1493 | fprintf(stderr, "Error: trying to reallocate NULL alg.\n"); | ||
| 1494 | return; | ||
| 1495 | } | ||
| 1496 | |||
| 1497 | if (n < alg->len) { | ||
| 1498 | fprintf(stderr, "Error: alg too long for reallocation "); | ||
| 1499 | fprintf(stderr, "(%d vs %d)\n", alg->len, n); | ||
| 1500 | return; | ||
| 1501 | } | ||
| 1502 | |||
| 1503 | if (n > 1000000) { | ||
| 1504 | fprintf(stderr, "Warning: very long alg,"); | ||
| 1505 | fprintf(stderr, "something might go wrong.\n"); | ||
| 1506 | } | ||
| 1507 | |||
| 1508 | alg->move = realloc(alg->move, n * sizeof(int)); | ||
| 1509 | alg->inv = realloc(alg->inv, n * sizeof(int)); | ||
| 1510 | alg->allocated = n; | ||
| 1511 | } | ||
| 1512 | |||
| 1513 | static bool | ||
| 1514 | read_mtables_file() | ||
| 1515 | { | ||
| 1516 | FILE *f; | ||
| 1517 | char fname[strlen(tabledir)+20]; | ||
| 1518 | int m, b = sizeof(int); | ||
| 1519 | bool r = true; | ||
| 1520 | |||
| 1521 | strcpy(fname, tabledir); | ||
| 1522 | strcat(fname, "/mtables"); | ||
| 1523 | |||
| 1524 | if ((f = fopen(fname, "rb")) == NULL) | ||
| 1525 | return false; | ||
| 1526 | |||
| 1527 | for (m = 0; m < NMOVES; m++) { | ||
| 1528 | r = r && fread(epose_mtable[m], b, me[0], f) == me[0]; | ||
| 1529 | r = r && fread(eposs_mtable[m], b, me[1], f) == me[1]; | ||
| 1530 | r = r && fread(eposm_mtable[m], b, me[2], f) == me[2]; | ||
| 1531 | r = r && fread(eofb_mtable[m], b, me[3], f) == me[3]; | ||
| 1532 | r = r && fread(eorl_mtable[m], b, me[4], f) == me[4]; | ||
| 1533 | r = r && fread(eoud_mtable[m], b, me[5], f) == me[5]; | ||
| 1534 | r = r && fread(cp_mtable[m], b, me[6], f) == me[6]; | ||
| 1535 | r = r && fread(coud_mtable[m], b, me[7], f) == me[7]; | ||
| 1536 | r = r && fread(corl_mtable[m], b, me[8], f) == me[8]; | ||
| 1537 | r = r && fread(cofb_mtable[m], b, me[9], f) == me[9]; | ||
| 1538 | r = r && fread(cpos_mtable[m], b, me[10], f) == me[10]; | ||
| 1539 | } | ||
| 1540 | |||
| 1541 | fclose(f); | ||
| 1542 | return r; | ||
| 1543 | } | ||
| 1544 | |||
| 1545 | static bool | ||
| 1546 | read_ptable_file(PruneData *pd) | ||
| 1547 | { | ||
| 1548 | FILE *f; | ||
| 1549 | char fname[strlen(tabledir)+100]; | ||
| 1550 | uint64_t r; | ||
| 1551 | |||
| 1552 | strcpy(fname, tabledir); | ||
| 1553 | strcat(fname, "/"); | ||
| 1554 | strcat(fname, pd->filename); | ||
| 1555 | |||
| 1556 | if ((f = fopen(fname, "rb")) == NULL) | ||
| 1557 | return false; | ||
| 1558 | |||
| 1559 | r = fread(pd->ptable, sizeof(uint8_t), ptablesize(pd), f); | ||
| 1560 | fclose(f); | ||
| 1561 | |||
| 1562 | return r == ptablesize(pd); | ||
| 1563 | } | ||
| 1564 | |||
| 1565 | static bool | ||
| 1566 | read_symdata_file(SymData *sd) | ||
| 1567 | { | ||
| 1568 | FILE *f; | ||
| 1569 | char fname[strlen(tabledir)+100]; | ||
| 1570 | uint64_t n = sd->coord->max, *sn = &sd->sym_coord->max; | ||
| 1571 | bool r = true; | ||
| 1572 | |||
| 1573 | strcpy(fname, tabledir); | ||
| 1574 | strcat(fname, "/"); | ||
| 1575 | strcat(fname, sd->filename); | ||
| 1576 | |||
| 1577 | if ((f = fopen(fname, "rb")) == NULL) | ||
| 1578 | return false; | ||
| 1579 | |||
| 1580 | r = r && fread(&sd->sym_coord->max, sizeof(uint64_t), 1, f) == 1; | ||
| 1581 | r = r && fread(sd->rep, sizeof(Cube), *sn, f) == *sn; | ||
| 1582 | r = r && fread(sd->class, sizeof(uint64_t), n, f) == n; | ||
| 1583 | r = r && fread(sd->transtorep, sizeof(Trans), n, f) == n; | ||
| 1584 | |||
| 1585 | fclose(f); | ||
| 1586 | return r; | ||
| 1587 | } | ||
| 1588 | |||
| 1589 | static bool | ||
| 1590 | read_ttables_file() | ||
| 1591 | { | ||
| 1592 | FILE *f; | ||
| 1593 | char fname[strlen(tabledir)+20]; | ||
| 1594 | int b = sizeof(int); | ||
| 1595 | bool r = true; | ||
| 1596 | Move m; | ||
| 1597 | |||
| 1598 | strcpy(fname, tabledir); | ||
| 1599 | strcat(fname, "/"); | ||
| 1600 | strcat(fname, "ttables"); | ||
| 1601 | |||
| 1602 | if ((f = fopen(fname, "rb")) == NULL) | ||
| 1603 | return false; | ||
| 1604 | |||
| 1605 | for (m = 0; m < NTRANS; m++) { | ||
| 1606 | r = r && fread(epose_ttable[m], b, me[0], f) == me[0]; | ||
| 1607 | r = r && fread(eposs_ttable[m], b, me[1], f) == me[1]; | ||
| 1608 | r = r && fread(eposm_ttable[m], b, me[2], f) == me[2]; | ||
| 1609 | r = r && fread(eo_ttable[m], b, me[3], f) == me[3]; | ||
| 1610 | r = r && fread(cp_ttable[m], b, me[6], f) == me[6]; | ||
| 1611 | r = r && fread(co_ttable[m], b, me[7], f) == me[7]; | ||
| 1612 | r = r && fread(cpos_ttable[m], b, me[10], f) == me[10]; | ||
| 1613 | r = r && fread(moves_ttable[m], b, me[11], f) == me[11]; | ||
| 1614 | } | ||
| 1615 | |||
| 1616 | fclose(f); | ||
| 1617 | return r; | ||
| 1618 | } | ||
| 1619 | |||
| 1620 | static Cube | ||
| 1621 | rotate_via_compose(Trans r, Cube c, PieceFilter f) | ||
| 1622 | { | ||
| 1623 | static int zero12[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; | ||
| 1624 | static int zero8[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; | ||
| 1625 | static CubeArray ma = { | ||
| 1626 | .ep = ep_mirror, | ||
| 1627 | .eofb = zero12, | ||
| 1628 | .eorl = zero12, | ||
| 1629 | .eoud = zero12, | ||
| 1630 | .cp = cp_mirror, | ||
| 1631 | .coud = zero8, | ||
| 1632 | .corl = zero8, | ||
| 1633 | .cofb = zero8, | ||
| 1634 | .cpos = cpos_mirror | ||
| 1635 | }; | ||
| 1636 | |||
| 1637 | Alg *inv = inverse_alg(rotation_algs[r % NROTATIONS]); | ||
| 1638 | Cube ret = {0}; | ||
| 1639 | |||
| 1640 | if (r >= NROTATIONS) | ||
| 1641 | ret = move_via_arrays(&ma, ret, f); | ||
| 1642 | ret = apply_alg_generic(inv, ret, f, true); | ||
| 1643 | |||
| 1644 | ret = compose_filtered(c, ret, f); | ||
| 1645 | |||
| 1646 | ret = apply_alg_generic(rotation_algs[r % NROTATIONS], ret, f, true); | ||
| 1647 | if (r >= NROTATIONS) | ||
| 1648 | ret = move_via_arrays(&ma, ret, f); | ||
| 1649 | |||
| 1650 | free_alg(inv); | ||
| 1651 | return ret; | ||
| 1652 | } | ||
| 1653 | |||
| 1654 | static int | ||
| 1655 | subset_to_index(int *a, int n, int k) | ||
| 1656 | { | ||
| 1657 | int i, ret = 0; | ||
| 1658 | |||
| 1659 | if (!is_subset(a, n, k)) | ||
| 1660 | return binomial(n, k); | ||
| 1661 | |||
| 1662 | for (i = 0; i < n; i++) { | ||
| 1663 | if (k == n-i) | ||
| 1664 | return ret; | ||
| 1665 | if (a[i]) { | ||
| 1666 | ret += binomial(n-i-1, k); | ||
| 1667 | k--; | ||
| 1668 | } | ||
| 1669 | } | ||
| 1670 | |||
| 1671 | return ret; | ||
| 1672 | } | ||
| 1673 | |||
| 1674 | static void | ||
| 1675 | sum_arrays_mod(int *src, int *dst, int n, int m) | ||
| 1676 | { | ||
| 1677 | int i; | ||
| 1678 | |||
| 1679 | for (i = 0; i < n; i++) | ||
| 1680 | dst[i] = (m <= 0) ? 0 : (src[i] + dst[i]) % m; | ||
| 1681 | } | ||
| 1682 | |||
| 1683 | static void | ||
| 1684 | swap(int *a, int *b) | ||
| 1685 | { | ||
| 1686 | int aux; | ||
| 1687 | |||
| 1688 | aux = *a; | ||
| 1689 | *a = *b; | ||
| 1690 | *b = aux; | ||
| 1691 | } | ||
| 1692 | |||
| 1693 | static bool | ||
| 1694 | write_mtables_file() | ||
| 1695 | { | ||
| 1696 | FILE *f; | ||
| 1697 | char fname[strlen(tabledir)+20]; | ||
| 1698 | int m, b = sizeof(int); | ||
| 1699 | bool r = true; | ||
| 1700 | |||
| 1701 | strcpy(fname, tabledir); | ||
| 1702 | strcat(fname, "/mtables"); | ||
| 1703 | |||
| 1704 | if ((f = fopen(fname, "wb")) == NULL) | ||
| 1705 | return false; | ||
| 1706 | |||
| 1707 | for (m = 0; m < NMOVES; m++) { | ||
| 1708 | r = r && fwrite(epose_mtable[m], b, me[0], f) == me[0]; | ||
| 1709 | r = r && fwrite(eposs_mtable[m], b, me[1], f) == me[1]; | ||
| 1710 | r = r && fwrite(eposm_mtable[m], b, me[2], f) == me[2]; | ||
| 1711 | r = r && fwrite(eofb_mtable[m], b, me[3], f) == me[3]; | ||
| 1712 | r = r && fwrite(eorl_mtable[m], b, me[4], f) == me[4]; | ||
| 1713 | r = r && fwrite(eoud_mtable[m], b, me[5], f) == me[5]; | ||
| 1714 | r = r && fwrite(cp_mtable[m], b, me[6], f) == me[6]; | ||
| 1715 | r = r && fwrite(coud_mtable[m], b, me[7], f) == me[7]; | ||
| 1716 | r = r && fwrite(corl_mtable[m], b, me[8], f) == me[8]; | ||
| 1717 | r = r && fwrite(cofb_mtable[m], b, me[9], f) == me[9]; | ||
| 1718 | r = r && fwrite(cpos_mtable[m], b, me[10], f) == me[10]; | ||
| 1719 | } | ||
| 1720 | |||
| 1721 | fclose(f); | ||
| 1722 | return r; | ||
| 1723 | } | ||
| 1724 | |||
| 1725 | static bool | ||
| 1726 | write_ptable_file(PruneData *pd) | ||
| 1727 | { | ||
| 1728 | FILE *f; | ||
| 1729 | char fname[strlen(tabledir)+100]; | ||
| 1730 | uint64_t written; | ||
| 1731 | |||
| 1732 | strcpy(fname, tabledir); | ||
| 1733 | strcat(fname, "/"); | ||
| 1734 | strcat(fname, pd->filename); | ||
| 1735 | |||
| 1736 | if ((f = fopen(fname, "wb")) == NULL) | ||
| 1737 | return false; | ||
| 1738 | |||
| 1739 | written = fwrite(pd->ptable, sizeof(uint8_t), ptablesize(pd), f); | ||
| 1740 | fclose(f); | ||
| 1741 | |||
| 1742 | return written == ptablesize(pd); | ||
| 1743 | } | ||
| 1744 | |||
| 1745 | static bool | ||
| 1746 | write_symdata_file(SymData *sd) | ||
| 1747 | { | ||
| 1748 | FILE *f; | ||
| 1749 | char fname[strlen(tabledir)+100]; | ||
| 1750 | uint64_t n = sd->coord->max, *sn = &sd->sym_coord->max; | ||
| 1751 | bool r = true; | ||
| 1752 | |||
| 1753 | strcpy(fname, tabledir); | ||
| 1754 | strcat(fname, "/"); | ||
| 1755 | strcat(fname, sd->filename); | ||
| 1756 | |||
| 1757 | if ((f = fopen(fname, "wb")) == NULL) | ||
| 1758 | return false; | ||
| 1759 | |||
| 1760 | r = r && fwrite(&sd->sym_coord->max, sizeof(uint64_t), 1, f) == 1; | ||
| 1761 | r = r && fwrite(sd->rep, sizeof(Cube), *sn, f) == *sn; | ||
| 1762 | r = r && fwrite(sd->class, sizeof(uint64_t), n, f) == n; | ||
| 1763 | r = r && fwrite(sd->transtorep, sizeof(Trans), n, f) == n; | ||
| 1764 | |||
| 1765 | fclose(f); | ||
| 1766 | return r; | ||
| 1767 | } | ||
| 1768 | |||
| 1769 | static bool | ||
| 1770 | write_ttables_file() | ||
| 1771 | { | ||
| 1772 | FILE *f; | ||
| 1773 | char fname[strlen(tabledir)+20]; | ||
| 1774 | bool r = true; | ||
| 1775 | int b = sizeof(int); | ||
| 1776 | Move m; | ||
| 1777 | |||
| 1778 | strcpy(fname, tabledir); | ||
| 1779 | strcat(fname, "/ttables"); | ||
| 1780 | |||
| 1781 | if ((f = fopen(fname, "wb")) == NULL) | ||
| 1782 | return false; | ||
| 1783 | |||
| 1784 | for (m = 0; m < NTRANS; m++) { | ||
| 1785 | r = r && fwrite(epose_ttable[m], b, me[0], f) == me[0]; | ||
| 1786 | r = r && fwrite(eposs_ttable[m], b, me[1], f) == me[1]; | ||
| 1787 | r = r && fwrite(eposm_ttable[m], b, me[2], f) == me[2]; | ||
| 1788 | r = r && fwrite(eo_ttable[m], b, me[3], f) == me[3]; | ||
| 1789 | r = r && fwrite(cp_ttable[m], b, me[6], f) == me[6]; | ||
| 1790 | r = r && fwrite(co_ttable[m], b, me[7], f) == me[7]; | ||
| 1791 | r = r && fwrite(cpos_ttable[m], b, me[10], f) == me[10]; | ||
| 1792 | r = r && fwrite(moves_ttable[m], b, me[11], f) == me[11]; | ||
| 1793 | } | ||
| 1794 | |||
| 1795 | fclose(f); | ||
| 1796 | return r; | ||
| 1797 | } | ||
| 1798 | |||
| 1799 | /* Init functions implementation *********************************************/ | ||
| 1800 | |||
| 1801 | static void | ||
| 1802 | init_auxtables() | ||
| 1803 | { | ||
| 1804 | Cube c1, c2; | ||
| 1805 | CubeArray *arr; | ||
| 1806 | uint64_t ui, uj; | ||
| 1807 | int i, j, k, auxarr[12]; | ||
| 1808 | bool cij, p1, p2; | ||
| 1809 | |||
| 1810 | for (ui = 0; ui < POW2TO11*BINOM12ON4; ui++) { | ||
| 1811 | k = (ui / POW2TO11) * 24; | ||
| 1812 | c1 = admissible_ep((Cube){ .epose = k }, pf_e); | ||
| 1813 | c1.eofb = ui % POW2TO11; | ||
| 1814 | c1 = admissible_eos_from_eofbepos(c1); | ||
| 1815 | admissible_ee_aux[ui] = c1; | ||
| 1816 | } | ||
| 1817 | |||
| 1818 | for (ui = 0; ui < FACTORIAL6; ui++) { | ||
| 1819 | arr = new_cubearray((Cube){.cpos = ui}, pf_cpos); | ||
| 1820 | for (i = 0; i < 6; i++) { | ||
| 1821 | what_center_at_aux[ui][i] = arr->cpos[i]; | ||
| 1822 | where_is_center_aux[ui][arr->cpos[i]] = i; | ||
| 1823 | } | ||
| 1824 | free_cubearray(arr, pf_cpos); | ||
| 1825 | } | ||
| 1826 | |||
| 1827 | for (ui = 0; ui < FACTORIAL8; ui++) { | ||
| 1828 | arr = new_cubearray((Cube){.cp = ui}, pf_cp); | ||
| 1829 | for (i = 0; i < 8; i++) { | ||
| 1830 | what_corner_at_aux[ui][i] = arr->cp[i]; | ||
| 1831 | where_is_corner_aux[ui][arr->cp[i]] = i; | ||
| 1832 | } | ||
| 1833 | free_cubearray(arr, pf_cp); | ||
| 1834 | } | ||
| 1835 | |||
| 1836 | for (ui = 0; ui < FACTORIAL12/FACTORIAL8; ui++) { | ||
| 1837 | arr = new_cubearray((Cube){.epose = ui}, pf_e); | ||
| 1838 | for (i = 0; i < 12; i++) | ||
| 1839 | if (edge_slice(arr->ep[i]) == 0) | ||
| 1840 | where_is_edge_aux[0][ui][arr->ep[i]] = i; | ||
| 1841 | free_cubearray(arr, pf_e); | ||
| 1842 | |||
| 1843 | arr = new_cubearray((Cube){.eposs = ui}, pf_s); | ||
| 1844 | for (i = 0; i < 12; i++) | ||
| 1845 | if (edge_slice(arr->ep[i]) == 1) | ||
| 1846 | where_is_edge_aux[1][ui][arr->ep[i]] = i; | ||
| 1847 | free_cubearray(arr, pf_s); | ||
| 1848 | |||
| 1849 | arr = new_cubearray((Cube){.eposm = ui}, pf_m); | ||
| 1850 | for (i = 0; i < 12; i++) | ||
| 1851 | if (edge_slice(arr->ep[i]) == 2) | ||
| 1852 | where_is_edge_aux[2][ui][arr->ep[i]] = i; | ||
| 1853 | free_cubearray(arr, pf_m); | ||
| 1854 | } | ||
| 1855 | |||
| 1856 | for (ui = 0; ui < POW3TO7; ui++) { | ||
| 1857 | int_to_sum_zero_array(ui, 3, 8, auxarr); | ||
| 1858 | what_orientation_last_corner_aux[ui] = auxarr[7]; | ||
| 1859 | } | ||
| 1860 | |||
| 1861 | for (ui = 0; ui < POW2TO11; ui++) { | ||
| 1862 | int_to_sum_zero_array(ui, 2, 12, auxarr); | ||
| 1863 | what_orientation_last_edge_aux[ui] = auxarr[11]; | ||
| 1864 | } | ||
| 1865 | |||
| 1866 | for (ui = 0; ui < BINOM12ON4; ui++) | ||
| 1867 | for (uj = 0; uj < BINOM12ON4; uj++) | ||
| 1868 | epos_dependent_aux[ui][uj]=epos_dependent_pos(ui, uj); | ||
| 1869 | |||
| 1870 | for (i = 0; i < NMOVES; i++) { | ||
| 1871 | for (j = 0; j < NMOVES; j++) { | ||
| 1872 | c1 = apply_move(i, apply_move(j, (Cube){0})); | ||
| 1873 | c2 = apply_move(j, apply_move(i, (Cube){0})); | ||
| 1874 | commute[i][j] = equal(c1, c2) && i && j; | ||
| 1875 | } | ||
| 1876 | } | ||
| 1877 | |||
| 1878 | for (i = 0; i < NMOVES; i++) { | ||
| 1879 | for (j = 0; j < NMOVES; j++) { | ||
| 1880 | for (k = 0; k < NMOVES; k++) { | ||
| 1881 | p1 = j && base_move(j) == base_move(k); | ||
| 1882 | p2 = i && base_move(i) == base_move(k); | ||
| 1883 | cij = commute[i][j]; | ||
| 1884 | possible_next[i][j][k] = !(p1 || (cij && p2)); | ||
| 1885 | } | ||
| 1886 | } | ||
| 1887 | } | ||
| 1888 | |||
| 1889 | for (i = 0; i < NMOVES; i++) | ||
| 1890 | inverse_move_aux[i] = i ? i + 2 - 2*((i-1)%3) : NULLMOVE; | ||
| 1891 | |||
| 1892 | /* Is there a more elegant way? */ | ||
| 1893 | inverse_trans_aux[uf] = uf; | ||
| 1894 | inverse_trans_aux[ur] = ul; | ||
| 1895 | inverse_trans_aux[ul] = ur; | ||
| 1896 | inverse_trans_aux[ub] = ub; | ||
| 1897 | |||
| 1898 | inverse_trans_aux[df] = df; | ||
| 1899 | inverse_trans_aux[dr] = dr; | ||
| 1900 | inverse_trans_aux[dl] = dl; | ||
| 1901 | inverse_trans_aux[db] = db; | ||
| 1902 | |||
| 1903 | inverse_trans_aux[rf] = lf; | ||
| 1904 | inverse_trans_aux[rd] = bl; | ||
| 1905 | inverse_trans_aux[rb] = rb; | ||
| 1906 | inverse_trans_aux[ru] = fr; | ||
| 1907 | |||
| 1908 | inverse_trans_aux[lf] = rf; | ||
| 1909 | inverse_trans_aux[ld] = br; | ||
| 1910 | inverse_trans_aux[lb] = lb; | ||
| 1911 | inverse_trans_aux[lu] = fl; | ||
| 1912 | |||
| 1913 | inverse_trans_aux[fu] = fu; | ||
| 1914 | inverse_trans_aux[fr] = ru; | ||
| 1915 | inverse_trans_aux[fd] = bu; | ||
| 1916 | inverse_trans_aux[fl] = lu; | ||
| 1917 | |||
| 1918 | inverse_trans_aux[bu] = fd; | ||
| 1919 | inverse_trans_aux[br] = ld; | ||
| 1920 | inverse_trans_aux[bd] = bd; | ||
| 1921 | inverse_trans_aux[bl] = rd; | ||
| 1922 | |||
| 1923 | inverse_trans_aux[uf_mirror] = uf_mirror; | ||
| 1924 | inverse_trans_aux[ur_mirror] = ur_mirror; | ||
| 1925 | inverse_trans_aux[ul_mirror] = ul_mirror; | ||
| 1926 | inverse_trans_aux[ub_mirror] = ub_mirror; | ||
| 1927 | |||
| 1928 | inverse_trans_aux[df_mirror] = df_mirror; | ||
| 1929 | inverse_trans_aux[dr_mirror] = dl_mirror; | ||
| 1930 | inverse_trans_aux[dl_mirror] = dr_mirror; | ||
| 1931 | inverse_trans_aux[db_mirror] = db_mirror; | ||
| 1932 | |||
| 1933 | inverse_trans_aux[rf_mirror] = rf_mirror; | ||
| 1934 | inverse_trans_aux[rd_mirror] = br_mirror; | ||
| 1935 | inverse_trans_aux[rb_mirror] = lb_mirror; | ||
| 1936 | inverse_trans_aux[ru_mirror] = fl_mirror; | ||
| 1937 | |||
| 1938 | inverse_trans_aux[lf_mirror] = lf_mirror; | ||
| 1939 | inverse_trans_aux[ld_mirror] = bl_mirror; | ||
| 1940 | inverse_trans_aux[lb_mirror] = rb_mirror; | ||
| 1941 | inverse_trans_aux[lu_mirror] = fr_mirror; | ||
| 1942 | |||
| 1943 | inverse_trans_aux[fu_mirror] = fu_mirror; | ||
| 1944 | inverse_trans_aux[fr_mirror] = lu_mirror; | ||
| 1945 | inverse_trans_aux[fd_mirror] = bu_mirror; | ||
| 1946 | inverse_trans_aux[fl_mirror] = ru_mirror; | ||
| 1947 | |||
| 1948 | inverse_trans_aux[bu_mirror] = fd_mirror; | ||
| 1949 | inverse_trans_aux[br_mirror] = rd_mirror; | ||
| 1950 | inverse_trans_aux[bd_mirror] = bd_mirror; | ||
| 1951 | inverse_trans_aux[bl_mirror] = ld_mirror; | ||
| 1952 | } | ||
| 1953 | |||
| 1954 | /* | ||
| 1955 | * There is certainly a bette way to do this, but for now I just use | ||
| 1956 | * a "graph coloring" algorithm to compute the left cosets, and I compose | ||
| 1957 | * with every possible cp to get the right cosets (it is possible that I am | ||
| 1958 | * mixing up left and right). | ||
| 1959 | * | ||
| 1960 | * For doing it better "Mathematically", we need 3 things: | ||
| 1961 | * - Checking that cp separates the orbits (UFR,UBL,DFL,DBR) and the other | ||
| 1962 | * This is easy and it is done in the commented function cphtr_cp(). | ||
| 1963 | * - Check that there is no ep/cp parity | ||
| 1964 | * - Check that we are not in the "3c" case; this is the part I don't | ||
| 1965 | * know how to do. | ||
| 1966 | */ | ||
| 1967 | static void | ||
| 1968 | init_cphtr_cosets() | ||
| 1969 | { | ||
| 1970 | unsigned int i; | ||
| 1971 | int c = 0, d = 0; | ||
| 1972 | |||
| 1973 | for (i = 0; i < FACTORIAL8; i++) { | ||
| 1974 | cphtr_left_cosets[i] = -1; | ||
| 1975 | cphtr_right_cosets[i] = -1; | ||
| 1976 | } | ||
| 1977 | |||
| 1978 | /* First we compute left cosets with a bfs */ | ||
| 1979 | for (i = 0; i < FACTORIAL8; i++) | ||
| 1980 | if (cphtr_left_cosets[i] == -1) | ||
| 1981 | init_cphtr_left_cosets_bfs(i, c++); | ||
| 1982 | |||
| 1983 | /* Then we compute right cosets using compose() */ | ||
| 1984 | for (i = 0; i < FACTORIAL8; i++) | ||
| 1985 | if (cphtr_right_cosets[i] == -1) | ||
| 1986 | init_cphtr_right_cosets_color(i, d++); | ||
| 1987 | } | ||
| 1988 | |||
| 1989 | static void | ||
| 1990 | init_cphtr_left_cosets_bfs(int i, int c) | ||
| 1991 | { | ||
| 1992 | int j, jj, k, next[FACTORIAL8], next2[FACTORIAL8], n, n2; | ||
| 1993 | Move moves[6] = {U2, D2, R2, L2, F2, B2}; | ||
| 1994 | |||
| 1995 | n = 1; | ||
| 1996 | next[0] = i; | ||
| 1997 | cphtr_left_cosets[i] = c; | ||
| 1998 | |||
| 1999 | while (n != 0) { | ||
| 2000 | for (j = 0, n2 = 0; j < n; j++) { | ||
| 2001 | for (k = 0; k < 6; k++) { | ||
| 2002 | jj = cp_mtable[moves[k]][next[j]]; | ||
| 2003 | if (cphtr_left_cosets[jj] == -1) { | ||
| 2004 | cphtr_left_cosets[jj] = c; | ||
| 2005 | next2[n2++] = jj; | ||
| 2006 | } | ||
| 2007 | } | ||
| 2008 | } | ||
| 2009 | |||
| 2010 | for (j = 0; j < n2; j++) | ||
| 2011 | next[j] = next2[j]; | ||
| 2012 | n = n2; | ||
| 2013 | } | ||
| 2014 | } | ||
| 2015 | |||
| 2016 | static void | ||
| 2017 | init_cphtr_right_cosets_color(int i, int d) | ||
| 2018 | { | ||
| 2019 | int cp; | ||
| 2020 | unsigned int j; | ||
| 2021 | |||
| 2022 | cphtr_right_rep[d] = i; | ||
| 2023 | for (j = 0; j < FACTORIAL8; j++) { | ||
| 2024 | if (cphtr_left_cosets[j] == 0) { | ||
| 2025 | /* TODO: use antindexer, it's nicer */ | ||
| 2026 | cp = compose((Cube){.cp = i}, (Cube){.cp = j}).cp; | ||
| 2027 | cphtr_right_cosets[cp] = d; | ||
| 2028 | } | ||
| 2029 | } | ||
| 2030 | } | ||
| 2031 | |||
| 2032 | static void | ||
| 2033 | init_environment() | ||
| 2034 | { | ||
| 2035 | char *nissydata = getenv("NISSYDATA"); | ||
| 2036 | char *localdata = getenv("XDG_DATA_HOME"); | ||
| 2037 | char *home = getenv("HOME"); | ||
| 2038 | bool read, write; | ||
| 2039 | |||
| 2040 | if (nissydata != NULL) { | ||
| 2041 | tabledir = malloc(strlen(nissydata) * sizeof(char) + 20); | ||
| 2042 | strcpy(tabledir, nissydata); | ||
| 2043 | } else if (localdata != NULL) { | ||
| 2044 | tabledir = malloc(strlen(localdata) * sizeof(char) + 20); | ||
| 2045 | strcpy(tabledir, localdata); | ||
| 2046 | strcat(tabledir, "/nissy"); | ||
| 2047 | } else if (home != NULL) { | ||
| 2048 | tabledir = malloc(strlen(home) * sizeof(char) + 20); | ||
| 2049 | strcpy(tabledir, home); | ||
| 2050 | strcat(tabledir, "/.nissy"); | ||
| 2051 | } | ||
| 2052 | |||
| 2053 | mkdir(tabledir, 0777); | ||
| 2054 | strcat(tabledir, "/tables"); | ||
| 2055 | mkdir(tabledir, 0777); | ||
| 2056 | |||
| 2057 | read = !access(tabledir, R_OK); | ||
| 2058 | write = !access(tabledir, W_OK); | ||
| 2059 | |||
| 2060 | if (!read) { | ||
| 2061 | fprintf(stderr, "Table files cannot be read.\n"); | ||
| 2062 | } else if (!write) { | ||
| 2063 | fprintf(stderr, "Data directory not writable: "); | ||
| 2064 | fprintf(stderr, "tables can be loaded, but not saved.\n"); | ||
| 2065 | } | ||
| 2066 | } | ||
| 2067 | |||
| 2068 | static void | ||
| 2069 | init_moves() { | ||
| 2070 | Cube c; | ||
| 2071 | CubeArray arrs; | ||
| 2072 | int i; | ||
| 2073 | unsigned int ui; | ||
| 2074 | Move m; | ||
| 2075 | |||
| 2076 | /* Generate all move cycles and flips; I do this regardless */ | ||
| 2077 | for (i = 0; i < NMOVES; i++) { | ||
| 2078 | if (i == U || i == x || i == y) | ||
| 2079 | continue; | ||
| 2080 | |||
| 2081 | c = apply_alg_generic(equiv_alg[i], (Cube){0}, pf_all, false); | ||
| 2082 | |||
| 2083 | arrs = (CubeArray) { | ||
| 2084 | edge_cycle[i], | ||
| 2085 | eofb_flipped[i], | ||
| 2086 | eorl_flipped[i], | ||
| 2087 | eoud_flipped[i], | ||
| 2088 | corner_cycle[i], | ||
| 2089 | coud_flipped[i], | ||
| 2090 | corl_flipped[i], | ||
| 2091 | cofb_flipped[i], | ||
| 2092 | center_cycle[i] | ||
| 2093 | }; | ||
| 2094 | cube_to_arrays(c, &arrs, pf_all); | ||
| 2095 | } | ||
| 2096 | |||
| 2097 | if (read_mtables_file()) | ||
| 2098 | return; | ||
| 2099 | |||
| 2100 | fprintf(stderr, "Cannot load %s, generating it\n", "mtables"); | ||
| 2101 | |||
| 2102 | /* Initialize transition tables */ | ||
| 2103 | for (m = 0; m < NMOVES; m++) { | ||
| 2104 | for (ui = 0; ui < FACTORIAL12/FACTORIAL8; ui++) { | ||
| 2105 | c = (Cube){ .epose = ui }; | ||
| 2106 | c = apply_move_cubearray(m, c, pf_e); | ||
| 2107 | epose_mtable[m][ui] = c.epose; | ||
| 2108 | |||
| 2109 | c = (Cube){ .eposs = ui }; | ||
| 2110 | c = apply_move_cubearray(m, c, pf_s); | ||
| 2111 | eposs_mtable[m][ui] = c.eposs; | ||
| 2112 | |||
| 2113 | c = (Cube){ .eposm = ui }; | ||
| 2114 | c = apply_move_cubearray(m, c, pf_m); | ||
| 2115 | eposm_mtable[m][ui] = c.eposm; | ||
| 2116 | } | ||
| 2117 | for (ui = 0; ui < POW2TO11; ui++ ) { | ||
| 2118 | c = (Cube){ .eofb = ui }; | ||
| 2119 | c = apply_move_cubearray(m, c, pf_eo); | ||
| 2120 | eofb_mtable[m][ui] = c.eofb; | ||
| 2121 | |||
| 2122 | c = (Cube){ .eorl = ui }; | ||
| 2123 | c = apply_move_cubearray(m, c, pf_eo); | ||
| 2124 | eorl_mtable[m][ui] = c.eorl; | ||
| 2125 | |||
| 2126 | c = (Cube){ .eoud = ui }; | ||
| 2127 | c = apply_move_cubearray(m, c, pf_eo); | ||
| 2128 | eoud_mtable[m][ui] = c.eoud; | ||
| 2129 | } | ||
| 2130 | for (ui = 0; ui < POW3TO7; ui++) { | ||
| 2131 | c = (Cube){ .coud = ui }; | ||
| 2132 | c = apply_move_cubearray(m, c, pf_co); | ||
| 2133 | coud_mtable[m][ui] = c.coud; | ||
| 2134 | |||
| 2135 | c = (Cube){ .corl = ui }; | ||
| 2136 | c = apply_move_cubearray(m, c, pf_co); | ||
| 2137 | corl_mtable[m][ui] = c.corl; | ||
| 2138 | |||
| 2139 | c = (Cube){ .cofb = ui }; | ||
| 2140 | c = apply_move_cubearray(m, c, pf_co); | ||
| 2141 | cofb_mtable[m][ui] = c.cofb; | ||
| 2142 | } | ||
| 2143 | for (ui = 0; ui < FACTORIAL8; ui++) { | ||
| 2144 | c = (Cube){ .cp = ui }; | ||
| 2145 | c = apply_move_cubearray(m, c, pf_cp); | ||
| 2146 | cp_mtable[m][ui] = c.cp; | ||
| 2147 | } | ||
| 2148 | for (ui = 0; ui < FACTORIAL6; ui++) { | ||
| 2149 | c = (Cube){ .cpos = ui }; | ||
| 2150 | c = apply_move_cubearray(m, c, pf_cpos); | ||
| 2151 | cpos_mtable[m][ui] = c.cpos; | ||
| 2152 | } | ||
| 2153 | } | ||
| 2154 | |||
| 2155 | if (!write_mtables_file()) | ||
| 2156 | fprintf(stderr, "Error writing mtables\n"); | ||
| 2157 | } | ||
| 2158 | |||
| 2159 | static void | ||
| 2160 | init_moves_aux() | ||
| 2161 | { | ||
| 2162 | /* Some standard PieceFilters */ | ||
| 2163 | pf_all.epose = true; | ||
| 2164 | pf_all.eposs = true; | ||
| 2165 | pf_all.eposm = true; | ||
| 2166 | pf_all.eofb = true; | ||
| 2167 | pf_all.eorl = true; | ||
| 2168 | pf_all.eoud = true; | ||
| 2169 | pf_all.cp = true; | ||
| 2170 | pf_all.cofb = true; | ||
| 2171 | pf_all.corl = true; | ||
| 2172 | pf_all.coud = true; | ||
| 2173 | pf_all.cpos = true; | ||
| 2174 | |||
| 2175 | pf_4val.epose = true; | ||
| 2176 | pf_4val.eposs = true; | ||
| 2177 | pf_4val.eposm = true; | ||
| 2178 | pf_4val.eofb = true; | ||
| 2179 | pf_4val.coud = true; | ||
| 2180 | pf_4val.cp = true; | ||
| 2181 | |||
| 2182 | pf_epcp.epose = true; | ||
| 2183 | pf_epcp.eposs = true; | ||
| 2184 | pf_epcp.eposm = true; | ||
| 2185 | pf_epcp.cp = true; | ||
| 2186 | |||
| 2187 | pf_cpos.cpos = true; | ||
| 2188 | |||
| 2189 | pf_cp.cp = true; | ||
| 2190 | |||
| 2191 | pf_ep.epose = true; | ||
| 2192 | pf_ep.eposs = true; | ||
| 2193 | pf_ep.eposm = true; | ||
| 2194 | |||
| 2195 | pf_e.epose = true; | ||
| 2196 | pf_s.eposs = true; | ||
| 2197 | pf_m.eposm = true; | ||
| 2198 | |||
| 2199 | pf_eo.eofb = true; | ||
| 2200 | pf_eo.eorl = true; | ||
| 2201 | pf_eo.eoud = true; | ||
| 2202 | |||
| 2203 | pf_co.cofb = true; | ||
| 2204 | pf_co.corl = true; | ||
| 2205 | pf_co.coud = true; | ||
| 2206 | |||
| 2207 | /* Used to convert to and from CubeArray */ | ||
| 2208 | epe_solved[0] = FR; | ||
| 2209 | epe_solved[1] = FL; | ||
| 2210 | epe_solved[2] = BL; | ||
| 2211 | epe_solved[3] = BR; | ||
| 2212 | |||
| 2213 | eps_solved[0] = UL; | ||
| 2214 | eps_solved[1] = UR; | ||
| 2215 | eps_solved[2] = DL; | ||
| 2216 | eps_solved[3] = DR; | ||
| 2217 | |||
| 2218 | epm_solved[0] = UF; | ||
| 2219 | epm_solved[1] = UB; | ||
| 2220 | epm_solved[2] = DF; | ||
| 2221 | epm_solved[3] = DB; | ||
| 2222 | |||
| 2223 | /* Table sizes, used for reading and writing files */ | ||
| 2224 | me[0] = FACTORIAL12/FACTORIAL8; | ||
| 2225 | me[1] = FACTORIAL12/FACTORIAL8; | ||
| 2226 | me[2] = FACTORIAL12/FACTORIAL8; | ||
| 2227 | me[3] = POW2TO11; | ||
| 2228 | me[4] = POW2TO11; | ||
| 2229 | me[5] = POW2TO11; | ||
| 2230 | me[6] = FACTORIAL8; | ||
| 2231 | me[7] = POW3TO7; | ||
| 2232 | me[8] = POW3TO7; | ||
| 2233 | me[9] = POW3TO7; | ||
| 2234 | me[10] = FACTORIAL6; | ||
| 2235 | me[11] = NMOVES; | ||
| 2236 | |||
| 2237 | /* Cycles *********************/ | ||
| 2238 | edge_cycle[U][UF] = UR; | ||
| 2239 | edge_cycle[U][UL] = UF; | ||
| 2240 | edge_cycle[U][UB] = UL; | ||
| 2241 | edge_cycle[U][UR] = UB; | ||
| 2242 | edge_cycle[U][DF] = DF; | ||
| 2243 | edge_cycle[U][DL] = DL; | ||
| 2244 | edge_cycle[U][DB] = DB; | ||
| 2245 | edge_cycle[U][DR] = DR; | ||
| 2246 | edge_cycle[U][FR] = FR; | ||
| 2247 | edge_cycle[U][FL] = FL; | ||
| 2248 | edge_cycle[U][BL] = BL; | ||
| 2249 | edge_cycle[U][BR] = BR; | ||
| 2250 | |||
| 2251 | edge_cycle[x][UF] = DF; | ||
| 2252 | edge_cycle[x][UL] = FL; | ||
| 2253 | edge_cycle[x][UB] = UF; | ||
| 2254 | edge_cycle[x][UR] = FR; | ||
| 2255 | edge_cycle[x][DF] = DB; | ||
| 2256 | edge_cycle[x][DL] = BL; | ||
| 2257 | edge_cycle[x][DB] = UB; | ||
| 2258 | edge_cycle[x][DR] = BR; | ||
| 2259 | edge_cycle[x][FR] = DR; | ||
| 2260 | edge_cycle[x][FL] = DL; | ||
| 2261 | edge_cycle[x][BL] = UL; | ||
| 2262 | edge_cycle[x][BR] = UR; | ||
| 2263 | |||
| 2264 | edge_cycle[y][UF] = UR; | ||
| 2265 | edge_cycle[y][UL] = UF; | ||
| 2266 | edge_cycle[y][UB] = UL; | ||
| 2267 | edge_cycle[y][UR] = UB; | ||
| 2268 | edge_cycle[y][DF] = DR; | ||
| 2269 | edge_cycle[y][DL] = DF; | ||
| 2270 | edge_cycle[y][DB] = DL; | ||
| 2271 | edge_cycle[y][DR] = DB; | ||
| 2272 | edge_cycle[y][FR] = BR; | ||
| 2273 | edge_cycle[y][FL] = FR; | ||
| 2274 | edge_cycle[y][BL] = FL; | ||
| 2275 | edge_cycle[y][BR] = BL; | ||
| 2276 | |||
| 2277 | corner_cycle[U][UFR] = UBR; | ||
| 2278 | corner_cycle[U][UFL] = UFR; | ||
| 2279 | corner_cycle[U][UBL] = UFL; | ||
| 2280 | corner_cycle[U][UBR] = UBL; | ||
| 2281 | corner_cycle[U][DFR] = DFR; | ||
| 2282 | corner_cycle[U][DFL] = DFL; | ||
| 2283 | corner_cycle[U][DBL] = DBL; | ||
| 2284 | corner_cycle[U][DBR] = DBR; | ||
| 2285 | |||
| 2286 | corner_cycle[x][UFR] = DFR; | ||
| 2287 | corner_cycle[x][UFL] = DFL; | ||
| 2288 | corner_cycle[x][UBL] = UFL; | ||
| 2289 | corner_cycle[x][UBR] = UFR; | ||
| 2290 | corner_cycle[x][DFR] = DBR; | ||
| 2291 | corner_cycle[x][DFL] = DBL; | ||
| 2292 | corner_cycle[x][DBL] = UBL; | ||
| 2293 | corner_cycle[x][DBR] = UBR; | ||
| 2294 | |||
| 2295 | corner_cycle[y][UFR] = UBR; | ||
| 2296 | corner_cycle[y][UFL] = UFR; | ||
| 2297 | corner_cycle[y][UBL] = UFL; | ||
| 2298 | corner_cycle[y][UBR] = UBL; | ||
| 2299 | corner_cycle[y][DFR] = DBR; | ||
| 2300 | corner_cycle[y][DFL] = DFR; | ||
| 2301 | corner_cycle[y][DBL] = DFL; | ||
| 2302 | corner_cycle[y][DBR] = DBL; | ||
| 2303 | |||
| 2304 | center_cycle[U][U_center] = U_center; | ||
| 2305 | center_cycle[U][D_center] = D_center; | ||
| 2306 | center_cycle[U][R_center] = R_center; | ||
| 2307 | center_cycle[U][L_center] = L_center; | ||
| 2308 | center_cycle[U][F_center] = F_center; | ||
| 2309 | center_cycle[U][B_center] = B_center; | ||
| 2310 | |||
| 2311 | center_cycle[x][U_center] = F_center; | ||
| 2312 | center_cycle[x][D_center] = B_center; | ||
| 2313 | center_cycle[x][R_center] = R_center; | ||
| 2314 | center_cycle[x][L_center] = L_center; | ||
| 2315 | center_cycle[x][F_center] = D_center; | ||
| 2316 | center_cycle[x][B_center] = U_center; | ||
| 2317 | |||
| 2318 | center_cycle[y][U_center] = U_center; | ||
| 2319 | center_cycle[y][D_center] = D_center; | ||
| 2320 | center_cycle[y][R_center] = B_center; | ||
| 2321 | center_cycle[y][L_center] = F_center; | ||
| 2322 | center_cycle[y][F_center] = R_center; | ||
| 2323 | center_cycle[y][B_center] = L_center; | ||
| 2324 | |||
| 2325 | /* Flipped pieces *************/ | ||
| 2326 | eofb_flipped[x][UF] = 1; | ||
| 2327 | eofb_flipped[x][UB] = 1; | ||
| 2328 | eofb_flipped[x][DF] = 1; | ||
| 2329 | eofb_flipped[x][DB] = 1; | ||
| 2330 | |||
| 2331 | eofb_flipped[y][FR] = 1; | ||
| 2332 | eofb_flipped[y][FL] = 1; | ||
| 2333 | eofb_flipped[y][BL] = 1; | ||
| 2334 | eofb_flipped[y][BR] = 1; | ||
| 2335 | |||
| 2336 | eorl_flipped[x][UF] = 1; | ||
| 2337 | eorl_flipped[x][UL] = 1; | ||
| 2338 | eorl_flipped[x][UB] = 1; | ||
| 2339 | eorl_flipped[x][UR] = 1; | ||
| 2340 | eorl_flipped[x][DF] = 1; | ||
| 2341 | eorl_flipped[x][DL] = 1; | ||
| 2342 | eorl_flipped[x][DB] = 1; | ||
| 2343 | eorl_flipped[x][DR] = 1; | ||
| 2344 | eorl_flipped[x][FR] = 1; | ||
| 2345 | eorl_flipped[x][FL] = 1; | ||
| 2346 | eorl_flipped[x][BL] = 1; | ||
| 2347 | eorl_flipped[x][BR] = 1; | ||
| 2348 | |||
| 2349 | eorl_flipped[y][FR] = 1; | ||
| 2350 | eorl_flipped[y][FL] = 1; | ||
| 2351 | eorl_flipped[y][BL] = 1; | ||
| 2352 | eorl_flipped[y][BR] = 1; | ||
| 2353 | |||
| 2354 | eoud_flipped[U][UF] = 1; | ||
| 2355 | eoud_flipped[U][UL] = 1; | ||
| 2356 | eoud_flipped[U][UB] = 1; | ||
| 2357 | eoud_flipped[U][UR] = 1; | ||
| 2358 | |||
| 2359 | eoud_flipped[x][UF] = 1; | ||
| 2360 | eoud_flipped[x][UB] = 1; | ||
| 2361 | eoud_flipped[x][DF] = 1; | ||
| 2362 | eoud_flipped[x][DB] = 1; | ||
| 2363 | |||
| 2364 | eoud_flipped[y][UF] = 1; | ||
| 2365 | eoud_flipped[y][UL] = 1; | ||
| 2366 | eoud_flipped[y][UB] = 1; | ||
| 2367 | eoud_flipped[y][UR] = 1; | ||
| 2368 | eoud_flipped[y][DF] = 1; | ||
| 2369 | eoud_flipped[y][DL] = 1; | ||
| 2370 | eoud_flipped[y][DB] = 1; | ||
| 2371 | eoud_flipped[y][DR] = 1; | ||
| 2372 | eoud_flipped[y][FR] = 1; | ||
| 2373 | eoud_flipped[y][FL] = 1; | ||
| 2374 | eoud_flipped[y][BL] = 1; | ||
| 2375 | eoud_flipped[y][BR] = 1; | ||
| 2376 | |||
| 2377 | coud_flipped[x][UFR] = 2; | ||
| 2378 | coud_flipped[x][UFL] = 1; | ||
| 2379 | coud_flipped[x][UBR] = 1; | ||
| 2380 | coud_flipped[x][UBL] = 2; | ||
| 2381 | coud_flipped[x][DFR] = 1; | ||
| 2382 | coud_flipped[x][DFL] = 2; | ||
| 2383 | coud_flipped[x][DBR] = 2; | ||
| 2384 | coud_flipped[x][DBL] = 1; | ||
| 2385 | |||
| 2386 | corl_flipped[U][UFR] = 1; | ||
| 2387 | corl_flipped[U][UFL] = 2; | ||
| 2388 | corl_flipped[U][UBL] = 1; | ||
| 2389 | corl_flipped[U][UBR] = 2; | ||
| 2390 | |||
| 2391 | corl_flipped[y][UFR] = 1; | ||
| 2392 | corl_flipped[y][UFL] = 2; | ||
| 2393 | corl_flipped[y][UBL] = 1; | ||
| 2394 | corl_flipped[y][UBR] = 2; | ||
| 2395 | corl_flipped[y][DFR] = 2; | ||
| 2396 | corl_flipped[y][DFL] = 1; | ||
| 2397 | corl_flipped[y][DBL] = 2; | ||
| 2398 | corl_flipped[y][DBR] = 1; | ||
| 2399 | |||
| 2400 | cofb_flipped[U][UFR] = 2; | ||
| 2401 | cofb_flipped[U][UFL] = 1; | ||
| 2402 | cofb_flipped[U][UBL] = 2; | ||
| 2403 | cofb_flipped[U][UBR] = 1; | ||
| 2404 | |||
| 2405 | cofb_flipped[x][UFR] = 1; | ||
| 2406 | cofb_flipped[x][UFL] = 2; | ||
| 2407 | cofb_flipped[x][UBL] = 1; | ||
| 2408 | cofb_flipped[x][UBR] = 2; | ||
| 2409 | cofb_flipped[x][DFR] = 2; | ||
| 2410 | cofb_flipped[x][DFL] = 1; | ||
| 2411 | cofb_flipped[x][DBL] = 2; | ||
| 2412 | cofb_flipped[x][DBR] = 1; | ||
| 2413 | |||
| 2414 | cofb_flipped[y][UFR] = 2; | ||
| 2415 | cofb_flipped[y][UFL] = 1; | ||
| 2416 | cofb_flipped[y][UBL] = 2; | ||
| 2417 | cofb_flipped[y][UBR] = 1; | ||
| 2418 | cofb_flipped[y][DFR] = 1; | ||
| 2419 | cofb_flipped[y][DFL] = 2; | ||
| 2420 | cofb_flipped[y][DBL] = 1; | ||
| 2421 | cofb_flipped[y][DBR] = 2; | ||
| 2422 | |||
| 2423 | /* Equivalent moves ***********/ | ||
| 2424 | equiv_alg[NULLMOVE] = new_alg(""); | ||
| 2425 | |||
| 2426 | equiv_alg[U] = new_alg(" U "); | ||
| 2427 | equiv_alg[U2] = new_alg(" UU "); | ||
| 2428 | equiv_alg[U3] = new_alg(" UUU "); | ||
| 2429 | equiv_alg[D] = new_alg(" xx U xx "); | ||
| 2430 | equiv_alg[D2] = new_alg(" xx UU xx "); | ||
| 2431 | equiv_alg[D3] = new_alg(" xx UUU xx "); | ||
| 2432 | equiv_alg[R] = new_alg(" yx U xxxyyy "); | ||
| 2433 | equiv_alg[R2] = new_alg(" yx UU xxxyyy "); | ||
| 2434 | equiv_alg[R3] = new_alg(" yx UUU xxxyyy "); | ||
| 2435 | equiv_alg[L] = new_alg(" yyyx U xxxy "); | ||
| 2436 | equiv_alg[L2] = new_alg(" yyyx UU xxxy "); | ||
| 2437 | equiv_alg[L3] = new_alg(" yyyx UUU xxxy "); | ||
| 2438 | equiv_alg[F] = new_alg(" x U xxx "); | ||
| 2439 | equiv_alg[F2] = new_alg(" x UU xxx "); | ||
| 2440 | equiv_alg[F3] = new_alg(" x UUU xxx "); | ||
| 2441 | equiv_alg[B] = new_alg(" xxx U x "); | ||
| 2442 | equiv_alg[B2] = new_alg(" xxx UU x "); | ||
| 2443 | equiv_alg[B3] = new_alg(" xxx UUU x "); | ||
| 2444 | |||
| 2445 | equiv_alg[Uw] = new_alg(" xx U xx y "); | ||
| 2446 | equiv_alg[Uw2] = new_alg(" xx UU xx yy "); | ||
| 2447 | equiv_alg[Uw3] = new_alg(" xx UUU xx yyy "); | ||
| 2448 | equiv_alg[Dw] = new_alg(" U yyy "); | ||
| 2449 | equiv_alg[Dw2] = new_alg(" UU yy "); | ||
| 2450 | equiv_alg[Dw3] = new_alg(" UUU y "); | ||
| 2451 | equiv_alg[Rw] = new_alg(" yyyx U xxxy x "); | ||
| 2452 | equiv_alg[Rw2] = new_alg(" yyyx UU xxxy xx "); | ||
| 2453 | equiv_alg[Rw3] = new_alg(" yyyx UUU xxxy xxx "); | ||
| 2454 | equiv_alg[Lw] = new_alg(" yx U xxxyyy xxx "); | ||
| 2455 | equiv_alg[Lw2] = new_alg(" yx UU xxxyyy xx "); | ||
| 2456 | equiv_alg[Lw3] = new_alg(" yx UUU xxxyyy x "); | ||
| 2457 | equiv_alg[Fw] = new_alg(" xxx U x yxxxyyy "); | ||
| 2458 | equiv_alg[Fw2] = new_alg(" xxx UU x yxxyyy "); | ||
| 2459 | equiv_alg[Fw3] = new_alg(" xxx UUU x yxyyy "); | ||
| 2460 | equiv_alg[Bw] = new_alg(" x U xxx yxyyy "); | ||
| 2461 | equiv_alg[Bw2] = new_alg(" x UU xxx yxxyyy "); | ||
| 2462 | equiv_alg[Bw3] = new_alg(" x UUU xxx yxxxyyy "); | ||
| 2463 | |||
| 2464 | equiv_alg[M] = new_alg(" yx U xx UUU yxyyy "); | ||
| 2465 | equiv_alg[M2] = new_alg(" yx UU xx UU xxxy "); | ||
| 2466 | equiv_alg[M3] = new_alg(" yx UUU xx U yxxxy "); | ||
| 2467 | equiv_alg[S] = new_alg(" x UUU xx U yyyx "); | ||
| 2468 | equiv_alg[S2] = new_alg(" x UU xx UU yyx "); | ||
| 2469 | equiv_alg[S3] = new_alg(" x U xx UUU yx "); | ||
| 2470 | equiv_alg[E] = new_alg(" U xx UUU xxyyy "); | ||
| 2471 | equiv_alg[E2] = new_alg(" UU xx UU xxyy "); | ||
| 2472 | equiv_alg[E3] = new_alg(" UUU xx U xxy "); | ||
| 2473 | |||
| 2474 | equiv_alg[x] = new_alg(" x "); | ||
| 2475 | equiv_alg[x2] = new_alg(" xx "); | ||
| 2476 | equiv_alg[x3] = new_alg(" xxx "); | ||
| 2477 | equiv_alg[y] = new_alg(" y "); | ||
| 2478 | equiv_alg[y2] = new_alg(" yy "); | ||
| 2479 | equiv_alg[y3] = new_alg(" yyy "); | ||
| 2480 | equiv_alg[z] = new_alg(" yyy x y "); | ||
| 2481 | equiv_alg[z2] = new_alg(" yy xx "); | ||
| 2482 | equiv_alg[z3] = new_alg(" y x yyy "); | ||
| 2483 | } | ||
| 2484 | |||
| 2485 | static void | ||
| 2486 | init_strings() | ||
| 2487 | { | ||
| 2488 | strcpy(move_string [NULLMOVE], "-" ); | ||
| 2489 | strcpy(move_string [U], "U" ); | ||
| 2490 | strcpy(move_string [U2], "U2" ); | ||
| 2491 | strcpy(move_string [U3], "U\'" ); | ||
| 2492 | strcpy(move_string [D], "D" ); | ||
| 2493 | strcpy(move_string [D2], "D2" ); | ||
| 2494 | strcpy(move_string [D3], "D\'" ); | ||
| 2495 | strcpy(move_string [R], "R" ); | ||
| 2496 | strcpy(move_string [R2], "R2" ); | ||
| 2497 | strcpy(move_string [R3], "R\'" ); | ||
| 2498 | strcpy(move_string [L], "L" ); | ||
| 2499 | strcpy(move_string [L2], "L2" ); | ||
| 2500 | strcpy(move_string [L3], "L\'" ); | ||
| 2501 | strcpy(move_string [F], "F" ); | ||
| 2502 | strcpy(move_string [F2], "F2" ); | ||
| 2503 | strcpy(move_string [F3], "F\'" ); | ||
| 2504 | strcpy(move_string [B], "B" ); | ||
| 2505 | strcpy(move_string [B2], "B2" ); | ||
| 2506 | strcpy(move_string [B3], "B\'" ); | ||
| 2507 | strcpy(move_string [Uw], "Uw" ); | ||
| 2508 | strcpy(move_string [Uw2], "Uw2" ); | ||
| 2509 | strcpy(move_string [Uw3], "Uw\'" ); | ||
| 2510 | strcpy(move_string [Dw], "Dw" ); | ||
| 2511 | strcpy(move_string [Dw2], "Dw2" ); | ||
| 2512 | strcpy(move_string [Dw3], "Dw\'" ); | ||
| 2513 | strcpy(move_string [Rw], "Rw" ); | ||
| 2514 | strcpy(move_string [Rw2], "Rw2" ); | ||
| 2515 | strcpy(move_string [Rw3], "Rw\'" ); | ||
| 2516 | strcpy(move_string [Lw], "Lw" ); | ||
| 2517 | strcpy(move_string [Lw2], "Lw2" ); | ||
| 2518 | strcpy(move_string [Lw3], "Lw\'" ); | ||
| 2519 | strcpy(move_string [Fw], "Fw" ); | ||
| 2520 | strcpy(move_string [Fw2], "Fw2" ); | ||
| 2521 | strcpy(move_string [Fw3], "Fw\'" ); | ||
| 2522 | strcpy(move_string [Bw], "Bw" ); | ||
| 2523 | strcpy(move_string [Bw2], "Bw2" ); | ||
| 2524 | strcpy(move_string [Bw3], "Bw\'" ); | ||
| 2525 | strcpy(move_string [M], "M" ); | ||
| 2526 | strcpy(move_string [M2], "M2" ); | ||
| 2527 | strcpy(move_string [M3], "M\'" ); | ||
| 2528 | strcpy(move_string [S], "S" ); | ||
| 2529 | strcpy(move_string [S2], "S2" ); | ||
| 2530 | strcpy(move_string [S3], "S\'" ); | ||
| 2531 | strcpy(move_string [E], "E" ); | ||
| 2532 | strcpy(move_string [E2], "E2" ); | ||
| 2533 | strcpy(move_string [E3], "E\'" ); | ||
| 2534 | strcpy(move_string [x], "x" ); | ||
| 2535 | strcpy(move_string [x2], "x2" ); | ||
| 2536 | strcpy(move_string [x3], "x\'" ); | ||
| 2537 | strcpy(move_string [y], "y" ); | ||
| 2538 | strcpy(move_string [y2], "y2" ); | ||
| 2539 | strcpy(move_string [y3], "y\'" ); | ||
| 2540 | strcpy(move_string [z], "z" ); | ||
| 2541 | strcpy(move_string [z2], "z2" ); | ||
| 2542 | strcpy(move_string [z3], "z\'" ); | ||
| 2543 | |||
| 2544 | strcpy(edge_string [UF], "UF" ); | ||
| 2545 | strcpy(edge_string [UL], "UL" ); | ||
| 2546 | strcpy(edge_string [UB], "UB" ); | ||
| 2547 | strcpy(edge_string [UR], "UR" ); | ||
| 2548 | strcpy(edge_string [DF], "DF" ); | ||
| 2549 | strcpy(edge_string [DL], "DL" ); | ||
| 2550 | strcpy(edge_string [DB], "DB" ); | ||
| 2551 | strcpy(edge_string [DR], "DR" ); | ||
| 2552 | strcpy(edge_string [FR], "FR" ); | ||
| 2553 | strcpy(edge_string [FL], "FL" ); | ||
| 2554 | strcpy(edge_string [BL], "BL" ); | ||
| 2555 | strcpy(edge_string [BR], "BR" ); | ||
| 2556 | |||
| 2557 | strcpy(corner_string [UFR], "UFR" ); | ||
| 2558 | strcpy(corner_string [UFL], "UFL" ); | ||
| 2559 | strcpy(corner_string [UBL], "UBL" ); | ||
| 2560 | strcpy(corner_string [UBR], "UBR" ); | ||
| 2561 | strcpy(corner_string [DFR], "DFR" ); | ||
| 2562 | strcpy(corner_string [DFL], "DFL" ); | ||
| 2563 | strcpy(corner_string [DBL], "DBL" ); | ||
| 2564 | strcpy(corner_string [DBR], "DBR" ); | ||
| 2565 | |||
| 2566 | strcpy(center_string [U_center], "U" ); | ||
| 2567 | strcpy(center_string [D_center], "D" ); | ||
| 2568 | strcpy(center_string [R_center], "R" ); | ||
| 2569 | strcpy(center_string [L_center], "L" ); | ||
| 2570 | strcpy(center_string [F_center], "F" ); | ||
| 2571 | strcpy(center_string [B_center], "B" ); | ||
| 2572 | } | ||
| 2573 | |||
| 2574 | static void | ||
| 2575 | init_symdata() | ||
| 2576 | { | ||
| 2577 | int i; | ||
| 2578 | |||
| 2579 | for (i = 0; i < n_all_symdata; i++) | ||
| 2580 | gensym(all_sd[i]); | ||
| 2581 | } | ||
| 2582 | |||
| 2583 | static void | ||
| 2584 | init_trans() { | ||
| 2585 | Cube aux, cube, mirr, c[3]; | ||
| 2586 | CubeArray epcp; | ||
| 2587 | int i, eparr[12], eoarr[12], cparr[8], coarr[8]; | ||
| 2588 | unsigned int ui; | ||
| 2589 | Move mi, move; | ||
| 2590 | Trans m; | ||
| 2591 | |||
| 2592 | /* Compute sources */ | ||
| 2593 | for (i = 0; i < NTRANS; i++) { | ||
| 2594 | cube = apply_alg(rotation_algs[i % NROTATIONS], (Cube){0}); | ||
| 2595 | |||
| 2596 | epose_source[i] = edge_slice(what_edge_at(cube, FR)); | ||
| 2597 | eposs_source[i] = edge_slice(what_edge_at(cube, UR)); | ||
| 2598 | eposm_source[i] = edge_slice(what_edge_at(cube, UF)); | ||
| 2599 | eofb_source[i] = what_center_at(cube, F_center)/2; | ||
| 2600 | eorl_source[i] = what_center_at(cube, R_center)/2; | ||
| 2601 | eoud_source[i] = what_center_at(cube, U_center)/2; | ||
| 2602 | coud_source[i] = what_center_at(cube, U_center)/2; | ||
| 2603 | cofb_source[i] = what_center_at(cube, F_center)/2; | ||
| 2604 | corl_source[i] = what_center_at(cube, R_center)/2; | ||
| 2605 | } | ||
| 2606 | |||
| 2607 | if (read_ttables_file()) | ||
| 2608 | return; | ||
| 2609 | |||
| 2610 | fprintf(stderr, "Cannot load %s, generating it\n", "ttables"); | ||
| 2611 | |||
| 2612 | /* Initialize tables */ | ||
| 2613 | for (m = 0; m < NTRANS; m++) { | ||
| 2614 | epcp = (CubeArray){ .ep = eparr, .cp = cparr }; | ||
| 2615 | cube = apply_alg(rotation_algs[m % NROTATIONS], (Cube){0}); | ||
| 2616 | cube_to_arrays(cube, &epcp, pf_epcp); | ||
| 2617 | if (m >= NROTATIONS) { | ||
| 2618 | apply_permutation(ep_mirror, eparr, 12); | ||
| 2619 | apply_permutation(cp_mirror, cparr, 8); | ||
| 2620 | } | ||
| 2621 | |||
| 2622 | for (ui = 0; ui < FACTORIAL12/FACTORIAL8; ui++) { | ||
| 2623 | c[0] = admissible_ep((Cube){ .epose = ui }, pf_e); | ||
| 2624 | c[1] = admissible_ep((Cube){ .eposs = ui }, pf_s); | ||
| 2625 | c[2] = admissible_ep((Cube){ .eposm = ui }, pf_m); | ||
| 2626 | |||
| 2627 | cube = rotate_via_compose(m,c[epose_source[m]],pf_ep); | ||
| 2628 | epose_ttable[m][ui] = cube.epose; | ||
| 2629 | |||
| 2630 | cube = rotate_via_compose(m,c[eposs_source[m]],pf_ep); | ||
| 2631 | eposs_ttable[m][ui] = cube.eposs; | ||
| 2632 | |||
| 2633 | cube = rotate_via_compose(m,c[eposm_source[m]],pf_ep); | ||
| 2634 | eposm_ttable[m][ui] = cube.eposm; | ||
| 2635 | } | ||
| 2636 | for (ui = 0; ui < POW2TO11; ui++ ) { | ||
| 2637 | int_to_sum_zero_array(ui, 2, 12, eoarr); | ||
| 2638 | apply_permutation(eparr, eoarr, 12); | ||
| 2639 | eo_ttable[m][ui] = digit_array_to_int(eoarr, 11, 2); | ||
| 2640 | } | ||
| 2641 | for (ui = 0; ui < POW3TO7; ui++) { | ||
| 2642 | int_to_sum_zero_array(ui, 3, 8, coarr); | ||
| 2643 | apply_permutation(cparr, coarr, 8); | ||
| 2644 | co_ttable[m][ui] = digit_array_to_int(coarr, 7, 3); | ||
| 2645 | if (m >= NROTATIONS) | ||
| 2646 | co_ttable[m][ui] = | ||
| 2647 | invert_digits(co_ttable[m][ui], 3, 7); | ||
| 2648 | } | ||
| 2649 | for (ui = 0; ui < FACTORIAL8; ui++) { | ||
| 2650 | cube = (Cube){ .cp = ui }; | ||
| 2651 | cube = rotate_via_compose(m, cube, pf_cp); | ||
| 2652 | cp_ttable[m][ui] = cube.cp; | ||
| 2653 | } | ||
| 2654 | for (ui = 0; ui < FACTORIAL6; ui++) { | ||
| 2655 | cube = (Cube){ .cpos = ui }; | ||
| 2656 | cube = rotate_via_compose(m, cube, pf_cpos); | ||
| 2657 | cpos_ttable[m][ui] = cube.cpos; | ||
| 2658 | } | ||
| 2659 | for (mi = 0; mi < NMOVES; mi++) { | ||
| 2660 | aux = apply_trans(m, apply_move(mi, (Cube){0})); | ||
| 2661 | for (move = 0; move < NMOVES; move++) { | ||
| 2662 | cube = apply_move(inverse_move_aux[move], aux); | ||
| 2663 | mirr = apply_trans(uf_mirror, cube); | ||
| 2664 | if (is_solved(cube, false) || | ||
| 2665 | is_solved(mirr, false)) | ||
| 2666 | moves_ttable[m][mi] = move; | ||
| 2667 | } | ||
| 2668 | } | ||
| 2669 | } | ||
| 2670 | |||
| 2671 | if (!write_ttables_file()) | ||
| 2672 | fprintf(stderr, "Error writing ttables\n"); | ||
| 2673 | } | ||
| 2674 | |||
| 2675 | static void | ||
| 2676 | init_trans_aux() | ||
| 2677 | { | ||
| 2678 | ep_mirror[UF] = UF; | ||
| 2679 | ep_mirror[UL] = UR; | ||
| 2680 | ep_mirror[UB] = UB; | ||
| 2681 | ep_mirror[UR] = UL; | ||
| 2682 | ep_mirror[DF] = DF; | ||
| 2683 | ep_mirror[DL] = DR; | ||
| 2684 | ep_mirror[DB] = DB; | ||
| 2685 | ep_mirror[DR] = DL; | ||
| 2686 | ep_mirror[FR] = FL; | ||
| 2687 | ep_mirror[FL] = FR; | ||
| 2688 | ep_mirror[BR] = BL; | ||
| 2689 | ep_mirror[BL] = BR; | ||
| 2690 | |||
| 2691 | cp_mirror[UFR] = UFL; | ||
| 2692 | cp_mirror[UFL] = UFR; | ||
| 2693 | cp_mirror[UBL] = UBR; | ||
| 2694 | cp_mirror[UBR] = UBL; | ||
| 2695 | cp_mirror[DFR] = DFL; | ||
| 2696 | cp_mirror[DFL] = DFR; | ||
| 2697 | cp_mirror[DBL] = DBR; | ||
| 2698 | cp_mirror[DBR] = DBL; | ||
| 2699 | |||
| 2700 | cpos_mirror[U_center] = U_center; | ||
| 2701 | cpos_mirror[D_center] = D_center; | ||
| 2702 | cpos_mirror[R_center] = L_center; | ||
| 2703 | cpos_mirror[L_center] = R_center; | ||
| 2704 | cpos_mirror[F_center] = F_center; | ||
| 2705 | cpos_mirror[B_center] = B_center; | ||
| 2706 | |||
| 2707 | /* Is there a more elegant way? */ | ||
| 2708 | rotation_algs[uf] = new_alg(""); | ||
| 2709 | rotation_algs[ur] = new_alg("y"); | ||
| 2710 | rotation_algs[ub] = new_alg("y2"); | ||
| 2711 | rotation_algs[ul] = new_alg("y3"); | ||
| 2712 | |||
| 2713 | rotation_algs[df] = new_alg("z2"); | ||
| 2714 | rotation_algs[dr] = new_alg("y z2"); | ||
| 2715 | rotation_algs[db] = new_alg("x2"); | ||
| 2716 | rotation_algs[dl] = new_alg("y3 z2"); | ||
| 2717 | |||
| 2718 | rotation_algs[rf] = new_alg("z3"); | ||
| 2719 | rotation_algs[rd] = new_alg("z3 y"); | ||
| 2720 | rotation_algs[rb] = new_alg("z3 y2"); | ||
| 2721 | rotation_algs[ru] = new_alg("z3 y3"); | ||
| 2722 | |||
| 2723 | rotation_algs[lf] = new_alg("z"); | ||
| 2724 | rotation_algs[ld] = new_alg("z y3"); | ||
| 2725 | rotation_algs[lb] = new_alg("z y2"); | ||
| 2726 | rotation_algs[lu] = new_alg("z y"); | ||
| 2727 | |||
| 2728 | rotation_algs[fu] = new_alg("x y2"); | ||
| 2729 | rotation_algs[fr] = new_alg("x y"); | ||
| 2730 | rotation_algs[fd] = new_alg("x"); | ||
| 2731 | rotation_algs[fl] = new_alg("x y3"); | ||
| 2732 | |||
| 2733 | rotation_algs[bu] = new_alg("x3"); | ||
| 2734 | rotation_algs[br] = new_alg("x3 y"); | ||
| 2735 | rotation_algs[bd] = new_alg("x3 y2"); | ||
| 2736 | rotation_algs[bl] = new_alg("x3 y3"); | ||
| 2737 | } | ||
| 2738 | |||
| 2739 | |||
| 2740 | /* Public functions implementation *******************************************/ | ||
| 2741 | |||
| 2742 | Cube | ||
| 2743 | apply_alg(Alg *alg, Cube cube) | ||
| 2744 | { | ||
| 2745 | return apply_alg_generic(alg, cube, pf_all, true); | ||
| 2746 | } | ||
| 2747 | |||
| 2748 | Cube | ||
| 2749 | apply_move(Move m, Cube cube) | ||
| 2750 | { | ||
| 2751 | return (Cube) { | ||
| 2752 | .epose = epose_mtable[m][cube.epose], | ||
| 2753 | .eposs = eposs_mtable[m][cube.eposs], | ||
| 2754 | .eposm = eposm_mtable[m][cube.eposm], | ||
| 2755 | .eofb = eofb_mtable[m][cube.eofb], | ||
| 2756 | .eorl = eorl_mtable[m][cube.eorl], | ||
| 2757 | .eoud = eoud_mtable[m][cube.eoud], | ||
| 2758 | .coud = coud_mtable[m][cube.coud], | ||
| 2759 | .cofb = cofb_mtable[m][cube.cofb], | ||
| 2760 | .corl = corl_mtable[m][cube.corl], | ||
| 2761 | .cp = cp_mtable[m][cube.cp], | ||
| 2762 | .cpos = cpos_mtable[m][cube.cpos] | ||
| 2763 | }; | ||
| 2764 | } | ||
| 2765 | |||
| 2766 | |||
| 2767 | Cube | ||
| 2768 | apply_trans(Trans t, Cube cube) | ||
| 2769 | { | ||
| 2770 | int aux_epos[3] = { cube.epose, cube.eposs, cube.eposm }; | ||
| 2771 | int aux_eo[3] = { cube.eoud, cube.eorl, cube.eofb }; | ||
| 2772 | int aux_co[3] = { cube.coud, cube.corl, cube.cofb }; | ||
| 2773 | |||
| 2774 | return (Cube) { | ||
| 2775 | .epose = epose_ttable[t][aux_epos[epose_source[t]]], | ||
| 2776 | .eposs = eposs_ttable[t][aux_epos[eposs_source[t]]], | ||
| 2777 | .eposm = eposm_ttable[t][aux_epos[eposm_source[t]]], | ||
| 2778 | .eofb = eo_ttable[t][aux_eo[eofb_source[t]]], | ||
| 2779 | .eorl = eo_ttable[t][aux_eo[eorl_source[t]]], | ||
| 2780 | .eoud = eo_ttable[t][aux_eo[eoud_source[t]]], | ||
| 2781 | .coud = co_ttable[t][aux_co[coud_source[t]]], | ||
| 2782 | .corl = co_ttable[t][aux_co[corl_source[t]]], | ||
| 2783 | .cofb = co_ttable[t][aux_co[cofb_source[t]]], | ||
| 2784 | .cp = cp_ttable[t][cube.cp], | ||
| 2785 | .cpos = cpos_ttable[t][cube.cpos] | ||
| 2786 | }; | ||
| 2787 | } | ||
| 2788 | |||
| 2789 | Move | ||
| 2790 | base_move(Move m) | ||
| 2791 | { | ||
| 2792 | if (m == NULLMOVE) | ||
| 2793 | return NULLMOVE; | ||
| 2794 | else | ||
| 2795 | return m - (m-1)%3; | ||
| 2796 | } | ||
| 2797 | |||
| 2798 | Cube | ||
| 2799 | compose(Cube c2, Cube c1) | ||
| 2800 | { | ||
| 2801 | return compose_filtered(c2, c1, pf_all); | ||
| 2802 | } | ||
| 2803 | |||
| 2804 | /*TODO maybe move the next two */ | ||
| 2805 | uint64_t | ||
| 2806 | cphtr(Cube cube) | ||
| 2807 | { | ||
| 2808 | return cphtr_right_cosets[cube.cp]; | ||
| 2809 | } | ||
| 2810 | |||
| 2811 | Cube | ||
| 2812 | anti_cphtr(uint64_t ind) | ||
| 2813 | { | ||
| 2814 | return (Cube) { .cp = cphtr_right_rep[ind] }; | ||
| 2815 | } | ||
| 2816 | |||
| 2817 | uint64_t | ||
| 2818 | epos_dependent(Cube c) | ||
| 2819 | { | ||
| 2820 | return epos_dependent_aux[c.eposs/FACTORIAL4][c.epose/FACTORIAL4]; | ||
| 2821 | } | ||
| 2822 | |||
| 2823 | bool | ||
| 2824 | equal(Cube c1, Cube c2) | ||
| 2825 | { | ||
| 2826 | return c1.eofb == c2.eofb && | ||
| 2827 | c1.epose == c2.epose && | ||
| 2828 | c1.eposs == c2.eposs && | ||
| 2829 | c1.eposm == c2.eposm && | ||
| 2830 | c1.coud == c2.coud && | ||
| 2831 | c1.cp == c2.cp && | ||
| 2832 | c1.cpos == c2.cpos; | ||
| 2833 | } | ||
| 2834 | |||
| 2835 | void | ||
| 2836 | genptable(PruneData *pd) | ||
| 2837 | { | ||
| 2838 | Move ms[NMOVES]; | ||
| 2839 | int d; | ||
| 2840 | uint64_t j, oldn = 0; | ||
| 2841 | |||
| 2842 | if (pd->generated) | ||
| 2843 | return; | ||
| 2844 | |||
| 2845 | /* TODO: check if memory is enough, otherwise maybe crash gracefully? */ | ||
| 2846 | pd->ptable = malloc(ptablesize(pd) * sizeof(uint8_t)); | ||
| 2847 | |||
| 2848 | if (read_ptable_file(pd)) { | ||
| 2849 | pd->generated = true; | ||
| 2850 | return; | ||
| 2851 | } | ||
| 2852 | |||
| 2853 | fprintf(stderr, "Cannot load %s, generating it\n", pd->filename); | ||
| 2854 | |||
| 2855 | moveset_to_list(pd->moveset, NULL, ms); | ||
| 2856 | |||
| 2857 | /* We use 4 bits per value, so any distance >= 15 is set to 15 */ | ||
| 2858 | for (j = 0; j < pd->coord->max; j++) | ||
| 2859 | ptable_update(pd, pd->coord->cube(j), 15); | ||
| 2860 | |||
| 2861 | /*TODO: change, set to 0 for every solved state (might be more than 1)*/ | ||
| 2862 | ptable_update(pd, (Cube){0}, 0); | ||
| 2863 | pd->n = 1; | ||
| 2864 | |||
| 2865 | for (d = 0; d < 15 && pd->n < pd->coord->max; d++) { | ||
| 2866 | genptable_bfs(pd, d, ms); | ||
| 2867 | fprintf(stderr, "Depth %d done, generated %lu\t(%lu/%lu)\n", | ||
| 2868 | d, pd->n - oldn, pd->n, pd->coord->max); | ||
| 2869 | oldn = pd->n; | ||
| 2870 | } | ||
| 2871 | |||
| 2872 | if (!write_ptable_file(pd)) | ||
| 2873 | fprintf(stderr, "Error writing ptable file\n"); | ||
| 2874 | |||
| 2875 | pd->generated = true; | ||
| 2876 | } | ||
| 2877 | |||
| 2878 | Cube | ||
| 2879 | inverse_cube(Cube cube) | ||
| 2880 | { | ||
| 2881 | CubeArray *arr = new_cubearray(cube, pf_all); | ||
| 2882 | CubeArray *inv = new_cubearray((Cube){0}, pf_all); | ||
| 2883 | Cube ret; | ||
| 2884 | int i; | ||
| 2885 | |||
| 2886 | for (i = 0; i < 12; i++) { | ||
| 2887 | inv->ep[arr->ep[i]] = i; | ||
| 2888 | inv->eofb[arr->ep[i]] = arr->eofb[i]; | ||
| 2889 | inv->eorl[arr->ep[i]] = arr->eorl[i]; | ||
| 2890 | inv->eoud[arr->ep[i]] = arr->eoud[i]; | ||
| 2891 | } | ||
| 2892 | |||
| 2893 | for (i = 0; i < 8; i++) { | ||
| 2894 | inv->cp[arr->cp[i]] = i; | ||
| 2895 | inv->coud[arr->cp[i]] = (3 - arr->coud[i]) % 3; | ||
| 2896 | inv->corl[arr->cp[i]] = (3 - arr->corl[i]) % 3; | ||
| 2897 | inv->cofb[arr->cp[i]] = (3 - arr->cofb[i]) % 3; | ||
| 2898 | } | ||
| 2899 | |||
| 2900 | for (int i = 0; i < 6; i++) | ||
| 2901 | inv->cpos[arr->cpos[i]] = i; | ||
| 2902 | |||
| 2903 | ret = arrays_to_cube(inv, pf_all); | ||
| 2904 | free_cubearray(arr, pf_all); | ||
| 2905 | free_cubearray(inv, pf_all); | ||
| 2906 | |||
| 2907 | return ret; | ||
| 2908 | } | ||
| 2909 | |||
| 2910 | Move | ||
| 2911 | inverse_move(Move m) | ||
| 2912 | { | ||
| 2913 | return inverse_move_aux[m]; | ||
| 2914 | } | ||
| 2915 | |||
| 2916 | Trans | ||
| 2917 | inverse_trans(Trans t) | ||
| 2918 | { | ||
| 2919 | return inverse_trans_aux[t]; | ||
| 2920 | } | ||
| 2921 | |||
| 2922 | bool | ||
| 2923 | is_admissible(Cube cube) | ||
| 2924 | { | ||
| 2925 | /* TODO: this should check consistency of different orientations */ | ||
| 2926 | /* TODO: check that centers are opposite and admissible */ | ||
| 2927 | |||
| 2928 | CubeArray *a = new_cubearray(cube, pf_all); | ||
| 2929 | int parity; | ||
| 2930 | bool perm; | ||
| 2931 | |||
| 2932 | perm = is_perm(a->ep, 12) && | ||
| 2933 | is_perm(a->cp, 8) && | ||
| 2934 | is_perm(a->cpos, 6); | ||
| 2935 | parity = perm_sign(a->ep, 12) + | ||
| 2936 | perm_sign(a->cp, 8) + | ||
| 2937 | perm_sign(a->cpos, 6); | ||
| 2938 | |||
| 2939 | return perm && parity % 2 == 0; | ||
| 2940 | } | ||
| 2941 | |||
| 2942 | bool | ||
| 2943 | is_solved(Cube cube, bool reorient) | ||
| 2944 | { | ||
| 2945 | int i; | ||
| 2946 | |||
| 2947 | if (reorient) { | ||
| 2948 | for (i = 0; i < NROTATIONS; i++) | ||
| 2949 | if (is_solved(apply_alg(rotation_algs[i], cube),false)) | ||
| 2950 | return true; | ||
| 2951 | return false; | ||
| 2952 | } else { | ||
| 2953 | return equal(cube, (Cube){0}); | ||
| 2954 | } | ||
| 2955 | } | ||
| 2956 | |||
| 2957 | bool | ||
| 2958 | is_solved_block(Cube cube, Block block) | ||
| 2959 | { | ||
| 2960 | int i; | ||
| 2961 | |||
| 2962 | for (i = 0; i < 12; i++) | ||
| 2963 | if (block.edge[i] && !is_solved_edge(cube, i)) | ||
| 2964 | return false; | ||
| 2965 | for (i = 0; i < 8; i++) | ||
| 2966 | if (block.corner[i] && !is_solved_corner(cube, i)) | ||
| 2967 | return false; | ||
| 2968 | for (i = 0; i < 6; i++) | ||
| 2969 | if (block.center[i] && !is_solved_center(cube, i)) | ||
| 2970 | return false; | ||
| 2971 | |||
| 2972 | return true; | ||
| 2973 | } | ||
| 2974 | |||
| 2975 | bool | ||
| 2976 | is_solved_center(Cube cube, Center c) | ||
| 2977 | { | ||
| 2978 | return what_center_at(cube, c) == c; | ||
| 2979 | } | ||
| 2980 | |||
| 2981 | bool | ||
| 2982 | is_solved_corner(Cube cube, Corner c) | ||
| 2983 | { | ||
| 2984 | return what_corner_at(cube, c) == c && | ||
| 2985 | what_orientation_corner(cube.coud, c); | ||
| 2986 | } | ||
| 2987 | |||
| 2988 | bool | ||
| 2989 | is_solved_edge(Cube cube, Edge e) | ||
| 2990 | { | ||
| 2991 | return what_edge_at(cube, e) == e && | ||
| 2992 | what_orientation_edge(cube.eofb, e); | ||
| 2993 | } | ||
| 2994 | |||
| 2995 | int | ||
| 2996 | piece_orientation(Cube cube, int piece, char *orientation) | ||
| 2997 | { | ||
| 2998 | int arr[12], n, b, x; | ||
| 2999 | |||
| 3000 | if (!strcmp(orientation, "eofb")) { | ||
| 3001 | x = cube.eofb; | ||
| 3002 | n = 12; | ||
| 3003 | b = 2; | ||
| 3004 | } else if (!strcmp(orientation, "eorl")) { | ||
| 3005 | x = cube.eorl; | ||
| 3006 | n = 12; | ||
| 3007 | b = 2; | ||
| 3008 | } else if (!strcmp(orientation, "eoud")) { | ||
| 3009 | x = cube.eoud; | ||
| 3010 | n = 12; | ||
| 3011 | b = 2; | ||
| 3012 | } else if (!strcmp(orientation, "coud")) { | ||
| 3013 | x = cube.coud; | ||
| 3014 | n = 8; | ||
| 3015 | b = 3; | ||
| 3016 | } else if (!strcmp(orientation, "corl")) { | ||
| 3017 | x = cube.corl; | ||
| 3018 | n = 8; | ||
| 3019 | b = 3; | ||
| 3020 | } else if (!strcmp(orientation, "cofb")) { | ||
| 3021 | x = cube.cofb; | ||
| 3022 | n = 8; | ||
| 3023 | b = 3; | ||
| 3024 | } else { | ||
| 3025 | return -1; | ||
| 3026 | } | ||
| 3027 | |||
| 3028 | int_to_sum_zero_array(x, b, n, arr); | ||
| 3029 | if (piece < n) | ||
| 3030 | return arr[piece]; | ||
| 3031 | |||
| 3032 | return -1; | ||
| 3033 | } | ||
| 3034 | |||
| 3035 | void | ||
| 3036 | print_cube(Cube cube) | ||
| 3037 | { | ||
| 3038 | /* | ||
| 3039 | CubeArray *arr = new_cubearray(cube, pf_all); | ||
| 3040 | |||
| 3041 | for (int i = 0; i < 12; i++) | ||
| 3042 | printf(" %s ", edge_string[arr->ep[i]]); | ||
| 3043 | printf("\n"); | ||
| 3044 | |||
| 3045 | for (int i = 0; i < 12; i++) | ||
| 3046 | printf(" %c ", arr->eofb[i] + '0'); | ||
| 3047 | printf("\n"); | ||
| 3048 | |||
| 3049 | for (int i = 0; i < 8; i++) | ||
| 3050 | printf("%s ", corner_string[arr->cp[i]]); | ||
| 3051 | printf("\n"); | ||
| 3052 | |||
| 3053 | for (int i = 0; i < 8; i++) | ||
| 3054 | printf(" %c ", arr->coud[i] + '0'); | ||
| 3055 | printf("\n"); | ||
| 3056 | |||
| 3057 | for (int i = 0; i < 6; i++) | ||
| 3058 | printf(" %s ", center_string[arr->cpos[i]]); | ||
| 3059 | printf("\n"); | ||
| 3060 | |||
| 3061 | free_cubearray(arr, pf_all); | ||
| 3062 | */ | ||
| 3063 | |||
| 3064 | for (int i = 0; i < 12; i++) | ||
| 3065 | printf(" %s ", edge_string[what_edge_at(cube, i)]); | ||
| 3066 | printf("\n"); | ||
| 3067 | |||
| 3068 | for (int i = 0; i < 12; i++) | ||
| 3069 | printf(" %d ", what_orientation_edge(cube.eofb, i)); | ||
| 3070 | printf("\n"); | ||
| 3071 | |||
| 3072 | for (int i = 0; i < 8; i++) | ||
| 3073 | printf("%s ", corner_string[what_corner_at(cube, i)]); | ||
| 3074 | printf("\n"); | ||
| 3075 | |||
| 3076 | for (int i = 0; i < 8; i++) | ||
| 3077 | printf(" %d ", what_orientation_corner(cube.coud, i)); | ||
| 3078 | printf("\n"); | ||
| 3079 | |||
| 3080 | for (int i = 0; i < 6; i++) | ||
| 3081 | printf(" %s ", center_string[what_center_at(cube, i)]); | ||
| 3082 | printf("\n"); | ||
| 3083 | |||
| 3084 | } | ||
| 3085 | |||
| 3086 | Cube | ||
| 3087 | random_cube() | ||
| 3088 | { | ||
| 3089 | CubeArray *arr = new_cubearray((Cube){0}, pf_4val); | ||
| 3090 | Cube ret; | ||
| 3091 | int ep, cp, eo, co; | ||
| 3092 | |||
| 3093 | ep = rand() % FACTORIAL12; | ||
| 3094 | cp = rand() % FACTORIAL8; | ||
| 3095 | eo = rand() % POW2TO11; | ||
| 3096 | co = rand() % POW3TO7; | ||
| 3097 | |||
| 3098 | index_to_perm(ep, 12, arr->ep); | ||
| 3099 | index_to_perm(cp, 8, arr->cp); | ||
| 3100 | int_to_sum_zero_array(eo, 2, 12, arr->eofb); | ||
| 3101 | int_to_sum_zero_array(co, 3, 8, arr->coud); | ||
| 3102 | |||
| 3103 | if (perm_sign(arr->ep, 12) != perm_sign(arr->cp, 8)) | ||
| 3104 | swap(&(arr->ep[0]), &(arr->ep[1])); | ||
| 3105 | |||
| 3106 | ret = arrays_to_cube(arr, pf_4val); | ||
| 3107 | free_cubearray(arr, pf_4val); | ||
| 3108 | |||
| 3109 | return ret; | ||
| 3110 | } | ||
| 3111 | |||
| 3112 | /* TODO: clean pre_trans or put it back */ | ||
| 3113 | AlgList * | ||
| 3114 | solve(Cube cube, Step step, SolveOptions *opts) | ||
| 3115 | { | ||
| 3116 | /*AlgListNode *node;*/ | ||
| 3117 | AlgList *sols = new_alglist(); | ||
| 3118 | /*Cube c = apply_trans(opts->pre_trans, cube);*/ | ||
| 3119 | DfsData dd = { | ||
| 3120 | .m = 0, | ||
| 3121 | .niss = false, | ||
| 3122 | .lb = -1, | ||
| 3123 | .last1 = NULLMOVE, | ||
| 3124 | .last2 = NULLMOVE, | ||
| 3125 | .sols = sols, | ||
| 3126 | .current_alg = new_alg("") | ||
| 3127 | }; | ||
| 3128 | |||
| 3129 | if (step.ready != NULL && !step.ready(cube)) { | ||
| 3130 | fprintf(stderr, "Cube not ready for solving step\n"); | ||
| 3131 | return sols; | ||
| 3132 | } | ||
| 3133 | |||
| 3134 | moveset_to_list(step.moveset, step.estimate, dd.sorted_moves); | ||
| 3135 | movelist_to_position(dd.sorted_moves, dd.move_position); | ||
| 3136 | |||
| 3137 | for (dd.d = opts->min_moves; | ||
| 3138 | dd.d <= opts->max_moves && !(sols->len && opts->optimal_only); | ||
| 3139 | dd.d++) { | ||
| 3140 | if (opts->feedback) | ||
| 3141 | fprintf(stderr, | ||
| 3142 | "Found %d solutions, searching depth %d...\n", | ||
| 3143 | sols->len, dd.d); | ||
| 3144 | dfs(cube, step, opts, &dd); | ||
| 3145 | } | ||
| 3146 | |||
| 3147 | /* | ||
| 3148 | for (node = sols->first; node != NULL; node = node->next) | ||
| 3149 | transform_alg(inverse_trans(opts->pre_trans), node->alg); | ||
| 3150 | */ | ||
| 3151 | |||
| 3152 | free_alg(dd.current_alg); | ||
| 3153 | return sols; | ||
| 3154 | } | ||
| 3155 | |||
| 3156 | Alg * | ||
| 3157 | inverse_alg(Alg *alg) | ||
| 3158 | { | ||
| 3159 | Alg *ret = new_alg(""); | ||
| 3160 | int i; | ||
| 3161 | |||
| 3162 | for (i = alg->len-1; i >= 0; i--) | ||
| 3163 | append_move(ret, inverse_move(alg->move[i]), alg->inv[i]); | ||
| 3164 | |||
| 3165 | return ret; | ||
| 3166 | } | ||
| 3167 | |||
| 3168 | Alg * | ||
| 3169 | new_alg(char *str) | ||
| 3170 | { | ||
| 3171 | Alg *alg = malloc(sizeof(Alg)); | ||
| 3172 | int i; | ||
| 3173 | bool niss = false; | ||
| 3174 | Move j, m; | ||
| 3175 | |||
| 3176 | alg->move = malloc(30 * sizeof(Move)); | ||
| 3177 | alg->inv = malloc(30 * sizeof(bool)); | ||
| 3178 | alg->allocated = 30; | ||
| 3179 | alg->len = 0; | ||
| 3180 | |||
| 3181 | for (i = 0; str[i]; i++) { | ||
| 3182 | if (str[i] == ' ' || str[i] == '\t' || str[i] == '\n') | ||
| 3183 | continue; | ||
| 3184 | |||
| 3185 | if (str[i] == '(' && niss) { | ||
| 3186 | fprintf(stderr, "Error reading moves: nested ( )\n"); | ||
| 3187 | return alg; | ||
| 3188 | } | ||
| 3189 | |||
| 3190 | if (str[i] == ')' && !niss) { | ||
| 3191 | fprintf(stderr, "Error reading moves: unmatched )\n"); | ||
| 3192 | return alg; | ||
| 3193 | } | ||
| 3194 | |||
| 3195 | if (str[i] == '(' || str[i] == ')') { | ||
| 3196 | niss = !niss; | ||
| 3197 | continue; | ||
| 3198 | } | ||
| 3199 | |||
| 3200 | for (j = 0; j < NMOVES; j++) { | ||
| 3201 | if (str[i] == move_string[j][0]) { | ||
| 3202 | m = j; | ||
| 3203 | if (m <= B && str[i+1]=='w') { | ||
| 3204 | m += Uw - U; | ||
| 3205 | i++; | ||
| 3206 | } | ||
| 3207 | if (str[i+1]=='2') { | ||
| 3208 | m += 1; | ||
| 3209 | i++; | ||
| 3210 | } else if (str[i+1]=='\'' || str[i+1]=='3') { | ||
| 3211 | m += 2; | ||
| 3212 | i++; | ||
| 3213 | } | ||
| 3214 | append_move(alg, m, niss); | ||
| 3215 | break; | ||
| 3216 | } | ||
| 3217 | } | ||
| 3218 | } | ||
| 3219 | |||
| 3220 | return alg; | ||
| 3221 | } | ||
| 3222 | |||
| 3223 | Alg * | ||
| 3224 | on_inverse(Alg *alg) | ||
| 3225 | { | ||
| 3226 | Alg *ret = new_alg(""); | ||
| 3227 | int i; | ||
| 3228 | |||
| 3229 | for (i = 0; i < alg->len; i++) | ||
| 3230 | append_move(ret, alg->move[i], !alg->inv[i]); | ||
| 3231 | |||
| 3232 | return ret; | ||
| 3233 | } | ||
| 3234 | |||
| 3235 | void | ||
| 3236 | print_alg(Alg *alg, bool l) | ||
| 3237 | { | ||
| 3238 | /* TODO: make it possible to print to stdout or to string */ | ||
| 3239 | /* Maybe just return a string */ | ||
| 3240 | char fill[4]; | ||
| 3241 | int i; | ||
| 3242 | bool niss = false; | ||
| 3243 | |||
| 3244 | for (i = 0; i < alg->len; i++) { | ||
| 3245 | if (!niss && alg->inv[i]) | ||
| 3246 | strcpy(fill, i == 0 ? "(" : " ("); | ||
| 3247 | if (niss && !alg->inv[i]) | ||
| 3248 | strcpy(fill, ") "); | ||
| 3249 | if (niss == alg->inv[i]) | ||
| 3250 | strcpy(fill, i == 0 ? "" : " "); | ||
| 3251 | |||
| 3252 | printf("%s%s", fill, move_string[alg->move[i]]); | ||
| 3253 | niss = alg->inv[i]; | ||
| 3254 | } | ||
| 3255 | |||
| 3256 | if (niss) | ||
| 3257 | printf(")"); | ||
| 3258 | if (l) | ||
| 3259 | printf(" (%d)", alg->len); | ||
| 3260 | |||
| 3261 | printf("\n"); | ||
| 3262 | } | ||
| 3263 | |||
| 3264 | void | ||
| 3265 | print_alglist(AlgList *al, bool l) | ||
| 3266 | { | ||
| 3267 | AlgListNode *i; | ||
| 3268 | |||
| 3269 | for (i = al->first; i != NULL; i = i->next) | ||
| 3270 | print_alg(i->alg, l); | ||
| 3271 | } | ||
| 3272 | |||
| 3273 | void | ||
| 3274 | print_ptable(PruneData *pd) | ||
| 3275 | { | ||
| 3276 | uint64_t i, a[16]; | ||
| 3277 | |||
| 3278 | for (i = 0; i < 16; i++) | ||
| 3279 | a[i] = 0; | ||
| 3280 | |||
| 3281 | if (!pd->generated) | ||
| 3282 | genptable(pd); | ||
| 3283 | |||
| 3284 | for (i = 0; i < pd->coord->max; i++) | ||
| 3285 | a[ptableval(pd, pd->coord->cube(i))]++; | ||
| 3286 | |||
| 3287 | fprintf(stderr, "Values for table %s\n", pd->filename); | ||
| 3288 | for (i = 0; i < 16; i++) | ||
| 3289 | printf("%2lu\t%10lu\n", i, a[i]); | ||
| 3290 | } | ||
| 3291 | |||
| 3292 | uint64_t | ||
| 3293 | ptablesize(PruneData *pd) | ||
| 3294 | { | ||
| 3295 | return (pd->coord->max + 1) / 2; | ||
| 3296 | } | ||
| 3297 | |||
| 3298 | int | ||
| 3299 | ptableval(PruneData *pd, Cube cube) | ||
| 3300 | { | ||
| 3301 | return ptableval_index(pd, pd->coord->index(cube)); | ||
| 3302 | } | ||
| 3303 | |||
| 3304 | Alg * | ||
| 3305 | rotation_alg(Trans i) | ||
| 3306 | { | ||
| 3307 | return rotation_algs[i % NROTATIONS]; | ||
| 3308 | } | ||
| 3309 | |||
| 3310 | void | ||
| 3311 | transform_alg(Trans t, Alg *alg) | ||
| 3312 | { | ||
| 3313 | int i; | ||
| 3314 | |||
| 3315 | for (i = 0; i < alg->len; i++) | ||
| 3316 | alg->move[i] = moves_ttable[t][alg->move[i]]; | ||
| 3317 | } | ||
| 3318 | |||
| 3319 | Center | ||
| 3320 | what_center_at(Cube cube, Center c) | ||
| 3321 | { | ||
| 3322 | return what_center_at_aux[cube.cpos][c]; | ||
| 3323 | } | ||
| 3324 | |||
| 3325 | Corner | ||
| 3326 | what_corner_at(Cube cube, Corner c) | ||
| 3327 | { | ||
| 3328 | return what_corner_at_aux[cube.cp][c]; | ||
| 3329 | } | ||
| 3330 | |||
| 3331 | Edge | ||
| 3332 | what_edge_at(Cube cube, Edge e) | ||
| 3333 | { | ||
| 3334 | Edge ret; | ||
| 3335 | CubeArray *arr = new_cubearray(cube, pf_ep); | ||
| 3336 | |||
| 3337 | ret = arr->ep[e]; | ||
| 3338 | |||
| 3339 | free_cubearray(arr, pf_ep); | ||
| 3340 | return ret; | ||
| 3341 | } | ||
| 3342 | |||
| 3343 | int | ||
| 3344 | what_orientation_corner(int co, Corner c) | ||
| 3345 | { | ||
| 3346 | if (c < 7) | ||
| 3347 | return (co / powint(3, c)) % 3; | ||
| 3348 | else | ||
| 3349 | return what_orientation_last_corner_aux[co]; | ||
| 3350 | } | ||
| 3351 | |||
| 3352 | int | ||
| 3353 | what_orientation_edge(int eo, Edge e) | ||
| 3354 | { | ||
| 3355 | if (e < 11) | ||
| 3356 | return (eo & (1 << e)) ? 1 : 0; | ||
| 3357 | else | ||
| 3358 | return what_orientation_last_edge_aux[eo]; | ||
| 3359 | } | ||
| 3360 | |||
| 3361 | Center | ||
| 3362 | where_is_center(Cube cube, Center c) | ||
| 3363 | { | ||
| 3364 | return where_is_center_aux[cube.cpos][c]; | ||
| 3365 | } | ||
| 3366 | |||
| 3367 | Corner | ||
| 3368 | where_is_corner(Cube cube, Corner c) | ||
| 3369 | { | ||
| 3370 | return where_is_corner_aux[cube.cp][c]; | ||
| 3371 | } | ||
| 3372 | |||
| 3373 | |||
| 3374 | void | ||
| 3375 | init() | ||
| 3376 | { | ||
| 3377 | /* Order is important! */ | ||
| 3378 | init_environment(); | ||
| 3379 | init_strings(); | ||
| 3380 | init_moves_aux(); | ||
| 3381 | init_moves(); | ||
| 3382 | init_auxtables(); | ||
| 3383 | init_cphtr_cosets(); | ||
| 3384 | init_trans_aux(); | ||
| 3385 | init_trans(); | ||
| 3386 | init_symdata(); | ||
| 3387 | } | ||
| 3388 | |||
diff --git a/old/2021-07-15-almostbeforerefactor/alg.h b/old/2021-07-15-almostbeforerefactor/alg.h new file mode 100644 index 0000000..865c2b3 --- /dev/null +++ b/old/2021-07-15-almostbeforerefactor/alg.h | |||
| @@ -0,0 +1,27 @@ | |||
| 1 | #ifndef ALG_H | ||
| 2 | #define ALG_H | ||
| 3 | |||
| 4 | #include <stdio.h> | ||
| 5 | #include <stdbool.h> | ||
| 6 | #include <stdlib.h> | ||
| 7 | #include <string.h> | ||
| 8 | |||
| 9 | #include "macros.h" | ||
| 10 | #include "cubetypes.h" | ||
| 11 | |||
| 12 | Move base_move(Move m); | ||
| 13 | void free_alg(Alg *alg); | ||
| 14 | void free_alglist(AlgList *l); | ||
| 15 | Alg * inverse_alg(Alg *alg); | ||
| 16 | Move inverse_move(Move m); | ||
| 17 | bool moveset_HTM(Move m); | ||
| 18 | bool moveset_URF(Move m); | ||
| 19 | Alg * new_alg(char *str); | ||
| 20 | Alg * on_inverse(Alg *alg); | ||
| 21 | void print_alg(Alg *alg, bool l); | ||
| 22 | void print_alglist(AlgList *al, bool l); | ||
| 23 | Alg * rotation_alg(Trans i); | ||
| 24 | void transform_alg(Trans t, Alg *alg); | ||
| 25 | |||
| 26 | #endif | ||
| 27 | |||
diff --git a/old/2021-07-15-almostbeforerefactor/cube.c b/old/2021-07-15-almostbeforerefactor/cube.c new file mode 100644 index 0000000..ef16f9d --- /dev/null +++ b/old/2021-07-15-almostbeforerefactor/cube.c | |||
| @@ -0,0 +1,3391 @@ | |||
| 1 | #include "cube.h" | ||
| 2 | |||
| 3 | /* TODO: remove! */ | ||
| 4 | #include "steps.h" | ||
| 5 | |||
| 6 | /* Local functions **********************************************************/ | ||
| 7 | |||
| 8 | static Cube admissible_ep(Cube cube, PieceFilter f); | ||
| 9 | static Cube admissible_eos_from_eofbepos(Cube cube); | ||
| 10 | static bool allowed_next(Move move, DfsData *dd); | ||
| 11 | static void append_alg(AlgList *l, Alg *alg); | ||
| 12 | static void append_move(Alg *alg, Move m, bool inverse); | ||
| 13 | static Cube apply_alg_generic(Alg *alg, Cube c, PieceFilter f, bool a); | ||
| 14 | static void apply_permutation(int *perm, int *set, int n); | ||
| 15 | static Cube apply_move_cubearray(Move m, Cube cube, PieceFilter f); | ||
| 16 | static int array_ep_to_epos(int *ep, int *eps_solved); | ||
| 17 | static Cube arrays_to_cube(CubeArray *arr, PieceFilter f); | ||
| 18 | static int binomial(int n, int k); | ||
| 19 | static Cube compose_filtered(Cube c2, Cube c1, PieceFilter f); | ||
| 20 | static void cube_to_arrays(Cube cube, CubeArray *arr, PieceFilter f); | ||
| 21 | static void dfs(Cube c, Step s, SolveOptions *opts, DfsData *dd); | ||
| 22 | static void dfs_branch(Cube c, Step s, SolveOptions *opts, DfsData *dd); | ||
| 23 | static bool dfs_check_solved(SolveOptions *opts, DfsData *dd); | ||
| 24 | static void dfs_niss(Cube c, Step s, SolveOptions *opts, DfsData *dd); | ||
| 25 | static bool dfs_stop(Cube c, Step s, SolveOptions *opts, DfsData *dd); | ||
| 26 | static int digit_array_to_int(int *a, int n, int b); | ||
| 27 | static int edge_slice(Edge e); /* E=0, S=1, M=2 */ | ||
| 28 | static int epos_dependent_pos(int pos1, int pos2); | ||
| 29 | static int epos_from_arrays(int *epos, int *ep); | ||
| 30 | static void epos_to_partial_ep(int epos, int *ep, int *ss); | ||
| 31 | static int factorial(int n); | ||
| 32 | static void free_alglistnode(AlgListNode *aln); | ||
| 33 | static void free_cubearray(CubeArray *arr, PieceFilter f); | ||
| 34 | static void genptable_bfs(PruneData *pd, int d, Move *ms); | ||
| 35 | static void genptable_branch(PruneData *pd, uint64_t i, int d, Move *m); | ||
| 36 | static void gensym(SymData *sd); | ||
| 37 | static void index_to_perm(int p, int n, int *r); | ||
| 38 | static void index_to_subset(int s, int n, int k, int *r); | ||
| 39 | static void init_auxtables(); | ||
| 40 | static void init_cphtr_cosets(); | ||
| 41 | static void init_cphtr_left_cosets_bfs(int i, int c); | ||
| 42 | static void init_cphtr_right_cosets_color(int i, int c); | ||
| 43 | static void init_environment(); | ||
| 44 | static void init_moves(); | ||
| 45 | static void init_moves_aux(); | ||
| 46 | static void init_strings(); | ||
| 47 | static void init_symdata(); | ||
| 48 | static void init_trans(); | ||
| 49 | static void init_trans_aux(); | ||
| 50 | static void int_to_digit_array(int a, int b, int n, int *r); | ||
| 51 | static void int_to_sum_zero_array(int x, int b, int n, int *a); | ||
| 52 | static int invert_digits(int a, int b, int n); | ||
| 53 | static bool is_perm(int *a, int n); | ||
| 54 | static bool is_subset(int *a, int n, int k); | ||
| 55 | static Cube move_via_arrays(CubeArray *arr, Cube c, PieceFilter pf); | ||
| 56 | static void movelist_to_position(Move *movelist, int *position); | ||
| 57 | static void moveset_to_list(Moveset ms, Estimator f, Move *r); | ||
| 58 | static AlgList * new_alglist(); | ||
| 59 | static CubeArray * new_cubearray(Cube cube, PieceFilter f); | ||
| 60 | static int perm_sign(int *a, int n); | ||
| 61 | static int perm_to_index(int *a, int n); | ||
| 62 | static int powint(int a, int b); | ||
| 63 | static void ptable_update(PruneData *pd, Cube cube, int m); | ||
| 64 | static int ptableval_index(PruneData *pd, uint64_t ind); | ||
| 65 | static void realloc_alg(Alg *alg, int n); | ||
| 66 | static bool read_mtables_file(); | ||
| 67 | static bool read_ptable_file(PruneData *pd); | ||
| 68 | static bool read_symdata_file(SymData *sd); | ||
| 69 | static bool read_ttables_file(); | ||
| 70 | static Cube rotate_via_compose(Trans r, Cube c, PieceFilter f); | ||
| 71 | static int subset_to_index(int *a, int n, int k); | ||
| 72 | static void sum_arrays_mod(int *src, int *dst, int n, int m); | ||
| 73 | static void swap(int *a, int *b); | ||
| 74 | static bool write_mtables_file(); | ||
| 75 | static bool write_ptable_file(PruneData *pd); | ||
| 76 | static bool write_symdata_file(SymData *sd); | ||
| 77 | static bool write_ttables_file(); | ||
| 78 | |||
| 79 | |||
| 80 | /* All sorts of useful costants and tables **********************************/ | ||
| 81 | |||
| 82 | static char * tabledir; | ||
| 83 | |||
| 84 | static PieceFilter pf_all; | ||
| 85 | static PieceFilter pf_4val; | ||
| 86 | static PieceFilter pf_epcp; | ||
| 87 | static PieceFilter pf_cpos; | ||
| 88 | static PieceFilter pf_cp; | ||
| 89 | static PieceFilter pf_ep; | ||
| 90 | static PieceFilter pf_e; | ||
| 91 | static PieceFilter pf_s; | ||
| 92 | static PieceFilter pf_m; | ||
| 93 | static PieceFilter pf_eo; | ||
| 94 | static PieceFilter pf_co; | ||
| 95 | |||
| 96 | static int epe_solved[4]; | ||
| 97 | static int eps_solved[4]; | ||
| 98 | static int epm_solved[4]; | ||
| 99 | |||
| 100 | static char move_string[NMOVES][7]; | ||
| 101 | static char edge_string[12][7]; | ||
| 102 | static char corner_string[8][7]; | ||
| 103 | static char center_string[6][7]; | ||
| 104 | |||
| 105 | static Cube admissible_ee_aux[POW2TO11*BINOM12ON4]; | ||
| 106 | static bool commute[NMOVES][NMOVES]; | ||
| 107 | static bool possible_next[NMOVES][NMOVES][NMOVES]; | ||
| 108 | static Move inverse_move_aux[NMOVES]; | ||
| 109 | static Trans inverse_trans_aux[NTRANS]; | ||
| 110 | static int epos_dependent_aux[BINOM12ON4][BINOM12ON4]; | ||
| 111 | static int cphtr_left_cosets[FACTORIAL8]; | ||
| 112 | static int cphtr_right_cosets[FACTORIAL8]; | ||
| 113 | static int cphtr_right_rep[BINOM8ON4*6]; | ||
| 114 | static Center what_center_at_aux[FACTORIAL6][6]; | ||
| 115 | static Corner what_corner_at_aux[FACTORIAL8][8]; | ||
| 116 | static int what_orientation_last_corner_aux[POW3TO7]; | ||
| 117 | static int what_orientation_last_edge_aux[POW2TO11]; | ||
| 118 | static Center where_is_center_aux[FACTORIAL6][6]; | ||
| 119 | static Corner where_is_corner_aux[FACTORIAL8][8]; | ||
| 120 | static Edge where_is_edge_aux[3][FACTORIAL12/FACTORIAL8][12]; | ||
| 121 | |||
| 122 | static int epose_ttable[NTRANS][FACTORIAL12/FACTORIAL8]; | ||
| 123 | static int eposs_ttable[NTRANS][FACTORIAL12/FACTORIAL8]; | ||
| 124 | static int eposm_ttable[NTRANS][FACTORIAL12/FACTORIAL8]; | ||
| 125 | static int eo_ttable[NTRANS][POW2TO11]; | ||
| 126 | static int cp_ttable[NTRANS][FACTORIAL8]; | ||
| 127 | static int co_ttable[NTRANS][POW3TO7]; | ||
| 128 | static int cpos_ttable[NTRANS][FACTORIAL6]; | ||
| 129 | static Move moves_ttable[NTRANS][NMOVES]; | ||
| 130 | |||
| 131 | static int epose_mtable[NMOVES][FACTORIAL12/FACTORIAL8]; | ||
| 132 | static int eposs_mtable[NMOVES][FACTORIAL12/FACTORIAL8]; | ||
| 133 | static int eposm_mtable[NMOVES][FACTORIAL12/FACTORIAL8]; | ||
| 134 | static int eofb_mtable[NMOVES][POW2TO11]; | ||
| 135 | static int eorl_mtable[NMOVES][POW2TO11]; | ||
| 136 | static int eoud_mtable[NMOVES][POW2TO11]; | ||
| 137 | static int cp_mtable[NMOVES][FACTORIAL8]; | ||
| 138 | static int coud_mtable[NMOVES][POW3TO7]; | ||
| 139 | static int cofb_mtable[NMOVES][POW3TO7]; | ||
| 140 | static int corl_mtable[NMOVES][POW3TO7]; | ||
| 141 | static int cpos_mtable[NMOVES][FACTORIAL6]; | ||
| 142 | |||
| 143 | static uint64_t me[12]; | ||
| 144 | |||
| 145 | static int edge_cycle[NMOVES][12]; | ||
| 146 | static int corner_cycle[NMOVES][8]; | ||
| 147 | static int center_cycle[NMOVES][6]; | ||
| 148 | static int eofb_flipped[NMOVES][12]; | ||
| 149 | static int eorl_flipped[NMOVES][12]; | ||
| 150 | static int eoud_flipped[NMOVES][12]; | ||
| 151 | static int coud_flipped[NMOVES][8]; | ||
| 152 | static int corl_flipped[NMOVES][8]; | ||
| 153 | static int cofb_flipped[NMOVES][8]; | ||
| 154 | static Alg * equiv_alg[NMOVES]; | ||
| 155 | |||
| 156 | static int epose_source[NTRANS]; /* 0=epose, 1=eposs, 2=eposm */ | ||
| 157 | static int eposs_source[NTRANS]; | ||
| 158 | static int eposm_source[NTRANS]; | ||
| 159 | static int eofb_source[NTRANS]; /* 0=eoud, 1=eorl, 2=eofb */ | ||
| 160 | static int eorl_source[NTRANS]; | ||
| 161 | static int eoud_source[NTRANS]; | ||
| 162 | static int coud_source[NTRANS]; /* 0=coud, 1=corl, 2=cofb */ | ||
| 163 | static int cofb_source[NTRANS]; | ||
| 164 | static int corl_source[NTRANS]; | ||
| 165 | static int ep_mirror[12]; | ||
| 166 | static int cp_mirror[8]; | ||
| 167 | static int cpos_mirror[6]; | ||
| 168 | static Alg * rotation_algs[NROTATIONS]; | ||
| 169 | |||
| 170 | |||
| 171 | /* Symmetry data for some coordinates ****************************************/ | ||
| 172 | |||
| 173 | Trans | ||
| 174 | trans_group_trivial[1] = { uf }; | ||
| 175 | |||
| 176 | Trans | ||
| 177 | trans_group_udfix[16] = { | ||
| 178 | uf, ur, ub, ul, | ||
| 179 | df, dr, db, dl, | ||
| 180 | uf_mirror, ur_mirror, ub_mirror, ul_mirror, | ||
| 181 | df_mirror, dr_mirror, db_mirror, dl_mirror, | ||
| 182 | }; | ||
| 183 | |||
| 184 | SymData | ||
| 185 | sd_coud_16 = { | ||
| 186 | .filename = "sd_coud_16", | ||
| 187 | .coord = &coord_coud, | ||
| 188 | .sym_coord = &coord_coud_sym16, | ||
| 189 | .ntrans = 16, | ||
| 190 | .trans = trans_group_udfix | ||
| 191 | }; | ||
| 192 | |||
| 193 | SymData | ||
| 194 | sd_eofbepos_16 = { | ||
| 195 | .filename = "sd_eofbepos_16", | ||
| 196 | .coord = &coord_eofbepos, | ||
| 197 | .sym_coord = &coord_eofbepos_sym16, | ||
| 198 | .ntrans = 16, | ||
| 199 | .trans = trans_group_udfix | ||
| 200 | }; | ||
| 201 | |||
| 202 | static int n_all_symdata = 2; | ||
| 203 | static SymData * all_sd[2] = { &sd_coud_16, &sd_eofbepos_16 }; | ||
| 204 | |||
| 205 | /* Coordinates and their implementation **************************************/ | ||
| 206 | |||
| 207 | static uint64_t index_eofb(Cube cube); | ||
| 208 | static uint64_t index_eofbepos(Cube cube); | ||
| 209 | static uint64_t index_coud(Cube cube); | ||
| 210 | static uint64_t index_corners(Cube cube); | ||
| 211 | static uint64_t index_cornershtr(Cube cube); | ||
| 212 | static uint64_t index_drud(Cube cube); | ||
| 213 | static uint64_t index_coud_sym16(Cube cube); | ||
| 214 | static uint64_t index_eofbepos_sym16(Cube cube); | ||
| 215 | static uint64_t index_drud_sym16(Cube cube); | ||
| 216 | static uint64_t index_khuge(Cube cube); | ||
| 217 | |||
| 218 | static Cube antindex_eofb(uint64_t ind); | ||
| 219 | static Cube antindex_eofbepos(uint64_t ind); | ||
| 220 | static Cube antindex_coud(uint64_t ind); | ||
| 221 | static Cube antindex_corners(uint64_t ind); | ||
| 222 | static Cube antindex_cornershtr(uint64_t ind); | ||
| 223 | static Cube antindex_drud(uint64_t ind); | ||
| 224 | static Cube antindex_coud_sym16(uint64_t ind); | ||
| 225 | static Cube antindex_eofbepos_sym16(uint64_t ind); | ||
| 226 | static Cube antindex_drud_sym16(uint64_t ind); | ||
| 227 | static Cube antindex_khuge(uint64_t ind); | ||
| 228 | |||
| 229 | Coordinate | ||
| 230 | coord_eofb = { | ||
| 231 | .index = index_eofb, | ||
| 232 | .cube = antindex_eofb, | ||
| 233 | .check = check_eofb, | ||
| 234 | .max = POW2TO11 | ||
| 235 | }; | ||
| 236 | |||
| 237 | Coordinate | ||
| 238 | coord_eofbepos = { | ||
| 239 | .index = index_eofbepos, | ||
| 240 | .cube = antindex_eofbepos, | ||
| 241 | .check = check_eofbepos, | ||
| 242 | .max = POW2TO11 * BINOM12ON4 | ||
| 243 | }; | ||
| 244 | |||
| 245 | Coordinate | ||
| 246 | coord_coud = { | ||
| 247 | .index = index_coud, | ||
| 248 | .cube = antindex_coud, | ||
| 249 | .check = check_coud, | ||
| 250 | .max = POW3TO7 | ||
| 251 | }; | ||
| 252 | |||
| 253 | Coordinate | ||
| 254 | coord_corners = { | ||
| 255 | .index = index_corners, | ||
| 256 | .cube = antindex_corners, | ||
| 257 | .check = check_corners, | ||
| 258 | .max = POW3TO7 * FACTORIAL8 | ||
| 259 | }; | ||
| 260 | |||
| 261 | Coordinate | ||
| 262 | coord_cornershtr = { | ||
| 263 | .index = index_cornershtr, | ||
| 264 | .cube = antindex_cornershtr, | ||
| 265 | .check = check_cornershtr, | ||
| 266 | .max = POW3TO7 * BINOM8ON4 * 6 | ||
| 267 | }; | ||
| 268 | |||
| 269 | Coordinate | ||
| 270 | coord_drud = { | ||
| 271 | .index = index_drud, | ||
| 272 | .cube = antindex_drud, | ||
| 273 | .check = check_drud, | ||
| 274 | .max = POW2TO11 * POW3TO7 * BINOM12ON4 | ||
| 275 | }; | ||
| 276 | |||
| 277 | Coordinate | ||
| 278 | coord_eofbepos_sym16 = { | ||
| 279 | .index = index_eofbepos_sym16, | ||
| 280 | .cube = antindex_eofbepos_sym16, | ||
| 281 | .check = check_eofbepos, | ||
| 282 | }; | ||
| 283 | |||
| 284 | Coordinate | ||
| 285 | coord_coud_sym16 = { | ||
| 286 | .index = index_coud_sym16, | ||
| 287 | .cube = antindex_coud_sym16, | ||
| 288 | .check = check_coud, | ||
| 289 | }; | ||
| 290 | |||
| 291 | Coordinate | ||
| 292 | coord_drud_sym16 = { | ||
| 293 | .index = index_drud_sym16, | ||
| 294 | .cube = antindex_drud_sym16, | ||
| 295 | .check = check_drud, | ||
| 296 | .max = POW3TO7 * 64430 | ||
| 297 | }; | ||
| 298 | |||
| 299 | Coordinate | ||
| 300 | coord_khuge = { | ||
| 301 | .index = index_khuge, | ||
| 302 | .cube = antindex_khuge, | ||
| 303 | .check = check_khuge, | ||
| 304 | .max = POW3TO7 * FACTORIAL4 * 64430 | ||
| 305 | }; | ||
| 306 | |||
| 307 | |||
| 308 | static uint64_t | ||
| 309 | index_eofb(Cube cube) | ||
| 310 | { | ||
| 311 | return cube.eofb; | ||
| 312 | } | ||
| 313 | |||
| 314 | static uint64_t | ||
| 315 | index_eofbepos(Cube cube) | ||
| 316 | { | ||
| 317 | return (cube.epose / FACTORIAL4) * POW2TO11 + cube.eofb; | ||
| 318 | } | ||
| 319 | |||
| 320 | static uint64_t | ||
| 321 | index_coud(Cube cube) | ||
| 322 | { | ||
| 323 | return cube.coud; | ||
| 324 | } | ||
| 325 | |||
| 326 | static uint64_t | ||
| 327 | index_corners(Cube cube) | ||
| 328 | { | ||
| 329 | return cube.coud * FACTORIAL8 + cube.cp; | ||
| 330 | } | ||
| 331 | |||
| 332 | static uint64_t | ||
| 333 | index_cornershtr(Cube cube) | ||
| 334 | { | ||
| 335 | return cube.coud * BINOM8ON4 * 6 + cphtr(cube); | ||
| 336 | } | ||
| 337 | |||
| 338 | static uint64_t | ||
| 339 | index_drud(Cube cube) | ||
| 340 | { | ||
| 341 | uint64_t a, b, c; | ||
| 342 | |||
| 343 | a = cube.eofb; | ||
| 344 | b = cube.coud; | ||
| 345 | c = cube.epose / FACTORIAL4; | ||
| 346 | |||
| 347 | b *= POW2TO11; | ||
| 348 | c *= POW2TO11 * POW3TO7; | ||
| 349 | |||
| 350 | return a + b + c; | ||
| 351 | } | ||
| 352 | |||
| 353 | static uint64_t | ||
| 354 | index_coud_sym16(Cube cube) | ||
| 355 | { | ||
| 356 | return sd_coud_16.class[index_coud(cube)]; | ||
| 357 | } | ||
| 358 | |||
| 359 | static uint64_t | ||
| 360 | index_drud_sym16(Cube cube) | ||
| 361 | { | ||
| 362 | Trans t; | ||
| 363 | Cube c; | ||
| 364 | |||
| 365 | t = sd_eofbepos_16.transtorep[index_eofbepos(cube)]; | ||
| 366 | c = apply_trans(t, cube); | ||
| 367 | |||
| 368 | return index_eofbepos_sym16(c) * POW3TO7 + c.coud; | ||
| 369 | } | ||
| 370 | |||
| 371 | static uint64_t | ||
| 372 | index_eofbepos_sym16(Cube cube) | ||
| 373 | { | ||
| 374 | return sd_eofbepos_16.class[index_eofbepos(cube)]; | ||
| 375 | } | ||
| 376 | |||
| 377 | static uint64_t | ||
| 378 | index_khuge(Cube cube) | ||
| 379 | { | ||
| 380 | Trans t; | ||
| 381 | Cube c; | ||
| 382 | uint64_t a; | ||
| 383 | |||
| 384 | t = sd_eofbepos_16.transtorep[index_eofbepos(cube)]; | ||
| 385 | c = apply_trans(t, cube); | ||
| 386 | a = (index_eofbepos_sym16(c) * 24) + (c.epose % 24); | ||
| 387 | |||
| 388 | return a * POW3TO7 + c.coud; | ||
| 389 | } | ||
| 390 | |||
| 391 | |||
| 392 | /* TODO: rename */ | ||
| 393 | static Cube | ||
| 394 | antindex_eofb(uint64_t ind) | ||
| 395 | { | ||
| 396 | return (Cube){ .eofb = ind, .eorl = ind, .eoud = ind }; | ||
| 397 | } | ||
| 398 | |||
| 399 | static Cube | ||
| 400 | antindex_eofbepos(uint64_t ind) | ||
| 401 | { | ||
| 402 | return admissible_ee_aux[ind]; | ||
| 403 | } | ||
| 404 | |||
| 405 | /* TODO: rename */ | ||
| 406 | static Cube | ||
| 407 | antindex_coud(uint64_t ind) | ||
| 408 | { | ||
| 409 | return (Cube){ .coud = ind, .corl = ind, .cofb = ind }; | ||
| 410 | } | ||
| 411 | |||
| 412 | /* TODO: admissible co for other orientations */ | ||
| 413 | static Cube | ||
| 414 | antindex_corners(uint64_t ind) | ||
| 415 | { | ||
| 416 | Cube c = {0}; | ||
| 417 | |||
| 418 | c.coud = ind / FACTORIAL8; | ||
| 419 | c.cp = ind % FACTORIAL8; | ||
| 420 | |||
| 421 | return c; | ||
| 422 | } | ||
| 423 | |||
| 424 | /* TODO: admissible co for other orientations */ | ||
| 425 | static Cube | ||
| 426 | antindex_cornershtr(uint64_t ind) | ||
| 427 | { | ||
| 428 | Cube c = anti_cphtr(ind % (BINOM8ON4 * 6)); | ||
| 429 | |||
| 430 | c.coud = ind / (BINOM8ON4 * 6); | ||
| 431 | |||
| 432 | return c; | ||
| 433 | } | ||
| 434 | |||
| 435 | /* TODO: admissible eos and cos */ | ||
| 436 | /* DONE: temporary fix, make it better */ | ||
| 437 | static Cube | ||
| 438 | antindex_drud(uint64_t ind) | ||
| 439 | { | ||
| 440 | uint64_t epos, eofb; | ||
| 441 | Cube c; | ||
| 442 | |||
| 443 | eofb = ind % POW2TO11; | ||
| 444 | epos = ind / (POW2TO11 * POW3TO7); | ||
| 445 | c = admissible_ee_aux[eofb + POW2TO11 * epos]; | ||
| 446 | |||
| 447 | c.coud = (ind / POW2TO11) % POW3TO7; | ||
| 448 | c.corl = c.coud; | ||
| 449 | c.cofb = c.coud; | ||
| 450 | |||
| 451 | return c; | ||
| 452 | } | ||
| 453 | |||
| 454 | static Cube | ||
| 455 | antindex_coud_sym16(uint64_t ind) | ||
| 456 | { | ||
| 457 | return sd_coud_16.rep[ind]; | ||
| 458 | } | ||
| 459 | |||
| 460 | static Cube | ||
| 461 | antindex_eofbepos_sym16(uint64_t ind) | ||
| 462 | { | ||
| 463 | return sd_eofbepos_16.rep[ind]; | ||
| 464 | } | ||
| 465 | |||
| 466 | static Cube | ||
| 467 | antindex_drud_sym16(uint64_t ind) | ||
| 468 | { | ||
| 469 | Cube c; | ||
| 470 | |||
| 471 | c = sd_eofbepos_16.rep[ind/POW3TO7]; | ||
| 472 | c.coud = ind % POW3TO7; | ||
| 473 | c.cofb = c.coud; | ||
| 474 | c.corl = c.coud; | ||
| 475 | |||
| 476 | return c; | ||
| 477 | } | ||
| 478 | |||
| 479 | static Cube | ||
| 480 | antindex_khuge(uint64_t ind) | ||
| 481 | { | ||
| 482 | Cube c; | ||
| 483 | |||
| 484 | c = sd_eofbepos_16.rep[ind/(FACTORIAL4*POW3TO7)]; | ||
| 485 | c.epose = ((c.epose / 24) * 24) + ((ind/POW3TO7) % 24); | ||
| 486 | c.coud = ind % POW3TO7; | ||
| 487 | |||
| 488 | return c; | ||
| 489 | } | ||
| 490 | |||
| 491 | |||
| 492 | /* Checkers ******************************************************************/ | ||
| 493 | |||
| 494 | bool | ||
| 495 | check_centers(Cube cube) | ||
| 496 | { | ||
| 497 | return cube.cpos == 0; | ||
| 498 | } | ||
| 499 | |||
| 500 | bool | ||
| 501 | check_corners(Cube cube) | ||
| 502 | { | ||
| 503 | return cube.cp == 0 && cube.coud == 0; | ||
| 504 | } | ||
| 505 | |||
| 506 | bool | ||
| 507 | check_cornershtr(Cube cube) | ||
| 508 | { | ||
| 509 | return cube.coud == 0 && cphtr(cube) == 0; /* TODO: use array cphtrcosets*/ | ||
| 510 | } | ||
| 511 | |||
| 512 | bool | ||
| 513 | check_coud(Cube cube) | ||
| 514 | { | ||
| 515 | return cube.coud == 0; | ||
| 516 | } | ||
| 517 | |||
| 518 | bool | ||
| 519 | check_drud(Cube cube) | ||
| 520 | { | ||
| 521 | return cube.eofb == 0 && cube.eorl == 0 && cube.coud == 0; | ||
| 522 | } | ||
| 523 | |||
| 524 | bool | ||
| 525 | check_eofb(Cube cube) | ||
| 526 | { | ||
| 527 | return cube.eofb == 0; | ||
| 528 | } | ||
| 529 | |||
| 530 | bool | ||
| 531 | check_eofbepos(Cube cube) | ||
| 532 | { | ||
| 533 | return cube.eofb == 0 && cube.epose / 24 == 0; | ||
| 534 | } | ||
| 535 | |||
| 536 | bool | ||
| 537 | check_epose(Cube cube) | ||
| 538 | { | ||
| 539 | return cube.epose == 0; | ||
| 540 | } | ||
| 541 | |||
| 542 | bool | ||
| 543 | check_ep(Cube cube) | ||
| 544 | { | ||
| 545 | return cube.epose == 0 && cube.eposs == 0 && cube.eposm == 0; | ||
| 546 | } | ||
| 547 | |||
| 548 | bool | ||
| 549 | check_khuge(Cube cube) | ||
| 550 | { | ||
| 551 | return check_drud(cube) && cube.epose % 24 == 0; | ||
| 552 | } | ||
| 553 | |||
| 554 | bool | ||
| 555 | check_nothing(Cube cube) | ||
| 556 | { | ||
| 557 | return is_admissible(cube); /*TODO: maybe change?*/ | ||
| 558 | } | ||
| 559 | |||
| 560 | /* Movesets ******************************************************************/ | ||
| 561 | |||
| 562 | bool | ||
| 563 | moveset_HTM(Move m) | ||
| 564 | { | ||
| 565 | return m >= U && m <= B3; | ||
| 566 | } | ||
| 567 | |||
| 568 | bool | ||
| 569 | moveset_URF(Move m) | ||
| 570 | { | ||
| 571 | Move b = base_move(m); | ||
| 572 | |||
| 573 | return b == U || b == R || b == F; | ||
| 574 | } | ||
| 575 | |||
| 576 | |||
| 577 | /* Local functions implementation ********************************************/ | ||
| 578 | |||
| 579 | /* TODO: this should be an anti index (maybe?) */ | ||
| 580 | static Cube | ||
| 581 | admissible_ep(Cube cube, PieceFilter f) | ||
| 582 | { | ||
| 583 | CubeArray *arr = new_cubearray(cube, f); | ||
| 584 | Cube ret; | ||
| 585 | bool used[12] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; | ||
| 586 | int i, j; | ||
| 587 | |||
| 588 | for (i = 0; i < 12; i++) | ||
| 589 | if (arr->ep[i] != -1) | ||
| 590 | used[arr->ep[i]] = true; | ||
| 591 | |||
| 592 | for (i = 0, j = 0; i < 12; i++) { | ||
| 593 | for ( ; j < 11 && used[j]; j++); | ||
| 594 | if (arr->ep[i] == -1) | ||
| 595 | arr->ep[i] = j++; | ||
| 596 | } | ||
| 597 | |||
| 598 | ret = arrays_to_cube(arr, pf_ep); | ||
| 599 | free_cubearray(arr, f); | ||
| 600 | |||
| 601 | return ret; | ||
| 602 | } | ||
| 603 | |||
| 604 | static Cube | ||
| 605 | admissible_eos_from_eofbepos(Cube cube) | ||
| 606 | { | ||
| 607 | Edge e; | ||
| 608 | Cube ret; | ||
| 609 | CubeArray *arr = new_cubearray(cube, pf_all); | ||
| 610 | |||
| 611 | memcpy(arr->eorl, arr->eofb, 12 * sizeof(int)); | ||
| 612 | memcpy(arr->eoud, arr->eofb, 12 * sizeof(int)); | ||
| 613 | |||
| 614 | for (e = 0; e < 12; e++) { | ||
| 615 | if ((edge_slice(e) != 0 && edge_slice(arr->ep[e]) == 0) || | ||
| 616 | (edge_slice(e) == 0 && edge_slice(arr->ep[e]) != 0)) | ||
| 617 | arr->eorl[e] = 1 - arr->eorl[e]; | ||
| 618 | if ((edge_slice(e) != 2 && edge_slice(arr->ep[e]) == 2) || | ||
| 619 | (edge_slice(e) == 2 && edge_slice(arr->ep[e]) != 2)) | ||
| 620 | arr->eoud[e] = 1 - arr->eoud[e]; | ||
| 621 | } | ||
| 622 | |||
| 623 | ret = arrays_to_cube(arr, pf_all); | ||
| 624 | free_cubearray(arr, pf_all); | ||
| 625 | |||
| 626 | return ret; | ||
| 627 | } | ||
| 628 | |||
| 629 | static bool | ||
| 630 | allowed_next(Move move, DfsData *dd) | ||
| 631 | { | ||
| 632 | if (!possible_next[dd->last2][dd->last1][move]) | ||
| 633 | return false; | ||
| 634 | |||
| 635 | if (commute[dd->last1][move]) | ||
| 636 | return dd->move_position[dd->last1] < dd->move_position[move]; | ||
| 637 | |||
| 638 | return true; | ||
| 639 | } | ||
| 640 | |||
| 641 | static void | ||
| 642 | append_alg(AlgList *l, Alg *alg) | ||
| 643 | { | ||
| 644 | AlgListNode *node = malloc(sizeof(AlgListNode)); | ||
| 645 | int i; | ||
| 646 | |||
| 647 | node->alg = new_alg(""); | ||
| 648 | for (i = 0; i < alg->len; i++) | ||
| 649 | append_move(node->alg, alg->move[i], alg->inv[i]); | ||
| 650 | node->next = NULL; | ||
| 651 | |||
| 652 | if (++l->len == 1) | ||
| 653 | l->first = node; | ||
| 654 | else | ||
| 655 | l->last->next = node; | ||
| 656 | l->last = node; | ||
| 657 | } | ||
| 658 | |||
| 659 | static void | ||
| 660 | append_move(Alg *alg, Move m, bool inverse) | ||
| 661 | { | ||
| 662 | if (alg->len == alg->allocated) | ||
| 663 | realloc_alg(alg, 2*alg->len); | ||
| 664 | |||
| 665 | alg->move[alg->len] = m; | ||
| 666 | alg->inv [alg->len] = inverse; | ||
| 667 | alg->len++; | ||
| 668 | } | ||
| 669 | |||
| 670 | static Cube | ||
| 671 | apply_alg_generic(Alg *alg, Cube c, PieceFilter f, bool a) | ||
| 672 | { | ||
| 673 | Cube ret = {0}; | ||
| 674 | int i; | ||
| 675 | |||
| 676 | for (i = 0; i < alg->len; i++) | ||
| 677 | if (alg->inv[i]) | ||
| 678 | ret = a ? apply_move(alg->move[i], ret) : | ||
| 679 | apply_move_cubearray(alg->move[i], ret, f); | ||
| 680 | |||
| 681 | ret = compose_filtered(c, inverse_cube(ret), f); | ||
| 682 | |||
| 683 | for (i = 0; i < alg->len; i++) | ||
| 684 | if (!alg->inv[i]) | ||
| 685 | ret = a ? apply_move(alg->move[i], ret) : | ||
| 686 | apply_move_cubearray(alg->move[i], ret, f); | ||
| 687 | |||
| 688 | return ret; | ||
| 689 | } | ||
| 690 | |||
| 691 | static void | ||
| 692 | apply_permutation(int *perm, int *set, int n) | ||
| 693 | { | ||
| 694 | int *aux = malloc(n * sizeof(int)); | ||
| 695 | int i; | ||
| 696 | |||
| 697 | if (!is_perm(perm, n)) | ||
| 698 | return; | ||
| 699 | |||
| 700 | for (i = 0; i < n; i++) | ||
| 701 | aux[i] = set[perm[i]]; | ||
| 702 | |||
| 703 | memcpy(set, aux, n * sizeof(int)); | ||
| 704 | free(aux); | ||
| 705 | } | ||
| 706 | |||
| 707 | static Cube | ||
| 708 | apply_move_cubearray(Move m, Cube cube, PieceFilter f) | ||
| 709 | { | ||
| 710 | CubeArray m_arr = { | ||
| 711 | edge_cycle[m], | ||
| 712 | eofb_flipped[m], | ||
| 713 | eorl_flipped[m], | ||
| 714 | eoud_flipped[m], | ||
| 715 | corner_cycle[m], | ||
| 716 | coud_flipped[m], | ||
| 717 | corl_flipped[m], | ||
| 718 | cofb_flipped[m], | ||
| 719 | center_cycle[m] | ||
| 720 | }; | ||
| 721 | |||
| 722 | return move_via_arrays(&m_arr, cube, f); | ||
| 723 | } | ||
| 724 | |||
| 725 | static int | ||
| 726 | array_ep_to_epos(int *ep, int *ss) | ||
| 727 | { | ||
| 728 | int epos[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; | ||
| 729 | int eps[4]; | ||
| 730 | int i, j, is; | ||
| 731 | |||
| 732 | for (i = 0, is = 0; i < 12; i++) { | ||
| 733 | for (j = 0; j < 4; j++) { | ||
| 734 | if (ep[i] == ss[j]) { | ||
| 735 | eps[is++] = j; | ||
| 736 | epos[i] = 1; | ||
| 737 | } | ||
| 738 | } | ||
| 739 | } | ||
| 740 | |||
| 741 | for (i = 0; i < 4; i++) | ||
| 742 | swap(&epos[ss[i]], &epos[i+8]); | ||
| 743 | |||
| 744 | return epos_from_arrays(epos, eps); | ||
| 745 | } | ||
| 746 | |||
| 747 | static Cube | ||
| 748 | arrays_to_cube(CubeArray *arr, PieceFilter f) | ||
| 749 | { | ||
| 750 | Cube ret = {0}; | ||
| 751 | |||
| 752 | if (f.epose) | ||
| 753 | ret.epose = array_ep_to_epos(arr->ep, epe_solved); | ||
| 754 | if (f.eposs) | ||
| 755 | ret.eposs = array_ep_to_epos(arr->ep, eps_solved); | ||
| 756 | if (f.eposm) | ||
| 757 | ret.eposm = array_ep_to_epos(arr->ep, epm_solved); | ||
| 758 | if (f.eofb) | ||
| 759 | ret.eofb = digit_array_to_int(arr->eofb, 11, 2); | ||
| 760 | if (f.eorl) | ||
| 761 | ret.eorl = digit_array_to_int(arr->eorl, 11, 2); | ||
| 762 | if (f.eoud) | ||
| 763 | ret.eoud = digit_array_to_int(arr->eoud, 11, 2); | ||
| 764 | if (f.cp) | ||
| 765 | ret.cp = perm_to_index(arr->cp, 8); | ||
| 766 | if (f.coud) | ||
| 767 | ret.coud = digit_array_to_int(arr->coud, 7, 3); | ||
| 768 | if (f.corl) | ||
| 769 | ret.corl = digit_array_to_int(arr->corl, 7, 3); | ||
| 770 | if (f.cofb) | ||
| 771 | ret.cofb = digit_array_to_int(arr->cofb, 7, 3); | ||
| 772 | if (f.cpos) | ||
| 773 | ret.cpos = perm_to_index(arr->cpos, 6); | ||
| 774 | |||
| 775 | return ret; | ||
| 776 | } | ||
| 777 | |||
| 778 | static int | ||
| 779 | binomial(int n, int k) | ||
| 780 | { | ||
| 781 | if (n < 0 || k < 0 || k > n) | ||
| 782 | return 0; | ||
| 783 | |||
| 784 | return factorial(n) / (factorial(k) * factorial(n-k)); | ||
| 785 | } | ||
| 786 | |||
| 787 | static Cube | ||
| 788 | compose_filtered(Cube c2, Cube c1, PieceFilter f) | ||
| 789 | { | ||
| 790 | CubeArray *arr = new_cubearray(c2, f); | ||
| 791 | Cube ret; | ||
| 792 | |||
| 793 | ret = move_via_arrays(arr, c1, f); | ||
| 794 | free_cubearray(arr, f); | ||
| 795 | |||
| 796 | return ret; | ||
| 797 | } | ||
| 798 | |||
| 799 | static void | ||
| 800 | cube_to_arrays(Cube cube, CubeArray *arr, PieceFilter f) | ||
| 801 | { | ||
| 802 | int i; | ||
| 803 | |||
| 804 | if (f.epose || f.eposs || f.eposm) | ||
| 805 | for (i = 0; i < 12; i++) | ||
| 806 | arr->ep[i] = -1; | ||
| 807 | |||
| 808 | if (f.epose) | ||
| 809 | epos_to_partial_ep(cube.epose, arr->ep, epe_solved); | ||
| 810 | if (f.eposs) | ||
| 811 | epos_to_partial_ep(cube.eposs, arr->ep, eps_solved); | ||
| 812 | if (f.eposm) | ||
| 813 | epos_to_partial_ep(cube.eposm, arr->ep, epm_solved); | ||
| 814 | if (f.eofb) | ||
| 815 | int_to_sum_zero_array(cube.eofb, 2, 12, arr->eofb); | ||
| 816 | if (f.eorl) | ||
| 817 | int_to_sum_zero_array(cube.eorl, 2, 12, arr->eorl); | ||
| 818 | if (f.eoud) | ||
| 819 | int_to_sum_zero_array(cube.eoud, 2, 12, arr->eoud); | ||
| 820 | if (f.cp) | ||
| 821 | index_to_perm(cube.cp, 8, arr->cp); | ||
| 822 | if (f.coud) | ||
| 823 | int_to_sum_zero_array(cube.coud, 3, 8, arr->coud); | ||
| 824 | if (f.corl) | ||
| 825 | int_to_sum_zero_array(cube.corl, 3, 8, arr->corl); | ||
| 826 | if (f.cofb) | ||
| 827 | int_to_sum_zero_array(cube.cofb, 3, 8, arr->cofb); | ||
| 828 | if (f.cpos) | ||
| 829 | index_to_perm(cube.cpos, 6, arr->cpos); | ||
| 830 | } | ||
| 831 | |||
| 832 | /* | ||
| 833 | static int | ||
| 834 | cphtr_cp(int cp) | ||
| 835 | { | ||
| 836 | int i, a[8]; | ||
| 837 | |||
| 838 | index_to_perm(cp, 8, a); | ||
| 839 | |||
| 840 | for (i = 0; i < 8; i++) | ||
| 841 | if (a[i] == UFR || a[i] == UBL || a[i] == DFL || a[i] == DBR) | ||
| 842 | a[i] = 0; | ||
| 843 | else | ||
| 844 | a[i] = 1; | ||
| 845 | |||
| 846 | swap(&a[1], &a[5]); | ||
| 847 | swap(&a[3], &a[7]); | ||
| 848 | |||
| 849 | return subset_to_index(a, 8, 4); | ||
| 850 | } | ||
| 851 | */ | ||
| 852 | |||
| 853 | static void | ||
| 854 | dfs(Cube c, Step s, SolveOptions *opts, DfsData *dd) | ||
| 855 | { | ||
| 856 | if (dfs_stop(c, s, opts, dd)) | ||
| 857 | return; | ||
| 858 | |||
| 859 | if (dfs_check_solved(opts, dd)) | ||
| 860 | return; | ||
| 861 | |||
| 862 | dfs_branch(c, s, opts, dd); | ||
| 863 | |||
| 864 | if (opts->can_niss && !dd->niss) | ||
| 865 | dfs_niss(c, s, opts, dd); | ||
| 866 | } | ||
| 867 | |||
| 868 | static void | ||
| 869 | dfs_branch(Cube c, Step s, SolveOptions *opts, DfsData *dd) | ||
| 870 | { | ||
| 871 | Move m, l1 = dd->last1, l2 = dd->last2, *moves = dd->sorted_moves; | ||
| 872 | |||
| 873 | int i, maxnsol = opts->max_solutions; | ||
| 874 | |||
| 875 | for (i = 0; moves[i] != NULLMOVE && dd->sols->len < maxnsol; i++) { | ||
| 876 | m = moves[i]; | ||
| 877 | if (allowed_next(m, dd)) { | ||
| 878 | dd->last2 = dd->last1; | ||
| 879 | dd->last1 = m; | ||
| 880 | append_move(dd->current_alg, m, dd->niss); | ||
| 881 | |||
| 882 | dfs(apply_move(m, c), s, opts, dd); | ||
| 883 | |||
| 884 | dd->current_alg->len--; | ||
| 885 | dd->last2 = l2; | ||
| 886 | dd->last1 = l1; | ||
| 887 | } | ||
| 888 | } | ||
| 889 | } | ||
| 890 | |||
| 891 | static bool | ||
| 892 | dfs_check_solved(SolveOptions *opts, DfsData *dd) | ||
| 893 | { | ||
| 894 | if (dd->lb != 0) | ||
| 895 | return false; | ||
| 896 | |||
| 897 | if (dd->current_alg->len == dd->d) { | ||
| 898 | append_alg(dd->sols, dd->current_alg); | ||
| 899 | |||
| 900 | if (opts->feedback) | ||
| 901 | print_alg(dd->current_alg, false); | ||
| 902 | } | ||
| 903 | |||
| 904 | return true; | ||
| 905 | } | ||
| 906 | |||
| 907 | static void | ||
| 908 | dfs_niss(Cube c, Step s, SolveOptions *opts, DfsData *dd) | ||
| 909 | { | ||
| 910 | Move l1 = dd->last1, l2 = dd->last2; | ||
| 911 | CubeTarget ct; | ||
| 912 | |||
| 913 | ct.cube = apply_move(inverse_move(l1), (Cube){0}); | ||
| 914 | ct.target = 1; | ||
| 915 | |||
| 916 | if (dd->current_alg->len == 0 || s.estimate(ct)) { | ||
| 917 | dd->niss = true; | ||
| 918 | dd->last1 = NULLMOVE; | ||
| 919 | dd->last2 = NULLMOVE; | ||
| 920 | |||
| 921 | dfs(inverse_cube(c), s, opts, dd); | ||
| 922 | |||
| 923 | dd->last1 = l1; | ||
| 924 | dd->last2 = l2; | ||
| 925 | dd->niss = false; | ||
| 926 | } | ||
| 927 | } | ||
| 928 | |||
| 929 | static bool | ||
| 930 | dfs_stop(Cube c, Step s, SolveOptions *opts, DfsData *dd) | ||
| 931 | { | ||
| 932 | CubeTarget ct = { | ||
| 933 | .cube = c, | ||
| 934 | .target = dd->d - dd->current_alg->len | ||
| 935 | }; | ||
| 936 | |||
| 937 | if (dd->sols->len >= opts->max_solutions) | ||
| 938 | return true; | ||
| 939 | |||
| 940 | dd->lb = s.estimate(ct); | ||
| 941 | if (opts->can_niss && !dd->niss) | ||
| 942 | dd->lb = MIN(1, dd->lb); | ||
| 943 | |||
| 944 | if (dd->current_alg->len + dd->lb > dd->d) | ||
| 945 | return true; | ||
| 946 | |||
| 947 | return false; | ||
| 948 | } | ||
| 949 | |||
| 950 | static int | ||
| 951 | digit_array_to_int(int *a, int n, int b) | ||
| 952 | { | ||
| 953 | int i, ret = 0, p = 1; | ||
| 954 | |||
| 955 | for (i = 0; i < n; i++, p *= b) | ||
| 956 | ret += a[i] * p; | ||
| 957 | |||
| 958 | return ret; | ||
| 959 | } | ||
| 960 | |||
| 961 | static int | ||
| 962 | edge_slice(Edge e) { | ||
| 963 | if (e < 0 || e > 11) | ||
| 964 | return -1; | ||
| 965 | |||
| 966 | if (e == FR || e == FL || e == BL || e == BR) | ||
| 967 | return 0; | ||
| 968 | if (e == UR || e == UL || e == DR || e == DL) | ||
| 969 | return 1; | ||
| 970 | |||
| 971 | return 2; | ||
| 972 | } | ||
| 973 | |||
| 974 | static int | ||
| 975 | epos_dependent_pos(int poss, int pose) | ||
| 976 | { | ||
| 977 | int ep[12] = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}; | ||
| 978 | int ep8[8] = {0, 0, 0, 0, 0, 0, 0, 0}; | ||
| 979 | int i, j; | ||
| 980 | |||
| 981 | epos_to_partial_ep(poss*FACTORIAL4, ep, eps_solved); | ||
| 982 | epos_to_partial_ep(pose*FACTORIAL4, ep, epe_solved); | ||
| 983 | |||
| 984 | for (i = 0, j = 0; i < 12; i++) | ||
| 985 | if (edge_slice(ep[i]) != 0) | ||
| 986 | ep8[j++] = (edge_slice(ep[i]) == 1) ? 1 : 0; | ||
| 987 | |||
| 988 | swap(&ep8[1], &ep8[4]); | ||
| 989 | swap(&ep8[3], &ep8[6]); | ||
| 990 | |||
| 991 | return subset_to_index(ep8, 8, 4); | ||
| 992 | } | ||
| 993 | |||
| 994 | static int | ||
| 995 | epos_from_arrays(int *epos, int *ep) | ||
| 996 | { | ||
| 997 | return FACTORIAL4 * subset_to_index(epos,12,4) + perm_to_index(ep,4); | ||
| 998 | } | ||
| 999 | |||
| 1000 | static void | ||
| 1001 | epos_to_partial_ep(int epos, int *ep, int *ss) | ||
| 1002 | { | ||
| 1003 | int i, is, eposs[12], eps[4]; | ||
| 1004 | |||
| 1005 | index_to_perm(epos % FACTORIAL4, 4, eps); | ||
| 1006 | index_to_subset(epos / FACTORIAL4, 12, 4, eposs); | ||
| 1007 | |||
| 1008 | for (i = 0; i < 4; i++) | ||
| 1009 | swap(&eposs[ss[i]], &eposs[i+8]); | ||
| 1010 | |||
| 1011 | for (i = 0, is = 0; i < 12; i++) | ||
| 1012 | if (eposs[i]) | ||
| 1013 | ep[i] = ss[eps[is++]]; | ||
| 1014 | } | ||
| 1015 | |||
| 1016 | static int | ||
| 1017 | factorial(int n) | ||
| 1018 | { | ||
| 1019 | int i, ret = 1; | ||
| 1020 | |||
| 1021 | if (n < 0) | ||
| 1022 | return 0; | ||
| 1023 | |||
| 1024 | for (i = 1; i <= n; i++) | ||
| 1025 | ret *= i; | ||
| 1026 | |||
| 1027 | return ret; | ||
| 1028 | } | ||
| 1029 | |||
| 1030 | void | ||
| 1031 | free_alg(Alg *alg) | ||
| 1032 | { | ||
| 1033 | free(alg->move); | ||
| 1034 | free(alg->inv); | ||
| 1035 | free(alg); | ||
| 1036 | } | ||
| 1037 | |||
| 1038 | void | ||
| 1039 | free_alglist(AlgList *l) | ||
| 1040 | { | ||
| 1041 | AlgListNode *aux, *i = l->first; | ||
| 1042 | |||
| 1043 | while (i != NULL) { | ||
| 1044 | aux = i->next; | ||
| 1045 | free_alglistnode(i); | ||
| 1046 | i = aux; | ||
| 1047 | } | ||
| 1048 | free(l); | ||
| 1049 | } | ||
| 1050 | |||
| 1051 | void | ||
| 1052 | free_alglistnode(AlgListNode *aln) | ||
| 1053 | { | ||
| 1054 | free_alg(aln->alg); | ||
| 1055 | free(aln); | ||
| 1056 | } | ||
| 1057 | |||
| 1058 | static void | ||
| 1059 | free_cubearray(CubeArray *arr, PieceFilter f) | ||
| 1060 | { | ||
| 1061 | if (f.epose || f.eposs || f.eposm) | ||
| 1062 | free(arr->ep); | ||
| 1063 | if (f.eofb) | ||
| 1064 | free(arr->eofb); | ||
| 1065 | if (f.eorl) | ||
| 1066 | free(arr->eorl); | ||
| 1067 | if (f.eoud) | ||
| 1068 | free(arr->eoud); | ||
| 1069 | if (f.cp) | ||
| 1070 | free(arr->cp); | ||
| 1071 | if (f.coud) | ||
| 1072 | free(arr->coud); | ||
| 1073 | if (f.corl) | ||
| 1074 | free(arr->corl); | ||
| 1075 | if (f.cofb) | ||
| 1076 | free(arr->cofb); | ||
| 1077 | if (f.cpos) | ||
| 1078 | free(arr->cpos); | ||
| 1079 | |||
| 1080 | free(arr); | ||
| 1081 | } | ||
| 1082 | |||
| 1083 | static void | ||
| 1084 | genptable_bfs(PruneData *pd, int d, Move *ms) | ||
| 1085 | { | ||
| 1086 | uint64_t i; | ||
| 1087 | |||
| 1088 | for (i = 0; i < pd->coord->max; i++) | ||
| 1089 | if (ptableval_index(pd, i) == d) | ||
| 1090 | genptable_branch(pd, i, d, ms); | ||
| 1091 | } | ||
| 1092 | |||
| 1093 | static void | ||
| 1094 | genptable_branch(PruneData *pd, uint64_t ind, int d, Move *ms) | ||
| 1095 | { | ||
| 1096 | int i, j; | ||
| 1097 | Cube cc, c; | ||
| 1098 | |||
| 1099 | |||
| 1100 | for (i = 0; i < pd->ntrans; i++) { | ||
| 1101 | c = apply_trans(pd->trans[i], pd->coord->cube(ind)); | ||
| 1102 | for (j = 0; ms[j] != NULLMOVE; j++) { | ||
| 1103 | cc = apply_move(ms[j], c); | ||
| 1104 | if (ptableval(pd, cc) > d+1) | ||
| 1105 | ptable_update(pd, cc, d+1); | ||
| 1106 | } | ||
| 1107 | } | ||
| 1108 | } | ||
| 1109 | |||
| 1110 | static void | ||
| 1111 | gensym(SymData *sd) | ||
| 1112 | { | ||
| 1113 | uint64_t i, in, nreps = 0; | ||
| 1114 | int j; | ||
| 1115 | Cube c, d; | ||
| 1116 | |||
| 1117 | if (sd->generated) | ||
| 1118 | return; | ||
| 1119 | |||
| 1120 | sd->class = malloc(sd->coord->max * sizeof(uint64_t)); | ||
| 1121 | sd->rep = malloc(sd->coord->max * sizeof(Cube)); | ||
| 1122 | sd->transtorep = malloc(sd->coord->max * sizeof(Trans)); | ||
| 1123 | |||
| 1124 | if (read_symdata_file(sd)) { | ||
| 1125 | sd->generated = true; | ||
| 1126 | return; | ||
| 1127 | } | ||
| 1128 | |||
| 1129 | fprintf(stderr, "Cannot load %s, generating it\n", sd->filename); | ||
| 1130 | |||
| 1131 | for (i = 0; i < sd->coord->max; i++) | ||
| 1132 | sd->class[i] = sd->coord->max + 1; | ||
| 1133 | |||
| 1134 | for (i = 0; i < sd->coord->max; i++) { | ||
| 1135 | if (sd->class[i] == sd->coord->max + 1) { | ||
| 1136 | c = sd->coord->cube(i); | ||
| 1137 | sd->rep[nreps] = c; | ||
| 1138 | for (j = 0; j < sd->ntrans; j++) { | ||
| 1139 | d = apply_trans(sd->trans[j], c); | ||
| 1140 | in = sd->coord->index(d); | ||
| 1141 | |||
| 1142 | if (sd->class[in] == sd->coord->max + 1) { | ||
| 1143 | sd->class[in] = nreps; | ||
| 1144 | sd->transtorep[in] = | ||
| 1145 | inverse_trans(sd->trans[j]); | ||
| 1146 | } | ||
| 1147 | } | ||
| 1148 | nreps++; | ||
| 1149 | } | ||
| 1150 | } | ||
| 1151 | |||
| 1152 | sd->sym_coord->max = nreps; | ||
| 1153 | sd->rep = realloc(sd->rep, nreps * sizeof(Cube)); | ||
| 1154 | sd->generated = true; | ||
| 1155 | |||
| 1156 | fprintf(stderr, "Found %lu classes\n", nreps); | ||
| 1157 | |||
| 1158 | if (!write_symdata_file(sd)) | ||
| 1159 | fprintf(stderr, "Error writing SymData file\n"); | ||
| 1160 | |||
| 1161 | return; | ||
| 1162 | } | ||
| 1163 | |||
| 1164 | static void | ||
| 1165 | index_to_perm(int p, int n, int *r) | ||
| 1166 | { | ||
| 1167 | int *a = malloc(n * sizeof(int)); | ||
| 1168 | int i, j, c; | ||
| 1169 | |||
| 1170 | for (i = 0; i < n; i++) | ||
| 1171 | a[i] = 0; | ||
| 1172 | |||
| 1173 | if (p < 0 || p >= factorial(n)) | ||
| 1174 | for (i = 0; i < n; i++) | ||
| 1175 | r[i] = -1; | ||
| 1176 | |||
| 1177 | for (i = 0; i < n; i++) { | ||
| 1178 | c = 0; | ||
| 1179 | j = 0; | ||
| 1180 | while (c <= p / factorial(n-i-1)) | ||
| 1181 | c += a[j++] ? 0 : 1; | ||
| 1182 | r[i] = j-1; | ||
| 1183 | a[j-1] = 1; | ||
| 1184 | p %= factorial(n-i-1); | ||
| 1185 | } | ||
| 1186 | |||
| 1187 | free(a); | ||
| 1188 | } | ||
| 1189 | |||
| 1190 | static void | ||
| 1191 | index_to_subset(int s, int n, int k, int *r) | ||
| 1192 | { | ||
| 1193 | int i, j, v; | ||
| 1194 | |||
| 1195 | if (s < 0 || s >= binomial(n, k)) { | ||
| 1196 | for (i = 0; i < n; i++) | ||
| 1197 | r[i] = -1; | ||
| 1198 | return; | ||
| 1199 | } | ||
| 1200 | |||
| 1201 | for (i = 0; i < n; i++) { | ||
| 1202 | if (k == n-i) { | ||
| 1203 | for (j = i; j < n; j++) | ||
| 1204 | r[j] = 1; | ||
| 1205 | return; | ||
| 1206 | } | ||
| 1207 | |||
| 1208 | if (k == 0) { | ||
| 1209 | for (j = i; j < n; j++) | ||
| 1210 | r[j] = 0; | ||
| 1211 | return; | ||
| 1212 | } | ||
| 1213 | |||
| 1214 | v = binomial(n-i-1, k); | ||
| 1215 | if (s >= v) { | ||
| 1216 | r[i] = 1; | ||
| 1217 | k--; | ||
| 1218 | s -= v; | ||
| 1219 | } else { | ||
| 1220 | r[i] = 0; | ||
| 1221 | } | ||
| 1222 | } | ||
| 1223 | } | ||
| 1224 | |||
| 1225 | static void | ||
| 1226 | int_to_digit_array(int a, int b, int n, int *r) | ||
| 1227 | { | ||
| 1228 | int i; | ||
| 1229 | |||
| 1230 | if (b <= 1) | ||
| 1231 | for (i = 0; i < n; i++) | ||
| 1232 | r[i] = 0; | ||
| 1233 | else | ||
| 1234 | for (i = 0; i < n; i++, a /= b) | ||
| 1235 | r[i] = a % b; | ||
| 1236 | } | ||
| 1237 | |||
| 1238 | static void | ||
| 1239 | int_to_sum_zero_array(int x, int b, int n, int *a) | ||
| 1240 | { | ||
| 1241 | int i, s = 0; | ||
| 1242 | |||
| 1243 | if (b <= 1) { | ||
| 1244 | for (i = 0; i < n; i++) | ||
| 1245 | a[i] = 0; | ||
| 1246 | } else { | ||
| 1247 | int_to_digit_array(x, b, n-1, a); | ||
| 1248 | for (i = 0; i < n - 1; i++) | ||
| 1249 | s = (s + a[i]) % b; | ||
| 1250 | a[n-1] = (b - s) % b; | ||
| 1251 | } | ||
| 1252 | } | ||
| 1253 | |||
| 1254 | static int | ||
| 1255 | invert_digits(int a, int b, int n) | ||
| 1256 | { | ||
| 1257 | int i, ret, *r = malloc(n * sizeof(int)); | ||
| 1258 | |||
| 1259 | int_to_digit_array(a, b, n, r); | ||
| 1260 | for (i = 0; i < n; i++) | ||
| 1261 | r[i] = (b-r[i]) % b; | ||
| 1262 | |||
| 1263 | ret = digit_array_to_int(r, n, b); | ||
| 1264 | free(r); | ||
| 1265 | return ret; | ||
| 1266 | } | ||
| 1267 | |||
| 1268 | static bool | ||
| 1269 | is_perm(int *a, int n) | ||
| 1270 | { | ||
| 1271 | int *aux = malloc(n * sizeof(int)); | ||
| 1272 | int i; | ||
| 1273 | |||
| 1274 | for (i = 0; i < n; i++) | ||
| 1275 | if (a[i] < 0 || a[i] >= n) | ||
| 1276 | return false; | ||
| 1277 | else | ||
| 1278 | aux[a[i]] = 1; | ||
| 1279 | |||
| 1280 | for (i = 0; i < n; i++) | ||
| 1281 | if (!aux[i]) | ||
| 1282 | return false; | ||
| 1283 | |||
| 1284 | free(aux); | ||
| 1285 | |||
| 1286 | return true; | ||
| 1287 | } | ||
| 1288 | |||
| 1289 | static bool | ||
| 1290 | is_subset(int *a, int n, int k) | ||
| 1291 | { | ||
| 1292 | int i, sum = 0; | ||
| 1293 | |||
| 1294 | for (i = 0; i < n; i++) | ||
| 1295 | sum += a[i] ? 1 : 0; | ||
| 1296 | |||
| 1297 | return sum == k; | ||
| 1298 | } | ||
| 1299 | |||
| 1300 | static Cube | ||
| 1301 | move_via_arrays(CubeArray *arr, Cube c, PieceFilter f) | ||
| 1302 | { | ||
| 1303 | CubeArray *arrc = new_cubearray(c, f); | ||
| 1304 | Cube ret; | ||
| 1305 | |||
| 1306 | if (f.epose || f.eposs || f.eposm) | ||
| 1307 | apply_permutation(arr->ep, arrc->ep, 12); | ||
| 1308 | |||
| 1309 | if (f.eofb) { | ||
| 1310 | apply_permutation(arr->ep, arrc->eofb, 12); | ||
| 1311 | sum_arrays_mod(arr->eofb, arrc->eofb, 12, 2); | ||
| 1312 | } | ||
| 1313 | |||
| 1314 | if (f.eorl) { | ||
| 1315 | apply_permutation(arr->ep, arrc->eorl, 12); | ||
| 1316 | sum_arrays_mod(arr->eorl, arrc->eorl, 12, 2); | ||
| 1317 | } | ||
| 1318 | |||
| 1319 | if (f.eoud) { | ||
| 1320 | apply_permutation(arr->ep, arrc->eoud, 12); | ||
| 1321 | sum_arrays_mod(arr->eoud, arrc->eoud, 12, 2); | ||
| 1322 | } | ||
| 1323 | |||
| 1324 | if (f.cp) | ||
| 1325 | apply_permutation(arr->cp, arrc->cp, 8); | ||
| 1326 | |||
| 1327 | if (f.coud) { | ||
| 1328 | apply_permutation(arr->cp, arrc->coud, 8); | ||
| 1329 | sum_arrays_mod(arr->coud, arrc->coud, 8, 3); | ||
| 1330 | } | ||
| 1331 | |||
| 1332 | if (f.corl) { | ||
| 1333 | apply_permutation(arr->cp, arrc->corl, 8); | ||
| 1334 | sum_arrays_mod(arr->corl, arrc->corl, 8, 3); | ||
| 1335 | } | ||
| 1336 | |||
| 1337 | if (f.cofb) { | ||
| 1338 | apply_permutation(arr->cp, arrc->cofb, 8); | ||
| 1339 | sum_arrays_mod(arr->cofb, arrc->cofb, 8, 3); | ||
| 1340 | } | ||
| 1341 | |||
| 1342 | if (f.cpos) | ||
| 1343 | apply_permutation(arr->cpos, arrc->cpos, 6); | ||
| 1344 | |||
| 1345 | ret = arrays_to_cube(arrc, f); | ||
| 1346 | free_cubearray(arrc, f); | ||
| 1347 | |||
| 1348 | return ret; | ||
| 1349 | } | ||
| 1350 | |||
| 1351 | static void | ||
| 1352 | movelist_to_position(Move *movelist, int *position) | ||
| 1353 | { | ||
| 1354 | Move m; | ||
| 1355 | |||
| 1356 | for (m = 0; m < NMOVES && movelist[m] != NULLMOVE; m++) | ||
| 1357 | position[movelist[m]] = m; | ||
| 1358 | } | ||
| 1359 | |||
| 1360 | static void | ||
| 1361 | moveset_to_list(Moveset ms, Estimator f, Move *r) | ||
| 1362 | { | ||
| 1363 | CubeTarget ct = { .target = 1 }; | ||
| 1364 | int b[NMOVES]; | ||
| 1365 | int na = 0, nb = 0; | ||
| 1366 | Move i; | ||
| 1367 | |||
| 1368 | if (ms == NULL) { | ||
| 1369 | fprintf(stderr, "Error: no moveset given\n"); | ||
| 1370 | return; | ||
| 1371 | } | ||
| 1372 | |||
| 1373 | for (i = U; i < NMOVES; i++) { | ||
| 1374 | if (ms(i)) { | ||
| 1375 | ct.cube = apply_move(i, (Cube){0}); | ||
| 1376 | if (f != NULL && f(ct)) | ||
| 1377 | r[na++] = i; | ||
| 1378 | else | ||
| 1379 | b[nb++] = i; | ||
| 1380 | } | ||
| 1381 | } | ||
| 1382 | |||
| 1383 | memcpy(r + na, b, nb * sizeof(Move)); | ||
| 1384 | r[na+nb] = NULLMOVE; | ||
| 1385 | } | ||
| 1386 | |||
| 1387 | static AlgList * | ||
| 1388 | new_alglist() | ||
| 1389 | { | ||
| 1390 | AlgList *ret = malloc(sizeof(AlgList)); | ||
| 1391 | |||
| 1392 | ret->len = 0; | ||
| 1393 | ret->first = NULL; | ||
| 1394 | ret->last = NULL; | ||
| 1395 | |||
| 1396 | return ret; | ||
| 1397 | } | ||
| 1398 | |||
| 1399 | static CubeArray * | ||
| 1400 | new_cubearray(Cube cube, PieceFilter f) | ||
| 1401 | { | ||
| 1402 | CubeArray *arr = malloc(sizeof(CubeArray)); | ||
| 1403 | |||
| 1404 | if (f.epose || f.eposs || f.eposm) | ||
| 1405 | arr->ep = malloc(12 * sizeof(int)); | ||
| 1406 | if (f.eofb) | ||
| 1407 | arr->eofb = malloc(12 * sizeof(int)); | ||
| 1408 | if (f.eorl) | ||
| 1409 | arr->eorl = malloc(12 * sizeof(int)); | ||
| 1410 | if (f.eoud) | ||
| 1411 | arr->eoud = malloc(12 * sizeof(int)); | ||
| 1412 | if (f.cp) | ||
| 1413 | arr->cp = malloc(8 * sizeof(int)); | ||
| 1414 | if (f.coud) | ||
| 1415 | arr->coud = malloc(8 * sizeof(int)); | ||
| 1416 | if (f.corl) | ||
| 1417 | arr->corl = malloc(8 * sizeof(int)); | ||
| 1418 | if (f.cofb) | ||
| 1419 | arr->cofb = malloc(8 * sizeof(int)); | ||
| 1420 | if (f.cpos) | ||
| 1421 | arr->cpos = malloc(6 * sizeof(int)); | ||
| 1422 | |||
| 1423 | cube_to_arrays(cube, arr, f); | ||
| 1424 | |||
| 1425 | return arr; | ||
| 1426 | } | ||
| 1427 | |||
| 1428 | static int | ||
| 1429 | perm_sign(int *a, int n) | ||
| 1430 | { | ||
| 1431 | int i, j, ret = 0; | ||
| 1432 | |||
| 1433 | if (!is_perm(a,n)) | ||
| 1434 | return -1; | ||
| 1435 | |||
| 1436 | for (i = 0; i < n; i++) | ||
| 1437 | for (j = i+1; j < n; j++) | ||
| 1438 | ret += (a[i] > a[j]) ? 1 : 0; | ||
| 1439 | |||
| 1440 | return ret % 2; | ||
| 1441 | } | ||
| 1442 | |||
| 1443 | static int | ||
| 1444 | perm_to_index(int *a, int n) | ||
| 1445 | { | ||
| 1446 | int i, j, c, ret = 0; | ||
| 1447 | |||
| 1448 | if (!is_perm(a, n)) | ||
| 1449 | return -1; | ||
| 1450 | |||
| 1451 | for (i = 0; i < n; i++) { | ||
| 1452 | c = 0; | ||
| 1453 | for (j = i+1; j < n; j++) | ||
| 1454 | c += (a[i] > a[j]) ? 1 : 0; | ||
| 1455 | ret += factorial(n-i-1) * c; | ||
| 1456 | } | ||
| 1457 | |||
| 1458 | return ret; | ||
| 1459 | } | ||
| 1460 | |||
| 1461 | static int | ||
| 1462 | powint(int a, int b) | ||
| 1463 | { | ||
| 1464 | if (b < 0) | ||
| 1465 | return 0; | ||
| 1466 | if (b == 0) | ||
| 1467 | return 1; | ||
| 1468 | |||
| 1469 | if (b % 2) | ||
| 1470 | return a * powint(a, b-1); | ||
| 1471 | else | ||
| 1472 | return powint(a*a, b/2); | ||
| 1473 | } | ||
| 1474 | |||
| 1475 | static void | ||
| 1476 | ptable_update(PruneData *pd, Cube cube, int n) | ||
| 1477 | { | ||
| 1478 | uint64_t ind = pd->coord->index(cube); | ||
| 1479 | uint8_t oldval2 = pd->ptable[ind/2]; | ||
| 1480 | int other = (ind % 2) ? oldval2 % 16 : oldval2 / 16; | ||
| 1481 | |||
| 1482 | pd->ptable[ind/2] = (ind % 2) ? 16*n + other : 16*other + n; | ||
| 1483 | pd->n++; | ||
| 1484 | } | ||
| 1485 | |||
| 1486 | static int | ||
| 1487 | ptableval_index(PruneData *pd, uint64_t ind) | ||
| 1488 | { | ||
| 1489 | return (ind % 2) ? pd->ptable[ind/2] / 16 : pd->ptable[ind/2] % 16; | ||
| 1490 | } | ||
| 1491 | |||
| 1492 | static void | ||
| 1493 | realloc_alg(Alg *alg, int n) | ||
| 1494 | { | ||
| 1495 | if (alg == NULL) { | ||
| 1496 | fprintf(stderr, "Error: trying to reallocate NULL alg.\n"); | ||
| 1497 | return; | ||
| 1498 | } | ||
| 1499 | |||
| 1500 | if (n < alg->len) { | ||
| 1501 | fprintf(stderr, "Error: alg too long for reallocation "); | ||
| 1502 | fprintf(stderr, "(%d vs %d)\n", alg->len, n); | ||
| 1503 | return; | ||
| 1504 | } | ||
| 1505 | |||
| 1506 | if (n > 1000000) { | ||
| 1507 | fprintf(stderr, "Warning: very long alg,"); | ||
| 1508 | fprintf(stderr, "something might go wrong.\n"); | ||
| 1509 | } | ||
| 1510 | |||
| 1511 | alg->move = realloc(alg->move, n * sizeof(int)); | ||
| 1512 | alg->inv = realloc(alg->inv, n * sizeof(int)); | ||
| 1513 | alg->allocated = n; | ||
| 1514 | } | ||
| 1515 | |||
| 1516 | static bool | ||
| 1517 | read_mtables_file() | ||
| 1518 | { | ||
| 1519 | FILE *f; | ||
| 1520 | char fname[strlen(tabledir)+20]; | ||
| 1521 | int m, b = sizeof(int); | ||
| 1522 | bool r = true; | ||
| 1523 | |||
| 1524 | strcpy(fname, tabledir); | ||
| 1525 | strcat(fname, "/mtables"); | ||
| 1526 | |||
| 1527 | if ((f = fopen(fname, "rb")) == NULL) | ||
| 1528 | return false; | ||
| 1529 | |||
| 1530 | for (m = 0; m < NMOVES; m++) { | ||
| 1531 | r = r && fread(epose_mtable[m], b, me[0], f) == me[0]; | ||
| 1532 | r = r && fread(eposs_mtable[m], b, me[1], f) == me[1]; | ||
| 1533 | r = r && fread(eposm_mtable[m], b, me[2], f) == me[2]; | ||
| 1534 | r = r && fread(eofb_mtable[m], b, me[3], f) == me[3]; | ||
| 1535 | r = r && fread(eorl_mtable[m], b, me[4], f) == me[4]; | ||
| 1536 | r = r && fread(eoud_mtable[m], b, me[5], f) == me[5]; | ||
| 1537 | r = r && fread(cp_mtable[m], b, me[6], f) == me[6]; | ||
| 1538 | r = r && fread(coud_mtable[m], b, me[7], f) == me[7]; | ||
| 1539 | r = r && fread(corl_mtable[m], b, me[8], f) == me[8]; | ||
| 1540 | r = r && fread(cofb_mtable[m], b, me[9], f) == me[9]; | ||
| 1541 | r = r && fread(cpos_mtable[m], b, me[10], f) == me[10]; | ||
| 1542 | } | ||
| 1543 | |||
| 1544 | fclose(f); | ||
| 1545 | return r; | ||
| 1546 | } | ||
| 1547 | |||
| 1548 | static bool | ||
| 1549 | read_ptable_file(PruneData *pd) | ||
| 1550 | { | ||
| 1551 | FILE *f; | ||
| 1552 | char fname[strlen(tabledir)+100]; | ||
| 1553 | uint64_t r; | ||
| 1554 | |||
| 1555 | strcpy(fname, tabledir); | ||
| 1556 | strcat(fname, "/"); | ||
| 1557 | strcat(fname, pd->filename); | ||
| 1558 | |||
| 1559 | if ((f = fopen(fname, "rb")) == NULL) | ||
| 1560 | return false; | ||
| 1561 | |||
| 1562 | r = fread(pd->ptable, sizeof(uint8_t), ptablesize(pd), f); | ||
| 1563 | fclose(f); | ||
| 1564 | |||
| 1565 | return r == ptablesize(pd); | ||
| 1566 | } | ||
| 1567 | |||
| 1568 | static bool | ||
| 1569 | read_symdata_file(SymData *sd) | ||
| 1570 | { | ||
| 1571 | FILE *f; | ||
| 1572 | char fname[strlen(tabledir)+100]; | ||
| 1573 | uint64_t n = sd->coord->max, *sn = &sd->sym_coord->max; | ||
| 1574 | bool r = true; | ||
| 1575 | |||
| 1576 | strcpy(fname, tabledir); | ||
| 1577 | strcat(fname, "/"); | ||
| 1578 | strcat(fname, sd->filename); | ||
| 1579 | |||
| 1580 | if ((f = fopen(fname, "rb")) == NULL) | ||
| 1581 | return false; | ||
| 1582 | |||
| 1583 | r = r && fread(&sd->sym_coord->max, sizeof(uint64_t), 1, f) == 1; | ||
| 1584 | r = r && fread(sd->rep, sizeof(Cube), *sn, f) == *sn; | ||
| 1585 | r = r && fread(sd->class, sizeof(uint64_t), n, f) == n; | ||
| 1586 | r = r && fread(sd->transtorep, sizeof(Trans), n, f) == n; | ||
| 1587 | |||
| 1588 | fclose(f); | ||
| 1589 | return r; | ||
| 1590 | } | ||
| 1591 | |||
| 1592 | static bool | ||
| 1593 | read_ttables_file() | ||
| 1594 | { | ||
| 1595 | FILE *f; | ||
| 1596 | char fname[strlen(tabledir)+20]; | ||
| 1597 | int b = sizeof(int); | ||
| 1598 | bool r = true; | ||
| 1599 | Move m; | ||
| 1600 | |||
| 1601 | strcpy(fname, tabledir); | ||
| 1602 | strcat(fname, "/"); | ||
| 1603 | strcat(fname, "ttables"); | ||
| 1604 | |||
| 1605 | if ((f = fopen(fname, "rb")) == NULL) | ||
| 1606 | return false; | ||
| 1607 | |||
| 1608 | for (m = 0; m < NTRANS; m++) { | ||
| 1609 | r = r && fread(epose_ttable[m], b, me[0], f) == me[0]; | ||
| 1610 | r = r && fread(eposs_ttable[m], b, me[1], f) == me[1]; | ||
| 1611 | r = r && fread(eposm_ttable[m], b, me[2], f) == me[2]; | ||
| 1612 | r = r && fread(eo_ttable[m], b, me[3], f) == me[3]; | ||
| 1613 | r = r && fread(cp_ttable[m], b, me[6], f) == me[6]; | ||
| 1614 | r = r && fread(co_ttable[m], b, me[7], f) == me[7]; | ||
| 1615 | r = r && fread(cpos_ttable[m], b, me[10], f) == me[10]; | ||
| 1616 | r = r && fread(moves_ttable[m], b, me[11], f) == me[11]; | ||
| 1617 | } | ||
| 1618 | |||
| 1619 | fclose(f); | ||
| 1620 | return r; | ||
| 1621 | } | ||
| 1622 | |||
| 1623 | static Cube | ||
| 1624 | rotate_via_compose(Trans r, Cube c, PieceFilter f) | ||
| 1625 | { | ||
| 1626 | static int zero12[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; | ||
| 1627 | static int zero8[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; | ||
| 1628 | static CubeArray ma = { | ||
| 1629 | .ep = ep_mirror, | ||
| 1630 | .eofb = zero12, | ||
| 1631 | .eorl = zero12, | ||
| 1632 | .eoud = zero12, | ||
| 1633 | .cp = cp_mirror, | ||
| 1634 | .coud = zero8, | ||
| 1635 | .corl = zero8, | ||
| 1636 | .cofb = zero8, | ||
| 1637 | .cpos = cpos_mirror | ||
| 1638 | }; | ||
| 1639 | |||
| 1640 | Alg *inv = inverse_alg(rotation_algs[r % NROTATIONS]); | ||
| 1641 | Cube ret = {0}; | ||
| 1642 | |||
| 1643 | if (r >= NROTATIONS) | ||
| 1644 | ret = move_via_arrays(&ma, ret, f); | ||
| 1645 | ret = apply_alg_generic(inv, ret, f, true); | ||
| 1646 | |||
| 1647 | ret = compose_filtered(c, ret, f); | ||
| 1648 | |||
| 1649 | ret = apply_alg_generic(rotation_algs[r % NROTATIONS], ret, f, true); | ||
| 1650 | if (r >= NROTATIONS) | ||
| 1651 | ret = move_via_arrays(&ma, ret, f); | ||
| 1652 | |||
| 1653 | free_alg(inv); | ||
| 1654 | return ret; | ||
| 1655 | } | ||
| 1656 | |||
| 1657 | static int | ||
| 1658 | subset_to_index(int *a, int n, int k) | ||
| 1659 | { | ||
| 1660 | int i, ret = 0; | ||
| 1661 | |||
| 1662 | if (!is_subset(a, n, k)) | ||
| 1663 | return binomial(n, k); | ||
| 1664 | |||
| 1665 | for (i = 0; i < n; i++) { | ||
| 1666 | if (k == n-i) | ||
| 1667 | return ret; | ||
| 1668 | if (a[i]) { | ||
| 1669 | ret += binomial(n-i-1, k); | ||
| 1670 | k--; | ||
| 1671 | } | ||
| 1672 | } | ||
| 1673 | |||
| 1674 | return ret; | ||
| 1675 | } | ||
| 1676 | |||
| 1677 | static void | ||
| 1678 | sum_arrays_mod(int *src, int *dst, int n, int m) | ||
| 1679 | { | ||
| 1680 | int i; | ||
| 1681 | |||
| 1682 | for (i = 0; i < n; i++) | ||
| 1683 | dst[i] = (m <= 0) ? 0 : (src[i] + dst[i]) % m; | ||
| 1684 | } | ||
| 1685 | |||
| 1686 | static void | ||
| 1687 | swap(int *a, int *b) | ||
| 1688 | { | ||
| 1689 | int aux; | ||
| 1690 | |||
| 1691 | aux = *a; | ||
| 1692 | *a = *b; | ||
| 1693 | *b = aux; | ||
| 1694 | } | ||
| 1695 | |||
| 1696 | static bool | ||
| 1697 | write_mtables_file() | ||
| 1698 | { | ||
| 1699 | FILE *f; | ||
| 1700 | char fname[strlen(tabledir)+20]; | ||
| 1701 | int m, b = sizeof(int); | ||
| 1702 | bool r = true; | ||
| 1703 | |||
| 1704 | strcpy(fname, tabledir); | ||
| 1705 | strcat(fname, "/mtables"); | ||
| 1706 | |||
| 1707 | if ((f = fopen(fname, "wb")) == NULL) | ||
| 1708 | return false; | ||
| 1709 | |||
| 1710 | for (m = 0; m < NMOVES; m++) { | ||
| 1711 | r = r && fwrite(epose_mtable[m], b, me[0], f) == me[0]; | ||
| 1712 | r = r && fwrite(eposs_mtable[m], b, me[1], f) == me[1]; | ||
| 1713 | r = r && fwrite(eposm_mtable[m], b, me[2], f) == me[2]; | ||
| 1714 | r = r && fwrite(eofb_mtable[m], b, me[3], f) == me[3]; | ||
| 1715 | r = r && fwrite(eorl_mtable[m], b, me[4], f) == me[4]; | ||
| 1716 | r = r && fwrite(eoud_mtable[m], b, me[5], f) == me[5]; | ||
| 1717 | r = r && fwrite(cp_mtable[m], b, me[6], f) == me[6]; | ||
| 1718 | r = r && fwrite(coud_mtable[m], b, me[7], f) == me[7]; | ||
| 1719 | r = r && fwrite(corl_mtable[m], b, me[8], f) == me[8]; | ||
| 1720 | r = r && fwrite(cofb_mtable[m], b, me[9], f) == me[9]; | ||
| 1721 | r = r && fwrite(cpos_mtable[m], b, me[10], f) == me[10]; | ||
| 1722 | } | ||
| 1723 | |||
| 1724 | fclose(f); | ||
| 1725 | return r; | ||
| 1726 | } | ||
| 1727 | |||
| 1728 | static bool | ||
| 1729 | write_ptable_file(PruneData *pd) | ||
| 1730 | { | ||
| 1731 | FILE *f; | ||
| 1732 | char fname[strlen(tabledir)+100]; | ||
| 1733 | uint64_t written; | ||
| 1734 | |||
| 1735 | strcpy(fname, tabledir); | ||
| 1736 | strcat(fname, "/"); | ||
| 1737 | strcat(fname, pd->filename); | ||
| 1738 | |||
| 1739 | if ((f = fopen(fname, "wb")) == NULL) | ||
| 1740 | return false; | ||
| 1741 | |||
| 1742 | written = fwrite(pd->ptable, sizeof(uint8_t), ptablesize(pd), f); | ||
| 1743 | fclose(f); | ||
| 1744 | |||
| 1745 | return written == ptablesize(pd); | ||
| 1746 | } | ||
| 1747 | |||
| 1748 | static bool | ||
| 1749 | write_symdata_file(SymData *sd) | ||
| 1750 | { | ||
| 1751 | FILE *f; | ||
| 1752 | char fname[strlen(tabledir)+100]; | ||
| 1753 | uint64_t n = sd->coord->max, *sn = &sd->sym_coord->max; | ||
| 1754 | bool r = true; | ||
| 1755 | |||
| 1756 | strcpy(fname, tabledir); | ||
| 1757 | strcat(fname, "/"); | ||
| 1758 | strcat(fname, sd->filename); | ||
| 1759 | |||
| 1760 | if ((f = fopen(fname, "wb")) == NULL) | ||
| 1761 | return false; | ||
| 1762 | |||
| 1763 | r = r && fwrite(&sd->sym_coord->max, sizeof(uint64_t), 1, f) == 1; | ||
| 1764 | r = r && fwrite(sd->rep, sizeof(Cube), *sn, f) == *sn; | ||
| 1765 | r = r && fwrite(sd->class, sizeof(uint64_t), n, f) == n; | ||
| 1766 | r = r && fwrite(sd->transtorep, sizeof(Trans), n, f) == n; | ||
| 1767 | |||
| 1768 | fclose(f); | ||
| 1769 | return r; | ||
| 1770 | } | ||
| 1771 | |||
| 1772 | static bool | ||
| 1773 | write_ttables_file() | ||
| 1774 | { | ||
| 1775 | FILE *f; | ||
| 1776 | char fname[strlen(tabledir)+20]; | ||
| 1777 | bool r = true; | ||
| 1778 | int b = sizeof(int); | ||
| 1779 | Move m; | ||
| 1780 | |||
| 1781 | strcpy(fname, tabledir); | ||
| 1782 | strcat(fname, "/ttables"); | ||
| 1783 | |||
| 1784 | if ((f = fopen(fname, "wb")) == NULL) | ||
| 1785 | return false; | ||
| 1786 | |||
| 1787 | for (m = 0; m < NTRANS; m++) { | ||
| 1788 | r = r && fwrite(epose_ttable[m], b, me[0], f) == me[0]; | ||
| 1789 | r = r && fwrite(eposs_ttable[m], b, me[1], f) == me[1]; | ||
| 1790 | r = r && fwrite(eposm_ttable[m], b, me[2], f) == me[2]; | ||
| 1791 | r = r && fwrite(eo_ttable[m], b, me[3], f) == me[3]; | ||
| 1792 | r = r && fwrite(cp_ttable[m], b, me[6], f) == me[6]; | ||
| 1793 | r = r && fwrite(co_ttable[m], b, me[7], f) == me[7]; | ||
| 1794 | r = r && fwrite(cpos_ttable[m], b, me[10], f) == me[10]; | ||
| 1795 | r = r && fwrite(moves_ttable[m], b, me[11], f) == me[11]; | ||
| 1796 | } | ||
| 1797 | |||
| 1798 | fclose(f); | ||
| 1799 | return r; | ||
| 1800 | } | ||
| 1801 | |||
| 1802 | /* Init functions implementation *********************************************/ | ||
| 1803 | |||
| 1804 | static void | ||
| 1805 | init_auxtables() | ||
| 1806 | { | ||
| 1807 | Cube c1, c2; | ||
| 1808 | CubeArray *arr; | ||
| 1809 | uint64_t ui, uj; | ||
| 1810 | int i, j, k, auxarr[12]; | ||
| 1811 | bool cij, p1, p2; | ||
| 1812 | |||
| 1813 | for (ui = 0; ui < POW2TO11*BINOM12ON4; ui++) { | ||
| 1814 | k = (ui / POW2TO11) * 24; | ||
| 1815 | c1 = admissible_ep((Cube){ .epose = k }, pf_e); | ||
| 1816 | c1.eofb = ui % POW2TO11; | ||
| 1817 | c1 = admissible_eos_from_eofbepos(c1); | ||
| 1818 | admissible_ee_aux[ui] = c1; | ||
| 1819 | } | ||
| 1820 | |||
| 1821 | for (ui = 0; ui < FACTORIAL6; ui++) { | ||
| 1822 | arr = new_cubearray((Cube){.cpos = ui}, pf_cpos); | ||
| 1823 | for (i = 0; i < 6; i++) { | ||
| 1824 | what_center_at_aux[ui][i] = arr->cpos[i]; | ||
| 1825 | where_is_center_aux[ui][arr->cpos[i]] = i; | ||
| 1826 | } | ||
| 1827 | free_cubearray(arr, pf_cpos); | ||
| 1828 | } | ||
| 1829 | |||
| 1830 | for (ui = 0; ui < FACTORIAL8; ui++) { | ||
| 1831 | arr = new_cubearray((Cube){.cp = ui}, pf_cp); | ||
| 1832 | for (i = 0; i < 8; i++) { | ||
| 1833 | what_corner_at_aux[ui][i] = arr->cp[i]; | ||
| 1834 | where_is_corner_aux[ui][arr->cp[i]] = i; | ||
| 1835 | } | ||
| 1836 | free_cubearray(arr, pf_cp); | ||
| 1837 | } | ||
| 1838 | |||
| 1839 | for (ui = 0; ui < FACTORIAL12/FACTORIAL8; ui++) { | ||
| 1840 | arr = new_cubearray((Cube){.epose = ui}, pf_e); | ||
| 1841 | for (i = 0; i < 12; i++) | ||
| 1842 | if (edge_slice(arr->ep[i]) == 0) | ||
| 1843 | where_is_edge_aux[0][ui][arr->ep[i]] = i; | ||
| 1844 | free_cubearray(arr, pf_e); | ||
| 1845 | |||
| 1846 | arr = new_cubearray((Cube){.eposs = ui}, pf_s); | ||
| 1847 | for (i = 0; i < 12; i++) | ||
| 1848 | if (edge_slice(arr->ep[i]) == 1) | ||
| 1849 | where_is_edge_aux[1][ui][arr->ep[i]] = i; | ||
| 1850 | free_cubearray(arr, pf_s); | ||
| 1851 | |||
| 1852 | arr = new_cubearray((Cube){.eposm = ui}, pf_m); | ||
| 1853 | for (i = 0; i < 12; i++) | ||
| 1854 | if (edge_slice(arr->ep[i]) == 2) | ||
| 1855 | where_is_edge_aux[2][ui][arr->ep[i]] = i; | ||
| 1856 | free_cubearray(arr, pf_m); | ||
| 1857 | } | ||
| 1858 | |||
| 1859 | for (ui = 0; ui < POW3TO7; ui++) { | ||
| 1860 | int_to_sum_zero_array(ui, 3, 8, auxarr); | ||
| 1861 | what_orientation_last_corner_aux[ui] = auxarr[7]; | ||
| 1862 | } | ||
| 1863 | |||
| 1864 | for (ui = 0; ui < POW2TO11; ui++) { | ||
| 1865 | int_to_sum_zero_array(ui, 2, 12, auxarr); | ||
| 1866 | what_orientation_last_edge_aux[ui] = auxarr[11]; | ||
| 1867 | } | ||
| 1868 | |||
| 1869 | for (ui = 0; ui < BINOM12ON4; ui++) | ||
| 1870 | for (uj = 0; uj < BINOM12ON4; uj++) | ||
| 1871 | epos_dependent_aux[ui][uj]=epos_dependent_pos(ui, uj); | ||
| 1872 | |||
| 1873 | for (i = 0; i < NMOVES; i++) { | ||
| 1874 | for (j = 0; j < NMOVES; j++) { | ||
| 1875 | c1 = apply_move(i, apply_move(j, (Cube){0})); | ||
| 1876 | c2 = apply_move(j, apply_move(i, (Cube){0})); | ||
| 1877 | commute[i][j] = equal(c1, c2) && i && j; | ||
| 1878 | } | ||
| 1879 | } | ||
| 1880 | |||
| 1881 | for (i = 0; i < NMOVES; i++) { | ||
| 1882 | for (j = 0; j < NMOVES; j++) { | ||
| 1883 | for (k = 0; k < NMOVES; k++) { | ||
| 1884 | p1 = j && base_move(j) == base_move(k); | ||
| 1885 | p2 = i && base_move(i) == base_move(k); | ||
| 1886 | cij = commute[i][j]; | ||
| 1887 | possible_next[i][j][k] = !(p1 || (cij && p2)); | ||
| 1888 | } | ||
| 1889 | } | ||
| 1890 | } | ||
| 1891 | |||
| 1892 | for (i = 0; i < NMOVES; i++) | ||
| 1893 | inverse_move_aux[i] = i ? i + 2 - 2*((i-1)%3) : NULLMOVE; | ||
| 1894 | |||
| 1895 | /* Is there a more elegant way? */ | ||
| 1896 | inverse_trans_aux[uf] = uf; | ||
| 1897 | inverse_trans_aux[ur] = ul; | ||
| 1898 | inverse_trans_aux[ul] = ur; | ||
| 1899 | inverse_trans_aux[ub] = ub; | ||
| 1900 | |||
| 1901 | inverse_trans_aux[df] = df; | ||
| 1902 | inverse_trans_aux[dr] = dr; | ||
| 1903 | inverse_trans_aux[dl] = dl; | ||
| 1904 | inverse_trans_aux[db] = db; | ||
| 1905 | |||
| 1906 | inverse_trans_aux[rf] = lf; | ||
| 1907 | inverse_trans_aux[rd] = bl; | ||
| 1908 | inverse_trans_aux[rb] = rb; | ||
| 1909 | inverse_trans_aux[ru] = fr; | ||
| 1910 | |||
| 1911 | inverse_trans_aux[lf] = rf; | ||
| 1912 | inverse_trans_aux[ld] = br; | ||
| 1913 | inverse_trans_aux[lb] = lb; | ||
| 1914 | inverse_trans_aux[lu] = fl; | ||
| 1915 | |||
| 1916 | inverse_trans_aux[fu] = fu; | ||
| 1917 | inverse_trans_aux[fr] = ru; | ||
| 1918 | inverse_trans_aux[fd] = bu; | ||
| 1919 | inverse_trans_aux[fl] = lu; | ||
| 1920 | |||
| 1921 | inverse_trans_aux[bu] = fd; | ||
| 1922 | inverse_trans_aux[br] = ld; | ||
| 1923 | inverse_trans_aux[bd] = bd; | ||
| 1924 | inverse_trans_aux[bl] = rd; | ||
| 1925 | |||
| 1926 | inverse_trans_aux[uf_mirror] = uf_mirror; | ||
| 1927 | inverse_trans_aux[ur_mirror] = ur_mirror; | ||
| 1928 | inverse_trans_aux[ul_mirror] = ul_mirror; | ||
| 1929 | inverse_trans_aux[ub_mirror] = ub_mirror; | ||
| 1930 | |||
| 1931 | inverse_trans_aux[df_mirror] = df_mirror; | ||
| 1932 | inverse_trans_aux[dr_mirror] = dl_mirror; | ||
| 1933 | inverse_trans_aux[dl_mirror] = dr_mirror; | ||
| 1934 | inverse_trans_aux[db_mirror] = db_mirror; | ||
| 1935 | |||
| 1936 | inverse_trans_aux[rf_mirror] = rf_mirror; | ||
| 1937 | inverse_trans_aux[rd_mirror] = br_mirror; | ||
| 1938 | inverse_trans_aux[rb_mirror] = lb_mirror; | ||
| 1939 | inverse_trans_aux[ru_mirror] = fl_mirror; | ||
| 1940 | |||
| 1941 | inverse_trans_aux[lf_mirror] = lf_mirror; | ||
| 1942 | inverse_trans_aux[ld_mirror] = bl_mirror; | ||
| 1943 | inverse_trans_aux[lb_mirror] = rb_mirror; | ||
| 1944 | inverse_trans_aux[lu_mirror] = fr_mirror; | ||
| 1945 | |||
| 1946 | inverse_trans_aux[fu_mirror] = fu_mirror; | ||
| 1947 | inverse_trans_aux[fr_mirror] = lu_mirror; | ||
| 1948 | inverse_trans_aux[fd_mirror] = bu_mirror; | ||
| 1949 | inverse_trans_aux[fl_mirror] = ru_mirror; | ||
| 1950 | |||
| 1951 | inverse_trans_aux[bu_mirror] = fd_mirror; | ||
| 1952 | inverse_trans_aux[br_mirror] = rd_mirror; | ||
| 1953 | inverse_trans_aux[bd_mirror] = bd_mirror; | ||
| 1954 | inverse_trans_aux[bl_mirror] = ld_mirror; | ||
| 1955 | } | ||
| 1956 | |||
| 1957 | /* | ||
| 1958 | * There is certainly a bette way to do this, but for now I just use | ||
| 1959 | * a "graph coloring" algorithm to compute the left cosets, and I compose | ||
| 1960 | * with every possible cp to get the right cosets (it is possible that I am | ||
| 1961 | * mixing up left and right). | ||
| 1962 | * | ||
| 1963 | * For doing it better "Mathematically", we need 3 things: | ||
| 1964 | * - Checking that cp separates the orbits (UFR,UBL,DFL,DBR) and the other | ||
| 1965 | * This is easy and it is done in the commented function cphtr_cp(). | ||
| 1966 | * - Check that there is no ep/cp parity | ||
| 1967 | * - Check that we are not in the "3c" case; this is the part I don't | ||
| 1968 | * know how to do. | ||
| 1969 | */ | ||
| 1970 | static void | ||
| 1971 | init_cphtr_cosets() | ||
| 1972 | { | ||
| 1973 | unsigned int i; | ||
| 1974 | int c = 0, d = 0; | ||
| 1975 | |||
| 1976 | for (i = 0; i < FACTORIAL8; i++) { | ||
| 1977 | cphtr_left_cosets[i] = -1; | ||
| 1978 | cphtr_right_cosets[i] = -1; | ||
| 1979 | } | ||
| 1980 | |||
| 1981 | /* First we compute left cosets with a bfs */ | ||
| 1982 | for (i = 0; i < FACTORIAL8; i++) | ||
| 1983 | if (cphtr_left_cosets[i] == -1) | ||
| 1984 | init_cphtr_left_cosets_bfs(i, c++); | ||
| 1985 | |||
| 1986 | /* Then we compute right cosets using compose() */ | ||
| 1987 | for (i = 0; i < FACTORIAL8; i++) | ||
| 1988 | if (cphtr_right_cosets[i] == -1) | ||
| 1989 | init_cphtr_right_cosets_color(i, d++); | ||
| 1990 | } | ||
| 1991 | |||
| 1992 | static void | ||
| 1993 | init_cphtr_left_cosets_bfs(int i, int c) | ||
| 1994 | { | ||
| 1995 | int j, jj, k, next[FACTORIAL8], next2[FACTORIAL8], n, n2; | ||
| 1996 | Move moves[6] = {U2, D2, R2, L2, F2, B2}; | ||
| 1997 | |||
| 1998 | n = 1; | ||
| 1999 | next[0] = i; | ||
| 2000 | cphtr_left_cosets[i] = c; | ||
| 2001 | |||
| 2002 | while (n != 0) { | ||
| 2003 | for (j = 0, n2 = 0; j < n; j++) { | ||
| 2004 | for (k = 0; k < 6; k++) { | ||
| 2005 | jj = cp_mtable[moves[k]][next[j]]; | ||
| 2006 | if (cphtr_left_cosets[jj] == -1) { | ||
| 2007 | cphtr_left_cosets[jj] = c; | ||
| 2008 | next2[n2++] = jj; | ||
| 2009 | } | ||
| 2010 | } | ||
| 2011 | } | ||
| 2012 | |||
| 2013 | for (j = 0; j < n2; j++) | ||
| 2014 | next[j] = next2[j]; | ||
| 2015 | n = n2; | ||
| 2016 | } | ||
| 2017 | } | ||
| 2018 | |||
| 2019 | static void | ||
| 2020 | init_cphtr_right_cosets_color(int i, int d) | ||
| 2021 | { | ||
| 2022 | int cp; | ||
| 2023 | unsigned int j; | ||
| 2024 | |||
| 2025 | cphtr_right_rep[d] = i; | ||
| 2026 | for (j = 0; j < FACTORIAL8; j++) { | ||
| 2027 | if (cphtr_left_cosets[j] == 0) { | ||
| 2028 | /* TODO: use antindexer, it's nicer */ | ||
| 2029 | cp = compose((Cube){.cp = i}, (Cube){.cp = j}).cp; | ||
| 2030 | cphtr_right_cosets[cp] = d; | ||
| 2031 | } | ||
| 2032 | } | ||
| 2033 | } | ||
| 2034 | |||
| 2035 | static void | ||
| 2036 | init_environment() | ||
| 2037 | { | ||
| 2038 | char *nissydata = getenv("NISSYDATA"); | ||
| 2039 | char *localdata = getenv("XDG_DATA_HOME"); | ||
| 2040 | char *home = getenv("HOME"); | ||
| 2041 | bool read, write; | ||
| 2042 | |||
| 2043 | if (nissydata != NULL) { | ||
| 2044 | tabledir = malloc(strlen(nissydata) * sizeof(char) + 20); | ||
| 2045 | strcpy(tabledir, nissydata); | ||
| 2046 | } else if (localdata != NULL) { | ||
| 2047 | tabledir = malloc(strlen(localdata) * sizeof(char) + 20); | ||
| 2048 | strcpy(tabledir, localdata); | ||
| 2049 | strcat(tabledir, "/nissy"); | ||
| 2050 | } else if (home != NULL) { | ||
| 2051 | tabledir = malloc(strlen(home) * sizeof(char) + 20); | ||
| 2052 | strcpy(tabledir, home); | ||
| 2053 | strcat(tabledir, "/.nissy"); | ||
| 2054 | } | ||
| 2055 | |||
| 2056 | mkdir(tabledir, 0777); | ||
| 2057 | strcat(tabledir, "/tables"); | ||
| 2058 | mkdir(tabledir, 0777); | ||
| 2059 | |||
| 2060 | read = !access(tabledir, R_OK); | ||
| 2061 | write = !access(tabledir, W_OK); | ||
| 2062 | |||
| 2063 | if (!read) { | ||
| 2064 | fprintf(stderr, "Table files cannot be read.\n"); | ||
| 2065 | } else if (!write) { | ||
| 2066 | fprintf(stderr, "Data directory not writable: "); | ||
| 2067 | fprintf(stderr, "tables can be loaded, but not saved.\n"); | ||
| 2068 | } | ||
| 2069 | } | ||
| 2070 | |||
| 2071 | static void | ||
| 2072 | init_moves() { | ||
| 2073 | Cube c; | ||
| 2074 | CubeArray arrs; | ||
| 2075 | int i; | ||
| 2076 | unsigned int ui; | ||
| 2077 | Move m; | ||
| 2078 | |||
| 2079 | /* Generate all move cycles and flips; I do this regardless */ | ||
| 2080 | for (i = 0; i < NMOVES; i++) { | ||
| 2081 | if (i == U || i == x || i == y) | ||
| 2082 | continue; | ||
| 2083 | |||
| 2084 | c = apply_alg_generic(equiv_alg[i], (Cube){0}, pf_all, false); | ||
| 2085 | |||
| 2086 | arrs = (CubeArray) { | ||
| 2087 | edge_cycle[i], | ||
| 2088 | eofb_flipped[i], | ||
| 2089 | eorl_flipped[i], | ||
| 2090 | eoud_flipped[i], | ||
| 2091 | corner_cycle[i], | ||
| 2092 | coud_flipped[i], | ||
| 2093 | corl_flipped[i], | ||
| 2094 | cofb_flipped[i], | ||
| 2095 | center_cycle[i] | ||
| 2096 | }; | ||
| 2097 | cube_to_arrays(c, &arrs, pf_all); | ||
| 2098 | } | ||
| 2099 | |||
| 2100 | if (read_mtables_file()) | ||
| 2101 | return; | ||
| 2102 | |||
| 2103 | fprintf(stderr, "Cannot load %s, generating it\n", "mtables"); | ||
| 2104 | |||
| 2105 | /* Initialize transition tables */ | ||
| 2106 | for (m = 0; m < NMOVES; m++) { | ||
| 2107 | for (ui = 0; ui < FACTORIAL12/FACTORIAL8; ui++) { | ||
| 2108 | c = (Cube){ .epose = ui }; | ||
| 2109 | c = apply_move_cubearray(m, c, pf_e); | ||
| 2110 | epose_mtable[m][ui] = c.epose; | ||
| 2111 | |||
| 2112 | c = (Cube){ .eposs = ui }; | ||
| 2113 | c = apply_move_cubearray(m, c, pf_s); | ||
| 2114 | eposs_mtable[m][ui] = c.eposs; | ||
| 2115 | |||
| 2116 | c = (Cube){ .eposm = ui }; | ||
| 2117 | c = apply_move_cubearray(m, c, pf_m); | ||
| 2118 | eposm_mtable[m][ui] = c.eposm; | ||
| 2119 | } | ||
| 2120 | for (ui = 0; ui < POW2TO11; ui++ ) { | ||
| 2121 | c = (Cube){ .eofb = ui }; | ||
| 2122 | c = apply_move_cubearray(m, c, pf_eo); | ||
| 2123 | eofb_mtable[m][ui] = c.eofb; | ||
| 2124 | |||
| 2125 | c = (Cube){ .eorl = ui }; | ||
| 2126 | c = apply_move_cubearray(m, c, pf_eo); | ||
| 2127 | eorl_mtable[m][ui] = c.eorl; | ||
| 2128 | |||
| 2129 | c = (Cube){ .eoud = ui }; | ||
| 2130 | c = apply_move_cubearray(m, c, pf_eo); | ||
| 2131 | eoud_mtable[m][ui] = c.eoud; | ||
| 2132 | } | ||
| 2133 | for (ui = 0; ui < POW3TO7; ui++) { | ||
| 2134 | c = (Cube){ .coud = ui }; | ||
| 2135 | c = apply_move_cubearray(m, c, pf_co); | ||
| 2136 | coud_mtable[m][ui] = c.coud; | ||
| 2137 | |||
| 2138 | c = (Cube){ .corl = ui }; | ||
| 2139 | c = apply_move_cubearray(m, c, pf_co); | ||
| 2140 | corl_mtable[m][ui] = c.corl; | ||
| 2141 | |||
| 2142 | c = (Cube){ .cofb = ui }; | ||
| 2143 | c = apply_move_cubearray(m, c, pf_co); | ||
| 2144 | cofb_mtable[m][ui] = c.cofb; | ||
| 2145 | } | ||
| 2146 | for (ui = 0; ui < FACTORIAL8; ui++) { | ||
| 2147 | c = (Cube){ .cp = ui }; | ||
| 2148 | c = apply_move_cubearray(m, c, pf_cp); | ||
| 2149 | cp_mtable[m][ui] = c.cp; | ||
| 2150 | } | ||
| 2151 | for (ui = 0; ui < FACTORIAL6; ui++) { | ||
| 2152 | c = (Cube){ .cpos = ui }; | ||
| 2153 | c = apply_move_cubearray(m, c, pf_cpos); | ||
| 2154 | cpos_mtable[m][ui] = c.cpos; | ||
| 2155 | } | ||
| 2156 | } | ||
| 2157 | |||
| 2158 | if (!write_mtables_file()) | ||
| 2159 | fprintf(stderr, "Error writing mtables\n"); | ||
| 2160 | } | ||
| 2161 | |||
| 2162 | static void | ||
| 2163 | init_moves_aux() | ||
| 2164 | { | ||
| 2165 | /* Some standard PieceFilters */ | ||
| 2166 | pf_all.epose = true; | ||
| 2167 | pf_all.eposs = true; | ||
| 2168 | pf_all.eposm = true; | ||
| 2169 | pf_all.eofb = true; | ||
| 2170 | pf_all.eorl = true; | ||
| 2171 | pf_all.eoud = true; | ||
| 2172 | pf_all.cp = true; | ||
| 2173 | pf_all.cofb = true; | ||
| 2174 | pf_all.corl = true; | ||
| 2175 | pf_all.coud = true; | ||
| 2176 | pf_all.cpos = true; | ||
| 2177 | |||
| 2178 | pf_4val.epose = true; | ||
| 2179 | pf_4val.eposs = true; | ||
| 2180 | pf_4val.eposm = true; | ||
| 2181 | pf_4val.eofb = true; | ||
| 2182 | pf_4val.coud = true; | ||
| 2183 | pf_4val.cp = true; | ||
| 2184 | |||
| 2185 | pf_epcp.epose = true; | ||
| 2186 | pf_epcp.eposs = true; | ||
| 2187 | pf_epcp.eposm = true; | ||
| 2188 | pf_epcp.cp = true; | ||
| 2189 | |||
| 2190 | pf_cpos.cpos = true; | ||
| 2191 | |||
| 2192 | pf_cp.cp = true; | ||
| 2193 | |||
| 2194 | pf_ep.epose = true; | ||
| 2195 | pf_ep.eposs = true; | ||
| 2196 | pf_ep.eposm = true; | ||
| 2197 | |||
| 2198 | pf_e.epose = true; | ||
| 2199 | pf_s.eposs = true; | ||
| 2200 | pf_m.eposm = true; | ||
| 2201 | |||
| 2202 | pf_eo.eofb = true; | ||
| 2203 | pf_eo.eorl = true; | ||
| 2204 | pf_eo.eoud = true; | ||
| 2205 | |||
| 2206 | pf_co.cofb = true; | ||
| 2207 | pf_co.corl = true; | ||
| 2208 | pf_co.coud = true; | ||
| 2209 | |||
| 2210 | /* Used to convert to and from CubeArray */ | ||
| 2211 | epe_solved[0] = FR; | ||
| 2212 | epe_solved[1] = FL; | ||
| 2213 | epe_solved[2] = BL; | ||
| 2214 | epe_solved[3] = BR; | ||
| 2215 | |||
| 2216 | eps_solved[0] = UL; | ||
| 2217 | eps_solved[1] = UR; | ||
| 2218 | eps_solved[2] = DL; | ||
| 2219 | eps_solved[3] = DR; | ||
| 2220 | |||
| 2221 | epm_solved[0] = UF; | ||
| 2222 | epm_solved[1] = UB; | ||
| 2223 | epm_solved[2] = DF; | ||
| 2224 | epm_solved[3] = DB; | ||
| 2225 | |||
| 2226 | /* Table sizes, used for reading and writing files */ | ||
| 2227 | me[0] = FACTORIAL12/FACTORIAL8; | ||
| 2228 | me[1] = FACTORIAL12/FACTORIAL8; | ||
| 2229 | me[2] = FACTORIAL12/FACTORIAL8; | ||
| 2230 | me[3] = POW2TO11; | ||
| 2231 | me[4] = POW2TO11; | ||
| 2232 | me[5] = POW2TO11; | ||
| 2233 | me[6] = FACTORIAL8; | ||
| 2234 | me[7] = POW3TO7; | ||
| 2235 | me[8] = POW3TO7; | ||
| 2236 | me[9] = POW3TO7; | ||
| 2237 | me[10] = FACTORIAL6; | ||
| 2238 | me[11] = NMOVES; | ||
| 2239 | |||
| 2240 | /* Cycles *********************/ | ||
| 2241 | edge_cycle[U][UF] = UR; | ||
| 2242 | edge_cycle[U][UL] = UF; | ||
| 2243 | edge_cycle[U][UB] = UL; | ||
| 2244 | edge_cycle[U][UR] = UB; | ||
| 2245 | edge_cycle[U][DF] = DF; | ||
| 2246 | edge_cycle[U][DL] = DL; | ||
| 2247 | edge_cycle[U][DB] = DB; | ||
| 2248 | edge_cycle[U][DR] = DR; | ||
| 2249 | edge_cycle[U][FR] = FR; | ||
| 2250 | edge_cycle[U][FL] = FL; | ||
| 2251 | edge_cycle[U][BL] = BL; | ||
| 2252 | edge_cycle[U][BR] = BR; | ||
| 2253 | |||
| 2254 | edge_cycle[x][UF] = DF; | ||
| 2255 | edge_cycle[x][UL] = FL; | ||
| 2256 | edge_cycle[x][UB] = UF; | ||
| 2257 | edge_cycle[x][UR] = FR; | ||
| 2258 | edge_cycle[x][DF] = DB; | ||
| 2259 | edge_cycle[x][DL] = BL; | ||
| 2260 | edge_cycle[x][DB] = UB; | ||
| 2261 | edge_cycle[x][DR] = BR; | ||
| 2262 | edge_cycle[x][FR] = DR; | ||
| 2263 | edge_cycle[x][FL] = DL; | ||
| 2264 | edge_cycle[x][BL] = UL; | ||
| 2265 | edge_cycle[x][BR] = UR; | ||
| 2266 | |||
| 2267 | edge_cycle[y][UF] = UR; | ||
| 2268 | edge_cycle[y][UL] = UF; | ||
| 2269 | edge_cycle[y][UB] = UL; | ||
| 2270 | edge_cycle[y][UR] = UB; | ||
| 2271 | edge_cycle[y][DF] = DR; | ||
| 2272 | edge_cycle[y][DL] = DF; | ||
| 2273 | edge_cycle[y][DB] = DL; | ||
| 2274 | edge_cycle[y][DR] = DB; | ||
| 2275 | edge_cycle[y][FR] = BR; | ||
| 2276 | edge_cycle[y][FL] = FR; | ||
| 2277 | edge_cycle[y][BL] = FL; | ||
| 2278 | edge_cycle[y][BR] = BL; | ||
| 2279 | |||
| 2280 | corner_cycle[U][UFR] = UBR; | ||
| 2281 | corner_cycle[U][UFL] = UFR; | ||
| 2282 | corner_cycle[U][UBL] = UFL; | ||
| 2283 | corner_cycle[U][UBR] = UBL; | ||
| 2284 | corner_cycle[U][DFR] = DFR; | ||
| 2285 | corner_cycle[U][DFL] = DFL; | ||
| 2286 | corner_cycle[U][DBL] = DBL; | ||
| 2287 | corner_cycle[U][DBR] = DBR; | ||
| 2288 | |||
| 2289 | corner_cycle[x][UFR] = DFR; | ||
| 2290 | corner_cycle[x][UFL] = DFL; | ||
| 2291 | corner_cycle[x][UBL] = UFL; | ||
| 2292 | corner_cycle[x][UBR] = UFR; | ||
| 2293 | corner_cycle[x][DFR] = DBR; | ||
| 2294 | corner_cycle[x][DFL] = DBL; | ||
| 2295 | corner_cycle[x][DBL] = UBL; | ||
| 2296 | corner_cycle[x][DBR] = UBR; | ||
| 2297 | |||
| 2298 | corner_cycle[y][UFR] = UBR; | ||
| 2299 | corner_cycle[y][UFL] = UFR; | ||
| 2300 | corner_cycle[y][UBL] = UFL; | ||
| 2301 | corner_cycle[y][UBR] = UBL; | ||
| 2302 | corner_cycle[y][DFR] = DBR; | ||
| 2303 | corner_cycle[y][DFL] = DFR; | ||
| 2304 | corner_cycle[y][DBL] = DFL; | ||
| 2305 | corner_cycle[y][DBR] = DBL; | ||
| 2306 | |||
| 2307 | center_cycle[U][U_center] = U_center; | ||
| 2308 | center_cycle[U][D_center] = D_center; | ||
| 2309 | center_cycle[U][R_center] = R_center; | ||
| 2310 | center_cycle[U][L_center] = L_center; | ||
| 2311 | center_cycle[U][F_center] = F_center; | ||
| 2312 | center_cycle[U][B_center] = B_center; | ||
| 2313 | |||
| 2314 | center_cycle[x][U_center] = F_center; | ||
| 2315 | center_cycle[x][D_center] = B_center; | ||
| 2316 | center_cycle[x][R_center] = R_center; | ||
| 2317 | center_cycle[x][L_center] = L_center; | ||
| 2318 | center_cycle[x][F_center] = D_center; | ||
| 2319 | center_cycle[x][B_center] = U_center; | ||
| 2320 | |||
| 2321 | center_cycle[y][U_center] = U_center; | ||
| 2322 | center_cycle[y][D_center] = D_center; | ||
| 2323 | center_cycle[y][R_center] = B_center; | ||
| 2324 | center_cycle[y][L_center] = F_center; | ||
| 2325 | center_cycle[y][F_center] = R_center; | ||
| 2326 | center_cycle[y][B_center] = L_center; | ||
| 2327 | |||
| 2328 | /* Flipped pieces *************/ | ||
| 2329 | eofb_flipped[x][UF] = 1; | ||
| 2330 | eofb_flipped[x][UB] = 1; | ||
| 2331 | eofb_flipped[x][DF] = 1; | ||
| 2332 | eofb_flipped[x][DB] = 1; | ||
| 2333 | |||
| 2334 | eofb_flipped[y][FR] = 1; | ||
| 2335 | eofb_flipped[y][FL] = 1; | ||
| 2336 | eofb_flipped[y][BL] = 1; | ||
| 2337 | eofb_flipped[y][BR] = 1; | ||
| 2338 | |||
| 2339 | eorl_flipped[x][UF] = 1; | ||
| 2340 | eorl_flipped[x][UL] = 1; | ||
| 2341 | eorl_flipped[x][UB] = 1; | ||
| 2342 | eorl_flipped[x][UR] = 1; | ||
| 2343 | eorl_flipped[x][DF] = 1; | ||
| 2344 | eorl_flipped[x][DL] = 1; | ||
| 2345 | eorl_flipped[x][DB] = 1; | ||
| 2346 | eorl_flipped[x][DR] = 1; | ||
| 2347 | eorl_flipped[x][FR] = 1; | ||
| 2348 | eorl_flipped[x][FL] = 1; | ||
| 2349 | eorl_flipped[x][BL] = 1; | ||
| 2350 | eorl_flipped[x][BR] = 1; | ||
| 2351 | |||
| 2352 | eorl_flipped[y][FR] = 1; | ||
| 2353 | eorl_flipped[y][FL] = 1; | ||
| 2354 | eorl_flipped[y][BL] = 1; | ||
| 2355 | eorl_flipped[y][BR] = 1; | ||
| 2356 | |||
| 2357 | eoud_flipped[U][UF] = 1; | ||
| 2358 | eoud_flipped[U][UL] = 1; | ||
| 2359 | eoud_flipped[U][UB] = 1; | ||
| 2360 | eoud_flipped[U][UR] = 1; | ||
| 2361 | |||
| 2362 | eoud_flipped[x][UF] = 1; | ||
| 2363 | eoud_flipped[x][UB] = 1; | ||
| 2364 | eoud_flipped[x][DF] = 1; | ||
| 2365 | eoud_flipped[x][DB] = 1; | ||
| 2366 | |||
| 2367 | eoud_flipped[y][UF] = 1; | ||
| 2368 | eoud_flipped[y][UL] = 1; | ||
| 2369 | eoud_flipped[y][UB] = 1; | ||
| 2370 | eoud_flipped[y][UR] = 1; | ||
| 2371 | eoud_flipped[y][DF] = 1; | ||
| 2372 | eoud_flipped[y][DL] = 1; | ||
| 2373 | eoud_flipped[y][DB] = 1; | ||
| 2374 | eoud_flipped[y][DR] = 1; | ||
| 2375 | eoud_flipped[y][FR] = 1; | ||
| 2376 | eoud_flipped[y][FL] = 1; | ||
| 2377 | eoud_flipped[y][BL] = 1; | ||
| 2378 | eoud_flipped[y][BR] = 1; | ||
| 2379 | |||
| 2380 | coud_flipped[x][UFR] = 2; | ||
| 2381 | coud_flipped[x][UFL] = 1; | ||
| 2382 | coud_flipped[x][UBR] = 1; | ||
| 2383 | coud_flipped[x][UBL] = 2; | ||
| 2384 | coud_flipped[x][DFR] = 1; | ||
| 2385 | coud_flipped[x][DFL] = 2; | ||
| 2386 | coud_flipped[x][DBR] = 2; | ||
| 2387 | coud_flipped[x][DBL] = 1; | ||
| 2388 | |||
| 2389 | corl_flipped[U][UFR] = 1; | ||
| 2390 | corl_flipped[U][UFL] = 2; | ||
| 2391 | corl_flipped[U][UBL] = 1; | ||
| 2392 | corl_flipped[U][UBR] = 2; | ||
| 2393 | |||
| 2394 | corl_flipped[y][UFR] = 1; | ||
| 2395 | corl_flipped[y][UFL] = 2; | ||
| 2396 | corl_flipped[y][UBL] = 1; | ||
| 2397 | corl_flipped[y][UBR] = 2; | ||
| 2398 | corl_flipped[y][DFR] = 2; | ||
| 2399 | corl_flipped[y][DFL] = 1; | ||
| 2400 | corl_flipped[y][DBL] = 2; | ||
| 2401 | corl_flipped[y][DBR] = 1; | ||
| 2402 | |||
| 2403 | cofb_flipped[U][UFR] = 2; | ||
| 2404 | cofb_flipped[U][UFL] = 1; | ||
| 2405 | cofb_flipped[U][UBL] = 2; | ||
| 2406 | cofb_flipped[U][UBR] = 1; | ||
| 2407 | |||
| 2408 | cofb_flipped[x][UFR] = 1; | ||
| 2409 | cofb_flipped[x][UFL] = 2; | ||
| 2410 | cofb_flipped[x][UBL] = 1; | ||
| 2411 | cofb_flipped[x][UBR] = 2; | ||
| 2412 | cofb_flipped[x][DFR] = 2; | ||
| 2413 | cofb_flipped[x][DFL] = 1; | ||
| 2414 | cofb_flipped[x][DBL] = 2; | ||
| 2415 | cofb_flipped[x][DBR] = 1; | ||
| 2416 | |||
| 2417 | cofb_flipped[y][UFR] = 2; | ||
| 2418 | cofb_flipped[y][UFL] = 1; | ||
| 2419 | cofb_flipped[y][UBL] = 2; | ||
| 2420 | cofb_flipped[y][UBR] = 1; | ||
| 2421 | cofb_flipped[y][DFR] = 1; | ||
| 2422 | cofb_flipped[y][DFL] = 2; | ||
| 2423 | cofb_flipped[y][DBL] = 1; | ||
| 2424 | cofb_flipped[y][DBR] = 2; | ||
| 2425 | |||
| 2426 | /* Equivalent moves ***********/ | ||
| 2427 | equiv_alg[NULLMOVE] = new_alg(""); | ||
| 2428 | |||
| 2429 | equiv_alg[U] = new_alg(" U "); | ||
| 2430 | equiv_alg[U2] = new_alg(" UU "); | ||
| 2431 | equiv_alg[U3] = new_alg(" UUU "); | ||
| 2432 | equiv_alg[D] = new_alg(" xx U xx "); | ||
| 2433 | equiv_alg[D2] = new_alg(" xx UU xx "); | ||
| 2434 | equiv_alg[D3] = new_alg(" xx UUU xx "); | ||
| 2435 | equiv_alg[R] = new_alg(" yx U xxxyyy "); | ||
| 2436 | equiv_alg[R2] = new_alg(" yx UU xxxyyy "); | ||
| 2437 | equiv_alg[R3] = new_alg(" yx UUU xxxyyy "); | ||
| 2438 | equiv_alg[L] = new_alg(" yyyx U xxxy "); | ||
| 2439 | equiv_alg[L2] = new_alg(" yyyx UU xxxy "); | ||
| 2440 | equiv_alg[L3] = new_alg(" yyyx UUU xxxy "); | ||
| 2441 | equiv_alg[F] = new_alg(" x U xxx "); | ||
| 2442 | equiv_alg[F2] = new_alg(" x UU xxx "); | ||
| 2443 | equiv_alg[F3] = new_alg(" x UUU xxx "); | ||
| 2444 | equiv_alg[B] = new_alg(" xxx U x "); | ||
| 2445 | equiv_alg[B2] = new_alg(" xxx UU x "); | ||
| 2446 | equiv_alg[B3] = new_alg(" xxx UUU x "); | ||
| 2447 | |||
| 2448 | equiv_alg[Uw] = new_alg(" xx U xx y "); | ||
| 2449 | equiv_alg[Uw2] = new_alg(" xx UU xx yy "); | ||
| 2450 | equiv_alg[Uw3] = new_alg(" xx UUU xx yyy "); | ||
| 2451 | equiv_alg[Dw] = new_alg(" U yyy "); | ||
| 2452 | equiv_alg[Dw2] = new_alg(" UU yy "); | ||
| 2453 | equiv_alg[Dw3] = new_alg(" UUU y "); | ||
| 2454 | equiv_alg[Rw] = new_alg(" yyyx U xxxy x "); | ||
| 2455 | equiv_alg[Rw2] = new_alg(" yyyx UU xxxy xx "); | ||
| 2456 | equiv_alg[Rw3] = new_alg(" yyyx UUU xxxy xxx "); | ||
| 2457 | equiv_alg[Lw] = new_alg(" yx U xxxyyy xxx "); | ||
| 2458 | equiv_alg[Lw2] = new_alg(" yx UU xxxyyy xx "); | ||
| 2459 | equiv_alg[Lw3] = new_alg(" yx UUU xxxyyy x "); | ||
| 2460 | equiv_alg[Fw] = new_alg(" xxx U x yxxxyyy "); | ||
| 2461 | equiv_alg[Fw2] = new_alg(" xxx UU x yxxyyy "); | ||
| 2462 | equiv_alg[Fw3] = new_alg(" xxx UUU x yxyyy "); | ||
| 2463 | equiv_alg[Bw] = new_alg(" x U xxx yxyyy "); | ||
| 2464 | equiv_alg[Bw2] = new_alg(" x UU xxx yxxyyy "); | ||
| 2465 | equiv_alg[Bw3] = new_alg(" x UUU xxx yxxxyyy "); | ||
| 2466 | |||
| 2467 | equiv_alg[M] = new_alg(" yx U xx UUU yxyyy "); | ||
| 2468 | equiv_alg[M2] = new_alg(" yx UU xx UU xxxy "); | ||
| 2469 | equiv_alg[M3] = new_alg(" yx UUU xx U yxxxy "); | ||
| 2470 | equiv_alg[S] = new_alg(" x UUU xx U yyyx "); | ||
| 2471 | equiv_alg[S2] = new_alg(" x UU xx UU yyx "); | ||
| 2472 | equiv_alg[S3] = new_alg(" x U xx UUU yx "); | ||
| 2473 | equiv_alg[E] = new_alg(" U xx UUU xxyyy "); | ||
| 2474 | equiv_alg[E2] = new_alg(" UU xx UU xxyy "); | ||
| 2475 | equiv_alg[E3] = new_alg(" UUU xx U xxy "); | ||
| 2476 | |||
| 2477 | equiv_alg[x] = new_alg(" x "); | ||
| 2478 | equiv_alg[x2] = new_alg(" xx "); | ||
| 2479 | equiv_alg[x3] = new_alg(" xxx "); | ||
| 2480 | equiv_alg[y] = new_alg(" y "); | ||
| 2481 | equiv_alg[y2] = new_alg(" yy "); | ||
| 2482 | equiv_alg[y3] = new_alg(" yyy "); | ||
| 2483 | equiv_alg[z] = new_alg(" yyy x y "); | ||
| 2484 | equiv_alg[z2] = new_alg(" yy xx "); | ||
| 2485 | equiv_alg[z3] = new_alg(" y x yyy "); | ||
| 2486 | } | ||
| 2487 | |||
| 2488 | static void | ||
| 2489 | init_strings() | ||
| 2490 | { | ||
| 2491 | strcpy(move_string [NULLMOVE], "-" ); | ||
| 2492 | strcpy(move_string [U], "U" ); | ||
| 2493 | strcpy(move_string [U2], "U2" ); | ||
| 2494 | strcpy(move_string [U3], "U\'" ); | ||
| 2495 | strcpy(move_string [D], "D" ); | ||
| 2496 | strcpy(move_string [D2], "D2" ); | ||
| 2497 | strcpy(move_string [D3], "D\'" ); | ||
| 2498 | strcpy(move_string [R], "R" ); | ||
| 2499 | strcpy(move_string [R2], "R2" ); | ||
| 2500 | strcpy(move_string [R3], "R\'" ); | ||
| 2501 | strcpy(move_string [L], "L" ); | ||
| 2502 | strcpy(move_string [L2], "L2" ); | ||
| 2503 | strcpy(move_string [L3], "L\'" ); | ||
| 2504 | strcpy(move_string [F], "F" ); | ||
| 2505 | strcpy(move_string [F2], "F2" ); | ||
| 2506 | strcpy(move_string [F3], "F\'" ); | ||
| 2507 | strcpy(move_string [B], "B" ); | ||
| 2508 | strcpy(move_string [B2], "B2" ); | ||
| 2509 | strcpy(move_string [B3], "B\'" ); | ||
| 2510 | strcpy(move_string [Uw], "Uw" ); | ||
| 2511 | strcpy(move_string [Uw2], "Uw2" ); | ||
| 2512 | strcpy(move_string [Uw3], "Uw\'" ); | ||
| 2513 | strcpy(move_string [Dw], "Dw" ); | ||
| 2514 | strcpy(move_string [Dw2], "Dw2" ); | ||
| 2515 | strcpy(move_string [Dw3], "Dw\'" ); | ||
| 2516 | strcpy(move_string [Rw], "Rw" ); | ||
| 2517 | strcpy(move_string [Rw2], "Rw2" ); | ||
| 2518 | strcpy(move_string [Rw3], "Rw\'" ); | ||
| 2519 | strcpy(move_string [Lw], "Lw" ); | ||
| 2520 | strcpy(move_string [Lw2], "Lw2" ); | ||
| 2521 | strcpy(move_string [Lw3], "Lw\'" ); | ||
| 2522 | strcpy(move_string [Fw], "Fw" ); | ||
| 2523 | strcpy(move_string [Fw2], "Fw2" ); | ||
| 2524 | strcpy(move_string [Fw3], "Fw\'" ); | ||
| 2525 | strcpy(move_string [Bw], "Bw" ); | ||
| 2526 | strcpy(move_string [Bw2], "Bw2" ); | ||
| 2527 | strcpy(move_string [Bw3], "Bw\'" ); | ||
| 2528 | strcpy(move_string [M], "M" ); | ||
| 2529 | strcpy(move_string [M2], "M2" ); | ||
| 2530 | strcpy(move_string [M3], "M\'" ); | ||
| 2531 | strcpy(move_string [S], "S" ); | ||
| 2532 | strcpy(move_string [S2], "S2" ); | ||
| 2533 | strcpy(move_string [S3], "S\'" ); | ||
| 2534 | strcpy(move_string [E], "E" ); | ||
| 2535 | strcpy(move_string [E2], "E2" ); | ||
| 2536 | strcpy(move_string [E3], "E\'" ); | ||
| 2537 | strcpy(move_string [x], "x" ); | ||
| 2538 | strcpy(move_string [x2], "x2" ); | ||
| 2539 | strcpy(move_string [x3], "x\'" ); | ||
| 2540 | strcpy(move_string [y], "y" ); | ||
| 2541 | strcpy(move_string [y2], "y2" ); | ||
| 2542 | strcpy(move_string [y3], "y\'" ); | ||
| 2543 | strcpy(move_string [z], "z" ); | ||
| 2544 | strcpy(move_string [z2], "z2" ); | ||
| 2545 | strcpy(move_string [z3], "z\'" ); | ||
| 2546 | |||
| 2547 | strcpy(edge_string [UF], "UF" ); | ||
| 2548 | strcpy(edge_string [UL], "UL" ); | ||
| 2549 | strcpy(edge_string [UB], "UB" ); | ||
| 2550 | strcpy(edge_string [UR], "UR" ); | ||
| 2551 | strcpy(edge_string [DF], "DF" ); | ||
| 2552 | strcpy(edge_string [DL], "DL" ); | ||
| 2553 | strcpy(edge_string [DB], "DB" ); | ||
| 2554 | strcpy(edge_string [DR], "DR" ); | ||
| 2555 | strcpy(edge_string [FR], "FR" ); | ||
| 2556 | strcpy(edge_string [FL], "FL" ); | ||
| 2557 | strcpy(edge_string [BL], "BL" ); | ||
| 2558 | strcpy(edge_string [BR], "BR" ); | ||
| 2559 | |||
| 2560 | strcpy(corner_string [UFR], "UFR" ); | ||
| 2561 | strcpy(corner_string [UFL], "UFL" ); | ||
| 2562 | strcpy(corner_string [UBL], "UBL" ); | ||
| 2563 | strcpy(corner_string [UBR], "UBR" ); | ||
| 2564 | strcpy(corner_string [DFR], "DFR" ); | ||
| 2565 | strcpy(corner_string [DFL], "DFL" ); | ||
| 2566 | strcpy(corner_string [DBL], "DBL" ); | ||
| 2567 | strcpy(corner_string [DBR], "DBR" ); | ||
| 2568 | |||
| 2569 | strcpy(center_string [U_center], "U" ); | ||
| 2570 | strcpy(center_string [D_center], "D" ); | ||
| 2571 | strcpy(center_string [R_center], "R" ); | ||
| 2572 | strcpy(center_string [L_center], "L" ); | ||
| 2573 | strcpy(center_string [F_center], "F" ); | ||
| 2574 | strcpy(center_string [B_center], "B" ); | ||
| 2575 | } | ||
| 2576 | |||
| 2577 | static void | ||
| 2578 | init_symdata() | ||
| 2579 | { | ||
| 2580 | int i; | ||
| 2581 | |||
| 2582 | for (i = 0; i < n_all_symdata; i++) | ||
| 2583 | gensym(all_sd[i]); | ||
| 2584 | } | ||
| 2585 | |||
| 2586 | static void | ||
| 2587 | init_trans() { | ||
| 2588 | Cube aux, cube, mirr, c[3]; | ||
| 2589 | CubeArray epcp; | ||
| 2590 | int i, eparr[12], eoarr[12], cparr[8], coarr[8]; | ||
| 2591 | unsigned int ui; | ||
| 2592 | Move mi, move; | ||
| 2593 | Trans m; | ||
| 2594 | |||
| 2595 | /* Compute sources */ | ||
| 2596 | for (i = 0; i < NTRANS; i++) { | ||
| 2597 | cube = apply_alg(rotation_algs[i % NROTATIONS], (Cube){0}); | ||
| 2598 | |||
| 2599 | epose_source[i] = edge_slice(what_edge_at(cube, FR)); | ||
| 2600 | eposs_source[i] = edge_slice(what_edge_at(cube, UR)); | ||
| 2601 | eposm_source[i] = edge_slice(what_edge_at(cube, UF)); | ||
| 2602 | eofb_source[i] = what_center_at(cube, F_center)/2; | ||
| 2603 | eorl_source[i] = what_center_at(cube, R_center)/2; | ||
| 2604 | eoud_source[i] = what_center_at(cube, U_center)/2; | ||
| 2605 | coud_source[i] = what_center_at(cube, U_center)/2; | ||
| 2606 | cofb_source[i] = what_center_at(cube, F_center)/2; | ||
| 2607 | corl_source[i] = what_center_at(cube, R_center)/2; | ||
| 2608 | } | ||
| 2609 | |||
| 2610 | if (read_ttables_file()) | ||
| 2611 | return; | ||
| 2612 | |||
| 2613 | fprintf(stderr, "Cannot load %s, generating it\n", "ttables"); | ||
| 2614 | |||
| 2615 | /* Initialize tables */ | ||
| 2616 | for (m = 0; m < NTRANS; m++) { | ||
| 2617 | epcp = (CubeArray){ .ep = eparr, .cp = cparr }; | ||
| 2618 | cube = apply_alg(rotation_algs[m % NROTATIONS], (Cube){0}); | ||
| 2619 | cube_to_arrays(cube, &epcp, pf_epcp); | ||
| 2620 | if (m >= NROTATIONS) { | ||
| 2621 | apply_permutation(ep_mirror, eparr, 12); | ||
| 2622 | apply_permutation(cp_mirror, cparr, 8); | ||
| 2623 | } | ||
| 2624 | |||
| 2625 | for (ui = 0; ui < FACTORIAL12/FACTORIAL8; ui++) { | ||
| 2626 | c[0] = admissible_ep((Cube){ .epose = ui }, pf_e); | ||
| 2627 | c[1] = admissible_ep((Cube){ .eposs = ui }, pf_s); | ||
| 2628 | c[2] = admissible_ep((Cube){ .eposm = ui }, pf_m); | ||
| 2629 | |||
| 2630 | cube = rotate_via_compose(m,c[epose_source[m]],pf_ep); | ||
| 2631 | epose_ttable[m][ui] = cube.epose; | ||
| 2632 | |||
| 2633 | cube = rotate_via_compose(m,c[eposs_source[m]],pf_ep); | ||
| 2634 | eposs_ttable[m][ui] = cube.eposs; | ||
| 2635 | |||
| 2636 | cube = rotate_via_compose(m,c[eposm_source[m]],pf_ep); | ||
| 2637 | eposm_ttable[m][ui] = cube.eposm; | ||
| 2638 | } | ||
| 2639 | for (ui = 0; ui < POW2TO11; ui++ ) { | ||
| 2640 | int_to_sum_zero_array(ui, 2, 12, eoarr); | ||
| 2641 | apply_permutation(eparr, eoarr, 12); | ||
| 2642 | eo_ttable[m][ui] = digit_array_to_int(eoarr, 11, 2); | ||
| 2643 | } | ||
| 2644 | for (ui = 0; ui < POW3TO7; ui++) { | ||
| 2645 | int_to_sum_zero_array(ui, 3, 8, coarr); | ||
| 2646 | apply_permutation(cparr, coarr, 8); | ||
| 2647 | co_ttable[m][ui] = digit_array_to_int(coarr, 7, 3); | ||
| 2648 | if (m >= NROTATIONS) | ||
| 2649 | co_ttable[m][ui] = | ||
| 2650 | invert_digits(co_ttable[m][ui], 3, 7); | ||
| 2651 | } | ||
| 2652 | for (ui = 0; ui < FACTORIAL8; ui++) { | ||
| 2653 | cube = (Cube){ .cp = ui }; | ||
| 2654 | cube = rotate_via_compose(m, cube, pf_cp); | ||
| 2655 | cp_ttable[m][ui] = cube.cp; | ||
| 2656 | } | ||
| 2657 | for (ui = 0; ui < FACTORIAL6; ui++) { | ||
| 2658 | cube = (Cube){ .cpos = ui }; | ||
| 2659 | cube = rotate_via_compose(m, cube, pf_cpos); | ||
| 2660 | cpos_ttable[m][ui] = cube.cpos; | ||
| 2661 | } | ||
| 2662 | for (mi = 0; mi < NMOVES; mi++) { | ||
| 2663 | aux = apply_trans(m, apply_move(mi, (Cube){0})); | ||
| 2664 | for (move = 0; move < NMOVES; move++) { | ||
| 2665 | cube = apply_move(inverse_move_aux[move], aux); | ||
| 2666 | mirr = apply_trans(uf_mirror, cube); | ||
| 2667 | if (is_solved(cube, false) || | ||
| 2668 | is_solved(mirr, false)) | ||
| 2669 | moves_ttable[m][mi] = move; | ||
| 2670 | } | ||
| 2671 | } | ||
| 2672 | } | ||
| 2673 | |||
| 2674 | if (!write_ttables_file()) | ||
| 2675 | fprintf(stderr, "Error writing ttables\n"); | ||
| 2676 | } | ||
| 2677 | |||
| 2678 | static void | ||
| 2679 | init_trans_aux() | ||
| 2680 | { | ||
| 2681 | ep_mirror[UF] = UF; | ||
| 2682 | ep_mirror[UL] = UR; | ||
| 2683 | ep_mirror[UB] = UB; | ||
| 2684 | ep_mirror[UR] = UL; | ||
| 2685 | ep_mirror[DF] = DF; | ||
| 2686 | ep_mirror[DL] = DR; | ||
| 2687 | ep_mirror[DB] = DB; | ||
| 2688 | ep_mirror[DR] = DL; | ||
| 2689 | ep_mirror[FR] = FL; | ||
| 2690 | ep_mirror[FL] = FR; | ||
| 2691 | ep_mirror[BR] = BL; | ||
| 2692 | ep_mirror[BL] = BR; | ||
| 2693 | |||
| 2694 | cp_mirror[UFR] = UFL; | ||
| 2695 | cp_mirror[UFL] = UFR; | ||
| 2696 | cp_mirror[UBL] = UBR; | ||
| 2697 | cp_mirror[UBR] = UBL; | ||
| 2698 | cp_mirror[DFR] = DFL; | ||
| 2699 | cp_mirror[DFL] = DFR; | ||
| 2700 | cp_mirror[DBL] = DBR; | ||
| 2701 | cp_mirror[DBR] = DBL; | ||
| 2702 | |||
| 2703 | cpos_mirror[U_center] = U_center; | ||
| 2704 | cpos_mirror[D_center] = D_center; | ||
| 2705 | cpos_mirror[R_center] = L_center; | ||
| 2706 | cpos_mirror[L_center] = R_center; | ||
| 2707 | cpos_mirror[F_center] = F_center; | ||
| 2708 | cpos_mirror[B_center] = B_center; | ||
| 2709 | |||
| 2710 | /* Is there a more elegant way? */ | ||
| 2711 | rotation_algs[uf] = new_alg(""); | ||
| 2712 | rotation_algs[ur] = new_alg("y"); | ||
| 2713 | rotation_algs[ub] = new_alg("y2"); | ||
| 2714 | rotation_algs[ul] = new_alg("y3"); | ||
| 2715 | |||
| 2716 | rotation_algs[df] = new_alg("z2"); | ||
| 2717 | rotation_algs[dr] = new_alg("y z2"); | ||
| 2718 | rotation_algs[db] = new_alg("x2"); | ||
| 2719 | rotation_algs[dl] = new_alg("y3 z2"); | ||
| 2720 | |||
| 2721 | rotation_algs[rf] = new_alg("z3"); | ||
| 2722 | rotation_algs[rd] = new_alg("z3 y"); | ||
| 2723 | rotation_algs[rb] = new_alg("z3 y2"); | ||
| 2724 | rotation_algs[ru] = new_alg("z3 y3"); | ||
| 2725 | |||
| 2726 | rotation_algs[lf] = new_alg("z"); | ||
| 2727 | rotation_algs[ld] = new_alg("z y3"); | ||
| 2728 | rotation_algs[lb] = new_alg("z y2"); | ||
| 2729 | rotation_algs[lu] = new_alg("z y"); | ||
| 2730 | |||
| 2731 | rotation_algs[fu] = new_alg("x y2"); | ||
| 2732 | rotation_algs[fr] = new_alg("x y"); | ||
| 2733 | rotation_algs[fd] = new_alg("x"); | ||
| 2734 | rotation_algs[fl] = new_alg("x y3"); | ||
| 2735 | |||
| 2736 | rotation_algs[bu] = new_alg("x3"); | ||
| 2737 | rotation_algs[br] = new_alg("x3 y"); | ||
| 2738 | rotation_algs[bd] = new_alg("x3 y2"); | ||
| 2739 | rotation_algs[bl] = new_alg("x3 y3"); | ||
| 2740 | } | ||
| 2741 | |||
| 2742 | |||
| 2743 | /* Public functions implementation *******************************************/ | ||
| 2744 | |||
| 2745 | Cube | ||
| 2746 | apply_alg(Alg *alg, Cube cube) | ||
| 2747 | { | ||
| 2748 | return apply_alg_generic(alg, cube, pf_all, true); | ||
| 2749 | } | ||
| 2750 | |||
| 2751 | Cube | ||
| 2752 | apply_move(Move m, Cube cube) | ||
| 2753 | { | ||
| 2754 | return (Cube) { | ||
| 2755 | .epose = epose_mtable[m][cube.epose], | ||
| 2756 | .eposs = eposs_mtable[m][cube.eposs], | ||
| 2757 | .eposm = eposm_mtable[m][cube.eposm], | ||
| 2758 | .eofb = eofb_mtable[m][cube.eofb], | ||
| 2759 | .eorl = eorl_mtable[m][cube.eorl], | ||
| 2760 | .eoud = eoud_mtable[m][cube.eoud], | ||
| 2761 | .coud = coud_mtable[m][cube.coud], | ||
| 2762 | .cofb = cofb_mtable[m][cube.cofb], | ||
| 2763 | .corl = corl_mtable[m][cube.corl], | ||
| 2764 | .cp = cp_mtable[m][cube.cp], | ||
| 2765 | .cpos = cpos_mtable[m][cube.cpos] | ||
| 2766 | }; | ||
| 2767 | } | ||
| 2768 | |||
| 2769 | |||
| 2770 | Cube | ||
| 2771 | apply_trans(Trans t, Cube cube) | ||
| 2772 | { | ||
| 2773 | int aux_epos[3] = { cube.epose, cube.eposs, cube.eposm }; | ||
| 2774 | int aux_eo[3] = { cube.eoud, cube.eorl, cube.eofb }; | ||
| 2775 | int aux_co[3] = { cube.coud, cube.corl, cube.cofb }; | ||
| 2776 | |||
| 2777 | return (Cube) { | ||
| 2778 | .epose = epose_ttable[t][aux_epos[epose_source[t]]], | ||
| 2779 | .eposs = eposs_ttable[t][aux_epos[eposs_source[t]]], | ||
| 2780 | .eposm = eposm_ttable[t][aux_epos[eposm_source[t]]], | ||
| 2781 | .eofb = eo_ttable[t][aux_eo[eofb_source[t]]], | ||
| 2782 | .eorl = eo_ttable[t][aux_eo[eorl_source[t]]], | ||
| 2783 | .eoud = eo_ttable[t][aux_eo[eoud_source[t]]], | ||
| 2784 | .coud = co_ttable[t][aux_co[coud_source[t]]], | ||
| 2785 | .corl = co_ttable[t][aux_co[corl_source[t]]], | ||
| 2786 | .cofb = co_ttable[t][aux_co[cofb_source[t]]], | ||
| 2787 | .cp = cp_ttable[t][cube.cp], | ||
| 2788 | .cpos = cpos_ttable[t][cube.cpos] | ||
| 2789 | }; | ||
| 2790 | } | ||
| 2791 | |||
| 2792 | Move | ||
| 2793 | base_move(Move m) | ||
| 2794 | { | ||
| 2795 | if (m == NULLMOVE) | ||
| 2796 | return NULLMOVE; | ||
| 2797 | else | ||
| 2798 | return m - (m-1)%3; | ||
| 2799 | } | ||
| 2800 | |||
| 2801 | Cube | ||
| 2802 | compose(Cube c2, Cube c1) | ||
| 2803 | { | ||
| 2804 | return compose_filtered(c2, c1, pf_all); | ||
| 2805 | } | ||
| 2806 | |||
| 2807 | /*TODO maybe move the next two */ | ||
| 2808 | uint64_t | ||
| 2809 | cphtr(Cube cube) | ||
| 2810 | { | ||
| 2811 | return cphtr_right_cosets[cube.cp]; | ||
| 2812 | } | ||
| 2813 | |||
| 2814 | Cube | ||
| 2815 | anti_cphtr(uint64_t ind) | ||
| 2816 | { | ||
| 2817 | return (Cube) { .cp = cphtr_right_rep[ind] }; | ||
| 2818 | } | ||
| 2819 | |||
| 2820 | uint64_t | ||
| 2821 | epos_dependent(Cube c) | ||
| 2822 | { | ||
| 2823 | return epos_dependent_aux[c.eposs/FACTORIAL4][c.epose/FACTORIAL4]; | ||
| 2824 | } | ||
| 2825 | |||
| 2826 | bool | ||
| 2827 | equal(Cube c1, Cube c2) | ||
| 2828 | { | ||
| 2829 | return c1.eofb == c2.eofb && | ||
| 2830 | c1.epose == c2.epose && | ||
| 2831 | c1.eposs == c2.eposs && | ||
| 2832 | c1.eposm == c2.eposm && | ||
| 2833 | c1.coud == c2.coud && | ||
| 2834 | c1.cp == c2.cp && | ||
| 2835 | c1.cpos == c2.cpos; | ||
| 2836 | } | ||
| 2837 | |||
| 2838 | void | ||
| 2839 | genptable(PruneData *pd) | ||
| 2840 | { | ||
| 2841 | Move ms[NMOVES]; | ||
| 2842 | int d; | ||
| 2843 | uint64_t j, oldn = 0; | ||
| 2844 | |||
| 2845 | if (pd->generated) | ||
| 2846 | return; | ||
| 2847 | |||
| 2848 | /* TODO: check if memory is enough, otherwise maybe crash gracefully? */ | ||
| 2849 | pd->ptable = malloc(ptablesize(pd) * sizeof(uint8_t)); | ||
| 2850 | |||
| 2851 | if (read_ptable_file(pd)) { | ||
| 2852 | pd->generated = true; | ||
| 2853 | return; | ||
| 2854 | } | ||
| 2855 | |||
| 2856 | fprintf(stderr, "Cannot load %s, generating it\n", pd->filename); | ||
| 2857 | |||
| 2858 | moveset_to_list(pd->moveset, NULL, ms); | ||
| 2859 | |||
| 2860 | /* We use 4 bits per value, so any distance >= 15 is set to 15 */ | ||
| 2861 | for (j = 0; j < pd->coord->max; j++) | ||
| 2862 | ptable_update(pd, pd->coord->cube(j), 15); | ||
| 2863 | |||
| 2864 | /*TODO: change, set to 0 for every solved state (might be more than 1)*/ | ||
| 2865 | ptable_update(pd, (Cube){0}, 0); | ||
| 2866 | pd->n = 1; | ||
| 2867 | |||
| 2868 | for (d = 0; d < 15 && pd->n < pd->coord->max; d++) { | ||
| 2869 | genptable_bfs(pd, d, ms); | ||
| 2870 | fprintf(stderr, "Depth %d done, generated %lu\t(%lu/%lu)\n", | ||
| 2871 | d, pd->n - oldn, pd->n, pd->coord->max); | ||
| 2872 | oldn = pd->n; | ||
| 2873 | } | ||
| 2874 | |||
| 2875 | if (!write_ptable_file(pd)) | ||
| 2876 | fprintf(stderr, "Error writing ptable file\n"); | ||
| 2877 | |||
| 2878 | pd->generated = true; | ||
| 2879 | } | ||
| 2880 | |||
| 2881 | Cube | ||
| 2882 | inverse_cube(Cube cube) | ||
| 2883 | { | ||
| 2884 | CubeArray *arr = new_cubearray(cube, pf_all); | ||
| 2885 | CubeArray *inv = new_cubearray((Cube){0}, pf_all); | ||
| 2886 | Cube ret; | ||
| 2887 | int i; | ||
| 2888 | |||
| 2889 | for (i = 0; i < 12; i++) { | ||
| 2890 | inv->ep[arr->ep[i]] = i; | ||
| 2891 | inv->eofb[arr->ep[i]] = arr->eofb[i]; | ||
| 2892 | inv->eorl[arr->ep[i]] = arr->eorl[i]; | ||
| 2893 | inv->eoud[arr->ep[i]] = arr->eoud[i]; | ||
| 2894 | } | ||
| 2895 | |||
| 2896 | for (i = 0; i < 8; i++) { | ||
| 2897 | inv->cp[arr->cp[i]] = i; | ||
| 2898 | inv->coud[arr->cp[i]] = (3 - arr->coud[i]) % 3; | ||
| 2899 | inv->corl[arr->cp[i]] = (3 - arr->corl[i]) % 3; | ||
| 2900 | inv->cofb[arr->cp[i]] = (3 - arr->cofb[i]) % 3; | ||
| 2901 | } | ||
| 2902 | |||
| 2903 | for (int i = 0; i < 6; i++) | ||
| 2904 | inv->cpos[arr->cpos[i]] = i; | ||
| 2905 | |||
| 2906 | ret = arrays_to_cube(inv, pf_all); | ||
| 2907 | free_cubearray(arr, pf_all); | ||
| 2908 | free_cubearray(inv, pf_all); | ||
| 2909 | |||
| 2910 | return ret; | ||
| 2911 | } | ||
| 2912 | |||
| 2913 | Move | ||
| 2914 | inverse_move(Move m) | ||
| 2915 | { | ||
| 2916 | return inverse_move_aux[m]; | ||
| 2917 | } | ||
| 2918 | |||
| 2919 | Trans | ||
| 2920 | inverse_trans(Trans t) | ||
| 2921 | { | ||
| 2922 | return inverse_trans_aux[t]; | ||
| 2923 | } | ||
| 2924 | |||
| 2925 | bool | ||
| 2926 | is_admissible(Cube cube) | ||
| 2927 | { | ||
| 2928 | /* TODO: this should check consistency of different orientations */ | ||
| 2929 | /* TODO: check that centers are opposite and admissible */ | ||
| 2930 | |||
| 2931 | CubeArray *a = new_cubearray(cube, pf_all); | ||
| 2932 | int parity; | ||
| 2933 | bool perm; | ||
| 2934 | |||
| 2935 | perm = is_perm(a->ep, 12) && | ||
| 2936 | is_perm(a->cp, 8) && | ||
| 2937 | is_perm(a->cpos, 6); | ||
| 2938 | parity = perm_sign(a->ep, 12) + | ||
| 2939 | perm_sign(a->cp, 8) + | ||
| 2940 | perm_sign(a->cpos, 6); | ||
| 2941 | |||
| 2942 | return perm && parity % 2 == 0; | ||
| 2943 | } | ||
| 2944 | |||
| 2945 | bool | ||
| 2946 | is_solved(Cube cube, bool reorient) | ||
| 2947 | { | ||
| 2948 | int i; | ||
| 2949 | |||
| 2950 | if (reorient) { | ||
| 2951 | for (i = 0; i < NROTATIONS; i++) | ||
| 2952 | if (is_solved(apply_alg(rotation_algs[i], cube),false)) | ||
| 2953 | return true; | ||
| 2954 | return false; | ||
| 2955 | } else { | ||
| 2956 | return equal(cube, (Cube){0}); | ||
| 2957 | } | ||
| 2958 | } | ||
| 2959 | |||
| 2960 | bool | ||
| 2961 | is_solved_block(Cube cube, Block block) | ||
| 2962 | { | ||
| 2963 | int i; | ||
| 2964 | |||
| 2965 | for (i = 0; i < 12; i++) | ||
| 2966 | if (block.edge[i] && !is_solved_edge(cube, i)) | ||
| 2967 | return false; | ||
| 2968 | for (i = 0; i < 8; i++) | ||
| 2969 | if (block.corner[i] && !is_solved_corner(cube, i)) | ||
| 2970 | return false; | ||
| 2971 | for (i = 0; i < 6; i++) | ||
| 2972 | if (block.center[i] && !is_solved_center(cube, i)) | ||
| 2973 | return false; | ||
| 2974 | |||
| 2975 | return true; | ||
| 2976 | } | ||
| 2977 | |||
| 2978 | bool | ||
| 2979 | is_solved_center(Cube cube, Center c) | ||
| 2980 | { | ||
| 2981 | return what_center_at(cube, c) == c; | ||
| 2982 | } | ||
| 2983 | |||
| 2984 | bool | ||
| 2985 | is_solved_corner(Cube cube, Corner c) | ||
| 2986 | { | ||
| 2987 | return what_corner_at(cube, c) == c && | ||
| 2988 | what_orientation_corner(cube.coud, c); | ||
| 2989 | } | ||
| 2990 | |||
| 2991 | bool | ||
| 2992 | is_solved_edge(Cube cube, Edge e) | ||
| 2993 | { | ||
| 2994 | return what_edge_at(cube, e) == e && | ||
| 2995 | what_orientation_edge(cube.eofb, e); | ||
| 2996 | } | ||
| 2997 | |||
| 2998 | int | ||
| 2999 | piece_orientation(Cube cube, int piece, char *orientation) | ||
| 3000 | { | ||
| 3001 | int arr[12], n, b, x; | ||
| 3002 | |||
| 3003 | if (!strcmp(orientation, "eofb")) { | ||
| 3004 | x = cube.eofb; | ||
| 3005 | n = 12; | ||
| 3006 | b = 2; | ||
| 3007 | } else if (!strcmp(orientation, "eorl")) { | ||
| 3008 | x = cube.eorl; | ||
| 3009 | n = 12; | ||
| 3010 | b = 2; | ||
| 3011 | } else if (!strcmp(orientation, "eoud")) { | ||
| 3012 | x = cube.eoud; | ||
| 3013 | n = 12; | ||
| 3014 | b = 2; | ||
| 3015 | } else if (!strcmp(orientation, "coud")) { | ||
| 3016 | x = cube.coud; | ||
| 3017 | n = 8; | ||
| 3018 | b = 3; | ||
| 3019 | } else if (!strcmp(orientation, "corl")) { | ||
| 3020 | x = cube.corl; | ||
| 3021 | n = 8; | ||
| 3022 | b = 3; | ||
| 3023 | } else if (!strcmp(orientation, "cofb")) { | ||
| 3024 | x = cube.cofb; | ||
| 3025 | n = 8; | ||
| 3026 | b = 3; | ||
| 3027 | } else { | ||
| 3028 | return -1; | ||
| 3029 | } | ||
| 3030 | |||
| 3031 | int_to_sum_zero_array(x, b, n, arr); | ||
| 3032 | if (piece < n) | ||
| 3033 | return arr[piece]; | ||
| 3034 | |||
| 3035 | return -1; | ||
| 3036 | } | ||
| 3037 | |||
| 3038 | void | ||
| 3039 | print_cube(Cube cube) | ||
| 3040 | { | ||
| 3041 | /* | ||
| 3042 | CubeArray *arr = new_cubearray(cube, pf_all); | ||
| 3043 | |||
| 3044 | for (int i = 0; i < 12; i++) | ||
| 3045 | printf(" %s ", edge_string[arr->ep[i]]); | ||
| 3046 | printf("\n"); | ||
| 3047 | |||
| 3048 | for (int i = 0; i < 12; i++) | ||
| 3049 | printf(" %c ", arr->eofb[i] + '0'); | ||
| 3050 | printf("\n"); | ||
| 3051 | |||
| 3052 | for (int i = 0; i < 8; i++) | ||
| 3053 | printf("%s ", corner_string[arr->cp[i]]); | ||
| 3054 | printf("\n"); | ||
| 3055 | |||
| 3056 | for (int i = 0; i < 8; i++) | ||
| 3057 | printf(" %c ", arr->coud[i] + '0'); | ||
| 3058 | printf("\n"); | ||
| 3059 | |||
| 3060 | for (int i = 0; i < 6; i++) | ||
| 3061 | printf(" %s ", center_string[arr->cpos[i]]); | ||
| 3062 | printf("\n"); | ||
| 3063 | |||
| 3064 | free_cubearray(arr, pf_all); | ||
| 3065 | */ | ||
| 3066 | |||
| 3067 | for (int i = 0; i < 12; i++) | ||
| 3068 | printf(" %s ", edge_string[what_edge_at(cube, i)]); | ||
| 3069 | printf("\n"); | ||
| 3070 | |||
| 3071 | for (int i = 0; i < 12; i++) | ||
| 3072 | printf(" %d ", what_orientation_edge(cube.eofb, i)); | ||
| 3073 | printf("\n"); | ||
| 3074 | |||
| 3075 | for (int i = 0; i < 8; i++) | ||
| 3076 | printf("%s ", corner_string[what_corner_at(cube, i)]); | ||
| 3077 | printf("\n"); | ||
| 3078 | |||
| 3079 | for (int i = 0; i < 8; i++) | ||
| 3080 | printf(" %d ", what_orientation_corner(cube.coud, i)); | ||
| 3081 | printf("\n"); | ||
| 3082 | |||
| 3083 | for (int i = 0; i < 6; i++) | ||
| 3084 | printf(" %s ", center_string[what_center_at(cube, i)]); | ||
| 3085 | printf("\n"); | ||
| 3086 | |||
| 3087 | } | ||
| 3088 | |||
| 3089 | Cube | ||
| 3090 | random_cube() | ||
| 3091 | { | ||
| 3092 | CubeArray *arr = new_cubearray((Cube){0}, pf_4val); | ||
| 3093 | Cube ret; | ||
| 3094 | int ep, cp, eo, co; | ||
| 3095 | |||
| 3096 | ep = rand() % FACTORIAL12; | ||
| 3097 | cp = rand() % FACTORIAL8; | ||
| 3098 | eo = rand() % POW2TO11; | ||
| 3099 | co = rand() % POW3TO7; | ||
| 3100 | |||
| 3101 | index_to_perm(ep, 12, arr->ep); | ||
| 3102 | index_to_perm(cp, 8, arr->cp); | ||
| 3103 | int_to_sum_zero_array(eo, 2, 12, arr->eofb); | ||
| 3104 | int_to_sum_zero_array(co, 3, 8, arr->coud); | ||
| 3105 | |||
| 3106 | if (perm_sign(arr->ep, 12) != perm_sign(arr->cp, 8)) | ||
| 3107 | swap(&(arr->ep[0]), &(arr->ep[1])); | ||
| 3108 | |||
| 3109 | ret = arrays_to_cube(arr, pf_4val); | ||
| 3110 | free_cubearray(arr, pf_4val); | ||
| 3111 | |||
| 3112 | return ret; | ||
| 3113 | } | ||
| 3114 | |||
| 3115 | /* TODO: clean pre_trans or put it back */ | ||
| 3116 | AlgList * | ||
| 3117 | solve(Cube cube, Step step, SolveOptions *opts) | ||
| 3118 | { | ||
| 3119 | /*AlgListNode *node;*/ | ||
| 3120 | AlgList *sols = new_alglist(); | ||
| 3121 | /*Cube c = apply_trans(opts->pre_trans, cube);*/ | ||
| 3122 | DfsData dd = { | ||
| 3123 | .m = 0, | ||
| 3124 | .niss = false, | ||
| 3125 | .lb = -1, | ||
| 3126 | .last1 = NULLMOVE, | ||
| 3127 | .last2 = NULLMOVE, | ||
| 3128 | .sols = sols, | ||
| 3129 | .current_alg = new_alg("") | ||
| 3130 | }; | ||
| 3131 | |||
| 3132 | if (step.ready != NULL && !step.ready(cube)) { | ||
| 3133 | fprintf(stderr, "Cube not ready for solving step\n"); | ||
| 3134 | return sols; | ||
| 3135 | } | ||
| 3136 | |||
| 3137 | moveset_to_list(step.moveset, step.estimate, dd.sorted_moves); | ||
| 3138 | movelist_to_position(dd.sorted_moves, dd.move_position); | ||
| 3139 | |||
| 3140 | for (dd.d = opts->min_moves; | ||
| 3141 | dd.d <= opts->max_moves && !(sols->len && opts->optimal_only); | ||
| 3142 | dd.d++) { | ||
| 3143 | if (opts->feedback) | ||
| 3144 | fprintf(stderr, | ||
| 3145 | "Found %d solutions, searching depth %d...\n", | ||
| 3146 | sols->len, dd.d); | ||
| 3147 | dfs(cube, step, opts, &dd); | ||
| 3148 | } | ||
| 3149 | |||
| 3150 | /* | ||
| 3151 | for (node = sols->first; node != NULL; node = node->next) | ||
| 3152 | transform_alg(inverse_trans(opts->pre_trans), node->alg); | ||
| 3153 | */ | ||
| 3154 | |||
| 3155 | free_alg(dd.current_alg); | ||
| 3156 | return sols; | ||
| 3157 | } | ||
| 3158 | |||
| 3159 | Alg * | ||
| 3160 | inverse_alg(Alg *alg) | ||
| 3161 | { | ||
| 3162 | Alg *ret = new_alg(""); | ||
| 3163 | int i; | ||
| 3164 | |||
| 3165 | for (i = alg->len-1; i >= 0; i--) | ||
| 3166 | append_move(ret, inverse_move(alg->move[i]), alg->inv[i]); | ||
| 3167 | |||
| 3168 | return ret; | ||
| 3169 | } | ||
| 3170 | |||
| 3171 | Alg * | ||
| 3172 | new_alg(char *str) | ||
| 3173 | { | ||
| 3174 | Alg *alg = malloc(sizeof(Alg)); | ||
| 3175 | int i; | ||
| 3176 | bool niss = false; | ||
| 3177 | Move j, m; | ||
| 3178 | |||
| 3179 | alg->move = malloc(30 * sizeof(Move)); | ||
| 3180 | alg->inv = malloc(30 * sizeof(bool)); | ||
| 3181 | alg->allocated = 30; | ||
| 3182 | alg->len = 0; | ||
| 3183 | |||
| 3184 | for (i = 0; str[i]; i++) { | ||
| 3185 | if (str[i] == ' ' || str[i] == '\t' || str[i] == '\n') | ||
| 3186 | continue; | ||
| 3187 | |||
| 3188 | if (str[i] == '(' && niss) { | ||
| 3189 | fprintf(stderr, "Error reading moves: nested ( )\n"); | ||
| 3190 | return alg; | ||
| 3191 | } | ||
| 3192 | |||
| 3193 | if (str[i] == ')' && !niss) { | ||
| 3194 | fprintf(stderr, "Error reading moves: unmatched )\n"); | ||
| 3195 | return alg; | ||
| 3196 | } | ||
| 3197 | |||
| 3198 | if (str[i] == '(' || str[i] == ')') { | ||
| 3199 | niss = !niss; | ||
| 3200 | continue; | ||
| 3201 | } | ||
| 3202 | |||
| 3203 | for (j = 0; j < NMOVES; j++) { | ||
| 3204 | if (str[i] == move_string[j][0]) { | ||
| 3205 | m = j; | ||
| 3206 | if (m <= B && str[i+1]=='w') { | ||
| 3207 | m += Uw - U; | ||
| 3208 | i++; | ||
| 3209 | } | ||
| 3210 | if (str[i+1]=='2') { | ||
| 3211 | m += 1; | ||
| 3212 | i++; | ||
| 3213 | } else if (str[i+1]=='\'' || str[i+1]=='3') { | ||
| 3214 | m += 2; | ||
| 3215 | i++; | ||
| 3216 | } | ||
| 3217 | append_move(alg, m, niss); | ||
| 3218 | break; | ||
| 3219 | } | ||
| 3220 | } | ||
| 3221 | } | ||
| 3222 | |||
| 3223 | return alg; | ||
| 3224 | } | ||
| 3225 | |||
| 3226 | Alg * | ||
| 3227 | on_inverse(Alg *alg) | ||
| 3228 | { | ||
| 3229 | Alg *ret = new_alg(""); | ||
| 3230 | int i; | ||
| 3231 | |||
| 3232 | for (i = 0; i < alg->len; i++) | ||
| 3233 | append_move(ret, alg->move[i], !alg->inv[i]); | ||
| 3234 | |||
| 3235 | return ret; | ||
| 3236 | } | ||
| 3237 | |||
| 3238 | void | ||
| 3239 | print_alg(Alg *alg, bool l) | ||
| 3240 | { | ||
| 3241 | /* TODO: make it possible to print to stdout or to string */ | ||
| 3242 | /* Maybe just return a string */ | ||
| 3243 | char fill[4]; | ||
| 3244 | int i; | ||
| 3245 | bool niss = false; | ||
| 3246 | |||
| 3247 | for (i = 0; i < alg->len; i++) { | ||
| 3248 | if (!niss && alg->inv[i]) | ||
| 3249 | strcpy(fill, i == 0 ? "(" : " ("); | ||
| 3250 | if (niss && !alg->inv[i]) | ||
| 3251 | strcpy(fill, ") "); | ||
| 3252 | if (niss == alg->inv[i]) | ||
| 3253 | strcpy(fill, i == 0 ? "" : " "); | ||
| 3254 | |||
| 3255 | printf("%s%s", fill, move_string[alg->move[i]]); | ||
| 3256 | niss = alg->inv[i]; | ||
| 3257 | } | ||
| 3258 | |||
| 3259 | if (niss) | ||
| 3260 | printf(")"); | ||
| 3261 | if (l) | ||
| 3262 | printf(" (%d)", alg->len); | ||
| 3263 | |||
| 3264 | printf("\n"); | ||
| 3265 | } | ||
| 3266 | |||
| 3267 | void | ||
| 3268 | print_alglist(AlgList *al, bool l) | ||
| 3269 | { | ||
| 3270 | AlgListNode *i; | ||
| 3271 | |||
| 3272 | for (i = al->first; i != NULL; i = i->next) | ||
| 3273 | print_alg(i->alg, l); | ||
| 3274 | } | ||
| 3275 | |||
| 3276 | void | ||
| 3277 | print_ptable(PruneData *pd) | ||
| 3278 | { | ||
| 3279 | uint64_t i, a[16]; | ||
| 3280 | |||
| 3281 | for (i = 0; i < 16; i++) | ||
| 3282 | a[i] = 0; | ||
| 3283 | |||
| 3284 | if (!pd->generated) | ||
| 3285 | genptable(pd); | ||
| 3286 | |||
| 3287 | for (i = 0; i < pd->coord->max; i++) | ||
| 3288 | a[ptableval(pd, pd->coord->cube(i))]++; | ||
| 3289 | |||
| 3290 | fprintf(stderr, "Values for table %s\n", pd->filename); | ||
| 3291 | for (i = 0; i < 16; i++) | ||
| 3292 | printf("%2lu\t%10lu\n", i, a[i]); | ||
| 3293 | } | ||
| 3294 | |||
| 3295 | uint64_t | ||
| 3296 | ptablesize(PruneData *pd) | ||
| 3297 | { | ||
| 3298 | return (pd->coord->max + 1) / 2; | ||
| 3299 | } | ||
| 3300 | |||
| 3301 | int | ||
| 3302 | ptableval(PruneData *pd, Cube cube) | ||
| 3303 | { | ||
| 3304 | return ptableval_index(pd, pd->coord->index(cube)); | ||
| 3305 | } | ||
| 3306 | |||
| 3307 | Alg * | ||
| 3308 | rotation_alg(Trans i) | ||
| 3309 | { | ||
| 3310 | return rotation_algs[i % NROTATIONS]; | ||
| 3311 | } | ||
| 3312 | |||
| 3313 | void | ||
| 3314 | transform_alg(Trans t, Alg *alg) | ||
| 3315 | { | ||
| 3316 | int i; | ||
| 3317 | |||
| 3318 | for (i = 0; i < alg->len; i++) | ||
| 3319 | alg->move[i] = moves_ttable[t][alg->move[i]]; | ||
| 3320 | } | ||
| 3321 | |||
| 3322 | Center | ||
| 3323 | what_center_at(Cube cube, Center c) | ||
| 3324 | { | ||
| 3325 | return what_center_at_aux[cube.cpos][c]; | ||
| 3326 | } | ||
| 3327 | |||
| 3328 | Corner | ||
| 3329 | what_corner_at(Cube cube, Corner c) | ||
| 3330 | { | ||
| 3331 | return what_corner_at_aux[cube.cp][c]; | ||
| 3332 | } | ||
| 3333 | |||
| 3334 | Edge | ||
| 3335 | what_edge_at(Cube cube, Edge e) | ||
| 3336 | { | ||
| 3337 | Edge ret; | ||
| 3338 | CubeArray *arr = new_cubearray(cube, pf_ep); | ||
| 3339 | |||
| 3340 | ret = arr->ep[e]; | ||
| 3341 | |||
| 3342 | free_cubearray(arr, pf_ep); | ||
| 3343 | return ret; | ||
| 3344 | } | ||
| 3345 | |||
| 3346 | int | ||
| 3347 | what_orientation_corner(int co, Corner c) | ||
| 3348 | { | ||
| 3349 | if (c < 7) | ||
| 3350 | return (co / powint(3, c)) % 3; | ||
| 3351 | else | ||
| 3352 | return what_orientation_last_corner_aux[co]; | ||
| 3353 | } | ||
| 3354 | |||
| 3355 | int | ||
| 3356 | what_orientation_edge(int eo, Edge e) | ||
| 3357 | { | ||
| 3358 | if (e < 11) | ||
| 3359 | return (eo & (1 << e)) ? 1 : 0; | ||
| 3360 | else | ||
| 3361 | return what_orientation_last_edge_aux[eo]; | ||
| 3362 | } | ||
| 3363 | |||
| 3364 | Center | ||
| 3365 | where_is_center(Cube cube, Center c) | ||
| 3366 | { | ||
| 3367 | return where_is_center_aux[cube.cpos][c]; | ||
| 3368 | } | ||
| 3369 | |||
| 3370 | Corner | ||
| 3371 | where_is_corner(Cube cube, Corner c) | ||
| 3372 | { | ||
| 3373 | return where_is_corner_aux[cube.cp][c]; | ||
| 3374 | } | ||
| 3375 | |||
| 3376 | |||
| 3377 | void | ||
| 3378 | init() | ||
| 3379 | { | ||
| 3380 | /* Order is important! */ | ||
| 3381 | init_environment(); | ||
| 3382 | init_strings(); | ||
| 3383 | init_moves_aux(); | ||
| 3384 | init_moves(); | ||
| 3385 | init_auxtables(); | ||
| 3386 | init_cphtr_cosets(); | ||
| 3387 | init_trans_aux(); | ||
| 3388 | init_trans(); | ||
| 3389 | init_symdata(); | ||
| 3390 | } | ||
| 3391 | |||
diff --git a/old/2021-07-15-almostbeforerefactor/cube.h b/old/2021-07-15-almostbeforerefactor/cube.h new file mode 100644 index 0000000..c400d14 --- /dev/null +++ b/old/2021-07-15-almostbeforerefactor/cube.h | |||
| @@ -0,0 +1,79 @@ | |||
| 1 | #ifndef CUBE_H | ||
| 2 | #define CUBE_H | ||
| 3 | |||
| 4 | #include <stdio.h> | ||
| 5 | #include <stdbool.h> | ||
| 6 | #include <stdint.h> | ||
| 7 | #include <stdlib.h> | ||
| 8 | #include <string.h> | ||
| 9 | #include <time.h> | ||
| 10 | #include <unistd.h> | ||
| 11 | #include <sys/stat.h> | ||
| 12 | |||
| 13 | #include "macros.h" | ||
| 14 | #include "cubetypes.h" | ||
| 15 | |||
| 16 | extern Coordinate coord_eofb; | ||
| 17 | extern Coordinate coord_eofbepos; | ||
| 18 | extern Coordinate coord_coud; | ||
| 19 | extern Coordinate coord_corners; | ||
| 20 | extern Coordinate coord_cornershtr; | ||
| 21 | extern Coordinate coord_drud; | ||
| 22 | extern Coordinate coord_coud_sym16; | ||
| 23 | extern Coordinate coord_eofbepos_sym16; | ||
| 24 | extern Coordinate coord_drud_sym16; | ||
| 25 | extern Coordinate coord_khuge; | ||
| 26 | |||
| 27 | extern Trans trans_group_udfix[16]; | ||
| 28 | extern Trans trans_group_trivial[1]; | ||
| 29 | |||
| 30 | Cube apply_alg(Alg *alg, Cube cube); | ||
| 31 | Cube apply_move(Move m, Cube cube); | ||
| 32 | Cube apply_trans(Trans t, Cube cube); | ||
| 33 | bool block_solved(Cube cube, Block); | ||
| 34 | Cube compose(Cube c2, Cube c1); /* Use c2 as an alg on c1 */ | ||
| 35 | uint64_t cphtr(Cube cube); /* TODO: rename (something with cosets) */ | ||
| 36 | Cube anti_cphtr(uint64_t ind); /*TODO also this */ | ||
| 37 | uint64_t epos_dependent(Cube cube); /* TODO: rename and turn into an indexer */ | ||
| 38 | bool equal(Cube c1, Cube c2); | ||
| 39 | Cube inverse_cube(Cube cube); | ||
| 40 | Move inverse_move(Move m); | ||
| 41 | Trans inverse_trans(Trans t); | ||
| 42 | bool is_admissible(Cube cube); | ||
| 43 | bool is_solved(Cube cube, bool reorient); | ||
| 44 | bool is_solved_center(Cube cube, Center c); | ||
| 45 | bool is_solved_corner(Cube cube, Corner c); | ||
| 46 | bool is_solved_edge(Cube cube, Edge e); | ||
| 47 | void print_cube(Cube cube); | ||
| 48 | Cube random_cube(); | ||
| 49 | AlgList * solve(Cube cube, Step step, SolveOptions *opts); | ||
| 50 | Center what_center_at(Cube cube, Center c); | ||
| 51 | Corner what_corner_at(Cube cube, Corner c); | ||
| 52 | Edge what_edge_at(Cube cube, Edge e); | ||
| 53 | int what_orientation_corner(int co, Corner c); | ||
| 54 | int what_orientation_edge(int eo, Edge e); | ||
| 55 | Center where_is_center(Cube cube, Center c); | ||
| 56 | Corner where_is_corner(Cube cube, Corner c); | ||
| 57 | Edge where_is_edge(Cube cube, Edge e); | ||
| 58 | |||
| 59 | bool check_centers(Cube cube); | ||
| 60 | bool check_corners(Cube cube); | ||
| 61 | bool check_cornershtr(Cube cube); | ||
| 62 | bool check_coud(Cube cube); | ||
| 63 | bool check_drud(Cube cube); | ||
| 64 | bool check_eofb(Cube cube); | ||
| 65 | bool check_eofbepos(Cube cube); | ||
| 66 | bool check_epose(Cube cube); | ||
| 67 | bool check_ep(Cube cube); | ||
| 68 | bool check_khuge(Cube cube); | ||
| 69 | bool check_nothing(Cube cube); | ||
| 70 | |||
| 71 | void genptable(PruneData *pd); | ||
| 72 | void print_ptable(PruneData *pd); | ||
| 73 | uint64_t ptablesize(PruneData *pd); | ||
| 74 | int ptableval(PruneData *pd, Cube cube); | ||
| 75 | |||
| 76 | void init(); | ||
| 77 | |||
| 78 | #endif | ||
| 79 | |||
diff --git a/old/2021-07-15-almostbeforerefactor/cubetypes.h b/old/2021-07-15-almostbeforerefactor/cubetypes.h new file mode 100644 index 0000000..d51314d --- /dev/null +++ b/old/2021-07-15-almostbeforerefactor/cubetypes.h | |||
| @@ -0,0 +1,252 @@ | |||
| 1 | #ifndef CUBETYPES_H | ||
| 2 | #define CUBETYPES_H | ||
| 3 | |||
| 4 | /* Typedefs ******************************************************************/ | ||
| 5 | |||
| 6 | typedef enum center Center; | ||
| 7 | typedef enum corner Corner; | ||
| 8 | typedef enum edge Edge; | ||
| 9 | typedef enum move Move; | ||
| 10 | typedef enum trans Trans; | ||
| 11 | |||
| 12 | typedef struct alg Alg; | ||
| 13 | typedef struct alglist AlgList; | ||
| 14 | typedef struct alglistnode AlgListNode; | ||
| 15 | typedef struct block Block; | ||
| 16 | typedef struct coordinate Coordinate; | ||
| 17 | typedef struct cube Cube; | ||
| 18 | typedef struct cubearray CubeArray; | ||
| 19 | typedef struct cubetarget CubeTarget; | ||
| 20 | typedef struct dfsdata DfsData; | ||
| 21 | typedef struct piecefilter PieceFilter; | ||
| 22 | typedef struct prunedata PruneData; | ||
| 23 | typedef struct solveoptions SolveOptions; | ||
| 24 | typedef struct step Step; | ||
| 25 | typedef struct symdata SymData; | ||
| 26 | |||
| 27 | typedef Cube (*AntiIndexer) (uint64_t); | ||
| 28 | typedef bool (*Checker) (Cube); | ||
| 29 | typedef int (*Estimator) (CubeTarget); | ||
| 30 | typedef uint64_t (*Indexer) (Cube); | ||
| 31 | typedef bool (*Moveset) (Move); | ||
| 32 | |||
| 33 | |||
| 34 | /* Enums *********************************************************************/ | ||
| 35 | |||
| 36 | enum | ||
| 37 | center | ||
| 38 | { | ||
| 39 | U_center, D_center, | ||
| 40 | R_center, L_center, | ||
| 41 | F_center, B_center | ||
| 42 | }; | ||
| 43 | |||
| 44 | enum | ||
| 45 | corner | ||
| 46 | { | ||
| 47 | UFR, UFL, UBL, UBR, | ||
| 48 | DFR, DFL, DBL, DBR | ||
| 49 | }; | ||
| 50 | |||
| 51 | enum | ||
| 52 | edge | ||
| 53 | { | ||
| 54 | UF, UL, UB, UR, | ||
| 55 | DF, DL, DB, DR, | ||
| 56 | FR, FL, BL, BR | ||
| 57 | }; | ||
| 58 | |||
| 59 | enum | ||
| 60 | move | ||
| 61 | { | ||
| 62 | NULLMOVE, | ||
| 63 | U, U2, U3, D, D2, D3, | ||
| 64 | R, R2, R3, L, L2, L3, | ||
| 65 | F, F2, F3, B, B2, B3, | ||
| 66 | Uw, Uw2, Uw3, Dw, Dw2, Dw3, | ||
| 67 | Rw, Rw2, Rw3, Lw, Lw2, Lw3, | ||
| 68 | Fw, Fw2, Fw3, Bw, Bw2, Bw3, | ||
| 69 | M, M2, M3, | ||
| 70 | S, S2, S3, | ||
| 71 | E, E2, E3, | ||
| 72 | x, x2, x3, | ||
| 73 | y, y2, y3, | ||
| 74 | z, z2, z3, | ||
| 75 | }; | ||
| 76 | |||
| 77 | enum | ||
| 78 | trans | ||
| 79 | { | ||
| 80 | uf, ur, ub, ul, | ||
| 81 | df, dr, db, dl, | ||
| 82 | rf, rd, rb, ru, | ||
| 83 | lf, ld, lb, lu, | ||
| 84 | fu, fr, fd, fl, | ||
| 85 | bu, br, bd, bl, | ||
| 86 | uf_mirror, ur_mirror, ub_mirror, ul_mirror, | ||
| 87 | df_mirror, dr_mirror, db_mirror, dl_mirror, | ||
| 88 | rf_mirror, rd_mirror, rb_mirror, ru_mirror, | ||
| 89 | lf_mirror, ld_mirror, lb_mirror, lu_mirror, | ||
| 90 | fu_mirror, fr_mirror, fd_mirror, fl_mirror, | ||
| 91 | bu_mirror, br_mirror, bd_mirror, bl_mirror, | ||
| 92 | }; | ||
| 93 | |||
| 94 | |||
| 95 | /* Structs *******************************************************************/ | ||
| 96 | |||
| 97 | struct | ||
| 98 | alg | ||
| 99 | { | ||
| 100 | Move * move; | ||
| 101 | bool * inv; | ||
| 102 | int len; | ||
| 103 | int allocated; | ||
| 104 | }; | ||
| 105 | |||
| 106 | struct | ||
| 107 | alglist | ||
| 108 | { | ||
| 109 | AlgListNode * first; | ||
| 110 | AlgListNode * last; | ||
| 111 | int len; | ||
| 112 | }; | ||
| 113 | |||
| 114 | struct | ||
| 115 | alglistnode | ||
| 116 | { | ||
| 117 | Alg * alg; | ||
| 118 | AlgListNode * next; | ||
| 119 | }; | ||
| 120 | |||
| 121 | struct | ||
| 122 | block | ||
| 123 | { | ||
| 124 | bool edge[12]; | ||
| 125 | bool corner[8]; | ||
| 126 | bool center[6]; | ||
| 127 | }; | ||
| 128 | |||
| 129 | struct | ||
| 130 | coordinate | ||
| 131 | { | ||
| 132 | Indexer index; | ||
| 133 | AntiIndexer cube; | ||
| 134 | Checker check; | ||
| 135 | uint64_t max; | ||
| 136 | }; | ||
| 137 | |||
| 138 | struct | ||
| 139 | cube | ||
| 140 | { | ||
| 141 | int epose; | ||
| 142 | int eposs; | ||
| 143 | int eposm; | ||
| 144 | int eofb; | ||
| 145 | int eorl; | ||
| 146 | int eoud; | ||
| 147 | int cp; | ||
| 148 | int coud; | ||
| 149 | int cofb; | ||
| 150 | int corl; | ||
| 151 | int cpos; | ||
| 152 | }; | ||
| 153 | |||
| 154 | struct | ||
| 155 | cubearray | ||
| 156 | { | ||
| 157 | int * ep; | ||
| 158 | int * eofb; | ||
| 159 | int * eorl; | ||
| 160 | int * eoud; | ||
| 161 | int * cp; | ||
| 162 | int * coud; | ||
| 163 | int * corl; | ||
| 164 | int * cofb; | ||
| 165 | int * cpos; | ||
| 166 | }; | ||
| 167 | |||
| 168 | struct | ||
| 169 | cubetarget | ||
| 170 | { | ||
| 171 | Cube cube; | ||
| 172 | int target; | ||
| 173 | }; | ||
| 174 | |||
| 175 | struct | ||
| 176 | dfsdata | ||
| 177 | { | ||
| 178 | int d; | ||
| 179 | int m; | ||
| 180 | int lb; | ||
| 181 | bool niss; | ||
| 182 | Move last1; | ||
| 183 | Move last2; | ||
| 184 | AlgList * sols; | ||
| 185 | Alg * current_alg; | ||
| 186 | Move sorted_moves[NMOVES]; | ||
| 187 | int move_position[NMOVES]; | ||
| 188 | }; | ||
| 189 | |||
| 190 | struct | ||
| 191 | piecefilter | ||
| 192 | { | ||
| 193 | bool epose; | ||
| 194 | bool eposs; | ||
| 195 | bool eposm; | ||
| 196 | bool eofb; | ||
| 197 | bool eorl; | ||
| 198 | bool eoud; | ||
| 199 | bool cp; | ||
| 200 | bool coud; | ||
| 201 | bool cofb; | ||
| 202 | bool corl; | ||
| 203 | bool cpos; | ||
| 204 | }; | ||
| 205 | |||
| 206 | struct | ||
| 207 | prunedata | ||
| 208 | { | ||
| 209 | char * filename; | ||
| 210 | uint8_t * ptable; | ||
| 211 | bool generated; | ||
| 212 | uint64_t n; | ||
| 213 | Coordinate * coord; | ||
| 214 | Moveset moveset; | ||
| 215 | int ntrans; | ||
| 216 | Trans * trans; | ||
| 217 | }; | ||
| 218 | |||
| 219 | struct | ||
| 220 | solveoptions | ||
| 221 | { | ||
| 222 | int min_moves; | ||
| 223 | int max_moves; | ||
| 224 | int max_solutions; | ||
| 225 | bool optimal_only; | ||
| 226 | bool can_niss; | ||
| 227 | bool feedback; | ||
| 228 | }; | ||
| 229 | |||
| 230 | struct | ||
| 231 | step | ||
| 232 | { | ||
| 233 | Estimator estimate; | ||
| 234 | Checker ready; | ||
| 235 | Moveset moveset; | ||
| 236 | }; | ||
| 237 | |||
| 238 | struct | ||
| 239 | symdata | ||
| 240 | { | ||
| 241 | char * filename; | ||
| 242 | bool generated; | ||
| 243 | Coordinate * coord; | ||
| 244 | Coordinate * sym_coord; | ||
| 245 | int ntrans; | ||
| 246 | Trans * trans; | ||
| 247 | uint64_t * class; | ||
| 248 | Cube * rep; | ||
| 249 | Trans * transtorep; | ||
| 250 | }; | ||
| 251 | |||
| 252 | #endif | ||
diff --git a/old/2021-07-15-almostbeforerefactor/macros.h b/old/2021-07-15-almostbeforerefactor/macros.h new file mode 100644 index 0000000..af3bca1 --- /dev/null +++ b/old/2021-07-15-almostbeforerefactor/macros.h | |||
| @@ -0,0 +1,23 @@ | |||
| 1 | #ifndef MACROS_H | ||
| 2 | #define MACROS_H | ||
| 3 | |||
| 4 | #define POW2TO6 64ULL | ||
| 5 | #define POW2TO11 2048ULL | ||
| 6 | #define POW2TO12 4096ULL | ||
| 7 | #define POW3TO7 2187ULL | ||
| 8 | #define POW3TO8 6561ULL | ||
| 9 | #define FACTORIAL4 24ULL | ||
| 10 | #define FACTORIAL6 720ULL | ||
| 11 | #define FACTORIAL7 5040ULL | ||
| 12 | #define FACTORIAL8 40320ULL | ||
| 13 | #define FACTORIAL12 479001600ULL | ||
| 14 | #define BINOM12ON4 495ULL | ||
| 15 | #define BINOM8ON4 70ULL | ||
| 16 | #define MIN(a,b) (((a) < (b)) ? (a) : (b)) | ||
| 17 | #define MAX(a,b) (((a) > (b)) ? (a) : (b)) | ||
| 18 | |||
| 19 | #define NMOVES (z3+1) | ||
| 20 | #define NTRANS 48 | ||
| 21 | #define NROTATIONS 24 | ||
| 22 | |||
| 23 | #endif | ||
diff --git a/old/2021-07-15-almostbeforerefactor/main.c b/old/2021-07-15-almostbeforerefactor/main.c new file mode 100644 index 0000000..482e007 --- /dev/null +++ b/old/2021-07-15-almostbeforerefactor/main.c | |||
| @@ -0,0 +1,60 @@ | |||
| 1 | #include <stdio.h> | ||
| 2 | #include "cube.h" | ||
| 3 | #include "steps.h" | ||
| 4 | |||
| 5 | int main() { | ||
| 6 | Alg *algo; | ||
| 7 | AlgList *sols; | ||
| 8 | Cube cube; | ||
| 9 | SolveOptions opts; | ||
| 10 | char line[1000]; | ||
| 11 | int i, ns = 1; | ||
| 12 | /* Move m;*/ | ||
| 13 | /* int nrand = 10000, sum1, sum2;*/ | ||
| 14 | |||
| 15 | Step *stps[20] = {&optimal_HTM}; | ||
| 16 | char sss[30][30] = {"Optimal solve"}; | ||
| 17 | |||
| 18 | opts = (SolveOptions) { | ||
| 19 | .min_moves = 0, | ||
| 20 | .max_moves = 20, | ||
| 21 | .optimal_only = true, | ||
| 22 | .max_solutions = 1, | ||
| 23 | .can_niss = false, | ||
| 24 | .feedback = true, | ||
| 25 | }; | ||
| 26 | |||
| 27 | init(); | ||
| 28 | |||
| 29 | /* | ||
| 30 | srand(time(NULL)); | ||
| 31 | sum1 = 0; | ||
| 32 | sum2 = 0; | ||
| 33 | for (i = 0; i < nrand; i++) { | ||
| 34 | cube = random_cube(); | ||
| 35 | sum1 += drud_HTM.estimate((CubeTarget){.cube = cube, .target = 20}); | ||
| 36 | sum2 += optimal_HTM.estimate((CubeTarget){.cube = cube, .target = 20}); | ||
| 37 | } | ||
| 38 | printf("Average drud pruning: %lf\n", ((double)sum1) / ((double) nrand)); | ||
| 39 | printf("Average corners htr pruning: %lf\n", ((double)sum2) / ((double) nrand)); | ||
| 40 | */ | ||
| 41 | |||
| 42 | |||
| 43 | printf("Welcome to nissy 2.0! Insert a scramble:\n"); | ||
| 44 | |||
| 45 | if (fgets(line, 1000, stdin) != NULL) { | ||
| 46 | algo = new_alg(line); | ||
| 47 | cube = apply_alg(algo, (Cube){0}); | ||
| 48 | |||
| 49 | for (i = 0; i < ns; i++) { | ||
| 50 | sols = solve(cube, *stps[i], &opts); | ||
| 51 | printf("%s: %d solutions found:\n", sss[i], sols->len); | ||
| 52 | print_alglist(sols, true); | ||
| 53 | free_alglist(sols); | ||
| 54 | } | ||
| 55 | free_alg(algo); | ||
| 56 | } | ||
| 57 | |||
| 58 | return 0; | ||
| 59 | } | ||
| 60 | |||
diff --git a/old/2021-07-15-almostbeforerefactor/nissy b/old/2021-07-15-almostbeforerefactor/nissy new file mode 100755 index 0000000..63f9c39 --- /dev/null +++ b/old/2021-07-15-almostbeforerefactor/nissy | |||
| Binary files differ | |||
diff --git a/old/2021-07-15-almostbeforerefactor/steps.c b/old/2021-07-15-almostbeforerefactor/steps.c new file mode 100644 index 0000000..33dc74d --- /dev/null +++ b/old/2021-07-15-almostbeforerefactor/steps.c | |||
| @@ -0,0 +1,284 @@ | |||
| 1 | #include "steps.h" | ||
| 2 | |||
| 3 | /* Standard checkers (return lower bound) ************************************/ | ||
| 4 | |||
| 5 | static int estimate_eofb_HTM(CubeTarget ct); | ||
| 6 | static int estimate_coud_HTM(CubeTarget ct); | ||
| 7 | static int estimate_coud_URF(CubeTarget ct); | ||
| 8 | static int estimate_corners_HTM(CubeTarget ct); | ||
| 9 | static int estimate_cornershtr_HTM(CubeTarget ct); | ||
| 10 | static int estimate_corners_URF(CubeTarget ct); | ||
| 11 | static int estimate_cornershtr_URF(CubeTarget ct); | ||
| 12 | static int estimate_drud_HTM(CubeTarget ct); | ||
| 13 | static int estimate_optimal_HTM(CubeTarget ct); | ||
| 14 | |||
| 15 | /* Steps *********************************************************************/ | ||
| 16 | |||
| 17 | Step | ||
| 18 | eofb_HTM = { | ||
| 19 | .estimate = estimate_eofb_HTM, | ||
| 20 | .ready = check_centers, | ||
| 21 | .moveset = moveset_HTM | ||
| 22 | }; | ||
| 23 | |||
| 24 | Step | ||
| 25 | coud_HTM = { | ||
| 26 | .estimate = estimate_coud_HTM, | ||
| 27 | .ready = check_centers, | ||
| 28 | .moveset = moveset_HTM | ||
| 29 | }; | ||
| 30 | |||
| 31 | Step | ||
| 32 | coud_URF = { | ||
| 33 | .estimate = estimate_coud_URF, | ||
| 34 | .ready = check_nothing, | ||
| 35 | .moveset = moveset_URF | ||
| 36 | }; | ||
| 37 | |||
| 38 | Step | ||
| 39 | corners_HTM = { | ||
| 40 | .estimate = estimate_corners_HTM, | ||
| 41 | .ready = check_centers, | ||
| 42 | .moveset = moveset_HTM | ||
| 43 | }; | ||
| 44 | |||
| 45 | Step | ||
| 46 | cornershtr_HTM = { | ||
| 47 | .estimate = estimate_cornershtr_HTM, | ||
| 48 | .ready = check_centers, | ||
| 49 | .moveset = moveset_HTM | ||
| 50 | }; | ||
| 51 | |||
| 52 | Step | ||
| 53 | cornershtr_URF = { | ||
| 54 | .estimate = estimate_cornershtr_URF, | ||
| 55 | .ready = check_nothing, | ||
| 56 | .moveset = moveset_URF | ||
| 57 | }; | ||
| 58 | |||
| 59 | Step | ||
| 60 | corners_URF = { | ||
| 61 | .estimate = estimate_corners_URF, | ||
| 62 | .ready = check_nothing, | ||
| 63 | .moveset = moveset_URF | ||
| 64 | }; | ||
| 65 | |||
| 66 | Step | ||
| 67 | drud_HTM = { | ||
| 68 | .estimate = estimate_drud_HTM, | ||
| 69 | .ready = check_centers, | ||
| 70 | .moveset = moveset_HTM | ||
| 71 | }; | ||
| 72 | |||
| 73 | Step | ||
| 74 | optimal_HTM = { | ||
| 75 | .estimate = estimate_optimal_HTM, | ||
| 76 | .ready = check_centers, | ||
| 77 | .moveset = moveset_HTM | ||
| 78 | }; | ||
| 79 | |||
| 80 | |||
| 81 | /* Pruning tables ************************************************************/ | ||
| 82 | |||
| 83 | PruneData | ||
| 84 | pd_eofb_HTM = { | ||
| 85 | .filename = "ptable_eofb_HTM", | ||
| 86 | .coord = &coord_eofb, | ||
| 87 | .moveset = moveset_HTM, | ||
| 88 | .ntrans = 1, | ||
| 89 | .trans = trans_group_trivial | ||
| 90 | }; | ||
| 91 | |||
| 92 | PruneData | ||
| 93 | pd_coud_HTM = { | ||
| 94 | .filename = "ptable_coud_HTM", | ||
| 95 | .coord = &coord_coud, | ||
| 96 | .moveset = moveset_HTM, | ||
| 97 | .ntrans = 1, | ||
| 98 | .trans = trans_group_trivial | ||
| 99 | }; | ||
| 100 | |||
| 101 | PruneData | ||
| 102 | pd_cornershtr_HTM = { | ||
| 103 | .filename = "ptable_cornershtr_withcosets_HTM", | ||
| 104 | .coord = &coord_cornershtr, | ||
| 105 | .moveset = moveset_HTM, | ||
| 106 | .ntrans = 1, | ||
| 107 | .trans = trans_group_trivial | ||
| 108 | }; | ||
| 109 | |||
| 110 | PruneData | ||
| 111 | pd_corners_HTM = { | ||
| 112 | .filename = "ptable_corners_HTM", | ||
| 113 | .coord = &coord_corners, | ||
| 114 | .moveset = moveset_HTM, | ||
| 115 | .ntrans = 1, | ||
| 116 | .trans = trans_group_trivial | ||
| 117 | }; | ||
| 118 | |||
| 119 | PruneData | ||
| 120 | pd_drud_HTM = { | ||
| 121 | .filename = "ptable_drud_HTM", | ||
| 122 | .coord = &coord_drud, | ||
| 123 | .moveset = moveset_HTM, | ||
| 124 | .ntrans = 1, | ||
| 125 | .trans = trans_group_trivial | ||
| 126 | }; | ||
| 127 | |||
| 128 | PruneData | ||
| 129 | pd_drud_sym16_HTM = { | ||
| 130 | .filename = "ptable_drud_sym16_HTM", | ||
| 131 | .coord = &coord_drud_sym16, | ||
| 132 | .moveset = moveset_HTM, | ||
| 133 | .ntrans = 16, | ||
| 134 | .trans = trans_group_udfix | ||
| 135 | }; | ||
| 136 | |||
| 137 | PruneData | ||
| 138 | pd_khuge_HTM = { | ||
| 139 | .filename = "ptable_khuge_HTM", | ||
| 140 | .coord = &coord_khuge, | ||
| 141 | .moveset = moveset_HTM, | ||
| 142 | .ntrans = 16, | ||
| 143 | .trans = trans_group_udfix | ||
| 144 | }; | ||
| 145 | |||
| 146 | |||
| 147 | /* Standard checkers (return lower bound) ************************************/ | ||
| 148 | |||
| 149 | static int | ||
| 150 | estimate_eofb_HTM(CubeTarget ct) | ||
| 151 | { | ||
| 152 | if (!pd_eofb_HTM.generated) | ||
| 153 | genptable(&pd_eofb_HTM); | ||
| 154 | |||
| 155 | return ptableval(&pd_eofb_HTM, ct.cube); | ||
| 156 | } | ||
| 157 | |||
| 158 | static int | ||
| 159 | estimate_coud_HTM(CubeTarget ct) | ||
| 160 | { | ||
| 161 | if (!pd_coud_HTM.generated) | ||
| 162 | genptable(&pd_coud_HTM); | ||
| 163 | |||
| 164 | return ptableval(&pd_coud_HTM, ct.cube); | ||
| 165 | } | ||
| 166 | |||
| 167 | static int | ||
| 168 | estimate_coud_URF(CubeTarget ct) | ||
| 169 | { | ||
| 170 | /* TODO: I can improve this by checking first the orientation of | ||
| 171 | * the corner in DBL and use that as a reference */ | ||
| 172 | |||
| 173 | CubeTarget ct2 = {.cube = apply_move(z, ct.cube), .target = ct.target}; | ||
| 174 | CubeTarget ct3 = {.cube = apply_move(x, ct.cube), .target = ct.target}; | ||
| 175 | |||
| 176 | int ud = estimate_coud_HTM(ct); | ||
| 177 | int rl = estimate_coud_HTM(ct2); | ||
| 178 | int fb = estimate_coud_HTM(ct3); | ||
| 179 | |||
| 180 | return MIN(ud, MIN(rl, fb)); | ||
| 181 | } | ||
| 182 | |||
| 183 | static int | ||
| 184 | estimate_corners_HTM(CubeTarget ct) | ||
| 185 | { | ||
| 186 | if (!pd_corners_HTM.generated) | ||
| 187 | genptable(&pd_corners_HTM); | ||
| 188 | |||
| 189 | return ptableval(&pd_corners_HTM, ct.cube); | ||
| 190 | } | ||
| 191 | |||
| 192 | static int | ||
| 193 | estimate_cornershtr_HTM(CubeTarget ct) | ||
| 194 | { | ||
| 195 | if (!pd_cornershtr_HTM.generated) | ||
| 196 | genptable(&pd_cornershtr_HTM); | ||
| 197 | |||
| 198 | return ptableval(&pd_cornershtr_HTM, ct.cube); | ||
| 199 | } | ||
| 200 | |||
| 201 | static int | ||
| 202 | estimate_cornershtr_URF(CubeTarget ct) | ||
| 203 | { | ||
| 204 | /* TODO: I can improve this by checking first the corner in DBL | ||
| 205 | * and use that as a reference */ | ||
| 206 | |||
| 207 | int c, ret = 15; | ||
| 208 | Trans i; | ||
| 209 | |||
| 210 | for (i = 0; i < NROTATIONS; i++) { | ||
| 211 | ct.cube = apply_alg(rotation_alg(i), ct.cube); | ||
| 212 | c = estimate_cornershtr_HTM(ct); | ||
| 213 | ret = MIN(ret, c); | ||
| 214 | } | ||
| 215 | |||
| 216 | return ret; | ||
| 217 | } | ||
| 218 | |||
| 219 | static int | ||
| 220 | estimate_corners_URF(CubeTarget ct) | ||
| 221 | { | ||
| 222 | /* TODO: I can improve this by checking first the corner in DBL | ||
| 223 | * and use that as a reference */ | ||
| 224 | |||
| 225 | int c, ret = 15; | ||
| 226 | Trans i; | ||
| 227 | |||
| 228 | for (i = 0; i < NROTATIONS; i++) { | ||
| 229 | ct.cube = apply_alg(rotation_alg(i), ct.cube); | ||
| 230 | c = estimate_corners_HTM(ct); | ||
| 231 | ret = MIN(ret, c); | ||
| 232 | } | ||
| 233 | |||
| 234 | return ret; | ||
| 235 | } | ||
| 236 | |||
| 237 | static int | ||
| 238 | estimate_drud_HTM(CubeTarget ct) | ||
| 239 | { | ||
| 240 | /* | ||
| 241 | if (!pd_drud_HTM.generated) | ||
| 242 | genptable(&pd_drud_HTM); | ||
| 243 | |||
| 244 | return ptableval(&pd_drud_HTM, ct.cube); | ||
| 245 | */ | ||
| 246 | |||
| 247 | if (!pd_drud_sym16_HTM.generated) | ||
| 248 | genptable(&pd_drud_sym16_HTM); | ||
| 249 | |||
| 250 | return ptableval(&pd_drud_sym16_HTM, ct.cube); | ||
| 251 | } | ||
| 252 | |||
| 253 | static int | ||
| 254 | estimate_optimal_HTM(CubeTarget ct) | ||
| 255 | { | ||
| 256 | int dr1, dr2, dr3, cor, ret; | ||
| 257 | Cube cube = ct.cube; | ||
| 258 | |||
| 259 | if (!pd_khuge_HTM.generated) | ||
| 260 | genptable(&pd_khuge_HTM); | ||
| 261 | |||
| 262 | dr1 = ptableval(&pd_khuge_HTM, cube); | ||
| 263 | cor = estimate_corners_HTM(ct); | ||
| 264 | ret = MAX(dr1, cor); | ||
| 265 | |||
| 266 | if (ret > ct.target) | ||
| 267 | return ret; | ||
| 268 | |||
| 269 | cube = apply_trans(rf, ct.cube); | ||
| 270 | dr2 = ptableval(&pd_khuge_HTM, cube); | ||
| 271 | ret = MAX(ret, dr2); | ||
| 272 | |||
| 273 | if (ret > ct.target) | ||
| 274 | return ret; | ||
| 275 | |||
| 276 | cube = apply_trans(fd, ct.cube); | ||
| 277 | dr3 = ptableval(&pd_khuge_HTM, cube); | ||
| 278 | |||
| 279 | /* Michiel de Bondt's trick */ | ||
| 280 | if (dr1 == dr2 && dr2 == dr3 && dr1 != 0) | ||
| 281 | dr3++; | ||
| 282 | |||
| 283 | return MAX(ret, dr3); | ||
| 284 | } | ||
diff --git a/old/2021-07-15-almostbeforerefactor/steps.h b/old/2021-07-15-almostbeforerefactor/steps.h new file mode 100644 index 0000000..81ae11c --- /dev/null +++ b/old/2021-07-15-almostbeforerefactor/steps.h | |||
| @@ -0,0 +1,24 @@ | |||
| 1 | #ifndef STEPS_H | ||
| 2 | #define STEPS_H | ||
| 3 | |||
| 4 | #include "cube.h" | ||
| 5 | |||
| 6 | extern Step eofb_HTM; | ||
| 7 | extern Step coud_HTM; | ||
| 8 | extern Step coud_URF; | ||
| 9 | extern Step corners_HTM; | ||
| 10 | extern Step cornershtr_HTM; | ||
| 11 | extern Step corners_URF; | ||
| 12 | extern Step cornershtr_URF; | ||
| 13 | extern Step drud_HTM; | ||
| 14 | extern Step optimal_HTM; | ||
| 15 | |||
| 16 | extern PruneData pd_eofb_HTM; | ||
| 17 | extern PruneData pd_coud_HTM; | ||
| 18 | extern PruneData pd_corners_HTM; | ||
| 19 | extern PruneData pd_cornershtr_HTM; | ||
| 20 | extern PruneData pd_cornershtreofb_HTM; | ||
| 21 | extern PruneData pd_drud_HTM; | ||
| 22 | extern PruneData pd_khuge_HTM; | ||
| 23 | |||
| 24 | #endif | ||
diff --git a/old/2021-11-10-beforeremovingchecker/alg.c b/old/2021-11-10-beforeremovingchecker/alg.c new file mode 100644 index 0000000..06c2d7b --- /dev/null +++ b/old/2021-11-10-beforeremovingchecker/alg.c | |||
| @@ -0,0 +1,366 @@ | |||
| 1 | #include "alg.h" | ||
| 2 | |||
| 3 | /* Local functions ***********************************************************/ | ||
| 4 | |||
| 5 | static void free_alglistnode(AlgListNode *aln); | ||
| 6 | static void realloc_alg(Alg *alg, int n); | ||
| 7 | |||
| 8 | /* Movesets ******************************************************************/ | ||
| 9 | |||
| 10 | bool | ||
| 11 | moveset_HTM(Move m) | ||
| 12 | { | ||
| 13 | return m >= U && m <= B3; | ||
| 14 | } | ||
| 15 | |||
| 16 | bool | ||
| 17 | moveset_URF(Move m) | ||
| 18 | { | ||
| 19 | Move b = base_move(m); | ||
| 20 | |||
| 21 | return b == U || b == R || b == F; | ||
| 22 | } | ||
| 23 | |||
| 24 | bool | ||
| 25 | moveset_eofb(Move m) | ||
| 26 | { | ||
| 27 | Move b = base_move(m); | ||
| 28 | |||
| 29 | return b == U || b == D || b == R || b == L || | ||
| 30 | ((b == F || b == B) && m == b+1); | ||
| 31 | } | ||
| 32 | |||
| 33 | bool | ||
| 34 | moveset_drud(Move m) | ||
| 35 | { | ||
| 36 | Move b = base_move(m); | ||
| 37 | |||
| 38 | return b == U || b == D || | ||
| 39 | ((b == R || b == L || b == F || b == B) && m == b + 1); | ||
| 40 | } | ||
| 41 | |||
| 42 | bool | ||
| 43 | moveset_htr(Move m) | ||
| 44 | { | ||
| 45 | Move b = base_move(m); | ||
| 46 | |||
| 47 | return moveset_HTM(m) && m == b + 1; | ||
| 48 | } | ||
| 49 | |||
| 50 | |||
| 51 | /* Functions *****************************************************************/ | ||
| 52 | |||
| 53 | void | ||
| 54 | append_alg(AlgList *l, Alg *alg) | ||
| 55 | { | ||
| 56 | AlgListNode *node = malloc(sizeof(AlgListNode)); | ||
| 57 | int i; | ||
| 58 | |||
| 59 | node->alg = new_alg(""); | ||
| 60 | for (i = 0; i < alg->len; i++) | ||
| 61 | append_move(node->alg, alg->move[i], alg->inv[i]); | ||
| 62 | node->next = NULL; | ||
| 63 | |||
| 64 | if (++l->len == 1) | ||
| 65 | l->first = node; | ||
| 66 | else | ||
| 67 | l->last->next = node; | ||
| 68 | l->last = node; | ||
| 69 | } | ||
| 70 | |||
| 71 | void | ||
| 72 | append_move(Alg *alg, Move m, bool inverse) | ||
| 73 | { | ||
| 74 | if (alg->len == alg->allocated) | ||
| 75 | realloc_alg(alg, 2*alg->len); | ||
| 76 | |||
| 77 | alg->move[alg->len] = m; | ||
| 78 | alg->inv [alg->len] = inverse; | ||
| 79 | alg->len++; | ||
| 80 | } | ||
| 81 | |||
| 82 | Move | ||
| 83 | base_move(Move m) | ||
| 84 | { | ||
| 85 | if (m == NULLMOVE) | ||
| 86 | return NULLMOVE; | ||
| 87 | else | ||
| 88 | return m - (m-1)%3; | ||
| 89 | } | ||
| 90 | |||
| 91 | void | ||
| 92 | compose_alg(Alg *alg1, Alg *alg2) | ||
| 93 | { | ||
| 94 | int i; | ||
| 95 | |||
| 96 | for (i = 0; i < alg2->len; i++) | ||
| 97 | append_move(alg1, alg2->move[i], alg2->inv[i]); | ||
| 98 | } | ||
| 99 | |||
| 100 | void | ||
| 101 | free_alg(Alg *alg) | ||
| 102 | { | ||
| 103 | free(alg->move); | ||
| 104 | free(alg->inv); | ||
| 105 | free(alg); | ||
| 106 | } | ||
| 107 | |||
| 108 | void | ||
| 109 | free_alglist(AlgList *l) | ||
| 110 | { | ||
| 111 | AlgListNode *aux, *i = l->first; | ||
| 112 | |||
| 113 | while (i != NULL) { | ||
| 114 | aux = i->next; | ||
| 115 | free_alglistnode(i); | ||
| 116 | i = aux; | ||
| 117 | } | ||
| 118 | free(l); | ||
| 119 | } | ||
| 120 | |||
| 121 | static void | ||
| 122 | free_alglistnode(AlgListNode *aln) | ||
| 123 | { | ||
| 124 | free_alg(aln->alg); | ||
| 125 | free(aln); | ||
| 126 | } | ||
| 127 | |||
| 128 | Alg * | ||
| 129 | inverse_alg(Alg *alg) | ||
| 130 | { | ||
| 131 | Alg *ret = new_alg(""); | ||
| 132 | int i; | ||
| 133 | |||
| 134 | for (i = alg->len-1; i >= 0; i--) | ||
| 135 | append_move(ret, inverse_move(alg->move[i]), alg->inv[i]); | ||
| 136 | |||
| 137 | return ret; | ||
| 138 | } | ||
| 139 | |||
| 140 | Move | ||
| 141 | inverse_move(Move m) | ||
| 142 | { | ||
| 143 | return m == NULLMOVE ? NULLMOVE : m + 2 - 2*((m-1) % 3); | ||
| 144 | } | ||
| 145 | |||
| 146 | char * | ||
| 147 | move_string(Move m) | ||
| 148 | { | ||
| 149 | static char move_string_aux[NMOVES][7] = { | ||
| 150 | [NULLMOVE] = "-", | ||
| 151 | [U] = "U", [U2] = "U2", [U3] = "U\'", | ||
| 152 | [D] = "D", [D2] = "D2", [D3] = "D\'", | ||
| 153 | [R] = "R", [R2] = "R2", [R3] = "R\'", | ||
| 154 | [L] = "L", [L2] = "L2", [L3] = "L\'", | ||
| 155 | [F] = "F", [F2] = "F2", [F3] = "F\'", | ||
| 156 | [B] = "B", [B2] = "B2", [B3] = "B\'", | ||
| 157 | [Uw] = "Uw", [Uw2] = "Uw2", [Uw3] = "Uw\'", | ||
| 158 | [Dw] = "Dw", [Dw2] = "Dw2", [Dw3] = "Dw\'", | ||
| 159 | [Rw] = "Rw", [Rw2] = "Rw2", [Rw3] = "Rw\'", | ||
| 160 | [Lw] = "Lw", [Lw2] = "Lw2", [Lw3] = "Lw\'", | ||
| 161 | [Fw] = "Fw", [Fw2] = "Fw2", [Fw3] = "Fw\'", | ||
| 162 | [Bw] = "Bw", [Bw2] = "Bw2", [Bw3] = "Bw\'", | ||
| 163 | [M] = "M", [M2] = "M2", [M3] = "M\'", | ||
| 164 | [E] = "E", [E2] = "E2", [E3] = "E\'", | ||
| 165 | [S] = "S", [S2] = "S2", [S3] = "S\'", | ||
| 166 | [x] = "x", [x2] = "x2", [x3] = "x\'", | ||
| 167 | [y] = "y", [y2] = "y2", [y3] = "y\'", | ||
| 168 | [z] = "z", [z2] = "z2", [z3] = "z\'", | ||
| 169 | }; | ||
| 170 | |||
| 171 | return move_string_aux[m]; | ||
| 172 | } | ||
| 173 | |||
| 174 | void | ||
| 175 | movelist_to_position(Move *movelist, int *position) | ||
| 176 | { | ||
| 177 | Move m; | ||
| 178 | |||
| 179 | for (m = 0; m < NMOVES && movelist[m] != NULLMOVE; m++) | ||
| 180 | position[movelist[m]] = m; | ||
| 181 | } | ||
| 182 | |||
| 183 | void | ||
| 184 | moveset_to_list(Moveset ms, Move *r) | ||
| 185 | { | ||
| 186 | int n = 0; | ||
| 187 | Move i; | ||
| 188 | |||
| 189 | if (ms == NULL) { | ||
| 190 | fprintf(stderr, "Error: no moveset given\n"); | ||
| 191 | return; | ||
| 192 | } | ||
| 193 | |||
| 194 | for (i = U; i < NMOVES; i++) | ||
| 195 | if (ms(i)) | ||
| 196 | r[n++] = i; | ||
| 197 | |||
| 198 | r[n] = NULLMOVE; | ||
| 199 | } | ||
| 200 | |||
| 201 | Alg * | ||
| 202 | new_alg(char *str) | ||
| 203 | { | ||
| 204 | Alg *alg = malloc(sizeof(Alg)); | ||
| 205 | int i; | ||
| 206 | bool niss = false, move_read; | ||
| 207 | Move j, m; | ||
| 208 | |||
| 209 | alg->move = malloc(30 * sizeof(Move)); | ||
| 210 | alg->inv = malloc(30 * sizeof(bool)); | ||
| 211 | alg->allocated = 30; | ||
| 212 | alg->len = 0; | ||
| 213 | |||
| 214 | for (i = 0; str[i]; i++) { | ||
| 215 | if (str[i] == ' ' || str[i] == '\t' || str[i] == '\n') | ||
| 216 | continue; | ||
| 217 | |||
| 218 | if (str[i] == '(' && niss) { | ||
| 219 | fprintf(stderr, "Error reading moves: nested ( )\n"); | ||
| 220 | return alg; | ||
| 221 | } | ||
| 222 | |||
| 223 | if (str[i] == ')' && !niss) { | ||
| 224 | fprintf(stderr, "Error reading moves: unmatched )\n"); | ||
| 225 | return alg; | ||
| 226 | } | ||
| 227 | |||
| 228 | if (str[i] == '(' || str[i] == ')') { | ||
| 229 | niss = !niss; | ||
| 230 | continue; | ||
| 231 | } | ||
| 232 | |||
| 233 | move_read = false; | ||
| 234 | for (j = 0; j < NMOVES; j++) { | ||
| 235 | if (str[i] == move_string(j)[0] || | ||
| 236 | (str[i] >= 'a' && str[i] <= 'z' && | ||
| 237 | str[i] == move_string(j)[0]-('A'-'a') && j<=B)) { | ||
| 238 | m = j; | ||
| 239 | if (str[i] >= 'a' && str[i] <= 'z' && j<=B) { | ||
| 240 | m += Uw - U; | ||
| 241 | } | ||
| 242 | if (m <= B && str[i+1]=='w') { | ||
| 243 | m += Uw - U; | ||
| 244 | i++; | ||
| 245 | } | ||
| 246 | if (str[i+1]=='2') { | ||
| 247 | m += 1; | ||
| 248 | i++; | ||
| 249 | } else if (str[i+1] == '\'' || | ||
| 250 | str[i+1] == '3' || | ||
| 251 | str[i+1] == '`' ) { | ||
| 252 | m += 2; | ||
| 253 | i++; | ||
| 254 | } else if ((int)str[i+1] == -62 && | ||
| 255 | (int)str[i+2] == -76) { | ||
| 256 | /* Weird apostrophe */ | ||
| 257 | m += 2; | ||
| 258 | i += 2; | ||
| 259 | } else if ((int)str[i+1] == -30 && | ||
| 260 | (int)str[i+2] == -128 && | ||
| 261 | (int)str[i+3] == -103) { | ||
| 262 | /* MacOS apostrophe */ | ||
| 263 | m += 2; | ||
| 264 | i += 3; | ||
| 265 | } | ||
| 266 | append_move(alg, m, niss); | ||
| 267 | move_read = true; | ||
| 268 | break; | ||
| 269 | } | ||
| 270 | } | ||
| 271 | |||
| 272 | if (!move_read) { | ||
| 273 | alg = new_alg(""); | ||
| 274 | return alg; | ||
| 275 | } | ||
| 276 | } | ||
| 277 | |||
| 278 | return alg; | ||
| 279 | } | ||
| 280 | |||
| 281 | AlgList * | ||
| 282 | new_alglist() | ||
| 283 | { | ||
| 284 | AlgList *ret = malloc(sizeof(AlgList)); | ||
| 285 | |||
| 286 | ret->len = 0; | ||
| 287 | ret->first = NULL; | ||
| 288 | ret->last = NULL; | ||
| 289 | |||
| 290 | return ret; | ||
| 291 | } | ||
| 292 | |||
| 293 | Alg * | ||
| 294 | on_inverse(Alg *alg) | ||
| 295 | { | ||
| 296 | Alg *ret = new_alg(""); | ||
| 297 | int i; | ||
| 298 | |||
| 299 | for (i = 0; i < alg->len; i++) | ||
| 300 | append_move(ret, alg->move[i], !alg->inv[i]); | ||
| 301 | |||
| 302 | return ret; | ||
| 303 | } | ||
| 304 | |||
| 305 | void | ||
| 306 | print_alg(Alg *alg, bool l) | ||
| 307 | { | ||
| 308 | /* TODO: make it possible to print to stdout or to string */ | ||
| 309 | /* Maybe just return a string */ | ||
| 310 | char fill[4]; | ||
| 311 | int i; | ||
| 312 | bool niss = false; | ||
| 313 | |||
| 314 | for (i = 0; i < alg->len; i++) { | ||
| 315 | if (!niss && alg->inv[i]) | ||
| 316 | strcpy(fill, i == 0 ? "(" : " ("); | ||
| 317 | if (niss && !alg->inv[i]) | ||
| 318 | strcpy(fill, ") "); | ||
| 319 | if (niss == alg->inv[i]) | ||
| 320 | strcpy(fill, i == 0 ? "" : " "); | ||
| 321 | |||
| 322 | printf("%s%s", fill, move_string(alg->move[i])); | ||
| 323 | niss = alg->inv[i]; | ||
| 324 | } | ||
| 325 | |||
| 326 | if (niss) | ||
| 327 | printf(")"); | ||
| 328 | if (l) | ||
| 329 | printf(" (%d)", alg->len); | ||
| 330 | |||
| 331 | printf("\n"); | ||
| 332 | } | ||
| 333 | |||
| 334 | void | ||
| 335 | print_alglist(AlgList *al, bool l) | ||
| 336 | { | ||
| 337 | AlgListNode *i; | ||
| 338 | |||
| 339 | for (i = al->first; i != NULL; i = i->next) | ||
| 340 | print_alg(i->alg, l); | ||
| 341 | } | ||
| 342 | |||
| 343 | static void | ||
| 344 | realloc_alg(Alg *alg, int n) | ||
| 345 | { | ||
| 346 | if (alg == NULL) { | ||
| 347 | fprintf(stderr, "Error: trying to reallocate NULL alg.\n"); | ||
| 348 | return; | ||
| 349 | } | ||
| 350 | |||
| 351 | if (n < alg->len) { | ||
| 352 | fprintf(stderr, "Error: alg too long for reallocation "); | ||
| 353 | fprintf(stderr, "(%d vs %d)\n", alg->len, n); | ||
| 354 | return; | ||
| 355 | } | ||
| 356 | |||
| 357 | if (n > 1000000) { | ||
| 358 | fprintf(stderr, "Warning: very long alg,"); | ||
| 359 | fprintf(stderr, "something might go wrong.\n"); | ||
| 360 | } | ||
| 361 | |||
| 362 | alg->move = realloc(alg->move, n * sizeof(int)); | ||
| 363 | alg->inv = realloc(alg->inv, n * sizeof(int)); | ||
| 364 | alg->allocated = n; | ||
| 365 | } | ||
| 366 | |||
diff --git a/old/2021-11-10-beforeremovingchecker/alg.h b/old/2021-11-10-beforeremovingchecker/alg.h new file mode 100644 index 0000000..98900b4 --- /dev/null +++ b/old/2021-11-10-beforeremovingchecker/alg.h | |||
| @@ -0,0 +1,35 @@ | |||
| 1 | #ifndef ALG_H | ||
| 2 | #define ALG_H | ||
| 3 | |||
| 4 | #include <stdio.h> | ||
| 5 | #include <stdlib.h> | ||
| 6 | #include <string.h> | ||
| 7 | |||
| 8 | #include "cubetypes.h" | ||
| 9 | #include "utils.h" | ||
| 10 | |||
| 11 | bool moveset_HTM(Move m); | ||
| 12 | bool moveset_URF(Move m); | ||
| 13 | bool moveset_eofb(Move m); | ||
| 14 | bool moveset_drud(Move m); | ||
| 15 | bool moveset_htr(Move m); | ||
| 16 | |||
| 17 | void append_alg(AlgList *l, Alg *alg); | ||
| 18 | void append_move(Alg *alg, Move m, bool inverse); | ||
| 19 | void compose_alg(Alg *alg1, Alg *alg2); | ||
| 20 | Move base_move(Move m); | ||
| 21 | void free_alg(Alg *alg); | ||
| 22 | void free_alglist(AlgList *l); | ||
| 23 | Alg * inverse_alg(Alg *alg); | ||
| 24 | Move inverse_move(Move m); | ||
| 25 | char * move_string(Move m); | ||
| 26 | void movelist_to_position(Move *ml, int *pos); | ||
| 27 | void moveset_to_list(Moveset ms, Move *lst); | ||
| 28 | Alg * new_alg(char *str); | ||
| 29 | AlgList * new_alglist(); | ||
| 30 | Alg * on_inverse(Alg *alg); | ||
| 31 | void print_alg(Alg *alg, bool l); | ||
| 32 | void print_alglist(AlgList *al, bool l); | ||
| 33 | |||
| 34 | #endif | ||
| 35 | |||
diff --git a/old/2021-11-10-beforeremovingchecker/commands.c b/old/2021-11-10-beforeremovingchecker/commands.c new file mode 100644 index 0000000..b141229 --- /dev/null +++ b/old/2021-11-10-beforeremovingchecker/commands.c | |||
| @@ -0,0 +1,329 @@ | |||
| 1 | #include "commands.h" | ||
| 2 | |||
| 3 | /* Arg parsing functions *****************************************************/ | ||
| 4 | |||
| 5 | CommandArgs * solvestep_parse_args(int c, char **v); | ||
| 6 | CommandArgs * help_parse_args(int c, char **v); | ||
| 7 | CommandArgs * print_parse_args(int c, char **v); | ||
| 8 | CommandArgs * parse_no_arg(int c, char **v); | ||
| 9 | |||
| 10 | /* Exec functions ************************************************************/ | ||
| 11 | |||
| 12 | static void solvestep_exec(CommandArgs *args); | ||
| 13 | static void steps_exec(CommandArgs *args); | ||
| 14 | static void commands_exec(CommandArgs *args); | ||
| 15 | static void print_exec(CommandArgs *args); | ||
| 16 | static void help_exec(CommandArgs *args); | ||
| 17 | static void quit_exec(CommandArgs *args); | ||
| 18 | |||
| 19 | /* Local functions ***********************************************************/ | ||
| 20 | |||
| 21 | static bool read_step(CommandArgs *args, char *str); | ||
| 22 | static bool read_scramble(int c, char **v, CommandArgs *args); | ||
| 23 | |||
| 24 | /* Commands ******************************************************************/ | ||
| 25 | |||
| 26 | Command | ||
| 27 | solvestep_cmd = { | ||
| 28 | .name = "solve", | ||
| 29 | .usage = "solve STEP [OPTIONS] SCRAMBLE", | ||
| 30 | .description = "Solve a step", | ||
| 31 | .parse_args = solvestep_parse_args, | ||
| 32 | .exec = solvestep_exec | ||
| 33 | }; | ||
| 34 | |||
| 35 | Command | ||
| 36 | steps_cmd = { | ||
| 37 | .name = "steps", | ||
| 38 | .usage = "steps", | ||
| 39 | .description = "List available steps", | ||
| 40 | .parse_args = parse_no_arg, | ||
| 41 | .exec = steps_exec | ||
| 42 | }; | ||
| 43 | |||
| 44 | Command | ||
| 45 | commands_cmd = { | ||
| 46 | .name = "commands", | ||
| 47 | .usage = "commands", | ||
| 48 | .description = "List available commands", | ||
| 49 | .parse_args = parse_no_arg, | ||
| 50 | .exec = commands_exec | ||
| 51 | }; | ||
| 52 | |||
| 53 | Command | ||
| 54 | print_cmd = { | ||
| 55 | .name = "print", | ||
| 56 | .usage = "print SCRAMBLE", | ||
| 57 | .description = "Print written description of the cube", | ||
| 58 | .parse_args = print_parse_args, | ||
| 59 | .exec = print_exec, | ||
| 60 | }; | ||
| 61 | |||
| 62 | Command | ||
| 63 | help_cmd = { | ||
| 64 | .name = "help", | ||
| 65 | .usage = "help [COMMAND]", | ||
| 66 | .description = "Display nissy manual page or help on specific command", | ||
| 67 | .parse_args = help_parse_args, | ||
| 68 | .exec = help_exec, | ||
| 69 | }; | ||
| 70 | |||
| 71 | Command | ||
| 72 | quit_cmd = { | ||
| 73 | .name = "quit", | ||
| 74 | .usage = "quit", | ||
| 75 | .description = "Quit nissy", | ||
| 76 | .parse_args = parse_no_arg, | ||
| 77 | .exec = quit_exec, | ||
| 78 | }; | ||
| 79 | |||
| 80 | Command *commands[NCOMMANDS] = { | ||
| 81 | &solvestep_cmd, | ||
| 82 | &steps_cmd, | ||
| 83 | &commands_cmd, | ||
| 84 | &help_cmd, | ||
| 85 | &print_cmd, | ||
| 86 | &quit_cmd | ||
| 87 | }; | ||
| 88 | |||
| 89 | /* Arg parsing functions implementation **************************************/ | ||
| 90 | |||
| 91 | CommandArgs * | ||
| 92 | solvestep_parse_args(int c, char **v) | ||
| 93 | { | ||
| 94 | int i; | ||
| 95 | long val; | ||
| 96 | |||
| 97 | CommandArgs *a = malloc(sizeof(CommandArgs)); | ||
| 98 | |||
| 99 | a->success = false; | ||
| 100 | a->opts = malloc(sizeof(SolveOptions)); | ||
| 101 | a->step = steps[0]; | ||
| 102 | a->command = NULL; | ||
| 103 | a->scramble = NULL; | ||
| 104 | |||
| 105 | a->opts->min_moves = 0; | ||
| 106 | a->opts->max_moves = 20; | ||
| 107 | a->opts->max_solutions = 1; | ||
| 108 | a->opts->optimal_only = false; | ||
| 109 | a->opts->can_niss = false; | ||
| 110 | a->opts->feedback = false; | ||
| 111 | a->opts->all = false; | ||
| 112 | a->opts->print_number = true; | ||
| 113 | |||
| 114 | for (i = 0; i < c; i++) { | ||
| 115 | if (!strcmp(v[i], "-m")) { | ||
| 116 | val = strtol(v[++i], NULL, 10); | ||
| 117 | if (val < 0 || val > 100) { | ||
| 118 | fprintf(stderr, | ||
| 119 | "Invalid min number of moves.\n"); | ||
| 120 | return a; | ||
| 121 | } | ||
| 122 | a->opts->min_moves = val; | ||
| 123 | } else if (!strcmp(v[i], "-M")) { | ||
| 124 | val = strtol(v[++i], NULL, 10); | ||
| 125 | if (val < 0 || val > 100) { | ||
| 126 | fprintf(stderr, | ||
| 127 | "Invalid max number of moves.\n"); | ||
| 128 | return a; | ||
| 129 | } | ||
| 130 | a->opts->max_moves = val; | ||
| 131 | } else if (!strcmp(v[i], "-s")) { | ||
| 132 | val = strtol(v[++i], NULL, 10); | ||
| 133 | if (val < 1 || val > 1000000) { | ||
| 134 | fprintf(stderr, | ||
| 135 | "Invalid number of solutions.\n"); | ||
| 136 | return a; | ||
| 137 | } | ||
| 138 | a->opts->max_solutions = val; | ||
| 139 | } else if (!strcmp(v[i], "-o")) { | ||
| 140 | a->opts->optimal_only = true; | ||
| 141 | } else if (!strcmp(v[i], "-n")) { | ||
| 142 | a->opts->can_niss = true; | ||
| 143 | } else if (!strcmp(v[i], "-v")) { | ||
| 144 | a->opts->feedback = true; | ||
| 145 | } else if (!strcmp(v[i], "-a")) { | ||
| 146 | a->opts->all = true; | ||
| 147 | } else if (!strcmp(v[i], "-p")) { | ||
| 148 | a->opts->print_number = false; | ||
| 149 | } else if (!read_step(a, v[i])) { | ||
| 150 | break; | ||
| 151 | } | ||
| 152 | } | ||
| 153 | |||
| 154 | a->success = read_scramble(c-i, &v[i], a); | ||
| 155 | return a; | ||
| 156 | } | ||
| 157 | |||
| 158 | CommandArgs * | ||
| 159 | help_parse_args(int c, char **v) | ||
| 160 | { | ||
| 161 | int i; | ||
| 162 | CommandArgs *a = malloc(sizeof(CommandArgs)); | ||
| 163 | |||
| 164 | a->scramble = NULL; | ||
| 165 | a->opts = NULL; | ||
| 166 | a->step = NULL; | ||
| 167 | a->command = NULL; | ||
| 168 | |||
| 169 | if (c == 1) { | ||
| 170 | for (i = 0; i < NCOMMANDS; i++) | ||
| 171 | if (commands[i] != NULL && | ||
| 172 | !strcmp(v[0], commands[i]->name)) | ||
| 173 | a->command = commands[i]; | ||
| 174 | if (a->command == NULL) | ||
| 175 | fprintf(stderr, "%s: command not found\n", v[0]); | ||
| 176 | } | ||
| 177 | |||
| 178 | a->success = c == 0 || (c == 1 && a->command != NULL); | ||
| 179 | return a; | ||
| 180 | } | ||
| 181 | |||
| 182 | CommandArgs * | ||
| 183 | parse_no_arg(int c, char **v) | ||
| 184 | { | ||
| 185 | CommandArgs *a = malloc(sizeof(CommandArgs)); | ||
| 186 | |||
| 187 | a->scramble = NULL; | ||
| 188 | a->opts = NULL; | ||
| 189 | a->step = NULL; | ||
| 190 | a->command = NULL; | ||
| 191 | |||
| 192 | return a; | ||
| 193 | } | ||
| 194 | |||
| 195 | CommandArgs * | ||
| 196 | print_parse_args(int c, char **v) | ||
| 197 | { | ||
| 198 | CommandArgs *a = malloc(sizeof(CommandArgs)); | ||
| 199 | |||
| 200 | a->opts = NULL; | ||
| 201 | a->step = NULL; | ||
| 202 | a->command = NULL; | ||
| 203 | |||
| 204 | a->success = read_scramble(c-1, &v[1], a); | ||
| 205 | return a; | ||
| 206 | } | ||
| 207 | |||
| 208 | /* Exec functions implementation *********************************************/ | ||
| 209 | |||
| 210 | static void | ||
| 211 | solvestep_exec(CommandArgs *args) | ||
| 212 | { | ||
| 213 | Cube c = apply_alg(args->scramble, (Cube){0}); | ||
| 214 | AlgList *sols = solve(c, args->step, args->opts); | ||
| 215 | print_alglist(sols, args->opts->print_number); | ||
| 216 | free_alglist(sols); | ||
| 217 | } | ||
| 218 | |||
| 219 | static void | ||
| 220 | steps_exec(CommandArgs *args) | ||
| 221 | { | ||
| 222 | int i; | ||
| 223 | |||
| 224 | for (i = 0; i < NSTEPS && steps[i] != NULL; i++) | ||
| 225 | printf("%-15s %s\n", steps[i]->shortname, steps[i]->name); | ||
| 226 | } | ||
| 227 | |||
| 228 | static void | ||
| 229 | commands_exec(CommandArgs *args) | ||
| 230 | { | ||
| 231 | int i; | ||
| 232 | |||
| 233 | for (i = 0; i < NCOMMANDS && commands[i] != NULL; i++) | ||
| 234 | printf("%s\n", commands[i]->usage); | ||
| 235 | |||
| 236 | } | ||
| 237 | |||
| 238 | static void | ||
| 239 | print_exec(CommandArgs *args) | ||
| 240 | { | ||
| 241 | print_cube(apply_alg(args->scramble, (Cube){0})); | ||
| 242 | } | ||
| 243 | |||
| 244 | static void | ||
| 245 | help_exec(CommandArgs *args) | ||
| 246 | { | ||
| 247 | /* TODO: print full nissy manpage */ | ||
| 248 | if (args->command == NULL) { | ||
| 249 | printf("Type help COMMAND for information on a "); | ||
| 250 | printf("specific command.\n"); | ||
| 251 | printf("A more complete manual page is work in progress.\n"); | ||
| 252 | } else { | ||
| 253 | printf("Command %s: %s\nusage: %s\n", args->command->name, | ||
| 254 | args->command->description, args->command->usage); | ||
| 255 | } | ||
| 256 | } | ||
| 257 | |||
| 258 | static void | ||
| 259 | quit_exec(CommandArgs *args) | ||
| 260 | { | ||
| 261 | exit(0); | ||
| 262 | } | ||
| 263 | |||
| 264 | /* Local functions implementation ********************************************/ | ||
| 265 | |||
| 266 | static bool | ||
| 267 | read_step(CommandArgs *args, char *str) | ||
| 268 | { | ||
| 269 | int i; | ||
| 270 | |||
| 271 | for (i = 0; i < NSTEPS; i++) { | ||
| 272 | if (steps[i] != NULL && !strcmp(steps[i]->shortname, str)) { | ||
| 273 | args->step = steps[i]; | ||
| 274 | return true; | ||
| 275 | } | ||
| 276 | } | ||
| 277 | |||
| 278 | return false; | ||
| 279 | } | ||
| 280 | |||
| 281 | static bool | ||
| 282 | read_scramble(int c, char **v, CommandArgs *args) | ||
| 283 | { | ||
| 284 | int i, k, n; | ||
| 285 | unsigned int j; | ||
| 286 | char *algstr; | ||
| 287 | |||
| 288 | if (new_alg(v[0])->len == 0) { | ||
| 289 | fprintf(stderr, "%s: moves or option unrecognized\n", v[0]); | ||
| 290 | return false; | ||
| 291 | } | ||
| 292 | |||
| 293 | n = 0; | ||
| 294 | for(i = 0; i < c; i++) | ||
| 295 | n += strlen(v[i]); | ||
| 296 | |||
| 297 | algstr = malloc((n + 1) * sizeof(char)); | ||
| 298 | k = 0; | ||
| 299 | for (i = 0; i < c; i++) | ||
| 300 | for (j = 0; j < strlen(v[i]); j++) | ||
| 301 | algstr[k++] = v[i][j]; | ||
| 302 | algstr[k] = 0; | ||
| 303 | |||
| 304 | args->scramble = new_alg(algstr); | ||
| 305 | free(algstr); | ||
| 306 | |||
| 307 | if (args->scramble->len == 0) | ||
| 308 | fprintf(stderr, "Error reading scramble\n"); | ||
| 309 | |||
| 310 | return args->scramble->len > 0; | ||
| 311 | } | ||
| 312 | |||
| 313 | /* Public functions implementation *******************************************/ | ||
| 314 | |||
| 315 | void | ||
| 316 | free_args(CommandArgs *args) | ||
| 317 | { | ||
| 318 | if (args == NULL) | ||
| 319 | return; | ||
| 320 | |||
| 321 | if (args->scramble != NULL) | ||
| 322 | free_alg(args->scramble); | ||
| 323 | if (args->opts != NULL) | ||
| 324 | free(args->opts); | ||
| 325 | |||
| 326 | /* step and command must not be freed, they are static! */ | ||
| 327 | |||
| 328 | free(args); | ||
| 329 | } | ||
diff --git a/old/2021-11-10-beforeremovingchecker/commands.h b/old/2021-11-10-beforeremovingchecker/commands.h new file mode 100644 index 0000000..f2703fa --- /dev/null +++ b/old/2021-11-10-beforeremovingchecker/commands.h | |||
| @@ -0,0 +1,13 @@ | |||
| 1 | #ifndef COMMANDS_H | ||
| 2 | #define COMMANDS_H | ||
| 3 | |||
| 4 | #include "solve.h" | ||
| 5 | #include "steps.h" | ||
| 6 | |||
| 7 | #define NCOMMANDS 10 | ||
| 8 | |||
| 9 | void free_args(CommandArgs *args); | ||
| 10 | |||
| 11 | extern Command * commands[NCOMMANDS]; | ||
| 12 | |||
| 13 | #endif | ||
diff --git a/old/2021-11-10-beforeremovingchecker/coord.c b/old/2021-11-10-beforeremovingchecker/coord.c new file mode 100644 index 0000000..343dfb3 --- /dev/null +++ b/old/2021-11-10-beforeremovingchecker/coord.c | |||
| @@ -0,0 +1,629 @@ | |||
| 1 | #include "coord.h" | ||
| 2 | |||
| 3 | static Cube antindex_eofb(uint64_t ind); | ||
| 4 | static Cube antindex_eofbepos(uint64_t ind); | ||
| 5 | static Cube antindex_epud(uint64_t ind); | ||
| 6 | static Cube antindex_coud(uint64_t ind); | ||
| 7 | static Cube antindex_corners(uint64_t ind); | ||
| 8 | static Cube antindex_cp(uint64_t ind); | ||
| 9 | static Cube antindex_cphtr(uint64_t); | ||
| 10 | static Cube antindex_cornershtr(uint64_t ind); | ||
| 11 | static Cube antindex_cornershtrfin(uint64_t ind); | ||
| 12 | static Cube antindex_drud(uint64_t ind); | ||
| 13 | static Cube antindex_drud_eofb(uint64_t ind); | ||
| 14 | static Cube antindex_htr_drud(uint64_t ind); | ||
| 15 | static Cube antindex_htrfin(uint64_t ind); | ||
| 16 | |||
| 17 | static uint64_t index_eofb(Cube cube); | ||
| 18 | static uint64_t index_eofbepos(Cube cube); | ||
| 19 | static uint64_t index_epud(Cube cube); | ||
| 20 | static uint64_t index_coud(Cube cube); | ||
| 21 | static uint64_t index_corners(Cube cube); | ||
| 22 | static uint64_t index_cp(Cube cube); | ||
| 23 | static uint64_t index_cphtr(Cube cube); | ||
| 24 | static uint64_t index_cornershtr(Cube cube); | ||
| 25 | static uint64_t index_cornershtrfin(Cube cube); | ||
| 26 | static uint64_t index_drud(Cube cube); | ||
| 27 | static uint64_t index_drud_eofb(Cube cube); | ||
| 28 | static uint64_t index_htr_drud(Cube cube); | ||
| 29 | static uint64_t index_htrfin(Cube cube); | ||
| 30 | |||
| 31 | static void init_cphtr_cosets(); | ||
| 32 | static void init_cphtr_left_cosets_bfs(int i, int c); | ||
| 33 | static void init_cphtr_right_cosets_color(int i, int c); | ||
| 34 | static void init_cornershtrfin(); | ||
| 35 | |||
| 36 | |||
| 37 | /* All sorts of useful costants and tables **********************************/ | ||
| 38 | |||
| 39 | static int cphtr_left_cosets[FACTORIAL8]; | ||
| 40 | static int cphtr_right_cosets[FACTORIAL8]; | ||
| 41 | static int cphtr_right_rep[BINOM8ON4*6]; | ||
| 42 | static int cornershtrfin_ind[FACTORIAL8]; | ||
| 43 | static int cornershtrfin_ant[24*24/6]; | ||
| 44 | |||
| 45 | /* Coordinates and their implementation **************************************/ | ||
| 46 | |||
| 47 | Coordinate | ||
| 48 | coord_eofb = { | ||
| 49 | .index = index_eofb, | ||
| 50 | .cube = antindex_eofb, | ||
| 51 | .check = check_eofb, | ||
| 52 | .max = POW2TO11, | ||
| 53 | .ntrans = 1, | ||
| 54 | }; | ||
| 55 | |||
| 56 | Coordinate | ||
| 57 | coord_eofbepos = { | ||
| 58 | .index = index_eofbepos, | ||
| 59 | .cube = antindex_eofbepos, | ||
| 60 | .check = check_eofbepos, | ||
| 61 | .max = POW2TO11 * BINOM12ON4, | ||
| 62 | .ntrans = 1, | ||
| 63 | }; | ||
| 64 | |||
| 65 | Coordinate | ||
| 66 | coord_coud = { | ||
| 67 | .index = index_coud, | ||
| 68 | .cube = antindex_coud, | ||
| 69 | .check = check_coud, | ||
| 70 | .max = POW3TO7, | ||
| 71 | .ntrans = 1, | ||
| 72 | }; | ||
| 73 | |||
| 74 | Coordinate | ||
| 75 | coord_corners = { | ||
| 76 | .index = index_corners, | ||
| 77 | .cube = antindex_corners, | ||
| 78 | .check = check_corners, | ||
| 79 | .max = POW3TO7 * FACTORIAL8, | ||
| 80 | .ntrans = 1, | ||
| 81 | }; | ||
| 82 | |||
| 83 | Coordinate | ||
| 84 | coord_cp = { | ||
| 85 | .index = index_cp, | ||
| 86 | .cube = antindex_cp, | ||
| 87 | .check = check_cp, | ||
| 88 | .max = FACTORIAL8, | ||
| 89 | .ntrans = 1, | ||
| 90 | }; | ||
| 91 | |||
| 92 | Coordinate | ||
| 93 | coord_cphtr = { | ||
| 94 | .index = index_cphtr, | ||
| 95 | .cube = antindex_cphtr, | ||
| 96 | .check = check_cphtr, | ||
| 97 | .max = BINOM8ON4 * 6, | ||
| 98 | .ntrans = 1, | ||
| 99 | }; | ||
| 100 | |||
| 101 | Coordinate | ||
| 102 | coord_cornershtr = { | ||
| 103 | .index = index_cornershtr, | ||
| 104 | .cube = antindex_cornershtr, | ||
| 105 | .check = check_cornershtr, | ||
| 106 | .max = POW3TO7 * BINOM8ON4 * 6, | ||
| 107 | .ntrans = 1, | ||
| 108 | }; | ||
| 109 | |||
| 110 | Coordinate | ||
| 111 | coord_cornershtrfin = { | ||
| 112 | .index = index_cornershtrfin, | ||
| 113 | .cube = antindex_cornershtrfin, | ||
| 114 | .check = check_cp, | ||
| 115 | .max = 24*24/6, | ||
| 116 | .ntrans = 1, | ||
| 117 | }; | ||
| 118 | |||
| 119 | Coordinate | ||
| 120 | coord_epud = { | ||
| 121 | .index = index_epud, | ||
| 122 | .cube = antindex_epud, | ||
| 123 | .check = check_epud, | ||
| 124 | .max = FACTORIAL8, | ||
| 125 | .ntrans = 1, | ||
| 126 | }; | ||
| 127 | |||
| 128 | Coordinate | ||
| 129 | coord_drud = { | ||
| 130 | .index = index_drud, | ||
| 131 | .cube = antindex_drud, | ||
| 132 | .check = check_drud, | ||
| 133 | .max = POW2TO11 * POW3TO7 * BINOM12ON4, | ||
| 134 | .ntrans = 1, | ||
| 135 | }; | ||
| 136 | |||
| 137 | Coordinate | ||
| 138 | coord_htr_drud = { | ||
| 139 | .index = index_htr_drud, | ||
| 140 | .cube = antindex_htr_drud, | ||
| 141 | .check = check_drud, | ||
| 142 | .max = BINOM8ON4 * 6 * BINOM8ON4, | ||
| 143 | .ntrans = 1, | ||
| 144 | }; | ||
| 145 | |||
| 146 | Coordinate | ||
| 147 | coord_htrfin = { | ||
| 148 | .index = index_htrfin, | ||
| 149 | .cube = antindex_htrfin, | ||
| 150 | .check = check_htr, | ||
| 151 | .max = 24 * 24 * 24 *24 * 24 / 6, /* should be /12 but it's ok */ | ||
| 152 | .ntrans = 1, | ||
| 153 | }; | ||
| 154 | |||
| 155 | Coordinate | ||
| 156 | coord_drud_eofb = { | ||
| 157 | .index = index_drud_eofb, | ||
| 158 | .cube = antindex_drud_eofb, | ||
| 159 | .check = check_drud, | ||
| 160 | .max = POW3TO7 * BINOM12ON4, | ||
| 161 | .ntrans = 1, | ||
| 162 | }; | ||
| 163 | |||
| 164 | /* Functions *****************************************************************/ | ||
| 165 | |||
| 166 | static Cube | ||
| 167 | antindex_eofb(uint64_t ind) | ||
| 168 | { | ||
| 169 | return (Cube){ .eofb = ind, .eorl = ind, .eoud = ind }; | ||
| 170 | } | ||
| 171 | |||
| 172 | static Cube | ||
| 173 | antindex_eofbepos(uint64_t ind) | ||
| 174 | { | ||
| 175 | Cube ret = {0}; | ||
| 176 | |||
| 177 | ret.eofb = ind % POW2TO11; | ||
| 178 | ret.epose = (ind / POW2TO11) * 24; | ||
| 179 | |||
| 180 | return ret; | ||
| 181 | } | ||
| 182 | |||
| 183 | static Cube | ||
| 184 | antindex_epud(uint64_t ind) | ||
| 185 | { | ||
| 186 | static bool initialized = false; | ||
| 187 | static Cube epud_aux[FACTORIAL8]; | ||
| 188 | int a[12]; | ||
| 189 | uint64_t ui; | ||
| 190 | CubeArray arr; | ||
| 191 | |||
| 192 | if (!initialized) { | ||
| 193 | a[FR] = FR; | ||
| 194 | a[FL] = FL; | ||
| 195 | a[BL] = BL; | ||
| 196 | a[BR] = BR; | ||
| 197 | for (ui = 0; ui < FACTORIAL8; ui++) { | ||
| 198 | index_to_perm(ui, 8, a); | ||
| 199 | arr.ep = a; | ||
| 200 | epud_aux[ui] = arrays_to_cube(&arr, pf_ep); | ||
| 201 | } | ||
| 202 | |||
| 203 | initialized = true; | ||
| 204 | } | ||
| 205 | |||
| 206 | return epud_aux[ind]; | ||
| 207 | } | ||
| 208 | |||
| 209 | static Cube | ||
| 210 | antindex_coud(uint64_t ind) | ||
| 211 | { | ||
| 212 | return (Cube){ .coud = ind, .corl = ind, .cofb = ind }; | ||
| 213 | } | ||
| 214 | |||
| 215 | static Cube | ||
| 216 | antindex_corners(uint64_t ind) | ||
| 217 | { | ||
| 218 | Cube c = {0}; | ||
| 219 | |||
| 220 | c.coud = ind / FACTORIAL8; | ||
| 221 | c.cp = ind % FACTORIAL8; | ||
| 222 | |||
| 223 | return c; | ||
| 224 | } | ||
| 225 | |||
| 226 | static Cube | ||
| 227 | antindex_cp(uint64_t ind) | ||
| 228 | { | ||
| 229 | Cube c = {0}; | ||
| 230 | |||
| 231 | c.cp = ind; | ||
| 232 | |||
| 233 | return c; | ||
| 234 | } | ||
| 235 | |||
| 236 | static Cube | ||
| 237 | antindex_cphtr(uint64_t ind) | ||
| 238 | { | ||
| 239 | return (Cube) { .cp = cphtr_right_rep[ind] }; | ||
| 240 | } | ||
| 241 | |||
| 242 | static Cube | ||
| 243 | antindex_cornershtr(uint64_t ind) | ||
| 244 | { | ||
| 245 | Cube c = antindex_cphtr(ind % (BINOM8ON4 * 6)); | ||
| 246 | |||
| 247 | c.coud = ind / (BINOM8ON4 * 6); | ||
| 248 | |||
| 249 | return c; | ||
| 250 | } | ||
| 251 | |||
| 252 | static Cube | ||
| 253 | antindex_cornershtrfin(uint64_t ind) | ||
| 254 | { | ||
| 255 | return (Cube){ .cp = cornershtrfin_ant[ind] }; | ||
| 256 | } | ||
| 257 | |||
| 258 | static Cube | ||
| 259 | antindex_drud(uint64_t ind) | ||
| 260 | { | ||
| 261 | uint64_t epos, eofb; | ||
| 262 | Cube c; | ||
| 263 | |||
| 264 | eofb = ind % POW2TO11; | ||
| 265 | epos = ind / (POW2TO11 * POW3TO7); | ||
| 266 | c = antindex_eofbepos(eofb + POW2TO11 * epos); | ||
| 267 | |||
| 268 | c.coud = (ind / POW2TO11) % POW3TO7; | ||
| 269 | |||
| 270 | return c; | ||
| 271 | } | ||
| 272 | |||
| 273 | static Cube | ||
| 274 | antindex_drud_eofb(uint64_t ind) | ||
| 275 | { | ||
| 276 | return antindex_drud(ind * POW2TO11); | ||
| 277 | } | ||
| 278 | |||
| 279 | static Cube | ||
| 280 | antindex_htr_drud(uint64_t ind) | ||
| 281 | { | ||
| 282 | Cube ret; | ||
| 283 | |||
| 284 | ret = antindex_cphtr(ind / BINOM8ON4); | ||
| 285 | ret.eposs = (ind % BINOM8ON4) * FACTORIAL4; | ||
| 286 | |||
| 287 | return ret; | ||
| 288 | } | ||
| 289 | |||
| 290 | static Cube | ||
| 291 | antindex_htrfin(uint64_t ind) | ||
| 292 | { | ||
| 293 | Cube ret; | ||
| 294 | |||
| 295 | ret = antindex_cornershtrfin(ind/(24*24*24)); | ||
| 296 | |||
| 297 | ret.eposm = ind % 24; | ||
| 298 | ind /= 24; | ||
| 299 | ret.eposs = ind % 24; | ||
| 300 | ind /= 24; | ||
| 301 | ret.epose = ind % 24; | ||
| 302 | |||
| 303 | return ret; | ||
| 304 | } | ||
| 305 | |||
| 306 | bool | ||
| 307 | check_centers(Cube cube) | ||
| 308 | { | ||
| 309 | return cube.cpos == 0; | ||
| 310 | } | ||
| 311 | |||
| 312 | bool | ||
| 313 | check_corners(Cube cube) | ||
| 314 | { | ||
| 315 | return cube.cp == 0 && cube.coud == 0; | ||
| 316 | } | ||
| 317 | |||
| 318 | bool | ||
| 319 | check_cp(Cube cube) | ||
| 320 | { | ||
| 321 | return cube.cp == 0; | ||
| 322 | } | ||
| 323 | |||
| 324 | bool | ||
| 325 | check_cphtr(Cube cube) | ||
| 326 | { | ||
| 327 | return index_cphtr(cube) == 0; | ||
| 328 | } | ||
| 329 | |||
| 330 | bool | ||
| 331 | check_cornershtr(Cube cube) | ||
| 332 | { | ||
| 333 | return cube.coud == 0 && index_cphtr(cube) == 0; | ||
| 334 | } | ||
| 335 | |||
| 336 | bool | ||
| 337 | check_coud(Cube cube) | ||
| 338 | { | ||
| 339 | return cube.coud == 0; | ||
| 340 | } | ||
| 341 | |||
| 342 | bool | ||
| 343 | check_drud(Cube cube) | ||
| 344 | { | ||
| 345 | return cube.eofb == 0 && cube.eorl == 0 && cube.coud == 0; | ||
| 346 | } | ||
| 347 | |||
| 348 | bool | ||
| 349 | check_htr(Cube cube) | ||
| 350 | { | ||
| 351 | return check_cornershtr(cube) && | ||
| 352 | cube.eofb == 0 && cube.eorl == 0 && cube.eoud == 0; | ||
| 353 | } | ||
| 354 | |||
| 355 | bool | ||
| 356 | check_drudfin_noE(Cube cube) | ||
| 357 | { | ||
| 358 | return cube.eposs == 0 && cube.eposm == 0 && cube.cp == 0; | ||
| 359 | } | ||
| 360 | |||
| 361 | bool | ||
| 362 | check_eofb(Cube cube) | ||
| 363 | { | ||
| 364 | return cube.eofb == 0; | ||
| 365 | } | ||
| 366 | |||
| 367 | bool | ||
| 368 | check_eofbepos(Cube cube) | ||
| 369 | { | ||
| 370 | return cube.eofb == 0 && cube.epose / 24 == 0; | ||
| 371 | } | ||
| 372 | |||
| 373 | bool | ||
| 374 | check_epose(Cube cube) | ||
| 375 | { | ||
| 376 | return cube.epose == 0; | ||
| 377 | } | ||
| 378 | |||
| 379 | bool | ||
| 380 | check_epud(Cube cube) | ||
| 381 | { | ||
| 382 | return cube.eposs == 0 && cube.eposm == 0; | ||
| 383 | } | ||
| 384 | |||
| 385 | bool | ||
| 386 | check_ep(Cube cube) | ||
| 387 | { | ||
| 388 | return cube.epose == 0 && cube.eposs == 0 && cube.eposm == 0; | ||
| 389 | } | ||
| 390 | |||
| 391 | bool | ||
| 392 | check_khuge(Cube cube) | ||
| 393 | { | ||
| 394 | return check_drud(cube) && cube.epose % 24 == 0; | ||
| 395 | } | ||
| 396 | |||
| 397 | bool | ||
| 398 | check_nothing(Cube cube) | ||
| 399 | { | ||
| 400 | return is_admissible(cube); /*TODO: maybe change?*/ | ||
| 401 | } | ||
| 402 | |||
| 403 | static uint64_t | ||
| 404 | index_eofb(Cube cube) | ||
| 405 | { | ||
| 406 | return cube.eofb; | ||
| 407 | } | ||
| 408 | |||
| 409 | static uint64_t | ||
| 410 | index_eofbepos(Cube cube) | ||
| 411 | { | ||
| 412 | return (cube.epose / FACTORIAL4) * POW2TO11 + cube.eofb; | ||
| 413 | } | ||
| 414 | |||
| 415 | static uint64_t | ||
| 416 | index_epud(Cube cube) | ||
| 417 | { | ||
| 418 | uint64_t ret; | ||
| 419 | CubeArray *arr = new_cubearray(cube, pf_ep); | ||
| 420 | |||
| 421 | ret = perm_to_index(arr->ep, 8); | ||
| 422 | free_cubearray(arr, pf_ep); | ||
| 423 | |||
| 424 | return ret; | ||
| 425 | } | ||
| 426 | |||
| 427 | static uint64_t | ||
| 428 | index_coud(Cube cube) | ||
| 429 | { | ||
| 430 | return cube.coud; | ||
| 431 | } | ||
| 432 | |||
| 433 | static uint64_t | ||
| 434 | index_corners(Cube cube) | ||
| 435 | { | ||
| 436 | return cube.coud * FACTORIAL8 + cube.cp; | ||
| 437 | } | ||
| 438 | |||
| 439 | static uint64_t | ||
| 440 | index_cp(Cube cube) | ||
| 441 | { | ||
| 442 | return cube.cp; | ||
| 443 | } | ||
| 444 | |||
| 445 | static uint64_t | ||
| 446 | index_cphtr(Cube cube) | ||
| 447 | { | ||
| 448 | return cphtr_right_cosets[cube.cp]; | ||
| 449 | } | ||
| 450 | |||
| 451 | static uint64_t | ||
| 452 | index_cornershtr(Cube cube) | ||
| 453 | { | ||
| 454 | return cube.coud * BINOM8ON4 * 6 + index_cphtr(cube); | ||
| 455 | } | ||
| 456 | |||
| 457 | static uint64_t | ||
| 458 | index_cornershtrfin(Cube cube) | ||
| 459 | { | ||
| 460 | return cornershtrfin_ind[cube.cp]; | ||
| 461 | } | ||
| 462 | |||
| 463 | static uint64_t | ||
| 464 | index_drud(Cube cube) | ||
| 465 | { | ||
| 466 | uint64_t a, b, c; | ||
| 467 | |||
| 468 | a = cube.eofb; | ||
| 469 | b = cube.coud; | ||
| 470 | c = cube.epose / FACTORIAL4; | ||
| 471 | |||
| 472 | b *= POW2TO11; | ||
| 473 | c *= POW2TO11 * POW3TO7; | ||
| 474 | |||
| 475 | return a + b + c; | ||
| 476 | } | ||
| 477 | |||
| 478 | static uint64_t | ||
| 479 | index_drud_eofb(Cube cube) | ||
| 480 | { | ||
| 481 | return index_drud(cube) / POW2TO11; | ||
| 482 | } | ||
| 483 | |||
| 484 | static uint64_t | ||
| 485 | index_htr_drud(Cube cube) | ||
| 486 | { | ||
| 487 | return index_cphtr(cube) * BINOM8ON4 + | ||
| 488 | (cube.eposs / FACTORIAL4) % BINOM8ON4; | ||
| 489 | } | ||
| 490 | |||
| 491 | static uint64_t | ||
| 492 | index_htrfin(Cube cube) | ||
| 493 | { | ||
| 494 | uint64_t epe, eps, epm, cp, ep; | ||
| 495 | |||
| 496 | epe = cube.epose % 24; | ||
| 497 | eps = cube.eposs % 24; | ||
| 498 | epm = cube.eposm % 24; | ||
| 499 | ep = (epe * 24 + eps) *24 + epm; | ||
| 500 | cp = index_cornershtrfin(cube); | ||
| 501 | |||
| 502 | return cp * 24 * 24 * 24 + ep; | ||
| 503 | } | ||
| 504 | |||
| 505 | /* Init functions implementation *********************************************/ | ||
| 506 | |||
| 507 | /* | ||
| 508 | * There is certainly a better way to do this, but for now I just use | ||
| 509 | * a "graph coloring" algorithm to compute the left cosets, and I compose | ||
| 510 | * with every possible cp to get the right cosets (it is possible that I am | ||
| 511 | * mixing up left and right). | ||
| 512 | * | ||
| 513 | * For doing it better "Mathematically", we need 3 things: | ||
| 514 | * - Checking that cp separates the orbits (UFR,UBL,DFL,DBR) and the other | ||
| 515 | * This is easy and it is done in the commented function cphtr_cp(). | ||
| 516 | * - Check that there is no ep/cp parity | ||
| 517 | * - Check that we are not in the "3c" case; this is the part I don't | ||
| 518 | * know how to do. | ||
| 519 | */ | ||
| 520 | static void | ||
| 521 | init_cphtr_cosets() | ||
| 522 | { | ||
| 523 | unsigned int i; | ||
| 524 | int c = 0, d = 0; | ||
| 525 | |||
| 526 | for (i = 0; i < FACTORIAL8; i++) { | ||
| 527 | cphtr_left_cosets[i] = -1; | ||
| 528 | cphtr_right_cosets[i] = -1; | ||
| 529 | } | ||
| 530 | |||
| 531 | /* First we compute left cosets with a bfs */ | ||
| 532 | for (i = 0; i < FACTORIAL8; i++) | ||
| 533 | if (cphtr_left_cosets[i] == -1) | ||
| 534 | init_cphtr_left_cosets_bfs(i, c++); | ||
| 535 | |||
| 536 | /* Then we compute right cosets using compose() */ | ||
| 537 | for (i = 0; i < FACTORIAL8; i++) | ||
| 538 | if (cphtr_right_cosets[i] == -1) | ||
| 539 | init_cphtr_right_cosets_color(i, d++); | ||
| 540 | } | ||
| 541 | |||
| 542 | static void | ||
| 543 | init_cphtr_left_cosets_bfs(int i, int c) | ||
| 544 | { | ||
| 545 | int j, jj, k, next[FACTORIAL8], next2[FACTORIAL8], n, n2; | ||
| 546 | Move moves[6] = {U2, D2, R2, L2, F2, B2}; | ||
| 547 | |||
| 548 | n = 1; | ||
| 549 | next[0] = i; | ||
| 550 | cphtr_left_cosets[i] = c; | ||
| 551 | |||
| 552 | while (n != 0) { | ||
| 553 | for (j = 0, n2 = 0; j < n; j++) { | ||
| 554 | for (k = 0; k < 6; k++) { | ||
| 555 | /*jj = cp_mtable[moves[k]][next[j]];*/ | ||
| 556 | /* TODO fix formatting */ | ||
| 557 | jj = apply_move(moves[k], (Cube){.cp=next[j]}).cp; | ||
| 558 | if (cphtr_left_cosets[jj] == -1) { | ||
| 559 | cphtr_left_cosets[jj] = c; | ||
| 560 | next2[n2++] = jj; | ||
| 561 | } | ||
| 562 | } | ||
| 563 | } | ||
| 564 | |||
| 565 | for (j = 0; j < n2; j++) | ||
| 566 | next[j] = next2[j]; | ||
| 567 | n = n2; | ||
| 568 | } | ||
| 569 | } | ||
| 570 | |||
| 571 | static void | ||
| 572 | init_cphtr_right_cosets_color(int i, int d) | ||
| 573 | { | ||
| 574 | int cp; | ||
| 575 | unsigned int j; | ||
| 576 | |||
| 577 | cphtr_right_rep[d] = i; | ||
| 578 | for (j = 0; j < FACTORIAL8; j++) { | ||
| 579 | if (cphtr_left_cosets[j] == 0) { | ||
| 580 | /* TODO: use antindexer, it's nicer */ | ||
| 581 | cp = compose((Cube){.cp = i}, (Cube){.cp = j}).cp; | ||
| 582 | cphtr_right_cosets[cp] = d; | ||
| 583 | } | ||
| 584 | } | ||
| 585 | } | ||
| 586 | |||
| 587 | static void | ||
| 588 | init_cornershtrfin() | ||
| 589 | { | ||
| 590 | unsigned int i, j; | ||
| 591 | int n, c; | ||
| 592 | Move m; | ||
| 593 | |||
| 594 | for (i = 0; i < FACTORIAL8; i++) | ||
| 595 | cornershtrfin_ind[i] = -1; | ||
| 596 | cornershtrfin_ind[0] = 0; | ||
| 597 | |||
| 598 | /* 10-pass, I think 5 is enough, but just in case */ | ||
| 599 | n = 1; | ||
| 600 | for (i = 0; i < 10; i++) { | ||
| 601 | for (j = 0; j < FACTORIAL8; j++) { | ||
| 602 | if (cornershtrfin_ind[j] == -1) | ||
| 603 | continue; | ||
| 604 | for (m = U; m < NMOVES; m++) { | ||
| 605 | if (moveset_htr(m)) { | ||
| 606 | c = apply_move(m, (Cube){.cp = j}).cp; | ||
| 607 | if (cornershtrfin_ind[c] == -1) { | ||
| 608 | cornershtrfin_ind[c] = n; | ||
| 609 | cornershtrfin_ant[n] = c; | ||
| 610 | n++; | ||
| 611 | } | ||
| 612 | } | ||
| 613 | } | ||
| 614 | } | ||
| 615 | } | ||
| 616 | } | ||
| 617 | |||
| 618 | void | ||
| 619 | init_coord() | ||
| 620 | { | ||
| 621 | static bool initialized = false; | ||
| 622 | if (initialized) | ||
| 623 | return; | ||
| 624 | initialized = true; | ||
| 625 | |||
| 626 | init_cphtr_cosets(); | ||
| 627 | init_cornershtrfin(); | ||
| 628 | } | ||
| 629 | |||
diff --git a/old/2021-11-10-beforeremovingchecker/coord.h b/old/2021-11-10-beforeremovingchecker/coord.h new file mode 100644 index 0000000..81c1e9c --- /dev/null +++ b/old/2021-11-10-beforeremovingchecker/coord.h | |||
| @@ -0,0 +1,40 @@ | |||
| 1 | #ifndef COORD_H | ||
| 2 | #define COORD_H | ||
| 3 | |||
| 4 | #include "trans.h" | ||
| 5 | |||
| 6 | extern Coordinate coord_eofb; | ||
| 7 | extern Coordinate coord_eofbepos; | ||
| 8 | extern Coordinate coord_coud; | ||
| 9 | extern Coordinate coord_cp; | ||
| 10 | extern Coordinate coord_cphtr; | ||
| 11 | extern Coordinate coord_corners; | ||
| 12 | extern Coordinate coord_cornershtr; | ||
| 13 | extern Coordinate coord_cornershtrfin; | ||
| 14 | extern Coordinate coord_epud; | ||
| 15 | extern Coordinate coord_drud; | ||
| 16 | extern Coordinate coord_drud_eofb; | ||
| 17 | extern Coordinate coord_htr_drud; | ||
| 18 | extern Coordinate coord_htrfin; | ||
| 19 | |||
| 20 | bool check_centers(Cube cube); | ||
| 21 | bool check_corners(Cube cube); | ||
| 22 | bool check_cp(Cube cube); | ||
| 23 | bool check_cphtr(Cube cube); | ||
| 24 | bool check_cornershtr(Cube cube); | ||
| 25 | bool check_coud(Cube cube); | ||
| 26 | bool check_drud(Cube cube); | ||
| 27 | bool check_htr(Cube cube); | ||
| 28 | bool check_drudfin_noE(Cube cube); | ||
| 29 | bool check_eofb(Cube cube); | ||
| 30 | bool check_eofbepos(Cube cube); | ||
| 31 | bool check_epose(Cube cube); | ||
| 32 | bool check_ep(Cube cube); | ||
| 33 | bool check_epud(Cube cube); | ||
| 34 | bool check_khuge(Cube cube); | ||
| 35 | bool check_nothing(Cube cube); | ||
| 36 | |||
| 37 | void init_coord(); | ||
| 38 | |||
| 39 | #endif | ||
| 40 | |||
diff --git a/old/2021-11-10-beforeremovingchecker/cube.c b/old/2021-11-10-beforeremovingchecker/cube.c new file mode 100644 index 0000000..b621d7b --- /dev/null +++ b/old/2021-11-10-beforeremovingchecker/cube.c | |||
| @@ -0,0 +1,716 @@ | |||
| 1 | #include "cube.h" | ||
| 2 | |||
| 3 | /* Local functions **********************************************************/ | ||
| 4 | |||
| 5 | static int array_ep_to_epos(int *ep, int *eps_solved); | ||
| 6 | static int epos_from_arrays(int *epos, int *ep); | ||
| 7 | |||
| 8 | /* Local functions implementation ********************************************/ | ||
| 9 | |||
| 10 | static int | ||
| 11 | array_ep_to_epos(int *ep, int *ss) | ||
| 12 | { | ||
| 13 | int epos[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; | ||
| 14 | int eps[4]; | ||
| 15 | int i, j, is; | ||
| 16 | |||
| 17 | for (i = 0, is = 0; i < 12; i++) { | ||
| 18 | for (j = 0; j < 4; j++) { | ||
| 19 | if (ep[i] == ss[j]) { | ||
| 20 | eps[is++] = j; | ||
| 21 | epos[i] = 1; | ||
| 22 | } | ||
| 23 | } | ||
| 24 | } | ||
| 25 | |||
| 26 | for (i = 0; i < 4; i++) | ||
| 27 | swap(&epos[ss[i]], &epos[i+8]); | ||
| 28 | |||
| 29 | return epos_from_arrays(epos, eps); | ||
| 30 | } | ||
| 31 | |||
| 32 | static int | ||
| 33 | epos_from_arrays(int *epos, int *ep) | ||
| 34 | { | ||
| 35 | return FACTORIAL4 * subset_to_index(epos,12,4) + perm_to_index(ep,4); | ||
| 36 | } | ||
| 37 | |||
| 38 | /* Public functions implementation *******************************************/ | ||
| 39 | |||
| 40 | Cube | ||
| 41 | arrays_to_cube(CubeArray *arr, PieceFilter f) | ||
| 42 | { | ||
| 43 | Cube ret = {0}; | ||
| 44 | |||
| 45 | static int epe_solved[4] = {FR, FL, BL, BR}; | ||
| 46 | static int eps_solved[4] = {UL, UR, DL, DR}; | ||
| 47 | static int epm_solved[4] = {UF, UB, DF, DB}; | ||
| 48 | |||
| 49 | if (f.epose) | ||
| 50 | ret.epose = array_ep_to_epos(arr->ep, epe_solved); | ||
| 51 | if (f.eposs) | ||
| 52 | ret.eposs = array_ep_to_epos(arr->ep, eps_solved); | ||
| 53 | if (f.eposm) | ||
| 54 | ret.eposm = array_ep_to_epos(arr->ep, epm_solved); | ||
| 55 | if (f.eofb) | ||
| 56 | ret.eofb = digit_array_to_int(arr->eofb, 11, 2); | ||
| 57 | if (f.eorl) | ||
| 58 | ret.eorl = digit_array_to_int(arr->eorl, 11, 2); | ||
| 59 | if (f.eoud) | ||
| 60 | ret.eoud = digit_array_to_int(arr->eoud, 11, 2); | ||
| 61 | if (f.cp) | ||
| 62 | ret.cp = perm_to_index(arr->cp, 8); | ||
| 63 | if (f.coud) | ||
| 64 | ret.coud = digit_array_to_int(arr->coud, 7, 3); | ||
| 65 | if (f.corl) | ||
| 66 | ret.corl = digit_array_to_int(arr->corl, 7, 3); | ||
| 67 | if (f.cofb) | ||
| 68 | ret.cofb = digit_array_to_int(arr->cofb, 7, 3); | ||
| 69 | if (f.cpos) | ||
| 70 | ret.cpos = perm_to_index(arr->cpos, 6); | ||
| 71 | |||
| 72 | return ret; | ||
| 73 | } | ||
| 74 | |||
| 75 | Cube | ||
| 76 | compose_filtered(Cube c2, Cube c1, PieceFilter f) | ||
| 77 | { | ||
| 78 | CubeArray *arr = new_cubearray(c2, f); | ||
| 79 | Cube ret; | ||
| 80 | |||
| 81 | ret = move_via_arrays(arr, c1, f); | ||
| 82 | free_cubearray(arr, f); | ||
| 83 | |||
| 84 | return ret; | ||
| 85 | } | ||
| 86 | |||
| 87 | void | ||
| 88 | cube_to_arrays(Cube cube, CubeArray *arr, PieceFilter f) | ||
| 89 | { | ||
| 90 | int i; | ||
| 91 | |||
| 92 | static int epe_solved[4] = {FR, FL, BL, BR}; | ||
| 93 | static int eps_solved[4] = {UL, UR, DL, DR}; | ||
| 94 | static int epm_solved[4] = {UF, UB, DF, DB}; | ||
| 95 | |||
| 96 | if (f.epose || f.eposs || f.eposm) | ||
| 97 | for (i = 0; i < 12; i++) | ||
| 98 | arr->ep[i] = -1; | ||
| 99 | |||
| 100 | if (f.epose) | ||
| 101 | epos_to_partial_ep(cube.epose, arr->ep, epe_solved); | ||
| 102 | if (f.eposs) | ||
| 103 | epos_to_partial_ep(cube.eposs, arr->ep, eps_solved); | ||
| 104 | if (f.eposm) | ||
| 105 | epos_to_partial_ep(cube.eposm, arr->ep, epm_solved); | ||
| 106 | if (f.eofb) | ||
| 107 | int_to_sum_zero_array(cube.eofb, 2, 12, arr->eofb); | ||
| 108 | if (f.eorl) | ||
| 109 | int_to_sum_zero_array(cube.eorl, 2, 12, arr->eorl); | ||
| 110 | if (f.eoud) | ||
| 111 | int_to_sum_zero_array(cube.eoud, 2, 12, arr->eoud); | ||
| 112 | if (f.cp) | ||
| 113 | index_to_perm(cube.cp, 8, arr->cp); | ||
| 114 | if (f.coud) | ||
| 115 | int_to_sum_zero_array(cube.coud, 3, 8, arr->coud); | ||
| 116 | if (f.corl) | ||
| 117 | int_to_sum_zero_array(cube.corl, 3, 8, arr->corl); | ||
| 118 | if (f.cofb) | ||
| 119 | int_to_sum_zero_array(cube.cofb, 3, 8, arr->cofb); | ||
| 120 | if (f.cpos) | ||
| 121 | index_to_perm(cube.cpos, 6, arr->cpos); | ||
| 122 | } | ||
| 123 | |||
| 124 | void | ||
| 125 | epos_to_partial_ep(int epos, int *ep, int *ss) | ||
| 126 | { | ||
| 127 | int i, is, eposs[12], eps[4]; | ||
| 128 | |||
| 129 | index_to_perm(epos % FACTORIAL4, 4, eps); | ||
| 130 | index_to_subset(epos / FACTORIAL4, 12, 4, eposs); | ||
| 131 | |||
| 132 | for (i = 0; i < 4; i++) | ||
| 133 | swap(&eposs[ss[i]], &eposs[i+8]); | ||
| 134 | |||
| 135 | for (i = 0, is = 0; i < 12; i++) | ||
| 136 | if (eposs[i]) | ||
| 137 | ep[i] = ss[eps[is++]]; | ||
| 138 | } | ||
| 139 | |||
| 140 | void | ||
| 141 | free_cubearray(CubeArray *arr, PieceFilter f) | ||
| 142 | { | ||
| 143 | if (f.epose || f.eposs || f.eposm) | ||
| 144 | free(arr->ep); | ||
| 145 | if (f.eofb) | ||
| 146 | free(arr->eofb); | ||
| 147 | if (f.eorl) | ||
| 148 | free(arr->eorl); | ||
| 149 | if (f.eoud) | ||
| 150 | free(arr->eoud); | ||
| 151 | if (f.cp) | ||
| 152 | free(arr->cp); | ||
| 153 | if (f.coud) | ||
| 154 | free(arr->coud); | ||
| 155 | if (f.corl) | ||
| 156 | free(arr->corl); | ||
| 157 | if (f.cofb) | ||
| 158 | free(arr->cofb); | ||
| 159 | if (f.cpos) | ||
| 160 | free(arr->cpos); | ||
| 161 | |||
| 162 | free(arr); | ||
| 163 | } | ||
| 164 | |||
| 165 | Cube | ||
| 166 | move_via_arrays(CubeArray *arr, Cube c, PieceFilter f) | ||
| 167 | { | ||
| 168 | CubeArray *arrc = new_cubearray(c, f); | ||
| 169 | Cube ret; | ||
| 170 | |||
| 171 | if (f.epose || f.eposs || f.eposm) | ||
| 172 | apply_permutation(arr->ep, arrc->ep, 12); | ||
| 173 | |||
| 174 | if (f.eofb) { | ||
| 175 | apply_permutation(arr->ep, arrc->eofb, 12); | ||
| 176 | sum_arrays_mod(arr->eofb, arrc->eofb, 12, 2); | ||
| 177 | } | ||
| 178 | |||
| 179 | if (f.eorl) { | ||
| 180 | apply_permutation(arr->ep, arrc->eorl, 12); | ||
| 181 | sum_arrays_mod(arr->eorl, arrc->eorl, 12, 2); | ||
| 182 | } | ||
| 183 | |||
| 184 | if (f.eoud) { | ||
| 185 | apply_permutation(arr->ep, arrc->eoud, 12); | ||
| 186 | sum_arrays_mod(arr->eoud, arrc->eoud, 12, 2); | ||
| 187 | } | ||
| 188 | |||
| 189 | if (f.cp) | ||
| 190 | apply_permutation(arr->cp, arrc->cp, 8); | ||
| 191 | |||
| 192 | if (f.coud) { | ||
| 193 | apply_permutation(arr->cp, arrc->coud, 8); | ||
| 194 | sum_arrays_mod(arr->coud, arrc->coud, 8, 3); | ||
| 195 | } | ||
| 196 | |||
| 197 | if (f.corl) { | ||
| 198 | apply_permutation(arr->cp, arrc->corl, 8); | ||
| 199 | sum_arrays_mod(arr->corl, arrc->corl, 8, 3); | ||
| 200 | } | ||
| 201 | |||
| 202 | if (f.cofb) { | ||
| 203 | apply_permutation(arr->cp, arrc->cofb, 8); | ||
| 204 | sum_arrays_mod(arr->cofb, arrc->cofb, 8, 3); | ||
| 205 | } | ||
| 206 | |||
| 207 | if (f.cpos) | ||
| 208 | apply_permutation(arr->cpos, arrc->cpos, 6); | ||
| 209 | |||
| 210 | ret = arrays_to_cube(arrc, f); | ||
| 211 | free_cubearray(arrc, f); | ||
| 212 | |||
| 213 | return ret; | ||
| 214 | } | ||
| 215 | |||
| 216 | CubeArray * | ||
| 217 | new_cubearray(Cube cube, PieceFilter f) | ||
| 218 | { | ||
| 219 | CubeArray *arr = malloc(sizeof(CubeArray)); | ||
| 220 | |||
| 221 | if (f.epose || f.eposs || f.eposm) | ||
| 222 | arr->ep = malloc(12 * sizeof(int)); | ||
| 223 | if (f.eofb) | ||
| 224 | arr->eofb = malloc(12 * sizeof(int)); | ||
| 225 | if (f.eorl) | ||
| 226 | arr->eorl = malloc(12 * sizeof(int)); | ||
| 227 | if (f.eoud) | ||
| 228 | arr->eoud = malloc(12 * sizeof(int)); | ||
| 229 | if (f.cp) | ||
| 230 | arr->cp = malloc(8 * sizeof(int)); | ||
| 231 | if (f.coud) | ||
| 232 | arr->coud = malloc(8 * sizeof(int)); | ||
| 233 | if (f.corl) | ||
| 234 | arr->corl = malloc(8 * sizeof(int)); | ||
| 235 | if (f.cofb) | ||
| 236 | arr->cofb = malloc(8 * sizeof(int)); | ||
| 237 | if (f.cpos) | ||
| 238 | arr->cpos = malloc(6 * sizeof(int)); | ||
| 239 | |||
| 240 | cube_to_arrays(cube, arr, f); | ||
| 241 | |||
| 242 | return arr; | ||
| 243 | } | ||
| 244 | |||
| 245 | |||
| 246 | /* TODO: consider if this is good here or better in coord.c | ||
| 247 | in any case it is used in transformation init at the moment */ | ||
| 248 | Cube | ||
| 249 | admissible_ep(Cube cube, PieceFilter f) | ||
| 250 | { | ||
| 251 | CubeArray *arr = new_cubearray(cube, f); | ||
| 252 | Cube ret; | ||
| 253 | bool used[12] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; | ||
| 254 | int i, j; | ||
| 255 | |||
| 256 | for (i = 0; i < 12; i++) | ||
| 257 | if (arr->ep[i] != -1) | ||
| 258 | used[arr->ep[i]] = true; | ||
| 259 | |||
| 260 | for (i = 0, j = 0; i < 12; i++) { | ||
| 261 | for ( ; j < 11 && used[j]; j++); | ||
| 262 | if (arr->ep[i] == -1) | ||
| 263 | arr->ep[i] = j++; | ||
| 264 | } | ||
| 265 | |||
| 266 | ret = arrays_to_cube(arr, pf_ep); | ||
| 267 | free_cubearray(arr, f); | ||
| 268 | |||
| 269 | return ret; | ||
| 270 | } | ||
| 271 | |||
| 272 | Cube | ||
| 273 | compose(Cube c2, Cube c1) | ||
| 274 | { | ||
| 275 | return compose_filtered(c2, c1, pf_all); | ||
| 276 | } | ||
| 277 | |||
| 278 | int | ||
| 279 | edge_slice(Edge e) { | ||
| 280 | if (e < 0 || e > 11) | ||
| 281 | return -1; | ||
| 282 | |||
| 283 | if (e == FR || e == FL || e == BL || e == BR) | ||
| 284 | return 0; | ||
| 285 | if (e == UR || e == UL || e == DR || e == DL) | ||
| 286 | return 1; | ||
| 287 | |||
| 288 | return 2; | ||
| 289 | } | ||
| 290 | |||
| 291 | bool | ||
| 292 | equal(Cube c1, Cube c2) | ||
| 293 | { | ||
| 294 | return c1.eofb == c2.eofb && | ||
| 295 | c1.epose == c2.epose && | ||
| 296 | c1.eposs == c2.eposs && | ||
| 297 | c1.eposm == c2.eposm && | ||
| 298 | c1.coud == c2.coud && | ||
| 299 | c1.cp == c2.cp && | ||
| 300 | c1.cpos == c2.cpos; | ||
| 301 | } | ||
| 302 | |||
| 303 | Cube | ||
| 304 | inverse_cube(Cube cube) | ||
| 305 | { | ||
| 306 | CubeArray *arr = new_cubearray(cube, pf_all); | ||
| 307 | CubeArray *inv = new_cubearray((Cube){0}, pf_all); | ||
| 308 | Cube ret; | ||
| 309 | int i; | ||
| 310 | |||
| 311 | for (i = 0; i < 12; i++) { | ||
| 312 | inv->ep[arr->ep[i]] = i; | ||
| 313 | inv->eofb[arr->ep[i]] = arr->eofb[i]; | ||
| 314 | inv->eorl[arr->ep[i]] = arr->eorl[i]; | ||
| 315 | inv->eoud[arr->ep[i]] = arr->eoud[i]; | ||
| 316 | } | ||
| 317 | |||
| 318 | for (i = 0; i < 8; i++) { | ||
| 319 | inv->cp[arr->cp[i]] = i; | ||
| 320 | inv->coud[arr->cp[i]] = (3 - arr->coud[i]) % 3; | ||
| 321 | inv->corl[arr->cp[i]] = (3 - arr->corl[i]) % 3; | ||
| 322 | inv->cofb[arr->cp[i]] = (3 - arr->cofb[i]) % 3; | ||
| 323 | } | ||
| 324 | |||
| 325 | for (int i = 0; i < 6; i++) | ||
| 326 | inv->cpos[arr->cpos[i]] = i; | ||
| 327 | |||
| 328 | ret = arrays_to_cube(inv, pf_all); | ||
| 329 | free_cubearray(arr, pf_all); | ||
| 330 | free_cubearray(inv, pf_all); | ||
| 331 | |||
| 332 | return ret; | ||
| 333 | } | ||
| 334 | |||
| 335 | bool | ||
| 336 | is_admissible(Cube cube) | ||
| 337 | { | ||
| 338 | /* TODO: this should check consistency of different orientations */ | ||
| 339 | /* TODO: check that centers are opposite and admissible */ | ||
| 340 | |||
| 341 | CubeArray *a = new_cubearray(cube, pf_all); | ||
| 342 | int parity; | ||
| 343 | bool perm; | ||
| 344 | |||
| 345 | perm = is_perm(a->ep, 12) && | ||
| 346 | is_perm(a->cp, 8) && | ||
| 347 | is_perm(a->cpos, 6); | ||
| 348 | parity = perm_sign(a->ep, 12) + | ||
| 349 | perm_sign(a->cp, 8) + | ||
| 350 | perm_sign(a->cpos, 6); | ||
| 351 | |||
| 352 | return perm && parity % 2 == 0; | ||
| 353 | } | ||
| 354 | |||
| 355 | bool | ||
| 356 | is_solved(Cube cube) | ||
| 357 | { | ||
| 358 | /* TODO: move somewhere else, like in solve.c | ||
| 359 | int i; | ||
| 360 | if (reorient) { | ||
| 361 | for (i = 0; i < NROTATIONS; i++) | ||
| 362 | if (is_solved(apply_alg(rotation_algs[i], cube),false)) | ||
| 363 | return true; | ||
| 364 | return false; | ||
| 365 | } else { | ||
| 366 | return equal(cube, (Cube){0}); | ||
| 367 | } | ||
| 368 | */ | ||
| 369 | |||
| 370 | return equal(cube, (Cube){0}); | ||
| 371 | } | ||
| 372 | |||
| 373 | bool | ||
| 374 | is_solved_block(Cube cube, Block block) | ||
| 375 | { | ||
| 376 | int i; | ||
| 377 | |||
| 378 | for (i = 0; i < 12; i++) | ||
| 379 | if (block.edge[i] && !is_solved_edge(cube, i)) | ||
| 380 | return false; | ||
| 381 | for (i = 0; i < 8; i++) | ||
| 382 | if (block.corner[i] && !is_solved_corner(cube, i)) | ||
| 383 | return false; | ||
| 384 | for (i = 0; i < 6; i++) | ||
| 385 | if (block.center[i] && !is_solved_center(cube, i)) | ||
| 386 | return false; | ||
| 387 | |||
| 388 | return true; | ||
| 389 | } | ||
| 390 | |||
| 391 | bool | ||
| 392 | is_solved_center(Cube cube, Center c) | ||
| 393 | { | ||
| 394 | return what_center_at(cube, c) == c; | ||
| 395 | } | ||
| 396 | |||
| 397 | bool | ||
| 398 | is_solved_corner(Cube cube, Corner c) | ||
| 399 | { | ||
| 400 | return what_corner_at(cube, c) == c && | ||
| 401 | what_orientation_corner(cube.coud, c); | ||
| 402 | } | ||
| 403 | |||
| 404 | bool | ||
| 405 | is_solved_edge(Cube cube, Edge e) | ||
| 406 | { | ||
| 407 | return what_edge_at(cube, e) == e && | ||
| 408 | what_orientation_edge(cube.eofb, e); | ||
| 409 | } | ||
| 410 | |||
| 411 | int | ||
| 412 | piece_orientation(Cube cube, int piece, char *orientation) | ||
| 413 | { | ||
| 414 | int arr[12], n, b, x; | ||
| 415 | |||
| 416 | if (!strcmp(orientation, "eofb")) { | ||
| 417 | x = cube.eofb; | ||
| 418 | n = 12; | ||
| 419 | b = 2; | ||
| 420 | } else if (!strcmp(orientation, "eorl")) { | ||
| 421 | x = cube.eorl; | ||
| 422 | n = 12; | ||
| 423 | b = 2; | ||
| 424 | } else if (!strcmp(orientation, "eoud")) { | ||
| 425 | x = cube.eoud; | ||
| 426 | n = 12; | ||
| 427 | b = 2; | ||
| 428 | } else if (!strcmp(orientation, "coud")) { | ||
| 429 | x = cube.coud; | ||
| 430 | n = 8; | ||
| 431 | b = 3; | ||
| 432 | } else if (!strcmp(orientation, "corl")) { | ||
| 433 | x = cube.corl; | ||
| 434 | n = 8; | ||
| 435 | b = 3; | ||
| 436 | } else if (!strcmp(orientation, "cofb")) { | ||
| 437 | x = cube.cofb; | ||
| 438 | n = 8; | ||
| 439 | b = 3; | ||
| 440 | } else { | ||
| 441 | return -1; | ||
| 442 | } | ||
| 443 | |||
| 444 | int_to_sum_zero_array(x, b, n, arr); | ||
| 445 | if (piece < n) | ||
| 446 | return arr[piece]; | ||
| 447 | |||
| 448 | return -1; | ||
| 449 | } | ||
| 450 | |||
| 451 | void | ||
| 452 | print_cube(Cube cube) | ||
| 453 | { | ||
| 454 | static char edge_string[12][7] = { | ||
| 455 | [UF] = "UF", [UL] = "UL", [UB] = "UB", [UR] = "UR", | ||
| 456 | [DF] = "DF", [DL] = "DL", [DB] = "DB", [DR] = "DR", | ||
| 457 | [FR] = "FR", [FL] = "FL", [BL] = "BL", [BR] = "BR" | ||
| 458 | }; | ||
| 459 | |||
| 460 | static char corner_string[8][7] = { | ||
| 461 | [UFR] = "UFR", [UFL] = "UFL", [UBL] = "UBL", [UBR] = "UBR", | ||
| 462 | [DFR] = "DFR", [DFL] = "DFL", [DBL] = "DBL", [DBR] = "DBR" | ||
| 463 | }; | ||
| 464 | |||
| 465 | static char center_string[6][7] = { | ||
| 466 | [U_center] = "U", [D_center] = "D", | ||
| 467 | [R_center] = "R", [L_center] = "L", | ||
| 468 | [F_center] = "F", [B_center] = "B" | ||
| 469 | }; | ||
| 470 | |||
| 471 | for (int i = 0; i < 12; i++) | ||
| 472 | printf(" %s ", edge_string[what_edge_at(cube, i)]); | ||
| 473 | printf("\n"); | ||
| 474 | |||
| 475 | for (int i = 0; i < 12; i++) | ||
| 476 | printf(" %d ", what_orientation_edge(cube.eofb, i)); | ||
| 477 | printf("\n"); | ||
| 478 | |||
| 479 | for (int i = 0; i < 8; i++) | ||
| 480 | printf("%s ", corner_string[what_corner_at(cube, i)]); | ||
| 481 | printf("\n"); | ||
| 482 | |||
| 483 | for (int i = 0; i < 8; i++) | ||
| 484 | printf(" %d ", what_orientation_corner(cube.coud, i)); | ||
| 485 | printf("\n"); | ||
| 486 | |||
| 487 | for (int i = 0; i < 6; i++) | ||
| 488 | printf(" %s ", center_string[what_center_at(cube, i)]); | ||
| 489 | printf("\n"); | ||
| 490 | } | ||
| 491 | |||
| 492 | Cube | ||
| 493 | random_cube() | ||
| 494 | { | ||
| 495 | CubeArray *arr = new_cubearray((Cube){0}, pf_4val); | ||
| 496 | Cube ret; | ||
| 497 | int ep, cp, eo, co; | ||
| 498 | |||
| 499 | ep = rand() % FACTORIAL12; | ||
| 500 | cp = rand() % FACTORIAL8; | ||
| 501 | eo = rand() % POW2TO11; | ||
| 502 | co = rand() % POW3TO7; | ||
| 503 | |||
| 504 | index_to_perm(ep, 12, arr->ep); | ||
| 505 | index_to_perm(cp, 8, arr->cp); | ||
| 506 | int_to_sum_zero_array(eo, 2, 12, arr->eofb); | ||
| 507 | int_to_sum_zero_array(co, 3, 8, arr->coud); | ||
| 508 | |||
| 509 | if (perm_sign(arr->ep, 12) != perm_sign(arr->cp, 8)) | ||
| 510 | swap(&(arr->ep[0]), &(arr->ep[1])); | ||
| 511 | |||
| 512 | ret = arrays_to_cube(arr, pf_4val); | ||
| 513 | free_cubearray(arr, pf_4val); | ||
| 514 | |||
| 515 | return ret; | ||
| 516 | } | ||
| 517 | |||
| 518 | Center | ||
| 519 | what_center_at(Cube cube, Center c) | ||
| 520 | { | ||
| 521 | static bool initialized = false; | ||
| 522 | static Center aux[FACTORIAL6][6]; | ||
| 523 | static int i; | ||
| 524 | static unsigned int ui; | ||
| 525 | static CubeArray *arr; | ||
| 526 | |||
| 527 | if (!initialized) { | ||
| 528 | for (ui = 0; ui < FACTORIAL6; ui++) { | ||
| 529 | arr = new_cubearray((Cube){.cpos = ui}, pf_cpos); | ||
| 530 | for (i = 0; i < 6; i++) | ||
| 531 | aux[ui][i] = arr->cpos[i]; | ||
| 532 | free_cubearray(arr, pf_cpos); | ||
| 533 | } | ||
| 534 | |||
| 535 | initialized = true; | ||
| 536 | } | ||
| 537 | |||
| 538 | return aux[cube.cpos][c]; | ||
| 539 | } | ||
| 540 | |||
| 541 | Corner | ||
| 542 | what_corner_at(Cube cube, Corner c) | ||
| 543 | { | ||
| 544 | static bool initialized = false; | ||
| 545 | static Corner aux[FACTORIAL8][8]; | ||
| 546 | static int i; | ||
| 547 | static unsigned int ui; | ||
| 548 | static CubeArray *arr; | ||
| 549 | |||
| 550 | if (!initialized) { | ||
| 551 | for (ui = 0; ui < FACTORIAL8; ui++) { | ||
| 552 | arr = new_cubearray((Cube){.cp = ui}, pf_cp); | ||
| 553 | for (i = 0; i < 8; i++) | ||
| 554 | aux[ui][i] = arr->cp[i]; | ||
| 555 | free_cubearray(arr, pf_cp); | ||
| 556 | } | ||
| 557 | |||
| 558 | initialized = true; | ||
| 559 | } | ||
| 560 | |||
| 561 | return aux[cube.cp][c]; | ||
| 562 | } | ||
| 563 | |||
| 564 | Edge | ||
| 565 | what_edge_at(Cube cube, Edge e) | ||
| 566 | { | ||
| 567 | Edge ret; | ||
| 568 | CubeArray *arr = new_cubearray(cube, pf_ep); | ||
| 569 | |||
| 570 | ret = arr->ep[e]; | ||
| 571 | |||
| 572 | free_cubearray(arr, pf_ep); | ||
| 573 | return ret; | ||
| 574 | } | ||
| 575 | |||
| 576 | int | ||
| 577 | what_orientation_corner(int co, Corner c) | ||
| 578 | { | ||
| 579 | static bool initialized = false; | ||
| 580 | static int auxlast[POW3TO7]; | ||
| 581 | static int auxarr[8]; | ||
| 582 | static unsigned int ui; | ||
| 583 | |||
| 584 | if (!initialized) { | ||
| 585 | for (ui = 0; ui < POW3TO7; ui++) { | ||
| 586 | int_to_sum_zero_array(ui, 3, 8, auxarr); | ||
| 587 | auxlast[ui] = auxarr[7]; | ||
| 588 | } | ||
| 589 | |||
| 590 | initialized = true; | ||
| 591 | } | ||
| 592 | |||
| 593 | if (c < 7) | ||
| 594 | return (co / powint(3, c)) % 3; | ||
| 595 | else | ||
| 596 | return auxlast[co]; | ||
| 597 | } | ||
| 598 | |||
| 599 | int | ||
| 600 | what_orientation_edge(int eo, Edge e) | ||
| 601 | { | ||
| 602 | static bool initialized = false; | ||
| 603 | static int auxlast[POW2TO11]; | ||
| 604 | static int auxarr[12]; | ||
| 605 | static unsigned int ui; | ||
| 606 | |||
| 607 | if (!initialized) { | ||
| 608 | for (ui = 0; ui < POW2TO11; ui++) { | ||
| 609 | int_to_sum_zero_array(ui, 2, 12, auxarr); | ||
| 610 | auxlast[ui] = auxarr[11]; | ||
| 611 | } | ||
| 612 | |||
| 613 | initialized = true; | ||
| 614 | } | ||
| 615 | |||
| 616 | if (e < 11) | ||
| 617 | return (eo & (1 << e)) ? 1 : 0; | ||
| 618 | else | ||
| 619 | return auxlast[eo]; | ||
| 620 | } | ||
| 621 | |||
| 622 | Center | ||
| 623 | where_is_center(Cube cube, Center c) | ||
| 624 | { | ||
| 625 | static bool initialized = false; | ||
| 626 | static Center aux[FACTORIAL6][6]; | ||
| 627 | static int i; | ||
| 628 | static unsigned int ui; | ||
| 629 | static CubeArray *arr; | ||
| 630 | |||
| 631 | if (!initialized) { | ||
| 632 | for (ui = 0; ui < FACTORIAL6; ui++) { | ||
| 633 | arr = new_cubearray((Cube){.cpos = ui}, pf_cpos); | ||
| 634 | for (i = 0; i < 6; i++) | ||
| 635 | aux[ui][arr->cpos[i]] = i; | ||
| 636 | free_cubearray(arr, pf_cpos); | ||
| 637 | } | ||
| 638 | |||
| 639 | initialized = true; | ||
| 640 | } | ||
| 641 | |||
| 642 | return aux[cube.cpos][c]; | ||
| 643 | } | ||
| 644 | |||
| 645 | Corner | ||
| 646 | where_is_corner(Cube cube, Corner c) | ||
| 647 | { | ||
| 648 | static bool initialized = false; | ||
| 649 | static Corner aux[FACTORIAL8][8]; | ||
| 650 | static int i; | ||
| 651 | static unsigned int ui; | ||
| 652 | static CubeArray *arr; | ||
| 653 | |||
| 654 | if (!initialized) { | ||
| 655 | for (ui = 0; ui < FACTORIAL8; ui++) { | ||
| 656 | arr = new_cubearray((Cube){.cp = ui}, pf_cp); | ||
| 657 | for (i = 0; i < 8; i++) | ||
| 658 | aux[ui][arr->cp[i]] = i; | ||
| 659 | free_cubearray(arr, pf_cp); | ||
| 660 | } | ||
| 661 | |||
| 662 | initialized = true; | ||
| 663 | } | ||
| 664 | return aux[cube.cp][c]; | ||
| 665 | } | ||
| 666 | |||
| 667 | Edge | ||
| 668 | where_is_edge(Cube cube, Edge e) | ||
| 669 | { | ||
| 670 | /* TODO: when I wrote this code I forgot to add the final | ||
| 671 | part, and now I can't remember how it was supposed to | ||
| 672 | work (i.e. how to recover the location of the edge | ||
| 673 | from these tables. I think it is either very easy or | ||
| 674 | wrong, in any case it is not a priority now. | ||
| 675 | Future Seba can deal with it. | ||
| 676 | |||
| 677 | static bool initialized = false; | ||
| 678 | static Edge aux[3][FACTORIAL12/FACTORIAL8][12]; | ||
| 679 | static int i; | ||
| 680 | static unsigned int ui; | ||
| 681 | static CubeArray *arr; | ||
| 682 | |||
| 683 | if (!initialized) { | ||
| 684 | for (ui = 0; ui < FACTORIAL12/FACTORIAL8; ui++) { | ||
| 685 | arr = new_cubearray((Cube){.epose = ui}, pf_e); | ||
| 686 | for (i = 0; i < 12; i++) | ||
| 687 | if (edge_slice(arr->ep[i]) == 0) | ||
| 688 | aux[0][ui][arr->ep[i]] = i; | ||
| 689 | free_cubearray(arr, pf_e); | ||
| 690 | |||
| 691 | arr = new_cubearray((Cube){.eposs = ui}, pf_s); | ||
| 692 | for (i = 0; i < 12; i++) | ||
| 693 | if (edge_slice(arr->ep[i]) == 1) | ||
| 694 | aux[1][ui][arr->ep[i]] = i; | ||
| 695 | free_cubearray(arr, pf_s); | ||
| 696 | |||
| 697 | arr = new_cubearray((Cube){.eposm = ui}, pf_m); | ||
| 698 | for (i = 0; i < 12; i++) | ||
| 699 | if (edge_slice(arr->ep[i]) == 2) | ||
| 700 | aux[2][ui][arr->ep[i]] = i; | ||
| 701 | free_cubearray(arr, pf_m); | ||
| 702 | } | ||
| 703 | |||
| 704 | initialized = true; | ||
| 705 | } | ||
| 706 | */ | ||
| 707 | |||
| 708 | int i; | ||
| 709 | CubeArray *arr = new_cubearray(cube, pf_ep); | ||
| 710 | |||
| 711 | for (i = 0; i < 12; i++) | ||
| 712 | if ((Edge)arr->ep[i] == e) | ||
| 713 | return i; | ||
| 714 | |||
| 715 | return -1; | ||
| 716 | } | ||
diff --git a/old/2021-11-10-beforeremovingchecker/cube.h b/old/2021-11-10-beforeremovingchecker/cube.h new file mode 100644 index 0000000..98657ab --- /dev/null +++ b/old/2021-11-10-beforeremovingchecker/cube.h | |||
| @@ -0,0 +1,40 @@ | |||
| 1 | #ifndef CUBE_H | ||
| 2 | #define CUBE_H | ||
| 3 | |||
| 4 | #include <stdio.h> | ||
| 5 | #include <time.h> | ||
| 6 | |||
| 7 | #include "pf.h" | ||
| 8 | #include "utils.h" | ||
| 9 | |||
| 10 | Cube admissible_ep(Cube cube, PieceFilter f); /* TODO: move? */ | ||
| 11 | Cube arrays_to_cube(CubeArray *arr, PieceFilter f); /* TODO: remove */ | ||
| 12 | Cube compose(Cube c2, Cube c1); /* Use c2 as an alg on c1 */ | ||
| 13 | Cube compose_filtered(Cube c2, Cube c1, PieceFilter f); | ||
| 14 | void cube_to_arrays(Cube cube, CubeArray *arr, PieceFilter f); | ||
| 15 | int edge_slice(Edge e); /* E=0, S=1, M=2 */ | ||
| 16 | bool equal(Cube c1, Cube c2); | ||
| 17 | Cube inverse_cube(Cube cube); | ||
| 18 | bool is_admissible(Cube cube); | ||
| 19 | bool is_solved(Cube cube); | ||
| 20 | bool block_solved(Cube cube, Block); /*TODO: rename to is_solved_block()*/ | ||
| 21 | bool is_solved_center(Cube cube, Center c); | ||
| 22 | bool is_solved_corner(Cube cube, Corner c); | ||
| 23 | bool is_solved_edge(Cube cube, Edge e); | ||
| 24 | void epos_to_partial_ep(int epos, int *ep, int *ss); | ||
| 25 | void free_cubearray(CubeArray *arr, PieceFilter f); /* TODO: remove */ | ||
| 26 | Cube move_via_arrays(CubeArray *arr, Cube c, PieceFilter pf); | ||
| 27 | CubeArray * new_cubearray(Cube cube, PieceFilter f); /* TODO: remove */ | ||
| 28 | void print_cube(Cube cube); | ||
| 29 | Cube random_cube(); | ||
| 30 | Center what_center_at(Cube cube, Center c); | ||
| 31 | Corner what_corner_at(Cube cube, Corner c); | ||
| 32 | Edge what_edge_at(Cube cube, Edge e); | ||
| 33 | int what_orientation_corner(int co, Corner c); | ||
| 34 | int what_orientation_edge(int eo, Edge e); | ||
| 35 | Center where_is_center(Cube cube, Center c); | ||
| 36 | Corner where_is_corner(Cube cube, Corner c); | ||
| 37 | Edge where_is_edge(Cube cube, Edge e); | ||
| 38 | |||
| 39 | #endif | ||
| 40 | |||
diff --git a/old/2021-11-10-beforeremovingchecker/cubetypes.h b/old/2021-11-10-beforeremovingchecker/cubetypes.h new file mode 100644 index 0000000..38a6f8d --- /dev/null +++ b/old/2021-11-10-beforeremovingchecker/cubetypes.h | |||
| @@ -0,0 +1,298 @@ | |||
| 1 | #ifndef CUBETYPES_H | ||
| 2 | #define CUBETYPES_H | ||
| 3 | |||
| 4 | #include <stdbool.h> | ||
| 5 | #include <stdint.h> | ||
| 6 | |||
| 7 | #define NMOVES 55 /* Actually 55, but one is NULLMOVE */ | ||
| 8 | #define NTRANS 48 | ||
| 9 | #define NROTATIONS 24 | ||
| 10 | |||
| 11 | |||
| 12 | /* Typedefs ******************************************************************/ | ||
| 13 | |||
| 14 | typedef enum center Center; | ||
| 15 | typedef enum corner Corner; | ||
| 16 | typedef enum edge Edge; | ||
| 17 | typedef enum move Move; | ||
| 18 | typedef enum trans Trans; | ||
| 19 | |||
| 20 | typedef struct alg Alg; | ||
| 21 | typedef struct alglist AlgList; | ||
| 22 | typedef struct alglistnode AlgListNode; | ||
| 23 | typedef struct block Block; | ||
| 24 | typedef struct command Command; | ||
| 25 | typedef struct commandargs CommandArgs; | ||
| 26 | typedef struct coordinate Coordinate; | ||
| 27 | typedef struct cube Cube; | ||
| 28 | typedef struct cubearray CubeArray; | ||
| 29 | typedef struct cubetarget CubeTarget; | ||
| 30 | typedef struct dfsdata DfsData; | ||
| 31 | typedef struct piecefilter PieceFilter; | ||
| 32 | typedef struct prunedata PruneData; | ||
| 33 | typedef struct solveoptions SolveOptions; | ||
| 34 | typedef struct step Step; | ||
| 35 | typedef struct symdata SymData; | ||
| 36 | |||
| 37 | typedef Cube (*AntiIndexer) (uint64_t); | ||
| 38 | typedef bool (*Checker) (Cube); | ||
| 39 | typedef int (*Estimator) (CubeTarget); | ||
| 40 | typedef bool (*Validator) (Alg *); | ||
| 41 | typedef void (*Exec) (CommandArgs *); | ||
| 42 | typedef uint64_t (*Indexer) (Cube); | ||
| 43 | typedef bool (*Moveset) (Move); | ||
| 44 | typedef CommandArgs * (*ArgParser) (int, char **); | ||
| 45 | typedef Trans (*TransDetector) (Cube); | ||
| 46 | |||
| 47 | |||
| 48 | /* Enums *********************************************************************/ | ||
| 49 | |||
| 50 | enum | ||
| 51 | center | ||
| 52 | { | ||
| 53 | U_center, D_center, | ||
| 54 | R_center, L_center, | ||
| 55 | F_center, B_center | ||
| 56 | }; | ||
| 57 | |||
| 58 | enum | ||
| 59 | corner | ||
| 60 | { | ||
| 61 | UFR, UFL, UBL, UBR, | ||
| 62 | DFR, DFL, DBL, DBR | ||
| 63 | }; | ||
| 64 | |||
| 65 | enum | ||
| 66 | edge | ||
| 67 | { | ||
| 68 | UF, UL, UB, UR, | ||
| 69 | DF, DL, DB, DR, | ||
| 70 | FR, FL, BL, BR | ||
| 71 | }; | ||
| 72 | |||
| 73 | enum | ||
| 74 | move | ||
| 75 | { | ||
| 76 | NULLMOVE, | ||
| 77 | U, U2, U3, D, D2, D3, | ||
| 78 | R, R2, R3, L, L2, L3, | ||
| 79 | F, F2, F3, B, B2, B3, | ||
| 80 | Uw, Uw2, Uw3, Dw, Dw2, Dw3, | ||
| 81 | Rw, Rw2, Rw3, Lw, Lw2, Lw3, | ||
| 82 | Fw, Fw2, Fw3, Bw, Bw2, Bw3, | ||
| 83 | M, M2, M3, | ||
| 84 | S, S2, S3, | ||
| 85 | E, E2, E3, | ||
| 86 | x, x2, x3, | ||
| 87 | y, y2, y3, | ||
| 88 | z, z2, z3, | ||
| 89 | }; | ||
| 90 | |||
| 91 | enum | ||
| 92 | trans | ||
| 93 | { | ||
| 94 | uf, ur, ub, ul, | ||
| 95 | df, dr, db, dl, | ||
| 96 | rf, rd, rb, ru, | ||
| 97 | lf, ld, lb, lu, | ||
| 98 | fu, fr, fd, fl, | ||
| 99 | bu, br, bd, bl, | ||
| 100 | uf_mirror, ur_mirror, ub_mirror, ul_mirror, | ||
| 101 | df_mirror, dr_mirror, db_mirror, dl_mirror, | ||
| 102 | rf_mirror, rd_mirror, rb_mirror, ru_mirror, | ||
| 103 | lf_mirror, ld_mirror, lb_mirror, lu_mirror, | ||
| 104 | fu_mirror, fr_mirror, fd_mirror, fl_mirror, | ||
| 105 | bu_mirror, br_mirror, bd_mirror, bl_mirror, | ||
| 106 | }; | ||
| 107 | |||
| 108 | |||
| 109 | /* Structs *******************************************************************/ | ||
| 110 | |||
| 111 | struct | ||
| 112 | alg | ||
| 113 | { | ||
| 114 | Move * move; | ||
| 115 | bool * inv; | ||
| 116 | int len; | ||
| 117 | int allocated; | ||
| 118 | }; | ||
| 119 | |||
| 120 | struct | ||
| 121 | alglist | ||
| 122 | { | ||
| 123 | AlgListNode * first; | ||
| 124 | AlgListNode * last; | ||
| 125 | int len; | ||
| 126 | }; | ||
| 127 | |||
| 128 | struct | ||
| 129 | alglistnode | ||
| 130 | { | ||
| 131 | Alg * alg; | ||
| 132 | AlgListNode * next; | ||
| 133 | }; | ||
| 134 | |||
| 135 | struct | ||
| 136 | block | ||
| 137 | { | ||
| 138 | bool edge[12]; | ||
| 139 | bool corner[8]; | ||
| 140 | bool center[6]; | ||
| 141 | }; | ||
| 142 | |||
| 143 | struct | ||
| 144 | command | ||
| 145 | { | ||
| 146 | /* TODO: more stuff to add? maybe complete help? */ | ||
| 147 | /* Maybe add list of options */ | ||
| 148 | char * name; | ||
| 149 | char * usage; | ||
| 150 | char * description; | ||
| 151 | ArgParser parse_args; | ||
| 152 | Exec exec; | ||
| 153 | }; | ||
| 154 | |||
| 155 | struct | ||
| 156 | commandargs | ||
| 157 | { | ||
| 158 | bool success; | ||
| 159 | Alg * scramble; | ||
| 160 | SolveOptions * opts; | ||
| 161 | Step * step; | ||
| 162 | Command * command; /* For help */ | ||
| 163 | }; | ||
| 164 | |||
| 165 | struct | ||
| 166 | coordinate | ||
| 167 | { | ||
| 168 | Indexer index; | ||
| 169 | AntiIndexer cube; | ||
| 170 | Checker check; | ||
| 171 | uint64_t max; | ||
| 172 | int ntrans; | ||
| 173 | Trans * trans; | ||
| 174 | }; | ||
| 175 | |||
| 176 | struct | ||
| 177 | cube | ||
| 178 | { | ||
| 179 | int epose; | ||
| 180 | int eposs; | ||
| 181 | int eposm; | ||
| 182 | int eofb; | ||
| 183 | int eorl; | ||
| 184 | int eoud; | ||
| 185 | int cp; | ||
| 186 | int coud; | ||
| 187 | int cofb; | ||
| 188 | int corl; | ||
| 189 | int cpos; | ||
| 190 | }; | ||
| 191 | |||
| 192 | struct | ||
| 193 | cubearray | ||
| 194 | { | ||
| 195 | int * ep; | ||
| 196 | int * eofb; | ||
| 197 | int * eorl; | ||
| 198 | int * eoud; | ||
| 199 | int * cp; | ||
| 200 | int * coud; | ||
| 201 | int * corl; | ||
| 202 | int * cofb; | ||
| 203 | int * cpos; | ||
| 204 | }; | ||
| 205 | |||
| 206 | struct | ||
| 207 | cubetarget | ||
| 208 | { | ||
| 209 | Cube cube; | ||
| 210 | int target; | ||
| 211 | }; | ||
| 212 | |||
| 213 | struct | ||
| 214 | dfsdata | ||
| 215 | { | ||
| 216 | int d; | ||
| 217 | int m; | ||
| 218 | int lb; | ||
| 219 | bool niss; | ||
| 220 | Move last1; | ||
| 221 | Move last2; | ||
| 222 | AlgList * sols; | ||
| 223 | Alg * current_alg; | ||
| 224 | Move sorted_moves[NMOVES]; | ||
| 225 | int move_position[NMOVES]; | ||
| 226 | }; | ||
| 227 | |||
| 228 | struct | ||
| 229 | piecefilter | ||
| 230 | { | ||
| 231 | bool epose; | ||
| 232 | bool eposs; | ||
| 233 | bool eposm; | ||
| 234 | bool eofb; | ||
| 235 | bool eorl; | ||
| 236 | bool eoud; | ||
| 237 | bool cp; | ||
| 238 | bool coud; | ||
| 239 | bool cofb; | ||
| 240 | bool corl; | ||
| 241 | bool cpos; | ||
| 242 | }; | ||
| 243 | |||
| 244 | struct | ||
| 245 | prunedata | ||
| 246 | { | ||
| 247 | char * filename; | ||
| 248 | uint8_t * ptable; | ||
| 249 | bool generated; | ||
| 250 | uint64_t n; | ||
| 251 | Coordinate * coord; | ||
| 252 | Moveset moveset; | ||
| 253 | }; | ||
| 254 | |||
| 255 | struct | ||
| 256 | solveoptions | ||
| 257 | { | ||
| 258 | /* TODO: add option to list *all* solutions satisfying other | ||
| 259 | constraints (min/max moves and optimality) */ | ||
| 260 | int min_moves; | ||
| 261 | int max_moves; | ||
| 262 | int max_solutions; | ||
| 263 | bool optimal_only; | ||
| 264 | bool can_niss; | ||
| 265 | bool feedback; /* TODO: rename with "verbose" */ | ||
| 266 | bool all; | ||
| 267 | bool print_number; | ||
| 268 | }; | ||
| 269 | |||
| 270 | struct | ||
| 271 | step | ||
| 272 | { | ||
| 273 | char * shortname; | ||
| 274 | char * name; | ||
| 275 | Estimator estimate; | ||
| 276 | Checker ready; | ||
| 277 | char * ready_msg; | ||
| 278 | Validator is_valid; | ||
| 279 | Moveset moveset; | ||
| 280 | Trans pre_trans; | ||
| 281 | TransDetector detect; | ||
| 282 | }; | ||
| 283 | |||
| 284 | struct | ||
| 285 | symdata | ||
| 286 | { | ||
| 287 | char * filename; | ||
| 288 | bool generated; | ||
| 289 | Coordinate * coord; | ||
| 290 | Coordinate * sym_coord; | ||
| 291 | int ntrans; | ||
| 292 | Trans * trans; | ||
| 293 | uint64_t * class; | ||
| 294 | Cube * rep; | ||
| 295 | Trans * transtorep; | ||
| 296 | }; | ||
| 297 | |||
| 298 | #endif | ||
diff --git a/old/2021-11-10-beforeremovingchecker/env.c b/old/2021-11-10-beforeremovingchecker/env.c new file mode 100644 index 0000000..d13642f --- /dev/null +++ b/old/2021-11-10-beforeremovingchecker/env.c | |||
| @@ -0,0 +1,45 @@ | |||
| 1 | #include "env.h" | ||
| 2 | |||
| 3 | bool initialized_env = false; | ||
| 4 | char *tabledir; | ||
| 5 | |||
| 6 | void | ||
| 7 | init_env() | ||
| 8 | { | ||
| 9 | char *nissydata = getenv("NISSYDATA"); | ||
| 10 | char *localdata = getenv("XDG_DATA_HOME"); | ||
| 11 | char *home = getenv("HOME"); | ||
| 12 | bool read, write; | ||
| 13 | |||
| 14 | if (initialized_env) | ||
| 15 | return; | ||
| 16 | |||
| 17 | if (nissydata != NULL) { | ||
| 18 | tabledir = malloc(strlen(nissydata) * sizeof(char) + 20); | ||
| 19 | strcpy(tabledir, nissydata); | ||
| 20 | } else if (localdata != NULL) { | ||
| 21 | tabledir = malloc(strlen(localdata) * sizeof(char) + 20); | ||
| 22 | strcpy(tabledir, localdata); | ||
| 23 | strcat(tabledir, "/nissy"); | ||
| 24 | } else if (home != NULL) { | ||
| 25 | tabledir = malloc(strlen(home) * sizeof(char) + 20); | ||
| 26 | strcpy(tabledir, home); | ||
| 27 | strcat(tabledir, "/.nissy"); | ||
| 28 | } | ||
| 29 | |||
| 30 | mkdir(tabledir, 0777); | ||
| 31 | strcat(tabledir, "/tables"); | ||
| 32 | mkdir(tabledir, 0777); | ||
| 33 | |||
| 34 | read = !access(tabledir, R_OK); | ||
| 35 | write = !access(tabledir, W_OK); | ||
| 36 | |||
| 37 | if (!read) { | ||
| 38 | fprintf(stderr, "Table files cannot be read.\n"); | ||
| 39 | } else if (!write) { | ||
| 40 | fprintf(stderr, "Data directory not writable: "); | ||
| 41 | fprintf(stderr, "tables can be loaded, but not saved.\n"); | ||
| 42 | } | ||
| 43 | |||
| 44 | initialized_env = true; | ||
| 45 | } | ||
diff --git a/old/2021-11-10-beforeremovingchecker/env.h b/old/2021-11-10-beforeremovingchecker/env.h new file mode 100644 index 0000000..871a9c1 --- /dev/null +++ b/old/2021-11-10-beforeremovingchecker/env.h | |||
| @@ -0,0 +1,15 @@ | |||
| 1 | #ifndef ENV_H | ||
| 2 | #define ENV_H | ||
| 3 | |||
| 4 | #include <stdbool.h> | ||
| 5 | #include <stdio.h> | ||
| 6 | #include <stdlib.h> | ||
| 7 | #include <string.h> | ||
| 8 | #include <unistd.h> | ||
| 9 | #include <sys/stat.h> | ||
| 10 | |||
| 11 | extern char *tabledir; | ||
| 12 | |||
| 13 | void init_env(); | ||
| 14 | |||
| 15 | #endif | ||
diff --git a/old/2021-11-10-beforeremovingchecker/moves.c b/old/2021-11-10-beforeremovingchecker/moves.c new file mode 100644 index 0000000..5ba17ca --- /dev/null +++ b/old/2021-11-10-beforeremovingchecker/moves.c | |||
| @@ -0,0 +1,474 @@ | |||
| 1 | #include "moves.h" | ||
| 2 | |||
| 3 | /* Local functions ***********************************************************/ | ||
| 4 | |||
| 5 | static Cube apply_move_cubearray(Move m, Cube cube, PieceFilter f); | ||
| 6 | static bool read_mtables_file(); | ||
| 7 | static bool write_mtables_file(); | ||
| 8 | |||
| 9 | /* Tables and other data *****************************************************/ | ||
| 10 | |||
| 11 | /* Every move is translated to a an <U, x, y> alg before filling the | ||
| 12 | transition tables, see init_moves() */ | ||
| 13 | |||
| 14 | static int edge_cycle[NMOVES][12] = | ||
| 15 | { | ||
| 16 | [U] = { UR, UF, UL, UB, DF, DL, DB, DR, FR, FL, BL, BR }, | ||
| 17 | [x] = { DF, FL, UF, FR, DB, BL, UB, BR, DR, DL, UL, UR }, | ||
| 18 | [y] = { UR, UF, UL, UB, DR, DF, DL, DB, BR, FR, FL, BL } | ||
| 19 | }; | ||
| 20 | |||
| 21 | static int corner_cycle[NMOVES][8] = | ||
| 22 | { | ||
| 23 | [U] = { UBR, UFR, UFL, UBL, DFR, DFL, DBL, DBR }, | ||
| 24 | [x] = { DFR, DFL, UFL, UFR, DBR, DBL, UBL, UBR }, | ||
| 25 | [y] = { UBR, UFR, UFL, UBL, DBR, DFR, DFL, DBL } | ||
| 26 | }; | ||
| 27 | |||
| 28 | static int center_cycle[NMOVES][6] = | ||
| 29 | { | ||
| 30 | [x] = { F_center, B_center, R_center, L_center, D_center, U_center }, | ||
| 31 | [y] = { U_center, D_center, B_center, F_center, R_center, L_center } | ||
| 32 | }; | ||
| 33 | |||
| 34 | static int eofb_flipped[NMOVES][12] = { | ||
| 35 | [x] = { [UF] = 1, [UB] = 1, [DF] = 1, [DB] = 1 }, | ||
| 36 | [y] = { [FR] = 1, [FL] = 1, [BL] = 1, [BR] = 1 } | ||
| 37 | }; | ||
| 38 | |||
| 39 | static int eorl_flipped[NMOVES][12] = { | ||
| 40 | [x] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, | ||
| 41 | [y] = { [FR] = 1, [FL] = 1, [BL] = 1, [BR] = 1 } | ||
| 42 | }; | ||
| 43 | |||
| 44 | static int eoud_flipped[NMOVES][12] = { | ||
| 45 | [U] = { [UF] = 1, [UL] = 1, [UB] = 1, [UR] = 1 }, | ||
| 46 | [x] = { [UF] = 1, [UB] = 1, [DF] = 1, [DB] = 1 }, | ||
| 47 | [y] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 } | ||
| 48 | }; | ||
| 49 | |||
| 50 | static int coud_flipped[NMOVES][8] = { | ||
| 51 | [x] = { | ||
| 52 | [UFR] = 2, [UBR] = 1, [UFL] = 1, [UBL] = 2, | ||
| 53 | [DBR] = 2, [DFR] = 1, [DBL] = 1, [DFL] = 2 | ||
| 54 | } | ||
| 55 | }; | ||
| 56 | |||
| 57 | static int corl_flipped[NMOVES][8] = { | ||
| 58 | [U] = { [UFR] = 1, [UBR] = 2, [UBL] = 1, [UFL] = 2 }, | ||
| 59 | [y] = { | ||
| 60 | [UFR] = 1, [UBR] = 2, [UBL] = 1, [UFL] = 2, | ||
| 61 | [DFR] = 2, [DBR] = 1, [DBL] = 2, [DFL] = 1 | ||
| 62 | } | ||
| 63 | }; | ||
| 64 | |||
| 65 | static int cofb_flipped[NMOVES][8] = { | ||
| 66 | [U] = { [UFR] = 2, [UBR] = 1, [UBL] = 2, [UFL] = 1 }, | ||
| 67 | [x] = { | ||
| 68 | [UFR] = 1, [UBR] = 2, [UBL] = 1, [UFL] = 2, | ||
| 69 | [DFR] = 2, [DBR] = 1, [DBL] = 2, [DFL] = 1 | ||
| 70 | }, | ||
| 71 | [y] = { | ||
| 72 | [UFR] = 2, [UBR] = 1, [UBL] = 2, [UFL] = 1, | ||
| 73 | [DFR] = 1, [DBR] = 2, [DBL] = 1, [DFL] = 2 | ||
| 74 | } | ||
| 75 | }; | ||
| 76 | |||
| 77 | static char equiv_alg_string[100][NMOVES] = { | ||
| 78 | [NULLMOVE] = "", | ||
| 79 | |||
| 80 | [U] = " U ", | ||
| 81 | [U2] = " UU ", | ||
| 82 | [U3] = " UUU ", | ||
| 83 | [D] = " xx U xx ", | ||
| 84 | [D2] = " xx UU xx ", | ||
| 85 | [D3] = " xx UUU xx ", | ||
| 86 | [R] = " yx U xxxyyy ", | ||
| 87 | [R2] = " yx UU xxxyyy ", | ||
| 88 | [R3] = " yx UUU xxxyyy ", | ||
| 89 | [L] = " yyyx U xxxy ", | ||
| 90 | [L2] = " yyyx UU xxxy ", | ||
| 91 | [L3] = " yyyx UUU xxxy ", | ||
| 92 | [F] = " x U xxx ", | ||
| 93 | [F2] = " x UU xxx ", | ||
| 94 | [F3] = " x UUU xxx ", | ||
| 95 | [B] = " xxx U x ", | ||
| 96 | [B2] = " xxx UU x ", | ||
| 97 | [B3] = " xxx UUU x ", | ||
| 98 | |||
| 99 | [Uw] = " xx U xx y ", | ||
| 100 | [Uw2] = " xx UU xx yy ", | ||
| 101 | [Uw3] = " xx UUU xx yyy ", | ||
| 102 | [Dw] = " U yyy ", | ||
| 103 | [Dw2] = " UU yy ", | ||
| 104 | [Dw3] = " UUU y ", | ||
| 105 | [Rw] = " yyyx U xxxy x ", | ||
| 106 | [Rw2] = " yyyx UU xxxy xx ", | ||
| 107 | [Rw3] = " yyyx UUU xxxy xxx ", | ||
| 108 | [Lw] = " yx U xxxyyy xxx ", | ||
| 109 | [Lw2] = " yx UU xxxyyy xx ", | ||
| 110 | [Lw3] = " yx UUU xxxyyy x ", | ||
| 111 | [Fw] = " xxx U x yxxxyyy ", | ||
| 112 | [Fw2] = " xxx UU x yxxyyy ", | ||
| 113 | [Fw3] = " xxx UUU x yxyyy ", | ||
| 114 | [Bw] = " x U xxx yxyyy ", | ||
| 115 | [Bw2] = " x UU xxx yxxyyy ", | ||
| 116 | [Bw3] = " x UUU xxx yxxxyyy ", | ||
| 117 | |||
| 118 | [M] = " yx U xx UUU yxyyy ", | ||
| 119 | [M2] = " yx UU xx UU xxxy ", | ||
| 120 | [M3] = " yx UUU xx U yxxxy ", | ||
| 121 | [S] = " x UUU xx U yyyx ", | ||
| 122 | [S2] = " x UU xx UU yyx ", | ||
| 123 | [S3] = " x U xx UUU yx ", | ||
| 124 | [E] = " U xx UUU xxyyy ", | ||
| 125 | [E2] = " UU xx UU xxyy ", | ||
| 126 | [E3] = " UUU xx U xxy ", | ||
| 127 | |||
| 128 | [x] = " x ", | ||
| 129 | [x2] = " xx ", | ||
| 130 | [x3] = " xxx ", | ||
| 131 | [y] = " y ", | ||
| 132 | [y2] = " yy ", | ||
| 133 | [y3] = " yyy ", | ||
| 134 | [z] = " yyy x y ", | ||
| 135 | [z2] = " yy xx ", | ||
| 136 | [z3] = " y x yyy " | ||
| 137 | }; | ||
| 138 | |||
| 139 | /* Transition tables, to be loaded up at the beginning */ | ||
| 140 | static int epose_mtable[NMOVES][FACTORIAL12/FACTORIAL8]; | ||
| 141 | static int eposs_mtable[NMOVES][FACTORIAL12/FACTORIAL8]; | ||
| 142 | static int eposm_mtable[NMOVES][FACTORIAL12/FACTORIAL8]; | ||
| 143 | static int eofb_mtable[NMOVES][POW2TO11]; | ||
| 144 | static int eorl_mtable[NMOVES][POW2TO11]; | ||
| 145 | static int eoud_mtable[NMOVES][POW2TO11]; | ||
| 146 | static int cp_mtable[NMOVES][FACTORIAL8]; | ||
| 147 | static int coud_mtable[NMOVES][POW3TO7]; | ||
| 148 | static int cofb_mtable[NMOVES][POW3TO7]; | ||
| 149 | static int corl_mtable[NMOVES][POW3TO7]; | ||
| 150 | static int cpos_mtable[NMOVES][FACTORIAL6]; | ||
| 151 | |||
| 152 | |||
| 153 | /* Local functions implementation ********************************************/ | ||
| 154 | |||
| 155 | static Cube | ||
| 156 | apply_move_cubearray(Move m, Cube cube, PieceFilter f) | ||
| 157 | { | ||
| 158 | /*init_moves();*/ | ||
| 159 | |||
| 160 | CubeArray m_arr = { | ||
| 161 | edge_cycle[m], | ||
| 162 | eofb_flipped[m], | ||
| 163 | eorl_flipped[m], | ||
| 164 | eoud_flipped[m], | ||
| 165 | corner_cycle[m], | ||
| 166 | coud_flipped[m], | ||
| 167 | corl_flipped[m], | ||
| 168 | cofb_flipped[m], | ||
| 169 | center_cycle[m] | ||
| 170 | }; | ||
| 171 | |||
| 172 | return move_via_arrays(&m_arr, cube, f); | ||
| 173 | } | ||
| 174 | |||
| 175 | /* Public functions **********************************************************/ | ||
| 176 | |||
| 177 | Cube | ||
| 178 | apply_alg_generic(Alg *alg, Cube c, PieceFilter f, bool a) | ||
| 179 | { | ||
| 180 | Cube ret = {0}; | ||
| 181 | int i; | ||
| 182 | |||
| 183 | for (i = 0; i < alg->len; i++) | ||
| 184 | if (alg->inv[i]) | ||
| 185 | ret = a ? apply_move(alg->move[i], ret) : | ||
| 186 | apply_move_cubearray(alg->move[i], ret, f); | ||
| 187 | |||
| 188 | ret = compose_filtered(c, inverse_cube(ret), f); | ||
| 189 | |||
| 190 | for (i = 0; i < alg->len; i++) | ||
| 191 | if (!alg->inv[i]) | ||
| 192 | ret = a ? apply_move(alg->move[i], ret) : | ||
| 193 | apply_move_cubearray(alg->move[i], ret, f); | ||
| 194 | |||
| 195 | return ret; | ||
| 196 | } | ||
| 197 | |||
| 198 | Cube | ||
| 199 | apply_alg(Alg *alg, Cube cube) | ||
| 200 | { | ||
| 201 | return apply_alg_generic(alg, cube, pf_all, true); | ||
| 202 | } | ||
| 203 | |||
| 204 | Cube | ||
| 205 | apply_move(Move m, Cube cube) | ||
| 206 | { | ||
| 207 | /*init_moves();*/ | ||
| 208 | |||
| 209 | return (Cube) { | ||
| 210 | .epose = epose_mtable[m][cube.epose], | ||
| 211 | .eposs = eposs_mtable[m][cube.eposs], | ||
| 212 | .eposm = eposm_mtable[m][cube.eposm], | ||
| 213 | .eofb = eofb_mtable[m][cube.eofb], | ||
| 214 | .eorl = eorl_mtable[m][cube.eorl], | ||
| 215 | .eoud = eoud_mtable[m][cube.eoud], | ||
| 216 | .coud = coud_mtable[m][cube.coud], | ||
| 217 | .cofb = cofb_mtable[m][cube.cofb], | ||
| 218 | .corl = corl_mtable[m][cube.corl], | ||
| 219 | .cp = cp_mtable[m][cube.cp], | ||
| 220 | .cpos = cpos_mtable[m][cube.cpos] | ||
| 221 | }; | ||
| 222 | } | ||
| 223 | |||
| 224 | void | ||
| 225 | init_moves() { | ||
| 226 | static bool initialized = false; | ||
| 227 | if (initialized) | ||
| 228 | return; | ||
| 229 | initialized = true; | ||
| 230 | |||
| 231 | Cube c; | ||
| 232 | CubeArray arrs; | ||
| 233 | int i; | ||
| 234 | unsigned int ui; | ||
| 235 | Move m; | ||
| 236 | Alg *equiv_alg[NMOVES]; | ||
| 237 | |||
| 238 | for (i = 0; i < NMOVES; i++) | ||
| 239 | equiv_alg[i] = new_alg(equiv_alg_string[i]); | ||
| 240 | |||
| 241 | /* Generate all move cycles and flips; I do this regardless */ | ||
| 242 | for (i = 0; i < NMOVES; i++) { | ||
| 243 | if (i == U || i == x || i == y) | ||
| 244 | continue; | ||
| 245 | |||
| 246 | c = apply_alg_generic(equiv_alg[i], (Cube){0}, pf_all, false); | ||
| 247 | |||
| 248 | arrs = (CubeArray) { | ||
| 249 | edge_cycle[i], | ||
| 250 | eofb_flipped[i], | ||
| 251 | eorl_flipped[i], | ||
| 252 | eoud_flipped[i], | ||
| 253 | corner_cycle[i], | ||
| 254 | coud_flipped[i], | ||
| 255 | corl_flipped[i], | ||
| 256 | cofb_flipped[i], | ||
| 257 | center_cycle[i] | ||
| 258 | }; | ||
| 259 | cube_to_arrays(c, &arrs, pf_all); | ||
| 260 | } | ||
| 261 | |||
| 262 | if (read_mtables_file()) | ||
| 263 | return; | ||
| 264 | |||
| 265 | fprintf(stderr, "Cannot load %s, generating it\n", "mtables"); | ||
| 266 | |||
| 267 | /* Initialize transition tables */ | ||
| 268 | for (m = 0; m < NMOVES; m++) { | ||
| 269 | for (ui = 0; ui < FACTORIAL12/FACTORIAL8; ui++) { | ||
| 270 | c = (Cube){ .epose = ui }; | ||
| 271 | c = apply_move_cubearray(m, c, pf_e); | ||
| 272 | epose_mtable[m][ui] = c.epose; | ||
| 273 | |||
| 274 | c = (Cube){ .eposs = ui }; | ||
| 275 | c = apply_move_cubearray(m, c, pf_s); | ||
| 276 | eposs_mtable[m][ui] = c.eposs; | ||
| 277 | |||
| 278 | c = (Cube){ .eposm = ui }; | ||
| 279 | c = apply_move_cubearray(m, c, pf_m); | ||
| 280 | eposm_mtable[m][ui] = c.eposm; | ||
| 281 | } | ||
| 282 | for (ui = 0; ui < POW2TO11; ui++ ) { | ||
| 283 | c = (Cube){ .eofb = ui }; | ||
| 284 | c = apply_move_cubearray(m, c, pf_eo); | ||
| 285 | eofb_mtable[m][ui] = c.eofb; | ||
| 286 | |||
| 287 | c = (Cube){ .eorl = ui }; | ||
| 288 | c = apply_move_cubearray(m, c, pf_eo); | ||
| 289 | eorl_mtable[m][ui] = c.eorl; | ||
| 290 | |||
| 291 | c = (Cube){ .eoud = ui }; | ||
| 292 | c = apply_move_cubearray(m, c, pf_eo); | ||
| 293 | eoud_mtable[m][ui] = c.eoud; | ||
| 294 | } | ||
| 295 | for (ui = 0; ui < POW3TO7; ui++) { | ||
| 296 | c = (Cube){ .coud = ui }; | ||
| 297 | c = apply_move_cubearray(m, c, pf_co); | ||
| 298 | coud_mtable[m][ui] = c.coud; | ||
| 299 | |||
| 300 | c = (Cube){ .corl = ui }; | ||
| 301 | c = apply_move_cubearray(m, c, pf_co); | ||
| 302 | corl_mtable[m][ui] = c.corl; | ||
| 303 | |||
| 304 | c = (Cube){ .cofb = ui }; | ||
| 305 | c = apply_move_cubearray(m, c, pf_co); | ||
| 306 | cofb_mtable[m][ui] = c.cofb; | ||
| 307 | } | ||
| 308 | for (ui = 0; ui < FACTORIAL8; ui++) { | ||
| 309 | c = (Cube){ .cp = ui }; | ||
| 310 | c = apply_move_cubearray(m, c, pf_cp); | ||
| 311 | cp_mtable[m][ui] = c.cp; | ||
| 312 | } | ||
| 313 | for (ui = 0; ui < FACTORIAL6; ui++) { | ||
| 314 | c = (Cube){ .cpos = ui }; | ||
| 315 | c = apply_move_cubearray(m, c, pf_cpos); | ||
| 316 | cpos_mtable[m][ui] = c.cpos; | ||
| 317 | } | ||
| 318 | } | ||
| 319 | |||
| 320 | if (!write_mtables_file()) | ||
| 321 | fprintf(stderr, "Error writing mtables\n"); | ||
| 322 | |||
| 323 | for (i = 0; i < NMOVES; i++) | ||
| 324 | free_alg(equiv_alg[i]); | ||
| 325 | } | ||
| 326 | |||
| 327 | static bool | ||
| 328 | read_mtables_file() | ||
| 329 | { | ||
| 330 | init_env(); | ||
| 331 | |||
| 332 | FILE *f; | ||
| 333 | char fname[strlen(tabledir)+20]; | ||
| 334 | int m, b = sizeof(int); | ||
| 335 | bool r = true; | ||
| 336 | |||
| 337 | /* Table sizes, used for reading and writing files */ | ||
| 338 | uint64_t me[11] = { | ||
| 339 | [0] = FACTORIAL12/FACTORIAL8, | ||
| 340 | [1] = FACTORIAL12/FACTORIAL8, | ||
| 341 | [2] = FACTORIAL12/FACTORIAL8, | ||
| 342 | [3] = POW2TO11, | ||
| 343 | [4] = POW2TO11, | ||
| 344 | [5] = POW2TO11, | ||
| 345 | [6] = FACTORIAL8, | ||
| 346 | [7] = POW3TO7, | ||
| 347 | [8] = POW3TO7, | ||
| 348 | [9] = POW3TO7, | ||
| 349 | [10] = FACTORIAL6 | ||
| 350 | }; | ||
| 351 | |||
| 352 | strcpy(fname, tabledir); | ||
| 353 | strcat(fname, "/mtables"); | ||
| 354 | |||
| 355 | if ((f = fopen(fname, "rb")) == NULL) | ||
| 356 | return false; | ||
| 357 | |||
| 358 | for (m = 0; m < NMOVES; m++) { | ||
| 359 | r = r && fread(epose_mtable[m], b, me[0], f) == me[0]; | ||
| 360 | r = r && fread(eposs_mtable[m], b, me[1], f) == me[1]; | ||
| 361 | r = r && fread(eposm_mtable[m], b, me[2], f) == me[2]; | ||
| 362 | r = r && fread(eofb_mtable[m], b, me[3], f) == me[3]; | ||
| 363 | r = r && fread(eorl_mtable[m], b, me[4], f) == me[4]; | ||
| 364 | r = r && fread(eoud_mtable[m], b, me[5], f) == me[5]; | ||
| 365 | r = r && fread(cp_mtable[m], b, me[6], f) == me[6]; | ||
| 366 | r = r && fread(coud_mtable[m], b, me[7], f) == me[7]; | ||
| 367 | r = r && fread(corl_mtable[m], b, me[8], f) == me[8]; | ||
| 368 | r = r && fread(cofb_mtable[m], b, me[9], f) == me[9]; | ||
| 369 | r = r && fread(cpos_mtable[m], b, me[10], f) == me[10]; | ||
| 370 | } | ||
| 371 | |||
| 372 | fclose(f); | ||
| 373 | return r; | ||
| 374 | } | ||
| 375 | |||
| 376 | static bool | ||
| 377 | write_mtables_file() | ||
| 378 | { | ||
| 379 | init_env(); | ||
| 380 | |||
| 381 | FILE *f; | ||
| 382 | char fname[strlen(tabledir)+20]; | ||
| 383 | int m, b = sizeof(int); | ||
| 384 | bool r = true; | ||
| 385 | |||
| 386 | /* Table sizes, used for reading and writing files */ | ||
| 387 | uint64_t me[11] = { | ||
| 388 | [0] = FACTORIAL12/FACTORIAL8, | ||
| 389 | [1] = FACTORIAL12/FACTORIAL8, | ||
| 390 | [2] = FACTORIAL12/FACTORIAL8, | ||
| 391 | [3] = POW2TO11, | ||
| 392 | [4] = POW2TO11, | ||
| 393 | [5] = POW2TO11, | ||
| 394 | [6] = FACTORIAL8, | ||
| 395 | [7] = POW3TO7, | ||
| 396 | [8] = POW3TO7, | ||
| 397 | [9] = POW3TO7, | ||
| 398 | [10] = FACTORIAL6 | ||
| 399 | }; | ||
| 400 | |||
| 401 | strcpy(fname, tabledir); | ||
| 402 | strcat(fname, "/mtables"); | ||
| 403 | |||
| 404 | if ((f = fopen(fname, "wb")) == NULL) | ||
| 405 | return false; | ||
| 406 | |||
| 407 | for (m = 0; m < NMOVES; m++) { | ||
| 408 | r = r && fwrite(epose_mtable[m], b, me[0], f) == me[0]; | ||
| 409 | r = r && fwrite(eposs_mtable[m], b, me[1], f) == me[1]; | ||
| 410 | r = r && fwrite(eposm_mtable[m], b, me[2], f) == me[2]; | ||
| 411 | r = r && fwrite(eofb_mtable[m], b, me[3], f) == me[3]; | ||
| 412 | r = r && fwrite(eorl_mtable[m], b, me[4], f) == me[4]; | ||
| 413 | r = r && fwrite(eoud_mtable[m], b, me[5], f) == me[5]; | ||
| 414 | r = r && fwrite(cp_mtable[m], b, me[6], f) == me[6]; | ||
| 415 | r = r && fwrite(coud_mtable[m], b, me[7], f) == me[7]; | ||
| 416 | r = r && fwrite(corl_mtable[m], b, me[8], f) == me[8]; | ||
| 417 | r = r && fwrite(cofb_mtable[m], b, me[9], f) == me[9]; | ||
| 418 | r = r && fwrite(cpos_mtable[m], b, me[10], f) == me[10]; | ||
| 419 | } | ||
| 420 | |||
| 421 | fclose(f); | ||
| 422 | return r; | ||
| 423 | } | ||
| 424 | |||
| 425 | bool | ||
| 426 | commute(Move m1, Move m2) | ||
| 427 | { | ||
| 428 | static bool initialized = false; | ||
| 429 | static bool commute_aux[NMOVES][NMOVES]; | ||
| 430 | |||
| 431 | if (!initialized) { | ||
| 432 | Cube c1, c2; | ||
| 433 | int i, j; | ||
| 434 | |||
| 435 | for (i = 0; i < NMOVES; i++) { | ||
| 436 | for (j = 0; j < NMOVES; j++) { | ||
| 437 | c1 = apply_move(i, apply_move(j, (Cube){0})); | ||
| 438 | c2 = apply_move(j, apply_move(i, (Cube){0})); | ||
| 439 | commute_aux[i][j] = equal(c1, c2) && i && j; | ||
| 440 | } | ||
| 441 | } | ||
| 442 | |||
| 443 | initialized = true; | ||
| 444 | } | ||
| 445 | |||
| 446 | return commute_aux[m1][m2]; | ||
| 447 | } | ||
| 448 | |||
| 449 | bool | ||
| 450 | possible_next(Move m1, Move m2, Move m3) | ||
| 451 | { | ||
| 452 | static bool initialized = false; | ||
| 453 | static bool paux[NMOVES][NMOVES][NMOVES]; | ||
| 454 | |||
| 455 | if (!initialized) { | ||
| 456 | int i, j, k; | ||
| 457 | bool p, q, c; | ||
| 458 | |||
| 459 | for (i = 0; i < NMOVES; i++) { | ||
| 460 | for (j = 0; j < NMOVES; j++) { | ||
| 461 | for (k = 0; k < NMOVES; k++) { | ||
| 462 | p = j && base_move(j) == base_move(k); | ||
| 463 | q = i && base_move(i) == base_move(k); | ||
| 464 | c = commute(i, j); | ||
| 465 | paux[i][j][k] = !(p || (c && q)); | ||
| 466 | } | ||
| 467 | } | ||
| 468 | } | ||
| 469 | |||
| 470 | initialized = true; | ||
| 471 | } | ||
| 472 | |||
| 473 | return paux[m1][m2][m3]; | ||
| 474 | } | ||
diff --git a/old/2021-11-10-beforeremovingchecker/moves.h b/old/2021-11-10-beforeremovingchecker/moves.h new file mode 100644 index 0000000..082a080 --- /dev/null +++ b/old/2021-11-10-beforeremovingchecker/moves.h | |||
| @@ -0,0 +1,16 @@ | |||
| 1 | #ifndef MOVES_H | ||
| 2 | #define MOVES_H | ||
| 3 | |||
| 4 | #include "alg.h" | ||
| 5 | #include "cube.h" | ||
| 6 | #include "env.h" | ||
| 7 | |||
| 8 | Cube apply_alg(Alg *alg, Cube cube); | ||
| 9 | Cube apply_alg_generic(Alg *alg, Cube c, PieceFilter f, bool a); | ||
| 10 | Cube apply_move(Move m, Cube cube); | ||
| 11 | bool commute(Move m1, Move m2); | ||
| 12 | bool possible_next(Move m1, Move m2, Move m3); | ||
| 13 | |||
| 14 | void init_moves(); | ||
| 15 | |||
| 16 | #endif | ||
diff --git a/old/2021-11-10-beforeremovingchecker/pf.c b/old/2021-11-10-beforeremovingchecker/pf.c new file mode 100644 index 0000000..34be4fd --- /dev/null +++ b/old/2021-11-10-beforeremovingchecker/pf.c | |||
| @@ -0,0 +1,80 @@ | |||
| 1 | #include "pf.h" | ||
| 2 | |||
| 3 | PieceFilter | ||
| 4 | pf_all = { | ||
| 5 | .epose = true, | ||
| 6 | .eposs = true, | ||
| 7 | .eposm = true, | ||
| 8 | .eofb = true, | ||
| 9 | .eorl = true, | ||
| 10 | .eoud = true, | ||
| 11 | .cp = true, | ||
| 12 | .cofb = true, | ||
| 13 | .corl = true, | ||
| 14 | .coud = true, | ||
| 15 | .cpos = true | ||
| 16 | }; | ||
| 17 | |||
| 18 | PieceFilter | ||
| 19 | pf_4val = { | ||
| 20 | .epose = true, | ||
| 21 | .eposs = true, | ||
| 22 | .eposm = true, | ||
| 23 | .eofb = true, | ||
| 24 | .coud = true, | ||
| 25 | .cp = true | ||
| 26 | }; | ||
| 27 | |||
| 28 | PieceFilter | ||
| 29 | pf_epcp = { | ||
| 30 | .epose = true, | ||
| 31 | .eposs = true, | ||
| 32 | .eposm = true, | ||
| 33 | .cp = true | ||
| 34 | }; | ||
| 35 | |||
| 36 | PieceFilter | ||
| 37 | pf_cpos = { | ||
| 38 | .cpos = true | ||
| 39 | }; | ||
| 40 | |||
| 41 | PieceFilter | ||
| 42 | pf_cp = { | ||
| 43 | .cp = true | ||
| 44 | }; | ||
| 45 | |||
| 46 | PieceFilter | ||
| 47 | pf_ep = { | ||
| 48 | .epose = true, | ||
| 49 | .eposs = true, | ||
| 50 | .eposm = true | ||
| 51 | }; | ||
| 52 | |||
| 53 | PieceFilter | ||
| 54 | pf_e = { | ||
| 55 | .epose = true | ||
| 56 | }; | ||
| 57 | |||
| 58 | PieceFilter | ||
| 59 | pf_s = { | ||
| 60 | .eposs = true | ||
| 61 | }; | ||
| 62 | |||
| 63 | PieceFilter | ||
| 64 | pf_m = { | ||
| 65 | .eposm = true | ||
| 66 | }; | ||
| 67 | |||
| 68 | PieceFilter | ||
| 69 | pf_eo = { | ||
| 70 | .eofb = true, | ||
| 71 | .eorl = true, | ||
| 72 | .eoud = true | ||
| 73 | }; | ||
| 74 | |||
| 75 | PieceFilter | ||
| 76 | pf_co = { | ||
| 77 | .cofb = true, | ||
| 78 | .corl = true, | ||
| 79 | .coud = true | ||
| 80 | }; | ||
diff --git a/old/2021-11-10-beforeremovingchecker/pf.h b/old/2021-11-10-beforeremovingchecker/pf.h new file mode 100644 index 0000000..85ee1eb --- /dev/null +++ b/old/2021-11-10-beforeremovingchecker/pf.h | |||
| @@ -0,0 +1,18 @@ | |||
| 1 | #ifndef PF_H | ||
| 2 | #define PF_H | ||
| 3 | |||
| 4 | #include "cubetypes.h" | ||
| 5 | |||
| 6 | extern PieceFilter pf_all; | ||
| 7 | extern PieceFilter pf_4val; | ||
| 8 | extern PieceFilter pf_epcp; | ||
| 9 | extern PieceFilter pf_cpos; | ||
| 10 | extern PieceFilter pf_cp; | ||
| 11 | extern PieceFilter pf_ep; | ||
| 12 | extern PieceFilter pf_e; | ||
| 13 | extern PieceFilter pf_s; | ||
| 14 | extern PieceFilter pf_m; | ||
| 15 | extern PieceFilter pf_eo; | ||
| 16 | extern PieceFilter pf_co; | ||
| 17 | |||
| 18 | #endif | ||
diff --git a/old/2021-11-10-beforeremovingchecker/pruning.c b/old/2021-11-10-beforeremovingchecker/pruning.c new file mode 100644 index 0000000..86363f4 --- /dev/null +++ b/old/2021-11-10-beforeremovingchecker/pruning.c | |||
| @@ -0,0 +1,272 @@ | |||
| 1 | #include "pruning.h" | ||
| 2 | |||
| 3 | static void genptable_bfs(PruneData *pd, int d, Move *ms); | ||
| 4 | static void genptable_branch(PruneData *pd, uint64_t i, int d, Move *m); | ||
| 5 | static void ptable_update(PruneData *pd, Cube cube, int m); | ||
| 6 | static void ptable_update_index(PruneData *pd, uint64_t ind, int m); | ||
| 7 | static int ptableval_index(PruneData *pd, uint64_t ind); | ||
| 8 | static bool read_ptable_file(PruneData *pd); | ||
| 9 | static bool write_ptable_file(PruneData *pd); | ||
| 10 | |||
| 11 | PruneData | ||
| 12 | pd_eofb_HTM = { | ||
| 13 | .filename = "pt_eofb_HTM", | ||
| 14 | .coord = &coord_eofb, | ||
| 15 | .moveset = moveset_HTM, | ||
| 16 | }; | ||
| 17 | |||
| 18 | PruneData | ||
| 19 | pd_coud_HTM = { | ||
| 20 | .filename = "pt_coud_HTM", | ||
| 21 | .coord = &coord_coud, | ||
| 22 | .moveset = moveset_HTM, | ||
| 23 | }; | ||
| 24 | |||
| 25 | PruneData | ||
| 26 | pd_cornershtr_HTM = { | ||
| 27 | .filename = "pt_cornershtr_withcosets_HTM", | ||
| 28 | .coord = &coord_cornershtr, | ||
| 29 | .moveset = moveset_HTM, | ||
| 30 | }; | ||
| 31 | |||
| 32 | PruneData | ||
| 33 | pd_corners_HTM = { | ||
| 34 | .filename = "pt_corners_HTM", | ||
| 35 | .coord = &coord_corners, | ||
| 36 | .moveset = moveset_HTM, | ||
| 37 | }; | ||
| 38 | |||
| 39 | PruneData | ||
| 40 | pd_drud_sym16_HTM = { | ||
| 41 | .filename = "pt_drud_sym16_HTM", | ||
| 42 | .coord = &coord_drud_sym16, | ||
| 43 | .moveset = moveset_HTM, | ||
| 44 | }; | ||
| 45 | |||
| 46 | PruneData | ||
| 47 | pd_drud_eofb = { | ||
| 48 | .filename = "pt_drud_eofb", | ||
| 49 | .coord = &coord_drud_eofb, | ||
| 50 | .moveset = moveset_eofb, | ||
| 51 | }; | ||
| 52 | |||
| 53 | PruneData | ||
| 54 | pd_drudfin_noE_sym16_drud = { | ||
| 55 | .filename = "pt_drudfin_noE_sym16_drud", | ||
| 56 | .coord = &coord_drudfin_noE_sym16, | ||
| 57 | .moveset = moveset_drud, | ||
| 58 | }; | ||
| 59 | |||
| 60 | PruneData | ||
| 61 | pd_htr_drud = { | ||
| 62 | .filename = "pt_htr_drud", | ||
| 63 | .coord = &coord_htr_drud, | ||
| 64 | .moveset = moveset_drud, | ||
| 65 | }; | ||
| 66 | |||
| 67 | PruneData | ||
| 68 | pd_htrfin_htr = { | ||
| 69 | .filename = "pt_htrfin_htr", | ||
| 70 | .coord = &coord_htrfin, | ||
| 71 | .moveset = moveset_htr, | ||
| 72 | }; | ||
| 73 | |||
| 74 | PruneData | ||
| 75 | pd_khuge_HTM = { | ||
| 76 | .filename = "pt_khuge_HTM", | ||
| 77 | .coord = &coord_khuge, | ||
| 78 | .moveset = moveset_HTM, | ||
| 79 | }; | ||
| 80 | |||
| 81 | void | ||
| 82 | genptable(PruneData *pd) | ||
| 83 | { | ||
| 84 | Move ms[NMOVES]; | ||
| 85 | int d; | ||
| 86 | uint64_t j, oldn; | ||
| 87 | |||
| 88 | if (pd->generated) | ||
| 89 | return; | ||
| 90 | |||
| 91 | /* TODO: check if memory is enough, otherwise maybe exit gracefully? */ | ||
| 92 | pd->ptable = malloc(ptablesize(pd) * sizeof(uint8_t)); | ||
| 93 | |||
| 94 | if (read_ptable_file(pd)) { | ||
| 95 | pd->generated = true; | ||
| 96 | return; | ||
| 97 | } | ||
| 98 | pd->generated = true; | ||
| 99 | |||
| 100 | fprintf(stderr, "Cannot load %s, generating it\n", pd->filename); | ||
| 101 | |||
| 102 | moveset_to_list(pd->moveset, ms); | ||
| 103 | |||
| 104 | /* We use 4 bits per value, so any distance >= 15 is set to 15 */ | ||
| 105 | for (j = 0; j < pd->coord->max; j++) | ||
| 106 | ptable_update_index(pd, j, 15); | ||
| 107 | |||
| 108 | for (j = 0; j < pd->coord->max; j++) | ||
| 109 | if (ptableval_index(pd, j) != 15) { | ||
| 110 | printf("Error, non-max value at index %lu!\n", j); | ||
| 111 | break; | ||
| 112 | } | ||
| 113 | printf("Table set, ready to start\n"); | ||
| 114 | |||
| 115 | /*TODO: change, set to 0 for every solved state (might be more than 1)*/ | ||
| 116 | ptable_update(pd, (Cube){0}, 0); | ||
| 117 | pd->n = 1; | ||
| 118 | oldn = 0; | ||
| 119 | fprintf(stderr, "Depth %d done, generated %lu\t(%lu/%lu)\n", | ||
| 120 | 0, pd->n - oldn, pd->n, pd->coord->max); | ||
| 121 | oldn = 1; | ||
| 122 | for (d = 0; d < 15 && pd->n < pd->coord->max; d++) { | ||
| 123 | genptable_bfs(pd, d, ms); | ||
| 124 | fprintf(stderr, "Depth %d done, generated %lu\t(%lu/%lu)\n", | ||
| 125 | d+1, pd->n - oldn, pd->n, pd->coord->max); | ||
| 126 | oldn = pd->n; | ||
| 127 | } | ||
| 128 | |||
| 129 | if (!write_ptable_file(pd)) | ||
| 130 | fprintf(stderr, "Error writing ptable file\n"); | ||
| 131 | } | ||
| 132 | |||
| 133 | static void | ||
| 134 | genptable_bfs(PruneData *pd, int d, Move *ms) | ||
| 135 | { | ||
| 136 | uint64_t i; | ||
| 137 | |||
| 138 | for (i = 0; i < pd->coord->max; i++) | ||
| 139 | if (ptableval_index(pd, i) == d) | ||
| 140 | genptable_branch(pd, i, d, ms); | ||
| 141 | } | ||
| 142 | |||
| 143 | static void | ||
| 144 | genptable_branch(PruneData *pd, uint64_t ind, int d, Move *ms) | ||
| 145 | { | ||
| 146 | int i, j; | ||
| 147 | Cube ci, cc, c; | ||
| 148 | |||
| 149 | /* | ||
| 150 | * This is the only line of the whole program where we REALLY need an | ||
| 151 | * anti-indexer function. We could get rid of it if only we could save | ||
| 152 | * a cube object for each index value as we go, but then we would need | ||
| 153 | * an incredible amount of memory to generate each ptable: assuming | ||
| 154 | * fields in struct cube are 32 bit ints that would take 88 times the | ||
| 155 | * memory of the table to be generated, more than 120Gb for | ||
| 156 | * ptable_khuge for example! | ||
| 157 | */ | ||
| 158 | ci = pd->coord->cube(ind); | ||
| 159 | |||
| 160 | for (i = 0; i < pd->coord->ntrans; i++) { | ||
| 161 | /* For simplicity trans[] is NULL when ntrans = 1 */ | ||
| 162 | c = i == 0 ? ci : | ||
| 163 | apply_trans(pd->coord->trans[i], ci); | ||
| 164 | for (j = 0; ms[j] != NULLMOVE; j++) { | ||
| 165 | cc = apply_move(ms[j], c); | ||
| 166 | if (ptableval(pd, cc) > d+1) | ||
| 167 | ptable_update(pd, cc, d+1); | ||
| 168 | } | ||
| 169 | } | ||
| 170 | } | ||
| 171 | |||
| 172 | void | ||
| 173 | print_ptable(PruneData *pd) | ||
| 174 | { | ||
| 175 | uint64_t i, a[16]; | ||
| 176 | |||
| 177 | for (i = 0; i < 16; i++) | ||
| 178 | a[i] = 0; | ||
| 179 | |||
| 180 | if (!pd->generated) | ||
| 181 | genptable(pd); | ||
| 182 | |||
| 183 | for (i = 0; i < pd->coord->max; i++) | ||
| 184 | a[ptableval_index(pd, i)]++; | ||
| 185 | |||
| 186 | fprintf(stderr, "Values for table %s\n", pd->filename); | ||
| 187 | for (i = 0; i < 16; i++) | ||
| 188 | printf("%2lu\t%10lu\n", i, a[i]); | ||
| 189 | } | ||
| 190 | |||
| 191 | uint64_t | ||
| 192 | ptablesize(PruneData *pd) | ||
| 193 | { | ||
| 194 | return (pd->coord->max + 1) / 2; | ||
| 195 | } | ||
| 196 | |||
| 197 | static void | ||
| 198 | ptable_update(PruneData *pd, Cube cube, int n) | ||
| 199 | { | ||
| 200 | uint64_t ind = pd->coord->index(cube); | ||
| 201 | ptable_update_index(pd, ind, n); | ||
| 202 | } | ||
| 203 | |||
| 204 | static void | ||
| 205 | ptable_update_index(PruneData *pd, uint64_t ind, int n) | ||
| 206 | { | ||
| 207 | uint8_t oldval2 = pd->ptable[ind/2]; | ||
| 208 | int other = (ind % 2) ? oldval2 % 16 : oldval2 / 16; | ||
| 209 | |||
| 210 | pd->ptable[ind/2] = (ind % 2) ? 16*n + other : 16*other + n; | ||
| 211 | pd->n++; | ||
| 212 | } | ||
| 213 | |||
| 214 | int | ||
| 215 | ptableval(PruneData *pd, Cube cube) | ||
| 216 | { | ||
| 217 | return ptableval_index(pd, pd->coord->index(cube)); | ||
| 218 | } | ||
| 219 | |||
| 220 | static int | ||
| 221 | ptableval_index(PruneData *pd, uint64_t ind) | ||
| 222 | { | ||
| 223 | if (!pd->generated) | ||
| 224 | genptable(pd); | ||
| 225 | |||
| 226 | return (ind % 2) ? pd->ptable[ind/2] / 16 : pd->ptable[ind/2] % 16; | ||
| 227 | } | ||
| 228 | |||
| 229 | static bool | ||
| 230 | read_ptable_file(PruneData *pd) | ||
| 231 | { | ||
| 232 | init_env(); | ||
| 233 | |||
| 234 | FILE *f; | ||
| 235 | char fname[strlen(tabledir)+100]; | ||
| 236 | uint64_t r; | ||
| 237 | |||
| 238 | strcpy(fname, tabledir); | ||
| 239 | strcat(fname, "/"); | ||
| 240 | strcat(fname, pd->filename); | ||
| 241 | |||
| 242 | if ((f = fopen(fname, "rb")) == NULL) | ||
| 243 | return false; | ||
| 244 | |||
| 245 | r = fread(pd->ptable, sizeof(uint8_t), ptablesize(pd), f); | ||
| 246 | fclose(f); | ||
| 247 | |||
| 248 | return r == ptablesize(pd); | ||
| 249 | } | ||
| 250 | |||
| 251 | static bool | ||
| 252 | write_ptable_file(PruneData *pd) | ||
| 253 | { | ||
| 254 | init_env(); | ||
| 255 | |||
| 256 | FILE *f; | ||
| 257 | char fname[strlen(tabledir)+100]; | ||
| 258 | uint64_t written; | ||
| 259 | |||
| 260 | strcpy(fname, tabledir); | ||
| 261 | strcat(fname, "/"); | ||
| 262 | strcat(fname, pd->filename); | ||
| 263 | |||
| 264 | if ((f = fopen(fname, "wb")) == NULL) | ||
| 265 | return false; | ||
| 266 | |||
| 267 | written = fwrite(pd->ptable, sizeof(uint8_t), ptablesize(pd), f); | ||
| 268 | fclose(f); | ||
| 269 | |||
| 270 | return written == ptablesize(pd); | ||
| 271 | } | ||
| 272 | |||
diff --git a/old/2021-11-10-beforeremovingchecker/pruning.h b/old/2021-11-10-beforeremovingchecker/pruning.h new file mode 100644 index 0000000..631ee3a --- /dev/null +++ b/old/2021-11-10-beforeremovingchecker/pruning.h | |||
| @@ -0,0 +1,23 @@ | |||
| 1 | #ifndef PRUNING_H | ||
| 2 | #define PRUNING_H | ||
| 3 | |||
| 4 | #include "symcoord.h" | ||
| 5 | |||
| 6 | extern PruneData pd_eofb_HTM; | ||
| 7 | extern PruneData pd_coud_HTM; | ||
| 8 | extern PruneData pd_corners_HTM; | ||
| 9 | extern PruneData pd_cornershtr_HTM; | ||
| 10 | extern PruneData pd_drud_sym16_HTM; | ||
| 11 | extern PruneData pd_drud_eofb; | ||
| 12 | extern PruneData pd_drudfin_noE_sym16_drud; | ||
| 13 | extern PruneData pd_htr_drud; | ||
| 14 | extern PruneData pd_htrfin_htr; | ||
| 15 | extern PruneData pd_khuge_HTM; | ||
| 16 | |||
| 17 | void genptable(PruneData *pd); | ||
| 18 | void print_ptable(PruneData *pd); | ||
| 19 | uint64_t ptablesize(PruneData *pd); | ||
| 20 | int ptableval(PruneData *pd, Cube cube); | ||
| 21 | |||
| 22 | #endif | ||
| 23 | |||
diff --git a/old/2021-11-10-beforeremovingchecker/shell.c b/old/2021-11-10-beforeremovingchecker/shell.c new file mode 100644 index 0000000..e591faa --- /dev/null +++ b/old/2021-11-10-beforeremovingchecker/shell.c | |||
| @@ -0,0 +1,99 @@ | |||
| 1 | #include "shell.h" | ||
| 2 | |||
| 3 | static void cleanwhitespaces(char *line); | ||
| 4 | static int parseline(char *line, char **v); | ||
| 5 | |||
| 6 | static void | ||
| 7 | cleanwhitespaces(char *line) | ||
| 8 | { | ||
| 9 | char *i; | ||
| 10 | |||
| 11 | for (i = line; *i != 0; i++) | ||
| 12 | if (*i == '\t' || *i == '\n') | ||
| 13 | *i = ' '; | ||
| 14 | } | ||
| 15 | |||
| 16 | /* This function assumes that **v is large enough */ | ||
| 17 | static int | ||
| 18 | parseline(char *line, char **v) | ||
| 19 | { | ||
| 20 | char *t; | ||
| 21 | int n = 0; | ||
| 22 | |||
| 23 | cleanwhitespaces(line); | ||
| 24 | |||
| 25 | for (t = strtok(line, " "); t != NULL; t = strtok(NULL, " ")) | ||
| 26 | strcpy(v[n++], t); | ||
| 27 | |||
| 28 | return n; | ||
| 29 | } | ||
| 30 | |||
| 31 | void | ||
| 32 | exec_args(int c, char **v) | ||
| 33 | { | ||
| 34 | int i; | ||
| 35 | Command *cmd = NULL; | ||
| 36 | CommandArgs *args; | ||
| 37 | |||
| 38 | for (i = 0; i < NCOMMANDS; i++) | ||
| 39 | if (commands[i] != NULL && !strcmp(v[0], commands[i]->name)) | ||
| 40 | cmd = commands[i]; | ||
| 41 | |||
| 42 | if (cmd == NULL) { | ||
| 43 | fprintf(stderr, "%s: command not found\n", v[0]); | ||
| 44 | return; | ||
| 45 | } | ||
| 46 | |||
| 47 | args = cmd->parse_args(c-1, &v[1]); | ||
| 48 | if (!args->success) { | ||
| 49 | fprintf(stderr, "usage: %s\n", cmd->usage); | ||
| 50 | return; | ||
| 51 | } | ||
| 52 | |||
| 53 | cmd->exec(args); | ||
| 54 | free_args(args); | ||
| 55 | } | ||
| 56 | |||
| 57 | void | ||
| 58 | launch() | ||
| 59 | { | ||
| 60 | int i, shell_argc; | ||
| 61 | char line[MAXLINELEN], **shell_argv; | ||
| 62 | |||
| 63 | shell_argv = malloc(MAXNTOKENS * sizeof(char *)); | ||
| 64 | for (i = 0; i < MAXNTOKENS; i++) | ||
| 65 | shell_argv[i] = malloc((MAXTOKENLEN+1) * sizeof(char)); | ||
| 66 | |||
| 67 | fprintf(stderr, "Welcome to Nissy 2.0 (demo version).\n"); | ||
| 68 | fprintf(stderr, "Limited commands available. "); | ||
| 69 | fprintf(stderr, "Type 'help' for a list.\n"); | ||
| 70 | |||
| 71 | while (true) { | ||
| 72 | fprintf(stderr, "nissy-# "); | ||
| 73 | if (fgets(line, MAXLINELEN, stdin) == NULL) | ||
| 74 | break; | ||
| 75 | shell_argc = parseline(line, shell_argv); | ||
| 76 | exec_args(shell_argc, shell_argv); | ||
| 77 | } | ||
| 78 | |||
| 79 | for (i = 0; i < MAXNTOKENS; i++) | ||
| 80 | free(shell_argv[i]); | ||
| 81 | free(shell_argv); | ||
| 82 | } | ||
| 83 | |||
| 84 | /* We will have our main() here, for now */ | ||
| 85 | int | ||
| 86 | main(int argc, char *argv[]) | ||
| 87 | { | ||
| 88 | init_moves(); | ||
| 89 | init_trans(); | ||
| 90 | init_coord(); | ||
| 91 | init_symcoord(); | ||
| 92 | |||
| 93 | if (argc > 1) | ||
| 94 | exec_args(argc-1, &argv[1]); | ||
| 95 | else | ||
| 96 | launch(); | ||
| 97 | |||
| 98 | return 0; | ||
| 99 | } | ||
diff --git a/old/2021-11-10-beforeremovingchecker/shell.h b/old/2021-11-10-beforeremovingchecker/shell.h new file mode 100644 index 0000000..a72d136 --- /dev/null +++ b/old/2021-11-10-beforeremovingchecker/shell.h | |||
| @@ -0,0 +1,13 @@ | |||
| 1 | #ifndef SHELL_H | ||
| 2 | #define SHELL_H | ||
| 3 | |||
| 4 | #include "commands.h" | ||
| 5 | |||
| 6 | #define MAXLINELEN 10000 | ||
| 7 | #define MAXTOKENLEN 255 | ||
| 8 | #define MAXNTOKENS 255 | ||
| 9 | |||
| 10 | void exec_args(int c, char **v); | ||
| 11 | void launch(); | ||
| 12 | |||
| 13 | #endif | ||
diff --git a/old/2021-11-10-beforeremovingchecker/solve.c b/old/2021-11-10-beforeremovingchecker/solve.c new file mode 100644 index 0000000..af685ec --- /dev/null +++ b/old/2021-11-10-beforeremovingchecker/solve.c | |||
| @@ -0,0 +1,209 @@ | |||
| 1 | #include "solve.h" | ||
| 2 | |||
| 3 | /* Local functions ***********************************************************/ | ||
| 4 | |||
| 5 | static bool allowed_next(Move move, DfsData *dd); | ||
| 6 | static void dfs(Cube c, Step *s, SolveOptions *opts, DfsData *dd); | ||
| 7 | static void dfs_branch(Cube c, Step *s, SolveOptions *os, DfsData *dd); | ||
| 8 | static bool dfs_check_solved(Step *s, SolveOptions *opts, DfsData *dd); | ||
| 9 | static void dfs_niss(Cube c, Step *s, SolveOptions *opts, DfsData *dd); | ||
| 10 | static bool dfs_stop(Cube c, Step *s, SolveOptions *opts, DfsData *dd); | ||
| 11 | |||
| 12 | /* Local functions ***********************************************************/ | ||
| 13 | |||
| 14 | static bool | ||
| 15 | allowed_next(Move move, DfsData *dd) | ||
| 16 | { | ||
| 17 | |||
| 18 | /* TODO: remove the commented part, was added to moves.c | ||
| 19 | static bool initialized = false; | ||
| 20 | static bool commute[NMOVES][NMOVES], pnext[NMOVES][NMOVES][NMOVES]; | ||
| 21 | |||
| 22 | if (!initialized) { | ||
| 23 | Cube c1, c2; | ||
| 24 | int i, j, k; | ||
| 25 | bool p1, p2, cij; | ||
| 26 | |||
| 27 | for (i = 0; i < NMOVES; i++) { | ||
| 28 | for (j = 0; j < NMOVES; j++) { | ||
| 29 | c1 = apply_move(i, apply_move(j, (Cube){0})); | ||
| 30 | c2 = apply_move(j, apply_move(i, (Cube){0})); | ||
| 31 | commute[i][j] = equal(c1, c2) && i && j; | ||
| 32 | for (k = 0; k < NMOVES; k++) { | ||
| 33 | p1 = j && base_move(j) == base_move(k); | ||
| 34 | p2 = i && base_move(i) == base_move(k); | ||
| 35 | cij = commute[i][j]; | ||
| 36 | pnext[i][j][k] = !(p1 || (cij && p2)); | ||
| 37 | } | ||
| 38 | } | ||
| 39 | } | ||
| 40 | |||
| 41 | initialized = true; | ||
| 42 | } | ||
| 43 | |||
| 44 | if (!pnext[dd->last2][dd->last1][move]) | ||
| 45 | return false; | ||
| 46 | |||
| 47 | if (commute[dd->last1][move]) | ||
| 48 | return dd->move_position[dd->last1] < dd->move_position[move]; | ||
| 49 | |||
| 50 | return true; | ||
| 51 | */ | ||
| 52 | |||
| 53 | if (!possible_next(dd->last2, dd->last1, move)) | ||
| 54 | return false; | ||
| 55 | |||
| 56 | if (commute(dd->last1, move)) | ||
| 57 | return dd->move_position[dd->last1] < dd->move_position[move]; | ||
| 58 | |||
| 59 | return true; | ||
| 60 | } | ||
| 61 | |||
| 62 | static void | ||
| 63 | dfs(Cube c, Step *s, SolveOptions *opts, DfsData *dd) | ||
| 64 | { | ||
| 65 | if (dfs_stop(c, s, opts, dd)) | ||
| 66 | return; | ||
| 67 | |||
| 68 | if (dfs_check_solved(s, opts, dd)) | ||
| 69 | return; | ||
| 70 | |||
| 71 | dfs_branch(c, s, opts, dd); | ||
| 72 | |||
| 73 | if (opts->can_niss && !dd->niss) | ||
| 74 | dfs_niss(c, s, opts, dd); | ||
| 75 | } | ||
| 76 | |||
| 77 | static void | ||
| 78 | dfs_branch(Cube c, Step *s, SolveOptions *opts, DfsData *dd) | ||
| 79 | { | ||
| 80 | Move m, l1 = dd->last1, l2 = dd->last2, *moves = dd->sorted_moves; | ||
| 81 | |||
| 82 | int i, maxnsol = opts->max_solutions; | ||
| 83 | |||
| 84 | for (i = 0; moves[i] != NULLMOVE && dd->sols->len < maxnsol; i++) { | ||
| 85 | m = moves[i]; | ||
| 86 | if (allowed_next(m, dd)) { | ||
| 87 | dd->last2 = dd->last1; | ||
| 88 | dd->last1 = m; | ||
| 89 | append_move(dd->current_alg, m, dd->niss); | ||
| 90 | |||
| 91 | dfs(apply_move(m, c), s, opts, dd); | ||
| 92 | |||
| 93 | dd->current_alg->len--; | ||
| 94 | dd->last2 = l2; | ||
| 95 | dd->last1 = l1; | ||
| 96 | } | ||
| 97 | } | ||
| 98 | } | ||
| 99 | |||
| 100 | static bool | ||
| 101 | dfs_check_solved(Step *s, SolveOptions *opts, DfsData *dd) | ||
| 102 | { | ||
| 103 | if (dd->lb != 0) | ||
| 104 | return false; | ||
| 105 | |||
| 106 | if (dd->current_alg->len == dd->d) { | ||
| 107 | if (s->is_valid(dd->current_alg) || opts->all) | ||
| 108 | append_alg(dd->sols, dd->current_alg); | ||
| 109 | |||
| 110 | if (opts->feedback) | ||
| 111 | print_alg(dd->current_alg, false); | ||
| 112 | } | ||
| 113 | |||
| 114 | return true; | ||
| 115 | } | ||
| 116 | |||
| 117 | static void | ||
| 118 | dfs_niss(Cube c, Step *s, SolveOptions *opts, DfsData *dd) | ||
| 119 | { | ||
| 120 | Move l1 = dd->last1, l2 = dd->last2; | ||
| 121 | CubeTarget ct; | ||
| 122 | |||
| 123 | ct.cube = apply_move(inverse_move(l1), (Cube){0}); | ||
| 124 | ct.target = 1; | ||
| 125 | |||
| 126 | if (dd->current_alg->len == 0 || s->estimate(ct)) { | ||
| 127 | dd->niss = true; | ||
| 128 | dd->last1 = NULLMOVE; | ||
| 129 | dd->last2 = NULLMOVE; | ||
| 130 | |||
| 131 | dfs(inverse_cube(c), s, opts, dd); | ||
| 132 | |||
| 133 | dd->last1 = l1; | ||
| 134 | dd->last2 = l2; | ||
| 135 | dd->niss = false; | ||
| 136 | } | ||
| 137 | } | ||
| 138 | |||
| 139 | static bool | ||
| 140 | dfs_stop(Cube c, Step *s, SolveOptions *opts, DfsData *dd) | ||
| 141 | { | ||
| 142 | CubeTarget ct = { | ||
| 143 | .cube = c, | ||
| 144 | .target = dd->d - dd->current_alg->len | ||
| 145 | }; | ||
| 146 | |||
| 147 | if (dd->sols->len >= opts->max_solutions) | ||
| 148 | return true; | ||
| 149 | |||
| 150 | dd->lb = s->estimate(ct); | ||
| 151 | if (opts->can_niss && !dd->niss) | ||
| 152 | dd->lb = MIN(1, dd->lb); | ||
| 153 | |||
| 154 | if (dd->current_alg->len + dd->lb > dd->d) | ||
| 155 | return true; | ||
| 156 | |||
| 157 | return false; | ||
| 158 | } | ||
| 159 | |||
| 160 | /* Public functions **********************************************************/ | ||
| 161 | |||
| 162 | AlgList * | ||
| 163 | solve(Cube cube, Step *step, SolveOptions *opts) | ||
| 164 | { | ||
| 165 | AlgListNode *node; | ||
| 166 | AlgList *sols = new_alglist(); | ||
| 167 | Cube c; | ||
| 168 | |||
| 169 | if (step->detect != NULL) | ||
| 170 | step->pre_trans = step->detect(cube); | ||
| 171 | c = apply_trans(step->pre_trans, cube); | ||
| 172 | |||
| 173 | DfsData dd = { | ||
| 174 | .m = 0, | ||
| 175 | .niss = false, | ||
| 176 | .lb = -1, | ||
| 177 | .last1 = NULLMOVE, | ||
| 178 | .last2 = NULLMOVE, | ||
| 179 | .sols = sols, | ||
| 180 | .current_alg = new_alg("") | ||
| 181 | }; | ||
| 182 | |||
| 183 | if (step->ready != NULL && !step->ready(c)) { | ||
| 184 | fprintf(stderr, "Cube not ready for solving step: "); | ||
| 185 | fprintf(stderr, "%s\n", step->ready_msg); | ||
| 186 | return sols; | ||
| 187 | } | ||
| 188 | |||
| 189 | moveset_to_list(step->moveset, dd.sorted_moves); | ||
| 190 | movelist_to_position(dd.sorted_moves, dd.move_position); | ||
| 191 | |||
| 192 | for (dd.d = opts->min_moves; | ||
| 193 | dd.d <= opts->max_moves && | ||
| 194 | !(sols->len && opts->optimal_only) && | ||
| 195 | sols->len < opts->max_solutions; | ||
| 196 | dd.d++) { | ||
| 197 | if (opts->feedback) | ||
| 198 | fprintf(stderr, | ||
| 199 | "Found %d solutions, searching depth %d...\n", | ||
| 200 | sols->len, dd.d); | ||
| 201 | dfs(c, step, opts, &dd); | ||
| 202 | } | ||
| 203 | |||
| 204 | for (node = sols->first; node != NULL; node = node->next) | ||
| 205 | transform_alg(inverse_trans(step->pre_trans), node->alg); | ||
| 206 | |||
| 207 | free_alg(dd.current_alg); | ||
| 208 | return sols; | ||
| 209 | } | ||
diff --git a/old/2021-11-10-beforeremovingchecker/solve.h b/old/2021-11-10-beforeremovingchecker/solve.h new file mode 100644 index 0000000..ff84e7e --- /dev/null +++ b/old/2021-11-10-beforeremovingchecker/solve.h | |||
| @@ -0,0 +1,9 @@ | |||
| 1 | #ifndef SOLVE_H | ||
| 2 | #define SOLVE_H | ||
| 3 | |||
| 4 | #include "moves.h" | ||
| 5 | #include "trans.h" | ||
| 6 | |||
| 7 | AlgList * solve(Cube cube, Step *step, SolveOptions *opts); | ||
| 8 | |||
| 9 | #endif | ||
diff --git a/old/2021-11-10-beforeremovingchecker/steps.c b/old/2021-11-10-beforeremovingchecker/steps.c new file mode 100644 index 0000000..7213766 --- /dev/null +++ b/old/2021-11-10-beforeremovingchecker/steps.c | |||
| @@ -0,0 +1,916 @@ | |||
| 1 | #include "steps.h" | ||
| 2 | |||
| 3 | /* Standard checkers (return lower bound) ************************************/ | ||
| 4 | |||
| 5 | static int estimate_eoany_HTM(CubeTarget ct); | ||
| 6 | static int estimate_eofb_HTM(CubeTarget ct); | ||
| 7 | static int estimate_coany_HTM(CubeTarget ct); | ||
| 8 | static int estimate_coud_HTM(CubeTarget ct); | ||
| 9 | static int estimate_coany_URF(CubeTarget ct); | ||
| 10 | static int estimate_coud_URF(CubeTarget ct); | ||
| 11 | static int estimate_corners_HTM(CubeTarget ct); | ||
| 12 | static int estimate_cornershtr_HTM(CubeTarget ct); | ||
| 13 | static int estimate_corners_URF(CubeTarget ct); | ||
| 14 | static int estimate_cornershtr_URF(CubeTarget ct); | ||
| 15 | static int estimate_drany_HTM(CubeTarget ct); | ||
| 16 | static int estimate_drud_HTM(CubeTarget ct); | ||
| 17 | static int estimate_drud_eofb(CubeTarget ct); | ||
| 18 | static int estimate_dr_eofb(CubeTarget ct); | ||
| 19 | static int estimate_drudfin_drud(CubeTarget ct); | ||
| 20 | static int estimate_htr_drud(CubeTarget ct); | ||
| 21 | static int estimate_htrfin_htr(CubeTarget ct); | ||
| 22 | static int estimate_optimal_HTM(CubeTarget ct); | ||
| 23 | |||
| 24 | /* Validators ****************************************************************/ | ||
| 25 | |||
| 26 | static bool always_valid(Alg *alg); | ||
| 27 | static bool validate_singlecw_ending(Alg *alg); | ||
| 28 | |||
| 29 | /* Pre-transformation detectors **********************************************/ | ||
| 30 | |||
| 31 | static Trans detect_pretrans_eofb(Cube cube); | ||
| 32 | static Trans detect_pretrans_drud(Cube cube); | ||
| 33 | |||
| 34 | /* Messages for when cube is not ready ***************************************/ | ||
| 35 | |||
| 36 | static char check_centers_msg[100] = "cube must be oriented (centers solved)"; | ||
| 37 | static char check_eo_msg[100] = "EO must be solved on given axis"; | ||
| 38 | static char check_dr_msg[100] = "DR must be solved on given axis"; | ||
| 39 | static char check_htr_msg[100] = "HTR must be solved"; | ||
| 40 | static char check_drany_msg[100] = "DR must be solved on at least one axis"; | ||
| 41 | |||
| 42 | /* Steps *********************************************************************/ | ||
| 43 | |||
| 44 | Step | ||
| 45 | optimal_HTM = { | ||
| 46 | .shortname = "optimal", | ||
| 47 | .name = "Optimal solve (in HTM)", | ||
| 48 | |||
| 49 | .estimate = estimate_optimal_HTM, | ||
| 50 | .ready = check_centers, | ||
| 51 | .ready_msg = check_centers_msg, | ||
| 52 | .is_valid = always_valid, | ||
| 53 | .moveset = moveset_HTM, | ||
| 54 | |||
| 55 | .pre_trans = uf, | ||
| 56 | }; | ||
| 57 | |||
| 58 | /* EO steps **************************/ | ||
| 59 | Step | ||
| 60 | eoany_HTM = { | ||
| 61 | .shortname = "eo", | ||
| 62 | .name = "EO on any axis", | ||
| 63 | |||
| 64 | .estimate = estimate_eoany_HTM, | ||
| 65 | .ready = check_centers, | ||
| 66 | .ready_msg = check_centers_msg, | ||
| 67 | .is_valid = validate_singlecw_ending, | ||
| 68 | .moveset = moveset_HTM, | ||
| 69 | |||
| 70 | .pre_trans = uf, | ||
| 71 | }; | ||
| 72 | |||
| 73 | Step | ||
| 74 | eofb_HTM = { | ||
| 75 | .shortname = "eofb", | ||
| 76 | .name = "EO on F/B", | ||
| 77 | |||
| 78 | .estimate = estimate_eofb_HTM, | ||
| 79 | .ready = check_centers, | ||
| 80 | .ready_msg = check_centers_msg, | ||
| 81 | .is_valid = validate_singlecw_ending, | ||
| 82 | .moveset = moveset_HTM, | ||
| 83 | |||
| 84 | .pre_trans = uf, | ||
| 85 | }; | ||
| 86 | |||
| 87 | Step | ||
| 88 | eorl_HTM = { | ||
| 89 | .shortname = "eorl", | ||
| 90 | .name = "EO on R/L", | ||
| 91 | |||
| 92 | .estimate = estimate_eofb_HTM, | ||
| 93 | .ready = check_centers, | ||
| 94 | .ready_msg = check_centers_msg, | ||
| 95 | .is_valid = validate_singlecw_ending, | ||
| 96 | .moveset = moveset_HTM, | ||
| 97 | |||
| 98 | .pre_trans = ur, | ||
| 99 | }; | ||
| 100 | |||
| 101 | Step | ||
| 102 | eoud_HTM = { | ||
| 103 | .shortname = "eoud", | ||
| 104 | .name = "EO on U/D", | ||
| 105 | |||
| 106 | .estimate = estimate_eofb_HTM, | ||
| 107 | .ready = check_centers, | ||
| 108 | .ready_msg = check_centers_msg, | ||
| 109 | .is_valid = validate_singlecw_ending, | ||
| 110 | .moveset = moveset_HTM, | ||
| 111 | |||
| 112 | .pre_trans = fd, | ||
| 113 | }; | ||
| 114 | |||
| 115 | /* CO steps **************************/ | ||
| 116 | Step | ||
| 117 | coany_HTM = { | ||
| 118 | .shortname = "co", | ||
| 119 | .name = "CO on any axis", | ||
| 120 | |||
| 121 | .estimate = estimate_coany_HTM, | ||
| 122 | .ready = NULL, | ||
| 123 | .is_valid = validate_singlecw_ending, | ||
| 124 | .moveset = moveset_HTM, | ||
| 125 | |||
| 126 | .pre_trans = uf, | ||
| 127 | }; | ||
| 128 | |||
| 129 | Step | ||
| 130 | coud_HTM = { | ||
| 131 | .shortname = "coud", | ||
| 132 | .name = "CO on U/D", | ||
| 133 | |||
| 134 | .estimate = estimate_coud_HTM, | ||
| 135 | .ready = NULL, | ||
| 136 | .is_valid = validate_singlecw_ending, | ||
| 137 | .moveset = moveset_HTM, | ||
| 138 | |||
| 139 | .pre_trans = uf, | ||
| 140 | }; | ||
| 141 | |||
| 142 | Step | ||
| 143 | corl_HTM = { | ||
| 144 | .shortname = "corl", | ||
| 145 | .name = "CO on R/L", | ||
| 146 | |||
| 147 | .estimate = estimate_coud_HTM, | ||
| 148 | .ready = NULL, | ||
| 149 | .is_valid = validate_singlecw_ending, | ||
| 150 | .moveset = moveset_HTM, | ||
| 151 | |||
| 152 | .pre_trans = rf, | ||
| 153 | }; | ||
| 154 | |||
| 155 | Step | ||
| 156 | cofb_HTM = { | ||
| 157 | .shortname = "cofb", | ||
| 158 | .name = "CO on F/B", | ||
| 159 | |||
| 160 | .estimate = estimate_coud_HTM, | ||
| 161 | .ready = NULL, | ||
| 162 | .is_valid = validate_singlecw_ending, | ||
| 163 | .moveset = moveset_HTM, | ||
| 164 | |||
| 165 | .pre_trans = fd, | ||
| 166 | }; | ||
| 167 | |||
| 168 | Step | ||
| 169 | coany_URF = { | ||
| 170 | .shortname = "co-URF", | ||
| 171 | .name = "CO any axis (URF moveset)", | ||
| 172 | |||
| 173 | .estimate = estimate_coany_URF, | ||
| 174 | .ready = NULL, | ||
| 175 | .is_valid = validate_singlecw_ending, | ||
| 176 | .moveset = moveset_URF, | ||
| 177 | |||
| 178 | .pre_trans = uf, | ||
| 179 | }; | ||
| 180 | |||
| 181 | Step | ||
| 182 | coud_URF = { | ||
| 183 | .shortname = "coud-URF", | ||
| 184 | .name = "CO on U/D (URF moveset)", | ||
| 185 | |||
| 186 | .estimate = estimate_coud_URF, | ||
| 187 | .ready = NULL, | ||
| 188 | .is_valid = validate_singlecw_ending, | ||
| 189 | .moveset = moveset_URF, | ||
| 190 | |||
| 191 | .pre_trans = uf, | ||
| 192 | }; | ||
| 193 | |||
| 194 | Step | ||
| 195 | corl_URF = { | ||
| 196 | .shortname = "corl-URF", | ||
| 197 | .name = "CO on R/L (URF moveset)", | ||
| 198 | |||
| 199 | .estimate = estimate_coud_URF, | ||
| 200 | .ready = NULL, | ||
| 201 | .is_valid = validate_singlecw_ending, | ||
| 202 | .moveset = moveset_URF, | ||
| 203 | |||
| 204 | .pre_trans = rf, | ||
| 205 | }; | ||
| 206 | |||
| 207 | Step | ||
| 208 | cofb_URF = { | ||
| 209 | .shortname = "cofb-URF", | ||
| 210 | .name = "CO on F/B (URF moveset)", | ||
| 211 | |||
| 212 | .estimate = estimate_coud_URF, | ||
| 213 | .ready = NULL, | ||
| 214 | .is_valid = validate_singlecw_ending, | ||
| 215 | .moveset = moveset_URF, | ||
| 216 | |||
| 217 | .pre_trans = fd, | ||
| 218 | }; | ||
| 219 | |||
| 220 | /* Misc corner steps *****************/ | ||
| 221 | Step | ||
| 222 | cornershtr_HTM = { | ||
| 223 | .shortname = "chtr", | ||
| 224 | .name = "Solve corners to HTR state", | ||
| 225 | |||
| 226 | .estimate = estimate_cornershtr_HTM, | ||
| 227 | .ready = NULL, | ||
| 228 | .is_valid = validate_singlecw_ending, | ||
| 229 | .moveset = moveset_HTM, | ||
| 230 | |||
| 231 | .pre_trans = uf, | ||
| 232 | }; | ||
| 233 | |||
| 234 | Step | ||
| 235 | cornershtr_URF = { | ||
| 236 | .shortname = "chtr-URF", | ||
| 237 | .name = "Solve corners to HTR state (URF moveset)", | ||
| 238 | |||
| 239 | .estimate = estimate_cornershtr_URF, | ||
| 240 | .ready = NULL, | ||
| 241 | .is_valid = validate_singlecw_ending, | ||
| 242 | .moveset = moveset_URF, | ||
| 243 | |||
| 244 | .pre_trans = uf, | ||
| 245 | }; | ||
| 246 | |||
| 247 | Step | ||
| 248 | corners_HTM = { | ||
| 249 | .shortname = "corners", | ||
| 250 | .name = "Solve corners", | ||
| 251 | |||
| 252 | .estimate = estimate_corners_HTM, | ||
| 253 | .ready = NULL, | ||
| 254 | .is_valid = always_valid, | ||
| 255 | .moveset = moveset_HTM, | ||
| 256 | |||
| 257 | .pre_trans = uf, | ||
| 258 | }; | ||
| 259 | |||
| 260 | Step | ||
| 261 | corners_URF = { | ||
| 262 | .shortname = "corners-URF", | ||
| 263 | .name = "Solve corners (URF moveset)", | ||
| 264 | |||
| 265 | .estimate = estimate_corners_URF, | ||
| 266 | .ready = NULL, | ||
| 267 | .is_valid = always_valid, | ||
| 268 | .moveset = moveset_URF, | ||
| 269 | |||
| 270 | .pre_trans = uf, | ||
| 271 | }; | ||
| 272 | |||
| 273 | /* DR steps **************************/ | ||
| 274 | Step | ||
| 275 | drany_HTM = { | ||
| 276 | .shortname = "dr", | ||
| 277 | .name = "DR on any axis", | ||
| 278 | |||
| 279 | .estimate = estimate_drany_HTM, | ||
| 280 | .ready = check_centers, | ||
| 281 | .ready_msg = check_centers_msg, | ||
| 282 | .is_valid = validate_singlecw_ending, | ||
| 283 | .moveset = moveset_HTM, | ||
| 284 | |||
| 285 | .pre_trans = uf, | ||
| 286 | }; | ||
| 287 | |||
| 288 | Step | ||
| 289 | drud_HTM = { | ||
| 290 | .shortname = "drud", | ||
| 291 | .name = "DR on U/D", | ||
| 292 | |||
| 293 | .estimate = estimate_drud_HTM, | ||
| 294 | .ready = check_centers, | ||
| 295 | .ready_msg = check_centers_msg, | ||
| 296 | .is_valid = validate_singlecw_ending, | ||
| 297 | .moveset = moveset_HTM, | ||
| 298 | |||
| 299 | .pre_trans = uf, | ||
| 300 | }; | ||
| 301 | |||
| 302 | Step | ||
| 303 | drrl_HTM = { | ||
| 304 | .shortname = "drrl", | ||
| 305 | .name = "DR on R/L", | ||
| 306 | |||
| 307 | .estimate = estimate_drud_HTM, | ||
| 308 | .ready = check_centers, | ||
| 309 | .ready_msg = check_centers_msg, | ||
| 310 | .is_valid = validate_singlecw_ending, | ||
| 311 | .moveset = moveset_HTM, | ||
| 312 | |||
| 313 | .pre_trans = rf, | ||
| 314 | }; | ||
| 315 | |||
| 316 | Step | ||
| 317 | drfb_HTM = { | ||
| 318 | .shortname = "drfb", | ||
| 319 | .name = "DR on F/B", | ||
| 320 | |||
| 321 | .estimate = estimate_drud_HTM, | ||
| 322 | .ready = check_centers, | ||
| 323 | .ready_msg = check_centers_msg, | ||
| 324 | .is_valid = validate_singlecw_ending, | ||
| 325 | .moveset = moveset_HTM, | ||
| 326 | |||
| 327 | .pre_trans = fd, | ||
| 328 | }; | ||
| 329 | |||
| 330 | /* DR from EO */ | ||
| 331 | Step | ||
| 332 | dr_eo = { | ||
| 333 | .shortname = "dr-eo", | ||
| 334 | .name = "DR without breaking EO (automatically detected)", | ||
| 335 | |||
| 336 | .estimate = estimate_dr_eofb, | ||
| 337 | .ready = check_eofb, | ||
| 338 | .ready_msg = check_eo_msg, | ||
| 339 | .is_valid = validate_singlecw_ending, | ||
| 340 | .moveset = moveset_eofb, | ||
| 341 | |||
| 342 | .detect = detect_pretrans_eofb, | ||
| 343 | }; | ||
| 344 | |||
| 345 | Step | ||
| 346 | dr_eofb = { | ||
| 347 | .shortname = "dr-eofb", | ||
| 348 | .name = "DR on U/D or R/L without breaking EO on F/B", | ||
| 349 | |||
| 350 | .estimate = estimate_dr_eofb, | ||
| 351 | .ready = check_eofb, | ||
| 352 | .ready_msg = check_eo_msg, | ||
| 353 | .is_valid = validate_singlecw_ending, | ||
| 354 | .moveset = moveset_eofb, | ||
| 355 | |||
| 356 | .pre_trans = uf, | ||
| 357 | }; | ||
| 358 | |||
| 359 | Step | ||
| 360 | dr_eorl = { | ||
| 361 | .shortname = "dr-eorl", | ||
| 362 | .name = "DR on U/D or F/B without breaking EO on R/L", | ||
| 363 | |||
| 364 | .estimate = estimate_dr_eofb, | ||
| 365 | .ready = check_eofb, | ||
| 366 | .ready_msg = check_eo_msg, | ||
| 367 | .is_valid = validate_singlecw_ending, | ||
| 368 | .moveset = moveset_eofb, | ||
| 369 | |||
| 370 | .pre_trans = ur, | ||
| 371 | }; | ||
| 372 | |||
| 373 | Step | ||
| 374 | dr_eoud = { | ||
| 375 | .shortname = "dr-eoud", | ||
| 376 | .name = "DR on R/L or F/B without breaking EO on U/R", | ||
| 377 | |||
| 378 | .estimate = estimate_dr_eofb, | ||
| 379 | .ready = check_eofb, | ||
| 380 | .ready_msg = check_eo_msg, | ||
| 381 | .is_valid = validate_singlecw_ending, | ||
| 382 | .moveset = moveset_eofb, | ||
| 383 | |||
| 384 | .pre_trans = fd, | ||
| 385 | }; | ||
| 386 | |||
| 387 | Step | ||
| 388 | drud_eofb = { | ||
| 389 | .shortname = "drud-eofb", | ||
| 390 | .name = "DR on U/D without breaking EO on F/B", | ||
| 391 | |||
| 392 | .estimate = estimate_drud_eofb, | ||
| 393 | .ready = check_eofb, | ||
| 394 | .ready_msg = check_eo_msg, | ||
| 395 | .is_valid = validate_singlecw_ending, | ||
| 396 | .moveset = moveset_eofb, | ||
| 397 | |||
| 398 | .pre_trans = uf, | ||
| 399 | }; | ||
| 400 | |||
| 401 | Step | ||
| 402 | drrl_eofb = { | ||
| 403 | .shortname = "drrl-eofb", | ||
| 404 | .name = "DR on R/L without breaking EO on F/B", | ||
| 405 | |||
| 406 | .estimate = estimate_drud_eofb, | ||
| 407 | .ready = check_eofb, | ||
| 408 | .ready_msg = check_eo_msg, | ||
| 409 | .is_valid = validate_singlecw_ending, | ||
| 410 | .moveset = moveset_eofb, | ||
| 411 | |||
| 412 | .pre_trans = rf, | ||
| 413 | }; | ||
| 414 | |||
| 415 | Step | ||
| 416 | drud_eorl = { | ||
| 417 | .shortname = "drud-eorl", | ||
| 418 | .name = "DR on U/D without breaking EO on R/L", | ||
| 419 | |||
| 420 | .estimate = estimate_drud_eofb, | ||
| 421 | .ready = check_eofb, | ||
| 422 | .ready_msg = check_eo_msg, | ||
| 423 | .is_valid = validate_singlecw_ending, | ||
| 424 | .moveset = moveset_eofb, | ||
| 425 | |||
| 426 | .pre_trans = ur, | ||
| 427 | }; | ||
| 428 | |||
| 429 | Step | ||
| 430 | drfb_eorl = { | ||
| 431 | .shortname = "drfb-eorl", | ||
| 432 | .name = "DR on F/B without breaking EO on R/L", | ||
| 433 | |||
| 434 | .estimate = estimate_drud_eofb, | ||
| 435 | .ready = check_eofb, | ||
| 436 | .ready_msg = check_eo_msg, | ||
| 437 | .is_valid = validate_singlecw_ending, | ||
| 438 | .moveset = moveset_eofb, | ||
| 439 | |||
| 440 | .pre_trans = fr, | ||
| 441 | }; | ||
| 442 | |||
| 443 | Step | ||
| 444 | drfb_eoud = { | ||
| 445 | .shortname = "drfb-eoud", | ||
| 446 | .name = "DR on F/B without breaking EO on U/D", | ||
| 447 | |||
| 448 | .estimate = estimate_drud_eofb, | ||
| 449 | .ready = check_eofb, | ||
| 450 | .ready_msg = check_eo_msg, | ||
| 451 | .is_valid = validate_singlecw_ending, | ||
| 452 | .moveset = moveset_eofb, | ||
| 453 | |||
| 454 | .pre_trans = fd, | ||
| 455 | }; | ||
| 456 | |||
| 457 | Step | ||
| 458 | drrl_eoud = { | ||
| 459 | .shortname = "drrl-eoud", | ||
| 460 | .name = "DR on R/L without breaking EO on U/D", | ||
| 461 | |||
| 462 | .estimate = estimate_drud_eofb, | ||
| 463 | .ready = check_eofb, | ||
| 464 | .ready_msg = check_eo_msg, | ||
| 465 | .is_valid = validate_singlecw_ending, | ||
| 466 | .moveset = moveset_eofb, | ||
| 467 | |||
| 468 | .pre_trans = rd, | ||
| 469 | }; | ||
| 470 | |||
| 471 | /* DR finish steps */ | ||
| 472 | Step | ||
| 473 | dranyfin_DR = { | ||
| 474 | .shortname = "drfin", | ||
| 475 | .name = "DR finish on any axis without breaking DR", | ||
| 476 | |||
| 477 | .estimate = estimate_drudfin_drud, | ||
| 478 | .ready = check_drud, | ||
| 479 | .ready_msg = check_drany_msg, | ||
| 480 | .is_valid = always_valid, | ||
| 481 | .moveset = moveset_drud, | ||
| 482 | |||
| 483 | .detect = detect_pretrans_drud, | ||
| 484 | }; | ||
| 485 | |||
| 486 | Step | ||
| 487 | drudfin_drud = { | ||
| 488 | .shortname = "drudfin", | ||
| 489 | .name = "DR finish on U/D without breaking DR", | ||
| 490 | |||
| 491 | .estimate = estimate_drudfin_drud, | ||
| 492 | .ready = check_drud, | ||
| 493 | .ready_msg = check_dr_msg, | ||
| 494 | .is_valid = always_valid, | ||
| 495 | .moveset = moveset_drud, | ||
| 496 | |||
| 497 | .pre_trans = uf, | ||
| 498 | }; | ||
| 499 | |||
| 500 | Step | ||
| 501 | drrlfin_drrl = { | ||
| 502 | .shortname = "drrlfin", | ||
| 503 | .name = "DR finish on R/L without breaking DR", | ||
| 504 | |||
| 505 | .estimate = estimate_drudfin_drud, | ||
| 506 | .ready = check_drud, | ||
| 507 | .ready_msg = check_dr_msg, | ||
| 508 | .is_valid = always_valid, | ||
| 509 | .moveset = moveset_drud, | ||
| 510 | |||
| 511 | .pre_trans = rf, | ||
| 512 | }; | ||
| 513 | |||
| 514 | Step | ||
| 515 | drfbfin_drfb = { | ||
| 516 | .shortname = "drfbfin", | ||
| 517 | .name = "DR finish on F/B without breaking DR", | ||
| 518 | |||
| 519 | .estimate = estimate_drudfin_drud, | ||
| 520 | .ready = check_drud, | ||
| 521 | .ready_msg = check_dr_msg, | ||
| 522 | .is_valid = always_valid, | ||
| 523 | .moveset = moveset_drud, | ||
| 524 | |||
| 525 | .pre_trans = fd, | ||
| 526 | }; | ||
| 527 | |||
| 528 | /* HTR from DR */ | ||
| 529 | Step | ||
| 530 | htr_any = { | ||
| 531 | .shortname = "htr", | ||
| 532 | .name = "HTR from DR", | ||
| 533 | |||
| 534 | .estimate = estimate_htr_drud, | ||
| 535 | .ready = check_drud, | ||
| 536 | .ready_msg = check_drany_msg, | ||
| 537 | .is_valid = validate_singlecw_ending, | ||
| 538 | .moveset = moveset_drud, | ||
| 539 | |||
| 540 | .detect = detect_pretrans_drud, | ||
| 541 | }; | ||
| 542 | |||
| 543 | Step | ||
| 544 | htr_drud = { | ||
| 545 | .shortname = "htr-drud", | ||
| 546 | .name = "HTR from DR on U/D", | ||
| 547 | |||
| 548 | .estimate = estimate_htr_drud, | ||
| 549 | .ready = check_drud, | ||
| 550 | .ready_msg = check_dr_msg, | ||
| 551 | .is_valid = validate_singlecw_ending, | ||
| 552 | .moveset = moveset_drud, | ||
| 553 | |||
| 554 | .pre_trans = uf, | ||
| 555 | }; | ||
| 556 | |||
| 557 | Step | ||
| 558 | htr_drrl = { | ||
| 559 | .shortname = "htr-drrl", | ||
| 560 | .name = "HTR from DR on R/L", | ||
| 561 | |||
| 562 | .estimate = estimate_htr_drud, | ||
| 563 | .ready = check_drud, | ||
| 564 | .ready_msg = check_dr_msg, | ||
| 565 | .is_valid = validate_singlecw_ending, | ||
| 566 | .moveset = moveset_drud, | ||
| 567 | |||
| 568 | .pre_trans = rf, | ||
| 569 | }; | ||
| 570 | |||
| 571 | Step | ||
| 572 | htr_drfb = { | ||
| 573 | .shortname = "htr-drfb", | ||
| 574 | .name = "HTR from DR on F/B", | ||
| 575 | |||
| 576 | .estimate = estimate_htr_drud, | ||
| 577 | .ready = check_drud, | ||
| 578 | .ready_msg = check_dr_msg, | ||
| 579 | .is_valid = validate_singlecw_ending, | ||
| 580 | .moveset = moveset_drud, | ||
| 581 | |||
| 582 | .pre_trans = fd, | ||
| 583 | }; | ||
| 584 | |||
| 585 | /* HTR finish */ | ||
| 586 | Step | ||
| 587 | htrfin_htr = { | ||
| 588 | .shortname = "htrfin", | ||
| 589 | .name = "HTR finish without breaking HTR", | ||
| 590 | |||
| 591 | .estimate = estimate_htrfin_htr, | ||
| 592 | .ready = check_htr, | ||
| 593 | .ready_msg = check_htr_msg, | ||
| 594 | .is_valid = always_valid, | ||
| 595 | .moveset = moveset_htr, | ||
| 596 | |||
| 597 | .pre_trans = uf, | ||
| 598 | }; | ||
| 599 | |||
| 600 | Step *steps[NSTEPS] = { | ||
| 601 | &optimal_HTM, /* first is default */ | ||
| 602 | |||
| 603 | &eoany_HTM, | ||
| 604 | &eofb_HTM, | ||
| 605 | &eorl_HTM, | ||
| 606 | &eoud_HTM, | ||
| 607 | |||
| 608 | &coany_HTM, | ||
| 609 | &coud_HTM, | ||
| 610 | &corl_HTM, | ||
| 611 | &cofb_HTM, | ||
| 612 | |||
| 613 | &coany_URF, | ||
| 614 | &coud_URF, | ||
| 615 | &corl_URF, | ||
| 616 | &cofb_URF, | ||
| 617 | |||
| 618 | &drany_HTM, | ||
| 619 | &drud_HTM, | ||
| 620 | &drrl_HTM, | ||
| 621 | &drfb_HTM, | ||
| 622 | |||
| 623 | &dr_eo, | ||
| 624 | &dr_eofb, | ||
| 625 | &dr_eorl, | ||
| 626 | &dr_eoud, | ||
| 627 | &drud_eofb, | ||
| 628 | &drrl_eofb, | ||
| 629 | &drud_eorl, | ||
| 630 | &drfb_eorl, | ||
| 631 | &drfb_eoud, | ||
| 632 | &drrl_eoud, | ||
| 633 | |||
| 634 | &dranyfin_DR, | ||
| 635 | &drudfin_drud, | ||
| 636 | &drrlfin_drrl, | ||
| 637 | &drfbfin_drfb, | ||
| 638 | |||
| 639 | &htr_any, | ||
| 640 | &htr_drud, | ||
| 641 | &htr_drrl, | ||
| 642 | &htr_drfb, | ||
| 643 | |||
| 644 | &htrfin_htr, | ||
| 645 | |||
| 646 | &cornershtr_HTM, | ||
| 647 | &cornershtr_URF, | ||
| 648 | &corners_HTM, | ||
| 649 | &corners_URF, | ||
| 650 | }; | ||
| 651 | |||
| 652 | /* Standard checkers (return lower bound) ************************************/ | ||
| 653 | |||
| 654 | static int | ||
| 655 | estimate_eoany_HTM(CubeTarget ct) | ||
| 656 | { | ||
| 657 | int r1, r2, r3; | ||
| 658 | |||
| 659 | r1 = ptableval(&pd_eofb_HTM, ct.cube); | ||
| 660 | r2 = ptableval(&pd_eofb_HTM, apply_trans(ur, ct.cube)); | ||
| 661 | r3 = ptableval(&pd_eofb_HTM, apply_trans(fd, ct.cube)); | ||
| 662 | |||
| 663 | return MIN(r1, MIN(r2, r3)); | ||
| 664 | } | ||
| 665 | |||
| 666 | static int | ||
| 667 | estimate_eofb_HTM(CubeTarget ct) | ||
| 668 | { | ||
| 669 | return ptableval(&pd_eofb_HTM, ct.cube); | ||
| 670 | } | ||
| 671 | |||
| 672 | static int | ||
| 673 | estimate_coany_HTM(CubeTarget ct) | ||
| 674 | { | ||
| 675 | int r1, r2, r3; | ||
| 676 | |||
| 677 | r1 = ptableval(&pd_coud_HTM, ct.cube); | ||
| 678 | r2 = ptableval(&pd_coud_HTM, apply_trans(rf, ct.cube)); | ||
| 679 | r3 = ptableval(&pd_coud_HTM, apply_trans(fd, ct.cube)); | ||
| 680 | |||
| 681 | return MIN(r1, MIN(r2, r3)); | ||
| 682 | } | ||
| 683 | |||
| 684 | static int | ||
| 685 | estimate_coud_HTM(CubeTarget ct) | ||
| 686 | { | ||
| 687 | return ptableval(&pd_coud_HTM, ct.cube); | ||
| 688 | } | ||
| 689 | |||
| 690 | static int | ||
| 691 | estimate_coany_URF(CubeTarget ct) | ||
| 692 | { | ||
| 693 | int r1, r2, r3; | ||
| 694 | CubeTarget ct2, ct3; | ||
| 695 | |||
| 696 | ct2.cube = apply_trans(rf, ct.cube); | ||
| 697 | ct2.target = ct.target; | ||
| 698 | |||
| 699 | ct3.cube = apply_trans(fd, ct.cube); | ||
| 700 | ct3.target = ct.target; | ||
| 701 | |||
| 702 | r1 = estimate_coud_URF(ct); | ||
| 703 | r2 = estimate_coud_URF(ct2); | ||
| 704 | r3 = estimate_coud_URF(ct3); | ||
| 705 | |||
| 706 | return MIN(r1, MIN(r2, r3)); | ||
| 707 | } | ||
| 708 | |||
| 709 | static int | ||
| 710 | estimate_coud_URF(CubeTarget ct) | ||
| 711 | { | ||
| 712 | /* TODO: I can improve this by checking first the orientation of | ||
| 713 | * the corner in DBL and use that as a reference */ | ||
| 714 | |||
| 715 | CubeTarget ct2 = {.cube = apply_move(z, ct.cube), .target = ct.target}; | ||
| 716 | CubeTarget ct3 = {.cube = apply_move(x, ct.cube), .target = ct.target}; | ||
| 717 | |||
| 718 | int ud = estimate_coud_HTM(ct); | ||
| 719 | int rl = estimate_coud_HTM(ct2); | ||
| 720 | int fb = estimate_coud_HTM(ct3); | ||
| 721 | |||
| 722 | return MIN(ud, MIN(rl, fb)); | ||
| 723 | } | ||
| 724 | |||
| 725 | static int | ||
| 726 | estimate_corners_HTM(CubeTarget ct) | ||
| 727 | { | ||
| 728 | return ptableval(&pd_corners_HTM, ct.cube); | ||
| 729 | } | ||
| 730 | |||
| 731 | static int | ||
| 732 | estimate_cornershtr_HTM(CubeTarget ct) | ||
| 733 | { | ||
| 734 | return ptableval(&pd_cornershtr_HTM, ct.cube); | ||
| 735 | } | ||
| 736 | |||
| 737 | static int | ||
| 738 | estimate_cornershtr_URF(CubeTarget ct) | ||
| 739 | { | ||
| 740 | /* TODO: I can improve this by checking first the corner in DBL | ||
| 741 | * and use that as a reference */ | ||
| 742 | |||
| 743 | int c, ret = 15; | ||
| 744 | Trans i; | ||
| 745 | |||
| 746 | for (i = 0; i < NROTATIONS; i++) { | ||
| 747 | ct.cube = apply_alg(rotation_alg(i), ct.cube); | ||
| 748 | c = estimate_cornershtr_HTM(ct); | ||
| 749 | ret = MIN(ret, c); | ||
| 750 | } | ||
| 751 | |||
| 752 | return ret; | ||
| 753 | } | ||
| 754 | |||
| 755 | static int | ||
| 756 | estimate_corners_URF(CubeTarget ct) | ||
| 757 | { | ||
| 758 | /* TODO: I can improve this by checking first the corner in DBL | ||
| 759 | * and use that as a reference */ | ||
| 760 | |||
| 761 | int c, ret = 15; | ||
| 762 | Trans i; | ||
| 763 | |||
| 764 | for (i = 0; i < NROTATIONS; i++) { | ||
| 765 | ct.cube = apply_alg(rotation_alg(i), ct.cube); | ||
| 766 | c = estimate_corners_HTM(ct); | ||
| 767 | ret = MIN(ret, c); | ||
| 768 | } | ||
| 769 | |||
| 770 | return ret; | ||
| 771 | } | ||
| 772 | |||
| 773 | static int | ||
| 774 | estimate_drany_HTM(CubeTarget ct) | ||
| 775 | { | ||
| 776 | int r1, r2, r3; | ||
| 777 | |||
| 778 | r1 = ptableval(&pd_drud_sym16_HTM, ct.cube); | ||
| 779 | r2 = ptableval(&pd_drud_sym16_HTM, apply_trans(rf, ct.cube)); | ||
| 780 | r3 = ptableval(&pd_drud_sym16_HTM, apply_trans(fd, ct.cube)); | ||
| 781 | |||
| 782 | return MIN(r1, MIN(r2, r3)); | ||
| 783 | } | ||
| 784 | |||
| 785 | static int | ||
| 786 | estimate_drud_HTM(CubeTarget ct) | ||
| 787 | { | ||
| 788 | return ptableval(&pd_drud_sym16_HTM, ct.cube); | ||
| 789 | } | ||
| 790 | |||
| 791 | static int | ||
| 792 | estimate_drud_eofb(CubeTarget ct) | ||
| 793 | { | ||
| 794 | return ptableval(&pd_drud_eofb, ct.cube); | ||
| 795 | } | ||
| 796 | |||
| 797 | static int | ||
| 798 | estimate_dr_eofb(CubeTarget ct) | ||
| 799 | { | ||
| 800 | int r1, r2; | ||
| 801 | |||
| 802 | r1 = ptableval(&pd_drud_eofb, ct.cube); | ||
| 803 | r2 = ptableval(&pd_drud_eofb, apply_trans(rf, ct.cube)); | ||
| 804 | |||
| 805 | return MIN(r1, r2); | ||
| 806 | } | ||
| 807 | |||
| 808 | static int | ||
| 809 | estimate_drudfin_drud(CubeTarget ct) | ||
| 810 | { | ||
| 811 | int val = ptableval(&pd_drudfin_noE_sym16_drud, ct.cube); | ||
| 812 | |||
| 813 | if (val != 0) | ||
| 814 | return val; | ||
| 815 | |||
| 816 | return ct.cube.epose % 24 == 0 ? 0 : 1; | ||
| 817 | } | ||
| 818 | |||
| 819 | static int | ||
| 820 | estimate_htr_drud(CubeTarget ct) | ||
| 821 | { | ||
| 822 | return ptableval(&pd_htr_drud, ct.cube); | ||
| 823 | } | ||
| 824 | |||
| 825 | static int | ||
| 826 | estimate_htrfin_htr(CubeTarget ct) | ||
| 827 | { | ||
| 828 | return ptableval(&pd_htrfin_htr, ct.cube); | ||
| 829 | } | ||
| 830 | |||
| 831 | static int | ||
| 832 | estimate_optimal_HTM(CubeTarget ct) | ||
| 833 | { | ||
| 834 | int dr1, dr2, dr3, cor, ret; | ||
| 835 | Cube cube = ct.cube; | ||
| 836 | |||
| 837 | dr1 = ptableval(&pd_khuge_HTM, cube); | ||
| 838 | cor = estimate_corners_HTM(ct); | ||
| 839 | ret = MAX(dr1, cor); | ||
| 840 | |||
| 841 | if (ret > ct.target) | ||
| 842 | return ret; | ||
| 843 | |||
| 844 | cube = apply_trans(rf, ct.cube); | ||
| 845 | dr2 = ptableval(&pd_khuge_HTM, cube); | ||
| 846 | ret = MAX(ret, dr2); | ||
| 847 | |||
| 848 | if (ret > ct.target) | ||
| 849 | return ret; | ||
| 850 | |||
| 851 | cube = apply_trans(fd, ct.cube); | ||
| 852 | dr3 = ptableval(&pd_khuge_HTM, cube); | ||
| 853 | |||
| 854 | /* Michiel de Bondt's trick */ | ||
| 855 | if (dr1 == dr2 && dr2 == dr3 && dr1 != 0) | ||
| 856 | dr3++; | ||
| 857 | |||
| 858 | return MAX(ret, dr3); | ||
| 859 | } | ||
| 860 | |||
| 861 | /* Validators ****************************************************************/ | ||
| 862 | |||
| 863 | static bool | ||
| 864 | always_valid(Alg *alg) | ||
| 865 | { | ||
| 866 | return true; | ||
| 867 | } | ||
| 868 | |||
| 869 | static bool | ||
| 870 | validate_singlecw_ending(Alg *alg) | ||
| 871 | { | ||
| 872 | int i; | ||
| 873 | bool nor, inv; | ||
| 874 | Move l2 = NULLMOVE, l1 = NULLMOVE, l2i = NULLMOVE, l1i = NULLMOVE; | ||
| 875 | |||
| 876 | for (i = 0; i < alg->len; i++) { | ||
| 877 | if (alg->inv[i]) { | ||
| 878 | l2i = l1i; | ||
| 879 | l1i = alg->move[i]; | ||
| 880 | } else { | ||
| 881 | l2 = l1; | ||
| 882 | l1 = alg->move[i]; | ||
| 883 | } | ||
| 884 | } | ||
| 885 | |||
| 886 | nor = l1 ==base_move(l1) && (!commute(l1, l2) ||l2 ==base_move(l2)); | ||
| 887 | inv = l1i==base_move(l1i) && (!commute(l1i,l2i)||l2i==base_move(l2i)); | ||
| 888 | |||
| 889 | return nor && inv; | ||
| 890 | } | ||
| 891 | |||
| 892 | /* Pre-transformation detectors **********************************************/ | ||
| 893 | |||
| 894 | static Trans | ||
| 895 | detect_pretrans_eofb(Cube cube) | ||
| 896 | { | ||
| 897 | Trans i; | ||
| 898 | |||
| 899 | for (i = 0; i < NROTATIONS; i++) | ||
| 900 | if (check_eofb(apply_trans(i, cube))) | ||
| 901 | return i; | ||
| 902 | |||
| 903 | return 0; | ||
| 904 | } | ||
| 905 | |||
| 906 | static Trans | ||
| 907 | detect_pretrans_drud(Cube cube) | ||
| 908 | { | ||
| 909 | Trans i; | ||
| 910 | |||
| 911 | for (i = 0; i < NROTATIONS; i++) | ||
| 912 | if (check_drud(apply_trans(i, cube))) | ||
| 913 | return i; | ||
| 914 | |||
| 915 | return 0; | ||
| 916 | } | ||
diff --git a/old/2021-11-10-beforeremovingchecker/steps.h b/old/2021-11-10-beforeremovingchecker/steps.h new file mode 100644 index 0000000..aa3178c --- /dev/null +++ b/old/2021-11-10-beforeremovingchecker/steps.h | |||
| @@ -0,0 +1,10 @@ | |||
| 1 | #ifndef STEPS_H | ||
| 2 | #define STEPS_H | ||
| 3 | |||
| 4 | #include "pruning.h" | ||
| 5 | |||
| 6 | #define NSTEPS 50 | ||
| 7 | |||
| 8 | extern Step * steps[NSTEPS]; | ||
| 9 | |||
| 10 | #endif | ||
diff --git a/old/2021-11-10-beforeremovingchecker/symcoord.c b/old/2021-11-10-beforeremovingchecker/symcoord.c new file mode 100644 index 0000000..9a4d49a --- /dev/null +++ b/old/2021-11-10-beforeremovingchecker/symcoord.c | |||
| @@ -0,0 +1,359 @@ | |||
| 1 | #include "symcoord.h" | ||
| 2 | |||
| 3 | static Cube antindex_coud_sym16(uint64_t ind); | ||
| 4 | static Cube antindex_cp_sym16(uint64_t ind); | ||
| 5 | static Cube antindex_eofbepos_sym16(uint64_t ind); | ||
| 6 | static Cube antindex_drud_sym16(uint64_t ind); | ||
| 7 | static Cube antindex_drudfin_noE_sym16(uint64_t ind); | ||
| 8 | static Cube antindex_khuge(uint64_t ind); | ||
| 9 | |||
| 10 | static uint64_t index_coud_sym16(Cube cube); | ||
| 11 | static uint64_t index_cp_sym16(Cube cube); | ||
| 12 | static uint64_t index_eofbepos_sym16(Cube cube); | ||
| 13 | static uint64_t index_drud_sym16(Cube cube); | ||
| 14 | static uint64_t index_drudfin_noE_sym16(Cube cube); | ||
| 15 | static uint64_t index_khuge(Cube cube); | ||
| 16 | |||
| 17 | static void gensym(SymData *sd); | ||
| 18 | static bool read_symdata_file(SymData *sd); | ||
| 19 | static bool write_symdata_file(SymData *sd); | ||
| 20 | |||
| 21 | /* Transformation groups and symmetry data ***********************************/ | ||
| 22 | |||
| 23 | static Trans | ||
| 24 | trans_group_udfix[16] = { | ||
| 25 | uf, ur, ub, ul, | ||
| 26 | df, dr, db, dl, | ||
| 27 | uf_mirror, ur_mirror, ub_mirror, ul_mirror, | ||
| 28 | df_mirror, dr_mirror, db_mirror, dl_mirror, | ||
| 29 | }; | ||
| 30 | |||
| 31 | static SymData | ||
| 32 | sd_coud_16 = { | ||
| 33 | .filename = "sd_coud_16", | ||
| 34 | .coord = &coord_coud, | ||
| 35 | .sym_coord = &coord_coud_sym16, | ||
| 36 | .ntrans = 16, | ||
| 37 | .trans = trans_group_udfix | ||
| 38 | }; | ||
| 39 | |||
| 40 | static SymData | ||
| 41 | sd_cp_16 = { | ||
| 42 | .filename = "sd_cp_16", | ||
| 43 | .coord = &coord_cp, | ||
| 44 | .sym_coord = &coord_cp_sym16, | ||
| 45 | .ntrans = 16, | ||
| 46 | .trans = trans_group_udfix | ||
| 47 | }; | ||
| 48 | |||
| 49 | static SymData | ||
| 50 | sd_eofbepos_16 = { | ||
| 51 | .filename = "sd_eofbepos_16", | ||
| 52 | .coord = &coord_eofbepos, | ||
| 53 | .sym_coord = &coord_eofbepos_sym16, | ||
| 54 | .ntrans = 16, | ||
| 55 | .trans = trans_group_udfix | ||
| 56 | }; | ||
| 57 | |||
| 58 | static int nsymdata = 3; | ||
| 59 | static SymData * all_sd[] = { | ||
| 60 | &sd_coud_16, | ||
| 61 | &sd_cp_16, | ||
| 62 | &sd_eofbepos_16, | ||
| 63 | }; | ||
| 64 | |||
| 65 | |||
| 66 | /* Coordinates and their implementation **************************************/ | ||
| 67 | |||
| 68 | Coordinate | ||
| 69 | coord_eofbepos_sym16 = { | ||
| 70 | .index = index_eofbepos_sym16, | ||
| 71 | .cube = antindex_eofbepos_sym16, | ||
| 72 | .check = check_eofbepos, | ||
| 73 | .ntrans = 16, | ||
| 74 | .trans = trans_group_udfix, | ||
| 75 | }; | ||
| 76 | |||
| 77 | Coordinate | ||
| 78 | coord_coud_sym16 = { | ||
| 79 | .index = index_coud_sym16, | ||
| 80 | .cube = antindex_coud_sym16, | ||
| 81 | .check = check_coud, | ||
| 82 | .ntrans = 16, | ||
| 83 | .trans = trans_group_udfix, | ||
| 84 | }; | ||
| 85 | |||
| 86 | Coordinate | ||
| 87 | coord_cp_sym16 = { | ||
| 88 | .index = index_cp_sym16, | ||
| 89 | .cube = antindex_cp_sym16, | ||
| 90 | .check = check_cp, | ||
| 91 | .ntrans = 16, | ||
| 92 | .trans = trans_group_udfix, | ||
| 93 | }; | ||
| 94 | |||
| 95 | Coordinate | ||
| 96 | coord_drud_sym16 = { | ||
| 97 | .index = index_drud_sym16, | ||
| 98 | .cube = antindex_drud_sym16, | ||
| 99 | .check = check_drud, | ||
| 100 | .max = POW3TO7 * 64430, | ||
| 101 | .ntrans = 16, | ||
| 102 | .trans = trans_group_udfix, | ||
| 103 | }; | ||
| 104 | |||
| 105 | Coordinate | ||
| 106 | coord_drudfin_noE_sym16 = { | ||
| 107 | .index = index_drudfin_noE_sym16, | ||
| 108 | .cube = antindex_drudfin_noE_sym16, | ||
| 109 | .check = check_drudfin_noE, | ||
| 110 | .max = FACTORIAL8 * 2768, | ||
| 111 | .ntrans = 16, | ||
| 112 | .trans = trans_group_udfix, | ||
| 113 | }; | ||
| 114 | |||
| 115 | Coordinate | ||
| 116 | coord_khuge = { | ||
| 117 | .index = index_khuge, | ||
| 118 | .cube = antindex_khuge, | ||
| 119 | .check = check_khuge, | ||
| 120 | .max = POW3TO7 * FACTORIAL4 * 64430, | ||
| 121 | .ntrans = 16, | ||
| 122 | .trans = trans_group_udfix, | ||
| 123 | }; | ||
| 124 | |||
| 125 | /* Functions *****************************************************************/ | ||
| 126 | |||
| 127 | static Cube | ||
| 128 | antindex_coud_sym16(uint64_t ind) | ||
| 129 | { | ||
| 130 | return sd_coud_16.rep[ind]; | ||
| 131 | } | ||
| 132 | |||
| 133 | static Cube | ||
| 134 | antindex_cp_sym16(uint64_t ind) | ||
| 135 | { | ||
| 136 | return sd_cp_16.rep[ind]; | ||
| 137 | } | ||
| 138 | |||
| 139 | static Cube | ||
| 140 | antindex_eofbepos_sym16(uint64_t ind) | ||
| 141 | { | ||
| 142 | return sd_eofbepos_16.rep[ind]; | ||
| 143 | } | ||
| 144 | |||
| 145 | static Cube | ||
| 146 | antindex_drud_sym16(uint64_t ind) | ||
| 147 | { | ||
| 148 | Cube c; | ||
| 149 | |||
| 150 | c = antindex_eofbepos_sym16(ind/POW3TO7); | ||
| 151 | c.coud = ind % POW3TO7; | ||
| 152 | c.cofb = c.coud; | ||
| 153 | c.corl = c.coud; | ||
| 154 | |||
| 155 | return c; | ||
| 156 | } | ||
| 157 | |||
| 158 | static Cube | ||
| 159 | antindex_drudfin_noE_sym16(uint64_t ind) | ||
| 160 | { | ||
| 161 | Cube c1, c2; | ||
| 162 | |||
| 163 | c1 = coord_epud.cube(ind % FACTORIAL8); | ||
| 164 | c2 = antindex_cp_sym16(ind/FACTORIAL8); | ||
| 165 | c1.cp = c2.cp; | ||
| 166 | |||
| 167 | return c1; | ||
| 168 | } | ||
| 169 | |||
| 170 | static Cube | ||
| 171 | antindex_khuge(uint64_t ind) | ||
| 172 | { | ||
| 173 | Cube c; | ||
| 174 | |||
| 175 | c = antindex_eofbepos_sym16(ind/(FACTORIAL4*POW3TO7)); | ||
| 176 | c.epose = ((c.epose / 24) * 24) + ((ind/POW3TO7) % 24); | ||
| 177 | c.coud = ind % POW3TO7; | ||
| 178 | |||
| 179 | return c; | ||
| 180 | } | ||
| 181 | |||
| 182 | static uint64_t | ||
| 183 | index_coud_sym16(Cube cube) | ||
| 184 | { | ||
| 185 | return sd_coud_16.class[coord_coud.index(cube)]; | ||
| 186 | } | ||
| 187 | |||
| 188 | static uint64_t | ||
| 189 | index_cp_sym16(Cube cube) | ||
| 190 | { | ||
| 191 | return sd_cp_16.class[coord_cp.index(cube)]; | ||
| 192 | } | ||
| 193 | |||
| 194 | static uint64_t | ||
| 195 | index_drud_sym16(Cube cube) | ||
| 196 | { | ||
| 197 | Trans t; | ||
| 198 | Cube c; | ||
| 199 | |||
| 200 | t = sd_eofbepos_16.transtorep[coord_eofbepos.index(cube)]; | ||
| 201 | c = apply_trans(t, cube); | ||
| 202 | |||
| 203 | return index_eofbepos_sym16(c) * POW3TO7 + c.coud; | ||
| 204 | } | ||
| 205 | |||
| 206 | static uint64_t | ||
| 207 | index_drudfin_noE_sym16(Cube cube) | ||
| 208 | { | ||
| 209 | Trans t; | ||
| 210 | Cube c; | ||
| 211 | |||
| 212 | t = sd_cp_16.transtorep[coord_cp.index(cube)]; | ||
| 213 | c = apply_trans(t, cube); | ||
| 214 | |||
| 215 | return index_cp_sym16(c) * FACTORIAL8 + coord_epud.index(c); | ||
| 216 | } | ||
| 217 | |||
| 218 | static uint64_t | ||
| 219 | index_eofbepos_sym16(Cube cube) | ||
| 220 | { | ||
| 221 | return sd_eofbepos_16.class[coord_eofbepos.index(cube)]; | ||
| 222 | } | ||
| 223 | |||
| 224 | static uint64_t | ||
| 225 | index_khuge(Cube cube) | ||
| 226 | { | ||
| 227 | Trans t; | ||
| 228 | Cube c; | ||
| 229 | uint64_t a; | ||
| 230 | |||
| 231 | t = sd_eofbepos_16.transtorep[coord_eofbepos.index(cube)]; | ||
| 232 | c = apply_trans(t, cube); | ||
| 233 | a = (index_eofbepos_sym16(c) * 24) + (c.epose % 24); | ||
| 234 | |||
| 235 | return a * POW3TO7 + c.coud; | ||
| 236 | } | ||
| 237 | |||
| 238 | /* Other functions ***********************************************************/ | ||
| 239 | |||
| 240 | static void | ||
| 241 | gensym(SymData *sd) | ||
| 242 | { | ||
| 243 | uint64_t i, in, nreps = 0; | ||
| 244 | int j; | ||
| 245 | Cube c, d; | ||
| 246 | |||
| 247 | if (sd->generated) | ||
| 248 | return; | ||
| 249 | |||
| 250 | sd->class = malloc(sd->coord->max * sizeof(uint64_t)); | ||
| 251 | sd->rep = malloc(sd->coord->max * sizeof(Cube)); | ||
| 252 | sd->transtorep = malloc(sd->coord->max * sizeof(Trans)); | ||
| 253 | |||
| 254 | if (read_symdata_file(sd)) { | ||
| 255 | sd->generated = true; | ||
| 256 | return; | ||
| 257 | } | ||
| 258 | |||
| 259 | fprintf(stderr, "Cannot load %s, generating it\n", sd->filename); | ||
| 260 | |||
| 261 | for (i = 0; i < sd->coord->max; i++) | ||
| 262 | sd->class[i] = sd->coord->max + 1; | ||
| 263 | |||
| 264 | for (i = 0; i < sd->coord->max; i++) { | ||
| 265 | if (sd->class[i] == sd->coord->max + 1) { | ||
| 266 | c = sd->coord->cube(i); | ||
| 267 | sd->rep[nreps] = c; | ||
| 268 | for (j = 0; j < sd->ntrans; j++) { | ||
| 269 | d = apply_trans(sd->trans[j], c); | ||
| 270 | in = sd->coord->index(d); | ||
| 271 | |||
| 272 | if (sd->class[in] == sd->coord->max + 1) { | ||
| 273 | sd->class[in] = nreps; | ||
| 274 | sd->transtorep[in] = | ||
| 275 | inverse_trans(sd->trans[j]); | ||
| 276 | } | ||
| 277 | } | ||
| 278 | nreps++; | ||
| 279 | } | ||
| 280 | } | ||
| 281 | |||
| 282 | sd->sym_coord->max = nreps; | ||
| 283 | sd->rep = realloc(sd->rep, nreps * sizeof(Cube)); | ||
| 284 | sd->generated = true; | ||
| 285 | |||
| 286 | fprintf(stderr, "Found %lu classes\n", nreps); | ||
| 287 | |||
| 288 | if (!write_symdata_file(sd)) | ||
| 289 | fprintf(stderr, "Error writing SymData file\n"); | ||
| 290 | |||
| 291 | return; | ||
| 292 | } | ||
| 293 | |||
| 294 | static bool | ||
| 295 | read_symdata_file(SymData *sd) | ||
| 296 | { | ||
| 297 | init_env(); | ||
| 298 | |||
| 299 | FILE *f; | ||
| 300 | char fname[strlen(tabledir)+100]; | ||
| 301 | uint64_t n = sd->coord->max, *sn = &sd->sym_coord->max; | ||
| 302 | bool r = true; | ||
| 303 | |||
| 304 | strcpy(fname, tabledir); | ||
| 305 | strcat(fname, "/"); | ||
| 306 | strcat(fname, sd->filename); | ||
| 307 | |||
| 308 | if ((f = fopen(fname, "rb")) == NULL) | ||
| 309 | return false; | ||
| 310 | |||
| 311 | r = r && fread(&sd->sym_coord->max, sizeof(uint64_t), 1, f) == 1; | ||
| 312 | r = r && fread(sd->rep, sizeof(Cube), *sn, f) == *sn; | ||
| 313 | r = r && fread(sd->class, sizeof(uint64_t), n, f) == n; | ||
| 314 | r = r && fread(sd->transtorep, sizeof(Trans), n, f) == n; | ||
| 315 | |||
| 316 | fclose(f); | ||
| 317 | return r; | ||
| 318 | } | ||
| 319 | |||
| 320 | static bool | ||
| 321 | write_symdata_file(SymData *sd) | ||
| 322 | { | ||
| 323 | init_env(); | ||
| 324 | |||
| 325 | FILE *f; | ||
| 326 | char fname[strlen(tabledir)+100]; | ||
| 327 | uint64_t n = sd->coord->max, *sn = &sd->sym_coord->max; | ||
| 328 | bool r = true; | ||
| 329 | |||
| 330 | strcpy(fname, tabledir); | ||
| 331 | strcat(fname, "/"); | ||
| 332 | strcat(fname, sd->filename); | ||
| 333 | |||
| 334 | if ((f = fopen(fname, "wb")) == NULL) | ||
| 335 | return false; | ||
| 336 | |||
| 337 | r = r && fwrite(&sd->sym_coord->max, sizeof(uint64_t), 1, f) == 1; | ||
| 338 | r = r && fwrite(sd->rep, sizeof(Cube), *sn, f) == *sn; | ||
| 339 | r = r && fwrite(sd->class, sizeof(uint64_t), n, f) == n; | ||
| 340 | r = r && fwrite(sd->transtorep, sizeof(Trans), n, f) == n; | ||
| 341 | |||
| 342 | fclose(f); | ||
| 343 | return r; | ||
| 344 | } | ||
| 345 | |||
| 346 | void | ||
| 347 | init_symcoord() | ||
| 348 | { | ||
| 349 | int i; | ||
| 350 | |||
| 351 | static bool initialized = false; | ||
| 352 | if (initialized) | ||
| 353 | return; | ||
| 354 | initialized = true; | ||
| 355 | |||
| 356 | for (i = 0; i < nsymdata; i++) | ||
| 357 | gensym(all_sd[i]); | ||
| 358 | } | ||
| 359 | |||
diff --git a/old/2021-11-10-beforeremovingchecker/symcoord.h b/old/2021-11-10-beforeremovingchecker/symcoord.h new file mode 100644 index 0000000..f231c92 --- /dev/null +++ b/old/2021-11-10-beforeremovingchecker/symcoord.h | |||
| @@ -0,0 +1,15 @@ | |||
| 1 | #ifndef SYMCOORD_H | ||
| 2 | #define SYMCOORD_H | ||
| 3 | |||
| 4 | #include "coord.h" | ||
| 5 | |||
| 6 | extern Coordinate coord_coud_sym16; | ||
| 7 | extern Coordinate coord_cp_sym16; | ||
| 8 | extern Coordinate coord_eofbepos_sym16; | ||
| 9 | extern Coordinate coord_drud_sym16; | ||
| 10 | extern Coordinate coord_drudfin_noE_sym16; | ||
| 11 | extern Coordinate coord_khuge; | ||
| 12 | |||
| 13 | void init_symcoord(); | ||
| 14 | |||
| 15 | #endif | ||
diff --git a/old/2021-11-10-beforeremovingchecker/trans.c b/old/2021-11-10-beforeremovingchecker/trans.c new file mode 100644 index 0000000..ff3cdbb --- /dev/null +++ b/old/2021-11-10-beforeremovingchecker/trans.c | |||
| @@ -0,0 +1,372 @@ | |||
| 1 | #include "trans.h" | ||
| 2 | |||
| 3 | /* Local functions ***********************************************************/ | ||
| 4 | |||
| 5 | static bool read_ttables_file(); | ||
| 6 | static Cube rotate_via_compose(Trans r, Cube c, PieceFilter f); | ||
| 7 | static bool write_ttables_file(); | ||
| 8 | |||
| 9 | /* Tables and other data *****************************************************/ | ||
| 10 | |||
| 11 | static int ep_mirror[12] = { | ||
| 12 | [UF] = UF, [UL] = UR, [UB] = UB, [UR] = UL, | ||
| 13 | [DF] = DF, [DL] = DR, [DB] = DB, [DR] = DL, | ||
| 14 | [FR] = FL, [FL] = FR, [BL] = BR, [BR] = BL | ||
| 15 | }; | ||
| 16 | |||
| 17 | static int cp_mirror[8] = { | ||
| 18 | [UFR] = UFL, [UFL] = UFR, [UBL] = UBR, [UBR] = UBL, | ||
| 19 | [DFR] = DFL, [DFL] = DFR, [DBL] = DBR, [DBR] = DBL | ||
| 20 | }; | ||
| 21 | |||
| 22 | static int cpos_mirror[6] = { | ||
| 23 | [U_center] = U_center, [D_center] = D_center, | ||
| 24 | [R_center] = L_center, [L_center] = R_center, | ||
| 25 | [F_center] = F_center, [B_center] = B_center | ||
| 26 | }; | ||
| 27 | |||
| 28 | /* TODO Is there a more elegant way? */ | ||
| 29 | static char rotation_alg_string[100][NROTATIONS] = { | ||
| 30 | [uf] = "", [ur] = "y", [ub] = "y2", [ul] = "y3", | ||
| 31 | [df] = "z2", [dr] = "y z2", [db] = "x2", [dl] = "y3 z2", | ||
| 32 | [rf] = "z3", [rd] = "z3 y", [rb] = "z3 y2", [ru] = "z3 y3", | ||
| 33 | [lf] = "z", [ld] = "z y3", [lb] = "z y2", [lu] = "z y", | ||
| 34 | [fu] = "x y2", [fr] = "x y", [fd] = "x", [fl] = "x y3", | ||
| 35 | [bu] = "x3", [br] = "x3 y", [bd] = "x3 y2", [bl] = "x3 y3", | ||
| 36 | }; | ||
| 37 | |||
| 38 | static int epose_source[NTRANS]; /* 0=epose, 1=eposs, 2=eposm */ | ||
| 39 | static int eposs_source[NTRANS]; | ||
| 40 | static int eposm_source[NTRANS]; | ||
| 41 | static int eofb_source[NTRANS]; /* 0=eoud, 1=eorl, 2=eofb */ | ||
| 42 | static int eorl_source[NTRANS]; | ||
| 43 | static int eoud_source[NTRANS]; | ||
| 44 | static int coud_source[NTRANS]; /* 0=coud, 1=corl, 2=cofb */ | ||
| 45 | static int cofb_source[NTRANS]; | ||
| 46 | static int corl_source[NTRANS]; | ||
| 47 | |||
| 48 | static int epose_ttable[NTRANS][FACTORIAL12/FACTORIAL8]; | ||
| 49 | static int eposs_ttable[NTRANS][FACTORIAL12/FACTORIAL8]; | ||
| 50 | static int eposm_ttable[NTRANS][FACTORIAL12/FACTORIAL8]; | ||
| 51 | static int eo_ttable[NTRANS][POW2TO11]; | ||
| 52 | static int cp_ttable[NTRANS][FACTORIAL8]; | ||
| 53 | static int co_ttable[NTRANS][POW3TO7]; | ||
| 54 | static int cpos_ttable[NTRANS][FACTORIAL6]; | ||
| 55 | static Move moves_ttable[NTRANS][NMOVES]; | ||
| 56 | |||
| 57 | /* Local functions implementation ********************************************/ | ||
| 58 | |||
| 59 | void | ||
| 60 | init_trans() { | ||
| 61 | static bool initialized = false; | ||
| 62 | if (initialized) | ||
| 63 | return; | ||
| 64 | initialized = true; | ||
| 65 | |||
| 66 | Cube aux, cube, c[3]; | ||
| 67 | CubeArray epcp; | ||
| 68 | int i, eparr[12], eoarr[12], cparr[8], coarr[8]; | ||
| 69 | unsigned int ui; | ||
| 70 | Move mi, move; | ||
| 71 | Trans m; | ||
| 72 | |||
| 73 | /* Compute sources */ | ||
| 74 | for (i = 0; i < NTRANS; i++) { | ||
| 75 | cube = apply_alg(rotation_alg(i), (Cube){0}); | ||
| 76 | |||
| 77 | epose_source[i] = edge_slice(what_edge_at(cube, FR)); | ||
| 78 | eposs_source[i] = edge_slice(what_edge_at(cube, UR)); | ||
| 79 | eposm_source[i] = edge_slice(what_edge_at(cube, UF)); | ||
| 80 | eofb_source[i] = what_center_at(cube, F_center)/2; | ||
| 81 | eorl_source[i] = what_center_at(cube, R_center)/2; | ||
| 82 | eoud_source[i] = what_center_at(cube, U_center)/2; | ||
| 83 | coud_source[i] = what_center_at(cube, U_center)/2; | ||
| 84 | cofb_source[i] = what_center_at(cube, F_center)/2; | ||
| 85 | corl_source[i] = what_center_at(cube, R_center)/2; | ||
| 86 | } | ||
| 87 | |||
| 88 | if (read_ttables_file()) | ||
| 89 | return; | ||
| 90 | |||
| 91 | fprintf(stderr, "Cannot load %s, generating it\n", "ttables"); | ||
| 92 | |||
| 93 | /* Initialize tables */ | ||
| 94 | for (m = 0; m < NTRANS; m++) { | ||
| 95 | epcp = (CubeArray){ .ep = eparr, .cp = cparr }; | ||
| 96 | cube = apply_alg(rotation_alg(m), (Cube){0}); | ||
| 97 | cube_to_arrays(cube, &epcp, pf_epcp); | ||
| 98 | if (m >= NROTATIONS) { | ||
| 99 | apply_permutation(ep_mirror, eparr, 12); | ||
| 100 | apply_permutation(cp_mirror, cparr, 8); | ||
| 101 | } | ||
| 102 | |||
| 103 | for (ui = 0; ui < FACTORIAL12/FACTORIAL8; ui++) { | ||
| 104 | c[0] = admissible_ep((Cube){ .epose = ui }, pf_e); | ||
| 105 | c[1] = admissible_ep((Cube){ .eposs = ui }, pf_s); | ||
| 106 | c[2] = admissible_ep((Cube){ .eposm = ui }, pf_m); | ||
| 107 | |||
| 108 | cube = rotate_via_compose(m,c[epose_source[m]],pf_ep); | ||
| 109 | epose_ttable[m][ui] = cube.epose; | ||
| 110 | |||
| 111 | cube = rotate_via_compose(m,c[eposs_source[m]],pf_ep); | ||
| 112 | eposs_ttable[m][ui] = cube.eposs; | ||
| 113 | |||
| 114 | cube = rotate_via_compose(m,c[eposm_source[m]],pf_ep); | ||
| 115 | eposm_ttable[m][ui] = cube.eposm; | ||
| 116 | } | ||
| 117 | for (ui = 0; ui < POW2TO11; ui++ ) { | ||
| 118 | int_to_sum_zero_array(ui, 2, 12, eoarr); | ||
| 119 | apply_permutation(eparr, eoarr, 12); | ||
| 120 | eo_ttable[m][ui] = digit_array_to_int(eoarr, 11, 2); | ||
| 121 | } | ||
| 122 | for (ui = 0; ui < POW3TO7; ui++) { | ||
| 123 | int_to_sum_zero_array(ui, 3, 8, coarr); | ||
| 124 | apply_permutation(cparr, coarr, 8); | ||
| 125 | co_ttable[m][ui] = digit_array_to_int(coarr, 7, 3); | ||
| 126 | if (m >= NROTATIONS) | ||
| 127 | co_ttable[m][ui] = | ||
| 128 | invert_digits(co_ttable[m][ui], 3, 7); | ||
| 129 | } | ||
| 130 | for (ui = 0; ui < FACTORIAL8; ui++) { | ||
| 131 | cube = (Cube){ .cp = ui }; | ||
| 132 | cube = rotate_via_compose(m, cube, pf_cp); | ||
| 133 | cp_ttable[m][ui] = cube.cp; | ||
| 134 | } | ||
| 135 | for (ui = 0; ui < FACTORIAL6; ui++) { | ||
| 136 | cube = (Cube){ .cpos = ui }; | ||
| 137 | cube = rotate_via_compose(m, cube, pf_cpos); | ||
| 138 | cpos_ttable[m][ui] = cube.cpos; | ||
| 139 | } | ||
| 140 | for (mi = 0; mi < NMOVES; mi++) { | ||
| 141 | /* Old version: | ||
| 142 | * | ||
| 143 | aux = apply_trans(m, apply_move(mi, (Cube){0})); | ||
| 144 | for (move = 0; move < NMOVES; move++) { | ||
| 145 | cube = apply_move(inverse_move(move), aux); | ||
| 146 | mirr = apply_trans(uf_mirror, cube); | ||
| 147 | if (is_solved(cube) || is_solved(mirr)) | ||
| 148 | moves_ttable[m][mi] = move; | ||
| 149 | } | ||
| 150 | */ | ||
| 151 | |||
| 152 | aux = apply_trans(m, apply_move(mi, (Cube){0})); | ||
| 153 | for (move = 0; move < NMOVES; move++) { | ||
| 154 | cube = apply_move(inverse_move(move), aux); | ||
| 155 | if (is_solved(cube)) { | ||
| 156 | moves_ttable[m][mi] = move; | ||
| 157 | break; | ||
| 158 | } | ||
| 159 | } | ||
| 160 | } | ||
| 161 | } | ||
| 162 | |||
| 163 | if (!write_ttables_file()) | ||
| 164 | fprintf(stderr, "Error writing ttables\n"); | ||
| 165 | } | ||
| 166 | |||
| 167 | static bool | ||
| 168 | read_ttables_file() | ||
| 169 | { | ||
| 170 | init_env(); | ||
| 171 | |||
| 172 | FILE *f; | ||
| 173 | char fname[strlen(tabledir)+20]; | ||
| 174 | int b = sizeof(int); | ||
| 175 | bool r = true; | ||
| 176 | Move m; | ||
| 177 | |||
| 178 | /* Table sizes, used for reading and writing files */ | ||
| 179 | uint64_t me[11] = { | ||
| 180 | [0] = FACTORIAL12/FACTORIAL8, | ||
| 181 | [1] = FACTORIAL12/FACTORIAL8, | ||
| 182 | [2] = FACTORIAL12/FACTORIAL8, | ||
| 183 | [3] = POW2TO11, | ||
| 184 | [4] = FACTORIAL8, | ||
| 185 | [5] = POW3TO7, | ||
| 186 | [6] = FACTORIAL6, | ||
| 187 | [7] = NMOVES | ||
| 188 | }; | ||
| 189 | |||
| 190 | strcpy(fname, tabledir); | ||
| 191 | strcat(fname, "/"); | ||
| 192 | strcat(fname, "ttables"); | ||
| 193 | |||
| 194 | if ((f = fopen(fname, "rb")) == NULL) | ||
| 195 | return false; | ||
| 196 | |||
| 197 | for (m = 0; m < NTRANS; m++) { | ||
| 198 | r = r && fread(epose_ttable[m], b, me[0], f) == me[0]; | ||
| 199 | r = r && fread(eposs_ttable[m], b, me[1], f) == me[1]; | ||
| 200 | r = r && fread(eposm_ttable[m], b, me[2], f) == me[2]; | ||
| 201 | r = r && fread(eo_ttable[m], b, me[3], f) == me[3]; | ||
| 202 | r = r && fread(cp_ttable[m], b, me[4], f) == me[4]; | ||
| 203 | r = r && fread(co_ttable[m], b, me[5], f) == me[5]; | ||
| 204 | r = r && fread(cpos_ttable[m], b, me[6], f) == me[6]; | ||
| 205 | r = r && fread(moves_ttable[m], b, me[7], f) == me[7]; | ||
| 206 | } | ||
| 207 | |||
| 208 | fclose(f); | ||
| 209 | return r; | ||
| 210 | } | ||
| 211 | |||
| 212 | static Cube | ||
| 213 | rotate_via_compose(Trans r, Cube c, PieceFilter f) | ||
| 214 | { | ||
| 215 | static int zero12[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; | ||
| 216 | static int zero8[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; | ||
| 217 | static CubeArray ma = { | ||
| 218 | .ep = ep_mirror, | ||
| 219 | .eofb = zero12, | ||
| 220 | .eorl = zero12, | ||
| 221 | .eoud = zero12, | ||
| 222 | .cp = cp_mirror, | ||
| 223 | .coud = zero8, | ||
| 224 | .corl = zero8, | ||
| 225 | .cofb = zero8, | ||
| 226 | .cpos = cpos_mirror | ||
| 227 | }; | ||
| 228 | |||
| 229 | Alg *inv = inverse_alg(rotation_alg(r)); | ||
| 230 | Cube ret = {0}; | ||
| 231 | |||
| 232 | if (r >= NROTATIONS) | ||
| 233 | ret = move_via_arrays(&ma, ret, f); | ||
| 234 | ret = apply_alg_generic(inv, ret, f, true); | ||
| 235 | |||
| 236 | ret = compose_filtered(c, ret, f); | ||
| 237 | |||
| 238 | ret = apply_alg_generic(rotation_alg(r), ret, f, true); | ||
| 239 | if (r >= NROTATIONS) | ||
| 240 | ret = move_via_arrays(&ma, ret, f); | ||
| 241 | |||
| 242 | free_alg(inv); | ||
| 243 | return ret; | ||
| 244 | } | ||
| 245 | |||
| 246 | static bool | ||
| 247 | write_ttables_file() | ||
| 248 | { | ||
| 249 | init_env(); | ||
| 250 | |||
| 251 | FILE *f; | ||
| 252 | char fname[strlen(tabledir)+20]; | ||
| 253 | bool r = true; | ||
| 254 | int b = sizeof(int); | ||
| 255 | Move m; | ||
| 256 | |||
| 257 | /* Table sizes, used for reading and writing files */ | ||
| 258 | uint64_t me[11] = { | ||
| 259 | [0] = FACTORIAL12/FACTORIAL8, | ||
| 260 | [1] = FACTORIAL12/FACTORIAL8, | ||
| 261 | [2] = FACTORIAL12/FACTORIAL8, | ||
| 262 | [3] = POW2TO11, | ||
| 263 | [4] = FACTORIAL8, | ||
| 264 | [5] = POW3TO7, | ||
| 265 | [6] = FACTORIAL6, | ||
| 266 | [7] = NMOVES | ||
| 267 | }; | ||
| 268 | |||
| 269 | strcpy(fname, tabledir); | ||
| 270 | strcat(fname, "/ttables"); | ||
| 271 | |||
| 272 | if ((f = fopen(fname, "wb")) == NULL) | ||
| 273 | return false; | ||
| 274 | |||
| 275 | for (m = 0; m < NTRANS; m++) { | ||
| 276 | r = r && fwrite(epose_ttable[m], b, me[0], f) == me[0]; | ||
| 277 | r = r && fwrite(eposs_ttable[m], b, me[1], f) == me[1]; | ||
| 278 | r = r && fwrite(eposm_ttable[m], b, me[2], f) == me[2]; | ||
| 279 | r = r && fwrite(eo_ttable[m], b, me[3], f) == me[3]; | ||
| 280 | r = r && fwrite(cp_ttable[m], b, me[4], f) == me[4]; | ||
| 281 | r = r && fwrite(co_ttable[m], b, me[5], f) == me[5]; | ||
| 282 | r = r && fwrite(cpos_ttable[m], b, me[6], f) == me[6]; | ||
| 283 | r = r && fwrite(moves_ttable[m], b, me[7], f) == me[7]; | ||
| 284 | } | ||
| 285 | |||
| 286 | fclose(f); | ||
| 287 | return r; | ||
| 288 | } | ||
| 289 | |||
| 290 | /* Public functions **********************************************************/ | ||
| 291 | |||
| 292 | Cube | ||
| 293 | apply_trans(Trans t, Cube cube) | ||
| 294 | { | ||
| 295 | /*init_trans();*/ | ||
| 296 | |||
| 297 | int aux_epos[3] = { cube.epose, cube.eposs, cube.eposm }; | ||
| 298 | int aux_eo[3] = { cube.eoud, cube.eorl, cube.eofb }; | ||
| 299 | int aux_co[3] = { cube.coud, cube.corl, cube.cofb }; | ||
| 300 | |||
| 301 | return (Cube) { | ||
| 302 | .epose = epose_ttable[t][aux_epos[epose_source[t]]], | ||
| 303 | .eposs = eposs_ttable[t][aux_epos[eposs_source[t]]], | ||
| 304 | .eposm = eposm_ttable[t][aux_epos[eposm_source[t]]], | ||
| 305 | .eofb = eo_ttable[t][aux_eo[eofb_source[t]]], | ||
| 306 | .eorl = eo_ttable[t][aux_eo[eorl_source[t]]], | ||
| 307 | .eoud = eo_ttable[t][aux_eo[eoud_source[t]]], | ||
| 308 | .coud = co_ttable[t][aux_co[coud_source[t]]], | ||
| 309 | .corl = co_ttable[t][aux_co[corl_source[t]]], | ||
| 310 | .cofb = co_ttable[t][aux_co[cofb_source[t]]], | ||
| 311 | .cp = cp_ttable[t][cube.cp], | ||
| 312 | .cpos = cpos_ttable[t][cube.cpos] | ||
| 313 | }; | ||
| 314 | } | ||
| 315 | |||
| 316 | Trans | ||
| 317 | inverse_trans(Trans t) | ||
| 318 | { | ||
| 319 | /* TODO is there a more elegant way? */ | ||
| 320 | static Trans inverse_trans_aux[NTRANS] = { | ||
| 321 | [uf] = uf, [ur] = ul, [ul] = ur, [ub] = ub, | ||
| 322 | [df] = df, [dr] = dr, [dl] = dl, [db] = db, | ||
| 323 | [rf] = lf, [rd] = bl, [rb] = rb, [ru] = fr, | ||
| 324 | [lf] = rf, [ld] = br, [lb] = lb, [lu] = fl, | ||
| 325 | [fu] = fu, [fr] = ru, [fd] = bu, [fl] = lu, | ||
| 326 | [bu] = fd, [br] = ld, [bd] = bd, [bl] = rd, | ||
| 327 | |||
| 328 | [uf_mirror] = uf_mirror, [ur_mirror] = ur_mirror, | ||
| 329 | [ul_mirror] = ul_mirror, [ub_mirror] = ub_mirror, | ||
| 330 | [df_mirror] = df_mirror, [dr_mirror] = dl_mirror, | ||
| 331 | [dl_mirror] = dr_mirror, [db_mirror] = db_mirror, | ||
| 332 | [rf_mirror] = rf_mirror, [rd_mirror] = br_mirror, | ||
| 333 | [rb_mirror] = lb_mirror, [ru_mirror] = fl_mirror, | ||
| 334 | [lf_mirror] = lf_mirror, [ld_mirror] = bl_mirror, | ||
| 335 | [lb_mirror] = rb_mirror, [lu_mirror] = fr_mirror, | ||
| 336 | [fu_mirror] = fu_mirror, [fr_mirror] = lu_mirror, | ||
| 337 | [fd_mirror] = bu_mirror, [fl_mirror] = ru_mirror, | ||
| 338 | [bu_mirror] = fd_mirror, [br_mirror] = rd_mirror, | ||
| 339 | [bd_mirror] = bd_mirror, [bl_mirror] = ld_mirror | ||
| 340 | }; | ||
| 341 | |||
| 342 | return inverse_trans_aux[t]; | ||
| 343 | } | ||
| 344 | |||
| 345 | Alg * | ||
| 346 | rotation_alg(Trans t) | ||
| 347 | { | ||
| 348 | int i; | ||
| 349 | |||
| 350 | static Alg *rotation_alg_arr[NROTATIONS]; | ||
| 351 | static bool initialized = false; | ||
| 352 | |||
| 353 | if (!initialized) { | ||
| 354 | for (i = 0; i < NROTATIONS; i++) | ||
| 355 | rotation_alg_arr[i] = new_alg(rotation_alg_string[i]); | ||
| 356 | |||
| 357 | initialized = true; | ||
| 358 | } | ||
| 359 | |||
| 360 | return rotation_alg_arr[t % NROTATIONS]; | ||
| 361 | } | ||
| 362 | |||
| 363 | void | ||
| 364 | transform_alg(Trans t, Alg *alg) | ||
| 365 | { | ||
| 366 | int i; | ||
| 367 | |||
| 368 | /*init_trans();*/ | ||
| 369 | |||
| 370 | for (i = 0; i < alg->len; i++) | ||
| 371 | alg->move[i] = moves_ttable[t][alg->move[i]]; | ||
| 372 | } | ||
diff --git a/old/2021-11-10-beforeremovingchecker/trans.h b/old/2021-11-10-beforeremovingchecker/trans.h new file mode 100644 index 0000000..2eda568 --- /dev/null +++ b/old/2021-11-10-beforeremovingchecker/trans.h | |||
| @@ -0,0 +1,13 @@ | |||
| 1 | #ifndef TRANS_H | ||
| 2 | #define TRANS_H | ||
| 3 | |||
| 4 | #include "moves.h" | ||
| 5 | |||
| 6 | Cube apply_trans(Trans t, Cube cube); | ||
| 7 | Trans inverse_trans(Trans t); | ||
| 8 | Alg * rotation_alg(Trans i); | ||
| 9 | void transform_alg(Trans i, Alg *alg); | ||
| 10 | |||
| 11 | void init_trans(); | ||
| 12 | |||
| 13 | #endif | ||
diff --git a/old/2021-11-10-beforeremovingchecker/utils.c b/old/2021-11-10-beforeremovingchecker/utils.c new file mode 100644 index 0000000..f72a00e --- /dev/null +++ b/old/2021-11-10-beforeremovingchecker/utils.c | |||
| @@ -0,0 +1,274 @@ | |||
| 1 | #include "utils.h" | ||
| 2 | |||
| 3 | void | ||
| 4 | apply_permutation(int *perm, int *set, int n) | ||
| 5 | { | ||
| 6 | int *aux = malloc(n * sizeof(int)); | ||
| 7 | int i; | ||
| 8 | |||
| 9 | if (!is_perm(perm, n)) | ||
| 10 | return; | ||
| 11 | |||
| 12 | for (i = 0; i < n; i++) | ||
| 13 | aux[i] = set[perm[i]]; | ||
| 14 | |||
| 15 | memcpy(set, aux, n * sizeof(int)); | ||
| 16 | free(aux); | ||
| 17 | } | ||
| 18 | |||
| 19 | int | ||
| 20 | binomial(int n, int k) | ||
| 21 | { | ||
| 22 | if (n < 0 || k < 0 || k > n) | ||
| 23 | return 0; | ||
| 24 | |||
| 25 | return factorial(n) / (factorial(k) * factorial(n-k)); | ||
| 26 | } | ||
| 27 | |||
| 28 | int | ||
| 29 | digit_array_to_int(int *a, int n, int b) | ||
| 30 | { | ||
| 31 | int i, ret = 0, p = 1; | ||
| 32 | |||
| 33 | for (i = 0; i < n; i++, p *= b) | ||
| 34 | ret += a[i] * p; | ||
| 35 | |||
| 36 | return ret; | ||
| 37 | } | ||
| 38 | |||
| 39 | int | ||
| 40 | factorial(int n) | ||
| 41 | { | ||
| 42 | int i, ret = 1; | ||
| 43 | |||
| 44 | if (n < 0) | ||
| 45 | return 0; | ||
| 46 | |||
| 47 | for (i = 1; i <= n; i++) | ||
| 48 | ret *= i; | ||
| 49 | |||
| 50 | return ret; | ||
| 51 | } | ||
| 52 | |||
| 53 | void | ||
| 54 | index_to_perm(int p, int n, int *r) | ||
| 55 | { | ||
| 56 | int *a = malloc(n * sizeof(int)); | ||
| 57 | int i, j, c; | ||
| 58 | |||
| 59 | for (i = 0; i < n; i++) | ||
| 60 | a[i] = 0; | ||
| 61 | |||
| 62 | if (p < 0 || p >= factorial(n)) | ||
| 63 | for (i = 0; i < n; i++) | ||
| 64 | r[i] = -1; | ||
| 65 | |||
| 66 | for (i = 0; i < n; i++) { | ||
| 67 | c = 0; | ||
| 68 | j = 0; | ||
| 69 | while (c <= p / factorial(n-i-1)) | ||
| 70 | c += a[j++] ? 0 : 1; | ||
| 71 | r[i] = j-1; | ||
| 72 | a[j-1] = 1; | ||
| 73 | p %= factorial(n-i-1); | ||
| 74 | } | ||
| 75 | |||
| 76 | free(a); | ||
| 77 | } | ||
| 78 | |||
| 79 | void | ||
| 80 | index_to_subset(int s, int n, int k, int *r) | ||
| 81 | { | ||
| 82 | int i, j, v; | ||
| 83 | |||
| 84 | if (s < 0 || s >= binomial(n, k)) { | ||
| 85 | for (i = 0; i < n; i++) | ||
| 86 | r[i] = -1; | ||
| 87 | return; | ||
| 88 | } | ||
| 89 | |||
| 90 | for (i = 0; i < n; i++) { | ||
| 91 | if (k == n-i) { | ||
| 92 | for (j = i; j < n; j++) | ||
| 93 | r[j] = 1; | ||
| 94 | return; | ||
| 95 | } | ||
| 96 | |||
| 97 | if (k == 0) { | ||
| 98 | for (j = i; j < n; j++) | ||
| 99 | r[j] = 0; | ||
| 100 | return; | ||
| 101 | } | ||
| 102 | |||
| 103 | v = binomial(n-i-1, k); | ||
| 104 | if (s >= v) { | ||
| 105 | r[i] = 1; | ||
| 106 | k--; | ||
| 107 | s -= v; | ||
| 108 | } else { | ||
| 109 | r[i] = 0; | ||
| 110 | } | ||
| 111 | } | ||
| 112 | } | ||
| 113 | |||
| 114 | void | ||
| 115 | int_to_digit_array(int a, int b, int n, int *r) | ||
| 116 | { | ||
| 117 | int i; | ||
| 118 | |||
| 119 | if (b <= 1) | ||
| 120 | for (i = 0; i < n; i++) | ||
| 121 | r[i] = 0; | ||
| 122 | else | ||
| 123 | for (i = 0; i < n; i++, a /= b) | ||
| 124 | r[i] = a % b; | ||
| 125 | } | ||
| 126 | |||
| 127 | void | ||
| 128 | int_to_sum_zero_array(int x, int b, int n, int *a) | ||
| 129 | { | ||
| 130 | int i, s = 0; | ||
| 131 | |||
| 132 | if (b <= 1) { | ||
| 133 | for (i = 0; i < n; i++) | ||
| 134 | a[i] = 0; | ||
| 135 | } else { | ||
| 136 | int_to_digit_array(x, b, n-1, a); | ||
| 137 | for (i = 0; i < n - 1; i++) | ||
| 138 | s = (s + a[i]) % b; | ||
| 139 | a[n-1] = (b - s) % b; | ||
| 140 | } | ||
| 141 | } | ||
| 142 | |||
| 143 | int | ||
| 144 | invert_digits(int a, int b, int n) | ||
| 145 | { | ||
| 146 | int i, ret, *r = malloc(n * sizeof(int)); | ||
| 147 | |||
| 148 | int_to_digit_array(a, b, n, r); | ||
| 149 | for (i = 0; i < n; i++) | ||
| 150 | r[i] = (b-r[i]) % b; | ||
| 151 | |||
| 152 | ret = digit_array_to_int(r, n, b); | ||
| 153 | free(r); | ||
| 154 | return ret; | ||
| 155 | } | ||
| 156 | |||
| 157 | bool | ||
| 158 | is_perm(int *a, int n) | ||
| 159 | { | ||
| 160 | int *aux = malloc(n * sizeof(int)); | ||
| 161 | int i; | ||
| 162 | |||
| 163 | for (i = 0; i < n; i++) | ||
| 164 | if (a[i] < 0 || a[i] >= n) | ||
| 165 | return false; | ||
| 166 | else | ||
| 167 | aux[a[i]] = 1; | ||
| 168 | |||
| 169 | for (i = 0; i < n; i++) | ||
| 170 | if (!aux[i]) | ||
| 171 | return false; | ||
| 172 | |||
| 173 | free(aux); | ||
| 174 | |||
| 175 | return true; | ||
| 176 | } | ||
| 177 | |||
| 178 | bool | ||
| 179 | is_subset(int *a, int n, int k) | ||
| 180 | { | ||
| 181 | int i, sum = 0; | ||
| 182 | |||
| 183 | for (i = 0; i < n; i++) | ||
| 184 | sum += a[i] ? 1 : 0; | ||
| 185 | |||
| 186 | return sum == k; | ||
| 187 | } | ||
| 188 | |||
| 189 | int | ||
| 190 | perm_sign(int *a, int n) | ||
| 191 | { | ||
| 192 | int i, j, ret = 0; | ||
| 193 | |||
| 194 | if (!is_perm(a,n)) | ||
| 195 | return -1; | ||
| 196 | |||
| 197 | for (i = 0; i < n; i++) | ||
| 198 | for (j = i+1; j < n; j++) | ||
| 199 | ret += (a[i] > a[j]) ? 1 : 0; | ||
| 200 | |||
| 201 | return ret % 2; | ||
| 202 | } | ||
| 203 | |||
| 204 | int | ||
| 205 | perm_to_index(int *a, int n) | ||
| 206 | { | ||
| 207 | int i, j, c, ret = 0; | ||
| 208 | |||
| 209 | if (!is_perm(a, n)) | ||
| 210 | return -1; | ||
| 211 | |||
| 212 | for (i = 0; i < n; i++) { | ||
| 213 | c = 0; | ||
| 214 | for (j = i+1; j < n; j++) | ||
| 215 | c += (a[i] > a[j]) ? 1 : 0; | ||
| 216 | ret += factorial(n-i-1) * c; | ||
| 217 | } | ||
| 218 | |||
| 219 | return ret; | ||
| 220 | } | ||
| 221 | |||
| 222 | int | ||
| 223 | powint(int a, int b) | ||
| 224 | { | ||
| 225 | if (b < 0) | ||
| 226 | return 0; | ||
| 227 | if (b == 0) | ||
| 228 | return 1; | ||
| 229 | |||
| 230 | if (b % 2) | ||
| 231 | return a * powint(a, b-1); | ||
| 232 | else | ||
| 233 | return powint(a*a, b/2); | ||
| 234 | } | ||
| 235 | |||
| 236 | int | ||
| 237 | subset_to_index(int *a, int n, int k) | ||
| 238 | { | ||
| 239 | int i, ret = 0; | ||
| 240 | |||
| 241 | if (!is_subset(a, n, k)) | ||
| 242 | return binomial(n, k); | ||
| 243 | |||
| 244 | for (i = 0; i < n; i++) { | ||
| 245 | if (k == n-i) | ||
| 246 | return ret; | ||
| 247 | if (a[i]) { | ||
| 248 | ret += binomial(n-i-1, k); | ||
| 249 | k--; | ||
| 250 | } | ||
| 251 | } | ||
| 252 | |||
| 253 | return ret; | ||
| 254 | } | ||
| 255 | |||
| 256 | void | ||
| 257 | sum_arrays_mod(int *src, int *dst, int n, int m) | ||
| 258 | { | ||
| 259 | int i; | ||
| 260 | |||
| 261 | for (i = 0; i < n; i++) | ||
| 262 | dst[i] = (m <= 0) ? 0 : (src[i] + dst[i]) % m; | ||
| 263 | } | ||
| 264 | |||
| 265 | void | ||
| 266 | swap(int *a, int *b) | ||
| 267 | { | ||
| 268 | int aux; | ||
| 269 | |||
| 270 | aux = *a; | ||
| 271 | *a = *b; | ||
| 272 | *b = aux; | ||
| 273 | } | ||
| 274 | |||
diff --git a/old/2021-11-10-beforeremovingchecker/utils.h b/old/2021-11-10-beforeremovingchecker/utils.h new file mode 100644 index 0000000..80c33ae --- /dev/null +++ b/old/2021-11-10-beforeremovingchecker/utils.h | |||
| @@ -0,0 +1,41 @@ | |||
| 1 | #ifndef UTILS_H | ||
| 2 | #define UTILS_H | ||
| 3 | |||
| 4 | #include <stdbool.h> | ||
| 5 | #include <stdlib.h> | ||
| 6 | #include <string.h> | ||
| 7 | |||
| 8 | #define POW2TO6 64ULL | ||
| 9 | #define POW2TO11 2048ULL | ||
| 10 | #define POW2TO12 4096ULL | ||
| 11 | #define POW3TO7 2187ULL | ||
| 12 | #define POW3TO8 6561ULL | ||
| 13 | #define FACTORIAL4 24ULL | ||
| 14 | #define FACTORIAL6 720ULL | ||
| 15 | #define FACTORIAL7 5040ULL | ||
| 16 | #define FACTORIAL8 40320ULL | ||
| 17 | #define FACTORIAL12 479001600ULL | ||
| 18 | #define BINOM12ON4 495ULL | ||
| 19 | #define BINOM8ON4 70ULL | ||
| 20 | #define MIN(a,b) (((a) < (b)) ? (a) : (b)) | ||
| 21 | #define MAX(a,b) (((a) > (b)) ? (a) : (b)) | ||
| 22 | |||
| 23 | void apply_permutation(int *perm, int *set, int n); | ||
| 24 | int binomial(int n, int k); | ||
| 25 | int digit_array_to_int(int *a, int n, int b); | ||
| 26 | int factorial(int n); | ||
| 27 | void index_to_perm(int p, int n, int *r); | ||
| 28 | void index_to_subset(int s, int n, int k, int *r); | ||
| 29 | void int_to_digit_array(int a, int b, int n, int *r); | ||
| 30 | void int_to_sum_zero_array(int x, int b, int n, int *a); | ||
| 31 | int invert_digits(int a, int b, int n); | ||
| 32 | bool is_perm(int *a, int n); | ||
| 33 | bool is_subset(int *a, int n, int k); | ||
| 34 | int perm_sign(int *a, int n); | ||
| 35 | int perm_to_index(int *a, int n); | ||
| 36 | int powint(int a, int b); | ||
| 37 | int subset_to_index(int *a, int n, int k); | ||
| 38 | void sum_arrays_mod(int *src, int *dst, int n, int m); | ||
| 39 | void swap(int *a, int *b); | ||
| 40 | |||
| 41 | #endif | ||
diff --git a/old/backup-manysteps-pretrans/steps.c b/old/backup-manysteps-pretrans/steps.c new file mode 100644 index 0000000..e4d79cd --- /dev/null +++ b/old/backup-manysteps-pretrans/steps.c | |||
| @@ -0,0 +1,369 @@ | |||
| 1 | #include "steps.h" | ||
| 2 | |||
| 3 | /* Check functions ***********************************************************/ | ||
| 4 | |||
| 5 | static int check_nothing(Cube cube); | ||
| 6 | static int check_eofb_HTM(Cube cube); | ||
| 7 | static int check_coud_HTM(Cube cube); | ||
| 8 | static int check_coud_URF(Cube cube); | ||
| 9 | static int check_corners_HTM(Cube cube); | ||
| 10 | static int check_corners_URF(Cube cube); | ||
| 11 | static int check_edges_HTM(Cube cube); | ||
| 12 | static int check_drud_HTM(Cube cube); | ||
| 13 | static int check_optimal_HTM(Cube cube); | ||
| 14 | |||
| 15 | |||
| 16 | /* Index functions ***********************************************************/ | ||
| 17 | |||
| 18 | static uint64_t index_eofb(Cube cube); | ||
| 19 | static uint64_t index_coud(Cube cube); | ||
| 20 | static uint64_t index_corners(Cube cube); | ||
| 21 | static uint64_t index_ep(Cube cube); | ||
| 22 | static uint64_t index_drud(Cube cube); | ||
| 23 | |||
| 24 | |||
| 25 | /* Steps *********************************************************************/ | ||
| 26 | |||
| 27 | Step | ||
| 28 | eofb_HTM = { | ||
| 29 | .check = check_eofb_HTM, | ||
| 30 | .ready = check_nothing, | ||
| 31 | .pre_trans = uf, | ||
| 32 | .moveset = moveset_HTM | ||
| 33 | }; | ||
| 34 | |||
| 35 | Step | ||
| 36 | eorl_HTM = { | ||
| 37 | .check = check_eofb_HTM, | ||
| 38 | .ready = check_nothing, | ||
| 39 | .pre_trans = ur, | ||
| 40 | .moveset = moveset_HTM | ||
| 41 | }; | ||
| 42 | |||
| 43 | Step | ||
| 44 | eoud_HTM = { | ||
| 45 | .check = check_eofb_HTM, | ||
| 46 | .ready = check_nothing, | ||
| 47 | .pre_trans = bu, | ||
| 48 | .moveset = moveset_HTM | ||
| 49 | }; | ||
| 50 | |||
| 51 | Step | ||
| 52 | coud_HTM = { | ||
| 53 | .check = check_coud_HTM, | ||
| 54 | .ready = check_nothing, | ||
| 55 | .pre_trans = uf, | ||
| 56 | .moveset = moveset_HTM | ||
| 57 | }; | ||
| 58 | |||
| 59 | Step | ||
| 60 | corl_HTM = { | ||
| 61 | .check = check_coud_HTM, | ||
| 62 | .ready = check_nothing, | ||
| 63 | .pre_trans = rf, | ||
| 64 | .moveset = moveset_HTM | ||
| 65 | }; | ||
| 66 | |||
| 67 | Step | ||
| 68 | cofb_HTM = { | ||
| 69 | .check = check_coud_HTM, | ||
| 70 | .ready = check_nothing, | ||
| 71 | .pre_trans = fd, | ||
| 72 | .moveset = moveset_HTM | ||
| 73 | }; | ||
| 74 | |||
| 75 | Step | ||
| 76 | coud_URF = { | ||
| 77 | .check = check_coud_URF, | ||
| 78 | .ready = check_nothing, | ||
| 79 | .pre_trans = uf, | ||
| 80 | .moveset = moveset_URF | ||
| 81 | }; | ||
| 82 | |||
| 83 | Step | ||
| 84 | corl_URF = { | ||
| 85 | .check = check_coud_URF, | ||
| 86 | .ready = check_nothing, | ||
| 87 | .pre_trans = rf, | ||
| 88 | .moveset = moveset_URF | ||
| 89 | }; | ||
| 90 | |||
| 91 | Step | ||
| 92 | cofb_URF = { | ||
| 93 | .check = check_coud_URF, | ||
| 94 | .ready = check_nothing, | ||
| 95 | .pre_trans = fd, | ||
| 96 | .moveset = moveset_URF | ||
| 97 | }; | ||
| 98 | |||
| 99 | Step | ||
| 100 | corners_HTM = { | ||
| 101 | .check = check_corners_HTM, | ||
| 102 | .ready = check_nothing, | ||
| 103 | .pre_trans = uf, | ||
| 104 | .moveset = moveset_HTM | ||
| 105 | }; | ||
| 106 | |||
| 107 | Step | ||
| 108 | corners_URF = { | ||
| 109 | .check = check_corners_URF, | ||
| 110 | .ready = check_nothing, | ||
| 111 | .pre_trans = uf, | ||
| 112 | .moveset = moveset_URF | ||
| 113 | }; | ||
| 114 | |||
| 115 | Step | ||
| 116 | edges_HTM = { | ||
| 117 | .check = check_edges_HTM, | ||
| 118 | .ready = check_nothing, | ||
| 119 | .pre_trans = uf, | ||
| 120 | .moveset = moveset_HTM | ||
| 121 | }; | ||
| 122 | |||
| 123 | Step | ||
| 124 | drud_HTM = { | ||
| 125 | .check = check_drud_HTM, | ||
| 126 | .ready = check_nothing, | ||
| 127 | .pre_trans = uf, | ||
| 128 | .moveset = moveset_HTM | ||
| 129 | }; | ||
| 130 | |||
| 131 | Step | ||
| 132 | optimal_HTM = { | ||
| 133 | .check = check_optimal_HTM, | ||
| 134 | .ready = check_nothing, | ||
| 135 | .pre_trans = uf, | ||
| 136 | .moveset = moveset_HTM | ||
| 137 | }; | ||
| 138 | |||
| 139 | |||
| 140 | /* Pruning tables ************************************************************/ | ||
| 141 | |||
| 142 | PruneData | ||
| 143 | pd_eofb_HTM = { | ||
| 144 | .filename = "ptable_eofb_HTM", | ||
| 145 | .size = POW2TO11, | ||
| 146 | .index = index_eofb, | ||
| 147 | .moveset = moveset_HTM | ||
| 148 | }; | ||
| 149 | |||
| 150 | PruneData | ||
| 151 | pd_coud_HTM = { | ||
| 152 | .filename = "ptable_coud_HTM", | ||
| 153 | .size = POW3TO7, | ||
| 154 | .index = index_coud, | ||
| 155 | .moveset = moveset_HTM | ||
| 156 | }; | ||
| 157 | |||
| 158 | PruneData | ||
| 159 | pd_corners_HTM = { | ||
| 160 | .filename = "ptable_corners_HTM", | ||
| 161 | .size = POW3TO7 * FACTORIAL8, | ||
| 162 | .index = index_corners, | ||
| 163 | .moveset = moveset_HTM | ||
| 164 | }; | ||
| 165 | |||
| 166 | PruneData | ||
| 167 | pd_ep_HTM = { | ||
| 168 | .filename = "ptable_ep_HTM", | ||
| 169 | .size = FACTORIAL12, | ||
| 170 | .index = index_ep, | ||
| 171 | .moveset = moveset_HTM | ||
| 172 | }; | ||
| 173 | |||
| 174 | PruneData | ||
| 175 | pd_drud_HTM = { | ||
| 176 | .filename = "ptable_drud_HTM", | ||
| 177 | .size = POW2TO11 * POW3TO7 * BINOM12ON4, | ||
| 178 | .index = index_drud, | ||
| 179 | .moveset = moveset_HTM | ||
| 180 | }; | ||
| 181 | |||
| 182 | |||
| 183 | /* Check functions implementation ********************************************/ | ||
| 184 | |||
| 185 | static int | ||
| 186 | check_nothing(Cube cube) | ||
| 187 | { | ||
| 188 | /* At least we check that it is admissible */ | ||
| 189 | return is_admissible(cube); | ||
| 190 | } | ||
| 191 | |||
| 192 | static int | ||
| 193 | check_eofb_HTM(Cube cube) | ||
| 194 | { | ||
| 195 | if (!pd_eofb_HTM.generated) | ||
| 196 | generate_ptable(&pd_eofb_HTM); | ||
| 197 | |||
| 198 | return PTABLEVAL(pd_eofb_HTM.ptable, cube.eofb); | ||
| 199 | } | ||
| 200 | |||
| 201 | static int | ||
| 202 | check_coud_HTM(Cube cube) | ||
| 203 | { | ||
| 204 | if (!pd_coud_HTM.generated) | ||
| 205 | generate_ptable(&pd_coud_HTM); | ||
| 206 | |||
| 207 | return PTABLEVAL(pd_coud_HTM.ptable, cube.coud); | ||
| 208 | } | ||
| 209 | |||
| 210 | static int | ||
| 211 | check_coud_URF(Cube cube) | ||
| 212 | { | ||
| 213 | /* TODO: I can improve this by checking first the orientation of | ||
| 214 | * the corner in DBL and use that as a reference */ | ||
| 215 | |||
| 216 | int ud = check_coud_HTM(cube); | ||
| 217 | int rl = check_coud_HTM(apply_move(z, cube)); | ||
| 218 | int fb = check_coud_HTM(apply_move(x, cube)); | ||
| 219 | |||
| 220 | return MIN(ud, MIN(rl, fb)); | ||
| 221 | } | ||
| 222 | |||
| 223 | static int | ||
| 224 | check_corners_HTM(Cube cube) | ||
| 225 | { | ||
| 226 | if (!pd_corners_HTM.generated) | ||
| 227 | generate_ptable(&pd_corners_HTM); | ||
| 228 | |||
| 229 | return PTABLEVAL(pd_corners_HTM.ptable, index_corners(cube)); | ||
| 230 | } | ||
| 231 | |||
| 232 | static int | ||
| 233 | check_corners_URF(Cube cube) | ||
| 234 | { | ||
| 235 | /* TODO: I can improve this by checking first the corner in DBL | ||
| 236 | * and use that as a reference */ | ||
| 237 | |||
| 238 | int ret = 15; | ||
| 239 | Trans i; | ||
| 240 | |||
| 241 | for (i = 0; i < NROTATIONS; i++) | ||
| 242 | ret = MIN(ret,check_corners_HTM(apply_alg(trans_alg(i),cube))); | ||
| 243 | |||
| 244 | return ret; | ||
| 245 | } | ||
| 246 | |||
| 247 | static int | ||
| 248 | check_edges_HTM(Cube cube) | ||
| 249 | { | ||
| 250 | int ret = 0; | ||
| 251 | |||
| 252 | if (!pd_ep_HTM.generated) | ||
| 253 | generate_ptable(&pd_ep_HTM); | ||
| 254 | |||
| 255 | ret = MAX(ret, PTABLEVAL(pd_ep_HTM.ptable, index_ep(cube))); | ||
| 256 | ret = MAX(ret, check_eofb_HTM(cube)); | ||
| 257 | ret = MAX(ret, check_eofb_HTM(apply_trans(ur, cube))); | ||
| 258 | ret = MAX(ret, check_eofb_HTM(apply_trans(fd, cube))); | ||
| 259 | |||
| 260 | return ret; | ||
| 261 | } | ||
| 262 | |||
| 263 | static int | ||
| 264 | check_drud_HTM(Cube cube) | ||
| 265 | { | ||
| 266 | if (!pd_drud_HTM.generated) | ||
| 267 | generate_ptable(&pd_drud_HTM); | ||
| 268 | |||
| 269 | return PTABLEVAL(pd_drud_HTM.ptable, index_drud(cube)); | ||
| 270 | } | ||
| 271 | |||
| 272 | static int | ||
| 273 | check_optimal_HTM(Cube cube) | ||
| 274 | { | ||
| 275 | int dr1, dr2, dr3, drmax, cor; /*ep;*/ | ||
| 276 | |||
| 277 | if (!pd_drud_HTM.generated) | ||
| 278 | generate_ptable(&pd_drud_HTM); | ||
| 279 | if (!pd_corners_HTM.generated) | ||
| 280 | generate_ptable(&pd_corners_HTM); | ||
| 281 | /* | ||
| 282 | *if (!pd_ep_HTM.generated) | ||
| 283 | * generate_ptable(&pd_ep_HTM); | ||
| 284 | */ | ||
| 285 | |||
| 286 | dr1 = PTABLEVAL(pd_drud_HTM.ptable, index_drud(cube)); | ||
| 287 | dr2 = PTABLEVAL(pd_drud_HTM.ptable, index_drud(apply_trans(rf, cube))); | ||
| 288 | dr3 = PTABLEVAL(pd_drud_HTM.ptable, index_drud(apply_trans(fd, cube))); | ||
| 289 | |||
| 290 | drmax = MAX(dr1, MAX(dr2, dr3)); | ||
| 291 | if (dr1 == dr2 && dr2 == dr3 && dr1 != 0) | ||
| 292 | drmax++; | ||
| 293 | |||
| 294 | cor = PTABLEVAL(pd_corners_HTM.ptable, index_corners(cube)); | ||
| 295 | /* ep = PTABLEVAL(pd_ep_HTM.ptable, index_ep(cube)); */ | ||
| 296 | |||
| 297 | /*return MAX(drmax, MAX(ep, cor));*/ | ||
| 298 | if (drmax == 0 && cor == 0) | ||
| 299 | return is_solved(cube, false) ? 0 : 1; | ||
| 300 | return MAX(drmax, cor); | ||
| 301 | } | ||
| 302 | |||
| 303 | |||
| 304 | /* Index functions implementation ********************************************/ | ||
| 305 | |||
| 306 | static uint64_t | ||
| 307 | index_eofb(Cube cube) | ||
| 308 | { | ||
| 309 | return cube.eofb; | ||
| 310 | } | ||
| 311 | |||
| 312 | static uint64_t | ||
| 313 | index_coud(Cube cube) | ||
| 314 | { | ||
| 315 | return cube.coud; | ||
| 316 | } | ||
| 317 | |||
| 318 | static uint64_t | ||
| 319 | index_corners(Cube cube) | ||
| 320 | { | ||
| 321 | return cube.coud * FACTORIAL8 + cube.cp; | ||
| 322 | } | ||
| 323 | |||
| 324 | static uint64_t | ||
| 325 | index_ep(Cube cube) | ||
| 326 | { | ||
| 327 | uint64_t a, b, c; | ||
| 328 | |||
| 329 | a = cube.eposs; | ||
| 330 | b = (cube.epose % FACTORIAL4) + epos_dependent_cube(cube)*FACTORIAL4; | ||
| 331 | c = cube.eposm % FACTORIAL4; | ||
| 332 | |||
| 333 | b *= FACTORIAL4 * BINOM12ON4; | ||
| 334 | c *= FACTORIAL4 * BINOM12ON4 * FACTORIAL4 * BINOM8ON4; | ||
| 335 | |||
| 336 | return a + b + c; | ||
| 337 | } | ||
| 338 | |||
| 339 | static uint64_t | ||
| 340 | index_drud(Cube cube) | ||
| 341 | { | ||
| 342 | uint64_t a, b, c; | ||
| 343 | |||
| 344 | a = cube.eofb; | ||
| 345 | b = cube.coud; | ||
| 346 | c = cube.epose / FACTORIAL4; | ||
| 347 | |||
| 348 | b *= POW2TO11; | ||
| 349 | c *= POW2TO11 * POW3TO7; | ||
| 350 | |||
| 351 | return a + b + c; | ||
| 352 | } | ||
| 353 | |||
| 354 | /* Movesets ******************************************************************/ | ||
| 355 | |||
| 356 | bool | ||
| 357 | moveset_HTM(Move m) | ||
| 358 | { | ||
| 359 | return m >= U && m <= B3; | ||
| 360 | } | ||
| 361 | |||
| 362 | bool | ||
| 363 | moveset_URF(Move m) | ||
| 364 | { | ||
| 365 | Move b = base_move(m); | ||
| 366 | |||
| 367 | return b == U || b == R || b == F; | ||
| 368 | } | ||
| 369 | |||
diff --git a/old/backup-manysteps-pretrans/steps.h b/old/backup-manysteps-pretrans/steps.h new file mode 100644 index 0000000..b218e04 --- /dev/null +++ b/old/backup-manysteps-pretrans/steps.h | |||
| @@ -0,0 +1,36 @@ | |||
| 1 | #ifndef STEPS_H | ||
| 2 | #define STEPS_H | ||
| 3 | |||
| 4 | #include "cube.h" | ||
| 5 | |||
| 6 | /* Steps *********************************************************************/ | ||
| 7 | |||
| 8 | extern Step eofb_HTM; | ||
| 9 | extern Step eorl_HTM; | ||
| 10 | extern Step eoud_HTM; | ||
| 11 | extern Step coud_HTM; | ||
| 12 | extern Step corl_HTM; | ||
| 13 | extern Step cofb_HTM; | ||
| 14 | extern Step coud_URF; | ||
| 15 | extern Step corl_URF; | ||
| 16 | extern Step cofb_URF; | ||
| 17 | extern Step corners_HTM; | ||
| 18 | extern Step corners_URF; | ||
| 19 | extern Step edges_HTM; | ||
| 20 | extern Step drud_HTM; | ||
| 21 | extern Step optimal_HTM; | ||
| 22 | |||
| 23 | /* Pruning tables ************************************************************/ | ||
| 24 | |||
| 25 | extern PruneData pd_eofb_HTM; | ||
| 26 | extern PruneData pd_coud_HTM; | ||
| 27 | extern PruneData pd_corners_HTM; | ||
| 28 | extern PruneData pd_ep_HTM; | ||
| 29 | extern PruneData pd_drud_HTM; | ||
| 30 | |||
| 31 | /* Movesets ******************************************************************/ | ||
| 32 | |||
| 33 | bool moveset_HTM(Move m); | ||
| 34 | bool moveset_URF(Move m); | ||
| 35 | |||
| 36 | #endif | ||
diff --git a/old/coord.c b/old/coord.c new file mode 100644 index 0000000..cd2da69 --- /dev/null +++ b/old/coord.c | |||
| @@ -0,0 +1,1014 @@ | |||
| 1 | #include "coord.h" | ||
| 2 | |||
| 3 | static Cube admissible_eos_from_eofbepos(Cube cube); | ||
| 4 | static Cube antindex_eofb(uint64_t ind); | ||
| 5 | static Cube antindex_eofbepos(uint64_t ind); | ||
| 6 | static Cube antindex_epud(uint64_t ind); | ||
| 7 | static Cube antindex_coud(uint64_t ind); | ||
| 8 | static Cube antindex_corners(uint64_t ind); | ||
| 9 | static Cube antindex_cp(uint64_t ind); | ||
| 10 | static Cube antindex_cornershtr(uint64_t ind); | ||
| 11 | static Cube antindex_drud(uint64_t ind); | ||
| 12 | static Cube antindex_coud_sym16(uint64_t ind); | ||
| 13 | static Cube antindex_cp_sym16(uint64_t ind); | ||
| 14 | static Cube antindex_eofbepos_sym16(uint64_t ind); | ||
| 15 | static Cube antindex_drud_sym16(uint64_t ind); | ||
| 16 | static Cube antindex_drud_eofb(uint64_t ind); | ||
| 17 | static Cube antindex_drudfin_noE_sym16(uint64_t ind); | ||
| 18 | static Cube antindex_htrfin(uint64_t ind); | ||
| 19 | static Cube antindex_khuge(uint64_t ind); | ||
| 20 | static int epos_dependent_pos(int pos1, int pos2); | ||
| 21 | static void gensym(SymData *sd); | ||
| 22 | static uint64_t index_eofb(Cube cube); | ||
| 23 | static uint64_t index_eofbepos(Cube cube); | ||
| 24 | static uint64_t index_epud(Cube cube); | ||
| 25 | static uint64_t index_coud(Cube cube); | ||
| 26 | static uint64_t index_corners(Cube cube); | ||
| 27 | static uint64_t index_cp(Cube cube); | ||
| 28 | static uint64_t index_cornershtr(Cube cube); | ||
| 29 | static uint64_t index_drud(Cube cube); | ||
| 30 | static uint64_t index_coud_sym16(Cube cube); | ||
| 31 | static uint64_t index_cp_sym16(Cube cube); | ||
| 32 | static uint64_t index_eofbepos_sym16(Cube cube); | ||
| 33 | static uint64_t index_drud_sym16(Cube cube); | ||
| 34 | static uint64_t index_drud_eofb(Cube cube); | ||
| 35 | static uint64_t index_drudfin_noE_sym16(Cube cube); | ||
| 36 | static uint64_t index_htrfin(Cube cube); | ||
| 37 | static uint64_t index_khuge(Cube cube); | ||
| 38 | static void init_cphtr_cosets(); | ||
| 39 | static void init_cphtr_left_cosets_bfs(int i, int c); | ||
| 40 | static void init_cphtr_right_cosets_color(int i, int c); | ||
| 41 | static void init_symdata(); | ||
| 42 | static bool read_symdata_file(SymData *sd); | ||
| 43 | static bool write_symdata_file(SymData *sd); | ||
| 44 | |||
| 45 | /* All sorts of useful costants and tables **********************************/ | ||
| 46 | |||
| 47 | /* TODO: Can I move inside functions that use them? | ||
| 48 | Maybe I need to pass them as argument to some | ||
| 49 | secondary function */ | ||
| 50 | static int cphtr_left_cosets[FACTORIAL8]; | ||
| 51 | static int cphtr_right_cosets[FACTORIAL8]; | ||
| 52 | static int cphtr_right_rep[BINOM8ON4*6]; | ||
| 53 | |||
| 54 | |||
| 55 | /* Symmetry data for some coordinates ****************************************/ | ||
| 56 | |||
| 57 | static Trans | ||
| 58 | trans_group_trivial[1] = { uf }; | ||
| 59 | |||
| 60 | static Trans | ||
| 61 | trans_group_udfix[16] = { | ||
| 62 | uf, ur, ub, ul, | ||
| 63 | df, dr, db, dl, | ||
| 64 | uf_mirror, ur_mirror, ub_mirror, ul_mirror, | ||
| 65 | df_mirror, dr_mirror, db_mirror, dl_mirror, | ||
| 66 | }; | ||
| 67 | |||
| 68 | SymData | ||
| 69 | sd_coud_16 = { | ||
| 70 | .filename = "sd_coud_16", | ||
| 71 | .coord = &coord_coud, | ||
| 72 | .sym_coord = &coord_coud_sym16, | ||
| 73 | .ntrans = 16, | ||
| 74 | .trans = trans_group_udfix | ||
| 75 | }; | ||
| 76 | |||
| 77 | SymData | ||
| 78 | sd_cp_16 = { | ||
| 79 | .filename = "sd_cp_16", | ||
| 80 | .coord = &coord_cp, | ||
| 81 | .sym_coord = &coord_cp_sym16, | ||
| 82 | .ntrans = 16, | ||
| 83 | .trans = trans_group_udfix | ||
| 84 | }; | ||
| 85 | |||
| 86 | SymData | ||
| 87 | sd_eofbepos_16 = { | ||
| 88 | .filename = "sd_eofbepos_16", | ||
| 89 | .coord = &coord_eofbepos, | ||
| 90 | .sym_coord = &coord_eofbepos_sym16, | ||
| 91 | .ntrans = 16, | ||
| 92 | .trans = trans_group_udfix | ||
| 93 | }; | ||
| 94 | |||
| 95 | static int n_all_symdata = 3; | ||
| 96 | static SymData * all_sd[3] = { | ||
| 97 | &sd_coud_16, | ||
| 98 | &sd_cp_16, | ||
| 99 | &sd_eofbepos_16, | ||
| 100 | }; | ||
| 101 | |||
| 102 | /* Coordinates and their implementation **************************************/ | ||
| 103 | |||
| 104 | Coordinate | ||
| 105 | coord_eofb = { | ||
| 106 | .index = index_eofb, | ||
| 107 | .cube = antindex_eofb, | ||
| 108 | .check = check_eofb, | ||
| 109 | .max = POW2TO11, | ||
| 110 | .ntrans = 1, | ||
| 111 | .trans = trans_group_trivial, | ||
| 112 | }; | ||
| 113 | |||
| 114 | Coordinate | ||
| 115 | coord_eofbepos = { | ||
| 116 | .index = index_eofbepos, | ||
| 117 | .cube = antindex_eofbepos, | ||
| 118 | .check = check_eofbepos, | ||
| 119 | .max = POW2TO11 * BINOM12ON4, | ||
| 120 | .ntrans = 1, | ||
| 121 | .trans = trans_group_trivial, | ||
| 122 | }; | ||
| 123 | |||
| 124 | Coordinate | ||
| 125 | coord_coud = { | ||
| 126 | .index = index_coud, | ||
| 127 | .cube = antindex_coud, | ||
| 128 | .check = check_coud, | ||
| 129 | .max = POW3TO7, | ||
| 130 | .ntrans = 1, | ||
| 131 | .trans = trans_group_trivial, | ||
| 132 | }; | ||
| 133 | |||
| 134 | Coordinate | ||
| 135 | coord_corners = { | ||
| 136 | .index = index_corners, | ||
| 137 | .cube = antindex_corners, | ||
| 138 | .check = check_corners, | ||
| 139 | .max = POW3TO7 * FACTORIAL8, | ||
| 140 | .ntrans = 1, | ||
| 141 | .trans = trans_group_trivial, | ||
| 142 | }; | ||
| 143 | |||
| 144 | Coordinate | ||
| 145 | coord_cp = { | ||
| 146 | .index = index_cp, | ||
| 147 | .cube = antindex_cp, | ||
| 148 | .check = check_cp, | ||
| 149 | .max = FACTORIAL8, | ||
| 150 | .ntrans = 1, | ||
| 151 | .trans = trans_group_trivial, | ||
| 152 | }; | ||
| 153 | |||
| 154 | Coordinate | ||
| 155 | coord_cornershtr = { | ||
| 156 | .index = index_cornershtr, | ||
| 157 | .cube = antindex_cornershtr, | ||
| 158 | .check = check_cornershtr, | ||
| 159 | .max = POW3TO7 * BINOM8ON4 * 6, | ||
| 160 | .ntrans = 1, | ||
| 161 | .trans = trans_group_trivial, | ||
| 162 | }; | ||
| 163 | |||
| 164 | Coordinate | ||
| 165 | coord_drud = { | ||
| 166 | .index = index_drud, | ||
| 167 | .cube = antindex_drud, | ||
| 168 | .check = check_drud, | ||
| 169 | .max = POW2TO11 * POW3TO7 * BINOM12ON4, | ||
| 170 | .ntrans = 1, | ||
| 171 | .trans = trans_group_trivial, | ||
| 172 | }; | ||
| 173 | |||
| 174 | Coordinate | ||
| 175 | coord_htrfin = { | ||
| 176 | .index = index_htrfin, | ||
| 177 | .cube = antindex_htrfin, | ||
| 178 | .check = check_htrfin, | ||
| 179 | .max = 24 * 24 * 24 *24 * 24, | ||
| 180 | .ntrans = 1, | ||
| 181 | .trans = trans_group_trivial, | ||
| 182 | }; | ||
| 183 | |||
| 184 | Coordinate | ||
| 185 | coord_drud_eofb = { | ||
| 186 | .index = index_drud_eofb, | ||
| 187 | .cube = antindex_drud_eofb, | ||
| 188 | .check = check_drud, | ||
| 189 | .max = POW3TO7 * BINOM12ON4, | ||
| 190 | .ntrans = 1, | ||
| 191 | .trans = trans_group_trivial, | ||
| 192 | }; | ||
| 193 | |||
| 194 | Coordinate | ||
| 195 | coord_eofbepos_sym16 = { | ||
| 196 | .index = index_eofbepos_sym16, | ||
| 197 | .cube = antindex_eofbepos_sym16, | ||
| 198 | .check = check_eofbepos, | ||
| 199 | .ntrans = 16, | ||
| 200 | .trans = trans_group_udfix, | ||
| 201 | }; | ||
| 202 | |||
| 203 | Coordinate | ||
| 204 | coord_coud_sym16 = { | ||
| 205 | .index = index_coud_sym16, | ||
| 206 | .cube = antindex_coud_sym16, | ||
| 207 | .check = check_coud, | ||
| 208 | .ntrans = 16, | ||
| 209 | .trans = trans_group_udfix, | ||
| 210 | }; | ||
| 211 | |||
| 212 | Coordinate | ||
| 213 | coord_cp_sym16 = { | ||
| 214 | .index = index_cp_sym16, | ||
| 215 | .cube = antindex_cp_sym16, | ||
| 216 | .check = check_cp, | ||
| 217 | .ntrans = 16, | ||
| 218 | .trans = trans_group_udfix, | ||
| 219 | }; | ||
| 220 | |||
| 221 | Coordinate | ||
| 222 | coord_drud_sym16 = { | ||
| 223 | .index = index_drud_sym16, | ||
| 224 | .cube = antindex_drud_sym16, | ||
| 225 | .check = check_drud, | ||
| 226 | .max = POW3TO7 * 64430, | ||
| 227 | .ntrans = 16, | ||
| 228 | .trans = trans_group_udfix, | ||
| 229 | }; | ||
| 230 | |||
| 231 | Coordinate | ||
| 232 | coord_drudfin_noE_sym16 = { | ||
| 233 | .index = index_drudfin_noE_sym16, | ||
| 234 | .cube = antindex_drudfin_noE_sym16, | ||
| 235 | .check = check_drudfin_noE, | ||
| 236 | .max = FACTORIAL8 * 2768, | ||
| 237 | .ntrans = 16, | ||
| 238 | .trans = trans_group_udfix, | ||
| 239 | }; | ||
| 240 | |||
| 241 | Coordinate | ||
| 242 | coord_khuge = { | ||
| 243 | .index = index_khuge, | ||
| 244 | .cube = antindex_khuge, | ||
| 245 | .check = check_khuge, | ||
| 246 | .max = POW3TO7 * FACTORIAL4 * 64430, | ||
| 247 | .ntrans = 16, | ||
| 248 | .trans = trans_group_udfix, | ||
| 249 | }; | ||
| 250 | |||
| 251 | /* Functions *****************************************************************/ | ||
| 252 | |||
| 253 | static Cube | ||
| 254 | admissible_eos_from_eofbepos(Cube cube) | ||
| 255 | { | ||
| 256 | Edge e; | ||
| 257 | Cube ret; | ||
| 258 | CubeArray *arr = new_cubearray(cube, pf_all); | ||
| 259 | |||
| 260 | memcpy(arr->eorl, arr->eofb, 12 * sizeof(int)); | ||
| 261 | memcpy(arr->eoud, arr->eofb, 12 * sizeof(int)); | ||
| 262 | |||
| 263 | for (e = 0; e < 12; e++) { | ||
| 264 | if ((edge_slice(e) != 0 && edge_slice(arr->ep[e]) == 0) || | ||
| 265 | (edge_slice(e) == 0 && edge_slice(arr->ep[e]) != 0)) | ||
| 266 | arr->eorl[e] = 1 - arr->eorl[e]; | ||
| 267 | if ((edge_slice(e) != 2 && edge_slice(arr->ep[e]) == 2) || | ||
| 268 | (edge_slice(e) == 2 && edge_slice(arr->ep[e]) != 2)) | ||
| 269 | arr->eoud[e] = 1 - arr->eoud[e]; | ||
| 270 | } | ||
| 271 | |||
| 272 | ret = arrays_to_cube(arr, pf_all); | ||
| 273 | free_cubearray(arr, pf_all); | ||
| 274 | |||
| 275 | return ret; | ||
| 276 | } | ||
| 277 | |||
| 278 | |||
| 279 | static Cube | ||
| 280 | antindex_eofb(uint64_t ind) | ||
| 281 | { | ||
| 282 | return (Cube){ .eofb = ind, .eorl = ind, .eoud = ind }; | ||
| 283 | } | ||
| 284 | |||
| 285 | static Cube | ||
| 286 | antindex_eofbepos(uint64_t ind) | ||
| 287 | { | ||
| 288 | static bool initialized = false; | ||
| 289 | static Cube admissible_ee_aux[POW2TO11*BINOM12ON4]; | ||
| 290 | static Cube c1; | ||
| 291 | static int k; | ||
| 292 | static uint64_t ui; | ||
| 293 | |||
| 294 | if (!initialized) { | ||
| 295 | for (ui = 0; ui < POW2TO11*BINOM12ON4; ui++) { | ||
| 296 | k = (ui / POW2TO11) * 24; | ||
| 297 | c1 = admissible_ep((Cube){ .epose = k }, pf_e); | ||
| 298 | c1.eofb = ui % POW2TO11; | ||
| 299 | c1 = admissible_eos_from_eofbepos(c1); | ||
| 300 | admissible_ee_aux[ui] = c1; | ||
| 301 | } | ||
| 302 | |||
| 303 | initialized = true; | ||
| 304 | } | ||
| 305 | |||
| 306 | return admissible_ee_aux[ind]; | ||
| 307 | } | ||
| 308 | |||
| 309 | static Cube | ||
| 310 | antindex_epud(uint64_t ind) | ||
| 311 | { | ||
| 312 | static bool initialized = false; | ||
| 313 | static Cube epud_aux[FACTORIAL8]; | ||
| 314 | int a[12]; | ||
| 315 | uint64_t ui; | ||
| 316 | CubeArray arr; | ||
| 317 | |||
| 318 | if (!initialized) { | ||
| 319 | a[FR] = FR; | ||
| 320 | a[FL] = FL; | ||
| 321 | a[BL] = BL; | ||
| 322 | a[BR] = BR; | ||
| 323 | for (ui = 0; ui < FACTORIAL8; ui++) { | ||
| 324 | index_to_perm(ui, 8, a); | ||
| 325 | arr.ep = a; | ||
| 326 | epud_aux[ui] = arrays_to_cube(&arr, pf_ep); | ||
| 327 | } | ||
| 328 | |||
| 329 | initialized = true; | ||
| 330 | } | ||
| 331 | |||
| 332 | return epud_aux[ind]; | ||
| 333 | } | ||
| 334 | |||
| 335 | static Cube | ||
| 336 | antindex_coud(uint64_t ind) | ||
| 337 | { | ||
| 338 | return (Cube){ .coud = ind, .corl = ind, .cofb = ind }; | ||
| 339 | } | ||
| 340 | |||
| 341 | static Cube | ||
| 342 | antindex_corners(uint64_t ind) | ||
| 343 | { | ||
| 344 | Cube c = {0}; | ||
| 345 | |||
| 346 | c.coud = ind / FACTORIAL8; | ||
| 347 | c.cp = ind % FACTORIAL8; | ||
| 348 | |||
| 349 | return c; | ||
| 350 | } | ||
| 351 | |||
| 352 | static Cube | ||
| 353 | antindex_cp(uint64_t ind) | ||
| 354 | { | ||
| 355 | Cube c = {0}; | ||
| 356 | |||
| 357 | c.cp = ind; | ||
| 358 | |||
| 359 | return c; | ||
| 360 | } | ||
| 361 | |||
| 362 | static Cube | ||
| 363 | antindex_cornershtr(uint64_t ind) | ||
| 364 | { | ||
| 365 | Cube c = anti_cphtr(ind % (BINOM8ON4 * 6)); | ||
| 366 | |||
| 367 | c.coud = ind / (BINOM8ON4 * 6); | ||
| 368 | |||
| 369 | return c; | ||
| 370 | } | ||
| 371 | |||
| 372 | /* TODO: admissible eos and cos */ | ||
| 373 | /* DONE: temporary fix, make it better */ | ||
| 374 | /* Or maybe it's ok like this? */ | ||
| 375 | static Cube | ||
| 376 | antindex_drud(uint64_t ind) | ||
| 377 | { | ||
| 378 | uint64_t epos, eofb; | ||
| 379 | Cube c; | ||
| 380 | |||
| 381 | eofb = ind % POW2TO11; | ||
| 382 | epos = ind / (POW2TO11 * POW3TO7); | ||
| 383 | c = antindex_eofbepos(eofb + POW2TO11 * epos); | ||
| 384 | |||
| 385 | c.coud = (ind / POW2TO11) % POW3TO7; | ||
| 386 | c.corl = c.coud; | ||
| 387 | c.cofb = c.coud; | ||
| 388 | |||
| 389 | return c; | ||
| 390 | } | ||
| 391 | |||
| 392 | static Cube | ||
| 393 | antindex_drud_eofb(uint64_t ind) | ||
| 394 | { | ||
| 395 | return antindex_drud(ind * POW2TO11); | ||
| 396 | } | ||
| 397 | |||
| 398 | static Cube | ||
| 399 | antindex_coud_sym16(uint64_t ind) | ||
| 400 | { | ||
| 401 | return sd_coud_16.rep[ind]; | ||
| 402 | } | ||
| 403 | |||
| 404 | static Cube | ||
| 405 | antindex_cp_sym16(uint64_t ind) | ||
| 406 | { | ||
| 407 | return sd_cp_16.rep[ind]; | ||
| 408 | } | ||
| 409 | |||
| 410 | static Cube | ||
| 411 | antindex_eofbepos_sym16(uint64_t ind) | ||
| 412 | { | ||
| 413 | return sd_eofbepos_16.rep[ind]; | ||
| 414 | } | ||
| 415 | |||
| 416 | static Cube | ||
| 417 | antindex_drud_sym16(uint64_t ind) | ||
| 418 | { | ||
| 419 | Cube c; | ||
| 420 | |||
| 421 | c = sd_eofbepos_16.rep[ind/POW3TO7]; | ||
| 422 | c.coud = ind % POW3TO7; | ||
| 423 | c.cofb = c.coud; | ||
| 424 | c.corl = c.coud; | ||
| 425 | |||
| 426 | return c; | ||
| 427 | } | ||
| 428 | |||
| 429 | static Cube | ||
| 430 | antindex_drudfin_noE_sym16(uint64_t ind) | ||
| 431 | { | ||
| 432 | Cube c1, c2; | ||
| 433 | |||
| 434 | c1 = antindex_epud(ind % FACTORIAL8); | ||
| 435 | c2 = sd_cp_16.rep[ind/FACTORIAL8]; | ||
| 436 | c1.cp = c2.cp; | ||
| 437 | |||
| 438 | return c1; | ||
| 439 | } | ||
| 440 | |||
| 441 | static Cube | ||
| 442 | antindex_htrfin(uint64_t ind) | ||
| 443 | { | ||
| 444 | Cube ret = {0}; | ||
| 445 | uint64_t cp1, cp2; | ||
| 446 | |||
| 447 | static bool initialized = false; | ||
| 448 | static int i, j, k, c[8], c1[4], c2[4], cp[24][24]; | ||
| 449 | static int c1solved[4] = {UFR, UBL, DFL, DBR}; | ||
| 450 | static int c2solved[4] = {UFL, UBR, DFR, DBL}; | ||
| 451 | |||
| 452 | if (!initialized) { | ||
| 453 | for (i = 0; i < 24; i++) { | ||
| 454 | for (j = 0; j < 24; j++) { | ||
| 455 | index_to_perm(i, 4, c1); | ||
| 456 | index_to_perm(j, 4, c2); | ||
| 457 | for (k = 0; k < 8; k++) | ||
| 458 | if (k == UFR || k == UBL || | ||
| 459 | k == DFL || k == DBR) | ||
| 460 | c[k] = c1[c1solved[k/2]]; | ||
| 461 | else | ||
| 462 | c[k] = c2[c2solved[k/2]]; | ||
| 463 | |||
| 464 | cp[i][j] = perm_to_index(c, 8); | ||
| 465 | } | ||
| 466 | } | ||
| 467 | |||
| 468 | initialized = true; | ||
| 469 | } | ||
| 470 | |||
| 471 | cp2 = ind % 24; | ||
| 472 | ind /= 24; | ||
| 473 | cp1 = ind % 24; | ||
| 474 | ret.cp = cp[cp1][cp2]; | ||
| 475 | |||
| 476 | ind /= 24; | ||
| 477 | ret.eposm = ind % 24; | ||
| 478 | ind /= 24; | ||
| 479 | ret.eposs = ind % 24; | ||
| 480 | ret.epose = ind / 24; | ||
| 481 | |||
| 482 | return ret; | ||
| 483 | } | ||
| 484 | |||
| 485 | static Cube | ||
| 486 | antindex_khuge(uint64_t ind) | ||
| 487 | { | ||
| 488 | Cube c; | ||
| 489 | |||
| 490 | c = sd_eofbepos_16.rep[ind/(FACTORIAL4*POW3TO7)]; | ||
| 491 | c.epose = ((c.epose / 24) * 24) + ((ind/POW3TO7) % 24); | ||
| 492 | c.coud = ind % POW3TO7; | ||
| 493 | |||
| 494 | return c; | ||
| 495 | } | ||
| 496 | |||
| 497 | bool | ||
| 498 | check_centers(Cube cube) | ||
| 499 | { | ||
| 500 | return cube.cpos == 0; | ||
| 501 | } | ||
| 502 | |||
| 503 | bool | ||
| 504 | check_corners(Cube cube) | ||
| 505 | { | ||
| 506 | return cube.cp == 0 && cube.coud == 0; | ||
| 507 | } | ||
| 508 | |||
| 509 | bool | ||
| 510 | check_cp(Cube cube) | ||
| 511 | { | ||
| 512 | return cube.cp == 0; | ||
| 513 | } | ||
| 514 | |||
| 515 | bool | ||
| 516 | check_cornershtr(Cube cube) | ||
| 517 | { | ||
| 518 | return cube.coud == 0 && cphtr(cube) == 0; /* TODO: use array cphtrcosets*/ | ||
| 519 | } | ||
| 520 | |||
| 521 | bool | ||
| 522 | check_coud(Cube cube) | ||
| 523 | { | ||
| 524 | return cube.coud == 0; | ||
| 525 | } | ||
| 526 | |||
| 527 | bool | ||
| 528 | check_drud(Cube cube) | ||
| 529 | { | ||
| 530 | return cube.eofb == 0 && cube.eorl == 0 && cube.coud == 0; | ||
| 531 | } | ||
| 532 | |||
| 533 | bool | ||
| 534 | check_htr(Cube cube) | ||
| 535 | { | ||
| 536 | return check_cornershtr(cube) && | ||
| 537 | cube.eofb == 0 && cube.eorl == 0 && cube.eoud == 0; | ||
| 538 | } | ||
| 539 | |||
| 540 | bool | ||
| 541 | check_htrfin(Cube cube) | ||
| 542 | { | ||
| 543 | return cube.cp == 0 && | ||
| 544 | cube.epose == 0 && cube.eposs == 0 && cube.eposm == 0; | ||
| 545 | } | ||
| 546 | |||
| 547 | bool | ||
| 548 | check_drudfin_noE(Cube cube) | ||
| 549 | { | ||
| 550 | return cube.eposs == 0 && cube.eposm == 0 && cube.cp == 0; | ||
| 551 | } | ||
| 552 | |||
| 553 | bool | ||
| 554 | check_eofb(Cube cube) | ||
| 555 | { | ||
| 556 | return cube.eofb == 0; | ||
| 557 | } | ||
| 558 | |||
| 559 | bool | ||
| 560 | check_eofbepos(Cube cube) | ||
| 561 | { | ||
| 562 | return cube.eofb == 0 && cube.epose / 24 == 0; | ||
| 563 | } | ||
| 564 | |||
| 565 | bool | ||
| 566 | check_epose(Cube cube) | ||
| 567 | { | ||
| 568 | return cube.epose == 0; | ||
| 569 | } | ||
| 570 | |||
| 571 | bool | ||
| 572 | check_ep(Cube cube) | ||
| 573 | { | ||
| 574 | return cube.epose == 0 && cube.eposs == 0 && cube.eposm == 0; | ||
| 575 | } | ||
| 576 | |||
| 577 | bool | ||
| 578 | check_khuge(Cube cube) | ||
| 579 | { | ||
| 580 | return check_drud(cube) && cube.epose % 24 == 0; | ||
| 581 | } | ||
| 582 | |||
| 583 | bool | ||
| 584 | check_nothing(Cube cube) | ||
| 585 | { | ||
| 586 | return is_admissible(cube); /*TODO: maybe change?*/ | ||
| 587 | } | ||
| 588 | |||
| 589 | static int | ||
| 590 | epos_dependent_pos(int poss, int pose) | ||
| 591 | { | ||
| 592 | static int epe_solved[4] = {FR, FL, BL, BR}; | ||
| 593 | static int eps_solved[4] = {UL, UR, DL, DR}; | ||
| 594 | int ep[12] = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}; | ||
| 595 | int ep8[8] = {0, 0, 0, 0, 0, 0, 0, 0}; | ||
| 596 | int i, j; | ||
| 597 | |||
| 598 | epos_to_partial_ep(poss*FACTORIAL4, ep, eps_solved); | ||
| 599 | epos_to_partial_ep(pose*FACTORIAL4, ep, epe_solved); | ||
| 600 | |||
| 601 | for (i = 0, j = 0; i < 12; i++) | ||
| 602 | if (edge_slice(ep[i]) != 0) | ||
| 603 | ep8[j++] = (edge_slice(ep[i]) == 1) ? 1 : 0; | ||
| 604 | |||
| 605 | swap(&ep8[1], &ep8[4]); | ||
| 606 | swap(&ep8[3], &ep8[6]); | ||
| 607 | |||
| 608 | return subset_to_index(ep8, 8, 4); | ||
| 609 | } | ||
| 610 | |||
| 611 | static void | ||
| 612 | gensym(SymData *sd) | ||
| 613 | { | ||
| 614 | uint64_t i, in, nreps = 0; | ||
| 615 | int j; | ||
| 616 | Cube c, d; | ||
| 617 | |||
| 618 | if (sd->generated) | ||
| 619 | return; | ||
| 620 | |||
| 621 | sd->class = malloc(sd->coord->max * sizeof(uint64_t)); | ||
| 622 | sd->rep = malloc(sd->coord->max * sizeof(Cube)); | ||
| 623 | sd->transtorep = malloc(sd->coord->max * sizeof(Trans)); | ||
| 624 | |||
| 625 | if (read_symdata_file(sd)) { | ||
| 626 | sd->generated = true; | ||
| 627 | return; | ||
| 628 | } | ||
| 629 | |||
| 630 | fprintf(stderr, "Cannot load %s, generating it\n", sd->filename); | ||
| 631 | |||
| 632 | for (i = 0; i < sd->coord->max; i++) | ||
| 633 | sd->class[i] = sd->coord->max + 1; | ||
| 634 | |||
| 635 | for (i = 0; i < sd->coord->max; i++) { | ||
| 636 | if (sd->class[i] == sd->coord->max + 1) { | ||
| 637 | c = sd->coord->cube(i); | ||
| 638 | sd->rep[nreps] = c; | ||
| 639 | for (j = 0; j < sd->ntrans; j++) { | ||
| 640 | d = apply_trans(sd->trans[j], c); | ||
| 641 | in = sd->coord->index(d); | ||
| 642 | |||
| 643 | if (sd->class[in] == sd->coord->max + 1) { | ||
| 644 | sd->class[in] = nreps; | ||
| 645 | sd->transtorep[in] = | ||
| 646 | inverse_trans(sd->trans[j]); | ||
| 647 | } | ||
| 648 | } | ||
| 649 | nreps++; | ||
| 650 | } | ||
| 651 | } | ||
| 652 | |||
| 653 | sd->sym_coord->max = nreps; | ||
| 654 | sd->rep = realloc(sd->rep, nreps * sizeof(Cube)); | ||
| 655 | sd->generated = true; | ||
| 656 | |||
| 657 | fprintf(stderr, "Found %lu classes\n", nreps); | ||
| 658 | |||
| 659 | if (!write_symdata_file(sd)) | ||
| 660 | fprintf(stderr, "Error writing SymData file\n"); | ||
| 661 | |||
| 662 | return; | ||
| 663 | } | ||
| 664 | |||
| 665 | static uint64_t | ||
| 666 | index_eofb(Cube cube) | ||
| 667 | { | ||
| 668 | return cube.eofb; | ||
| 669 | } | ||
| 670 | |||
| 671 | static uint64_t | ||
| 672 | index_eofbepos(Cube cube) | ||
| 673 | { | ||
| 674 | return (cube.epose / FACTORIAL4) * POW2TO11 + cube.eofb; | ||
| 675 | } | ||
| 676 | |||
| 677 | static uint64_t | ||
| 678 | index_epud(Cube cube) | ||
| 679 | { | ||
| 680 | uint64_t ret; | ||
| 681 | CubeArray *arr = new_cubearray(cube, pf_ep); | ||
| 682 | |||
| 683 | ret = perm_to_index(arr->ep, 8); | ||
| 684 | free_cubearray(arr, pf_ep); | ||
| 685 | |||
| 686 | return ret; | ||
| 687 | } | ||
| 688 | |||
| 689 | static uint64_t | ||
| 690 | index_coud(Cube cube) | ||
| 691 | { | ||
| 692 | return cube.coud; | ||
| 693 | } | ||
| 694 | |||
| 695 | static uint64_t | ||
| 696 | index_corners(Cube cube) | ||
| 697 | { | ||
| 698 | return cube.coud * FACTORIAL8 + cube.cp; | ||
| 699 | } | ||
| 700 | |||
| 701 | static uint64_t | ||
| 702 | index_cp(Cube cube) | ||
| 703 | { | ||
| 704 | return cube.cp; | ||
| 705 | } | ||
| 706 | |||
| 707 | static uint64_t | ||
| 708 | index_cornershtr(Cube cube) | ||
| 709 | { | ||
| 710 | return cube.coud * BINOM8ON4 * 6 + cphtr(cube); | ||
| 711 | } | ||
| 712 | |||
| 713 | static uint64_t | ||
| 714 | index_drud(Cube cube) | ||
| 715 | { | ||
| 716 | uint64_t a, b, c; | ||
| 717 | |||
| 718 | a = cube.eofb; | ||
| 719 | b = cube.coud; | ||
| 720 | c = cube.epose / FACTORIAL4; | ||
| 721 | |||
| 722 | b *= POW2TO11; | ||
| 723 | c *= POW2TO11 * POW3TO7; | ||
| 724 | |||
| 725 | return a + b + c; | ||
| 726 | } | ||
| 727 | |||
| 728 | static uint64_t | ||
| 729 | index_drud_eofb(Cube cube) | ||
| 730 | { | ||
| 731 | return index_drud(cube) / POW2TO11; | ||
| 732 | } | ||
| 733 | |||
| 734 | static uint64_t | ||
| 735 | index_coud_sym16(Cube cube) | ||
| 736 | { | ||
| 737 | return sd_coud_16.class[index_coud(cube)]; | ||
| 738 | } | ||
| 739 | |||
| 740 | static uint64_t | ||
| 741 | index_cp_sym16(Cube cube) | ||
| 742 | { | ||
| 743 | return sd_cp_16.class[index_cp(cube)]; | ||
| 744 | } | ||
| 745 | |||
| 746 | static uint64_t | ||
| 747 | index_drud_sym16(Cube cube) | ||
| 748 | { | ||
| 749 | Trans t; | ||
| 750 | Cube c; | ||
| 751 | |||
| 752 | t = sd_eofbepos_16.transtorep[index_eofbepos(cube)]; | ||
| 753 | c = apply_trans(t, cube); | ||
| 754 | |||
| 755 | return index_eofbepos_sym16(c) * POW3TO7 + c.coud; | ||
| 756 | } | ||
| 757 | |||
| 758 | static uint64_t | ||
| 759 | index_drudfin_noE_sym16(Cube cube) | ||
| 760 | { | ||
| 761 | Trans t; | ||
| 762 | Cube c; | ||
| 763 | |||
| 764 | t = sd_cp_16.transtorep[index_cp(cube)]; | ||
| 765 | c = apply_trans(t, cube); | ||
| 766 | |||
| 767 | return index_cp_sym16(c) * FACTORIAL8 + index_epud(c); | ||
| 768 | } | ||
| 769 | |||
| 770 | static uint64_t | ||
| 771 | index_htrfin(Cube cube) | ||
| 772 | { | ||
| 773 | uint64_t epe, eps, epm, cp, ep; | ||
| 774 | |||
| 775 | static bool initialized = false; | ||
| 776 | static uint64_t cp1[FACTORIAL8], cp2[FACTORIAL8]; | ||
| 777 | static unsigned int i; | ||
| 778 | static int j, n1, n2, c[8], c1[4], c2[4]; | ||
| 779 | |||
| 780 | if (!initialized) { | ||
| 781 | for (i = 0; i < FACTORIAL8; i++) { | ||
| 782 | index_to_perm(i, 8, c); | ||
| 783 | n1 = 0; | ||
| 784 | n2 = 0; | ||
| 785 | for (j = 0; j < 8; j++) | ||
| 786 | if (c[j] == UFR || c[j] == UBL || | ||
| 787 | c[j] == DFL || c[j] == DBR) | ||
| 788 | c1[n1++] = c[j] / 2; | ||
| 789 | else | ||
| 790 | c2[n2++] = c[j] / 2; | ||
| 791 | |||
| 792 | cp1[i] = perm_to_index(c1, 4); | ||
| 793 | cp2[i] = perm_to_index(c2, 4); | ||
| 794 | } | ||
| 795 | |||
| 796 | initialized = true; | ||
| 797 | } | ||
| 798 | |||
| 799 | epe = cube.epose % 24; | ||
| 800 | eps = cube.eposs % 24; | ||
| 801 | epm = cube.eposm % 24; | ||
| 802 | |||
| 803 | cp = cp1[cube.cp] * 24 + cp2[cube.cp]; | ||
| 804 | ep = (epe * 24 + eps) *24 + epm; | ||
| 805 | |||
| 806 | return ep * 24 * 24 + cp; | ||
| 807 | } | ||
| 808 | |||
| 809 | static uint64_t | ||
| 810 | index_eofbepos_sym16(Cube cube) | ||
| 811 | { | ||
| 812 | return sd_eofbepos_16.class[index_eofbepos(cube)]; | ||
| 813 | } | ||
| 814 | |||
| 815 | static uint64_t | ||
| 816 | index_khuge(Cube cube) | ||
| 817 | { | ||
| 818 | Trans t; | ||
| 819 | Cube c; | ||
| 820 | uint64_t a; | ||
| 821 | |||
| 822 | t = sd_eofbepos_16.transtorep[index_eofbepos(cube)]; | ||
| 823 | c = apply_trans(t, cube); | ||
| 824 | a = (index_eofbepos_sym16(c) * 24) + (c.epose % 24); | ||
| 825 | |||
| 826 | return a * POW3TO7 + c.coud; | ||
| 827 | } | ||
| 828 | |||
| 829 | static bool | ||
| 830 | read_symdata_file(SymData *sd) | ||
| 831 | { | ||
| 832 | init_env(); | ||
| 833 | |||
| 834 | FILE *f; | ||
| 835 | char fname[strlen(tabledir)+100]; | ||
| 836 | uint64_t n = sd->coord->max, *sn = &sd->sym_coord->max; | ||
| 837 | bool r = true; | ||
| 838 | |||
| 839 | strcpy(fname, tabledir); | ||
| 840 | strcat(fname, "/"); | ||
| 841 | strcat(fname, sd->filename); | ||
| 842 | |||
| 843 | if ((f = fopen(fname, "rb")) == NULL) | ||
| 844 | return false; | ||
| 845 | |||
| 846 | r = r && fread(&sd->sym_coord->max, sizeof(uint64_t), 1, f) == 1; | ||
| 847 | r = r && fread(sd->rep, sizeof(Cube), *sn, f) == *sn; | ||
| 848 | r = r && fread(sd->class, sizeof(uint64_t), n, f) == n; | ||
| 849 | r = r && fread(sd->transtorep, sizeof(Trans), n, f) == n; | ||
| 850 | |||
| 851 | fclose(f); | ||
| 852 | return r; | ||
| 853 | } | ||
| 854 | |||
| 855 | static bool | ||
| 856 | write_symdata_file(SymData *sd) | ||
| 857 | { | ||
| 858 | init_env(); | ||
| 859 | |||
| 860 | FILE *f; | ||
| 861 | char fname[strlen(tabledir)+100]; | ||
| 862 | uint64_t n = sd->coord->max, *sn = &sd->sym_coord->max; | ||
| 863 | bool r = true; | ||
| 864 | |||
| 865 | strcpy(fname, tabledir); | ||
| 866 | strcat(fname, "/"); | ||
| 867 | strcat(fname, sd->filename); | ||
| 868 | |||
| 869 | if ((f = fopen(fname, "wb")) == NULL) | ||
| 870 | return false; | ||
| 871 | |||
| 872 | r = r && fwrite(&sd->sym_coord->max, sizeof(uint64_t), 1, f) == 1; | ||
| 873 | r = r && fwrite(sd->rep, sizeof(Cube), *sn, f) == *sn; | ||
| 874 | r = r && fwrite(sd->class, sizeof(uint64_t), n, f) == n; | ||
| 875 | r = r && fwrite(sd->transtorep, sizeof(Trans), n, f) == n; | ||
| 876 | |||
| 877 | fclose(f); | ||
| 878 | return r; | ||
| 879 | } | ||
| 880 | |||
| 881 | /* Init functions implementation *********************************************/ | ||
| 882 | |||
| 883 | /* | ||
| 884 | * There is certainly a bette way to do this, but for now I just use | ||
| 885 | * a "graph coloring" algorithm to compute the left cosets, and I compose | ||
| 886 | * with every possible cp to get the right cosets (it is possible that I am | ||
| 887 | * mixing up left and right). | ||
| 888 | * | ||
| 889 | * For doing it better "Mathematically", we need 3 things: | ||
| 890 | * - Checking that cp separates the orbits (UFR,UBL,DFL,DBR) and the other | ||
| 891 | * This is easy and it is done in the commented function cphtr_cp(). | ||
| 892 | * - Check that there is no ep/cp parity | ||
| 893 | * - Check that we are not in the "3c" case; this is the part I don't | ||
| 894 | * know how to do. | ||
| 895 | */ | ||
| 896 | static void | ||
| 897 | init_cphtr_cosets() | ||
| 898 | { | ||
| 899 | unsigned int i; | ||
| 900 | int c = 0, d = 0; | ||
| 901 | |||
| 902 | for (i = 0; i < FACTORIAL8; i++) { | ||
| 903 | cphtr_left_cosets[i] = -1; | ||
| 904 | cphtr_right_cosets[i] = -1; | ||
| 905 | } | ||
| 906 | |||
| 907 | /* First we compute left cosets with a bfs */ | ||
| 908 | for (i = 0; i < FACTORIAL8; i++) | ||
| 909 | if (cphtr_left_cosets[i] == -1) | ||
| 910 | init_cphtr_left_cosets_bfs(i, c++); | ||
| 911 | |||
| 912 | /* Then we compute right cosets using compose() */ | ||
| 913 | for (i = 0; i < FACTORIAL8; i++) | ||
| 914 | if (cphtr_right_cosets[i] == -1) | ||
| 915 | init_cphtr_right_cosets_color(i, d++); | ||
| 916 | } | ||
| 917 | |||
| 918 | static void | ||
| 919 | init_cphtr_left_cosets_bfs(int i, int c) | ||
| 920 | { | ||
| 921 | int j, jj, k, next[FACTORIAL8], next2[FACTORIAL8], n, n2; | ||
| 922 | Move moves[6] = {U2, D2, R2, L2, F2, B2}; | ||
| 923 | |||
| 924 | n = 1; | ||
| 925 | next[0] = i; | ||
| 926 | cphtr_left_cosets[i] = c; | ||
| 927 | |||
| 928 | while (n != 0) { | ||
| 929 | for (j = 0, n2 = 0; j < n; j++) { | ||
| 930 | for (k = 0; k < 6; k++) { | ||
| 931 | /*jj = cp_mtable[moves[k]][next[j]];*/ | ||
| 932 | /* TODO fix formatting */ | ||
| 933 | jj = apply_move(moves[k], (Cube){.cp=next[j]}).cp; | ||
| 934 | if (cphtr_left_cosets[jj] == -1) { | ||
| 935 | cphtr_left_cosets[jj] = c; | ||
| 936 | next2[n2++] = jj; | ||
| 937 | } | ||
| 938 | } | ||
| 939 | } | ||
| 940 | |||
| 941 | for (j = 0; j < n2; j++) | ||
| 942 | next[j] = next2[j]; | ||
| 943 | n = n2; | ||
| 944 | } | ||
| 945 | } | ||
| 946 | |||
| 947 | static void | ||
| 948 | init_cphtr_right_cosets_color(int i, int d) | ||
| 949 | { | ||
| 950 | int cp; | ||
| 951 | unsigned int j; | ||
| 952 | |||
| 953 | cphtr_right_rep[d] = i; | ||
| 954 | for (j = 0; j < FACTORIAL8; j++) { | ||
| 955 | if (cphtr_left_cosets[j] == 0) { | ||
| 956 | /* TODO: use antindexer, it's nicer */ | ||
| 957 | cp = compose((Cube){.cp = i}, (Cube){.cp = j}).cp; | ||
| 958 | cphtr_right_cosets[cp] = d; | ||
| 959 | } | ||
| 960 | } | ||
| 961 | } | ||
| 962 | |||
| 963 | static void | ||
| 964 | init_symdata() | ||
| 965 | { | ||
| 966 | int i; | ||
| 967 | |||
| 968 | for (i = 0; i < n_all_symdata; i++) | ||
| 969 | gensym(all_sd[i]); | ||
| 970 | } | ||
| 971 | |||
| 972 | /*TODO maybe move the next two */ | ||
| 973 | uint64_t | ||
| 974 | cphtr(Cube cube) | ||
| 975 | { | ||
| 976 | return cphtr_right_cosets[cube.cp]; | ||
| 977 | } | ||
| 978 | |||
| 979 | Cube | ||
| 980 | anti_cphtr(uint64_t ind) | ||
| 981 | { | ||
| 982 | return (Cube) { .cp = cphtr_right_rep[ind] }; | ||
| 983 | } | ||
| 984 | |||
| 985 | uint64_t | ||
| 986 | epos_dependent(Cube c) | ||
| 987 | { | ||
| 988 | static int initialized = false; | ||
| 989 | static int aux[BINOM12ON4][BINOM12ON4]; | ||
| 990 | static uint64_t ui, uj; | ||
| 991 | |||
| 992 | if (!initialized) { | ||
| 993 | for (ui = 0; ui < BINOM12ON4; ui++) | ||
| 994 | for (uj = 0; uj < BINOM12ON4; uj++) | ||
| 995 | aux[ui][uj] = epos_dependent_pos(ui, uj); | ||
| 996 | |||
| 997 | initialized = true; | ||
| 998 | } | ||
| 999 | |||
| 1000 | return aux[c.eposs/FACTORIAL4][c.epose/FACTORIAL4]; | ||
| 1001 | } | ||
| 1002 | |||
| 1003 | void | ||
| 1004 | init_coord() | ||
| 1005 | { | ||
| 1006 | static bool initialized = false; | ||
| 1007 | if (initialized) | ||
| 1008 | return; | ||
| 1009 | initialized = true; | ||
| 1010 | |||
| 1011 | init_cphtr_cosets(); | ||
| 1012 | init_symdata(); | ||
| 1013 | } | ||
| 1014 | |||
diff --git a/old/coord.h b/old/coord.h new file mode 100644 index 0000000..3e230a8 --- /dev/null +++ b/old/coord.h | |||
| @@ -0,0 +1,45 @@ | |||
| 1 | #ifndef COORD_H | ||
| 2 | #define COORD_H | ||
| 3 | |||
| 4 | #include "trans.h" | ||
| 5 | |||
| 6 | extern Coordinate coord_eofb; | ||
| 7 | extern Coordinate coord_eofbepos; | ||
| 8 | extern Coordinate coord_coud; | ||
| 9 | extern Coordinate coord_cp; | ||
| 10 | extern Coordinate coord_corners; | ||
| 11 | extern Coordinate coord_cornershtr; | ||
| 12 | extern Coordinate coord_drud; | ||
| 13 | extern Coordinate coord_coud_sym16; | ||
| 14 | extern Coordinate coord_drud_eofb; | ||
| 15 | extern Coordinate coord_cp_sym16; | ||
| 16 | extern Coordinate coord_eofbepos_sym16; | ||
| 17 | extern Coordinate coord_drud_sym16; | ||
| 18 | extern Coordinate coord_drudfin_noE_sym16; | ||
| 19 | extern Coordinate coord_htrfin; | ||
| 20 | extern Coordinate coord_khuge; | ||
| 21 | |||
| 22 | uint64_t cphtr(Cube cube); /* TODO: rename (something with cosets) */ | ||
| 23 | Cube anti_cphtr(uint64_t ind); /*TODO also this */ | ||
| 24 | uint64_t epos_dependent(Cube cube); /* TODO: rename and turn into an indexer */ | ||
| 25 | |||
| 26 | bool check_centers(Cube cube); | ||
| 27 | bool check_corners(Cube cube); | ||
| 28 | bool check_cp(Cube cube); | ||
| 29 | bool check_cornershtr(Cube cube); | ||
| 30 | bool check_coud(Cube cube); | ||
| 31 | bool check_drud(Cube cube); | ||
| 32 | bool check_htr(Cube cube); | ||
| 33 | bool check_htrfin(Cube cube); | ||
| 34 | bool check_drudfin_noE(Cube cube); | ||
| 35 | bool check_eofb(Cube cube); | ||
| 36 | bool check_eofbepos(Cube cube); | ||
| 37 | bool check_epose(Cube cube); | ||
| 38 | bool check_ep(Cube cube); | ||
| 39 | bool check_khuge(Cube cube); | ||
| 40 | bool check_nothing(Cube cube); | ||
| 41 | |||
| 42 | void init_coord(); | ||
| 43 | |||
| 44 | #endif | ||
| 45 | |||
diff --git a/old/utils.c b/old/utils.c new file mode 100644 index 0000000..3b5388e --- /dev/null +++ b/old/utils.c | |||
| @@ -0,0 +1,294 @@ | |||
| 1 | #include "utils.h" | ||
| 2 | |||
| 3 | /* Generic utility functions *************************************************/ | ||
| 4 | |||
| 5 | void | ||
| 6 | apply_permutation(int *perm, int *set, int n) | ||
| 7 | { | ||
| 8 | int *aux = malloc(n * sizeof(int)); | ||
| 9 | int i; | ||
| 10 | |||
| 11 | if (!is_perm(perm, n)) | ||
| 12 | return; | ||
| 13 | |||
| 14 | for (i = 0; i < n; i++) | ||
| 15 | aux[i] = set[perm[i]]; | ||
| 16 | |||
| 17 | intarrcopy(aux, set, n); | ||
| 18 | free(aux); | ||
| 19 | } | ||
| 20 | |||
| 21 | void | ||
| 22 | intarrcopy(int *src, int *dst, int n) | ||
| 23 | { | ||
| 24 | int i; | ||
| 25 | for (i = 0; i < n; i++) | ||
| 26 | dst[i] = src[i]; | ||
| 27 | } | ||
| 28 | |||
| 29 | bool | ||
| 30 | is_perm(int *a, int n) | ||
| 31 | { | ||
| 32 | int *aux = malloc(n * sizeof(int)); | ||
| 33 | int i; | ||
| 34 | |||
| 35 | for (i = 0; i < n; i++) | ||
| 36 | if (a[i] < 0 || a[i] >= n) | ||
| 37 | return false; | ||
| 38 | else | ||
| 39 | aux[a[i]] = 1; | ||
| 40 | |||
| 41 | for (i = 0; i < n; i++) | ||
| 42 | if (!aux[i]) | ||
| 43 | return false; | ||
| 44 | |||
| 45 | free(aux); | ||
| 46 | |||
| 47 | return true; | ||
| 48 | } | ||
| 49 | |||
| 50 | bool | ||
| 51 | is_subset(int *a, int n, int k) | ||
| 52 | { | ||
| 53 | int i, sum = 0; | ||
| 54 | |||
| 55 | for (i = 0; i < n; i++) | ||
| 56 | sum += a[i] ? 1 : 0; | ||
| 57 | |||
| 58 | return sum == k; | ||
| 59 | } | ||
| 60 | |||
| 61 | int | ||
| 62 | sum(int *a, int n) | ||
| 63 | { | ||
| 64 | int i, ret = 0; | ||
| 65 | |||
| 66 | for (i = 0; i < n; i++) | ||
| 67 | ret += a[i]; | ||
| 68 | |||
| 69 | return ret; | ||
| 70 | } | ||
| 71 | |||
| 72 | void | ||
| 73 | sum_arrays_mod(int *src, int *dst, int n, int m) | ||
| 74 | { | ||
| 75 | int i; | ||
| 76 | |||
| 77 | for (i = 0; i < n; i++) | ||
| 78 | dst[i] = (m <= 0) ? 0 : (src[i] + dst[i]) % m; | ||
| 79 | } | ||
| 80 | |||
| 81 | void | ||
| 82 | swap(int *a, int *b) | ||
| 83 | { | ||
| 84 | int aux; | ||
| 85 | |||
| 86 | aux = *a; | ||
| 87 | *a = *b; | ||
| 88 | *b = aux; | ||
| 89 | } | ||
| 90 | |||
| 91 | /* Standard mathematical functions *******************************************/ | ||
| 92 | |||
| 93 | int | ||
| 94 | binomial(int n, int k) | ||
| 95 | { | ||
| 96 | if (n < 0 || k < 0 || k > n) | ||
| 97 | return 0; | ||
| 98 | |||
| 99 | return factorial(n) / (factorial(k) * factorial(n-k)); | ||
| 100 | } | ||
| 101 | |||
| 102 | int | ||
| 103 | factorial(int n) | ||
| 104 | { | ||
| 105 | int i, ret = 1; | ||
| 106 | |||
| 107 | if (n < 0) | ||
| 108 | return 0; | ||
| 109 | |||
| 110 | for (i = 1; i <= n; i++) | ||
| 111 | ret *= i; | ||
| 112 | |||
| 113 | return ret; | ||
| 114 | } | ||
| 115 | |||
| 116 | int | ||
| 117 | perm_sign(int *a, int n) | ||
| 118 | { | ||
| 119 | int i, j, ret = 0; | ||
| 120 | if (!is_perm(a,n)) | ||
| 121 | return -1; | ||
| 122 | |||
| 123 | for (i = 0; i < n; i++) | ||
| 124 | for (j = i+1; j < n; j++) | ||
| 125 | ret += (a[i] > a[j]) ? 1 : 0; | ||
| 126 | |||
| 127 | return ret % 2; | ||
| 128 | } | ||
| 129 | |||
| 130 | int | ||
| 131 | powint(int a, int b) | ||
| 132 | { | ||
| 133 | if (b < 0) | ||
| 134 | return 0; /* Truncate */ | ||
| 135 | if (b == 0) | ||
| 136 | return 1; | ||
| 137 | |||
| 138 | if (b % 2) | ||
| 139 | return a * powint(a, b-1); | ||
| 140 | else | ||
| 141 | return powint(a*a, b/2); | ||
| 142 | } | ||
| 143 | |||
| 144 | /* Conversions to and from int (base b digits, permutations...) **************/ | ||
| 145 | |||
| 146 | int | ||
| 147 | digit_array_to_int(int *a, int n, int b) | ||
| 148 | { | ||
| 149 | int i, ret = 0, p = 1; | ||
| 150 | |||
| 151 | for (i = 0; i < n; i++, p *= b) | ||
| 152 | ret += a[i] * p; | ||
| 153 | |||
| 154 | return ret; | ||
| 155 | } | ||
| 156 | |||
| 157 | void | ||
| 158 | int_to_digit_array(int a, int b, int n, int *r) | ||
| 159 | { | ||
| 160 | int i; | ||
| 161 | |||
| 162 | if (b <= 1) | ||
| 163 | for (i = 0; i < n; i++) | ||
| 164 | r[i] = 0; | ||
| 165 | else | ||
| 166 | for (i = 0; i < n; i++, a /= b) | ||
| 167 | r[i] = a % b; | ||
| 168 | } | ||
| 169 | |||
| 170 | void | ||
| 171 | int_to_sum_zero_array(int x, int b, int n, int *a) | ||
| 172 | { | ||
| 173 | int i, s = 0; | ||
| 174 | |||
| 175 | if (b <= 1) { | ||
| 176 | for (i = 0; i < n; i++) | ||
| 177 | a[i] = 0; | ||
| 178 | } else { | ||
| 179 | int_to_digit_array(x, b, n-1, a); | ||
| 180 | for (i = 0; i < n - 1; i++) | ||
| 181 | s = (s + a[i]) % b; | ||
| 182 | a[n-1] = (b - s) % b; | ||
| 183 | } | ||
| 184 | } | ||
| 185 | |||
| 186 | int | ||
| 187 | invert_digits(int a, int b, int n) | ||
| 188 | { | ||
| 189 | int i, *r = malloc(n * sizeof(int)); | ||
| 190 | |||
| 191 | int_to_digit_array(a, b, n, r); | ||
| 192 | for (i = 0; i < n; i++) | ||
| 193 | r[i] = (b-r[i]) % b; | ||
| 194 | |||
| 195 | return digit_array_to_int(r, n, b); | ||
| 196 | } | ||
| 197 | |||
| 198 | void | ||
| 199 | index_to_perm(int p, int n, int *r) | ||
| 200 | { | ||
| 201 | int *a = malloc(n * sizeof(int)); | ||
| 202 | int i, j, c; | ||
| 203 | |||
| 204 | for (i = 0; i < n; i++) | ||
| 205 | a[i] = 0; | ||
| 206 | |||
| 207 | if (p < 0 || p >= factorial(n)) | ||
| 208 | for (i = 0; i < n; i++) | ||
| 209 | r[i] = -1; | ||
| 210 | |||
| 211 | for (i = 0; i < n; i++) { | ||
| 212 | c = 0; | ||
| 213 | j = 0; | ||
| 214 | while (c <= p / factorial(n-i-1)) | ||
| 215 | c += a[j++] ? 0 : 1; | ||
| 216 | r[i] = j-1; | ||
| 217 | a[j-1] = 1; | ||
| 218 | p %= factorial(n-i-1); | ||
| 219 | } | ||
| 220 | |||
| 221 | free(a); | ||
| 222 | } | ||
| 223 | |||
| 224 | int | ||
| 225 | perm_to_index(int *a, int n) | ||
| 226 | { | ||
| 227 | int i, j, c, ret = 0; | ||
| 228 | |||
| 229 | if (!is_perm(a, n)) | ||
| 230 | return -1; | ||
| 231 | |||
| 232 | for (i = 0; i < n; i++) { | ||
| 233 | c = 0; | ||
| 234 | for (j = i+1; j < n; j++) | ||
| 235 | c += (a[i] > a[j]) ? 1 : 0; | ||
| 236 | ret += factorial(n-i-1) * c; | ||
| 237 | } | ||
| 238 | |||
| 239 | return ret; | ||
| 240 | } | ||
| 241 | |||
| 242 | void | ||
| 243 | index_to_subset(int s, int n, int k, int *r) | ||
| 244 | { | ||
| 245 | int i, j, v; | ||
| 246 | |||
| 247 | if (s < 0 || s >= binomial(n, k)) { | ||
| 248 | for (i = 0; i < n; i++) | ||
| 249 | r[i] = -1; | ||
| 250 | return; | ||
| 251 | } | ||
| 252 | |||
| 253 | for (i = 0; i < n; i++) { | ||
| 254 | if (k == n-i) { | ||
| 255 | for (j = i; j < n; j++) | ||
| 256 | r[j] = 1; | ||
| 257 | return; | ||
| 258 | } | ||
| 259 | |||
| 260 | if (k == 0) { | ||
| 261 | for (j = i; j < n; j++) | ||
| 262 | r[j] = 0; | ||
| 263 | return; | ||
| 264 | } | ||
| 265 | |||
| 266 | v = binomial(n-i-1, k); | ||
| 267 | if (s >= v) { | ||
| 268 | r[i] = 1; | ||
| 269 | k--; | ||
| 270 | s -= v; | ||
| 271 | } else { | ||
| 272 | r[i] = 0; | ||
| 273 | } | ||
| 274 | } | ||
| 275 | } | ||
| 276 | |||
| 277 | int subset_to_index(int *a, int n, int k) { | ||
| 278 | int i, ret = 0; | ||
| 279 | |||
| 280 | /* TODO: better checks */ | ||
| 281 | if (!is_subset(a, n, k)) | ||
| 282 | return binomial(n, k); | ||
| 283 | |||
| 284 | for (i = 0; i < n; i++) { | ||
| 285 | if (k == n-i) | ||
| 286 | return ret; | ||
| 287 | if (a[i]) { | ||
| 288 | ret += binomial(n-i-1, k); | ||
| 289 | k--; | ||
| 290 | } | ||
| 291 | } | ||
| 292 | |||
| 293 | return ret; | ||
| 294 | } | ||
diff --git a/old/utils.h b/old/utils.h new file mode 100644 index 0000000..ee8ac6e --- /dev/null +++ b/old/utils.h | |||
| @@ -0,0 +1,59 @@ | |||
| 1 | #ifndef UTILS_H | ||
| 2 | #define UTILS_H | ||
| 3 | |||
| 4 | #include <stdbool.h> | ||
| 5 | #include <stdlib.h> | ||
| 6 | |||
| 7 | /* Constants and macros *****************************************************/ | ||
| 8 | |||
| 9 | #define pow2to11 2048 | ||
| 10 | #define pow2to12 4096 | ||
| 11 | #define pow3to7 2187 | ||
| 12 | #define pow3to8 6561 | ||
| 13 | #define pow12to4 20736 | ||
| 14 | #define factorial4 24 | ||
| 15 | #define factorial6 720 | ||
| 16 | #define factorial8 40320 | ||
| 17 | #define factorial12 479001600 | ||
| 18 | #define binom12on4 495 | ||
| 19 | #define binom8on4 70 | ||
| 20 | |||
| 21 | #define min(a,b) (((a) < (b)) ? (a) : (b)) | ||
| 22 | #define max(a,b) (((a) > (b)) ? (a) : (b)) | ||
| 23 | |||
| 24 | /* Generic utility functions *************************************************/ | ||
| 25 | |||
| 26 | void apply_permutation(int *perm, int *set, int n); | ||
| 27 | void intarrcopy(int *src, int *dst, int n); | ||
| 28 | bool is_perm(int *a, int n); | ||
| 29 | bool is_subset(int *a, int n, int k); | ||
| 30 | int sum(int *a, int n); | ||
| 31 | void sum_arrays_mod(int *src, int *dst, int n, int m); | ||
| 32 | void swap(int *a, int *b); | ||
| 33 | |||
| 34 | /* Standard mathematical functions *******************************************/ | ||
| 35 | |||
| 36 | int binomial(int n, int k); | ||
| 37 | int factorial(int n); | ||
| 38 | int perm_sign(int a[], int n); | ||
| 39 | int powint(int a, int b); | ||
| 40 | |||
| 41 | /* Conversions to and from int (base b digits, permutations...) **************/ | ||
| 42 | |||
| 43 | int digit_array_to_int(int *a, int n, int b); | ||
| 44 | void int_to_digit_array(int a, int b, int n, int *r); | ||
| 45 | void int_to_sum_zero_array(int x, int b, int n, int *a); | ||
| 46 | int invert_digits(int a, int b, int n); | ||
| 47 | |||
| 48 | void index_to_perm(int p, int n, int *r); | ||
| 49 | int perm_to_index(int *a, int n); | ||
| 50 | |||
| 51 | void index_to_subset(int s, int n, int k, int *r); | ||
| 52 | int subset_to_index(int *a, int n, int k); | ||
| 53 | |||
| 54 | /* Am I not using these two? | ||
| 55 | void index_to_ordered_subset(int s, int n, int k, int *r); | ||
| 56 | int ordered_subset_to_index(int *a, int n, int k); | ||
| 57 | */ | ||
| 58 | |||
| 59 | #endif | ||
