Skip to main content

Python module providing tools manipulating cubing algorithms.

Project description

Cubing Algs

Python module providing comprehensive tools for Rubik's cube algorithm manipulation, analysis, and simulation.

Installation

pip install cubing-algs

Features

  • Dual Representation System: Work with both facelet (visual) and cubie (mathematical) representations
  • Algorithm Analysis: Comprehensive metrics, impact analysis, ergonomics, and structure detection
  • Powerful Transformations: Invert, rotate, compress, and compose algorithms with a clean pipeline API
  • Virtual Cube Simulation: Full 3x3x3 cube state tracking with orientation support
  • Advanced Notation: Commutators [A, B], conjugates [A: B], wide moves, slice moves, rotations
  • Pattern Library: 70+ classic cube patterns (Superflip, Checkerboard, etc.)
  • Scramble Generation: Smart scrambles for 2x2x2 through 7x7x7+ cubes
  • Big Cube Support: Multi-layer notation for larger cubes
  • Performance Optimized: C extension for move execution, LRU caching for conversions

Quick Start

from cubing_algs import Algorithm, VCube

# Parse a classic algorithm
sexy_move = Algorithm.parse_moves("R U R' U'")

# Analyze it
print(f"Moves: {sexy_move.metrics.htm} HTM")        # 4 HTM
print(f"Pattern: {sexy_move.structure.compressed}") # [R, U] (commutator)
print(f"Cycles: {sexy_move.cycles}")                # 6 (repeats 6 times to solve)
print(f"Comfort: {sexy_move.ergonomics.comfort_rating}")  # Execution difficulty

# Test on virtual cube
cube = VCube()
cube.rotate(sexy_move)
cube.show()  # Display the result
print(f"Solved: {cube.is_solved}")  # False

Core Concepts

Dual Representation System

This library uses two complementary representations of cube state:

Facelet Representation (54-character string):

  • Visual representation of all 54 stickers on the cube
  • Format: UUUUUUUUURRRRRRRRRFFFFFFFFFDDDDDDDDDLLLLLLLLLBBBBBBBBB
  • Position 0-53 represent: U face (0-8), R face (9-17), F (18-26), D (27-35), L (36-44), B (45-53)
  • Based on the Kociemba facelet format, widely used in cube solving algorithms
  • Used for visualization, display, and move execution (via optimized C extension)

Cubie Representation (permutation + orientation arrays):

cp = [0,1,2,3,4,5,6,7]           # Corner Permutation (8 corners)
co = [0,0,0,0,0,0,0,0]           # Corner Orientation (0, 1, or 2)
ep = [0,1,2,3,4,5,6,7,8,9,10,11] # Edge Permutation (12 edges)
eo = [0,0,0,0,0,0,0,0,0,0,0,0]   # Edge Orientation (0 or 1)
so = [0,1,2,3,4,5]               # Spatial Orientation (6 centers)
  • Mathematical representation for analysis and group theory operations
  • Used for integrity checking and advanced analysis

Both representations can be converted bidirectionally with caching for performance.

Parsing

Parse a string of moves into an Algorithm object:

from cubing_algs.parsing import parse_moves

# Basic parsing
algo = parse_moves("R U R' U'")

# Parsing multiple formats
algo = parse_moves("R U R` U`")       # Backtick notation
algo = parse_moves("R:U:R':U'")       # With colons
algo = parse_moves("R(U)R'[U']")      # With brackets/parentheses
algo = parse_moves("3Rw 3-4u' 2R2")   # For big cubes

# Parse CFOP style (removes starting/ending U/y rotations)
from cubing_algs.parsing import parse_moves_cfop
algo = parse_moves_cfop("y U R U R' U'")  # Will remove the initial y

Commutators and Conjugates

The module supports advanced notation for commutators and conjugates:

from cubing_algs.parsing import parse_moves

# Commutator notation [A, B] = A B A' B'
algo = parse_moves("[R, U]")  # Expands to: R U R' U'

# Conjugate notation [A: B] = A B A'
algo = parse_moves("[R: U]")  # Expands to: R U R'

# Nested commutators and conjugates
algo = parse_moves("[R, [U, D]]")  # Nested commutator
algo = parse_moves("[R: [U, D]]")  # Conjugate with commutator

# Complex examples
algo = parse_moves("[R U: F]")     # R U F U' R'
algo = parse_moves("[R, U D']")    # R U D' R' D U'

Supported notation:

  • [A, B] - Commutator: expands to A B A' B'
  • [A: B] - Conjugate: expands to A B A'
  • Nested brackets are fully supported
  • Can be mixed with regular move notation

Transformations

Apply various transformations to algorithms using the transform pipeline:

from cubing_algs.parsing import parse_moves
from cubing_algs.transform.invert import invert_moves
from cubing_algs.transform.size import compress_moves, expand_moves
from cubing_algs.transform.symmetry import symmetry_m_moves

