diff options
Diffstat (limited to 'src/solvers/h48/solve.h')
| -rw-r--r-- | src/solvers/h48/solve.h | 242 |
1 files changed, 242 insertions, 0 deletions
diff --git a/src/solvers/h48/solve.h b/src/solvers/h48/solve.h new file mode 100644 index 0000000..8531a40 --- /dev/null +++ b/src/solvers/h48/solve.h | |||
| @@ -0,0 +1,242 @@ | |||
| 1 | typedef struct { | ||
| 2 | cube_t cube; | ||
| 3 | cube_t inverse; | ||
| 4 | int8_t nmoves; | ||
| 5 | int8_t depth; | ||
| 6 | uint8_t moves[MAXLEN]; | ||
| 7 | int64_t *nsols; | ||
| 8 | int64_t maxsolutions; | ||
| 9 | uint8_t h; | ||
| 10 | uint32_t *cocsepdata; | ||
| 11 | uint32_t *h48data; | ||
| 12 | char **nextsol; | ||
| 13 | } dfsarg_solveh48_t; | ||
| 14 | |||
| 15 | typedef struct { | ||
| 16 | cube_t cube; | ||
| 17 | int8_t nmoves; | ||
| 18 | int8_t depth; | ||
| 19 | uint8_t moves[MAXLEN]; | ||
| 20 | uint32_t *cocsepdata; | ||
| 21 | uint32_t *h48data; | ||
| 22 | char *s; | ||
| 23 | } dfsarg_solveh48stats_t; | ||
| 24 | |||
| 25 | _static void solve_h48_appendsolution(dfsarg_solveh48_t *); | ||
| 26 | _static_inline bool solve_h48_stop(dfsarg_solveh48_t *); | ||
| 27 | _static int64_t solve_h48_dfs(dfsarg_solveh48_t *); | ||
| 28 | _static int64_t solve_h48( | ||
| 29 | cube_t, int8_t, int8_t, int8_t, uint8_t, const void *, char *); | ||
| 30 | |||
| 31 | _static int64_t solve_h48stats_dfs(dfsarg_solveh48stats_t *); | ||
| 32 | _static int64_t solve_h48stats(cube_t, int8_t, const void *, char [static 12]); | ||
| 33 | |||
| 34 | _static void | ||
| 35 | solve_h48_appendsolution(dfsarg_solveh48_t *arg) | ||
| 36 | { | ||
| 37 | int strl; | ||
| 38 | |||
| 39 | strl = writemoves(arg->moves, arg->nmoves, *arg->nextsol); | ||
| 40 | LOG("Solution found: %s\n", *arg->nextsol); | ||
| 41 | *arg->nextsol += strl; | ||
| 42 | **arg->nextsol = '\n'; | ||
| 43 | (*arg->nextsol)++; | ||
| 44 | (*arg->nsols)++; | ||
| 45 | } | ||
| 46 | |||
| 47 | _static_inline bool | ||
| 48 | solve_h48_stop(dfsarg_solveh48_t *arg) | ||
| 49 | { | ||
| 50 | uint32_t data, data_inv; | ||
| 51 | int8_t bound; | ||
| 52 | |||
| 53 | bound = get_h48_cdata(arg->cube, arg->cocsepdata, &data); | ||
| 54 | if (bound + arg->nmoves > arg->depth) | ||
| 55 | return true; | ||
| 56 | |||
| 57 | bound = get_h48_cdata(arg->inverse, arg->cocsepdata, &data_inv); | ||
| 58 | if (bound + arg->nmoves > arg->depth) | ||
| 59 | return true; | ||
| 60 | |||
| 61 | /* | ||
| 62 | bound = get_h48_bound(arg->cube, data, arg->h, arg->h48data); | ||
| 63 | LOG("Using pval %" PRId8 "\n", bound); | ||
| 64 | if (bound + arg->nmoves > arg->depth) | ||
| 65 | return true; | ||
| 66 | |||
| 67 | bound = get_h48_bound(arg->inverse, data_inv, arg->h, arg->h48data); | ||
| 68 | if (bound + arg->nmoves > arg->depth) | ||
| 69 | return true; | ||
| 70 | */ | ||
| 71 | |||
| 72 | return false; | ||
| 73 | } | ||
| 74 | |||
| 75 | _static int64_t | ||
| 76 | solve_h48_dfs(dfsarg_solveh48_t *arg) | ||
| 77 | { | ||
| 78 | dfsarg_solveh48_t nextarg; | ||
| 79 | int64_t ret; | ||
| 80 | uint8_t m; | ||
| 81 | |||
| 82 | if (*arg->nsols == arg->maxsolutions) | ||
| 83 | return 0; | ||
| 84 | |||
| 85 | if (solve_h48_stop(arg)) | ||
| 86 | return 0; | ||
| 87 | |||
| 88 | if (issolved(arg->cube)) { | ||
| 89 | if (arg->nmoves != arg->depth) | ||
| 90 | return 0; | ||
| 91 | solve_h48_appendsolution(arg); | ||
| 92 | return 1; | ||
| 93 | } | ||
| 94 | |||
| 95 | /* TODO: avoid copy, change arg and undo changes after recursion */ | ||
| 96 | nextarg = *arg; | ||
| 97 | nextarg.nmoves = arg->nmoves + 1; | ||
| 98 | ret = 0; | ||
| 99 | for (m = 0; m < 18; m++) { | ||
| 100 | nextarg.moves[arg->nmoves] = m; | ||
| 101 | if (!allowednextmove(nextarg.moves, nextarg.nmoves)) { | ||
| 102 | /* If a move is not allowed, neither are its 180 | ||
| 103 | * and 270 degree variations */ | ||
| 104 | m += 2; | ||
| 105 | continue; | ||
| 106 | } | ||
| 107 | nextarg.cube = move(arg->cube, m); | ||
| 108 | nextarg.inverse = inverse(nextarg.cube); /* TODO: use premove */ | ||
| 109 | ret += solve_h48_dfs(&nextarg); | ||
| 110 | } | ||
| 111 | |||
| 112 | return ret; | ||
| 113 | } | ||
| 114 | |||
| 115 | _static int64_t | ||
| 116 | solve_h48( | ||
| 117 | cube_t cube, | ||
| 118 | int8_t minmoves, | ||
| 119 | int8_t maxmoves, | ||
| 120 | int8_t maxsolutions, | ||
| 121 | uint8_t h, | ||
| 122 | const void *data, | ||
| 123 | char *solutions | ||
| 124 | ) | ||
| 125 | { | ||
| 126 | int64_t nsols; | ||
| 127 | dfsarg_solveh48_t arg; | ||
| 128 | |||
| 129 | arg = (dfsarg_solveh48_t) { | ||
| 130 | .cube = cube, | ||
| 131 | .inverse = inverse(cube), | ||
| 132 | .nsols = &nsols, | ||
| 133 | .maxsolutions = maxsolutions, | ||
| 134 | .h = h, | ||
| 135 | .cocsepdata = (uint32_t *)data, | ||
| 136 | .h48data = ((uint32_t *)data) + COCSEP_FULLSIZE / 4, | ||
| 137 | .nextsol = &solutions | ||
| 138 | }; | ||
| 139 | |||
| 140 | nsols = 0; | ||
| 141 | for (arg.depth = minmoves; | ||
| 142 | arg.depth <= maxmoves && nsols < maxsolutions; | ||
| 143 | arg.depth++) | ||
| 144 | { | ||
| 145 | LOG("Found %" PRId64 " solutions, searching at depth %" | ||
| 146 | PRId8 "\n", nsols, arg.depth); | ||
| 147 | arg.nmoves = 0; | ||
| 148 | solve_h48_dfs(&arg); | ||
| 149 | } | ||
| 150 | |||
| 151 | return nsols; | ||
| 152 | } | ||
| 153 | |||
| 154 | /* | ||
| 155 | The h48stats solver computes how many moves it takes to solve to | ||
| 156 | each of the 12 h48 coordinates, one for each value of h from 0 to 11. | ||
| 157 | The solutions array is filled with the length of the solutions. The | ||
| 158 | solution array is therefore not a printable string. | ||
| 159 | */ | ||
| 160 | _static int64_t | ||
| 161 | solve_h48stats_dfs(dfsarg_solveh48stats_t *arg) | ||
| 162 | { | ||
| 163 | const int64_t limit = 11; | ||
| 164 | |||
| 165 | int8_t bound, u; | ||
| 166 | uint8_t m; | ||
| 167 | uint32_t d; | ||
| 168 | int64_t coord, h; | ||
| 169 | dfsarg_solveh48stats_t nextarg; | ||
| 170 | |||
| 171 | /* Check cocsep lower bound (corners only) */ | ||
| 172 | bound = get_h48_cdata(arg->cube, arg->cocsepdata, &d); | ||
| 173 | if (bound + arg->nmoves > arg->depth) | ||
| 174 | return 0; | ||
| 175 | |||
| 176 | /* Check h48 lower bound for h=0 (esep, but no eo) */ | ||
| 177 | coord = coord_h48_edges(arg->cube, COCLASS(d), TTREP(d), 0); | ||
| 178 | bound = get_esep_pval(arg->h48data, coord); | ||
| 179 | if (bound + arg->nmoves > arg->depth) | ||
| 180 | return 0; | ||
| 181 | |||
| 182 | /* Update all other values, if solved */ | ||
| 183 | coord = coord_h48_edges(arg->cube, COCLASS(d), TTREP(d), 11); | ||
| 184 | for (h = 0; h <= limit; h++) { | ||
| 185 | u = coord >> (11-h) == 0 && arg->s[h] == 99; | ||
| 186 | arg->s[h] = u * arg->nmoves + (1-u) * arg->s[h]; | ||
| 187 | } | ||
| 188 | |||
| 189 | if (arg->s[limit] != 99) | ||
| 190 | return 0; | ||
| 191 | |||
| 192 | nextarg = *arg; | ||
| 193 | nextarg.nmoves = arg->nmoves + 1; | ||
| 194 | for (m = 0; m < 18; m++) { | ||
| 195 | nextarg.moves[arg->nmoves] = m; | ||
| 196 | if (!allowednextmove(nextarg.moves, nextarg.nmoves)) { | ||
| 197 | /* If a move is not allowed, neither are its 180 | ||
| 198 | * and 270 degree variations */ | ||
| 199 | m += 2; | ||
| 200 | continue; | ||
| 201 | } | ||
| 202 | nextarg.cube = move(arg->cube, m); | ||
| 203 | solve_h48stats_dfs(&nextarg); | ||
| 204 | } | ||
| 205 | |||
| 206 | return 0; | ||
| 207 | } | ||
| 208 | |||
| 209 | _static int64_t | ||
| 210 | solve_h48stats( | ||
| 211 | cube_t cube, | ||
| 212 | int8_t maxmoves, | ||
| 213 | const void *data, | ||
| 214 | char solutions[static 12] | ||
| 215 | ) | ||
| 216 | { | ||
| 217 | int i; | ||
| 218 | size_t cocsepsize; | ||
| 219 | dfsarg_solveh48stats_t arg; | ||
| 220 | |||
| 221 | cocsepsize = gendata_cocsep(NULL, NULL, NULL); | ||
| 222 | |||
| 223 | arg = (dfsarg_solveh48stats_t) { | ||
| 224 | .cube = cube, | ||
| 225 | .cocsepdata = (uint32_t *)data, | ||
| 226 | .h48data = ((uint32_t *)data) + (cocsepsize/4), | ||
| 227 | .s = solutions | ||
| 228 | }; | ||
| 229 | |||
| 230 | for (i = 0; i < 12; i++) | ||
| 231 | solutions[i] = (char)99; | ||
| 232 | |||
| 233 | for (arg.depth = 0; | ||
| 234 | arg.depth <= maxmoves && solutions[11] == 99; | ||
| 235 | arg.depth++) | ||
| 236 | { | ||
| 237 | arg.nmoves = 0; | ||
| 238 | solve_h48stats_dfs(&arg); | ||
| 239 | } | ||
| 240 | |||
| 241 | return 0; | ||
| 242 | } | ||
