aboutsummaryrefslogtreecommitdiff
path: root/src/solvers/solutions.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/solvers/solutions.h')
-rw-r--r--src/solvers/solutions.h213
1 files changed, 208 insertions, 5 deletions
diff --git a/src/solvers/solutions.h b/src/solvers/solutions.h
index 1396210..802075d 100644
--- a/src/solvers/solutions.h
+++ b/src/solvers/solutions.h
@@ -1,14 +1,217 @@
1#define MAXLEN 20 1STATIC void solution_moves_reset(solution_moves_t [static 1]);
2STATIC void solution_moves_transform(solution_moves_t [static 1], uint8_t t);
3STATIC bool solution_list_init(
4 solution_list_t [static 1], size_t n, char [n]);
5STATIC bool solution_moves_equal(
6 const solution_moves_t [static 1], const solution_moves_t [static 1]);
7STATIC bool solution_moves_is_duplicate(size_t n, const solution_moves_t[n]);
8STATIC bool appendchar(solution_list_t [static 1], char);
9STATIC int64_t appendsolution(const solution_moves_t [static 1],
10 const solution_settings_t [static 1], solution_list_t [static 1]);
11STATIC bool solutions_done(const solution_list_t [static 1],
12 const solution_settings_t [static 1], int8_t depth);
2 13
3STATIC bool appendchar(size_t n, char [n], size_t *, char); 14STATIC void
15solution_moves_reset(solution_moves_t sol[static 1])
16{
17 sol->nmoves = 0;
18 sol->npremoves = 0;
19}
20
21STATIC void
22solution_moves_transform(solution_moves_t moves[static 1], uint8_t t)
23{
24 uint8_t i;
25
26 for (i = 0; i < moves->nmoves; i++)
27 moves->moves[i] = transform_move(moves->moves[i], t);
28
29 for (i = 0; i < moves->npremoves; i++)
30 moves->premoves[i] = transform_move(moves->premoves[i], t);
31}
4 32
5STATIC bool 33STATIC bool
6appendchar(size_t n, char s[n], size_t *used, char c) 34solution_list_init(solution_list_t sols[static 1], size_t n, char buf[n])
7{ 35{
8 if (n <= *used) 36 if (n == 0) {
37 LOG("Cannot use solution buffer with size 0\n");
9 return false; 38 return false;
39 }
40
41 sols->nsols = 0;
42 sols->shortest_sol = MAXLEN + 1;
43 sols->size = n;
44 sols->used = 0;
45 sols->buf = buf;
10 46
11 s[(*used)++] = c; 47 /* Ensure string buffer is NULL-terminated */
48 sols->buf[0] = '\0';
12 49
13 return true; 50 return true;
14} 51}
52
53STATIC bool
54solution_moves_equal(
55 const solution_moves_t a[static 1],
56 const solution_moves_t b[static 1]
57)
58{
59 uint8_t i;
60
61 if (a->nmoves != b->nmoves || a->npremoves != b->npremoves)
62 return false;
63
64 for (i = 0; i < a->nmoves; i++)
65 if (a->moves[i] != b->moves[i])
66 return false;
67
68 for (i = 0; i < a->npremoves; i++)
69 if (a->premoves[i] != b->premoves[i])
70 return false;
71
72 return true;
73}
74
75STATIC bool
76solution_moves_is_duplicate(size_t r, const solution_moves_t s[r])
77{
78 size_t i;
79
80 for (i = 0; i < r; i++)
81 if (solution_moves_equal(&s[i], &s[r]))
82 return true;
83
84 return false;
85}
86
87STATIC bool
88appendchar(solution_list_t solutions[static 1], char c)
89{
90 if (solutions->size <= solutions->used)
91 return false;
92
93 solutions->buf[solutions->used++] = c;
94
95 return true;
96}
97
98STATIC int64_t
99appendsolution(
100 const solution_moves_t moves[static 1],
101 const solution_settings_t settings[static 1],
102 solution_list_t list[static 1]
103)
104{
105 int64_t r, strl;
106 int i;
107 uint8_t t;
108 solution_moves_t tsol[NTRANS];
109
110 if (moves->nmoves + moves->npremoves > MAXLEN)
111 goto appendsolution_error_solution_length;
112
113 for (
114 t = 0, r = 0;
115 t < NTRANS && list->nsols < settings->maxsolutions;
116 t++
117 ) {
118 if (!(settings->tmask & TM_SINGLE(t)))
119 continue;
120
121 tsol[r] = *moves;
122 if (settings->unniss) {
123 tsol[r].nmoves += moves->npremoves;
124 tsol[r].npremoves = 0;
125 for (i = moves->npremoves-1; i >= 0; i--)
126 tsol[r].moves[tsol[r].nmoves - i - 1] =
127 inverse_move(moves->premoves[i]);
128
129 /*
130 This is a bit ugly: we have to sort now and then again
131 later, because the allowednext check would fail with
132 improperly sorted parallel moves, but then transforming
133 could swap the pairs the wrong way around.
134 TODO: maybe fix this
135 */
136 sortparallel_moves(tsol[r].nmoves, tsol[r].moves);
137
138 /* Check if unnissed premoves cancel with normal. */
139 if (!allowedmoves(tsol[r].nmoves, tsol[r].moves))
140 continue;
141 }
142 solution_moves_transform(&tsol[r], t);
143 sortparallel_moves(tsol[r].nmoves, tsol[r].moves);
144 sortparallel_moves(tsol[r].npremoves, tsol[r].premoves);
145
146 /* Skip duplicates that may appear after transforming */
147 if (solution_moves_is_duplicate(r, tsol))
148 continue;
149
150 /* Write moves on normal */
151 strl = writemoves(tsol[r].nmoves, tsol[r].moves,
152 list->size - list->used, list->buf + list->used);
153 if (strl < 0)
154 goto appendsolution_error_buffer;
155 list->used += (size_t)(strl-1);
156
157 /* Write moves on inverse with NISS notation */
158 if (tsol[r].npremoves > 0) {
159 if (!appendchar(list, ' '))
160 goto appendsolution_error_buffer;
161 if (!appendchar(list, '('))
162 goto appendsolution_error_buffer;
163
164 strl = writemoves(tsol[r].npremoves, tsol[r].premoves,
165 list->size - list->used, list->buf + list->used);
166 if (strl < 0)
167 goto appendsolution_error_buffer;
168 list->used += (size_t)(strl-1);
169
170 if (!appendchar(list, ')'))
171 goto appendsolution_error_buffer;
172 }
173
174 if (!appendchar(list, '\n'))
175 goto appendsolution_error_buffer;
176
177 ++list->nsols;
178 list->shortest_sol = MIN(
179 list->shortest_sol, tsol[r].nmoves + tsol[r].npremoves);
180 r++;
181 }
182
183 list->buf[list->used] = '\0';
184 return r;
185
186appendsolution_error_buffer:
187 LOG("Could not append solution to buffer: size too small\n");
188 list->buf[0] = '\0';
189 return NISSY_ERROR_BUFFER_SIZE;
190
191appendsolution_error_solution_length:
192 LOG("Error: solution is too long (%" PRIu8 ").\n"
193 "This is a bug, please report it.\n",
194 moves->nmoves + moves->npremoves);
195 list->buf[0] = '\0';
196 return NISSY_ERROR_UNKNOWN;
197}
198
199STATIC bool
200solutions_done(
201 const solution_list_t list[static 1],
202 const solution_settings_t settings[static 1],
203 int8_t depth
204)
205{
206 if (list->nsols >= settings->maxsolutions)
207 return true;
208
209 if (depth > settings->maxmoves)
210 return true;
211
212 if (list->nsols > 0 && settings->optimal >= 0 &&
213 depth > list->shortest_sol + settings->optimal)
214 return true;
215
216 return false;
217}

Generated with cgit - Back to sebastiano.tronto.net