Skip to main content

rubik-solver-py

A pure-Python implementation of Kociemba's two-phase algorithm for solving the Rubik's Cube optimally (≤22 moves). Port of the TypeScript rubik-solver library.

Installation

pip install rubik-solver-py

Quick Start

from rubik_solver import Cube, init_solver, solve, scramble

# init_solver() pre-computes move and pruning tables (~30-60 s, one-time cost).
# Call it once at application startup before solving anything.
init_solver()

# Solve from a move sequence
cube = Cube().move("R U R' U' R' F R2 U' R' U' R U R' F'")
solution = solve(cube)
print(solution)  # e.g. "F R U R' U' F'"

# Generate a random scramble
print(scramble())

API Reference

init_solver()

Pre-computes all move and pruning tables required by the solver.

Must be called once before solve() or scramble().

Safe to call multiple times — subsequent calls are no-ops.


solve(cube, max_depth=22) → str | None

Solves the given Cube instance using Kociemba's two-phase algorithm.

Parameter Type Default Description
cube Cube — The cube to solve
max_depth int 22 Maximum move count; returns Noneif exceeded

Returns a move string like "R U R' U'", or None if no solution was found.


scramble() → str

Returns a random scramble sequence as a move string.


Cube

The main cube class.

Method / Property Description
Cube() Creates a solved cube
.move(alg) Applies an algorithm string in place; returns self
.clone() Returns a deep copy
.is_solved() Returns Trueif the cube is solved
.as_string() Returns the 54-char facelet string
.randomize() Randomizes the cube in place; returns self
.verify() Returns Trueif valid, or an error string
Cube.from_string(s) Parses a 54-char facelet string into a Cube
Cube.random() Returns a new randomized Cube
Cube.inverse(alg) Inverts an algorithm string

Supported Move Notation

Faces: U R F D L B

Slice moves: E M S

Rotations: x y z

Wide moves: u r f d l b

Modifiers: ' (inverse), 2 (double)


Usage Examples

Build and verify a cube manually

from rubik_solver import Cube

# Solved cube
cube = Cube()
print(cube.is_solved())    # True

# Apply moves
cube.move("R U R' U'")
print(cube.is_solved())    # False

# Serialize to 54-char facelet string
print(cube.as_string())
# "UUUUUUUUURRRRRRRRRFFFFFFFFFDDDDDDDDDLLLLLLLLLBBBBBBBBB"

# Parse from a facelet string
cube2 = Cube.from_string("UUUUUUUUURRRRRRRRRFFFFFFFFFDDDDDDDDDLLLLLLLLLBBBBBBBBB")

# Invert an algorithm
print(Cube.inverse("R U R' U'"))  # "U R U' R'"

Solve a random cube

from rubik_solver import Cube, init_solver, solve

init_solver()
cube = Cube.random()
solution = solve(cube)
print(f"Solution ({len(solution.split())} moves): {solution}")

Validate a cube from facelet string

from rubik_solver import Cube

cube = Cube.from_string("UUUUUUUUURRRRRRRRRFFFFFFFFFDDDDDDDDDLLLLLLLLLBBBBBBBBB")
result = cube.verify()
if result is True:
    print("Cube is valid!")
else:
    print(f"Invalid: {result}")

Architecture

rubik_solver/
├── __init__.py        ← Public API exports
├── types.py           ← Enums (Center, Corner, Edge) and CubeState dataclass
├── constants.py       ← Table sizes, facelet mappings, base move data
├── math_utils.py      ← cnk, factorial, rotate_left, rotate_right
├── cube.py            ← Cube class (core logic, coordinates, serialization)
├── tables/
│   └── tables.py      ← Move table and pruning table generation
└── solver/
    ├── search_state.py ← SearchState used in phase 1 & 2 search
    └── solver.py       ← init_solver(), solve(), scramble(), two-phase search

Performance

Scenario Time
init_solver()— first ever call ~8 s (builds NumPy tables, writes cache)
init_solver()— subsequent calls ~15 ms (loads from ~/.cache/rubik_solver/)
solve()per cube ~0.1 – 1 s
scramble() ~0.5 – 2 s

Tables are cached automatically as .npy files. You can override the cache directory:

export RUBIK_SOLVER_CACHE_DIR=/path/to/your/cache

To force a rebuild:

from rubik_solver import clear_cache, init_solver
clear_cache()
init_solver(verbose=True)  # prints progress

Why not 10 ms like JavaScript?

V8 JIT-compiles the table construction loops. Python uses NumPy for vectorised BFS (fast) but the coordinate-computation inner loop still runs in CPython. The disk cache makes the difference negligible in practice — after the first run startup is ~15 ms regardless.

License

MIT

Metadata

Release files for rubik-solver-py 0.1.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for rubik-solver-py 0.1.1
File Size Uploaded
rubik_solver_py-0.1.1.tar.gz 15.7 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for rubik-solver-py 0.1.1
File Interpreter ABI Platform
rubik_solver_py-0.1.1-py3-none-any.whl Python 3 none any Details

Total release size: 33.2 kB

Release files / rubik_solver_py-0.1.1.tar.gz

Download URL rubik_solver_py-0.1.1.tar.gz
Size 15.7 kB
Tags Source
SHA-256 checksum
How to use checksums
c604a3b7455095aa3bb5a6f76162f28f2c626713794fa0f43b544f02b6acebe7
BLAKE2b-256 checksum
How to use checksums
f06848deb6786e8c92e927f7108716c163bc63582a5ca3e8a57b413517b2ba01
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.1.0 CPython/3.13.7

Release files / rubik_solver_py-0.1.1-py3-none-any.whl

Download URL rubik_solver_py-0.1.1-py3-none-any.whl
Size 17.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
461ac3c3fdf2aca63f70c3b00c36ec155f3c414d2a6cab5c0ae7b0d2cdecb1cc
BLAKE2b-256 checksum
How to use checksums
c445107563e3a2d2dee6405e059a7568b76dfde92ecbb64a7fb14f16f7b0b943
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.1.0 CPython/3.13.7

Release history Release notifications | RSS feed

This release

0.1.1 This release

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page