1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
|
/*
This is libnissy (temporarily also known as h48), a Rubik's cube library.
All the functions return 0 or a positive integer in case of success and
a negative integer in case of error, unless otherwise specified. See
below for the list of error codes and their meaning.
Cubes are passed as strings in the cccccccc=eeeeeeeeeeee=r format,
see the README.md file for more information.
Accepted moves are any of the following:
U, D, R, L, F, B, Uw, Dw, Rw, Lw, Fw, Bw, M, S, E, x, y, z
optionally followed by a 2, a ' or a 3.
A transformation must be given in the format
(rotation|mirrored) (2 letters)
for example 'rotation UF' or 'mirrored BL'.
*/
/* Constants *****************************************************************/
/* Some constants for size for I/O buffers */
#define NISSY_SIZE_CUBE 24U
#define NISSY_SIZE_TRANSFORMATION 12U
#define NISSY_SIZE_SOLVE_STATS 10U
#define NISSY_SIZE_DATAID 255U
/* Flags for NISS options */
#define NISSY_NISSFLAG_NORMAL 1U
#define NISSY_NISSFLAG_INVERSE 2U
#define NISSY_NISSFLAG_MIXED 4U
#define NISSY_NISSFLAG_LINEAR \
(NISSY_NISSFLAG_NORMAL | NISSY_NISSFLAG_INVERSE)
#define NISSY_NISSFLAG_ALL \
(NISSY_NISSFLAG_NORMAL | NISSY_NISSFLAG_INVERSE | NISSY_NISSFLAG_MIXED)
/* The solved cube */
#define NISSY_SOLVED_CUBE "ABCDEFGH=ABCDEFGHIJKL=A"
/* Error codes ***************************************************************/
/*
The value NISSY_OK denotes a success. If returned by solve, it means
that no solution has been found.
*/
#define NISSY_OK 0LL
/*
The value NISSY_WARNING_UNSOLVABLE is a warning. It means that the
operation was completed succesfully, but the resulting cube is in an
unsolvable state. This could be intended, for example if the user has
provided an unsolvable cube as input.
*/
#define NISSY_WARNING_UNSOLVABLE -1LL
/*
The value NISSY_ERROR_INVALID_CUBE means that the provided cube is
invalid. It could be written in an unknown format, or be ill-formed.
*/
#define NISSY_ERROR_INVALID_CUBE -10LL
/*
The value NISSY_ERROR_UNSOLVABLE_CUBE means that the provided cube is in
an unsolvable state for the given solver. This could mean either that the
cube is not solvable at all (for example in case it has a single twisted
corner), or that it is not ready for the given step (for example if the
caller wants to solve a DR finish without the cube being in DR state).
*/
#define NISSY_ERROR_UNSOLVABLE_CUBE -11LL
/*
The value NISSY_ERROR_INVALID_MOVES means that the given moves are
invalid.
*/
#define NISSY_ERROR_INVALID_MOVES -20LL
/*
The value NISSY_ERROR_INVALID_TRANS means that the given transformation
is invalid.
*/
#define NISSY_ERROR_INVALID_TRANS -30LL
/*
The value NISSY_ERROR_INVALID_SOLVER means that the given solver is
not known.
*/
#define NISSY_ERROR_INVALID_SOLVER -50LL
/*
The value NISSY_ERROR_NULL_POINTER means that one of the provided pointer
arguments is NULL. For example, it may be returned by solve when called
with a solver that requires some pre-computed data, but the provided
data is NULL.
*/
#define NISSY_ERROR_NULL_POINTER -60LL
/*
The value NISSY_ERROR_BUFFER_SIZE means that one of the buffers provided
is too small. For example, it could be too small to hold the result or
too small to hold the data generated by gendata.
*/
#define NISSY_ERROR_BUFFER_SIZE -61LL
/*
The value NISSY_ERROR_DATA means that the provided data is invalid. For
example, it may be returned by solve when called with incompatible solver
and data arguments.
*/
#define NISSY_ERROR_DATA -70LL
/*
The value NISSY_ERROR_OPTIONS means that one or more of the given options
are invalid. For example, it may be returned by solve when called with
a negative maximum number of solutions.
*/
#define NISSY_ERROR_OPTIONS -80LL
/*
The value NISSY_ERROR_UNKNOWN denotes an unexpected error. It probably
means that there some bug in this library. If you can, report any error
of this kind to sebastiano@tronto.net. Thanks!
*/
#define NISSY_ERROR_UNKNOWN -999LL
/* Library functions *********************************************************/
/*
Compute the inverse of the given cube.
Parameters:
cube - The cube to be inverted.
result - The return parameter for the resulting cube.
Return values:
NISSY_OK - The cube was inverted succesfully.
NISSY_WARNING_UNSOLVABLE - The resulting cube is not solvable. This is
either because the given cube was not solvable,
or due to an unknown internal error.
NISSY_ERROR_INVALID_CUBE - The given cube is invalid.
NISSY_ERROR_UNKNOWN - An unknown error occurred.
*/
long long
nissy_inverse(
const char cube[static NISSY_SIZE_CUBE],
char result[static NISSY_SIZE_CUBE]
);
/*
Apply the given sequence of moves on the given cube.
Parameters:
cube - The cube to move.
moves - The moves to apply to the cube. Must be a NULL-terminated string.
result - The return parameter for the resulting cube.
Return values:
NISSY_OK - The moves were applied succesfully.
NISSY_WARNING_UNSOLVABLE - The resulting cube is not solvable. This is
either because the given cube was not solvable,
or due to an unknown internal error.
NISSY_ERROR_INVALID_CUBE - The given cube is invalid.
NISSY_ERROR_INVALID_MOVES - The given moves are invalid.
NISSY_ERROR_NULL_POINTER - The 'moves' argument is NULL.
*/
long long
nissy_applymoves(
const char cube[static NISSY_SIZE_CUBE],
const char *moves,
char result[static NISSY_SIZE_CUBE]
);
/*
Apply the single given transformation to the given cube.
Parameters:
cube - The cube to be transformed.
transformation - The transformation in "(rotation|mirrored) __" format.
result - The return parameter for the resulting cube.
Return values:
NISSY_OK - The transformation was performed succesfully.
NISSY_WARNING_UNSOLVABLE - The resulting cube is not solvable. This is
probably due to an unknown internal error.
NISSY_ERROR_INVALID_CUBE - The given cube is invalid.
NISSY_ERROR_INVALID_TRANS - The given transformation is invalid.
*/
long long
nissy_applytrans(
const char cube[static NISSY_SIZE_CUBE],
const char transformation[static NISSY_SIZE_TRANSFORMATION],
char result[static NISSY_SIZE_CUBE]
);
/*
Get the cube with the given ep, eo, cp and co values. The values must be in the
ranges specified below, but if the option "fix" is given any values outside its
range will be adjusted before using it. The option "fix" also fixes parity and
orientation issues, resulting always in a solvable cube.
Parameters:
ep - The edge permutation, 0 <= ep < 479001600 (12!)
eo - The edge orientation, 0 <= eo < 2047 (2^11)
cp - The corner permutation, 0 <= cp < 40320 (8!)
co - The corner orientation, 0 <= co < 2187 (3^7)
orient - The orientation of the cube, 0 <= orient < 24
options - Other options.
result - The return parameter for the resulting cube.
Return values:
NISSY_OK - The cube was generated succesfully.
NISSY_WARNING_UNSOLVABLE - The resulting cube is unsolvable.
NISSY_ERROR_OPTIONS - One or more of the given parameters is invalid.
*/
long long
nissy_getcube(
long long ep,
long long eo,
long long cp,
long long co,
long long orient,
const char *options,
char result[static NISSY_SIZE_CUBE]
);
/*
Compute the size of the data generated by nissy_gendata when called for
the given solver, and other useful information.
Parameters:
solver - The name of the solver.
dataid - An identifier for the data computed for the solver. Different
solvers may use equivalent data. This identifier can be used
e.g. as a filename or database key to save and retrieve the
correct data for each solver, without duplication.
Return values:
NISSY_ERROR_INVALID_SOLVER - The given solver is not known.
NISSY_ERROR_NULL_POINTER - The 'solver' argument is null.
NISSY_ERROR_UNKNOWN - An unknown error occurred.
Any value >= 0 - The size of the data, in bytes.
*/
long long
nissy_solverinfo(
const char *solver,
char dataid[static NISSY_SIZE_DATAID]
);
/*
Compute the data for the given solver and store it in generated_data.
Parameters:
solver - The name of the solver.
data_size - The size of the data buffer. It is advised to use
nissy_solverinfo to check how much memory is needed.
data - The return parameter for the generated data.
This buffer must have 8-byte alignment.
Return values:
NISSY_ERROR_INVALID_SOLVER - The given solver is not known.
NISSY_ERROR_NULL_POINTER - The 'solver' argument is null.
NISSY_ERROR_UNKNOWN - An error occurred while generating the data.
NISSY_ERROR_DATA - The data buffer is invalid, for example because
it is not 8-byte aligned.
Any value >= 0 - The size of the data, in bytes.
*/
long long
nissy_gendata(
const char *solver,
unsigned long long data_size,
unsigned char data[data_size]
);
/*
Check that the data is a valid data table for a solver.
Parameters:
data_size - The size of the data buffer.
data - The data for the solver. Can be computed with gendata.
This buffer must have 8-byte alignment.
Return values:
NISSY_OK - The data is valid.
NISSY_ERROR_DATA - The data is invalid.
*/
long long
nissy_checkdata(
unsigned long long data_size,
const unsigned char data[data_size]
);
/*
Solve the given cube using the given solver and options.
Parameters:
cube - The cube to solver.
solver - The name of the solver.
nissflag - The flags for NISS (linear, inverse, mixed, or combinations).
minmoves - The minimum number of moves for a solution.
maxmoves - The maximum number of moves for a solution.
maxsols - The maximum number of solutions.
optimal - The maximum number of moves above the optimal solution length.
threads - The number of threads to use. Must be less than or equalt to
the value of the compile-time constant THREADS. If set to 0,
the default value THREADS will be used.
data_size - The size of the data buffer.
data - The data for the solver. Can be computed with gendata.
This buffer must have 8-byte alignment.
sols_size - The size of the solutions buffer.
sols - The return parameter for the solutions. The solutions are
separated by a '\n' (newline) and a '\0' (NULL character)
terminates the list.
stats - An array to store some statistics about the solve.
Return values:
NISSY_OK - Cube solved succesfully.
NISSY_ERROR_INVALID_CUBE - The given cube is invalid.
NISSY_ERROR_UNSOLVABLE_CUBE - The given cube is valid, but not solvable with
the given solver.
NISSY_ERROR_OPTIONS - One or more of the given options are invalid.
NISSY_ERROR_INVALID_SOLVER - The given solver is not known.
NISSY_ERROR_NULL_POINTER - The 'solver' argument is null.
NISSY_ERROR_DATA - The data buffer is invalid.
Any value >= 0 - The number of solutions found.
*/
long long
nissy_solve(
const char cube[static NISSY_SIZE_CUBE],
const char *solver,
unsigned nissflag,
unsigned minmoves,
unsigned maxmoves,
unsigned maxsolutions,
unsigned optimal,
unsigned threads,
unsigned long long data_size,
const unsigned char data[data_size],
unsigned sols_size,
char sols[sols_size],
long long stats[static NISSY_SIZE_SOLVE_STATS]
);
/*
Parameters:
moves - The moves to be counted.
Return values:
NISSY_ERROR_INVALID_MOVES - The given moves are invalid.
NISSY_ERROR_NULL_POINTER - The 'moves' argument is NULL.
Any value >= 0 - The number of moves.
*/
long long
nissy_countmoves(
const char *moves
);
/*
Set a global logger function used by this library. Setting the logger to NULL
disables logging.
Parameters:
logger_function - A pointer to a function that takes two parameters:
* A C string, the string to be printed.
* Any other data via a void pointer.
user_data - Any data that will be provided by the logger when
calling logger_function.
Return values:
NISSY_OK - Logger set succesfully. No warning or error is going to be given
if the logger is invalid.
*/
long long
nissy_setlogger(
void (*logger_function)(const char *, void *),
void *user_data
);
|