Skip to content

Commit

Permalink
Merge branch 'release/1.1'
Browse files Browse the repository at this point in the history
  • Loading branch information
muodov committed Jun 6, 2016
2 parents 18c34d2 + 528d853 commit 0e552b7
Show file tree
Hide file tree
Showing 20 changed files with 294 additions and 194 deletions.
9 changes: 8 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,19 @@ This package is published on PyPI and can be installed with:

It was tested under Python 2.7 and 3.5.

The package exposes just one function ```solve()```, which accepts a cube definition string and returns a solution string in standard notation (see below):
On some systems you might need to install libffi system library beforehand. For example, on Debian-based distributions (e.g. Raspbian) you would run `sudo apt-get install libffi-dev`.

The package exposes just one function ```solve()```, which accepts a cube definition string and returns a solution string in standard notation (see below).
Optional second argument allows solving to a specific pattern.

```python
>>> import kociemba

>>> kociemba.solve('DRLUUBFBRBLURRLRUBLRDDFDLFUFUFFDBRDUBRUFLLFDDBFLUBLRBD')
u"D2 R' D' F2 B D R2 D2 R' F2 D' F2 U' B2 L2 U2 D R2 U"

>>> kociemba.solve('FLBUULFFLFDURRDBUBUUDDFFBRDDBLRDRFLLRLRULFUDRRBDBBBUFL', 'BBURUDBFUFFFRRFUUFLULUFUDLRRDBBDBDBLUDDFLLRRBRLLLBRDDF')
u"R' D2 R' U2 R F2 D B2 U' R F' U R2 D L2 D' B2 R2 B2 U' B2"
```

## Standalone tool
Expand Down
18 changes: 12 additions & 6 deletions kociemba/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,9 @@ class SlowContextWarning(Warning):
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'))
def _solve(cube, pattern):
pattern_utf8 = pattern.encode('utf-8') if pattern is not None else ffi.NULL
res = lib.solve(cube.encode('utf-8'), pattern_utf8, cache_dir.encode('utf-8'))
if res != ffi.NULL:
return ffi.string(res).strip().decode('utf-8')
else:
Expand All @@ -26,7 +27,7 @@ def _solve(s):
SlowContextWarning)
from .pykociemba import search

def _solve(s):
def _solve(cube, pattern):
errors = {
'Error 1': 'There is not exactly one facelet of each colour',
'Error 2': 'Not all 12 edges exist exactly once',
Expand All @@ -37,21 +38,26 @@ def _solve(s):
'Error 7': 'No solution exists for the given maxDepth',
'Error 8': 'Timeout, no solution within given time'
}
res = search.Search().solution(s, 24, 1000, False).strip()
if pattern is not None:
cube = search.patternize(cube, pattern)
res = search.Search().solution(cube, 24, 1000, False).strip()
if res in errors:
raise ValueError(errors[res])
else:
return res


def solve(cubestring):
def solve(cubestring, patternstring=None):
"""
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'"
>>> kociemba.solve('FLBUULFFLFDURRDBUBUUDDFFBRDDBLRDRFLLRLRULFUDRRBDBBBUFL', 'BBURUDBFUFFFRRFUUFLULUFUDLRRDBBDBDBLUDDFLLRRBRLLLBRDDF')
u"R' D2 R' U2 R F2 D B2 U' R F' U R2 D L2 D' B2 R2 B2 U' B2"
"""

return _solve(cubestring)
return _solve(cubestring, patternstring)

__all__ = ['solve']
12 changes: 9 additions & 3 deletions kociemba/build_ckociemba.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,14 @@
#include <stdlib.h>
#include <search.h>
char* solve(char *cubestring, char *cache_dir)
char* solve(char *cubestring, char *patternstring, char *cache_dir)
{
char patternized[64];
if (patternstring) {
patternize(cubestring, patternstring, patternized);
cubestring = patternized;
}
char *sol = solution(
cubestring,
24,
Expand All @@ -26,9 +32,9 @@
'kociemba/ckociemba/cubiecube.c',
'kociemba/ckociemba/facecube.c',
'kociemba/ckociemba/search.c'],
extra_compile_args=['-std=c99'])
extra_compile_args=['-std=c99', '-O3', '-D_XOPEN_SOURCE=700'])

ffi.cdef("char* solve(char *cubestring, char *cache_dir);")
ffi.cdef("char* solve(char *cubestring, char *patternstring, char *cache_dir);")

if __name__ == "__main__":
ffi.compile(verbose=True)
2 changes: 1 addition & 1 deletion kociemba/ckociemba/Makefile
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
CKOCIEMBA_SRC = coordcube.c cubiecube.c facecube.c search.c
CKOCIEMBA_INCLUDE = include
CFLAGS = -std=c99
CFLAGS = -std=c99 -O3
BINDIR = bin
BIN = kociemba

Expand Down
35 changes: 18 additions & 17 deletions kociemba/ckociemba/coordcube.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,10 @@ 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};
char Slice_Flip_Prun[N_SLICE1 * N_FLIP / 2] = {0};
signed char Slice_URFtoDLF_Parity_Prun[N_SLICE2 * N_URFtoDLF * N_PARITY / 2] = {0};
signed char Slice_URtoDF_Parity_Prun[N_SLICE2 * N_URtoDF * N_PARITY / 2] = {0};
signed char Slice_Twist_Prun[N_SLICE1 * N_TWIST / 2 + 1] = {0};
signed char Slice_Flip_Prun[N_SLICE1 * N_FLIP / 2] = {0};

int PRUNING_INITED = 0;

Expand All @@ -46,7 +46,7 @@ void move(coordcube_t* coordcube, int m, const char *cache_dir)

