diff --git a/.gitignore b/.gitignore index ba74660..7972ad0 100644 --- a/.gitignore +++ b/.gitignore @@ -1,9 +1,13 @@ +kociemba/ckociemba/bin/* +kociemba/ckociemba/cache/* + # Byte-compiled / optimized / DLL files __pycache__/ *.py[cod] # C extensions *.so +*.o # Distribution / packaging .Python diff --git a/Makefile b/Makefile deleted file mode 100644 index 17eb640..0000000 --- a/Makefile +++ /dev/null @@ -1,7 +0,0 @@ -CKOCIEMBA_SRC = ckociemba/coordcube.c ckociemba/cubiecube.c ckociemba/facecube.c ckociemba/search.c -CKOCIEMBA_INCLUDE = ckociemba/include -CFLAGS = -std=c99 - -solve: solve.c $(CKOCIEMBA_SRC) - gcc $(CFLAGS) $(CKOCIEMBA_SRC) -I$(CKOCIEMBA_INCLUDE) solve.c -o solve - diff --git a/kociemba/__init__.py b/kociemba/__init__.py index e69de29..107fa90 100644 --- a/kociemba/__init__.py +++ b/kociemba/__init__.py @@ -0,0 +1,40 @@ +import warnings + + +class SlowContextWarning(Warning): + pass + +try: + import os + from ckociembawrapper import ffi, lib + cache_dir = os.path.join(os.path.dirname(__file__), 'cprunetables') + + def _solve(s): + res = lib.solve(s.encode('utf-8'), cache_dir.encode('utf-8')) + if res != ffi.NULL: + return ffi.string(res).strip() + else: + raise ValueError('Error. Probably cubestring is invalid') +except ImportError: + warnings.warn("Native version of the package is not available. " + "We have to fallback to pure-Python implementation of " + "the algorithm, which is usually many times slower. " + "If performance is important to you, check official " + "project page for a native implementation: " + "https://github.com/muodov/kociemba", + SlowContextWarning) + import pykociemba.search + _solve = lambda s: pykociemba.search.Search().solution(s, 24, 1000, False).strip() + + +def solve(cubestring): + """ + Solve a Rubik's cube using two-phase algorithm. + + >>> solve("BBURUDBFUFFFRRFUUFLULUFUDLRRDBBDBDBLUDDFLLRRBRLLLBRDDF") + "B U' L' D' R' D' L2 D' L F' L' D F2 R2 U R2 B2 U2 L2 F2 D'" + """ + + return _solve(cubestring) + +__all__ = ['solve'] diff --git a/kociemba/build_ckociemba.py b/kociemba/build_ckociemba.py new file mode 100644 index 0000000..535db62 --- /dev/null +++ b/kociemba/build_ckociemba.py @@ -0,0 +1,34 @@ +import cffi + +ffi = cffi.FFI() +ffi.set_source( + "kociemba.ckociembawrapper", + """ + #include + #include + #include + + char* solve(char *cubestring, char *cache_dir) + { + char *sol = solution( + cubestring, + 24, + 1000, + 0, + cache_dir + ); + return sol; + } + """, + include_dirs=['kociemba/ckociemba/include'], + sources=[ + 'kociemba/ckociemba/coordcube.c', + 'kociemba/ckociemba/cubiecube.c', + 'kociemba/ckociemba/facecube.c', + 'kociemba/ckociemba/search.c'], + extra_compile_args=['-std=c99']) + +ffi.cdef("char* solve(char *cubestring, char *cache_dir);") + +if __name__ == "__main__": + ffi.compile(verbose=True) diff --git a/kociemba/ckociemba/Makefile b/kociemba/ckociemba/Makefile new file mode 100644 index 0000000..afecee8 --- /dev/null +++ b/kociemba/ckociemba/Makefile @@ -0,0 +1,10 @@ +CKOCIEMBA_SRC = coordcube.c cubiecube.c facecube.c search.c +CKOCIEMBA_INCLUDE = include +CFLAGS = -std=c99 +BINDIR = bin +BIN = kociemba + +solve: solve.c $(CKOCIEMBA_SRC) + mkdir -p $(BINDIR) + gcc $(CFLAGS) $(CKOCIEMBA_SRC) -I$(CKOCIEMBA_INCLUDE) solve.c -o $(BINDIR)/$(BIN) + diff --git a/ckociemba/coordcube.c b/kociemba/ckociemba/coordcube.c similarity index 82% rename from ckociemba/coordcube.c rename to kociemba/ckociemba/coordcube.c index 9d9e4d6..610669b 100644 --- a/ckociemba/coordcube.c +++ b/kociemba/ckociemba/coordcube.c @@ -15,11 +15,11 @@ short parityMove[2][18] = { { 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0 } }; short FRtoBR_Move[N_FRtoBR][N_MOVE]; -short URFtoDLF_Move[N_URFtoDLF][N_MOVE] = {0}; -short URtoDF_Move[N_URtoDF][N_MOVE] = {0}; -short URtoUL_Move[N_URtoUL][N_MOVE] = {0}; -short UBtoDF_Move[N_UBtoDF][N_MOVE] = {0}; -short MergeURtoULandUBtoDF[336][336] = {0}; +short URFtoDLF_Move[N_URFtoDLF][N_MOVE] = {{0}}; +short URtoDF_Move[N_URtoDF][N_MOVE] = {{0}}; +short URtoUL_Move[N_URtoUL][N_MOVE] = {{0}}; +short UBtoDF_Move[N_UBtoDF][N_MOVE] = {{0}}; +short MergeURtoULandUBtoDF[336][336] = {{0}}; char Slice_URFtoDLF_Parity_Prun[N_SLICE2 * N_URFtoDLF * N_PARITY / 2] = {0}; char Slice_URtoDF_Parity_Prun[N_SLICE2 * N_URtoDF * N_PARITY / 2] = {0}; char Slice_Twist_Prun[N_SLICE1 * N_TWIST / 2 + 1] = {0}; @@ -27,10 +27,10 @@ char Slice_Flip_Prun[N_SLICE1 * N_FLIP / 2] = {0}; int PRUNING_INITED = 0; -void move(coordcube_t* coordcube, int m) +void move(coordcube_t* coordcube, int m, const char *cache_dir) { if (PRUNING_INITED == 0) { - initPruning(); + initPruning(cache_dir); } coordcube->twist = twistMove[coordcube->twist][m]; coordcube->flip = flipMove[coordcube->flip][m]; @@ -44,42 +44,63 @@ void move(coordcube_t* coordcube, int m) coordcube->URtoDF = MergeURtoULandUBtoDF[coordcube->URtoUL][coordcube->UBtoDF]; } -int check_cached_table(const char* name, void* ptr, int len) +char * join_path(const char *dir, const char *filename) { - char fname[100] = "prunetables/"; - strncat(fname, name, 30); + int path_len = strnlen(dir, 200); + if (path_len == 200) { + return NULL; + } + char *fpath = calloc(path_len + 32, 1); + strcpy(fpath, dir); + strcat(fpath, "/"); + strncat(fpath, filename, 30); + return fpath; +} + +int check_cached_table(const char* name, void* ptr, int len, const char *cache_dir) +{ + char *fname = join_path(cache_dir, name); + if (fname == NULL) { + fprintf(stderr, "Path to cache tables is too long\n"); + return -1; + } + int res = 0; if (access(fname, F_OK | R_OK) != -1) { - fprintf(stderr, "Found cache for %s. Loading...", name); - read_from_file(ptr, len, name); - fprintf(stderr, "done.\n"); - return 0; + // fprintf(stderr, "Found cache for %s. Loading...", name); + read_from_file(ptr, len, fname); + // fprintf(stderr, "done.\n"); + res = 0; } else { - fprintf(stderr, "Cache for %s was not found. Recalculating.\n", name); - return -1; + fprintf(stderr, "Cache table %s was not found. Recalculating.\n", fname); + res = 1; } + free(fname); + return res; } void read_from_file(void* ptr, int len, const char* name) { - char fname[100] = "prunetables/"; - strncat(fname, name, 30); - FILE* f = fopen(fname, "r"); + FILE* f = fopen(name, "r"); fread(ptr, len, 1, f); fclose(f); } -void dump_to_file(void* ptr, int len, const char* name) +void dump_to_file(void* ptr, int len, const char* name, const char *cache_dir) { int status; - status = mkdir("prunetables", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH); + status = mkdir(cache_dir, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH); if (status == 0 || errno == EEXIST) { - char fname[100] = "prunetables/"; - strncat(fname, name, 30); - FILE* f = fopen(fname, "w"); - fwrite(ptr, len, 1, f); - fclose(f); + char *fname = join_path(cache_dir, name); + if (fname == NULL) { + fprintf(stderr, "Path to cache tables is too long\n"); + } else { + FILE* f = fopen(fname, "w"); + fwrite(ptr, len, 1, f); + free(fname); + fclose(f); + } } else { - fprintf(stderr, "cannot create prunetables/ directory\n"); + fprintf(stderr, "cannot create cache tables directory\n"); } } @@ -99,11 +120,12 @@ coordcube_t* get_coordcube(cubiecube_t* cubiecube) return result; } -void initPruning() +void initPruning(const char *cache_dir) { cubiecube_t* a; + cubiecube_t* moveCube = get_moveCube(); - if(check_cached_table("twistMove", (void*) twistMove, sizeof(twistMove)) != 0) { + if(check_cached_table("twistMove", (void*) twistMove, sizeof(twistMove), cache_dir) != 0) { a = get_cubiecube(); for (short i = 0; i < N_TWIST; i++) { setTwist(a, i); @@ -116,10 +138,10 @@ void initPruning() } } free(a); - dump_to_file((void*) twistMove, sizeof(twistMove), "twistMove"); + dump_to_file((void*) twistMove, sizeof(twistMove), "twistMove", cache_dir); } - if(check_cached_table("flipMove", (void*) flipMove, sizeof(flipMove)) != 0) { + if(check_cached_table("flipMove", (void*) flipMove, sizeof(flipMove), cache_dir) != 0) { a = get_cubiecube(); for (short i = 0; i < N_FLIP; i++) { setFlip(a, i); @@ -132,10 +154,10 @@ void initPruning() } } free(a); - dump_to_file((void*) flipMove, sizeof(flipMove), "flipMove"); + dump_to_file((void*) flipMove, sizeof(flipMove), "flipMove", cache_dir); } - if(check_cached_table("FRtoBR_Move", (void*) FRtoBR_Move, sizeof(FRtoBR_Move)) != 0) { + if(check_cached_table("FRtoBR_Move", (void*) FRtoBR_Move, sizeof(FRtoBR_Move), cache_dir) != 0) { a = get_cubiecube(); for (short i = 0; i < N_FRtoBR; i++) { setFRtoBR(a, i); @@ -148,10 +170,10 @@ void initPruning() } } free(a); - dump_to_file((void*) FRtoBR_Move, sizeof(FRtoBR_Move), "FRtoBR_Move"); + dump_to_file((void*) FRtoBR_Move, sizeof(FRtoBR_Move), "FRtoBR_Move", cache_dir); } - if(check_cached_table("URFtoDLF_Move", (void*) URFtoDLF_Move, sizeof(URFtoDLF_Move)) != 0) { + if(check_cached_table("URFtoDLF_Move", (void*) URFtoDLF_Move, sizeof(URFtoDLF_Move), cache_dir) != 0) { a = get_cubiecube(); for (short i = 0; i < N_URFtoDLF; i++) { setURFtoDLF(a, i); @@ -164,10 +186,10 @@ void initPruning() } } free(a); - dump_to_file((void*) URFtoDLF_Move, sizeof(URFtoDLF_Move), "URFtoDLF_Move"); + dump_to_file((void*) URFtoDLF_Move, sizeof(URFtoDLF_Move), "URFtoDLF_Move", cache_dir); } - if(check_cached_table("URtoDF_Move", (void*) URtoDF_Move, sizeof(URtoDF_Move)) != 0) { + if(check_cached_table("URtoDF_Move", (void*) URtoDF_Move, sizeof(URtoDF_Move), cache_dir) != 0) { a = get_cubiecube(); for (short i = 0; i < N_URtoDF; i++) { setURtoDF(a, i); @@ -182,10 +204,10 @@ void initPruning() } } free(a); - dump_to_file((void*) URtoDF_Move, sizeof(URtoDF_Move), "URtoDF_Move"); + dump_to_file((void*) URtoDF_Move, sizeof(URtoDF_Move), "URtoDF_Move", cache_dir); } - if(check_cached_table("URtoUL_Move", (void*) URtoUL_Move, sizeof(URtoUL_Move)) != 0) { + if(check_cached_table("URtoUL_Move", (void*) URtoUL_Move, sizeof(URtoUL_Move), cache_dir) != 0) { a = get_cubiecube(); for (short i = 0; i < N_URtoUL; i++) { setURtoUL(a, i); @@ -198,10 +220,10 @@ void initPruning() } } free(a); - dump_to_file((void*) URtoUL_Move, sizeof(URtoUL_Move), "URtoUL_Move"); + dump_to_file((void*) URtoUL_Move, sizeof(URtoUL_Move), "URtoUL_Move", cache_dir); } - if(check_cached_table("UBtoDF_Move", (void*) UBtoDF_Move, sizeof(UBtoDF_Move)) != 0) { + if(check_cached_table("UBtoDF_Move", (void*) UBtoDF_Move, sizeof(UBtoDF_Move), cache_dir) != 0) { a = get_cubiecube(); for (short i = 0; i < N_UBtoDF; i++) { setUBtoDF(a, i); @@ -214,10 +236,10 @@ void initPruning() } } free(a); - dump_to_file((void*) UBtoDF_Move, sizeof(UBtoDF_Move), "UBtoDF_Move"); + dump_to_file((void*) UBtoDF_Move, sizeof(UBtoDF_Move), "UBtoDF_Move", cache_dir); } - if(check_cached_table("MergeURtoULandUBtoDF", (void*) MergeURtoULandUBtoDF, sizeof(MergeURtoULandUBtoDF)) != 0) { + if(check_cached_table("MergeURtoULandUBtoDF", (void*) MergeURtoULandUBtoDF, sizeof(MergeURtoULandUBtoDF), cache_dir) != 0) { // for i, j <336 the six edges UR,UF,UL,UB,DR,DF are not in the // UD-slice and the index is <20160 for (short uRtoUL = 0; uRtoUL < 336; uRtoUL++) { @@ -225,12 +247,12 @@ void initPruning() MergeURtoULandUBtoDF[uRtoUL][uBtoDF] = (short) getURtoDF_standalone(uRtoUL, uBtoDF); } } - dump_to_file((void*) MergeURtoULandUBtoDF, sizeof(MergeURtoULandUBtoDF), "MergeURtoULandUBtoDF"); + dump_to_file((void*) MergeURtoULandUBtoDF, sizeof(MergeURtoULandUBtoDF), "MergeURtoULandUBtoDF", cache_dir); } int depth, done; - if(check_cached_table("Slice_URFtoDLF_Parity_Prun", (void*) Slice_URFtoDLF_Parity_Prun, sizeof(Slice_URFtoDLF_Parity_Prun)) != 0) { + if(check_cached_table("Slice_URFtoDLF_Parity_Prun", (void*) Slice_URFtoDLF_Parity_Prun, sizeof(Slice_URFtoDLF_Parity_Prun), cache_dir) != 0) { for (int i = 0; i < N_SLICE2 * N_URFtoDLF * N_PARITY / 2; i++) Slice_URFtoDLF_Parity_Prun[i] = -1; depth = 0; @@ -271,10 +293,10 @@ void initPruning() } depth++; } - dump_to_file((void*) Slice_URFtoDLF_Parity_Prun, sizeof(Slice_URFtoDLF_Parity_Prun), "Slice_URFtoDLF_Parity_Prun"); + dump_to_file((void*) Slice_URFtoDLF_Parity_Prun, sizeof(Slice_URFtoDLF_Parity_Prun), "Slice_URFtoDLF_Parity_Prun", cache_dir); } - if(check_cached_table("Slice_URtoDF_Parity_Prun", (void*) Slice_URtoDF_Parity_Prun, sizeof(Slice_URtoDF_Parity_Prun)) != 0) { + if(check_cached_table("Slice_URtoDF_Parity_Prun", (void*) Slice_URtoDF_Parity_Prun, sizeof(Slice_URtoDF_Parity_Prun), cache_dir) != 0) { for (int i = 0; i < N_SLICE2 * N_URtoDF * N_PARITY / 2; i++) Slice_URtoDF_Parity_Prun[i] = -1; depth = 0; @@ -315,10 +337,10 @@ void initPruning() } depth++; } - dump_to_file((void*) Slice_URtoDF_Parity_Prun, sizeof(Slice_URtoDF_Parity_Prun), "Slice_URtoDF_Parity_Prun"); + dump_to_file((void*) Slice_URtoDF_Parity_Prun, sizeof(Slice_URtoDF_Parity_Prun), "Slice_URtoDF_Parity_Prun", cache_dir); } - if(check_cached_table("Slice_Twist_Prun", (void*) Slice_Twist_Prun, sizeof(Slice_Twist_Prun)) != 0) { + if(check_cached_table("Slice_Twist_Prun", (void*) Slice_Twist_Prun, sizeof(Slice_Twist_Prun), cache_dir) != 0) { for (int i = 0; i < N_SLICE1 * N_TWIST / 2 + 1; i++) Slice_Twist_Prun[i] = -1; depth = 0; @@ -340,10 +362,10 @@ void initPruning() } depth++; } - dump_to_file((void*) Slice_Twist_Prun, sizeof(Slice_Twist_Prun), "Slice_Twist_Prun"); + dump_to_file((void*) Slice_Twist_Prun, sizeof(Slice_Twist_Prun), "Slice_Twist_Prun", cache_dir); } - if(check_cached_table("Slice_Flip_Prun", (void*) Slice_Flip_Prun, sizeof(Slice_Flip_Prun)) != 0) { + if(check_cached_table("Slice_Flip_Prun", (void*) Slice_Flip_Prun, sizeof(Slice_Flip_Prun), cache_dir) != 0) { for (int i = 0; i < N_SLICE1 * N_FLIP / 2; i++) Slice_Flip_Prun[i] = -1; depth = 0; @@ -365,7 +387,7 @@ void initPruning() } depth++; } - dump_to_file((void*) Slice_Flip_Prun, sizeof(Slice_Flip_Prun), "Slice_Flip_Prun"); + dump_to_file((void*) Slice_Flip_Prun, sizeof(Slice_Flip_Prun), "Slice_Flip_Prun", cache_dir); } PRUNING_INITED = 1; diff --git a/ckociemba/cubiecube.c b/kociemba/ckociemba/cubiecube.c similarity index 93% rename from ckociemba/cubiecube.c rename to kociemba/ckociemba/cubiecube.c index 5aa6a2c..64f9874 100644 --- a/ckociemba/cubiecube.c +++ b/kociemba/ckociemba/cubiecube.c @@ -1,9 +1,10 @@ #include "cubiecube.h" +#include "facecube.h" -int MOVECUBE_INITED = 0; - -void init_moveCube() +cubiecube_t * get_moveCube() { + static cubiecube_t moveCube[6]; + static int moveCube_initialized = 0; static const corner_t cpU[8] = { UBR, URF, UFL, ULB, DFR, DLF, DBL, DRB }; static const char coU[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; static const edge_t epU[12] = { UB, UR, UF, UL, DR, DF, DL, DB, FR, FL, BL, BR }; @@ -29,39 +30,38 @@ void init_moveCube() static const edge_t epB[12] = { UR, UF, UL, BR, DR, DF, DL, BL, FR, FL, UB, DB }; static const char eoB[12] = { 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 1 }; - memcpy(moveCube[0].cp, cpU, sizeof(cpU)); - memcpy(moveCube[0].co, coU, sizeof(coU)); - memcpy(moveCube[0].ep, epU, sizeof(epU)); - memcpy(moveCube[0].eo, eoU, sizeof(eoU)); - memcpy(moveCube[1].cp, cpR, sizeof(cpR)); - memcpy(moveCube[1].co, coR, sizeof(coR)); - memcpy(moveCube[1].ep, epR, sizeof(epR)); - memcpy(moveCube[1].eo, eoR, sizeof(eoR)); - memcpy(moveCube[2].cp, cpF, sizeof(cpF)); - memcpy(moveCube[2].co, coF, sizeof(coF)); - memcpy(moveCube[2].ep, epF, sizeof(epF)); - memcpy(moveCube[2].eo, eoF, sizeof(eoF)); - memcpy(moveCube[3].cp, cpD, sizeof(cpD)); - memcpy(moveCube[3].co, coD, sizeof(coD)); - memcpy(moveCube[3].ep, epD, sizeof(epD)); - memcpy(moveCube[3].eo, eoD, sizeof(eoD)); - memcpy(moveCube[4].cp, cpL, sizeof(cpL)); - memcpy(moveCube[4].co, coL, sizeof(coL)); - memcpy(moveCube[4].ep, epL, sizeof(epL)); - memcpy(moveCube[4].eo, eoL, sizeof(eoL)); - memcpy(moveCube[5].cp, cpB, sizeof(cpB)); - memcpy(moveCube[5].co, coB, sizeof(coB)); - memcpy(moveCube[5].ep, epB, sizeof(epB)); - memcpy(moveCube[5].eo, eoB, sizeof(eoB)); - - MOVECUBE_INITED = 1; + if (!moveCube_initialized) { + memcpy(moveCube[0].cp, cpU, sizeof(cpU)); + memcpy(moveCube[0].co, coU, sizeof(coU)); + memcpy(moveCube[0].ep, epU, sizeof(epU)); + memcpy(moveCube[0].eo, eoU, sizeof(eoU)); + memcpy(moveCube[1].cp, cpR, sizeof(cpR)); + memcpy(moveCube[1].co, coR, sizeof(coR)); + memcpy(moveCube[1].ep, epR, sizeof(epR)); + memcpy(moveCube[1].eo, eoR, sizeof(eoR)); + memcpy(moveCube[2].cp, cpF, sizeof(cpF)); + memcpy(moveCube[2].co, coF, sizeof(coF)); + memcpy(moveCube[2].ep, epF, sizeof(epF)); + memcpy(moveCube[2].eo, eoF, sizeof(eoF)); + memcpy(moveCube[3].cp, cpD, sizeof(cpD)); + memcpy(moveCube[3].co, coD, sizeof(coD)); + memcpy(moveCube[3].ep, epD, sizeof(epD)); + memcpy(moveCube[3].eo, eoD, sizeof(eoD)); + memcpy(moveCube[4].cp, cpL, sizeof(cpL)); + memcpy(moveCube[4].co, coL, sizeof(coL)); + memcpy(moveCube[4].ep, epL, sizeof(epL)); + memcpy(moveCube[4].eo, eoL, sizeof(eoL)); + memcpy(moveCube[5].cp, cpB, sizeof(cpB)); + memcpy(moveCube[5].co, coB, sizeof(coB)); + memcpy(moveCube[5].ep, epB, sizeof(epB)); + memcpy(moveCube[5].eo, eoB, sizeof(eoB)); + } + + return moveCube; } cubiecube_t* get_cubiecube() { - if (MOVECUBE_INITED == 0) - init_moveCube(); - cubiecube_t* result = (cubiecube_t *) calloc(1, sizeof(cubiecube_t)); static const corner_t cp[8] = { URF, UFL, ULB, UBR, DFR, DLF, DBL, DRB }; diff --git a/ckociemba/facecube.c b/kociemba/ckociemba/facecube.c similarity index 99% rename from ckociemba/facecube.c rename to kociemba/ckociemba/facecube.c index 6bc7178..e851a0d 100644 --- a/ckociemba/facecube.c +++ b/kociemba/ckociemba/facecube.c @@ -81,7 +81,7 @@ void to_String(facecube_t* facecube, char* res) cubiecube_t* toCubieCube(facecube_t* facecube) { - char ori; + unsigned char ori; cubiecube_t* ccRet = (cubiecube_t*) calloc(1, sizeof(cubiecube_t)); for (int i = 0; i < 8; i++) ccRet->cp[i] = URF;// invalidate corners diff --git a/ckociemba/include/color.h b/kociemba/ckociemba/include/color.h similarity index 100% rename from ckociemba/include/color.h rename to kociemba/ckociemba/include/color.h diff --git a/ckociemba/include/coordcube.h b/kociemba/ckociemba/include/coordcube.h similarity index 93% rename from ckociemba/include/coordcube.h rename to kociemba/ckociemba/include/coordcube.h index d87e151..a6ae84f 100644 --- a/ckociemba/include/coordcube.h +++ b/kociemba/ckociemba/include/coordcube.h @@ -99,7 +99,7 @@ extern char Slice_Twist_Prun[N_SLICE1 * N_TWIST / 2 + 1]; extern char Slice_Flip_Prun[N_SLICE1 * N_FLIP / 2]; extern int PRUNING_INITED; -void initPruning(); +void initPruning(const char *cache_dir); // Set pruning value in table. Two values are stored in one char. void setPruning(char *table, int index, char value); @@ -108,9 +108,9 @@ void setPruning(char *table, int index, char value); char getPruning(char *table, int index); coordcube_t* get_coordcube(cubiecube_t* cubiecube); -void move(coordcube_t* coordcube, int m); -int check_cached_table(const char* name, void* ptr, int len); -void dump_to_file(void* ptr, int len, const char* name); +void move(coordcube_t* coordcube, int m, const char *cache_dir); +int check_cached_table(const char* name, void* ptr, int len, const char *cache_dir); +void dump_to_file(void* ptr, int len, const char* name, const char *cache_dir); void read_from_file(void* ptr, int len, const char* name); #endif diff --git a/ckociemba/include/corner.h b/kociemba/ckociemba/include/corner.h similarity index 100% rename from ckociemba/include/corner.h rename to kociemba/ckociemba/include/corner.h diff --git a/ckociemba/include/cubiecube.h b/kociemba/ckociemba/include/cubiecube.h similarity index 91% rename from ckociemba/include/cubiecube.h rename to kociemba/ckociemba/include/cubiecube.h index 2ea4dd5..6bbec06 100644 --- a/ckociemba/include/cubiecube.h +++ b/kociemba/ckociemba/include/cubiecube.h @@ -6,10 +6,9 @@ #include "corner.h" #include "edge.h" -#include "facecube.h" //Cube on the cubie level -struct cubiecube_struct { +typedef struct { // initialize to Id-Cube // corner permutation corner_t cp[8]; @@ -19,14 +18,10 @@ struct cubiecube_struct { edge_t ep[12]; // edge orientation char eo[12]; -}; +} cubiecube_t; // this CubieCube array represents the 6 basic cube moves -cubiecube_t moveCube[6]; -extern int MOVECUBE_INITED; - -void init_moveCube(); - +cubiecube_t* get_moveCube(); cubiecube_t* get_cubiecube(); // n choose k @@ -35,7 +30,7 @@ void rotateLeft_corner(corner_t* arr, int l, int r); void rotateRight_corner(corner_t* arr, int l, int r); void rotateLeft_edge(edge_t* arr, int l, int r); void rotateRight_edge(edge_t* arr, int l, int r); -facecube_t* toFaceCube(cubiecube_t* cubiecube); +// facecube_t* toFaceCube(cubiecube_t* cubiecube); void cornerMultiply(cubiecube_t* cubiecube, cubiecube_t* b); void edgeMultiply(cubiecube_t* cubiecube, cubiecube_t* b); void multiply(cubiecube_t* cubiecube, cubiecube_t* b); diff --git a/ckociemba/include/edge.h b/kociemba/ckociemba/include/edge.h similarity index 100% rename from ckociemba/include/edge.h rename to kociemba/ckociemba/include/edge.h diff --git a/ckociemba/include/facecube.h b/kociemba/ckociemba/include/facecube.h similarity index 94% rename from ckociemba/include/facecube.h rename to kociemba/ckociemba/include/facecube.h index f1aad12..687dff3 100644 --- a/ckociemba/include/facecube.h +++ b/kociemba/ckociemba/include/facecube.h @@ -5,9 +5,7 @@ #include "color.h" #include "corner.h" #include "edge.h" -#include "facecube.h" - -typedef struct cubiecube_struct cubiecube_t; +#include "cubiecube.h" //Cube on the facelet level typedef struct { diff --git a/ckociemba/include/facelet.h b/kociemba/ckociemba/include/facelet.h similarity index 100% rename from ckociemba/include/facelet.h rename to kociemba/ckociemba/include/facelet.h diff --git a/ckociemba/include/search.h b/kociemba/ckociemba/include/search.h similarity index 98% rename from ckociemba/include/search.h rename to kociemba/ckociemba/include/search.h index f3e1531..0a6a1b1 100644 --- a/ckociemba/include/search.h +++ b/kociemba/ckociemba/include/search.h @@ -49,7 +49,7 @@ char* solutionToString(search_t* search, int length, int depthPhase1); * Error 7: No solution exists for the given maxDepth
* Error 8: Timeout, no solution within given time */ -char* solution(char* facelets, int maxDepth, long timeOut, int useSeparator); +char* solution(char* facelets, int maxDepth, long timeOut, int useSeparator, const char* cache_dir); // Apply phase2 of algorithm and return the combined phase1 and phase2 depth. In phase2, only the moves // U,D,R2,F2,L2 and B2 are allowed. diff --git a/ckociemba/search.c b/kociemba/ckociemba/search.c similarity index 98% rename from ckociemba/search.c rename to kociemba/ckociemba/search.c index 196c62c..59237b1 100644 --- a/ckociemba/search.c +++ b/kociemba/ckociemba/search.c @@ -1,6 +1,8 @@ #include #include #include "search.h" +#include "color.h" +#include "facecube.h" #include "coordcube.h" #define MIN(a, b) (((a)<(b))?(a):(b)) @@ -53,10 +55,10 @@ char* solutionToString(search_t* search, int length, int depthPhase1) } -char* solution(char* facelets, int maxDepth, long timeOut, int useSeparator) +char* solution(char* facelets, int maxDepth, long timeOut, int useSeparator, const char* cache_dir) { if (PRUNING_INITED == 0) { - initPruning(); + initPruning(cache_dir); } search_t* search = (search_t*) calloc(1, sizeof(search_t)); diff --git a/solve.c b/kociemba/ckociemba/solve.c similarity index 91% rename from solve.c rename to kociemba/ckociemba/solve.c index d0199f7..3d3467e 100644 --- a/solve.c +++ b/kociemba/ckociemba/solve.c @@ -9,7 +9,8 @@ int main(int argc, char **argv) argv[1], 24, 1000, - 0 + 0, + "cache" ); if (sol == NULL) { puts("Unsolvable cube!"); diff --git a/kociemba/command_line.py b/kociemba/command_line.py new file mode 100644 index 0000000..1bdbcb9 --- /dev/null +++ b/kociemba/command_line.py @@ -0,0 +1,9 @@ +import sys +from kociemba import solve + + +def main(): + if len(sys.argv) > 1: + print(solve(sys.argv[1])) + else: + print('Usage: kociemba \nfor example:\nkociemba DRLUUBFBRBLURRLRUBLRDDFDLFUFUFFDBRDUBRUFLLFDDBFLUBLRBD') diff --git a/prunetables/FRtoBR_Move b/kociemba/cprunetables/FRtoBR_Move similarity index 100% rename from prunetables/FRtoBR_Move rename to kociemba/cprunetables/FRtoBR_Move diff --git a/prunetables/MergeURtoULandUBtoDF b/kociemba/cprunetables/MergeURtoULandUBtoDF similarity index 100% rename from prunetables/MergeURtoULandUBtoDF rename to kociemba/cprunetables/MergeURtoULandUBtoDF diff --git a/prunetables/Slice_Flip_Prun b/kociemba/cprunetables/Slice_Flip_Prun similarity index 100% rename from prunetables/Slice_Flip_Prun rename to kociemba/cprunetables/Slice_Flip_Prun diff --git a/prunetables/Slice_Twist_Prun b/kociemba/cprunetables/Slice_Twist_Prun similarity index 100% rename from prunetables/Slice_Twist_Prun rename to kociemba/cprunetables/Slice_Twist_Prun diff --git a/prunetables/Slice_URFtoDLF_Parity_Prun b/kociemba/cprunetables/Slice_URFtoDLF_Parity_Prun similarity index 100% rename from prunetables/Slice_URFtoDLF_Parity_Prun rename to kociemba/cprunetables/Slice_URFtoDLF_Parity_Prun diff --git a/prunetables/Slice_URtoDF_Parity_Prun b/kociemba/cprunetables/Slice_URtoDF_Parity_Prun similarity index 100% rename from prunetables/Slice_URtoDF_Parity_Prun rename to kociemba/cprunetables/Slice_URtoDF_Parity_Prun diff --git a/prunetables/UBtoDF_Move b/kociemba/cprunetables/UBtoDF_Move similarity index 100% rename from prunetables/UBtoDF_Move rename to kociemba/cprunetables/UBtoDF_Move diff --git a/prunetables/URFtoDLF_Move b/kociemba/cprunetables/URFtoDLF_Move similarity index 100% rename from prunetables/URFtoDLF_Move rename to kociemba/cprunetables/URFtoDLF_Move diff --git a/prunetables/URtoDF_Move b/kociemba/cprunetables/URtoDF_Move similarity index 100% rename from prunetables/URtoDF_Move rename to kociemba/cprunetables/URtoDF_Move diff --git a/prunetables/URtoUL_Move b/kociemba/cprunetables/URtoUL_Move similarity index 100% rename from prunetables/URtoUL_Move rename to kociemba/cprunetables/URtoUL_Move diff --git a/prunetables/flipMove b/kociemba/cprunetables/flipMove similarity index 100% rename from prunetables/flipMove rename to kociemba/cprunetables/flipMove diff --git a/prunetables/twistMove b/kociemba/cprunetables/twistMove similarity index 100% rename from prunetables/twistMove rename to kociemba/cprunetables/twistMove diff --git a/kociemba/pykociemba/__init__.py b/kociemba/pykociemba/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/kociemba/color.py b/kociemba/pykociemba/color.py similarity index 100% rename from kociemba/color.py rename to kociemba/pykociemba/color.py diff --git a/kociemba/coordcube.py b/kociemba/pykociemba/coordcube.py similarity index 100% rename from kociemba/coordcube.py rename to kociemba/pykociemba/coordcube.py diff --git a/kociemba/corner.py b/kociemba/pykociemba/corner.py similarity index 100% rename from kociemba/corner.py rename to kociemba/pykociemba/corner.py diff --git a/kociemba/cubiecube.py b/kociemba/pykociemba/cubiecube.py similarity index 100% rename from kociemba/cubiecube.py rename to kociemba/pykociemba/cubiecube.py diff --git a/kociemba/edge.py b/kociemba/pykociemba/edge.py similarity index 100% rename from kociemba/edge.py rename to kociemba/pykociemba/edge.py diff --git a/kociemba/facecube.py b/kociemba/pykociemba/facecube.py similarity index 100% rename from kociemba/facecube.py rename to kociemba/pykociemba/facecube.py diff --git a/kociemba/facelet.py b/kociemba/pykociemba/facelet.py similarity index 100% rename from kociemba/facelet.py rename to kociemba/pykociemba/facelet.py diff --git a/kociemba/prunetables/FRtoBR_Move.pkl b/kociemba/pykociemba/prunetables/FRtoBR_Move.pkl similarity index 100% rename from kociemba/prunetables/FRtoBR_Move.pkl rename to kociemba/pykociemba/prunetables/FRtoBR_Move.pkl diff --git a/kociemba/prunetables/MergeURtoULandUBtoDF.pkl b/kociemba/pykociemba/prunetables/MergeURtoULandUBtoDF.pkl similarity index 100% rename from kociemba/prunetables/MergeURtoULandUBtoDF.pkl rename to kociemba/pykociemba/prunetables/MergeURtoULandUBtoDF.pkl diff --git a/kociemba/prunetables/Slice_Flip_Prun.pkl b/kociemba/pykociemba/prunetables/Slice_Flip_Prun.pkl similarity index 100% rename from kociemba/prunetables/Slice_Flip_Prun.pkl rename to kociemba/pykociemba/prunetables/Slice_Flip_Prun.pkl diff --git a/kociemba/prunetables/Slice_Twist_Prun.pkl b/kociemba/pykociemba/prunetables/Slice_Twist_Prun.pkl similarity index 100% rename from kociemba/prunetables/Slice_Twist_Prun.pkl rename to kociemba/pykociemba/prunetables/Slice_Twist_Prun.pkl diff --git a/kociemba/prunetables/Slice_URFtoDLF_Parity_Prun.pkl b/kociemba/pykociemba/prunetables/Slice_URFtoDLF_Parity_Prun.pkl similarity index 100% rename from kociemba/prunetables/Slice_URFtoDLF_Parity_Prun.pkl rename to kociemba/pykociemba/prunetables/Slice_URFtoDLF_Parity_Prun.pkl diff --git a/kociemba/prunetables/Slice_URtoDF_Parity_Prun.pkl b/kociemba/pykociemba/prunetables/Slice_URtoDF_Parity_Prun.pkl similarity index 100% rename from kociemba/prunetables/Slice_URtoDF_Parity_Prun.pkl rename to kociemba/pykociemba/prunetables/Slice_URtoDF_Parity_Prun.pkl diff --git a/kociemba/prunetables/UBtoDF_Move.pkl b/kociemba/pykociemba/prunetables/UBtoDF_Move.pkl similarity index 100% rename from kociemba/prunetables/UBtoDF_Move.pkl rename to kociemba/pykociemba/prunetables/UBtoDF_Move.pkl diff --git a/kociemba/prunetables/URFtoDLF_Move.pkl b/kociemba/pykociemba/prunetables/URFtoDLF_Move.pkl similarity index 100% rename from kociemba/prunetables/URFtoDLF_Move.pkl rename to kociemba/pykociemba/prunetables/URFtoDLF_Move.pkl diff --git a/kociemba/prunetables/URtoDF_Move.pkl b/kociemba/pykociemba/prunetables/URtoDF_Move.pkl similarity index 100% rename from kociemba/prunetables/URtoDF_Move.pkl rename to kociemba/pykociemba/prunetables/URtoDF_Move.pkl diff --git a/kociemba/prunetables/URtoUL_Move.pkl b/kociemba/pykociemba/prunetables/URtoUL_Move.pkl similarity index 100% rename from kociemba/prunetables/URtoUL_Move.pkl rename to kociemba/pykociemba/prunetables/URtoUL_Move.pkl diff --git a/kociemba/prunetables/flipMove.pkl b/kociemba/pykociemba/prunetables/flipMove.pkl similarity index 100% rename from kociemba/prunetables/flipMove.pkl rename to kociemba/pykociemba/prunetables/flipMove.pkl diff --git a/kociemba/prunetables/twistMove.pkl b/kociemba/pykociemba/prunetables/twistMove.pkl similarity index 100% rename from kociemba/prunetables/twistMove.pkl rename to kociemba/pykociemba/prunetables/twistMove.pkl diff --git a/kociemba/search.py b/kociemba/pykociemba/search.py similarity index 100% rename from kociemba/search.py rename to kociemba/pykociemba/search.py diff --git a/kociemba/tools.py b/kociemba/pykociemba/tools.py similarity index 100% rename from kociemba/tools.py rename to kociemba/pykociemba/tools.py diff --git a/setup.cfg b/setup.cfg new file mode 100644 index 0000000..6a53971 --- /dev/null +++ b/setup.cfg @@ -0,0 +1,3 @@ +[aliases] +test=pytest + diff --git a/setup.py b/setup.py new file mode 100644 index 0000000..9d8749a --- /dev/null +++ b/setup.py @@ -0,0 +1,29 @@ +from setuptools import setup + + +setup( + name='kociemba', + version='1.0', + description='Python/C implementation of Herbert Kociemba\'s Two-Phase algorithm for solving Rubik\'s Cube', + keywords='kociemba rubik cube solver twophase', + url='https://github.com/muodov/kociemba', + author='muodov', + author_email='muodov@gmail.com', + license='GPLv2', + packages=['kociemba'], + package_data={ + '': ['cprunetables/*', 'pykociemba/**/*'], + }, + classifiers=( + 'Development Status :: 5 - Production/Stable', + 'Programming Language :: Python', + ), + entry_points = { + 'console_scripts': ['kociemba=kociemba.command_line:main'], + }, + setup_requires=['pytest-runner', "cffi>=1.0.0"], + tests_require=['pytest', ], + zip_safe=False, + cffi_modules=["kociemba/build_ckociemba.py:ffi"], + install_requires=["cffi>=1.0.0"], +) diff --git a/test.py b/test.py deleted file mode 100644 index 6810e09..0000000 --- a/test.py +++ /dev/null @@ -1,340 +0,0 @@ -import sys -import os -import subprocess -import logging -logging.basicConfig(level=logging.DEBUG, format='%(asctime)s - %(levelname)s - %(message)s') -# import kociemba.search - -# these results were produced by original Kociemba's Java implementation -javares = [ - ("BBURUDBFUFFFRRFUUFLULUFUDLRRDBBDBDBLUDDFLLRRBRLLLBRDDF", - "B U' L' D' R' D' L2 D' L F' L' D F2 R2 U R2 B2 U2 L2 F2 D' "), - - ("FDLUUURLFLBDFRRDLBBBUBFLDDLFBBUDUBRLURDFLRUFRFLRFBDUDR", - "U F' L2 U F' L2 F L2 F2 D L' F' U2 B2 D F2 D' R2 L2 D F2 U' "), - - ("UDRFULDRBLDUBRDUFBFBDRFDFURLBBLDRDURLLRULUFBUFRBFBFDLL", - "F U2 D2 L' F2 D' B R L2 U F U F2 D2 B2 D R2 U2 F2 L2 B2 "), - - ("LRLLURRLBDUULRFUFLFDRUFBRBLDUFDDRRBDDFURLLBFFBDBUBBFDU", - "B2 D' R2 F U R F' D2 L' B D F2 R2 L2 U' B2 D2 B2 U B2 "), - - ("UUULULFLFDUBDRRDBBUFLFFLBRRLDFFDDBUUFBRRLDRUDLBLFBBRRD", - "U2 F' D F U F' U F2 R' F R' D2 R2 F2 U2 D B2 U2 L2 F2 "), - - ("LRRFUUBDLFBBLRDLLRUFDLFURLFBBUBDDDDUDULRLFRRDUUBRBFFBF", - "R' B' D' R' B' L F2 U' D F' R2 L2 U' R2 F2 U R2 U B2 D' "), - - ("FBRDULFBRFBBRRRDLBRRUDFUUDFLBLFDUBFDLLDLLFRRBUUUDBFLUD", - "U F R' D' R' U2 L D B' R L' U' B2 L2 U2 D2 B2 R2 D L2 B2 "), - - ("FLBUULFFLFDURRDBUBUUDDFFBRDDBLRDRFLLRLRULFUDRRBDBBBUFL", - "U2 D B' U2 R' D2 L2 D R2 L B' U' L2 D L2 D F2 L2 B2 U' "), - - ("UBLLURBDLDDFRRLRFLDFBLFURFFFLDBDULBUBDRRLBDDUUURUBFBRF", - "U' R2 F U2 R' L' F' L U D' R' U' R2 B2 L2 B2 L2 U2 R2 D' F2 "), - - ("UDLFUBLRFRDDLRFDBDBBDDFUUUBFRRLDUFFLBLUFLRRBLFLRUBDBRU", - "U R' L F L' U' F' D R F' L' B2 U L2 B2 D L2 U2 R2 B2 D "), - - ("URBLUBDDBURDLRDLDBFBLLFFULDBBFUDFLRRRURBLDFFRLUFRBUDFU", - "U2 R2 F' R B' D2 B L' B U' R2 B L2 F2 U2 F2 U' R2 D' L2 D R2 "), - - ("BLBDUULUDBLRDRFLBUUBLRFFURDLDFRDRRUFRBFLLUFFBDDULBBRFD", - "U2 D2 B' D' F B L2 F2 L D2 L' U F2 U L2 D L2 U2 L2 D F2 "), - - ("ULFUUURRURLLLRRUBLDFFLFFBDRURBRDDDFBFBFFLDBBLDBLUBDDUR", - "U2 B2 L2 B' D R U2 B2 L' U D2 F' U F2 L2 U2 D' R2 F2 U2 D' F2 "), - - ("LUFBUUUDDLLRDRRDDLBFFFFRUDBLLRRDBRBFDURFLRFUBUFBBBLULD", - "D' L B2 U' F' B U B' R2 D2 R' B2 L2 U R2 U B2 R2 U' F2 D2 "), - - ("UDDBURDDBUFLFRLFDFRRLRFLUBRFDUBDFRFLBLBRLUFULBLRUBBDUD", - "U2 B' U' B' R' F2 U' L' F' D B U F2 D2 F2 D F2 R2 U2 F2 D' "), - - ("UUBUUBUDBDRLFRFDUDBBRBFRFBRUUFDDLLDFFRRDLLBRRUFLLBFLLD", - "U2 R' B2 U' F2 D B R F2 R U2 B2 U2 R2 U' F2 U2 R2 D' "), - - ("BDLRULLRRDFFBRLDRLBFFFFUUDBBRRLDURDDLBULLUUBRUBDUBDFFF", - "F2 D' L2 U B' D B L F' B U' L2 D2 L2 B2 U R2 F2 U F2 "), - - ("LFRUULBBDBFBDRBLFRDDLLFLFRDRBFDDUBUUURRFLBLRDURFUBDFLU", - "R' D' F' R U' L2 D2 R D L' D' F2 D' R2 U' R2 F2 B2 L2 U2 "), - - ("UBBRUDBLFRBRRRUFBBLFDDFFFULUFDDDLBLUFUDBLRLFRDULLBRRDU", - "R' U B R U' R D' R2 L' F' R' F2 R2 U L2 D' B2 U2 L2 D' "), - - ("FRRUUFURDBLFRRFFLUBDLRFBLFUFULLDDBBBULRDLURBDDFRDBBLUD", - "U R2 U F R' B' R F2 D F' L' D' R2 D B2 D' L2 B2 D R2 L2 "), - - ("ULDFUBBRRBDLFRBFFLUUDBFLRFDUDRLDUFUDRRLDLUUDBBBFRBRFLL", - "F' B' L' U D B U2 F' B' D2 R' B2 U L2 D' F2 R2 D2 R2 U R2 "), - - ("ULLLURFBBDUBBRUBLFURRDFDRFUDRRFDBUULLURRLLLDFDFBBBDDFF", - "U' F2 D2 B2 R2 U B R B U L' B' U B2 D B2 R2 D L2 U D2 "), - - ("BDBDURFFRDFDRRLUBLLLFBFURFBBULDDURLDRFURLRUBDLLUUBDFBF", - "U2 B2 U' F' D' R2 U F2 D' L' B R2 B2 U' B2 U' B2 D' B2 R2 U' "), - - ("DRUUUDDBRULLBRBFFLLLBFFDBURLFUUDLRRURRFFLDFLDFDBUBRBBD", - "D F R L B2 L' B U F' D' R U B2 U F2 U B2 U2 F2 U' L2 "), - - ("BDLLURUFRDBDRRRDFURLFLFUBFLRDBLDUBBLDDFFLBLUUFBRDBRFUU", - "L' D R' U' B D F D F2 B' R B2 U' L2 U' F2 U D F2 R2 D2 "), - - ("RRRUURUUBDDBFRBFLURLRFFRLULDBDLDBLLLDFFULDUDBUBFDBRFFB", - "U D2 R' F' R' U' B R' U' L F2 B2 U2 B2 D' F2 D R2 F2 D2 "), - - ("LFRLUUBBLBFUDRRUUFDDUDFFULLBUFLDBLFDFDRBLRBBRFRDUBRRLD", - "F2 R U' F D2 B D B' L U2 R U F2 U2 R2 U2 R2 U' B2 D' "), - - ("FRRBUBDDURLBDRDLUDRLFLFBLBFDUUFDRLUFRRBRLFUUBUDDFBFLLB", - "U2 D F' B' R' D' L B' R B R L2 D2 L2 F2 U B2 R2 B2 D2 F2 "), - - ("DBUFUFDFUBLLLRURUBLRRDFBFLDUUBFDRDDLFUFBLLLDRFDRBBRURB", - "F' B' U' B2 D' F L U' B R' D2 L2 U2 F2 D B2 U' F2 U2 L2 "), - - ("BFRFUBBLBLRFDRBDUUUBDFFRLFFULLDDRFDRDULLLRRLFDDRUBUBBU", - "L F2 R F' U2 R F' L F R U F2 D2 R2 U R2 L2 B2 D2 F2 "), - - ("BFDDURFBRDBLURLBUUDLFRFBDRURURLDLFFFUBLFLDUFBBRLDBDRUL", - "L2 U R2 B L' F L' F' R' L F R2 U2 R2 U F2 U F2 D R2 D2 "), - - ("LRBUULRDRDBLLRBDDUFRFDFURLLBFBUDBBFLFBUDLFURDUFDRBLFUR", - "R' B' D' R2 L B' L D L' B' U2 L2 D2 R2 B2 U' L2 D' F2 B2 "), - - ("RBBDUBBRRFLDFRFFRRDUUFFUDFULLLLDBBLBDBRDLRLUFLUFDBRUDU", - "U2 F2 U' D2 F U' R B' U L F B2 U D B2 R2 U2 B2 D' F2 "), - - ("FRBUURUDBLBRDRLDFDRBDDFLUFFLULDDLBLRLBFFLRUFBDUUUBRFBR", - "D B' U' D' F' U2 F' R F D2 F B2 U D2 F2 R2 D2 L2 F2 D' B2 "), - - ("FLURURDBRBDBBRUUUUFLDFFULUFFLRDDRLBRLFRFLLBBDLDUFBDBRD", - "F' U' F2 D2 F2 L' B' R2 U' R F U B2 D L2 D' F2 R2 D L2 U2 "), - - ("BULRUULFRDBDDRLUDRULFFFBLUBDRLFDLURBDBFLLDFRBFFRUBBUDR", - "U' F2 R' D2 L2 U2 F' B' R' F' B2 U2 D L2 F2 L2 D' F2 U2 F2 "), - - ("FFRRULFBDRFBURLFBUDLBRFFDBRBUUDDDLRLRULRLDULLUDDUBFFBB", - "U F D' B' U D' F L2 U R F' R2 F2 U' R2 F2 D' R2 U D' B2 "), - - ("DUFBUDBRDBRUFRURRBDFLLFDDLBLFULDURBLFDRDLBUUFLBRFBLURF", - "U L2 B D' L' U B' R2 L2 D' R F2 B2 R2 U2 B2 U' D2 F2 B2 R2 "), - - ("DRRUURBRURUBDRLUBFDBFBFBLFLDRFFDULLDLFRDLLUDBUDFUBLRFB", - "F2 B D2 R B' U2 B2 D2 F' L B2 R2 F2 L2 U' L2 U' R2 B2 U "), - - ("BRLFUDLDRFLUFRUFFLFBURFRUUDFBRUDDRRBRLDLLBDLLBUUFBBDDB", - "F2 D L F' B' L' F2 D F' U' R U F2 L2 F2 L2 F2 U2 L2 U' R2 "), - - ("UULFUFDLRFDBBRDBLFLFULFUDDURBRRDDURDFUFLLBBFBDRLRBURBL", - "F' R U B2 D B U2 R' L' F' L' D' F2 R2 U F2 L2 U2 B2 U B2 "), - - ("DUDUUUDBUFRFRRBRDUBLLUFDUBFBDDFDLUFFRBLFLFBRRLLBRBDRLL", - "B2 L U B' R' F2 B D2 R2 U2 R' U' R2 D' R2 D' R2 U B2 U' R2 "), - - ("LDRLUDRLFURBRRRRDDBBRFFUUBFLUDUDLLBFUFDFLUBLBUBFFBDLRD", - "D F2 R' L2 D' B2 R' D' L B U' F2 R2 B2 R2 F2 U B2 U D "), - - ("FUBUUFLBLURRDRFFUDDUFBFRUBDBLRRDLBFFURBLLDLBRDFRLBDLDU", - "F R' U L B' U' R2 L F D' F' D L2 D B2 U' B2 U2 R2 B2 L2 "), - - ("DFRBURUDDLBDRRFUDULLFLFUULFFBRRDRFBRBDBFLUDFLBULDBLBUR", - "U F2 R B' U L' U2 L' U' B2 L F U' R2 D2 F2 R2 D2 B2 D B2 U' "), - - ("RLRUURDLFUFDBRLFRBLFRFFDDLUFULRDUDFLUBFRLULBRBDBBBDUDB", - "U2 F2 D' F' L' F' B' U B' R' L2 B' U' F2 L2 D L2 U' F2 U2 L2 U2 "), - - ("BBURULRUULFLBRRBFBDFBFFDFRDUULUDRDDUDBFLLDFBRFLRDBURLL", - "U F D L2 U2 R' L U2 B2 R B' D' R2 D' F2 B2 D F2 D L2 D2 "), - - ("LBLLUBUFUBRUURFDLRRLRDFLDFLFRBRDDLBDFBFRLFFDRBUDUBUBDU", - "U L' D2 B U B D2 F R B U2 R' D' R2 U L2 D R2 D2 R2 D2 F2 "), - - ("FUFBUBURDFLRDRFBUFLDRFFLBDDDBLFDLURLLUBFLURDRURULBRDBB", - "B' R L F U' B' U L U R' B U L2 U2 L2 F2 U' F2 L2 B2 U2 "), - - ("RURFUDDDFLBBFRULUBFFUDFLDLDRBFBDLBDLFRRULRDRBURUBBFULL", - "U' D' R B2 U R2 F2 R' F' L' U' F2 B2 R2 D B2 U2 R2 U2 R2 "), - - ("DBRDULBFBUDUDRRULLDRLLFRLBRFUBUDUDDFBFRBLFRFDFLLUBRUBF", - "L' U R2 L F2 D2 B' U' L U2 R2 U D' R2 D' F2 R2 F2 "), - - ("URBLUBFDUBRRLRFLULRLRBFFLDDBFFLDRFFBRBDBLUUUUDDFRBDDUL", - "U' R L' F' R' U B R2 U B2 R' F2 R2 B2 U2 D R2 U D2 F2 U2 "), - - ("BUULURRDFRURFRBUFUBLDDFLFBFDRRBDRUULLBDRLFBULBFDDBDFLL", - "R D L' U' R2 B' L2 B2 U F' D' R U2 D' F2 R2 F2 D' F2 U L2 D "), - - ("FURBUDLRRUBDFRLBDFBUBFFRUDDRRLDDFULLRUUBLULLFBLDBBRDFF", - "R B' U' F' B2 L2 D2 R' U2 F' L D L2 U2 D' F2 L2 U R2 B2 R2 "), - - ("LLRDUBUBBURBBRBLRRRLLLFUBFDDRFFDUULFDFFDLULURUDBDBRDFF", - "R2 L2 U' B' U2 L' B' R L' D2 B D F2 B2 L2 U' F2 D B2 U "), - - ("FDRUUBBBLDRBDRLFFFDUBLFRBURURUFDRFFUDLRFLBDLLUBLDBDLUR", - "U D2 B' U' L' U' F U' B R' D2 L D' B2 U2 R2 D R2 L2 B2 "), - - ("FBBDULLFRUBRLRLDFUDRBBFFUURLLFUDDDBLURBFLRFRBDURDBUFDL", - "U R' D L' U2 D L U2 L' D2 F' R D' L2 U2 R2 D' F2 R2 D' F2 D2 "), - - ("LLBDURRDURBDLRLRULBBFBFDDBBFUUFDRLFFBRDFLLDDRLUUFBRUUF", - "U2 L' U2 B' R L2 U R' F2 R' B D R2 U2 D R2 F2 D R2 L2 F2 "), - - ("LFFDUBLRDLLDURLBDFDUFLFFFDUUBRRDRDBUBLBRLUBBRRDUFBFLUR", - "D2 B2 L' F R' L' B' L2 F2 D' R' U2 B2 D2 B2 D L2 U F2 D' F2 "), - - ("FBUDUBBRBUURLRRUFLDBLLFDRFFDLRFDRFUBDBRRLUUDFBLLUBDDFL", - "R2 U R F' U R2 D2 B' R' B' R' U2 F2 D F2 U F2 D2 L2 B2 D' "), - - ("ULBFURBDBDDDFRRBFFUBRLFUFRURBRUDDDLURRLLLFFBDLDFUBULBL", - "F2 L U' R' B2 L' D B2 L B' D' B2 U B2 L2 U B2 L2 D2 R2 "), - - ("DUBBUFLFFLRLDRBBLRDUUDFLLRRFBDDDURRUFLBFLRBFDUBRDBLFUU", - "D' F' D' L' F2 D F D2 R' L2 D2 R2 D B2 D B2 L2 U R2 "), - - ("BRDFUUUUULBFDRDDDFRLBUFRLBBUDRFDLBLDRRFBLFDLFLUUFBRRBL", - "L' U R' F B2 D F R B R L2 D R2 U2 F2 R2 B2 R2 U R2 "), - - ("DBRLUFFUBDLFBRFLBLLFRFFUBLBRUDDDDFUULDUBLRRRUDLFDBRBRU", - "R2 B2 R' L' F2 R2 B' D L U B D B2 R2 D' R2 D B2 D2 F2 "), - - ("LLURULDUDLBLURBBRFRFFRFLFRURBRFDDBBRDFBFLULDDFDBUBLUDU", - "U F D' R' B' U R' F' D' F U2 L B2 U2 D L2 F2 L2 U F2 L2 U "), - - ("UFLRULBLUBUBBRFRDFDFRBFLFUFLRDDDRBBLRFRBLULLUDDFUBDDRU", - "U R L' D2 B' L F2 U F L2 U2 L D' R2 D2 R2 B2 U' L2 F2 D' L2 "), - - ("BRRLUFBFFLRFDRUDLURDUFFRULFRDLRDUDBBLFULLUBUFDBDBBBLDR", - "U' D' F D' B' L2 F' R D' F B R2 F2 R2 D' R2 F2 U2 D R2 F2 "), - - ("DRDUUBRRLBLLRRLUFDUFULFBFDLULFDDUDBBFRBDLUFFRBDRFBBRUL", - "L' B R D' L B R D' F2 U2 F L2 F2 U B2 D F2 R2 D' B2 D2 "), - - ("LLFLUBRURDLUFRDRURUBFRFULBDDRBRDRLDUBUBDLDDFBLFUBBFFLF", - "L B' R' U' F L U D2 B' R B2 R2 F2 D2 B2 U2 D B2 L2 U2 "), - - ("LLBRUFUBBUURURDLLRBDLRFBBLFLUUDDFRRFFDRRLFUFDDBDLBBDUF", - "F L' U D B' L' U' D R' U2 F' D2 R2 U2 L2 F2 U L2 B2 L2 U "), - - ("FLLUUULLULBDRRFUFDUDBBFBBFRLRBBDURDBURFDLLFDDFURLBRRFD", - "F2 B2 U2 B' U F2 D2 F B2 R F R2 U R2 D R2 L2 B2 U F2 D2 "), - - ("FURFUDBUDFLBFRBDRDUBRBFRULBFFRBDULDFUULRLRBDLULRLBDLFD", - "U R L D R B U D F2 B2 R' U L2 B2 R2 U F2 D R2 B2 U' "), - - ("BFFBUFUBFDRDDRDFRDBRLFFBBDUDLLBDUUFLUURLLLFLRRDLRBUBUR", - "F' B' U2 R' F' B2 R' F2 L U' R U' B2 L2 D L2 D B2 D' F2 D "), - - ("UFFDUULUUBFRLRFLDUDLRRFBBRDDUFDDFFBLLLBRLDDBRURBLBBFUR", - "U D' F' R2 L' B2 R' L' D' L2 F' D' L2 U2 R2 F2 D' R2 F2 D' "), - - ("DDRBUUBUFUBFURLBRFDFRRFRFFULLRDDBLULBDRLLFUFUDRLDBBDLB", - "U' R' B2 R F' R U2 D F2 U2 R' U' R2 U R2 D' B2 L2 F2 D2 "), - - ("BDRLUBDBDFRBFRRBFFRURRFUDDDLLLUDLFDUUUBBLFRRFUBLDBLLFU", - "R2 F D L' D B U' L' D2 R' B' R2 D R2 F2 U' R2 D' F2 U' "), - - ("RFLUUFFDFDRBLRBRBRULLBFFUUFFFDLDDUDDURRBLRBULDDBLBUBRL", - "F2 L B2 U2 B' L' D R' U R' F2 U F2 B2 R2 D' F2 B2 U' F2 "), - - ("DURFULUBUFDFLRFRUBLRLRFBFDBUBUFDRDFRBRBULDFLRDLLDBBDUL", - "U L B2 R2 D' R B D2 F R L F R2 D R2 B2 D2 F2 U' D2 L2 B2 "), - - ("BRDFUBUBULULRRUDFUFRBDFUDFFRDLDDLFLFRULLLRDBBBFULBBRDR", - "F2 R D L B2 U L2 B' R' U D' F' R2 F2 R2 D F2 U2 D B2 R2 U' "), - - ("LFDLUUDRDBBBRRUBFLFFLBFURDUFBRUDDUBFFDRRLLBLURLDFBDURL", - "D' R B L' D R' D2 R F B L' U' R2 U' F2 L2 U' L2 D R2 U2 "), - - ("FUDLUBDLFLRBURFUDLLDUFFLBUFURRBDFRDBRFFDLRBLLRBDUBRDBU", - "F' U D2 B2 L B' U' R2 F2 R' D' L2 U' B2 L2 D' R2 L2 B2 D "), - - ("LUFFUURDFDLURRDBBFUBLUFFBRDDDLLDRRLDBLBBLRUDRLFUFBURBF", - "L F' L2 F D2 R2 L2 B2 U' F U D R2 D' B2 L2 F2 R2 U2 D' "), - - ("URDBUDLLBDFLBRUDLFBDRBFDDURLLFRDBULRBUUDLRLUFBFRFBRUFF", - "B2 U2 L' B' R L2 F B R2 L F' U' B2 U B2 R2 U' R2 F2 B2 L2 "), - - ("RLFDUFFBLDUDBRLDFFLDBUFULLBBDRRDDFURURURLLLBURFBBBFURD", - "U F' R2 F2 U' R F R2 D F2 R' F' D B2 U2 R2 B2 U2 R2 D F2 R2 "), - - ("BRDBUFBFBUURBRRFUUDLLDFDDDRLFULDLBULRURLLRDBFFFUBBDFRL", - "F' D B2 R' L2 U2 B L' F' D L' U R2 U' L2 B2 D2 B2 D2 L2 B2 "), - - ("BRBFUURBFRRDURLBDDFRDFFBBLRUDDLDRUBFRUUFLDLULLFUBBLLDF", - "U F' B R' D B' R U R' F U' L U' B2 U2 L2 U' R2 B2 L2 U F2 "), - - ("FLDRUBBRUBDRBRRLRFDFRDFUUUBFFDDDUULRDDRLLFBLLFULBBFUBL", - "U R F' U' L' F R2 F R' U2 B L' F2 B2 U F2 L2 D L2 D R2 U2 "), - - ("BFRLURUFFLFBBRRDLDLLUDFRULFRDLFDURBRLBBRLBDUFUDDDBUFUB", - "R B' D' L' U R D L' D R2 F D2 F2 D' R2 L2 B2 R2 U' R2 "), - - ("BDFBUUFDLUFDLRUFURDBFLFDUURLBUDDRDLBDRLFLFLRBRFRLBRUBB", - "R L2 U F R2 D2 R' L2 U F' D' L' U' B2 U' L2 U F2 R2 D2 L2 D "), - - ("FDLBUBRLUBUFDRURRBDURFFLLDUDFFRDFDLLDLFRLUBBBUBLRBDUFR", - "U R D' R U' B2 D2 R' B' D' F' L' U L2 D' F2 L2 D F2 U2 L2 U "), - - ("BBFRURDDLBFRDRFDLDFLUDFRFDFLBLUDBRULDURULFBLUURRLBFBBU", - "U' F' D2 B' L' U2 R2 D R D2 R' F2 U L2 F2 D B2 D2 L2 D' R2 "), - - ("BDBBULRBRFBLLRDFFBURUDFUDUULFLUDRRFDDUBLLRFRFUBRLBFLDD", - "U B' L' B L F B D' R L' F R U L2 F2 B2 D F2 D2 R2 U D2 "), - - ("URLBULDDULDBBRLRRFRRBFFLFLFDFDUDUURRBUBBLDLFLDFRUBDUBF", - "U L2 U D2 R' D B2 L F D L2 B' R2 B2 D2 F2 U2 L2 F2 L2 U L2 "), - - ("LDUFULFRURDRLRULBDDFFRFBFBURDBBDUBFLULLDLURRDBFFLBRBUD", - "F' U2 D' F U' F2 U' F D B' L' D2 F2 U R2 U' L2 B2 U' B2 U2 "), - - ("FDBBUDUBRDBLLRFBRRBUFRFULDDUFLFDURLUDRRLLDDUFULLRBFFBB", - "R2 F' R L' U R' U2 F' D2 F R U' R2 U L2 U' B2 L2 U2 D B2 "), - - ("UFBBURLLBRFDBRRFURBDUDFLDBDLDRFDLUBDRUUFLRLDFLLFUBUBRF", - "R D F' L F' L2 B' U' D' R D B' U2 F2 U' L2 B2 U' L2 D R2 L2 "), - - ("DURBULRULBUDRRRLDLDBULFFFBBULDDDRBBFLDFDLFUFRBFFUBLURR", - "F U' R F' R L D2 L' B' D R F2 U' R2 B2 D R2 D2 R2 L2 B2 "), - - ("UFBLURRDLDURRRLUFFFBBFFDULRFFBRDUFBDLBUDLRLBLDDBUBLRUD", - "B U R' D2 R2 D' B2 U' R B' U R2 D2 R2 B2 U F2 D' B2 U' "), - - ("FLBUUDFBDBFURRRUBLLULRFFLLFBDRBDLDRDRLUFLDBDURFDBBUFUR", - "U' D' R' F' R2 U' D2 F U' L U R2 U2 L2 F2 R2 L2 U' F2 D' "), - - ("DRLUUBFBRBLURRLRUBLRDDFDLFUFUFFDBRDUBRUFLLFDDBFLUBLRBD", - "D2 R' D' F2 B D R2 D2 R' F2 D' F2 U' B2 L2 U2 D R2 U "), -] - -if __name__ == '__main__': - - cmd = './solve' - - if len(sys.argv) > 1: - fname = sys.argv[1] - logging.info('loading tests from %s', fname) - with open(fname) as f: - cnt = 0 - t = f.readline() - while t: - logging.info('running test %d...' % (cnt + 1)) - t = t.strip() - r = f.readline().strip() - res = subprocess.check_output([cmd, t], stderr=open(os.devnull, 'wb')).strip() - if res != r: - logging.error('Error for %s:\n\tmust be: %s\n\tgot: %s' % (t, `r`, `res`)) - sys.exit(1) - cnt += 1 - t = f.readline() - logging.info('all %d tests passed' % cnt) - else: - for i, tst in enumerate(javares): - logging.info('running test %d of %d...' % (i + 1, len(javares))) - t, r = tst - res = subprocess.check_output([cmd, t], stderr=open(os.devnull, 'wb')).strip() - if res != r.strip(): - logging.error('Error for %s:\n\tmust be: %s\n\tgot: %s' % (t, `r`, `res`)) - sys.exit(1) - logging.info('all %d tests passed' % len(javares)) diff --git a/javares.txt b/tests/javares.txt similarity index 100% rename from javares.txt rename to tests/javares.txt diff --git a/tests/test_solve.py b/tests/test_solve.py new file mode 100644 index 0000000..e447ca4 --- /dev/null +++ b/tests/test_solve.py @@ -0,0 +1,333 @@ +from kociemba import solve +import pytest + + +# these results were produced by original Kociemba's Java implementation +@pytest.mark.parametrize("input,expected", [ + ("BBURUDBFUFFFRRFUUFLULUFUDLRRDBBDBDBLUDDFLLRRBRLLLBRDDF", + "B U' L' D' R' D' L2 D' L F' L' D F2 R2 U R2 B2 U2 L2 F2 D'"), + + ("FDLUUURLFLBDFRRDLBBBUBFLDDLFBBUDUBRLURDFLRUFRFLRFBDUDR", + "U F' L2 U F' L2 F L2 F2 D L' F' U2 B2 D F2 D' R2 L2 D F2 U'"), + + ("UDRFULDRBLDUBRDUFBFBDRFDFURLBBLDRDURLLRULUFBUFRBFBFDLL", + "F U2 D2 L' F2 D' B R L2 U F U F2 D2 B2 D R2 U2 F2 L2 B2"), + + ("LRLLURRLBDUULRFUFLFDRUFBRBLDUFDDRRBDDFURLLBFFBDBUBBFDU", + "B2 D' R2 F U R F' D2 L' B D F2 R2 L2 U' B2 D2 B2 U B2"), + + ("UUULULFLFDUBDRRDBBUFLFFLBRRLDFFDDBUUFBRRLDRUDLBLFBBRRD", + "U2 F' D F U F' U F2 R' F R' D2 R2 F2 U2 D B2 U2 L2 F2"), + + ("LRRFUUBDLFBBLRDLLRUFDLFURLFBBUBDDDDUDULRLFRRDUUBRBFFBF", + "R' B' D' R' B' L F2 U' D F' R2 L2 U' R2 F2 U R2 U B2 D'"), + + ("FBRDULFBRFBBRRRDLBRRUDFUUDFLBLFDUBFDLLDLLFRRBUUUDBFLUD", + "U F R' D' R' U2 L D B' R L' U' B2 L2 U2 D2 B2 R2 D L2 B2"), + + ("FLBUULFFLFDURRDBUBUUDDFFBRDDBLRDRFLLRLRULFUDRRBDBBBUFL", + "U2 D B' U2 R' D2 L2 D R2 L B' U' L2 D L2 D F2 L2 B2 U'"), + + ("UBLLURBDLDDFRRLRFLDFBLFURFFFLDBDULBUBDRRLBDDUUURUBFBRF", + "U' R2 F U2 R' L' F' L U D' R' U' R2 B2 L2 B2 L2 U2 R2 D' F2"), + + ("UDLFUBLRFRDDLRFDBDBBDDFUUUBFRRLDUFFLBLUFLRRBLFLRUBDBRU", + "U R' L F L' U' F' D R F' L' B2 U L2 B2 D L2 U2 R2 B2 D"), + + ("URBLUBDDBURDLRDLDBFBLLFFULDBBFUDFLRRRURBLDFFRLUFRBUDFU", + "U2 R2 F' R B' D2 B L' B U' R2 B L2 F2 U2 F2 U' R2 D' L2 D R2"), + + ("BLBDUULUDBLRDRFLBUUBLRFFURDLDFRDRRUFRBFLLUFFBDDULBBRFD", + "U2 D2 B' D' F B L2 F2 L D2 L' U F2 U L2 D L2 U2 L2 D F2"), + + ("ULFUUURRURLLLRRUBLDFFLFFBDRURBRDDDFBFBFFLDBBLDBLUBDDUR", + "U2 B2 L2 B' D R U2 B2 L' U D2 F' U F2 L2 U2 D' R2 F2 U2 D' F2"), + + ("LUFBUUUDDLLRDRRDDLBFFFFRUDBLLRRDBRBFDURFLRFUBUFBBBLULD", + "D' L B2 U' F' B U B' R2 D2 R' B2 L2 U R2 U B2 R2 U' F2 D2"), + + ("UDDBURDDBUFLFRLFDFRRLRFLUBRFDUBDFRFLBLBRLUFULBLRUBBDUD", + "U2 B' U' B' R' F2 U' L' F' D B U F2 D2 F2 D F2 R2 U2 F2 D'"), + + ("UUBUUBUDBDRLFRFDUDBBRBFRFBRUUFDDLLDFFRRDLLBRRUFLLBFLLD", + "U2 R' B2 U' F2 D B R F2 R U2 B2 U2 R2 U' F2 U2 R2 D'"), + + ("BDLRULLRRDFFBRLDRLBFFFFUUDBBRRLDURDDLBULLUUBRUBDUBDFFF", + "F2 D' L2 U B' D B L F' B U' L2 D2 L2 B2 U R2 F2 U F2"), + + ("LFRUULBBDBFBDRBLFRDDLLFLFRDRBFDDUBUUURRFLBLRDURFUBDFLU", + "R' D' F' R U' L2 D2 R D L' D' F2 D' R2 U' R2 F2 B2 L2 U2"), + + ("UBBRUDBLFRBRRRUFBBLFDDFFFULUFDDDLBLUFUDBLRLFRDULLBRRDU", + "R' U B R U' R D' R2 L' F' R' F2 R2 U L2 D' B2 U2 L2 D'"), + + ("FRRUUFURDBLFRRFFLUBDLRFBLFUFULLDDBBBULRDLURBDDFRDBBLUD", + "U R2 U F R' B' R F2 D F' L' D' R2 D B2 D' L2 B2 D R2 L2"), + + ("ULDFUBBRRBDLFRBFFLUUDBFLRFDUDRLDUFUDRRLDLUUDBBBFRBRFLL", + "F' B' L' U D B U2 F' B' D2 R' B2 U L2 D' F2 R2 D2 R2 U R2"), + + ("ULLLURFBBDUBBRUBLFURRDFDRFUDRRFDBUULLURRLLLDFDFBBBDDFF", + "U' F2 D2 B2 R2 U B R B U L' B' U B2 D B2 R2 D L2 U D2"), + + ("BDBDURFFRDFDRRLUBLLLFBFURFBBULDDURLDRFURLRUBDLLUUBDFBF", + "U2 B2 U' F' D' R2 U F2 D' L' B R2 B2 U' B2 U' B2 D' B2 R2 U'"), + + ("DRUUUDDBRULLBRBFFLLLBFFDBURLFUUDLRRURRFFLDFLDFDBUBRBBD", + "D F R L B2 L' B U F' D' R U B2 U F2 U B2 U2 F2 U' L2"), + + ("BDLLURUFRDBDRRRDFURLFLFUBFLRDBLDUBBLDDFFLBLUUFBRDBRFUU", + "L' D R' U' B D F D F2 B' R B2 U' L2 U' F2 U D F2 R2 D2"), + + ("RRRUURUUBDDBFRBFLURLRFFRLULDBDLDBLLLDFFULDUDBUBFDBRFFB", + "U D2 R' F' R' U' B R' U' L F2 B2 U2 B2 D' F2 D R2 F2 D2"), + + ("LFRLUUBBLBFUDRRUUFDDUDFFULLBUFLDBLFDFDRBLRBBRFRDUBRRLD", + "F2 R U' F D2 B D B' L U2 R U F2 U2 R2 U2 R2 U' B2 D'"), + + ("FRRBUBDDURLBDRDLUDRLFLFBLBFDUUFDRLUFRRBRLFUUBUDDFBFLLB", + "U2 D F' B' R' D' L B' R B R L2 D2 L2 F2 U B2 R2 B2 D2 F2"), + + ("DBUFUFDFUBLLLRURUBLRRDFBFLDUUBFDRDDLFUFBLLLDRFDRBBRURB", + "F' B' U' B2 D' F L U' B R' D2 L2 U2 F2 D B2 U' F2 U2 L2"), + + ("BFRFUBBLBLRFDRBDUUUBDFFRLFFULLDDRFDRDULLLRRLFDDRUBUBBU", + "L F2 R F' U2 R F' L F R U F2 D2 R2 U R2 L2 B2 D2 F2"), + + ("BFDDURFBRDBLURLBUUDLFRFBDRURURLDLFFFUBLFLDUFBBRLDBDRUL", + "L2 U R2 B L' F L' F' R' L F R2 U2 R2 U F2 U F2 D R2 D2"), + + ("LRBUULRDRDBLLRBDDUFRFDFURLLBFBUDBBFLFBUDLFURDUFDRBLFUR", + "R' B' D' R2 L B' L D L' B' U2 L2 D2 R2 B2 U' L2 D' F2 B2"), + + ("RBBDUBBRRFLDFRFFRRDUUFFUDFULLLLDBBLBDBRDLRLUFLUFDBRUDU", + "U2 F2 U' D2 F U' R B' U L F B2 U D B2 R2 U2 B2 D' F2"), + + ("FRBUURUDBLBRDRLDFDRBDDFLUFFLULDDLBLRLBFFLRUFBDUUUBRFBR", + "D B' U' D' F' U2 F' R F D2 F B2 U D2 F2 R2 D2 L2 F2 D' B2"), + + ("FLURURDBRBDBBRUUUUFLDFFULUFFLRDDRLBRLFRFLLBBDLDUFBDBRD", + "F' U' F2 D2 F2 L' B' R2 U' R F U B2 D L2 D' F2 R2 D L2 U2"), + + ("BULRUULFRDBDDRLUDRULFFFBLUBDRLFDLURBDBFLLDFRBFFRUBBUDR", + "U' F2 R' D2 L2 U2 F' B' R' F' B2 U2 D L2 F2 L2 D' F2 U2 F2"), + + ("FFRRULFBDRFBURLFBUDLBRFFDBRBUUDDDLRLRULRLDULLUDDUBFFBB", + "U F D' B' U D' F L2 U R F' R2 F2 U' R2 F2 D' R2 U D' B2"), + + ("DUFBUDBRDBRUFRURRBDFLLFDDLBLFULDURBLFDRDLBUUFLBRFBLURF", + "U L2 B D' L' U B' R2 L2 D' R F2 B2 R2 U2 B2 U' D2 F2 B2 R2"), + + ("DRRUURBRURUBDRLUBFDBFBFBLFLDRFFDULLDLFRDLLUDBUDFUBLRFB", + "F2 B D2 R B' U2 B2 D2 F' L B2 R2 F2 L2 U' L2 U' R2 B2 U"), + + ("BRLFUDLDRFLUFRUFFLFBURFRUUDFBRUDDRRBRLDLLBDLLBUUFBBDDB", + "F2 D L F' B' L' F2 D F' U' R U F2 L2 F2 L2 F2 U2 L2 U' R2"), + + ("UULFUFDLRFDBBRDBLFLFULFUDDURBRRDDURDFUFLLBBFBDRLRBURBL", + "F' R U B2 D B U2 R' L' F' L' D' F2 R2 U F2 L2 U2 B2 U B2"), + + ("DUDUUUDBUFRFRRBRDUBLLUFDUBFBDDFDLUFFRBLFLFBRRLLBRBDRLL", + "B2 L U B' R' F2 B D2 R2 U2 R' U' R2 D' R2 D' R2 U B2 U' R2"), + + ("LDRLUDRLFURBRRRRDDBBRFFUUBFLUDUDLLBFUFDFLUBLBUBFFBDLRD", + "D F2 R' L2 D' B2 R' D' L B U' F2 R2 B2 R2 F2 U B2 U D"), + + ("FUBUUFLBLURRDRFFUDDUFBFRUBDBLRRDLBFFURBLLDLBRDFRLBDLDU", + "F R' U L B' U' R2 L F D' F' D L2 D B2 U' B2 U2 R2 B2 L2"), + + ("DFRBURUDDLBDRRFUDULLFLFUULFFBRRDRFBRBDBFLUDFLBULDBLBUR", + "U F2 R B' U L' U2 L' U' B2 L F U' R2 D2 F2 R2 D2 B2 D B2 U'"), + + ("RLRUURDLFUFDBRLFRBLFRFFDDLUFULRDUDFLUBFRLULBRBDBBBDUDB", + "U2 F2 D' F' L' F' B' U B' R' L2 B' U' F2 L2 D L2 U' F2 U2 L2 U2"), + + ("BBURULRUULFLBRRBFBDFBFFDFRDUULUDRDDUDBFLLDFBRFLRDBURLL", + "U F D L2 U2 R' L U2 B2 R B' D' R2 D' F2 B2 D F2 D L2 D2"), + + ("LBLLUBUFUBRUURFDLRRLRDFLDFLFRBRDDLBDFBFRLFFDRBUDUBUBDU", + "U L' D2 B U B D2 F R B U2 R' D' R2 U L2 D R2 D2 R2 D2 F2"), + + ("FUFBUBURDFLRDRFBUFLDRFFLBDDDBLFDLURLLUBFLURDRURULBRDBB", + "B' R L F U' B' U L U R' B U L2 U2 L2 F2 U' F2 L2 B2 U2"), + + ("RURFUDDDFLBBFRULUBFFUDFLDLDRBFBDLBDLFRRULRDRBURUBBFULL", + "U' D' R B2 U R2 F2 R' F' L' U' F2 B2 R2 D B2 U2 R2 U2 R2"), + + ("DBRDULBFBUDUDRRULLDRLLFRLBRFUBUDUDDFBFRBLFRFDFLLUBRUBF", + "L' U R2 L F2 D2 B' U' L U2 R2 U D' R2 D' F2 R2 F2"), + + ("URBLUBFDUBRRLRFLULRLRBFFLDDBFFLDRFFBRBDBLUUUUDDFRBDDUL", + "U' R L' F' R' U B R2 U B2 R' F2 R2 B2 U2 D R2 U D2 F2 U2"), + + ("BUULURRDFRURFRBUFUBLDDFLFBFDRRBDRUULLBDRLFBULBFDDBDFLL", + "R D L' U' R2 B' L2 B2 U F' D' R U2 D' F2 R2 F2 D' F2 U L2 D"), + + ("FURBUDLRRUBDFRLBDFBUBFFRUDDRRLDDFULLRUUBLULLFBLDBBRDFF", + "R B' U' F' B2 L2 D2 R' U2 F' L D L2 U2 D' F2 L2 U R2 B2 R2"), + + ("LLRDUBUBBURBBRBLRRRLLLFUBFDDRFFDUULFDFFDLULURUDBDBRDFF", + "R2 L2 U' B' U2 L' B' R L' D2 B D F2 B2 L2 U' F2 D B2 U"), + + ("FDRUUBBBLDRBDRLFFFDUBLFRBURURUFDRFFUDLRFLBDLLUBLDBDLUR", + "U D2 B' U' L' U' F U' B R' D2 L D' B2 U2 R2 D R2 L2 B2"), + + ("FBBDULLFRUBRLRLDFUDRBBFFUURLLFUDDDBLURBFLRFRBDURDBUFDL", + "U R' D L' U2 D L U2 L' D2 F' R D' L2 U2 R2 D' F2 R2 D' F2 D2"), + + ("LLBDURRDURBDLRLRULBBFBFDDBBFUUFDRLFFBRDFLLDDRLUUFBRUUF", + "U2 L' U2 B' R L2 U R' F2 R' B D R2 U2 D R2 F2 D R2 L2 F2"), + + ("LFFDUBLRDLLDURLBDFDUFLFFFDUUBRRDRDBUBLBRLUBBRRDUFBFLUR", + "D2 B2 L' F R' L' B' L2 F2 D' R' U2 B2 D2 B2 D L2 U F2 D' F2"), + + ("FBUDUBBRBUURLRRUFLDBLLFDRFFDLRFDRFUBDBRRLUUDFBLLUBDDFL", + "R2 U R F' U R2 D2 B' R' B' R' U2 F2 D F2 U F2 D2 L2 B2 D'"), + + ("ULBFURBDBDDDFRRBFFUBRLFUFRURBRUDDDLURRLLLFFBDLDFUBULBL", + "F2 L U' R' B2 L' D B2 L B' D' B2 U B2 L2 U B2 L2 D2 R2"), + + ("DUBBUFLFFLRLDRBBLRDUUDFLLRRFBDDDURRUFLBFLRBFDUBRDBLFUU", + "D' F' D' L' F2 D F D2 R' L2 D2 R2 D B2 D B2 L2 U R2"), + + ("BRDFUUUUULBFDRDDDFRLBUFRLBBUDRFDLBLDRRFBLFDLFLUUFBRRBL", + "L' U R' F B2 D F R B R L2 D R2 U2 F2 R2 B2 R2 U R2"), + + ("DBRLUFFUBDLFBRFLBLLFRFFUBLBRUDDDDFUULDUBLRRRUDLFDBRBRU", + "R2 B2 R' L' F2 R2 B' D L U B D B2 R2 D' R2 D B2 D2 F2"), + + ("LLURULDUDLBLURBBRFRFFRFLFRURBRFDDBBRDFBFLULDDFDBUBLUDU", + "U F D' R' B' U R' F' D' F U2 L B2 U2 D L2 F2 L2 U F2 L2 U"), + + ("UFLRULBLUBUBBRFRDFDFRBFLFUFLRDDDRBBLRFRBLULLUDDFUBDDRU", + "U R L' D2 B' L F2 U F L2 U2 L D' R2 D2 R2 B2 U' L2 F2 D' L2"), + + ("BRRLUFBFFLRFDRUDLURDUFFRULFRDLRDUDBBLFULLUBUFDBDBBBLDR", + "U' D' F D' B' L2 F' R D' F B R2 F2 R2 D' R2 F2 U2 D R2 F2"), + + ("DRDUUBRRLBLLRRLUFDUFULFBFDLULFDDUDBBFRBDLUFFRBDRFBBRUL", + "L' B R D' L B R D' F2 U2 F L2 F2 U B2 D F2 R2 D' B2 D2"), + + ("LLFLUBRURDLUFRDRURUBFRFULBDDRBRDRLDUBUBDLDDFBLFUBBFFLF", + "L B' R' U' F L U D2 B' R B2 R2 F2 D2 B2 U2 D B2 L2 U2"), + + ("LLBRUFUBBUURURDLLRBDLRFBBLFLUUDDFRRFFDRRLFUFDDBDLBBDUF", + "F L' U D B' L' U' D R' U2 F' D2 R2 U2 L2 F2 U L2 B2 L2 U"), + + ("FLLUUULLULBDRRFUFDUDBBFBBFRLRBBDURDBURFDLLFDDFURLBRRFD", + "F2 B2 U2 B' U F2 D2 F B2 R F R2 U R2 D R2 L2 B2 U F2 D2"), + + ("FURFUDBUDFLBFRBDRDUBRBFRULBFFRBDULDFUULRLRBDLULRLBDLFD", + "U R L D R B U D F2 B2 R' U L2 B2 R2 U F2 D R2 B2 U'"), + + ("BFFBUFUBFDRDDRDFRDBRLFFBBDUDLLBDUUFLUURLLLFLRRDLRBUBUR", + "F' B' U2 R' F' B2 R' F2 L U' R U' B2 L2 D L2 D B2 D' F2 D"), + + ("UFFDUULUUBFRLRFLDUDLRRFBBRDDUFDDFFBLLLBRLDDBRURBLBBFUR", + "U D' F' R2 L' B2 R' L' D' L2 F' D' L2 U2 R2 F2 D' R2 F2 D'"), + + ("DDRBUUBUFUBFURLBRFDFRRFRFFULLRDDBLULBDRLLFUFUDRLDBBDLB", + "U' R' B2 R F' R U2 D F2 U2 R' U' R2 U R2 D' B2 L2 F2 D2"), + + ("BDRLUBDBDFRBFRRBFFRURRFUDDDLLLUDLFDUUUBBLFRRFUBLDBLLFU", + "R2 F D L' D B U' L' D2 R' B' R2 D R2 F2 U' R2 D' F2 U'"), + + ("RFLUUFFDFDRBLRBRBRULLBFFUUFFFDLDDUDDURRBLRBULDDBLBUBRL", + "F2 L B2 U2 B' L' D R' U R' F2 U F2 B2 R2 D' F2 B2 U' F2"), + + ("DURFULUBUFDFLRFRUBLRLRFBFDBUBUFDRDFRBRBULDFLRDLLDBBDUL", + "U L B2 R2 D' R B D2 F R L F R2 D R2 B2 D2 F2 U' D2 L2 B2"), + + ("BRDFUBUBULULRRUDFUFRBDFUDFFRDLDDLFLFRULLLRDBBBFULBBRDR", + "F2 R D L B2 U L2 B' R' U D' F' R2 F2 R2 D F2 U2 D B2 R2 U'"), + + ("LFDLUUDRDBBBRRUBFLFFLBFURDUFBRUDDUBFFDRRLLBLURLDFBDURL", + "D' R B L' D R' D2 R F B L' U' R2 U' F2 L2 U' L2 D R2 U2"), + + ("FUDLUBDLFLRBURFUDLLDUFFLBUFURRBDFRDBRFFDLRBLLRBDUBRDBU", + "F' U D2 B2 L B' U' R2 F2 R' D' L2 U' B2 L2 D' R2 L2 B2 D"), + + ("LUFFUURDFDLURRDBBFUBLUFFBRDDDLLDRRLDBLBBLRUDRLFUFBURBF", + "L F' L2 F D2 R2 L2 B2 U' F U D R2 D' B2 L2 F2 R2 U2 D'"), + + ("URDBUDLLBDFLBRUDLFBDRBFDDURLLFRDBULRBUUDLRLUFBFRFBRUFF", + "B2 U2 L' B' R L2 F B R2 L F' U' B2 U B2 R2 U' R2 F2 B2 L2"), + + ("RLFDUFFBLDUDBRLDFFLDBUFULLBBDRRDDFURURURLLLBURFBBBFURD", + "U F' R2 F2 U' R F R2 D F2 R' F' D B2 U2 R2 B2 U2 R2 D F2 R2"), + + ("BRDBUFBFBUURBRRFUUDLLDFDDDRLFULDLBULRURLLRDBFFFUBBDFRL", + "F' D B2 R' L2 U2 B L' F' D L' U R2 U' L2 B2 D2 B2 D2 L2 B2"), + + ("BRBFUURBFRRDURLBDDFRDFFBBLRUDDLDRUBFRUUFLDLULLFUBBLLDF", + "U F' B R' D B' R U R' F U' L U' B2 U2 L2 U' R2 B2 L2 U F2"), + + ("FLDRUBBRUBDRBRRLRFDFRDFUUUBFFDDDUULRDDRLLFBLLFULBBFUBL", + "U R F' U' L' F R2 F R' U2 B L' F2 B2 U F2 L2 D L2 D R2 U2"), + + ("BFRLURUFFLFBBRRDLDLLUDFRULFRDLFDURBRLBBRLBDUFUDDDBUFUB", + "R B' D' L' U R D L' D R2 F D2 F2 D' R2 L2 B2 R2 U' R2"), + + ("BDFBUUFDLUFDLRUFURDBFLFDUURLBUDDRDLBDRLFLFLRBRFRLBRUBB", + "R L2 U F R2 D2 R' L2 U F' D' L' U' B2 U' L2 U F2 R2 D2 L2 D"), + + ("FDLBUBRLUBUFDRURRBDURFFLLDUDFFRDFDLLDLFRLUBBBUBLRBDUFR", + "U R D' R U' B2 D2 R' B' D' F' L' U L2 D' F2 L2 D F2 U2 L2 U"), + + ("BBFRURDDLBFRDRFDLDFLUDFRFDFLBLUDBRULDURULFBLUURRLBFBBU", + "U' F' D2 B' L' U2 R2 D R D2 R' F2 U L2 F2 D B2 D2 L2 D' R2"), + + ("BDBBULRBRFBLLRDFFBURUDFUDUULFLUDRRFDDUBLLRFRFUBRLBFLDD", + "U B' L' B L F B D' R L' F R U L2 F2 B2 D F2 D2 R2 U D2"), + + ("URLBULDDULDBBRLRRFRRBFFLFLFDFDUDUURRBUBBLDLFLDFRUBDUBF", + "U L2 U D2 R' D B2 L F D L2 B' R2 B2 D2 F2 U2 L2 F2 L2 U L2"), + + ("LDUFULFRURDRLRULBDDFFRFBFBURDBBDUBFLULLDLURRDBFFLBRBUD", + "F' U2 D' F U' F2 U' F D B' L' D2 F2 U R2 U' L2 B2 U' B2 U2"), + + ("FDBBUDUBRDBLLRFBRRBUFRFULDDUFLFDURLUDRRLLDDUFULLRBFFBB", + "R2 F' R L' U R' U2 F' D2 F R U' R2 U L2 U' B2 L2 U2 D B2"), + + ("UFBBURLLBRFDBRRFURBDUDFLDBDLDRFDLUBDRUUFLRLDFLLFUBUBRF", + "R D F' L F' L2 B' U' D' R D B' U2 F2 U' L2 B2 U' L2 D R2 L2"), + + ("DURBULRULBUDRRRLDLDBULFFFBBULDDDRBBFLDFDLFUFRBFFUBLURR", + "F U' R F' R L D2 L' B' D R F2 U' R2 B2 D R2 D2 R2 L2 B2"), + + ("UFBLURRDLDURRRLUFFFBBFFDULRFFBRDUFBDLBUDLRLBLDDBUBLRUD", + "B U R' D2 R2 D' B2 U' R B' U R2 D2 R2 B2 U F2 D' B2 U'"), + + ("FLBUUDFBDBFURRRUBLLULRFFLLFBDRBDLDRDRLUFLDBDURFDBBUFUR", + "U' D' R' F' R2 U' D2 F U' L U R2 U2 L2 F2 R2 L2 U' F2 D'"), + + ("DRLUUBFBRBLURRLRUBLRDDFDLFUFUFFDBRDUBRUFLLFDDBFLUBLRBD", + "D2 R' D' F2 B D R2 D2 R' F2 D' F2 U' B2 L2 U2 D R2 U"), +]) +def test_solve_function(input, expected): + assert solve(input) == expected + + +if __name__ == '__main__': + import sys + import logging + logging.basicConfig(level=logging.DEBUG, format='%(asctime)s - %(levelname)s - %(message)s') + if len(sys.argv) > 1: + fname = sys.argv[1] + logging.info('loading tests from %s', fname) + with open(fname, 'rb') as f: + cnt = 0 + t = f.readline() + while t: + logging.info('running test %d...' % (cnt + 1)) + t = t.strip() + r = f.readline().strip() + res = solve(t) + if res != r: + logging.error('Error for %s:\n\tmust be: %s\n\tgot: %s' % (t, repr(r), repr(res))) + sys.exit(1) + cnt += 1 + t = f.readline() + logging.info('all %d tests passed' % cnt) + else: + logging.error('Usage: %s ', sys.argv[0])