diff options
Diffstat (limited to 'src/solve_h48.h')
| -rw-r--r-- | src/solve_h48.h | 111 |
1 files changed, 107 insertions, 4 deletions
diff --git a/src/solve_h48.h b/src/solve_h48.h index 201c7c6..c2c541d 100644 --- a/src/solve_h48.h +++ b/src/solve_h48.h | |||
| @@ -57,6 +57,15 @@ typedef struct { | |||
| 57 | char **nextsol; | 57 | char **nextsol; |
| 58 | } dfsarg_solveh48_t; | 58 | } dfsarg_solveh48_t; |
| 59 | 59 | ||
| 60 | typedef struct { | ||
| 61 | cube_t cube; | ||
| 62 | int8_t nmoves; | ||
| 63 | int8_t depth; | ||
| 64 | uint8_t moves[MAX_SOLUTION_LENGTH]; | ||
| 65 | uint32_t *cocsepdata; | ||
| 66 | char *s; | ||
| 67 | } dfsarg_solveh48stats_t; | ||
| 68 | |||
| 60 | _static_inline int64_t coord_h48(cube_t, const uint32_t *, uint8_t); | 69 | _static_inline int64_t coord_h48(cube_t, const uint32_t *, uint8_t); |
| 61 | _static_inline int64_t coord_h48_edges(cube_t, int64_t, uint8_t, uint8_t); | 70 | _static_inline int64_t coord_h48_edges(cube_t, int64_t, uint8_t, uint8_t); |
| 62 | _static_inline cube_t invcoord_h48(int64_t, const cube_t *, uint8_t); | 71 | _static_inline cube_t invcoord_h48(int64_t, const cube_t *, uint8_t); |
| @@ -78,6 +87,9 @@ _static_inline bool solve_h48_stop(dfsarg_solveh48_t *); | |||
| 78 | _static int64_t solve_h48_dfs(dfsarg_solveh48_t *); | 87 | _static int64_t solve_h48_dfs(dfsarg_solveh48_t *); |
| 79 | _static int64_t solve_h48(cube_t, int8_t, int8_t, int8_t, uint8_t, const void *, char *); | 88 | _static int64_t solve_h48(cube_t, int8_t, int8_t, int8_t, uint8_t, const void *, char *); |
| 80 | 89 | ||
| 90 | _static int64_t solve_h48stats_dfs(dfsarg_solveh48stats_t *); | ||
| 91 | _static int64_t solve_h48stats(cube_t, int8_t, const void *, char [static 13]); | ||
| 92 | |||
| 81 | _static_inline int64_t | 93 | _static_inline int64_t |
| 82 | coord_h48(cube_t c, const uint32_t *cocsepdata, uint8_t h) | 94 | coord_h48(cube_t c, const uint32_t *cocsepdata, uint8_t h) |
| 83 | { | 95 | { |
| @@ -104,9 +116,15 @@ coord_h48_edges(cube_t c, int64_t coclass, uint8_t t, uint8_t h) | |||
| 104 | d = transform_edges(c, t); | 116 | d = transform_edges(c, t); |
| 105 | esep = coord_esep(d); | 117 | esep = coord_esep(d); |
| 106 | eo = coord_eo(d); | 118 | eo = coord_eo(d); |
| 107 | edges = (esep << (int64_t)h) + (eo >> (11 - (int64_t)h)); | 119 | edges = (esep << 11) + eo; |
| 120 | |||
| 121 | return (coclass * H48_ESIZE(11) + edges) >> (11 - (int64_t)h); | ||
| 108 | 122 | ||
| 123 | /* | ||
| 124 | TODO: decide which alternative is better, if above or below | ||
| 125 | edges = (esep << (int64_t)h) + (eo >> (11 - (int64_t)h)); | ||
| 109 | return coclass * H48_ESIZE(h) + edges; | 126 | return coclass * H48_ESIZE(h) + edges; |
| 127 | */ | ||
| 110 | } | 128 | } |
| 111 | 129 | ||
| 112 | /* | 130 | /* |
| @@ -160,7 +178,8 @@ gendata_cocsep(void *buf, uint64_t *selfsim, cube_t *rep) | |||
| 160 | buf32 = (uint32_t *)buf; | 178 | buf32 = (uint32_t *)buf; |
| 161 | info = buf32 + COCSEP_TABLESIZE; | 179 | info = buf32 + COCSEP_TABLESIZE; |
| 162 | memset(buf32, 0xFF, sizeof(uint32_t) * COCSEP_TABLESIZE); | 180 | memset(buf32, 0xFF, sizeof(uint32_t) * COCSEP_TABLESIZE); |
| 163 | memset(selfsim, 0, sizeof(uint64_t) * COCSEP_CLASSES); | 181 | if (selfsim != NULL) |
| 182 | memset(selfsim, 0, sizeof(uint64_t) * COCSEP_CLASSES); | ||
| 164 | 183 | ||
| 165 | arg = (dfsarg_cocsep_t) { | 184 | arg = (dfsarg_cocsep_t) { |
| 166 | .cube = solved, | 185 | .cube = solved, |
| @@ -221,7 +240,8 @@ gendata_cocsep_dfs(dfsarg_cocsep_t *arg) | |||
| 221 | d = transform_corners(arg->cube, t); | 240 | d = transform_corners(arg->cube, t); |
| 222 | j = coord_cocsep(d); | 241 | j = coord_cocsep(d); |
| 223 | is = (i == j); | 242 | is = (i == j); |
| 224 | arg->selfsim[*arg->n] |= is << t; | 243 | if (arg->selfsim != NULL) |
| 244 | arg->selfsim[*arg->n] |= is << t; | ||
| 225 | set_visited(arg->visited, j); | 245 | set_visited(arg->visited, j); |
| 226 | tinv = inverse_trans(t); | 246 | tinv = inverse_trans(t); |
| 227 | olddepth = (uint8_t)(arg->buf32[j] & 0xFF); | 247 | olddepth = (uint8_t)(arg->buf32[j] & 0xFF); |
| @@ -232,7 +252,8 @@ gendata_cocsep_dfs(dfsarg_cocsep_t *arg) | |||
| 232 | depth = (uint32_t)arg->depth; | 252 | depth = (uint32_t)arg->depth; |
| 233 | arg->buf32[j] = class | ttrep | depth; | 253 | arg->buf32[j] = class | ttrep | depth; |
| 234 | } | 254 | } |
| 235 | arg->rep[*arg->n] = arg->cube; | 255 | if (arg->rep != NULL) |
| 256 | arg->rep[*arg->n] = arg->cube; | ||
| 236 | (*arg->n)++; | 257 | (*arg->n)++; |
| 237 | 258 | ||
| 238 | return cc; | 259 | return cc; |
| @@ -525,3 +546,85 @@ i, get_esep_pval(arg.h48data, i)); | |||
| 525 | */ | 546 | */ |
| 526 | return nsols; | 547 | return nsols; |
| 527 | } | 548 | } |
| 549 | |||
| 550 | /* | ||
| 551 | The h48stats solver computes how many moves it takes to solve to each of | ||
| 552 | the 13 h48 coordinates: the corner-only coordinate, and 12 cocsep+esep | ||
| 553 | coordinates with h from 0 to 11. The solutions array is filled with | ||
| 554 | the length of the solutions: solutions[0] contains the value for the | ||
| 555 | corner-only coordinate, and for i>0 solutions[i] contains the value for | ||
| 556 | the cocsep+esep coordinate with h=i-1. The solution array is therefore | ||
| 557 | not a printable string. | ||
| 558 | */ | ||
| 559 | _static int64_t | ||
| 560 | solve_h48stats_dfs(dfsarg_solveh48stats_t *arg) | ||
| 561 | { | ||
| 562 | int8_t bound, u; | ||
| 563 | uint8_t m; | ||
| 564 | uint32_t d; | ||
| 565 | int64_t coord, h; | ||
| 566 | dfsarg_solveh48stats_t nextarg; | ||
| 567 | |||
| 568 | bound = get_h48_cdata(arg->cube, arg->cocsepdata, &d); | ||
| 569 | if (bound + arg->nmoves > arg->depth) | ||
| 570 | return 0; | ||
| 571 | |||
| 572 | u = COCLASS(d) == 0 && arg->s[0] == 99; | ||
| 573 | arg->s[0] = u * arg->nmoves + (1-u) * arg->s[0]; | ||
| 574 | |||
| 575 | coord = coord_h48_edges(arg->cube, COCLASS(d), TTREP(d), 11); | ||
| 576 | for (h = 0; h <= 11; h++) { | ||
| 577 | u = coord >> (11-h) == 0 && arg->s[h+1] == 99; | ||
| 578 | arg->s[h+1] = u * arg->nmoves + (1-u) * arg->s[h+1]; | ||
| 579 | } | ||
| 580 | |||
| 581 | if (arg->s[12] != 99) | ||
| 582 | return 0; | ||
| 583 | |||
| 584 | nextarg = *arg; | ||
| 585 | nextarg.nmoves = arg->nmoves + 1; | ||
| 586 | for (m = 0; m < 18; m++) { | ||
| 587 | nextarg.moves[arg->nmoves] = m; | ||
| 588 | if (!allowednextmove(nextarg.moves, nextarg.nmoves)) { | ||
| 589 | /* If a move is not allowed, neither are its 180 | ||
| 590 | * and 270 degree variations */ | ||
| 591 | m += 2; | ||
| 592 | continue; | ||
| 593 | } | ||
| 594 | nextarg.cube = move(arg->cube, m); | ||
| 595 | solve_h48stats_dfs(&nextarg); | ||
| 596 | } | ||
| 597 | |||
| 598 | return 0; | ||
| 599 | } | ||
| 600 | |||
| 601 | _static int64_t | ||
| 602 | solve_h48stats( | ||
| 603 | cube_t cube, | ||
| 604 | int8_t maxmoves, | ||
| 605 | const void *data, | ||
| 606 | char solutions[static 13] | ||
| 607 | ) | ||
| 608 | { | ||
| 609 | int i; | ||
| 610 | dfsarg_solveh48stats_t arg; | ||
| 611 | |||
| 612 | arg = (dfsarg_solveh48stats_t) { | ||
| 613 | .cube = cube, | ||
| 614 | .cocsepdata = (uint32_t *)data, | ||
| 615 | .s = solutions | ||
| 616 | }; | ||
| 617 | |||
| 618 | for (i = 0; i < 13; i++) | ||
| 619 | solutions[i] = (char)99; | ||
| 620 | |||
| 621 | for (arg.depth = 0; | ||
| 622 | arg.depth <= maxmoves && solutions[12] == 99; | ||
| 623 | arg.depth++) | ||
| 624 | { | ||
| 625 | arg.nmoves = 0; | ||
| 626 | solve_h48stats_dfs(&arg); | ||
| 627 | } | ||
| 628 | |||
| 629 | return 0; | ||
| 630 | } | ||
