h48

A prototype for an optimal Rubik's cube solver, work in progress.
git clone https://git.tronto.net/h48
Download | Log | Files | Refs | README | LICENSE

nissy.h (13440B)


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