commit 8b72e391c7185e3da0dfbf0ab60068ac37e4d5cc
parent 510a7471348788fccba6b7c4b9f7b7cc9aee6ba9
Author: Sebastiano Tronto <sebastiano@tronto.net>
Date: Tue, 22 Apr 2025 09:00:15 +0200
Removed old scripts and updated public API
Diffstat:
24 files changed, 720 insertions(+), 880 deletions(-)
diff --git a/cpp/examples/move.cpp b/cpp/examples/move.cpp
@@ -0,0 +1,17 @@
+/* A simple example showing how to move a cube and print it in H48 format. */
+
+#include "../nissy.h"
+#include <iostream>
+
+int main() {
+ nissy::cube c;
+ if (!c.move("R' U' F").ok()) {
+ std::cout << "Error moving the cube!" << std::endl;
+ return 1;
+ }
+
+ auto str = c.to_string();
+ std::cout << "Cube after R' U' F:" << std::endl << str << std::endl;
+
+ return 0;
+}
diff --git a/cpp/examples/move_convert.cpp b/cpp/examples/move_convert.cpp
@@ -1,24 +0,0 @@
-/* A simple example showing how to move a cube and print it in H48 format. */
-
-#include "../nissy.h"
-#include <iostream>
-
-int main() {
- nissy::cube c;
- if (!c.move("R' U' F").ok()) {
- std::cout << "Error moving the cube!" << std::endl;
- return 1;
- }
-
- auto string_or_error = c.to_string("H48");
- if (std::holds_alternative<nissy::error>(string_or_error)) {
- std::cout << "Error converting cube!" << std::endl;
- return 1;
- }
-
- auto str = std::get<std::string>(string_or_error);
- std::cout << "Cube in H48 format after R' U' F:" << std::endl
- << str << std::endl;
-
- return 0;
-}
diff --git a/cpp/nissy.cpp b/cpp/nissy.cpp
@@ -13,8 +13,6 @@ extern "C" {
long long nissy_inverse(const char *, char *);
long long nissy_applymoves(const char *, const char *, char *);
long long nissy_applytrans(const char *, const char *, char *);
- long long nissy_convert(const char *, const char *, const char *,
- unsigned, char *);
long long nissy_getcube(long long, long long, long long, long long,
const char *, char *);
long long nissy_solverinfo(const char *, char *);
@@ -43,7 +41,6 @@ namespace nissy {
const error error::UNSOLVABLE_CUBE{-11};
const error error::INVALID_MOVES{-20};
const error error::INVALID_TRANS{-30};
- const error error::INVALID_FORMAT{-40};
const error error::INVALID_SOLVER{-50};
const error error::NULL_POINTER{-60};
const error error::BUFFER_SIZE{-61};
@@ -52,9 +49,7 @@ namespace nissy {
const error error::UNKNOWN{-999};
namespace size {
- constexpr size_t B32 = 22;
- constexpr size_t H48 = 88;
- constexpr size_t CUBE_MAX = H48;
+ constexpr size_t CUBE = 22;
constexpr size_t TRANSFORMATION = 12;
constexpr size_t DATAID = 255;
}
@@ -65,71 +60,54 @@ namespace nissy {
error cube::move(const std::string& moves)
{
- char result[size::B32];
+ char result[size::CUBE];
long long err = nissy_applymoves(
- m_b32.c_str(), moves.c_str(), result);
+ m_str.c_str(), moves.c_str(), result);
if (err < 0)
return error{err};
- m_b32 = result;
+ m_str = result;
return error::OK;
}
error cube::transform(const std::string& trans)
{
- char result[size::B32];
+ char result[size::CUBE];
long long err = nissy_applytrans(
- m_b32.c_str(), trans.c_str(), result);
+ m_str.c_str(), trans.c_str(), result);
if (err < 0)
return error{err};
- m_b32 = result;
+ m_str = result;
return error::OK;
}
void cube::invert()
{
- char result[size::B32];
- nissy_inverse(m_b32.c_str(), result);
- m_b32 = result;
+ char result[size::CUBE];
+ nissy_inverse(m_str.c_str(), result);
+ m_str = result;
}
void cube::compose(const cube& other)
{
- char result[size::B32];
+ char result[size::CUBE];
nissy_compose(
- m_b32.c_str(), other.to_string().c_str(), result);
- m_b32 = result;
+ m_str.c_str(), other.to_string().c_str(), result);
+ m_str = result;
}
- std::string cube::to_string() const { return m_b32; }
-
- std::variant<std::string, error>
- cube::to_string(const std::string& format) const
- {
- char result[size::CUBE_MAX];
- auto err = nissy_convert("B32", format.c_str(),
- m_b32.c_str(), size::CUBE_MAX, result);
- if (err < 0)
- return error{err};
- else
- return result;
- }
+ std::string cube::to_string() const { return m_str; }
std::variant<cube, error>
cube::from_string(const std::string& str)
{
- return from_string(str, "B32");
- }
-
- std::variant<cube, error>
- cube::from_string(const std::string& str, const std::string& format)
- {
- char result[size::B32];
- cube c;
- auto err = nissy_convert(format.c_str(),
- "B32", c.m_b32.c_str(), size::B32, result);
+ /* Check that the cube is valid by making a single move */
+ char result[size::CUBE];
+ auto err = nissy_applymoves(str.c_str(), "U", result);
if (err < 0)
return error{err};
- c.m_b32 = result;
+
+ cube c;
+ c.m_str = str;
return c;
}
@@ -143,13 +121,13 @@ namespace nissy {
cube::get(long long ep, long long eo, long long cp, long long co,
const std::string& options)
{
- char result[size::B32];
+ char result[size::CUBE];
cube c;
auto err = nissy_getcube(
ep, eo, cp, co, options.c_str(), result);
if (err < 0)
return error{err};
- c.m_b32 = result;
+ c.m_str = result;
return c;
}
diff --git a/cpp/nissy.h b/cpp/nissy.h
@@ -38,7 +38,6 @@ namespace nissy {
static const error UNSOLVABLE_CUBE;
static const error INVALID_MOVES;
static const error INVALID_TRANS;
- static const error INVALID_FORMAT;
static const error INVALID_SOLVER;
static const error NULL_POINTER;
static const error BUFFER_SIZE;
@@ -55,13 +54,9 @@ namespace nissy {
void invert();
void compose(const cube&);
std::string to_string() const;
- std::variant<std::string, error> to_string(
- const std::string& format) const;
static std::variant<cube, error> from_string(
const std::string&);
- static std::variant<cube, error> from_string(
- const std::string& str, const std::string& format);
static std::variant<cube, error> get(
long long ep, long long eo, long long cp, long long co);
static std::variant<cube, error> get(
@@ -69,7 +64,7 @@ namespace nissy {
const std::string& options);
private:
- std::string m_b32{"ABCDEFGH=ABCDEFGHIJKL"};
+ std::string m_str{"ABCDEFGH=ABCDEFGHIJKL=A"};
};
class solver {
diff --git a/python/nissy_module.c b/python/nissy_module.c
@@ -4,7 +4,6 @@
#include "../src/nissy.h"
-#define MAX_CUBE_STR_LEN 1024 /* Update when adding formats */
#define MAX_SOLUTIONS_SIZE 250000
static bool
@@ -24,7 +23,6 @@ check_error(long long err)
case NISSY_ERROR_UNSOLVABLE_CUBE: /* Fallthrough */
case NISSY_ERROR_INVALID_MOVES:
case NISSY_ERROR_INVALID_TRANS:
- case NISSY_ERROR_INVALID_FORMAT:
case NISSY_ERROR_INVALID_SOLVER:
case NISSY_ERROR_NULL_POINTER:
case NISSY_ERROR_BUFFER_SIZE:
@@ -70,17 +68,17 @@ PyDoc_STRVAR(compose_doc,
"Apply 'permutation' on 'cube'.\n"
"\n"
"Parameters:\n"
-" - cube: a cube in B32 format\n"
-" - permutation: another cube in B32 format\n"
+" - cube: a cube\n"
+" - permutation: another cube\n"
"\n"
-"Returns: the resulting cube string in B32 format\n"
+"Returns: the resulting cube string\n"
);
static PyObject *
compose(PyObject *self, PyObject *args)
{
long long err;
const char *cube, *permutation;
- char result[NISSY_SIZE_B32];
+ char result[NISSY_SIZE_CUBE];
if (!PyArg_ParseTuple(args, "ss", &cube, &permutation))
return NULL;
@@ -95,16 +93,16 @@ PyDoc_STRVAR(inverse_doc,
"Invert 'cube'.\n"
"\n"
"Parameters:\n"
-" - cube: a cube in B32 format\n"
+" - cube: a cube in\n"
"\n"
-"Returns: the inverse cube in B32 format\n"
+"Returns: the inverse cube\n"
);
static PyObject *
inverse(PyObject *self, PyObject *args)
{
long long err;
const char *cube;
- char result[NISSY_SIZE_B32];
+ char result[NISSY_SIZE_CUBE];
if (!PyArg_ParseTuple(args, "s", &cube))
return NULL;
@@ -119,17 +117,17 @@ PyDoc_STRVAR(applymoves_doc,
"Apply 'moves' to 'cube'.\n"
"\n"
"Parameters:\n"
-" - cube: a cube in B32 format\n"
+" - cube: a cube in\n"
" - moves: the moves to apply on the cube\n"
"\n"
-"Returns: the resulting cube in B32 format\n"
+"Returns: the resulting cube\n"
);
static PyObject *
applymoves(PyObject *self, PyObject *args)
{
long long err;
const char *cube, *moves;
- char result[NISSY_SIZE_B32];
+ char result[NISSY_SIZE_CUBE];
if (!PyArg_ParseTuple(args, "ss", &cube, &moves))
return NULL;
@@ -144,19 +142,19 @@ PyDoc_STRVAR(applytrans_doc,
"Apply 'transformation' to 'cube'.\n"
"\n"
"Parameters:\n"
-" - cube: a cube in B32 format\n"
+" - cube: a cube\n"
" - transformation: the transformation to apply on the cube, formatted as\n"
" (rotation|mirrored) (2 letters)\n"
" for example 'mirrored ur' or 'rotation lf'\n"
"\n"
-"Returns: the resulting cube in B32 format\n"
+"Returns: the resulting cube\n"
);
static PyObject *
applytrans(PyObject *self, PyObject *args)
{
long long err;
const char *cube, *trans;
- char result[NISSY_SIZE_B32];
+ char result[NISSY_SIZE_CUBE];
if (!PyArg_ParseTuple(args, "ss", &cube, &trans))
return NULL;
@@ -165,32 +163,6 @@ applytrans(PyObject *self, PyObject *args)
return string_result(err, result);
}
-PyDoc_STRVAR(convert_doc,
-"convert(fin, fout, cube)\n"
-"--\n\n"
-"Convert 'cube' from format 'fin' to format 'fout'.\n"
-"\n"
-"Parameters:\n"
-" - fin: the format in which 'cube' is given\n"
-" - fout: the format to which 'cube' has to be converted\n"
-" - cube: a cube in B32 format\n"
-"\n"
-"Returns: 'cube' in 'fout' format\n"
-);
-static PyObject *
-convert(PyObject *self, PyObject *args)
-{
- long long err;
- const char *fin, *fout, *cube;
- char result[MAX_CUBE_STR_LEN];
-
- if (!PyArg_ParseTuple(args, "sss", &fin, &fout, &cube))
- return NULL;
-
- err = nissy_convert(fin, fout, cube, MAX_CUBE_STR_LEN, result);
- return string_result(err, result);
-}
-
PyDoc_STRVAR(getcube_doc,
"getcube(ep, eo, cp, co, options)\n"
"--\n\n"
@@ -210,7 +182,7 @@ getcube(PyObject *self, PyObject *args)
{
long long ep, eo, cp, co, err;
const char *options;
- char result[NISSY_SIZE_B32];
+ char result[NISSY_SIZE_CUBE];
if (!PyArg_ParseTuple(args, "LLLLs", &ep, &eo, &cp, &co, &options))
return NULL;
@@ -321,7 +293,7 @@ PyDoc_STRVAR(solve_doc,
"See the documentation for libnissy (in nissy.h) for details.\n"
"\n"
"Parameters:\n"
-" - cube: a cube in B32 format\n"
+" - cube: a cube\n"
" - solver: the solver to use\n"
" - minmoves: the minimum number of moves to use\n"
" - maxmoves: the maximum number of moves to use\n"
@@ -400,7 +372,6 @@ static PyMethodDef nissy_methods[] = {
{ "inverse", inverse, METH_VARARGS, inverse_doc },
{ "applymoves", applymoves, METH_VARARGS, applymoves_doc },
{ "applytrans", applytrans, METH_VARARGS, applytrans_doc },
- { "convert", convert, METH_VARARGS, convert_doc },
{ "getcube", getcube, METH_VARARGS, getcube_doc },
{ "solverinfo", solverinfo, METH_VARARGS, solverinfo_doc },
{ "gendata", gendata, METH_VARARGS, gendata_doc },
diff --git a/shell/shell.c b/shell/shell.c
@@ -18,9 +18,6 @@
#define FLAG_PERM "-perm"
#define FLAG_COMMAND "-command"
#define FLAG_STR_CUBE "-cubestr"
-#define FLAG_FORMAT "-format"
-#define FLAG_FORMAT_IN "-fin"
-#define FLAG_FORMAT_OUT "-fout"
#define FLAG_MOVES "-moves"
#define FLAG_TRANS "-trans"
#define FLAG_SOLVER "-solver"
@@ -31,23 +28,18 @@
#define FLAG_MAXSOLUTIONS "-n"
#define FLAG_THREADS "-t"
-#define INFO_CUBEFORMAT(cube) cube " must be given in B32 format."
#define INFO_MOVESFORMAT "The accepted moves are U, D, R, L, F and B, " \
"optionally followed by a 2, a ' or a 3."
#define INFO_TRANSFORMAT "The transformation must be given in the format " \
"(rotation|mirrored) (2 letters), for exmple " \
"'rotation UF' or 'mirrored BL'."
-#define INFO_FORMATS "The available formats are H48, B32 and SRC."
typedef struct {
int command_index;
- char cube[22];
- char cube_perm[22];
+ char cube[NISSY_SIZE_CUBE];
+ char cube_perm[NISSY_SIZE_CUBE];
char *str_command;
char *str_cube;
- char *str_format;
- char *str_format_in;
- char *str_format_out;
char *str_moves;
char *str_trans;
char *str_solver;
@@ -64,7 +56,6 @@ static int64_t inverse_exec(args_t *);
static int64_t applymoves_exec(args_t *);
static int64_t applytrans_exec(args_t *);
static int64_t frommoves_exec(args_t *);
-static int64_t convert_exec(args_t *);
static int64_t randomcube_exec(args_t *);
static int64_t solverinfo_exec(args_t *);
static int64_t gendata_exec(args_t *);
@@ -81,9 +72,6 @@ static bool set_cube(int, char **, args_t *);
static bool set_cube_perm(int, char **, args_t *);
static bool set_str_command(int, char **, args_t *);
static bool set_str_cube(int, char **, args_t *);
-static bool set_str_format(int, char **, args_t *);
-static bool set_str_format_in(int, char **, args_t *);
-static bool set_str_format_out(int, char **, args_t *);
static bool set_str_moves(int, char **, args_t *);
static bool set_str_trans(int, char **, args_t *);
static bool set_str_solver(int, char **, args_t *);
@@ -107,9 +95,6 @@ struct {
OPTION(FLAG_PERM, 1, set_cube_perm),
OPTION(FLAG_COMMAND, 1, set_str_command),
OPTION(FLAG_STR_CUBE, 1, set_str_cube),
- OPTION(FLAG_FORMAT, 1, set_str_format),
- OPTION(FLAG_FORMAT_IN, 1, set_str_format_in),
- OPTION(FLAG_FORMAT_OUT, 1, set_str_format_out),
OPTION(FLAG_MOVES, 1, set_str_moves),
OPTION(FLAG_TRANS, 1, set_str_trans),
OPTION(FLAG_SOLVER, 1, set_str_solver),
@@ -133,29 +118,27 @@ struct {
COMMAND(
"compose",
"compose " FLAG_CUBE " CUBE " FLAG_PERM " PERM",
- "Apply on CUBE the permutation defined by PERM. "
- INFO_CUBEFORMAT("CUBE and PERM"),
+ "Apply on CUBE the permutation defined by PERM.",
compose_exec
),
COMMAND(
"inverse",
"inverse " FLAG_CUBE " CUBE ",
- "Compute the inverse of the given CUBE. "
- INFO_CUBEFORMAT("CUBE"),
+ "Compute the inverse of the given CUBE.",
inverse_exec
),
COMMAND(
"applymoves",
"applymoves " FLAG_CUBE " CUBE " FLAG_MOVES " MOVES",
"Apply the given MOVES to the given CUBE. "
- INFO_CUBEFORMAT("CUBE") " " INFO_MOVESFORMAT,
+ INFO_MOVESFORMAT,
applymoves_exec
),
COMMAND(
"applytrans",
"applytrans " FLAG_CUBE " CUBE " FLAG_TRANS " TRANS",
"Apply the single transformation TRANS to the given CUBE. "
- INFO_CUBEFORMAT("CUBE") " " INFO_TRANSFORMAT,
+ INFO_TRANSFORMAT,
applytrans_exec
),
COMMAND(
@@ -166,19 +149,9 @@ struct {
frommoves_exec
),
COMMAND(
- "convert",
- "convert " FLAG_STR_CUBE " CUBESTR "
- FLAG_FORMAT_IN " FORMAT_IN " FLAG_FORMAT_OUT " FORMAT_OUT",
- "Convert the cube described by CUBESTR from FORMAT_IN to "
- "FORMAT_OUT."
- INFO_FORMATS " "
- "CUBESTR must be a valid cube in the FORMAT_IN format.",
- convert_exec
- ),
- COMMAND(
"randomcube",
"randomcube",
- "Returns a random cube in B32 format.",
+ "Returns a random.",
randomcube_exec
),
COMMAND(
@@ -202,8 +175,7 @@ struct {
FLAG_CUBE " CUBE"
FLAG_THREADS " T",
"Solve the given CUBE using SOLVER, "
- "using at least n and at most N moves, and T threads. "
- INFO_CUBEFORMAT("CUBE"),
+ "using at least n and at most N moves, and T threads.",
solve_exec
),
COMMAND(
@@ -254,7 +226,7 @@ rand64(void)
static int64_t
compose_exec(args_t *args)
{
- char result[22];
+ char result[NISSY_SIZE_CUBE];
int64_t ret;
ret = nissy_compose(args->cube, args->cube_perm, result);
@@ -267,7 +239,7 @@ compose_exec(args_t *args)
static int64_t
inverse_exec(args_t *args)
{
- char result[22];
+ char result[NISSY_SIZE_CUBE];
int64_t ret;
ret = nissy_inverse(args->cube, result);
@@ -280,7 +252,7 @@ inverse_exec(args_t *args)
static int64_t
applymoves_exec(args_t *args)
{
- char result[22];
+ char result[NISSY_SIZE_CUBE];
int64_t ret;
ret = nissy_applymoves(args->cube, args->str_moves, result);
@@ -293,7 +265,7 @@ applymoves_exec(args_t *args)
static int64_t
applytrans_exec(args_t *args)
{
- char result[22];
+ char result[NISSY_SIZE_CUBE];
int64_t ret;
ret = nissy_applytrans(args->cube, args->str_trans, result);
@@ -311,20 +283,6 @@ frommoves_exec(args_t *args)
}
static int64_t
-convert_exec(args_t *args)
-{
- char result[PRINTCUBE_BUFFER_SIZE];
- int64_t ret;
-
- ret = nissy_convert(args->str_format_in, args->str_format_out,
- args->str_cube, PRINTCUBE_BUFFER_SIZE, result);
- if (ret == NISSY_OK || ret == NISSY_WARNING_UNSOLVABLE)
- printf("%s\n", result);
-
- return ret;
-}
-
-static int64_t
randomcube_exec(args_t *args)
{
char result[PRINTCUBE_BUFFER_SIZE];
@@ -575,9 +533,6 @@ parse_args(int argc, char **argv, args_t *args)
.cube = "",
.cube_perm = "",
.str_cube = "",
- .str_format = "",
- .str_format_in = "",
- .str_format_out = "",
.str_moves = "",
.str_trans = "",
.str_solver = "",
@@ -668,7 +623,7 @@ parse_nisstype(const char *arg)
static bool
set_cube(int argc, char **argv, args_t *args)
{
- memcpy(args->cube, argv[0], 22);
+ memcpy(args->cube, argv[0], NISSY_SIZE_CUBE);
args->cube[21] = 0;
return true;
@@ -677,7 +632,7 @@ set_cube(int argc, char **argv, args_t *args)
static bool
set_cube_perm(int argc, char **argv, args_t *args)
{
- memcpy(args->cube_perm, argv[0], 22);
+ memcpy(args->cube_perm, argv[0], NISSY_SIZE_CUBE);
args->cube_perm[21] = 0;
return true;
@@ -700,30 +655,6 @@ set_str_cube(int argc, char **argv, args_t *args)
}
static bool
-set_str_format(int argc, char **argv, args_t *args)
-{
- args->str_format = argv[0];
-
- return true;
-}
-
-static bool
-set_str_format_in(int argc, char **argv, args_t *args)
-{
- args->str_format_in = argv[0];
-
- return true;
-}
-
-static bool
-set_str_format_out(int argc, char **argv, args_t *args)
-{
- args->str_format_out = argv[0];
-
- return true;
-}
-
-static bool
set_str_moves(int argc, char **argv, args_t *args)
{
args->str_moves = argv[0];
diff --git a/src/core/core.h b/src/core/core.h
@@ -1,5 +1,4 @@
#include "constant_cubes.h"
#include "cube.h"
-#include "io_formats.h"
#include "moves.h"
#include "transform.h"
diff --git a/src/core/cube.h b/src/core/cube.h
@@ -174,3 +174,193 @@ getcube(int64_t ep, int64_t eo, int64_t cp, int64_t co)
return cubefromarray(carr, earr);
}
+
+
+/******************************************************************************/
+
+STATIC cube_t readcube(const char *, const char *);
+STATIC int64_t writecube(const char *, cube_t, size_t n, char [n]);
+STATIC uint8_t readco(const char *);
+STATIC uint8_t readcp(const char *);
+STATIC uint8_t readeo(const char *);
+STATIC uint8_t readep(const char *);
+
+STATIC cube_t readcube_B32(const char *);
+STATIC int64_t writecube_B32(cube_t, size_t n, char [n]);
+
+STATIC uint8_t b32toedge(char);
+STATIC uint8_t b32tocorner(char);
+STATIC char edgetob32(uint8_t);
+STATIC char cornertob32(uint8_t);
+
+STATIC cube_t
+readcube(const char *format, const char *buf)
+{
+ return readcube_B32(buf);
+}
+
+STATIC int64_t
+writecube(const char *format, cube_t cube, size_t buf_size, char buf[buf_size])
+{
+ return writecube_B32(cube, buf_size, buf);
+}
+
+STATIC uint8_t
+readco(const char *str)
+{
+ if (*str == '0')
+ return 0;
+ if (*str == '1')
+ return CTWIST_CW;
+ if (*str == '2')
+ return CTWIST_CCW;
+
+ LOG("Error reading CO\n");
+ return UINT8_ERROR;
+}
+
+STATIC uint8_t
+readcp(const char *str)
+{
+ uint8_t c;
+
+ for (c = 0; c < 8; c++)
+ if (!strncmp(str, cornerstr[c], 3) ||
+ !strncmp(str, cornerstralt[c], 3))
+ return c;
+
+ LOG("Error reading CP\n");
+ return UINT8_ERROR;
+}
+
+STATIC uint8_t
+readeo(const char *str)
+{
+ if (*str == '0')
+ return 0;
+ if (*str == '1')
+ return EFLIP;
+
+ LOG("Error reading EO\n");
+ return UINT8_ERROR;
+}
+
+STATIC uint8_t
+readep(const char *str)
+{
+ uint8_t e;
+
+ for (e = 0; e < 12; e++)
+ if (!strncmp(str, edgestr[e], 2))
+ return e;
+
+ LOG("Error reading EP\n");
+ return UINT8_ERROR;
+}
+
+STATIC cube_t
+readcube_B32(const char *buf)
+{
+ int i;
+ uint8_t c[8], e[12];
+
+ for (i = 0; i < 8; i++) {
+ c[i] = b32tocorner(buf[i]);
+ if (c[i] == UINT8_ERROR) {
+ LOG("Error reading B32 corner %d ", i);
+ if (buf[i] == 0) {
+ LOG("(string terminated early)\n");
+ } else {
+ LOG("(char '%c')\n", buf[i]);
+ }
+ return ZERO_CUBE;
+ }
+ }
+
+ if (buf[8] != '=') {
+ LOG("Error reading B32 separator: a single '=' "
+ "must be used to separate edges and corners\n");
+ return ZERO_CUBE;
+ }
+
+ for (i = 0; i < 12; i++) {
+ e[i] = b32toedge(buf[i+9]);
+ if (e[i] == UINT8_ERROR) {
+ LOG("Error reading B32 edge %d ", i);
+ if (buf[i+9] == 0) {
+ LOG("(string terminated early)\n");
+ } else {
+ LOG("(char '%c')\n", buf[i+9]);
+ }
+ return ZERO_CUBE;
+ }
+ }
+
+ return cubefromarray(c, e);
+}
+
+STATIC int64_t
+writecube_B32(cube_t cube, size_t buf_size, char buf[buf_size])
+{
+ int i;
+ uint8_t corner[8], edge[12];
+
+ if (buf_size < NISSY_SIZE_CUBE) {
+ LOG("Cannot write cube: buffer size must be at least %u "
+ "bytes, but the provided one is %zu bytes.\n",
+ NISSY_SIZE_CUBE, buf_size);
+ return NISSY_ERROR_BUFFER_SIZE;
+ }
+
+ pieces(&cube, corner, edge);
+
+ for (i = 0; i < 8; i++)
+ buf[i] = cornertob32(corner[i]);
+
+ buf[8] = '=';
+
+ for (i = 0; i < 12; i++)
+ buf[i+9] = edgetob32(edge[i]);
+
+ buf[21] = '\0';
+
+ return NISSY_OK;
+}
+
+STATIC uint8_t
+b32toedge(char c)
+{
+ if (!((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'f')))
+ return UINT8_ERROR;
+
+ return c <= 'Z' ? (uint8_t)(c - 'A') : (uint8_t)(c - 'a') + 26;
+}
+
+STATIC uint8_t
+b32tocorner(char c) {
+ uint8_t val;
+
+ if (!((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'f')))
+ return UINT8_ERROR;
+
+ val = c <= 'Z' ? (uint8_t)(c - 'A') : (uint8_t)(c - 'a') + 26;
+
+ return (val & 7) | ((val & 24) << 2);
+}
+
+STATIC char
+edgetob32(uint8_t edge)
+{
+ return edge < 26 ? 'A' + (char)edge : 'a' + (char)(edge - 26);
+}
+
+STATIC char
+cornertob32(uint8_t corner)
+{
+ uint8_t val;
+
+ val = (corner & 7) | ((corner & 96) >> 2);
+
+ return val < 26 ? 'A' + (char)val : 'a' + (char)(val - 26);
+}
+/******************************************************************************/
diff --git a/src/core/io_formats.h b/src/core/io_formats.h
@@ -1,403 +0,0 @@
-STATIC cube_t readcube(const char *, const char *);
-STATIC int64_t writecube(const char *, cube_t, size_t n, char [n]);
-STATIC void log_available_formats(void);
-STATIC uint8_t readco(const char *);
-STATIC uint8_t readcp(const char *);
-STATIC uint8_t readeo(const char *);
-STATIC uint8_t readep(const char *);
-STATIC cube_t readcube_B32(const char *);
-STATIC cube_t readcube_H48(const char *);
-STATIC uint8_t readpiece_LST(const char **);
-STATIC cube_t readcube_LST(const char *);
-
-STATIC int64_t writepiece_LST(uint8_t, size_t n, char [n]);
-STATIC int64_t writecube_B32(cube_t, size_t n, char [n]);
-STATIC int64_t writecube_H48(cube_t, size_t n, char [n]);
-STATIC int64_t writecube_LST(cube_t, size_t n, char [n]);
-
-STATIC uint8_t b32toedge(char);
-STATIC uint8_t b32tocorner(char);
-STATIC char edgetob32(uint8_t);
-STATIC char cornertob32(uint8_t);
-
-STATIC struct {
- const char *name;
- cube_t (*read)(const char *);
- int64_t (*write)(cube_t, size_t n, char [n]);
-} ioformat[] =
-{
- { .name = "B32", .read = readcube_B32, .write = writecube_B32 },
- { .name = "LST", .read = readcube_LST, .write = writecube_LST },
- { .name = "H48", .read = readcube_H48, .write = writecube_H48 },
- { .name = "NONE", .read = NULL, .write = NULL },
-};
-
-STATIC cube_t
-readcube(const char *format, const char *buf)
-{
- int i;
-
- for (i = 0; ioformat[i].read != NULL; i++)
- if (!strcmp(format, ioformat[i].name))
- return ioformat[i].read(buf);
-
- LOG("Cannot read cube: unknown format '%s'\n", format);
- log_available_formats();
- return ZERO_CUBE;
-}
-
-STATIC int64_t
-writecube(const char *format, cube_t cube, size_t buf_size, char buf[buf_size])
-{
- int i;
-
- for (i = 0; ioformat[i].write != NULL; i++)
- if (!strcmp(format, ioformat[i].name))
- return ioformat[i].write(cube, buf_size, buf);
-
- LOG("Cannot write cube: unknown format '%s'\n", format);
- log_available_formats();
- return NISSY_ERROR_INVALID_FORMAT;
-}
-
-STATIC void
-log_available_formats(void)
-{
- int i;
-
- LOG("Available formats: ");
- for (i = 0; ioformat[i].read != NULL; i++)
- LOG("'%s' ", ioformat[i].name);
- LOG("\n");
-}
-
-STATIC uint8_t
-readco(const char *str)
-{
- if (*str == '0')
- return 0;
- if (*str == '1')
- return CTWIST_CW;
- if (*str == '2')
- return CTWIST_CCW;
-
- LOG("Error reading CO\n");
- return UINT8_ERROR;
-}
-
-STATIC uint8_t
-readcp(const char *str)
-{
- uint8_t c;
-
- for (c = 0; c < 8; c++)
- if (!strncmp(str, cornerstr[c], 3) ||
- !strncmp(str, cornerstralt[c], 3))
- return c;
-
- LOG("Error reading CP\n");
- return UINT8_ERROR;
-}
-
-STATIC uint8_t
-readeo(const char *str)
-{
- if (*str == '0')
- return 0;
- if (*str == '1')
- return EFLIP;
-
- LOG("Error reading EO\n");
- return UINT8_ERROR;
-}
-
-STATIC uint8_t
-readep(const char *str)
-{
- uint8_t e;
-
- for (e = 0; e < 12; e++)
- if (!strncmp(str, edgestr[e], 2))
- return e;
-
- LOG("Error reading EP\n");
- return UINT8_ERROR;
-}
-
-STATIC cube_t
-readcube_B32(const char *buf)
-{
- int i;
- uint8_t c[8], e[12];
-
- for (i = 0; i < 8; i++) {
- c[i] = b32tocorner(buf[i]);
- if (c[i] == UINT8_ERROR) {
- LOG("Error reading B32 corner %d ", i);
- if (buf[i] == 0) {
- LOG("(string terminated early)\n");
- } else {
- LOG("(char '%c')\n", buf[i]);
- }
- return ZERO_CUBE;
- }
- }
-
- if (buf[8] != '=') {
- LOG("Error reading B32 separator: a single '=' "
- "must be used to separate edges and corners\n");
- return ZERO_CUBE;
- }
-
- for (i = 0; i < 12; i++) {
- e[i] = b32toedge(buf[i+9]);
- if (e[i] == UINT8_ERROR) {
- LOG("Error reading B32 edge %d ", i);
- if (buf[i+9] == 0) {
- LOG("(string terminated early)\n");
- } else {
- LOG("(char '%c')\n", buf[i+9]);
- }
- return ZERO_CUBE;
- }
- }
-
- return cubefromarray(c, e);
-}
-
-STATIC cube_t
-readcube_H48(const char *buf)
-{
- int i;
- uint8_t piece, orient, c[8], e[12];
- const char *b;
-
- b = buf;
-
- for (i = 0; i < 12; i++) {
- while (*b == ' ' || *b == '\t' || *b == '\n')
- b++;
- if ((piece = readep(b)) == UINT8_ERROR)
- return ZERO_CUBE;
- b += 2;
- if ((orient = readeo(b)) == UINT8_ERROR)
- return ZERO_CUBE;
- b++;
- e[i] = piece | orient;
- }
- for (i = 0; i < 8; i++) {
- while (*b == ' ' || *b == '\t' || *b == '\n')
- b++;
- if ((piece = readcp(b)) == UINT8_ERROR)
- return ZERO_CUBE;
- b += 3;
- if ((orient = readco(b)) == UINT8_ERROR)
- return ZERO_CUBE;
- b++;
- c[i] = piece | orient;
- }
-
- return cubefromarray(c, e);
-}
-
-STATIC uint8_t
-readpiece_LST(const char **b)
-{
- uint8_t ret;
- bool read;
-
- while (**b == ',' || **b == ' ' || **b == '\t' || **b == '\n')
- (*b)++;
-
- for (ret = 0, read = false; **b >= '0' && **b <= '9'; (*b)++) {
- read = true;
- ret = ret * 10 + (**b) - '0';
- }
-
- return read ? ret : UINT8_ERROR;
-}
-
-STATIC cube_t
-readcube_LST(const char *buf)
-{
- int i;
- uint8_t c[8], e[12];
-
- for (i = 0; i < 8; i++)
- c[i] = readpiece_LST(&buf);
-
- for (i = 0; i < 12; i++)
- e[i] = readpiece_LST(&buf);
-
- return cubefromarray(c, e);
-}
-
-STATIC int64_t
-writepiece_LST(uint8_t piece, size_t buf_size, char buf[buf_size])
-{
- char digits[3];
- size_t i, len;
-
- if (piece > 99 || buf_size < 3)
- return 0;
-
- len = 0;
- while (piece != 0) {
- digits[len++] = (piece % 10) + '0';
- piece /= 10;
- }
-
- if (buf_size < len+2)
- return 0;
-
- if (len == 0)
- digits[len++] = '0';
-
- for (i = 0; i < len; i++)
- buf[i] = digits[len-i-1];
-
- buf[len] = ',';
- buf[len+1] = ' ';
-
- return len+2;
-}
-
-STATIC int64_t
-writecube_B32(cube_t cube, size_t buf_size, char buf[buf_size])
-{
- int i;
- uint8_t corner[8], edge[12];
-
- if (buf_size < NISSY_SIZE_B32) {
- LOG("Cannot write cube in B32 format: buffer size must be at "
- "least %u bytes, but the provided one is %zu bytes.\n",
- NISSY_SIZE_B32, buf_size);
- return NISSY_ERROR_BUFFER_SIZE;
- }
-
- pieces(&cube, corner, edge);
-
- for (i = 0; i < 8; i++)
- buf[i] = cornertob32(corner[i]);
-
- buf[8] = '=';
-
- for (i = 0; i < 12; i++)
- buf[i+9] = edgetob32(edge[i]);
-
- buf[21] = '\0';
-
- return NISSY_OK;
-}
-
-STATIC int64_t
-writecube_H48(cube_t cube, size_t buf_size, char buf[buf_size])
-{
- uint8_t piece, perm, orient, corner[8], edge[12];
- int i;
-
- if (buf_size < NISSY_SIZE_H48) {
- LOG("Cannot write cube in H48 format: buffer size must be "
- "at least %u bytes, but the provided one is %zu bytes.\n",
- NISSY_SIZE_H48, buf_size);
- return NISSY_ERROR_BUFFER_SIZE;
- }
-
- pieces(&cube, corner, edge);
-
- for (i = 0; i < 12; i++) {
- piece = edge[i];
- perm = piece & PBITS;
- orient = (piece & EOBIT) >> EOSHIFT;
- buf[4*i ] = edgestr[perm][0];
- buf[4*i + 1] = edgestr[perm][1];
- buf[4*i + 2] = orient + '0';
- buf[4*i + 3] = ' ';
- }
- for (i = 0; i < 8; i++) {
- piece = corner[i];
- perm = piece & PBITS;
- orient = (piece & COBITS) >> COSHIFT;
- buf[48 + 5*i ] = cornerstr[perm][0];
- buf[48 + 5*i + 1] = cornerstr[perm][1];
- buf[48 + 5*i + 2] = cornerstr[perm][2];
- buf[48 + 5*i + 3] = orient + '0';
- buf[48 + 5*i + 4] = ' ';
- }
-
- buf[48+39] = '\0';
-
- return NISSY_OK;
-}
-
-STATIC int64_t
-writecube_LST(cube_t cube, size_t buf_size, char buf[buf_size])
-{
- int i;
- uint64_t ptr;
- uint8_t piece, corner[8], edge[12];
-
- ptr = 0;
- pieces(&cube, corner, edge);
-
- for (i = 0; i < 8; i++) {
- piece = corner[i];
- ptr += writepiece_LST(piece, buf_size - ptr, buf + ptr);
- if (ptr == 0)
- goto writecube_LST_error;
- }
-
- for (i = 0; i < 12; i++) {
- piece = edge[i];
- ptr += writepiece_LST(piece, buf_size - ptr, buf + ptr);
- if (ptr == 0)
- goto writecube_LST_error;
- }
-
- *(buf+ptr-2) = '\0';
-
- return NISSY_OK;
-
-writecube_LST_error:
- LOG("Cannot write cube in LST: buffer is too small (%" PRIu64
- " bytes given). The LST format has a variable size, try a "
- "larger buffer.\n", buf_size);
- return NISSY_ERROR_BUFFER_SIZE;
-}
-
-STATIC uint8_t
-b32toedge(char c)
-{
- if (!((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'f')))
- return UINT8_ERROR;
-
- return c <= 'Z' ? (uint8_t)(c - 'A') : (uint8_t)(c - 'a') + 26;
-}
-
-STATIC uint8_t
-b32tocorner(char c) {
- uint8_t val;
-
- if (!((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'f')))
- return UINT8_ERROR;
-
- val = c <= 'Z' ? (uint8_t)(c - 'A') : (uint8_t)(c - 'a') + 26;
-
- return (val & 7) | ((val & 24) << 2);
-}
-
-STATIC char
-edgetob32(uint8_t edge)
-{
- return edge < 26 ? 'A' + (char)edge : 'a' + (char)(edge - 26);
-}
-
-STATIC char
-cornertob32(uint8_t corner)
-{
- uint8_t val;
-
- val = (corner & 7) | ((corner & 96) >> 2);
-
- return val < 26 ? 'A' + (char)val : 'a' + (char)(val - 26);
-}
diff --git a/src/nissy.c b/src/nissy.c
@@ -17,7 +17,7 @@ long long parse_h48_solver(
STATIC bool checkdata(const unsigned char *, const tableinfo_t [static 1]);
STATIC bool distribution_equal(const uint64_t [static INFO_DISTRIBUTION_LEN],
const uint64_t [static INFO_DISTRIBUTION_LEN], uint8_t);
-STATIC long long write_result(cube_t, char [static NISSY_SIZE_B32]);
+STATIC long long write_result(cube_t, char [static NISSY_SIZE_CUBE]);
STATIC size_t my_strnlen(const char *, size_t);
STATIC long long nissy_dataid(const char *, char [static NISSY_SIZE_DATAID]);
STATIC long long nissy_gendata_unsafe(
@@ -117,9 +117,9 @@ distribution_equal(
}
STATIC long long
-write_result(cube_t cube, char result[static NISSY_SIZE_B32])
+write_result(cube_t cube, char result[static NISSY_SIZE_CUBE])
{
- writecube("B32", cube, NISSY_SIZE_B32, result);
+ writecube("B32", cube, NISSY_SIZE_CUBE, result);
if (!issolvable(cube)) {
LOG("Warning: resulting cube is not solvable\n");
@@ -143,9 +143,9 @@ my_strnlen(const char *str, size_t maxlen)
long long
nissy_compose(
- const char cube[static NISSY_SIZE_B32],
- const char permutation[static NISSY_SIZE_B32],
- char result[static NISSY_SIZE_B32]
+ const char cube[static NISSY_SIZE_CUBE],
+ const char permutation[static NISSY_SIZE_CUBE],
+ char result[static NISSY_SIZE_CUBE]
)
{
cube_t c, p, res;
@@ -178,14 +178,14 @@ nissy_compose(
return write_result(res, result);
nissy_compose_error:
- writecube("B32", ZERO_CUBE, NISSY_SIZE_B32, result);
+ writecube("B32", ZERO_CUBE, NISSY_SIZE_CUBE, result);
return err;
}
long long
nissy_inverse(
- const char cube[static NISSY_SIZE_B32],
- char result[static NISSY_SIZE_B32]
+ const char cube[static NISSY_SIZE_CUBE],
+ char result[static NISSY_SIZE_CUBE]
)
{
cube_t c, res;
@@ -210,15 +210,15 @@ nissy_inverse(
return write_result(res, result);
nissy_inverse_error:
- writecube("B32", ZERO_CUBE, NISSY_SIZE_B32, result);
+ writecube("B32", ZERO_CUBE, NISSY_SIZE_CUBE, result);
return err;
}
long long
nissy_applymoves(
- const char cube[static NISSY_SIZE_B32],
+ const char cube[static NISSY_SIZE_CUBE],
const char *moves,
- char result[static NISSY_SIZE_B32]
+ char result[static NISSY_SIZE_CUBE]
)
{
cube_t c, res;
@@ -249,15 +249,15 @@ nissy_applymoves(
return write_result(res, result);
nissy_applymoves_error:
- writecube("B32", ZERO_CUBE, NISSY_SIZE_B32, result);
+ writecube("B32", ZERO_CUBE, NISSY_SIZE_CUBE, result);
return err;
}
long long
nissy_applytrans(
- const char cube[static NISSY_SIZE_B32],
+ const char cube[static NISSY_SIZE_CUBE],
const char transformation[static NISSY_SIZE_TRANSFORMATION],
- char result[static NISSY_SIZE_B32]
+ char result[static NISSY_SIZE_CUBE]
)
{
cube_t c, res;
@@ -282,51 +282,7 @@ nissy_applytrans(
return write_result(res, result);
nissy_applytrans_error:
- writecube("B32", ZERO_CUBE, NISSY_SIZE_B32, result);
- return err;
-}
-
-long long
-nissy_convert(
- const char *format_in,
- const char *format_out,
- const char *cube_string,
- unsigned result_size,
- char result[result_size]
-)
-{
- cube_t c;
- long long err;
-
- if (format_in == NULL) {
- LOG("[convert] Error: 'format_in' argument is NULL\n");
- err = NISSY_ERROR_NULL_POINTER;
- goto nissy_convert_error;
- }
-
- if (format_out == NULL) {
- LOG("[convert] Error: 'format_out' argument is NULL\n");
- err = NISSY_ERROR_NULL_POINTER;
- goto nissy_convert_error;
- }
-
- if (cube_string == NULL) {
- LOG("[convert] Error: 'cube_string' argument is NULL\n");
- err = NISSY_ERROR_NULL_POINTER;
- goto nissy_convert_error;
- }
-
- c = readcube(format_in, cube_string);
-
- if (!isconsistent(c)) {
- err = NISSY_ERROR_INVALID_CUBE;
- goto nissy_convert_error;
- }
-
- return writecube(format_out, c, result_size, result);
-
-nissy_convert_error:
- result[0] = '\0';
+ writecube("B32", ZERO_CUBE, NISSY_SIZE_CUBE, result);
return err;
}
@@ -337,7 +293,7 @@ nissy_getcube(
long long cp,
long long co,
const char *options,
- char result[static NISSY_SIZE_B32]
+ char result[static NISSY_SIZE_CUBE]
)
{
int i;
@@ -526,7 +482,7 @@ nissy_checkdata(
long long
nissy_solve(
- const char cube[static NISSY_SIZE_B32],
+ const char cube[static NISSY_SIZE_CUBE],
const char *solver,
unsigned nissflag,
unsigned minmoves,
diff --git a/src/nissy.h b/src/nissy.h
@@ -5,12 +5,11 @@ 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 at
the bottom of this file for the list of error codes and their meaning.
-All cube arguments are in B32 formats, unless otherwise specified.
-Other available formats are H48 and SRC. See README.md for more info on
-these formats.
+TODO: explain cube format
Accepted moves are U, D, R, L, F and B, optionally followed by a 2,
a ' or a 3.
+TODO update when we accept also wide moves, slices and rotations
A transformation must be given in the format
(rotation|mirrored) (2 letters)
@@ -21,9 +20,7 @@ for example 'rotation UF' or 'mirrored BL'.
/* Constants *****************************************************************/
/* Some constants for size for I/O buffers */
-#define NISSY_SIZE_B32 22U
-#define NISSY_SIZE_H48 88U
-#define NISSY_SIZE_CUBE_MAX NISSY_SIZE_H48
+#define NISSY_SIZE_CUBE 24U
#define NISSY_SIZE_TRANSFORMATION 12U
#define NISSY_SIZE_SOLVE_STATS 10U
#define NISSY_SIZE_DATAID 255U
@@ -37,8 +34,8 @@ for example 'rotation UF' or 'mirrored BL'.
#define NISSY_NISSFLAG_ALL \
(NISSY_NISSFLAG_NORMAL | NISSY_NISSFLAG_INVERSE | NISSY_NISSFLAG_MIXED)
-/* The solved cube in B32 format */
-#define NISSY_SOLVED_CUBE "ABCDEFGH=ABCDEFGHIJKL"
+/* The solved cube */
+#define NISSY_SOLVED_CUBE "ABCDEFGH=ABCDEFGHIJKL=A"
/* Error codes ***************************************************************/
@@ -58,8 +55,7 @@ provided an unsolvable cube as input.
/*
The value NISSY_ERROR_INVALID_CUBE means that the provided cube is
-invalid. It could be written in an unknown format, or in a format
-different from what specified, or simply ill-formed.
+invalid. It could be written in an unknown format, or be ill-formed.
*/
#define NISSY_ERROR_INVALID_CUBE -10LL
@@ -85,12 +81,6 @@ is invalid.
#define NISSY_ERROR_INVALID_TRANS -30LL
/*
-The value NISSY_ERROR_INVALID_FORMAT means that the given format is
-not known.
-*/
-#define NISSY_ERROR_INVALID_FORMAT -40LL
-
-/*
The value NISSY_ERROR_INVALID_SOLVER means that the given solver is
not known.
*/
@@ -139,10 +129,10 @@ of this kind to sebastiano@tronto.net. Thanks!
Apply the secod argument as a permutation on the first argument.
Parameters:
- cube - The first cube, in B32 format.
- permutation - The second cube, in B32 format. This cube is treated as a
- permutation and "applied" to the first cube.
- result - The return parameter for the resulting cube, in B32 format.
+ cube - The first cube.
+ permutation - The second cub. This cube is treated as a permutation and
+ "applied" to the first cube.
+ result - The return parameter for the resulting cube.
Return values:
NISSY_OK - The cubes were composed succesfully.
@@ -155,17 +145,17 @@ Return values:
*/
long long
nissy_compose(
- const char cube[static NISSY_SIZE_B32],
- const char permutation[static NISSY_SIZE_B32],
- char result[static NISSY_SIZE_B32]
+ const char cube[static NISSY_SIZE_CUBE],
+ const char permutation[static NISSY_SIZE_CUBE],
+ char result[static NISSY_SIZE_CUBE]
);
/*
Compute the inverse of the given cube.
Parameters:
- cube - The cube to be inverted, in B32 format.
- result - The return parameter for the resulting cube, in B32 format.
+ cube - The cube to be inverted.
+ result - The return parameter for the resulting cube.
Return values:
NISSY_OK - The cube was inverted succesfully.
@@ -177,17 +167,17 @@ Return values:
*/
long long
nissy_inverse(
- const char cube[static NISSY_SIZE_B32],
- char result[static NISSY_SIZE_B32]
+ 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, in B32 format.
+ 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, in B32 format.
+ result - The return parameter for the resulting cube.
Return values:
NISSY_OK - The moves were applied succesfully.
@@ -200,18 +190,18 @@ Return values:
*/
long long
nissy_applymoves(
- const char cube[static NISSY_SIZE_B32],
+ const char cube[static NISSY_SIZE_CUBE],
const char *moves,
- char result[static NISSY_SIZE_B32]
+ char result[static NISSY_SIZE_CUBE]
);
/*
Apply the single given transformation to the given cube.
Parameters:
- cube - The cube to be transformed, in B32 format.
- transformation - The transformation in (rotation|mirrored) xy format.
- result - The return parameter for the resulting cube, in B32 format.
+ 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.
@@ -222,37 +212,9 @@ Return values:
*/
long long
nissy_applytrans(
- const char cube[static NISSY_SIZE_B32],
+ const char cube[static NISSY_SIZE_CUBE],
const char transformation[static NISSY_SIZE_TRANSFORMATION],
- char result[static NISSY_SIZE_B32]
-);
-
-/*
-Convert the given cube between the two given formats.
-
-Parameters:
- format_in - The input format.
- format_out - The output format.
- cube_string - The cube, in format_in format.
- result_size - The allocated size of the result array.
- result - Return parameter for the cube in format_out format.
-
-Return values:
- NISSY_OK - The conversion was performed succesfully.
- NISSY_ERROR_BUFFER_SIZE - The given buffer is too small for the result.
- NISSY_ERROR_INVALID_CUBE - The given cube is invalid.
- NISSY_ERROR_INVALID_FORMAT - At least one of the given formats is invalid.
- NISSY_ERROR_UNKNOWN - An unknown error occurred.
- NISSY_ERROR_NULL_POINTER - At least one of 'format_in', 'format_out' or
- 'cube_string' arguments is NULL.
-*/
-long long
-nissy_convert(
- const char *format_in,
- const char *format_out,
- const char *cube_string,
- unsigned result_size,
- char result[result_size]
+ char result[static NISSY_SIZE_CUBE]
);
/*
@@ -267,7 +229,7 @@ Parameters:
cp - The corner permutation, 0 <= cp <= 40320 (8!)
co - The corner orientation, 0 <= co <= 2187 (3^7)
options - Other options.
- result - The return parameter for the resulting cube, in B32 format.
+ result - The return parameter for the resulting cube.
Return values:
NISSY_OK - The cube was generated succesfully.
@@ -281,7 +243,7 @@ nissy_getcube(
long long cp,
long long co,
const char *options,
- char result[static NISSY_SIZE_B32]
+ char result[static NISSY_SIZE_CUBE]
);
/*
@@ -354,7 +316,7 @@ nissy_checkdata(
Solve the given cube using the given solver and options.
Parameters:
- cube - The cube to solver, in B32 format.
+ 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.
@@ -386,7 +348,7 @@ Return values:
*/
long long
nissy_solve(
- const char cube[static NISSY_SIZE_B32],
+ const char cube[static NISSY_SIZE_CUBE],
const char *solver,
unsigned nissflag,
unsigned minmoves,
diff --git a/tools/300_solve_small/solve_small.c b/tools/300_solve_small/solve_small.c
@@ -25,7 +25,7 @@ void run(void) {
int i;
int64_t n;
long long stats[NISSY_SIZE_SOLVE_STATS];
- char sol[SOL_BUFFER_LEN], cube[22];
+ char sol[SOL_BUFFER_LEN], cube[NISSY_SIZE_CUBE];
printf("Solved the following scrambles:\n\n");
for (i = 0; scrambles[i] != NULL; i++) {
diff --git a/tools/301_solve_file/solve_file.c b/tools/301_solve_file/solve_file.c
@@ -12,7 +12,7 @@ char scrambles[MAX_SCR][MAX_SCR_LEN];
void run(void) {
int64_t i, nsols;
long long stats[NISSY_SIZE_SOLVE_STATS];
- char sol[SOL_BUFFER_LEN], cube[22];
+ char sol[SOL_BUFFER_LEN], cube[NISSY_SIZE_CUBE];
printf("Solved the following scrambles:\n\n");
for (i = 0; i < N; i++) {
diff --git a/tools/302_solve_multisol/solve_multisol.c b/tools/302_solve_multisol/solve_multisol.c
@@ -18,7 +18,7 @@ void run(void) {
int i;
int64_t n;
long long stats[NISSY_SIZE_SOLVE_STATS];
- char sol[SOL_BUFFER_LEN], cube[22];
+ char sol[SOL_BUFFER_LEN], cube[NISSY_SIZE_CUBE];
printf("Solved the following scrambles:\n\n");
for (i = 0; scrambles[i] != NULL; i++) {
diff --git a/tools/400_solvetest/solve_test.c b/tools/400_solvetest/solve_test.c
@@ -45,7 +45,7 @@ void run(void) {
int i;
int64_t n;
long long stats[NISSY_SIZE_SOLVE_STATS];
- char sol[SOL_BUFFER_LEN], cube[22];
+ char sol[SOL_BUFFER_LEN], cube[NISSY_SIZE_CUBE];
for (i = 0; s[i].scramble[0]; i++) {
printf("\n%d. %s\n", i, s[i].scramble);
diff --git a/utils/convert.c b/utils/convert.c
@@ -0,0 +1,409 @@
+/*
+This file contains code related to cube format conversion that used to
+be in src/core. It is to be adapted into a standalone tool for cube
+format conversion.
+*/
+
+STATIC cube_t readcube(const char *, const char *);
+STATIC int64_t writecube(const char *, cube_t, size_t n, char [n]);
+STATIC void log_available_formats(void);
+STATIC uint8_t readco(const char *);
+STATIC uint8_t readcp(const char *);
+STATIC uint8_t readeo(const char *);
+STATIC uint8_t readep(const char *);
+STATIC cube_t readcube_B32(const char *);
+STATIC cube_t readcube_H48(const char *);
+STATIC uint8_t readpiece_LST(const char **);
+STATIC cube_t readcube_LST(const char *);
+
+STATIC int64_t writepiece_LST(uint8_t, size_t n, char [n]);
+STATIC int64_t writecube_B32(cube_t, size_t n, char [n]);
+STATIC int64_t writecube_H48(cube_t, size_t n, char [n]);
+STATIC int64_t writecube_LST(cube_t, size_t n, char [n]);
+
+STATIC uint8_t b32toedge(char);
+STATIC uint8_t b32tocorner(char);
+STATIC char edgetob32(uint8_t);
+STATIC char cornertob32(uint8_t);
+
+STATIC struct {
+ const char *name;
+ cube_t (*read)(const char *);
+ int64_t (*write)(cube_t, size_t n, char [n]);
+} ioformat[] =
+{
+ { .name = "B32", .read = readcube_B32, .write = writecube_B32 },
+ { .name = "LST", .read = readcube_LST, .write = writecube_LST },
+ { .name = "H48", .read = readcube_H48, .write = writecube_H48 },
+ { .name = "NONE", .read = NULL, .write = NULL },
+};
+
+STATIC cube_t
+readcube(const char *format, const char *buf)
+{
+ int i;
+
+ for (i = 0; ioformat[i].read != NULL; i++)
+ if (!strcmp(format, ioformat[i].name))
+ return ioformat[i].read(buf);
+
+ LOG("Cannot read cube: unknown format '%s'\n", format);
+ log_available_formats();
+ return ZERO_CUBE;
+}
+
+STATIC int64_t
+writecube(const char *format, cube_t cube, size_t buf_size, char buf[buf_size])
+{
+ int i;
+
+ for (i = 0; ioformat[i].write != NULL; i++)
+ if (!strcmp(format, ioformat[i].name))
+ return ioformat[i].write(cube, buf_size, buf);
+
+ LOG("Cannot write cube: unknown format '%s'\n", format);
+ log_available_formats();
+ return NISSY_ERROR_INVALID_FORMAT;
+}
+
+STATIC void
+log_available_formats(void)
+{
+ int i;
+
+ LOG("Available formats: ");
+ for (i = 0; ioformat[i].read != NULL; i++)
+ LOG("'%s' ", ioformat[i].name);
+ LOG("\n");
+}
+
+STATIC uint8_t
+readco(const char *str)
+{
+ if (*str == '0')
+ return 0;
+ if (*str == '1')
+ return CTWIST_CW;
+ if (*str == '2')
+ return CTWIST_CCW;
+
+ LOG("Error reading CO\n");
+ return UINT8_ERROR;
+}
+
+STATIC uint8_t
+readcp(const char *str)
+{
+ uint8_t c;
+
+ for (c = 0; c < 8; c++)
+ if (!strncmp(str, cornerstr[c], 3) ||
+ !strncmp(str, cornerstralt[c], 3))
+ return c;
+
+ LOG("Error reading CP\n");
+ return UINT8_ERROR;
+}
+
+STATIC uint8_t
+readeo(const char *str)
+{
+ if (*str == '0')
+ return 0;
+ if (*str == '1')
+ return EFLIP;
+
+ LOG("Error reading EO\n");
+ return UINT8_ERROR;
+}
+
+STATIC uint8_t
+readep(const char *str)
+{
+ uint8_t e;
+
+ for (e = 0; e < 12; e++)
+ if (!strncmp(str, edgestr[e], 2))
+ return e;
+
+ LOG("Error reading EP\n");
+ return UINT8_ERROR;
+}
+
+STATIC cube_t
+readcube_B32(const char *buf)
+{
+ int i;
+ uint8_t c[8], e[12];
+
+ for (i = 0; i < 8; i++) {
+ c[i] = b32tocorner(buf[i]);
+ if (c[i] == UINT8_ERROR) {
+ LOG("Error reading B32 corner %d ", i);
+ if (buf[i] == 0) {
+ LOG("(string terminated early)\n");
+ } else {
+ LOG("(char '%c')\n", buf[i]);
+ }
+ return ZERO_CUBE;
+ }
+ }
+
+ if (buf[8] != '=') {
+ LOG("Error reading B32 separator: a single '=' "
+ "must be used to separate edges and corners\n");
+ return ZERO_CUBE;
+ }
+
+ for (i = 0; i < 12; i++) {
+ e[i] = b32toedge(buf[i+9]);
+ if (e[i] == UINT8_ERROR) {
+ LOG("Error reading B32 edge %d ", i);
+ if (buf[i+9] == 0) {
+ LOG("(string terminated early)\n");
+ } else {
+ LOG("(char '%c')\n", buf[i+9]);
+ }
+ return ZERO_CUBE;
+ }
+ }
+
+ return cubefromarray(c, e);
+}
+
+STATIC cube_t
+readcube_H48(const char *buf)
+{
+ int i;
+ uint8_t piece, orient, c[8], e[12];
+ const char *b;
+
+ b = buf;
+
+ for (i = 0; i < 12; i++) {
+ while (*b == ' ' || *b == '\t' || *b == '\n')
+ b++;
+ if ((piece = readep(b)) == UINT8_ERROR)
+ return ZERO_CUBE;
+ b += 2;
+ if ((orient = readeo(b)) == UINT8_ERROR)
+ return ZERO_CUBE;
+ b++;
+ e[i] = piece | orient;
+ }
+ for (i = 0; i < 8; i++) {
+ while (*b == ' ' || *b == '\t' || *b == '\n')
+ b++;
+ if ((piece = readcp(b)) == UINT8_ERROR)
+ return ZERO_CUBE;
+ b += 3;
+ if ((orient = readco(b)) == UINT8_ERROR)
+ return ZERO_CUBE;
+ b++;
+ c[i] = piece | orient;
+ }
+
+ return cubefromarray(c, e);
+}
+
+STATIC uint8_t
+readpiece_LST(const char **b)
+{
+ uint8_t ret;
+ bool read;
+
+ while (**b == ',' || **b == ' ' || **b == '\t' || **b == '\n')
+ (*b)++;
+
+ for (ret = 0, read = false; **b >= '0' && **b <= '9'; (*b)++) {
+ read = true;
+ ret = ret * 10 + (**b) - '0';
+ }
+
+ return read ? ret : UINT8_ERROR;
+}
+
+STATIC cube_t
+readcube_LST(const char *buf)
+{
+ int i;
+ uint8_t c[8], e[12];
+
+ for (i = 0; i < 8; i++)
+ c[i] = readpiece_LST(&buf);
+
+ for (i = 0; i < 12; i++)
+ e[i] = readpiece_LST(&buf);
+
+ return cubefromarray(c, e);
+}
+
+STATIC int64_t
+writepiece_LST(uint8_t piece, size_t buf_size, char buf[buf_size])
+{
+ char digits[3];
+ size_t i, len;
+
+ if (piece > 99 || buf_size < 3)
+ return 0;
+
+ len = 0;
+ while (piece != 0) {
+ digits[len++] = (piece % 10) + '0';
+ piece /= 10;
+ }
+
+ if (buf_size < len+2)
+ return 0;
+
+ if (len == 0)
+ digits[len++] = '0';
+
+ for (i = 0; i < len; i++)
+ buf[i] = digits[len-i-1];
+
+ buf[len] = ',';
+ buf[len+1] = ' ';
+
+ return len+2;
+}
+
+STATIC int64_t
+writecube_B32(cube_t cube, size_t buf_size, char buf[buf_size])
+{
+ int i;
+ uint8_t corner[8], edge[12];
+
+ if (buf_size < NISSY_SIZE_B32) {
+ LOG("Cannot write cube in B32 format: buffer size must be at "
+ "least %u bytes, but the provided one is %zu bytes.\n",
+ NISSY_SIZE_B32, buf_size);
+ return NISSY_ERROR_BUFFER_SIZE;
+ }
+
+ pieces(&cube, corner, edge);
+
+ for (i = 0; i < 8; i++)
+ buf[i] = cornertob32(corner[i]);
+
+ buf[8] = '=';
+
+ for (i = 0; i < 12; i++)
+ buf[i+9] = edgetob32(edge[i]);
+
+ buf[21] = '\0';
+
+ return NISSY_OK;
+}
+
+STATIC int64_t
+writecube_H48(cube_t cube, size_t buf_size, char buf[buf_size])
+{
+ uint8_t piece, perm, orient, corner[8], edge[12];
+ int i;
+
+ if (buf_size < NISSY_SIZE_H48) {
+ LOG("Cannot write cube in H48 format: buffer size must be "
+ "at least %u bytes, but the provided one is %zu bytes.\n",
+ NISSY_SIZE_H48, buf_size);
+ return NISSY_ERROR_BUFFER_SIZE;
+ }
+
+ pieces(&cube, corner, edge);
+
+ for (i = 0; i < 12; i++) {
+ piece = edge[i];
+ perm = piece & PBITS;
+ orient = (piece & EOBIT) >> EOSHIFT;
+ buf[4*i ] = edgestr[perm][0];
+ buf[4*i + 1] = edgestr[perm][1];
+ buf[4*i + 2] = orient + '0';
+ buf[4*i + 3] = ' ';
+ }
+ for (i = 0; i < 8; i++) {
+ piece = corner[i];
+ perm = piece & PBITS;
+ orient = (piece & COBITS) >> COSHIFT;
+ buf[48 + 5*i ] = cornerstr[perm][0];
+ buf[48 + 5*i + 1] = cornerstr[perm][1];
+ buf[48 + 5*i + 2] = cornerstr[perm][2];
+ buf[48 + 5*i + 3] = orient + '0';
+ buf[48 + 5*i + 4] = ' ';
+ }
+
+ buf[48+39] = '\0';
+
+ return NISSY_OK;
+}
+
+STATIC int64_t
+writecube_LST(cube_t cube, size_t buf_size, char buf[buf_size])
+{
+ int i;
+ uint64_t ptr;
+ uint8_t piece, corner[8], edge[12];
+
+ ptr = 0;
+ pieces(&cube, corner, edge);
+
+ for (i = 0; i < 8; i++) {
+ piece = corner[i];
+ ptr += writepiece_LST(piece, buf_size - ptr, buf + ptr);
+ if (ptr == 0)
+ goto writecube_LST_error;
+ }
+
+ for (i = 0; i < 12; i++) {
+ piece = edge[i];
+ ptr += writepiece_LST(piece, buf_size - ptr, buf + ptr);
+ if (ptr == 0)
+ goto writecube_LST_error;
+ }
+
+ *(buf+ptr-2) = '\0';
+
+ return NISSY_OK;
+
+writecube_LST_error:
+ LOG("Cannot write cube in LST: buffer is too small (%" PRIu64
+ " bytes given). The LST format has a variable size, try a "
+ "larger buffer.\n", buf_size);
+ return NISSY_ERROR_BUFFER_SIZE;
+}
+
+STATIC uint8_t
+b32toedge(char c)
+{
+ if (!((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'f')))
+ return UINT8_ERROR;
+
+ return c <= 'Z' ? (uint8_t)(c - 'A') : (uint8_t)(c - 'a') + 26;
+}
+
+STATIC uint8_t
+b32tocorner(char c) {
+ uint8_t val;
+
+ if (!((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'f')))
+ return UINT8_ERROR;
+
+ val = c <= 'Z' ? (uint8_t)(c - 'A') : (uint8_t)(c - 'a') + 26;
+
+ return (val & 7) | ((val & 24) << 2);
+}
+
+STATIC char
+edgetob32(uint8_t edge)
+{
+ return edge < 26 ? 'A' + (char)edge : 'a' + (char)(edge - 26);
+}
+
+STATIC char
+cornertob32(uint8_t corner)
+{
+ uint8_t val;
+
+ val = (corner & 7) | ((corner & 96) >> 2);
+
+ return val < 26 ? 'A' + (char)val : 'a' + (char)(val - 26);
+}
diff --git a/utils/genmovecode.sh b/utils/genmovecode.sh
@@ -1,15 +0,0 @@
-#!/bin/sh
-
-cc -DDEBUG h48_to_lst.c ../src/nissy.c -o h48_to_lst
-
-gen() {
- for f in cubes/move_??_*.txt; do
- move="$(echo "$f" | sed 's/.*_// ; s/\.txt//')"
- printf '#define _move_cube_%s fastcube( \\\n ' "$move"
- ./h48_to_lst <"$f"
- printf ')\n'
- done
-}
-
-gen
-rm -f h48_to_lst invert
diff --git a/utils/genmoveswitch.sh b/utils/genmoveswitch.sh
@@ -1,8 +0,0 @@
-#!/bin/sh
-
-printf '\tswitch (m) {\n'
-for f in cubes/move_??_*.txt; do
- t="$(echo "$f" | sed 's/.*_// ; s/\.txt//')"
- printf '\tcase %s:\n\t\treturn _move(%s, c);\n' "$t" "$t"
-done
-printf '\t}\n'
diff --git a/utils/gentranscode.sh b/utils/gentranscode.sh
@@ -1,25 +0,0 @@
-#!/bin/sh
-
-cc -DDEBUG h48_to_lst.c ../src/nissy.c -o h48_to_lst
-cc -DDEBUG invert.c ../src/nissy.c -o invert
-
-lineavx() { printf '#define _trans_cube_%s ' "$1"; }
-linesrc() { printf '_static cube_fast_t _trans_cube_%s = ' "$1"; }
-sedavx() { sed '1,2s/$/ \\/ ; 3s/$/)/ ; 3q'; }
-sedsrc() { sed '3s/$/ };/ ; 3q'; }
-
-gen() {
- for f in cubes/transform_??_???.txt; do
- trans="$(echo "$f" | sed 's/.*_// ; s/\.txt//')"
- printf '#define _trans_cube_%s fastcube( \\\n ' "$trans"
- ./h48_to_lst <"$f"
- printf ')\n'
- printf '#define _trans_cube_%s_inverse fastcube( \\\n ' \
- "$trans"
- ./invert <"$f" | ./h48_to_lst
- printf ')\n'
- done
-}
-
-gen
-rm -f h48_to_lst invert
diff --git a/utils/gentransswitch.sh b/utils/gentransswitch.sh
@@ -1,14 +0,0 @@
-#!/bin/sh
-
-printf '\tswitch (t) {\n'
-for f in cubes/transform_??_???.txt; do
- t="$(echo "$f" | sed 's/.*_// ; s/\.txt//')"
- mirror_or_rotation="$(echo "$t" | grep m)"
- if [ -z "$mirror_or_rotation" ]; then
- m="rotation"
- else
- m="mirrored"
- fi
- printf '\tcase %s:\n\t\treturn _trans_%s(%s, c);\n' "$t" "$m" "$t"
-done
-printf '\t}\n'
diff --git a/utils/gentranstests.sh b/utils/gentranstests.sh
@@ -1,35 +0,0 @@
-#!/bin/sh
-
-outdir="./generated_trans_tests"
-
-mkdir -p "$outdir"
-i=100
-
-while read -r line; do
- [ -z "$line" ] && continue
-
- trans_piece="$(echo "$line" | awk '{print $1}' | tr -d 'rm')"
- move1="$(echo "$line" | awk '{print $2}')"
- move2="$(echo "$line" | awk '{print $3}')"
-
- rotation="rotation $trans_piece"
-
- file1="$(ls cubes | grep "move_.*_${move1}.txt")"
- file2="$(ls cubes | grep "move_.*_${move2}.txt")"
- echo "$rotation" >"$outdir/${i}_${trans_piece}r_${move1}.in"
- cat "cubes/$file1" >>"$outdir/${i}_${trans_piece}r_${move1}.in"
- cp "cubes/$file2" "$outdir/${i}_${trans_piece}r_${move1}.out"
-
- i=$((i+1))
-
- mirrored="mirrored $trans_piece"
- move2m="$(echo "${move2}" | tr 'LR' 'RL')3"
-
- file1="$(ls cubes | grep "move_.*_${move1}.txt")"
- file2="$(ls cubes | grep "move_.*_${move2m}.txt")"
- echo "$mirrored" >"$outdir/${i}_${trans_piece}m_${move1}.in"
- cat "cubes/$file1" >>"$outdir/${i}_${trans_piece}m_${move1}.in"
- cp "cubes/$file2" "$outdir/${i}_${trans_piece}m_${move1}.out"
-
- i=$((i+1))
-done <transform_moves.txt
diff --git a/utils/h48_to_lst.c b/utils/h48_to_lst.c
@@ -1,22 +0,0 @@
-#include <stdio.h>
-#include <inttypes.h>
-#include <stdbool.h>
-
-#include "../src/nissy.h"
-
-#define STRLENMAX 1000
-
-int main(void) {
- char strin[STRLENMAX], strout[STRLENMAX];
- int result;
-
- fgets(strin, STRLENMAX, stdin);
-
- result = nissy_convertcube("H48", "LST", strin, strout);
- if (result)
- fprintf(stderr, "Error converting cube: code %d\n", result);
-
- fputs(strout, stdout);
-
- return 0;
-}
diff --git a/utils/invert.c b/utils/invert.c
@@ -1,19 +0,0 @@
-#include <stdio.h>
-#include <inttypes.h>
-#include <stdbool.h>
-
-#include "../src/nissy.h"
-
-#define STRLENMAX 1000
-
-int main(void) {
- char str[STRLENMAX], cube[22], inv[22];
-
- fgets(str, STRLENMAX, stdin);
- nissy_readcube("H48", str, cube);
- nissy_inverse(cube, inv);
- nissy_writecube("H48", inv, str);
- fputs(str, stdout);
-
- return 0;
-}
diff --git a/utils/mirror.sh b/utils/mirror.sh
@@ -1,3 +0,0 @@
-#!/bin/sh
-
-tr 'LR' 'RL'