char * join_path(const char *dir, const char *filename)
{
int path_len = strnlen(dir, 200);
size_t path_len = strnlen(dir, 200);
if (path_len == 200) {
return NULL;
}
Expand Down Expand Up @@ -81,7 +81,8 @@ int check_cached_table(const char* name, void* ptr, int len, const char *cache_d
void read_from_file(void* ptr, int len, const char* name)
{
FILE* f = fopen(name, "r");
fread(ptr, len, 1, f);
if (!fread(ptr, len, 1, f))
((void)0); // suppress -Wunused-result warning
fclose(f);
}

Expand Down Expand Up @@ -256,7 +257,7 @@ void initPruning(const char *cache_dir)
for (int i = 0; i < N_SLICE2 * N_URFtoDLF * N_PARITY / 2; i++)
Slice_URFtoDLF_Parity_Prun[i] = -1;
depth = 0;
setPruning(Slice_URFtoDLF_Parity_Prun, 0, (char) 0);
setPruning(Slice_URFtoDLF_Parity_Prun, 0, 0);
done = 1;
while (done != N_SLICE2 * N_URFtoDLF * N_PARITY) {
for (int i = 0; i < N_SLICE2 * N_URFtoDLF * N_PARITY; i++) {
Expand Down Expand Up @@ -284,7 +285,7 @@ void initPruning(const char *cache_dir)
newParity = parityMove[parity][j];
if (getPruning(Slice_URFtoDLF_Parity_Prun, (N_SLICE2 * newURFtoDLF + newSlice) * 2 + newParity) == 0x0f) {
setPruning(Slice_URFtoDLF_Parity_Prun, (N_SLICE2 * newURFtoDLF + newSlice) * 2 + newParity,
(char) (depth + 1));
(signed char) (depth + 1));
done++;
}
}
Expand All @@ -300,7 +301,7 @@ void initPruning(const char *cache_dir)
for (int i = 0; i < N_SLICE2 * N_URtoDF * N_PARITY / 2; i++)
Slice_URtoDF_Parity_Prun[i] = -1;
depth = 0;
setPruning(Slice_URtoDF_Parity_Prun, 0, (char) 0);
setPruning(Slice_URtoDF_Parity_Prun, 0, 0);
done = 1;
while (done != N_SLICE2 * N_URtoDF * N_PARITY) {
for (int i = 0; i < N_SLICE2 * N_URtoDF * N_PARITY; i++) {
Expand Down Expand Up @@ -328,7 +329,7 @@ void initPruning(const char *cache_dir)
newParity = parityMove[parity][j];
if (getPruning(Slice_URtoDF_Parity_Prun, (N_SLICE2 * newURtoDF + newSlice) * 2 + newParity) == 0x0f) {
setPruning(Slice_URtoDF_Parity_Prun, (N_SLICE2 * newURtoDF + newSlice) * 2 + newParity,
(char) (depth + 1));
(signed char) (depth + 1));
done++;
}
}
Expand All @@ -344,7 +345,7 @@ void initPruning(const char *cache_dir)
for (int i = 0; i < N_SLICE1 * N_TWIST / 2 + 1; i++)
Slice_Twist_Prun[i] = -1;
depth = 0;
setPruning(Slice_Twist_Prun, 0, (char) 0);
setPruning(Slice_Twist_Prun, 0, 0);
done = 1;
while (done != N_SLICE1 * N_TWIST) {
for (int i = 0; i < N_SLICE1 * N_TWIST; i++) {
Expand All @@ -354,7 +355,7 @@ void initPruning(const char *cache_dir)
int newSlice = FRtoBR_Move[slice * 24][j] / 24;
int newTwist = twistMove[twist][j];
if (getPruning(Slice_Twist_Prun, N_SLICE1 * newTwist + newSlice) == 0x0f) {
setPruning(Slice_Twist_Prun, N_SLICE1 * newTwist + newSlice, (char) (depth + 1));
setPruning(Slice_Twist_Prun, N_SLICE1 * newTwist + newSlice, (signed char) (depth + 1));
done++;
}
}
Expand All @@ -369,7 +370,7 @@ void initPruning(const char *cache_dir)
for (int i = 0; i < N_SLICE1 * N_FLIP / 2; i++)
Slice_Flip_Prun[i] = -1;
depth = 0;
setPruning(Slice_Flip_Prun, 0, (char) 0);
setPruning(Slice_Flip_Prun, 0, 0);
done = 1;
while (done != N_SLICE1 * N_FLIP) {
for (int i = 0; i < N_SLICE1 * N_FLIP; i++) {
Expand All @@ -379,7 +380,7 @@ void initPruning(const char *cache_dir)
int newSlice = FRtoBR_Move[slice * 24][j] / 24;
int newFlip = flipMove[flip][j];
if (getPruning(Slice_Flip_Prun, N_SLICE1 * newFlip + newSlice) == 0x0f) {
setPruning(Slice_Flip_Prun, N_SLICE1 * newFlip + newSlice, (char) (depth + 1));
setPruning(Slice_Flip_Prun, N_SLICE1 * newFlip + newSlice, (signed char) (depth + 1));
done++;
}
}
Expand All @@ -393,16 +394,16 @@ void initPruning(const char *cache_dir)
PRUNING_INITED = 1;
}

void setPruning(char *table, int index, char value) {
void setPruning(signed char *table, int index, signed char value) {
if ((index & 1) == 0)
table[index / 2] &= 0xf0 | value;
else
table[index / 2] &= 0x0f | (value << 4);
}

// Extract pruning value
char getPruning(char *table, int index) {
char res;
signed char getPruning(signed char *table, int index) {
signed char res;

if ((index & 1) == 0)
res = (table[index / 2] & 0x0f);
Expand Down
Loading

0 comments on commit 0e552b7

Please sign in to comment.