nissy-core

The "engine" of nissy, including the H48 optimal solver.
git clone https://git.tronto.net/nissy-core
Download | Log | Files | Refs | README | LICENSE

nissy.h (15976B)


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