diff options
| author | Sebastiano Tronto <sebastiano@tronto.net> | 2024-05-10 09:10:12 +0200 |
|---|---|---|
| committer | Sebastiano Tronto <sebastiano@tronto.net> | 2024-05-10 09:10:12 +0200 |
| commit | a660922d738b78b11fc78207daabea031058f710 (patch) | |
| tree | db46bd95bffeb330cea6066c77f2709f96c033aa /src/solve_generic.h | |
| parent | 75966319fd5891c2c1bd35b1f7c93eab172fd28e (diff) | |
| download | nissy-core-a660922d738b78b11fc78207daabea031058f710.tar.gz nissy-core-a660922d738b78b11fc78207daabea031058f710.zip | |
Split into .h files
Diffstat (limited to 'src/solve_generic.h')
| -rw-r--r-- | src/solve_generic.h | 259 |
1 files changed, 259 insertions, 0 deletions
diff --git a/src/solve_generic.h b/src/solve_generic.h new file mode 100644 index 0000000..925aa33 --- /dev/null +++ b/src/solve_generic.h | |||
| @@ -0,0 +1,259 @@ | |||
| 1 | typedef struct { | ||
| 2 | cube_fast_t cube; | ||
| 3 | uint8_t depth; | ||
| 4 | int64_t maxsols; | ||
| 5 | char **nextsol; | ||
| 6 | int64_t *nsols; | ||
| 7 | uint8_t nmoves; | ||
| 8 | uint8_t moves[20]; | ||
| 9 | uint8_t (*estimate)(cube_fast_t); | ||
| 10 | } dfsarg_generic_t; | ||
| 11 | |||
| 12 | _static void solve_generic_appendsolution(dfsarg_generic_t *); | ||
| 13 | _static int solve_generic_dfs(dfsarg_generic_t *); | ||
| 14 | _static int64_t solve_generic(cube_t, const char *, int8_t, int8_t, int64_t, | ||
| 15 | int8_t, char *, uint8_t (*)(cube_fast_t)); | ||
| 16 | _static uint8_t estimate_simple(cube_fast_t); | ||
| 17 | _static int64_t solve_simple(cube_t, int8_t, int8_t, int64_t, int8_t, char *); | ||
| 18 | |||
| 19 | int64_t | ||
| 20 | solve( | ||
| 21 | cube_t cube, | ||
| 22 | const char *solver, | ||
| 23 | const char *options, | ||
| 24 | const char *nisstype, | ||
| 25 | int8_t minmoves, | ||
| 26 | int8_t maxmoves, | ||
| 27 | int64_t maxsols, | ||
| 28 | int8_t optimal, | ||
| 29 | const void *data, | ||
| 30 | char *solutions | ||
| 31 | ) | ||
| 32 | { | ||
| 33 | DBG_WARN(!strcmp(options, ""), | ||
| 34 | "solve: 'options' not implemented yet, ignoring\n"); | ||
| 35 | |||
| 36 | DBG_WARN(!strcmp(nisstype, ""), | ||
| 37 | "solve: NISS not implemented yet, ignoring 'nisstype'\n"); | ||
| 38 | |||
| 39 | DBG_WARN(data == NULL, | ||
| 40 | "solve: 'data' not implemented yet, ignoring\n"); | ||
| 41 | |||
| 42 | if (!strcmp(solver, "optimal") || !strcmp(solver, "simple")) { | ||
| 43 | return solve_simple( | ||
| 44 | cube, | ||
| 45 | minmoves, | ||
| 46 | maxmoves, | ||
| 47 | maxsols, | ||
| 48 | optimal, | ||
| 49 | solutions | ||
| 50 | ); | ||
| 51 | } else { | ||
| 52 | DBG_LOG("solve: unknown solver '%s'\n", solver); | ||
| 53 | return -1; | ||
| 54 | } | ||
| 55 | |||
| 56 | DBG_LOG("solve: error\n"); | ||
| 57 | return -1; | ||
| 58 | } | ||
| 59 | |||
| 60 | void | ||
| 61 | multisolve( | ||
| 62 | int n, | ||
| 63 | cube_t *cube, | ||
| 64 | const char *solver, | ||
| 65 | const void *data, | ||
| 66 | char *sols | ||
| 67 | ) | ||
| 68 | { | ||
| 69 | char *s; | ||
| 70 | int i; | ||
| 71 | |||
| 72 | s = sols; | ||
| 73 | for (i = 0; i < n; i++) { | ||
| 74 | solve(cube[i], solver, "", "normal", 0, -1, 1, 0, NULL, s); | ||
| 75 | while (s++); | ||
| 76 | } | ||
| 77 | } | ||
| 78 | |||
| 79 | int64_t | ||
| 80 | gendata(const char *solver, void *data) | ||
| 81 | { | ||
| 82 | DBG_LOG("gendata: not implemented yet\n"); | ||
| 83 | |||
| 84 | return -1; | ||
| 85 | } | ||
| 86 | |||
| 87 | _static void | ||
| 88 | solve_generic_appendsolution(dfsarg_generic_t *arg) | ||
| 89 | { | ||
| 90 | int strl; | ||
| 91 | |||
| 92 | strl = writemoves(arg->moves, arg->depth, *arg->nextsol); | ||
| 93 | DBG_LOG("Solution found: %s\n", *arg->nextsol); | ||
| 94 | *arg->nextsol += strl; | ||
| 95 | **arg->nextsol = '\n'; | ||
| 96 | (*arg->nextsol)++; | ||
| 97 | (*arg->nsols)++; | ||
| 98 | } | ||
| 99 | |||
| 100 | _static int | ||
| 101 | solve_generic_dfs(dfsarg_generic_t *arg) | ||
| 102 | { | ||
| 103 | dfsarg_generic_t nextarg; | ||
| 104 | uint8_t m, bound; | ||
| 105 | int64_t ret; | ||
| 106 | |||
| 107 | if (!allowednextmove(arg->moves, arg->nmoves)) | ||
| 108 | return 0; | ||
| 109 | |||
| 110 | if (arg->nmoves > 0) | ||
| 111 | arg->cube = move(arg->cube, arg->moves[arg->nmoves-1]); | ||
| 112 | |||
| 113 | bound = arg->estimate(arg->cube); | ||
| 114 | if (*arg->nsols == arg->maxsols || bound + arg->nmoves > arg->depth) | ||
| 115 | return 0; | ||
| 116 | |||
| 117 | if (bound == 0) { | ||
| 118 | if (arg->nmoves != arg->depth) | ||
| 119 | return 0; | ||
| 120 | solve_generic_appendsolution(arg); | ||
| 121 | return 1; | ||
| 122 | } | ||
| 123 | |||
| 124 | /* memcpy(&nextarg, arg, sizeof(dfsarg_generic_t)); */ | ||
| 125 | nextarg = *arg; | ||
| 126 | nextarg.nmoves = arg->nmoves + 1; | ||
| 127 | for (m = 0, ret = 0; m < 18; m++) { | ||
| 128 | nextarg.cube = arg->cube; | ||
| 129 | nextarg.moves[arg->nmoves] = m; | ||
| 130 | ret += solve_generic_dfs(&nextarg); | ||
| 131 | } | ||
| 132 | |||
| 133 | return ret; | ||
| 134 | } | ||
| 135 | |||
| 136 | _static int64_t | ||
| 137 | solve_generic( | ||
| 138 | cube_t cube, | ||
| 139 | const char *nisstype, | ||
| 140 | /* TODO: handle NISS */ | ||
| 141 | int8_t minmoves, | ||
| 142 | int8_t maxmoves, | ||
| 143 | int64_t maxsols, | ||
| 144 | int8_t optimal, | ||
| 145 | char *sols, | ||
| 146 | uint8_t (*estimate)(cube_fast_t) | ||
| 147 | /* TODO: add validator */ | ||
| 148 | /* TODO: maybe add data for estimate */ | ||
| 149 | /* TODO: add moveset (and allowednext?) */ | ||
| 150 | ) | ||
| 151 | { | ||
| 152 | dfsarg_generic_t arg; | ||
| 153 | int64_t ret, tmp, first; | ||
| 154 | |||
| 155 | if (!issolvable(cube)) { | ||
| 156 | DBG_LOG("solve: cube is not solvable\n"); | ||
| 157 | return -1; | ||
| 158 | } | ||
| 159 | |||
| 160 | if (issolved(cube)) { | ||
| 161 | DBG_LOG("solve: cube is already solved\n"); | ||
| 162 | sols[0] = '\n'; | ||
| 163 | sols[1] = 0; | ||
| 164 | return 1; | ||
| 165 | } | ||
| 166 | |||
| 167 | DBG_WARN(!strcmp(nisstype, ""), | ||
| 168 | "solve: NISS not implemented yet, 'nisstype' ignored\n"); | ||
| 169 | |||
| 170 | if (minmoves < 0) { | ||
| 171 | DBG_LOG("solve: 'minmoves' is negative, setting to 0\n"); | ||
| 172 | minmoves = 0; | ||
| 173 | } | ||
| 174 | |||
| 175 | if (maxmoves < 0) { | ||
| 176 | DBG_LOG("solve: invalid 'maxmoves', setting to 20\n"); | ||
| 177 | maxmoves = 20; | ||
| 178 | } | ||
| 179 | |||
| 180 | if (maxsols < 0) { | ||
| 181 | DBG_LOG("solve: 'maxsols' is negative\n"); | ||
| 182 | return -1; | ||
| 183 | } | ||
| 184 | |||
| 185 | if (maxsols == 0) { | ||
| 186 | DBG_LOG("solve: 'maxsols' is 0\n"); | ||
| 187 | return 0; | ||
| 188 | } | ||
| 189 | |||
| 190 | if (sols == NULL) { | ||
| 191 | DBG_LOG("solve: return parameter 'sols' is NULL\n"); | ||
| 192 | return -1; | ||
| 193 | } | ||
| 194 | |||
| 195 | if (estimate == NULL) { | ||
| 196 | DBG_LOG("solve: 'estimate' is NULL\n"); | ||
| 197 | return -1; | ||
| 198 | } | ||
| 199 | |||
| 200 | arg = (dfsarg_generic_t) { | ||
| 201 | .cube = cubetofast(cube), | ||
| 202 | .maxsols = maxsols, | ||
| 203 | .nextsol = &sols, | ||
| 204 | .nsols = &ret, | ||
| 205 | .nmoves = 0, | ||
| 206 | .moves = {0}, | ||
| 207 | .estimate = estimate, | ||
| 208 | }; | ||
| 209 | |||
| 210 | ret = 0; | ||
| 211 | first = -1; | ||
| 212 | for (arg.depth = minmoves; arg.depth <= maxmoves; arg.depth++) { | ||
| 213 | tmp = solve_generic_dfs(&arg); | ||
| 214 | if (tmp != 0) | ||
| 215 | first = arg.depth; | ||
| 216 | |||
| 217 | DBG_LOG("Found %" PRId64 " solution%s at depth %" PRIu8 "\n", | ||
| 218 | tmp, tmp == 1 ? "" : "s", arg.depth); | ||
| 219 | |||
| 220 | if (ret >= maxsols) | ||
| 221 | break; | ||
| 222 | |||
| 223 | if (optimal >= 0 && first >= 0 && arg.depth - first == optimal) | ||
| 224 | break; | ||
| 225 | } | ||
| 226 | |||
| 227 | DBG_ASSERT(ret <= maxsols, ret, | ||
| 228 | "solve: found more than 'maxsols' solutions\n"); | ||
| 229 | |||
| 230 | return ret; | ||
| 231 | } | ||
| 232 | |||
| 233 | _static uint8_t | ||
| 234 | estimate_simple(cube_fast_t cube) | ||
| 235 | { | ||
| 236 | return issolved_fast(cube) ? 0 : 1; | ||
| 237 | } | ||
| 238 | |||
| 239 | _static int64_t | ||
| 240 | solve_simple( | ||
| 241 | cube_t cube, | ||
| 242 | int8_t minmoves, | ||
| 243 | int8_t maxmoves, | ||
| 244 | int64_t maxsols, | ||
| 245 | int8_t optimal, | ||
| 246 | char *solutions | ||
| 247 | ) | ||
| 248 | { | ||
| 249 | return solve_generic( | ||
| 250 | cube, | ||
| 251 | "", | ||
| 252 | minmoves, | ||
| 253 | maxmoves, | ||
| 254 | maxsols, | ||
| 255 | optimal, | ||
| 256 | solutions, | ||
| 257 | &estimate_simple | ||
| 258 | ); | ||
| 259 | } | ||
