diff options
| author | Sebastiano Tronto <sebastiano@tronto.net> | 2025-08-07 15:09:46 +0200 |
|---|---|---|
| committer | Sebastiano Tronto <sebastiano@tronto.net> | 2025-08-07 15:28:01 +0200 |
| commit | 5355de2921126e2b75e24abd57e17556e22a6ed0 (patch) | |
| tree | 0df679e152ffb2798248982ac58ff123c6859114 /python | |
| parent | 57a7520545134ab95f7bb0397dcbe991c906a3e9 (diff) | |
| download | nissy-core-5355de2921126e2b75e24abd57e17556e22a6ed0.tar.gz nissy-core-5355de2921126e2b75e24abd57e17556e22a6ed0.zip | |
Added API function for solution variations
Diffstat (limited to 'python')
| -rw-r--r-- | python/examples/variations.py | 12 | ||||
| -rw-r--r-- | python/nissy_module.c | 74 |
2 files changed, 67 insertions, 19 deletions
diff --git a/python/examples/variations.py b/python/examples/variations.py new file mode 100644 index 0000000..1b85d32 --- /dev/null +++ b/python/examples/variations.py | |||
| @@ -0,0 +1,12 @@ | |||
| 1 | # Small example of nissy_python_module usage | ||
| 2 | # See the solve.py example for more details on how this works | ||
| 3 | |||
| 4 | from sys import path | ||
| 5 | path.append("./") | ||
| 6 | import nissy_python_module as nissy | ||
| 7 | |||
| 8 | moves = "R U' Bw2 M D' x' F B(E2 F D B' Lw2 U2 U' S2 B)" | ||
| 9 | |||
| 10 | print("Changing the last quarter turns of {} gives:".format(moves)) | ||
| 11 | for s in nissy.variations(moves, "lastqt"): | ||
| 12 | print(s) | ||
diff --git a/python/nissy_module.c b/python/nissy_module.c index a86b23f..88109d3 100644 --- a/python/nissy_module.c +++ b/python/nissy_module.c | |||
| @@ -44,6 +44,29 @@ string_result(long long err, const char *result) | |||
| 44 | } | 44 | } |
| 45 | 45 | ||
| 46 | static PyObject * | 46 | static PyObject * |
| 47 | stringlist_result(long long err, char *result) | ||
| 48 | { | ||
| 49 | int i, j, k; | ||
| 50 | PyObject *list, *item; | ||
| 51 | |||
| 52 | if(!check_error(err)) { | ||
| 53 | return NULL; | ||
| 54 | } else { | ||
| 55 | list = PyList_New(err); | ||
| 56 | for (i = 0, j = 0, k = 0; result[i] != 0; i++) { | ||
| 57 | if (result[i] != '\n') | ||
| 58 | continue; | ||
| 59 | result[i] = 0; | ||
| 60 | item = PyUnicode_FromString(&result[k]); | ||
| 61 | PyList_SetItem(list, j, item); | ||
| 62 | j++; | ||
| 63 | k = i+1; | ||
| 64 | } | ||
| 65 | return list; | ||
| 66 | } | ||
| 67 | } | ||
| 68 | |||
| 69 | static PyObject * | ||
| 47 | string_result_free(long long err, char *result) | 70 | string_result_free(long long err, char *result) |
| 48 | { | 71 | { |
| 49 | PyObject *ret; | 72 | PyObject *ret; |
| @@ -287,12 +310,11 @@ solve(PyObject *self, PyObject *args) | |||
| 287 | { | 310 | { |
| 288 | long long result; | 311 | long long result; |
| 289 | unsigned nissflag, minmoves, maxmoves, maxsolutions; | 312 | unsigned nissflag, minmoves, maxmoves, maxsolutions; |
| 290 | int optimal, i, j, k, threads; | 313 | int optimal, threads; |
| 291 | const char *cube, *solver; | 314 | const char *cube, *solver; |
| 292 | char solutions[MAX_SOLUTIONS_SIZE]; | 315 | char solutions[MAX_SOLUTIONS_SIZE]; |
| 293 | long long stats[NISSY_SIZE_SOLVE_STATS]; | 316 | long long stats[NISSY_SIZE_SOLVE_STATS]; |
| 294 | PyByteArrayObject *data; | 317 | PyByteArrayObject *data; |
| 295 | PyObject *list, *item; | ||
| 296 | 318 | ||
| 297 | if (!PyArg_ParseTuple(args, "ssIIIIIIY", &cube, &solver, &nissflag, | 319 | if (!PyArg_ParseTuple(args, "ssIIIIIIY", &cube, &solver, &nissflag, |
| 298 | &minmoves, &maxmoves, &maxsolutions, &optimal, &threads, &data)) | 320 | &minmoves, &maxmoves, &maxsolutions, &optimal, &threads, &data)) |
| @@ -305,21 +327,7 @@ solve(PyObject *self, PyObject *args) | |||
| 305 | stats, NULL, NULL); | 327 | stats, NULL, NULL); |
| 306 | Py_END_ALLOW_THREADS | 328 | Py_END_ALLOW_THREADS |
| 307 | 329 | ||
| 308 | if(!check_error(result)) { | 330 | return stringlist_result(result, solutions); |
| 309 | return NULL; | ||
| 310 | } else { | ||
| 311 | list = PyList_New(result); | ||
| 312 | for (i = 0, j = 0, k = 0; solutions[i] != 0; i++) { | ||
| 313 | if (solutions[i] != '\n') | ||
| 314 | continue; | ||
| 315 | solutions[i] = 0; | ||
| 316 | item = PyUnicode_FromString(&solutions[k]); | ||
| 317 | PyList_SetItem(list, j, item); | ||
| 318 | j++; | ||
| 319 | k = i+1; | ||
| 320 | } | ||
| 321 | return list; | ||
| 322 | } | ||
| 323 | } | 331 | } |
| 324 | 332 | ||
| 325 | PyDoc_STRVAR(countmoves_doc, | 333 | PyDoc_STRVAR(countmoves_doc, |
| @@ -368,8 +376,9 @@ comparemoves(PyObject *self, PyObject *args) | |||
| 368 | if (!PyArg_ParseTuple(args, "ss", &m1, &m2)) | 376 | if (!PyArg_ParseTuple(args, "ss", &m1, &m2)) |
| 369 | return NULL; | 377 | return NULL; |
| 370 | 378 | ||
| 371 | if ((cmp = nissy_comparemoves(m1, m2)) < 0) | 379 | cmp = nissy_comparemoves(m1, m2); |
| 372 | return long_result(cmp); | 380 | if (!check_error(cmp)) |
| 381 | return NULL; | ||
| 373 | 382 | ||
| 374 | switch (cmp) { | 383 | switch (cmp) { |
| 375 | case NISSY_COMPARE_MOVES_EQUAL: | 384 | case NISSY_COMPARE_MOVES_EQUAL: |
| @@ -381,6 +390,32 @@ comparemoves(PyObject *self, PyObject *args) | |||
| 381 | } | 390 | } |
| 382 | } | 391 | } |
| 383 | 392 | ||
| 393 | PyDoc_STRVAR(variations_doc, | ||
| 394 | "variations(moves, variation)\n" | ||
| 395 | "--\n\n" | ||
| 396 | "Find variations of a given move sequence\n" | ||
| 397 | "\n" | ||
| 398 | "Parameters:\n" | ||
| 399 | " - moves: the moves\n" | ||
| 400 | " - variation: the variation to apply, such as 'unniss' or 'lastqt'\n" | ||
| 401 | "\n" | ||
| 402 | "Returns: a list of move sequences, the variation of the given moves.\n" | ||
| 403 | ); | ||
| 404 | PyObject * | ||
| 405 | variations(PyObject *self, PyObject *args) | ||
| 406 | { | ||
| 407 | long long err; | ||
| 408 | const char *m, *v; | ||
| 409 | char result[MAX_SOLUTIONS_SIZE]; | ||
| 410 | |||
| 411 | if (!PyArg_ParseTuple(args, "ss", &m, &v)) | ||
| 412 | return NULL; | ||
| 413 | |||
| 414 | err = nissy_variations(m, v, MAX_SOLUTIONS_SIZE, result); | ||
| 415 | |||
| 416 | return stringlist_result(err, result); | ||
| 417 | } | ||
| 418 | |||
| 384 | static PyMethodDef nissy_methods[] = { | 419 | static PyMethodDef nissy_methods[] = { |
| 385 | { "inverse", inverse, METH_VARARGS, inverse_doc }, | 420 | { "inverse", inverse, METH_VARARGS, inverse_doc }, |
| 386 | { "applymoves", applymoves, METH_VARARGS, applymoves_doc }, | 421 | { "applymoves", applymoves, METH_VARARGS, applymoves_doc }, |
| @@ -392,6 +427,7 @@ static PyMethodDef nissy_methods[] = { | |||
| 392 | { "solve", solve, METH_VARARGS, solve_doc }, | 427 | { "solve", solve, METH_VARARGS, solve_doc }, |
| 393 | { "countmoves", countmoves, METH_VARARGS, countmoves_doc }, | 428 | { "countmoves", countmoves, METH_VARARGS, countmoves_doc }, |
| 394 | { "comparemoves", comparemoves, METH_VARARGS, comparemoves_doc }, | 429 | { "comparemoves", comparemoves, METH_VARARGS, comparemoves_doc }, |
| 430 | { "variations", variations, METH_VARARGS, variations_doc }, | ||
| 395 | { NULL, NULL, 0, NULL } | 431 | { NULL, NULL, 0, NULL } |
| 396 | }; | 432 | }; |
| 397 | 433 | ||