algo = parse_moves("R U R' U'")

# Invert an algorithm
inverse = algo.transform(invert_moves)  # U R U' R'

# Compression (optimize with cancellations)
compressed = parse_moves("R R U U U").transform(compress_moves)  # R2 U'

# Expansion (convert double moves to single pairs)
expanded = parse_moves("R2 U'").transform(expand_moves)  # R R U'

# Chain multiple transformations
result = algo.transform(invert_moves, compress_moves, symmetry_m_moves)

# Transform until fixed point (apply repeatedly until stable)
messy = parse_moves("R R F F' R2 U F2")
clean = messy.transform(compress_moves, to_fixpoint=True)  # U F2

Available Transformations

Basic transformations:

  • invert_moves - Invert moves
  • compress_moves - Optimize with move cancellations (R R → R2, R R' → ∅)
  • expand_moves - Convert double moves to pairs (R2 → R R)

Notation conversions:

  • sign_moves - Convert to SiGN notation (Rw → r)
  • unsign_moves - Convert to standard notation (r → Rw)
  • translate_moves - Translate between notation systems
  • translate_pov_moves - Translate point-of-view notation

Rotations:

  • remove_rotations - Remove all rotation moves
  • remove_starting_rotations - Remove leading rotation moves
  • remove_ending_rotations - Remove trailing rotation moves
  • compress_ending_rotations - Compress rotations at end (x x → x2)
  • unwide_rotation_moves - Expand wide moves (r → R M' x)
  • rewide_moves - Combine to wide moves (R M' x → r)

Slice moves:

  • unslice_wide_moves - Expand slice moves (M → r' R)
  • unslice_rotation_moves - Expand slice to rotation moves
  • reslice_moves - Combine to slice moves (L' R → M x)
  • reslice_m_moves, reslice_s_moves, reslice_e_moves - Reslice specific axes

Symmetries:

  • symmetry_m_moves - M-slice symmetry (L ↔ R)
  • symmetry_s_moves - S-slice symmetry (F ↔ B)
  • symmetry_e_moves - E-slice symmetry (U ↔ D)
  • symmetry_c_moves - Combined M and S symmetry

Viewpoint/Offset:

  • offset_x_moves, offset_y_moves, offset_z_moves - Change viewpoint (90° rotation)
  • offset_x2_moves, offset_y2_moves, offset_z2_moves - Change viewpoint (180° rotation)
  • offset_xprime_moves, offset_yprime_moves, offset_zprime_moves - Change viewpoint (-90° rotation)

Degrip (move rotations to end):

  • degrip_x_moves, degrip_y_moves, degrip_z_moves - Move specific axis rotations to end
  • degrip_full_moves - Move all rotations to the end

AUF (Adjust U Face):

  • remove_auf_moves - Remove AUF moves from algorithm

Timing:

  • untime_moves - Remove timing notation (@200ms, etc.)
  • pause_moves - Add pause moves
  • unpause_moves - Remove pause moves (.)

Trimming:

  • trim_moves - Remove setup and undo moves

Optimization:

  • optimize_repeat_three_moves - R R R → R'
  • optimize_do_undo_moves - R R' → (empty)
  • optimize_double_moves - R R → R2
  • optimize_triple_moves - R R2 → R'

See the Transformations section for import examples.

Metrics

Compute algorithm metrics:

from cubing_algs.parsing import parse_moves

algo = parse_moves("R U R' U' R' F R2 U' R' U' R U R' F'")  # T-Perm

# Access metrics
print(algo.metrics._asdict())
# {
#   'pauses': 0,
#   'rotations': 0,
#   'outer_moves': 14,
#   'inner_moves': 0,
#   'htm': 14,
#   'qtm': 16,
#   'stm': 14,
#   'etm': 14,
#   'qstm': 16,
#   'generators': ['R', 'U', 'F']
# }

# Individual metrics
print(f"HTM: {algo.metrics.htm}")   # 14
print(f"QTM: {algo.metrics.qtm}")   # 16
print(f"Generators: {', '.join(algo.metrics.generators)}")  # R, U, F

Metric definitions:

  • HTM (Half Turn Metric): Counts quarter turns as 1, half turns as 1 (also known as OBTM - Outer Block Turn Metric)
  • QTM (Quarter Turn Metric): Counts quarter turns as 1, half turns as 2 (also known as OBQTM - Outer Block Quantum Turn Metric)
  • STM (Slice Turn Metric): Counts both face turns and slice moves as 1 (also known as BTM/RBTM - Block/Range Block Turn Metric)
  • ETM (Execution Turn Metric): Counts all moves including rotations
  • RTM (Rotation Turn Metric): Counts only rotation moves (x, y, z)
  • QSTM (Quarter Slice Turn Metric): Counts quarter turns as 1, slice quarter turns as 1, half turns as 2 (also known as BQTM - Block Quarter Turn Metric)

Metric aliases: The MetricsData object also provides these property aliases for convenience:

  • obtmhtm
  • obqtmqtm
  • btm / rbtmstm
  • bqtmqstm

Algorithm Analysis

Beyond basic metrics, algorithms provide comprehensive analysis capabilities:

from cubing_algs.parsing import parse_moves

algo = parse_moves("R U R' U'")

# Structure analysis - detect commutators and conjugates
print(algo.structure.compressed)         # "[R, U]" (commutator notation)
print(algo.structure.commutator_count)   # 1
print(algo.structure.conjugate_count)    # 0
print(algo.structure.total_structures)   # 1
print(algo.structure.max_nesting_depth)  # 1

# Impact analysis - spatial effects on cube
impacts = algo.impacts()
print(impacts.facelets_mobilized_count)     # Number of facelets that change position
print(impacts.facelets_scrambled_percent)   # Fraction of movable facelets displaced
print(impacts.facelets_face_mobility)       # Impact breakdown by face

# Impact analysis on larger cubes
impacts_5x5 = algo.impacts(size=5)
print(impacts_5x5.facelets_mobilized_count)  # Facelets affected on 5x5x5

# Ergonomics analysis - execution comfort
print(algo.ergonomics.comfort_rating)       # Overall execution difficulty (0-10)
print(algo.ergonomics.estimated_time_ms)    # Estimated execution time
print(algo.ergonomics.regrip_count)         # Number of regrips needed
print(algo.ergonomics.finger_usage)         # Which fingers are used

# Cycle analysis
print(algo.cycles)  # 6 - How many repetitions return to solved state

# Minimum cube size
print(algo.min_cube_size)  # 2 - Minimum cube size to execute this algorithm

Analysis use cases:

  • Structure detection: Automatically identify commutator/conjugate patterns
  • Impact analysis: Understand which pieces are affected by an algorithm
  • Ergonomics: Evaluate execution difficulty and fingertrick requirements
  • Algorithm comparison: Compare different algorithms for the same case

Cube Patterns

Access a library of classic cube patterns:

from cubing_algs.patterns import get_pattern, PATTERNS

# Get a specific pattern
superflip = get_pattern('Superflip')
print(superflip)  # U R2 F B R B2 R U2 L B2 R U' D' R2 F R' L B2 U2 F2

checkerboard = get_pattern('EasyCheckerboard')
print(checkerboard)  # U2 D2 R2 L2 F2 B2

# List all available patterns
print(list(PATTERNS.keys()))

# Some popular patterns
cube_in_cube = get_pattern('CubeInTheCube')
anaconda = get_pattern('Anaconda')
wire = get_pattern('Wire')
tetris = get_pattern('Tetris')

Available patterns include:

  • Superflip - All edges flipped
  • EasyCheckerboard - Classic checkerboard pattern
  • CubeInTheCube - Cube within a cube effect
  • Tetris - Tetris-like pattern
  • Wire - Wire frame effect
  • Anaconda, Python, GreenMamba, BlackMamba - Snake patterns
  • Cross, Plus, Minus - Cross patterns
  • And many more! (70+ patterns total)

Scramble Generation

The cubing_algs.scrambler module provides comprehensive scramble generation:

  • NxN scrambles for cubes of any size (2x2x2 to NxNxN)
  • Step-based scrambles for speedcubing practice (PLL, OLL, F2L, ZBLL, etc.)
  • Piece-level constraints for fine-grained control over cube state
  • Practice scrambles for cross, x-cross, and F2L training

Basic NxN Scrambles

from cubing_algs.scrambler import scramble

# Generate scramble for 3x3x3 cube (default 25-30 moves)
scramble_3x3 = scramble(3)
print(scramble_3x3)

# Generate scramble for 4x4x4 cube (includes wide moves)
scramble_4x4 = scramble(4)
print(scramble_4x4)  # Example: Rw U R D' Fw2 R' Uw F2 ...

# Generate scramble for 6x6x6 cube (includes multi-layer moves)
scramble_6x6 = scramble(6)
print(scramble_6x6)  # Example: 3Rw F' 3Uw2 Fw R Bw' ...

# Generate scramble with specific number of moves
custom_scramble = scramble(3, iterations=20)
print(f"Custom 20-move scramble: {custom_scramble}")

# Include inner layer moves (e.g., 2R, 3R for big cubes)
inner_scramble = scramble(5, inner_layers=True)

# Left-handed optimized scramble (excludes D, R, B instead of D, L, B)
lh_scramble = scramble(4, right_handed=False)

Step-Based Scrambles

Generate scrambles for specific speedcubing steps. The cube state is constructed mathematically (not by applying random moves), ensuring a valid partial-solve state:

from cubing_algs.scrambler import scramble_step

# Last Layer steps
pll_scramble = scramble_step("PLL")          # Only U layer permuted
oll_scramble = scramble_step("OLL")          # U layer permuted + oriented
zbll_scramble = scramble_step("ZBLL")        # Corners oriented, all U pieces permuted

# With random AUF (Adjust U Face)
pll_with_auf = scramble_step("PLL", include_auf=True)

# F2L variants
f2l_scramble = scramble_step("F2L")          # First two layers scrambled
zzf2l_scramble = scramble_step("ZZF2L")      # ZZ method F2L

# Roux method
cmll_scramble = scramble_step("CMLL")        # Roux CMLL step
sb_scramble = scramble_step("SB")            # Roux Second Block

# Last Slot variants
ls_scramble = scramble_step("LS")            # Last Slot
wv_scramble = scramble_step("WV")            # Winter Variation

Supported steps:

  • Last Layer: LL, OLL, PLL, CLL, OLLCP, COLL, ZBLL, 2GLL, OCLL, ELL, EPLL, CPLL, ZZLL
  • F2L variants: F2L, ZZF2L, ZZRB, PETRUSF2L
  • Last Slot: LS, ELS, ZZLS, TSLE, CLS, CPLS, EJLS, EJF2L, TTLL, WV, SV, VLS, VHLS
  • Roux method: CMLL, CMLLEO, SB
  • Petrus method: PETRUS2X2X3, PETRUSEO

OCLL Case Scrambles

Generate scrambles for specific OCLL (Orientation of Corners of Last Layer) cases:

from cubing_algs.scrambler import scramble_ocll_case

sune_scramble = scramble_ocll_case("Sune")
antisune_scramble = scramble_ocll_case("AntiSune")
h_scramble = scramble_ocll_case("H")
pi_scramble = scramble_ocll_case("Pi")

Valid cases: T, U, L, H, Pi, Sune, AntiSune, Solved

Cross and X-Cross Practice

from cubing_algs.scrambler import scramble_easy_cross, scramble_x_cross

# Easy cross scramble - returns (scramble, solution) tuple
scramble_alg, solution = scramble_easy_cross()
print(f"Scramble: {scramble_alg}")
print(f"Solution: {solution}")

# Adjust difficulty: 'easy' (3 moves), 'normal' (5 moves), 'hard' (7 moves)
easy_scramble, easy_solution = scramble_easy_cross(difficulty='easy')
hard_scramble, hard_solution = scramble_easy_cross(difficulty='hard')

# X-cross scramble - cross + one F2L slot preserved
x_cross_scramble, x_cross_solution = scramble_x_cross(slots=['FR'])

# XX-cross - cross + two F2L slots preserved
xx_scramble, xx_solution = scramble_x_cross(slots=['FR', 'FL'])

# Valid slots: FR, FL, BR, BL

F2L Slot Practice

from cubing_algs.scrambler import scramble_f2l

# Scramble a single F2L slot (cross solved, one slot scrambled)
f2l_scramble = scramble_f2l(slots=['FR'])

# Scramble multiple F2L slots
multi_slot = scramble_f2l(slots=['FR', 'BL'])

Piece-Level Constraints

For maximum control over cube state, specify exactly which pieces should be solved, oriented, scrambled, or disoriented:

from cubing_algs.scrambler import scramble_with_piece_constraints

# PLL-like state: all pieces oriented, only permutation scrambled
pll_state = scramble_with_piece_constraints(
    orient_corners_spec="all",
    orient_edges_spec="all",
)

# F2L solved, last layer scrambled
f2l_solved = scramble_with_piece_constraints(
    solve_corners="D",
    solve_edges="D E",
    buffer_corners="U",
    buffer_edges="U",
)

# ZBLL-like: last layer corners oriented, permutation scrambled
zbll_state = scramble_with_piece_constraints(
    orient_corners_spec="U",
    orient_edges_spec="U",
)

# Specific pieces scrambled
specific = scramble_with_piece_constraints(
    solve_corners="URF UBR",    # Keep these corners solved
    derange_edges="UF UR",      # Ensure these edges are NOT solved
    disorient_corners_spec="U", # U-layer corners must be misoriented
)

Piece specification formats:

  • "all" or "": All pieces of that type
  • "U", "D", "R", "L", "F", "B": All pieces on that layer
  • "URF UBR": Specific pieces by name (space-separated)
  • "U DFR": Mix of layer and specific pieces

Scramble Features

  • Cube sizes: Supports 2x2x2 through 7x7x7+ cubes
  • Automatic move count: Based on cube size (configurable ranges)
    • 2x2x2: 9-11 moves
    • 3x3x3: 25-30 moves
    • 4x4x4: 45-50 moves
    • 5x5x5: 60 moves
    • 6x6x6: 80 moves
    • 7x7x7: 100 moves
  • Smart move validation: Prevents consecutive moves on same face or opposite faces
  • Big cube support:
    • Wide moves (Rw, Uw, etc.) for 4x4x4+
    • Multi-layer moves (3Rw, etc.) for 6x6x6+
    • Optional inner layer moves (2R, 3R, etc.)
  • Handedness: Right-handed (default) or left-handed move set optimization
  • Reproducible scrambles: Pass a Random instance for deterministic results
  • Physical constraints: Step-based scrambles maintain valid cube states (sum(co) % 3 == 0, sum(eo) % 2 == 0, matching permutation parity)

Virtual Cube Simulation

Track cube state and visualize the cube:

from cubing_algs import VCube
from cubing_algs.parsing import parse_moves

# Create a new solved cube
cube = VCube()
print(cube.is_solved)  # True
print(cube.orientation)  # "UF" - default orientation

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

# Apply algorithm object
algo = parse_moves("F R U R' U' F'")
cube.rotate(algo)

# Display the cube (ASCII art with colors)
cube.show()

# Display with different options
cube.show(orientation='UB')        # View from different angle
cube.show(mode='oll')              # OLL pattern visualization
cube.show(palette='colorblind')    # Colorblind-friendly colors
cube.show(mask='F2L')              # Highlight specific pieces

# Get cube state
print(cube.state)       # 54-character facelet string
print(cube.orientation) # Current orientation (e.g., "UF")
print(cube.history)     # List of all moves applied

# Orientation features
oriented = cube.oriented_copy('UB')  # Create copy with U top, B front
print(oriented.orientation)  # "UB"

moves = cube.compute_orientation_moves('DR')  # Calculate moves to get D top, R front
print(moves)  # e.g., "x2 y"

# Create cube from specific state
custom_cube = VCube("UUUUUUUUURRRRRRRRRFFFFFFFFFDDDDDDDDDLLLLLLLLLBBBBBBBBB")

# Work with cubie representation (mathematical)
cp, co, ep, eo, so = cube.cubies  # Convert to cubie format
new_cube = VCube.from_cubies(cp, co, ep, eo, so)  # Create from cubies

# Get individual faces
u_face = cube.get_face('U')  # Get U face facelets (9 characters)

VCube features:

  • Full 3x3x3 cube state tracking with dual representation
  • ASCII art display with colors, multiple orientations, and visual modes
  • Move history tracking
  • Orientation management (get current, create oriented copies, compute orientation moves)
  • Conversion between facelets and cubie coordinates
  • Integrity checking to ensure valid cube states
  • Support for creating cubes from custom states

Default orientation: The default orientation is 'UF', following the WCA (World Cube Association) standard:

  • U (Up/Top) face: White color
  • F (Front) face: Green color
  • R (Right) face: Red color
  • D (Down/Bottom) face: Yellow color (opposite White)
  • L (Left) face: Orange color (opposite Red)
  • B (Back) face: Blue color (opposite Green)

This standard orientation is used consistently across the library for cube initialization, display, and algorithm application.

Image Rendering

Generate SVG images of cube states using the render_cube function or the .image() method available on both VCube and Algorithm objects:

from cubing_algs import VCube
from cubing_algs.parsing import parse_moves
from cubing_algs.display.image import render_cube

# Render a cube state as SVG
cube = VCube()
cube.rotate("R U R' U'")
svg = cube.image()  # Returns SVG string

# Render an algorithm's effect directly
algo = parse_moves("R U R' U' R' F R2 U' R' U' R U R' F'")
svg = algo.image()  # Applies to solved cube and renders

# Using render_cube directly
svg = render_cube(cube, size=300)

Views

Two rendering modes are available:

# 3D perspective view (default)
svg_3d = cube.image(view='3d')

# Flat top-face view with adjacent strips from F, R, B, L faces
svg_top = cube.image(view='top')

Customization

# Custom image size (pixels)
svg = cube.image(size=400)

# Custom rotation angle for 3D view (axis-angle format)
svg = cube.image(rotation='y45x-34')   # Default angle
svg = cube.image(rotation='y-30')      # Different angle
svg = cube.image(rotation='y90x-20')   # Multiple rotations

# Camera distance (larger = flatter, smaller = more depth)
svg = cube.image(distance=20.0)

# Custom cube body color (supports alpha: #rrggbbaa)
svg = cube.image(cube_color='#222222')
svg = cube.image(cube_color='#11111180')  # Semi-transparent

# Color palettes
svg = cube.image(palette_name='default')
svg = cube.image(palette_name='colorblind')
svg = cube.image(palette_name='neon')

# Algorithm with explicit cube size
algo = parse_moves("R U R'")
svg = algo.image(cube_size=2)  # Render on a 2x2x2

Available palettes: default, rgb, vibrant, neon, metal, pastel, retro, minecraft, colorblind, dracula, alucard, solarized-dark, solarized-light, halloween, galaxy, vampire, ghoul, goblin, void, cyberpunk, synthwave, matrix, sunset, ocean, forest, fire, ice, white, black, red, green, blue

Saving to File

# Save as SVG
with open('cube.svg', 'w') as f:
    f.write(cube.image(size=400))

# Embed in HTML
html = f'<html><body>{cube.image()}</body></html>'
with open('cube.html', 'w') as f:
    f.write(html)

Move Object

The Move class represents a single move:

from cubing_algs.move import Move

move = Move("R")
move2 = Move("R2")
move3 = Move("R'")
wide = Move("Rw")
wide_sign = Move("r")
rotation = Move("x")

# Properties
print(move.base_move)  # R
print(move.modifier)   # ''

# Checking move type
print(move.is_rotation_move)   # False
print(move.is_outer_move)      # True
print(move.is_inner_move)      # False
print(move.is_wide_move)       # False

# Checking modifiers
print(move.is_clockwise)         # True
print(move.is_counter_clockwise) # False
print(move.is_double)            # False

# Transformations
print(move.inverted)   # R'
print(move.doubled)    # R2
print(wide.to_sign)    # r
print(wide_sign.to_standard)  # Rw

Performance

The library is optimized for performance:

  • C Extension: Move execution uses an optimized C extension (cubing_algs.extensions.rotate) compiled with -O3 optimization
  • LRU Caching: Facelet ↔ cubie conversion uses LRU caching (512 entries) for repeated operations
  • Lazy Evaluation: Algorithm transforms are composable and don't execute until needed
  • Lightweight State: Virtual cube state is a simple 54-character string with minimal overhead

Performance characteristics:

  • Move execution: ~1-2 microseconds per move (C extension)
  • Facelet/cubie conversion: ~10-20 microseconds uncached, ~0.1 microseconds cached
  • Algorithm parsing: ~50-100 microseconds for typical algorithms

Examples

Generating the inverse of an OLL algorithm

from cubing_algs.parsing import parse_moves
from cubing_algs.transform.invert import invert_moves
from cubing_algs import VCube

oll = parse_moves("F U F' R' F R U' R' F' R")  # OLL 14 Anti-Gun
oll_invert = oll.transform(invert_moves)
print(oll_invert)  # R' F R U R' F' R F U' F'

cube = VCube()
cube.rotate('z2')
cube.rotate(oll)
cube.show(mode='oll')  # Display OLL pattern

Converting a wide move algorithm to SiGN notation

from cubing_algs.parsing import parse_moves
from cubing_algs.transform.sign import sign_moves

algo = parse_moves("Rw U R' U' Rw' F R F'")
sign = algo.transform(sign_moves)
print(sign)  # r U R' U' r' F R F'

Finding the shortest form of an algorithm

from cubing_algs.parsing import parse_moves
from cubing_algs.transform.size import compress_moves

algo = parse_moves("R U U U R' R R F F' F F")
compressed = algo.transform(compress_moves)
print(compressed)  # R U' R2 F2

Changing the viewpoint of an algorithm

from cubing_algs.parsing import parse_moves
from cubing_algs.transform.offset import offset_y_moves

algo = parse_moves("R U R' U'")
y_rotated = algo.transform(offset_y_moves)
print(y_rotated)  # F R F' R'

De-gripping a fingertrick sequence

from cubing_algs.parsing import parse_moves
from cubing_algs.transform.degrip import degrip_y_moves

algo = parse_moves("y F R U R' U' F'")
degripped = algo.transform(degrip_y_moves)
print(degripped)  # R F R F' R' y

Working with commutators and patterns

from cubing_algs.parsing import parse_moves
from cubing_algs.patterns import get_pattern
from cubing_algs import VCube

# Parse and expand a commutator
comm = parse_moves("[R, U]")  # R U R' U'

# Apply a pattern to a virtual cube
cube = VCube()
pattern = get_pattern('Superflip')
cube.rotate(pattern)
cube.show()  # Display the superflip pattern

# Generate and apply a scramble
from cubing_algs.scrambler import scramble
scramble_algo = scramble(3, iterations=25)
cube = VCube()
cube.rotate(scramble_algo)
print(f"Scrambled with: {scramble_algo}")

Step-based scramble practice

from cubing_algs.scrambler import scramble_step, scramble_easy_cross, scramble_f2l
from cubing_algs import VCube

# Practice PLL recognition
cube = VCube()
pll_scramble = scramble_step("PLL")
cube.rotate(pll_scramble)
cube.show(mode='oll')  # Visualize - all pieces oriented, only permutation scrambled

# Practice cross building with solution
scramble_alg, solution = scramble_easy_cross(difficulty='normal')
cube = VCube()
cube.rotate(scramble_alg)
print(f"Scramble: {scramble_alg}")
print(f"Solution: {solution}")

# Practice a specific F2L slot
f2l_scramble = scramble_f2l(slots=['FR'])
cube = VCube()
cube.rotate(f2l_scramble)
cube.show()  # Cross solved, FR slot scrambled

Advanced algorithm development workflow

from cubing_algs.parsing import parse_moves
from cubing_algs.transform.invert import invert_moves
from cubing_algs.transform.symmetry import symmetry_m_moves
from cubing_algs import VCube
from cubing_algs.scrambler import scramble

# Start with a commutator
base_alg = parse_moves("[R U R', D]")  # R U R' D R U' R' D'

# Generate variations
inverse = base_alg.transform(invert_moves)
m_symmetric = base_alg.transform(symmetry_m_moves)

# Analyze algorithms
print(f"Original: {base_alg} ({base_alg.metrics.htm} HTM)")
print(f"Comfort: {base_alg.ergonomics.comfort_rating}/10")
print(f"Affected pieces: {base_alg.impacts().facelets_mobilized_count}")
print(f"Inverse: {inverse} ({inverse.metrics.htm} HTM)")

# Test on virtual cube
cube = VCube()
cube.rotate(base_alg)
print(f"Is solved after: {cube.is_solved}")

# Test algorithm on scrambled cube
test_cube = VCube()
test_scramble = scramble(3, iterations=15)
test_cube.rotate(test_scramble)
print(f"Applied scramble: {test_scramble}")

# Apply algorithm and check result
test_cube.rotate(base_alg)
print(f"Cube state after algorithm: {test_cube.state[:9]}...")  # First 9 facelets

# Create conjugate setup
setup = parse_moves("R U")
full_alg = parse_moves(f"[{setup}: {base_alg}]")
print(f"With setup: {full_alg}")

Development

This library is designed for both end-users and developers:

For users:

  • Comprehensive API with intuitive design
  • Full type hints for IDE support
  • Extensive examples and documentation

For developers:

  • Comprehensive test suite with pytest
  • C extension source in cubing_algs/extensions/rotate.c
  • Full type hints and docstrings throughout the codebase

Development commands:

# Install in development mode
pip install -e .[dev]

# Run tests
pytest cubing_algs

# Type checking
mypy --strict cubing_algs

# Linting
ruff check cubing_algs

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

cubing_algs-1.0.20.tar.gz (435.8 kB view details)

Uploaded Source

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

cubing_algs-1.0.20-cp314-cp314t-musllinux_1_2_x86_64.whl (599.4 kB view details)

Uploaded CPython 3.14tmusllinux: musl 1.2+ x86-64

cubing_algs-1.0.20-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl (601.7 kB view details)

Uploaded CPython 3.14tmanylinux: glibc 2.17+ x86-64manylinux: glibc 2.28+ x86-64

cubing_algs-1.0.20-cp314-cp314-musllinux_1_2_x86_64.whl (599.2 kB view details)

Uploaded CPython 3.14musllinux: musl 1.2+ x86-64

cubing_algs-1.0.20-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl (601.5 kB view details)

Uploaded CPython 3.14manylinux: glibc 2.17+ x86-64manylinux: glibc 2.28+ x86-64

cubing_algs-1.0.20-cp313-cp313-musllinux_1_2_x86_64.whl (599.1 kB view details)

Uploaded CPython 3.13musllinux: musl 1.2+ x86-64

cubing_algs-1.0.20-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl (601.4 kB view details)

Uploaded CPython 3.13manylinux: glibc 2.17+ x86-64manylinux: glibc 2.28+ x86-64

cubing_algs-1.0.20-cp312-cp312-musllinux_1_2_x86_64.whl (599.0 kB view details)

Uploaded CPython 3.12musllinux: musl 1.2+ x86-64

cubing_algs-1.0.20-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl (601.3 kB view details)

Uploaded CPython 3.12manylinux: glibc 2.17+ x86-64manylinux: glibc 2.28+ x86-64

File details

Details for the file cubing_algs-1.0.20.tar.gz.

File metadata

  • Download URL: cubing_algs-1.0.20.tar.gz
  • Upload date:
  • Size: 435.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for cubing_algs-1.0.20.tar.gz
Algorithm Hash digest
SHA256 5678030712af21c04786e0310977bab67c99b22db26ff99247658db1dbd73853
MD5 32df3bc1959129a6d9c051ed28d1e9aa
BLAKE2b-256 50f587febac714b64f649b714cd4ae7a2469c962ce6b4e072f28a49f7527a5af

See more details on using hashes here.

Provenance

The following attestation bundles were made for cubing_algs-1.0.20.tar.gz:

Publisher: release.yml on Fantomas42/cubing-algs

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file cubing_algs-1.0.20-cp314-cp314t-musllinux_1_2_x86_64.whl.

File metadata

File hashes

Hashes for cubing_algs-1.0.20-cp314-cp314t-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 376ec85f670d9c105c1b93ce0ed8c774bf29ca271feaa54eac96d79a680b40f9
MD5 7241c15b5906098b062d19dc53b09f5e
BLAKE2b-256 1b8417e4a169d1a8db046e5feb075ae4f2b5c29aa2eee535294f5b2ff91f6aee

See more details on using hashes here.

Provenance

The following attestation bundles were made for cubing_algs-1.0.20-cp314-cp314t-musllinux_1_2_x86_64.whl:

Publisher: release.yml on Fantomas42/cubing-algs

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file cubing_algs-1.0.20-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for cubing_algs-1.0.20-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 1fcb0cad1037e842b7f4a010c87d721c741639604d15a7b806c9384731cd47d5
MD5 f7935be7a6c7a05e93b51339c32f7157
BLAKE2b-256 faed808ccce75bd0a0552e4bcbbf4eb2e01688779466c93f1eff1f861faee707

See more details on using hashes here.

Provenance

The following attestation bundles were made for cubing_algs-1.0.20-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl:

Publisher: release.yml on Fantomas42/cubing-algs

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file cubing_algs-1.0.20-cp314-cp314-musllinux_1_2_x86_64.whl.

File metadata

File hashes

Hashes for cubing_algs-1.0.20-cp314-cp314-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 49d8797464409b46042e807bd3bf48749d69ff913789c77f938b905c134d0f07
MD5 d7258b11c0b576966ea98bd1f85b3798
BLAKE2b-256 27b5b4eb49aa11695471d294c70c358553ffc888ee562bdff9f5e397530684be

See more details on using hashes here.

Provenance

The following attestation bundles were made for cubing_algs-1.0.20-cp314-cp314-musllinux_1_2_x86_64.whl:

Publisher: release.yml on Fantomas42/cubing-algs

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file cubing_algs-1.0.20-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for cubing_algs-1.0.20-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 987e730c07762cfa8c41f055ce72a09be45d5fa0cc182ab7e43870ec552f327d
MD5 d149bf95ff26f02b91f84a4b7ed07fc9
BLAKE2b-256 84d86a29ad9d5692000ad39135fe773343012cbc9736b3761326cc2d79fce4a3

See more details on using hashes here.

Provenance

The following attestation bundles were made for cubing_algs-1.0.20-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl:

Publisher: release.yml on Fantomas42/cubing-algs

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file cubing_algs-1.0.20-cp313-cp313-musllinux_1_2_x86_64.whl.

File metadata

File hashes

Hashes for cubing_algs-1.0.20-cp313-cp313-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 7d90e438178e5aac19ab45c18e8a58286e3f3b2c4984a99152e7b20623eb5a51
MD5 d3bf2da60b10f744256d308fe7e20ecb
BLAKE2b-256 80a18b6c7058e6c8cc6d16e4cccc29bb7f4a0cd323533814e3cb3590b3a1536a

See more details on using hashes here.

Provenance

The following attestation bundles were made for cubing_algs-1.0.20-cp313-cp313-musllinux_1_2_x86_64.whl:

Publisher: release.yml on Fantomas42/cubing-algs

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file cubing_algs-1.0.20-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for cubing_algs-1.0.20-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 c63335916274d0b7e636b3baa135db54b339ddc1efafddc283f586539b040391
MD5 5f59ed7ad90ea5b352064ca8beef6e2f
BLAKE2b-256 05cf5403c687b8ecccf071d63276abba97be71dcc743de7667ac8df0150a1e1f

See more details on using hashes here.

Provenance

The following attestation bundles were made for cubing_algs-1.0.20-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl:

Publisher: release.yml on Fantomas42/cubing-algs

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file cubing_algs-1.0.20-cp312-cp312-musllinux_1_2_x86_64.whl.

File metadata

File hashes

Hashes for cubing_algs-1.0.20-cp312-cp312-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 f848585faed5f0000fc0395c4c3d9528688949395d084a73cafdfe08977910d4
MD5 0e88de8d34ab17eedfebfd3f46430098
BLAKE2b-256 f14d9b74d3e0f909da05e531ad2aef70151d7a3f102ad91de3041d975bc7bc9b

See more details on using hashes here.

Provenance

The following attestation bundles were made for cubing_algs-1.0.20-cp312-cp312-musllinux_1_2_x86_64.whl:

Publisher: release.yml on Fantomas42/cubing-algs

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file cubing_algs-1.0.20-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for cubing_algs-1.0.20-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 4c03651d508deeacf2afadbf6011bdb4ea69f251f0fe50d5dccf0103209ab1d4
MD5 ea85b94b578c8799fe069f27bedc0876
BLAKE2b-256 45b4b539dd5bd4132b24cfe0e8ebe6b4bf1ad8c04a25b58c10b19a0c57595c2f

See more details on using hashes here.

Provenance

The following attestation bundles were made for cubing_algs-1.0.20-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl:

Publisher: release.yml on Fantomas42/cubing-algs

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page