aboutsummaryrefslogtreecommitdiff
path: root/src/solve_generic.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/solve_generic.h')
-rw-r--r--src/solve_generic.h259
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 @@
1typedef 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
19int64_t
20solve(
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
60void
61multisolve(
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
79int64_t
80gendata(const char *solver, void *data)
81{
82 DBG_LOG("gendata: not implemented yet\n");
83
84 return -1;
85}
86
87_static void
88solve_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
101solve_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
137solve_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
234estimate_simple(cube_fast_t cube)
235{
236 return issolved_fast(cube) ? 0 : 1;
237}
238
239_static int64_t
240solve_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}

Generated with cgit - Back to sebastiano.tronto.net