Back to scramble generator

5×5 scramble: random-move vs random-state

Two methods both "scramble" a 5×5 cube, but they're mathematically very different. Random-move (the WCA standard) walks 60 random steps from solved. Random-state samples **uniformly** from the 2.27 × 10⁷⁴ legal 5×5 states and inverts a solver path back to scramble. The former is browser-instant; the latter is solver-heavy (~1-3 s) but distributes perfectly.

By the numbers

2.27 × 10⁷⁴
Legal 5×5 states
vs 3×3 ≈ 4.3 × 10¹⁹, 55 orders of magnitude more
60 / ~70
Scramble length (random-move / random-state)
WCA Reg 4d mandates 60
13 / ~230 MB
Pruning tables / total size
one per phase, Java-serialized to disk
~1.5 s
Single solver time (server)
IDA* + Kociemba two-phase, observed prod

The two methods, step by step

Random-Move

WCA

WCA competition standard. Walk 60 random steps from solved; the process is the output.

1
Pick a face at random
One of U / R / F / D / L / B, each 1/6. No slice (M/E/S), no rotation (x/y/z), no double-face primitives — keeps WCA spec.
2
Pick layer width
50/50 between 1 layer (R / U) and 2 layers (Rw / Uw). Wide turns exist only on N×N where N ≥ 4 — one reason 5×5 scrambles carry more information than 3×3.
3
Pick suffix
Empty / ' / 2, each 1/3. `R` (clockwise 90°), `R'` (counter 90°), `R2` (180°). `R2 R2` cancels — filtered next step.
4
Reject same-axis
If the new move shares an axis with the previous (U/D, R/L, F/B), reject and re-roll. Prevents trivially collapsible sequences (`R L R` ≡ `R' L`); ensures WCA-spec shortest-equivalent length.
5
Append
Append, loop back to step 1. Repeat until sequence length = 60 (WCA-mandated).

Pros

  • Instant (<1 ms), runs locally in browser
  • Zero network — works offline
  • Matches WCA Regulation §4d — competition-legal
  • Generator is ~50 LoC — auditable

Cons

  • A process, not an outcome — short-solve states are systematically over-represented
  • Effective state coverage is far smaller than 10⁷⁴
  • Two scrambles can collide on the same state (low odds, but the distribution is biased)

Random-State

cube555

cs0x7f's 5-phase reduction solver. Sample a state, then invert a solver path.

1
Sample a legal state
Sample uniformly across all 2.27 × 10⁷⁴ legal states — randomize each center / wing edge / mid edge / corner position+orientation, fix parity to land in the solvable coset.
2
Phase 1-3: reduce to 3×3
Stage-wise solve centers and pair wing edges. Each stage uses one IDA* pruning table (tens of MB, BFS-built). Total ~30 moves.
3
Phase 4: finish reduction
Pair the remaining mid edges, lock centre orientation. This phase is the hardest — 3 cooperating pruning tables. ~15 moves.
4
Phase 5: solve as 3×3
At this point the 5×5 is equivalent to a 3×3, handed off to the Kociemba two-phase solver (min2phase, ≤21 moves).
5
Invert solution
Reverse the full solution and invert each move (R → R', U2 → U2) → scramble (~70 moves). The trick is using the **solve** to derive the **scramble**.

Pros

  • Uniform over the state space — truly random
  • Each scramble is independent; no short-solve bias
  • Round-trip self-verify: every scramble is checked via CubieCube replay before return
  • A real 5×5 random-state solver is rare — cs0x7f/cube555 is the only public implementation

Cons

  • Slow: ~1.5 s / scramble on the server (varies by seed)
  • Requires network — falls back to random-move if backend is down
  • Not WCA-compliant: ~70-move output, not allowed in competition
  • Pins 230 MB of pruning tables in memory; JVM total RSS ~540 MB

Inside cube555: anatomy of the 5 phases

cs0x7f's cube555 cuts the 5×5 solve into 5 reduction phases. Each phase has a target sub-state and uses IDA* (iterative deepening A*) plus a pre-computed BFS pruning table (`heuristic`) so each phase terminates within near-optimal depth. The table below lists each phase's coord (the pruning-table index) and table size:

Phase 1~12
Pair opposite + adjacent centers
coordx-center sym + t-center sym
table~30 MB
Phase 2~10
Finish remaining centers
coordt-center, x-center raw
table~25 MB
Phase 3~14
Pair wing edges, lock centers
coordcenter + mid/wing edge sym
table~50 MB
Phase 4~14
Finish mid edges, reduce to 3×3
coordml-edge × ud-center, ml-edge × rl-center
table~90 MB
Phase 5≤21
Solve like a 3×3 (Kociemba two-phase)
coord3×3 corner / edge raw
table~35 MB

Cold-build of all 13 pruning tables takes ~5 min (BFS, persisted as `.jpdata` / `.jhdata` via Java Serialization); subsequent boots reload from disk in ~3 s. Tables live on the server container.

How it runs on cuberoot.me

Upstream cube555 ships as a Java GUI demo. We adapt it as a long-lived stdio daemon spawned by Hono (TypeScript), talking line-based stdin/stdout protocol. The user click → scramble path goes through:

1
Browser: pooledScramble
User clicks Generate(N). The client fires N pooledScramble calls; when the pool is empty, all callers wait on one shared SSE batch `/v1/scramble/555-rs/batch?count=N` rather than each firing its own (used to be 2N requests).
2
Edge: nginx reverse proxy
api.cuberoot.me is nginx-proxied to Hono (127.0.0.1:3001). The SSE endpoint sets `X-Accel-Buffering: no` to disable nginx's default proxy_buffering, so each scramble streams downstream as the solver produces it.
3
Hono: streamSSE → daemon
Hono uses `streamSSE` to open N concurrent `getScramble()` calls; each sends an id line over stdio to the Java daemon. The daemon's 3-worker thread pool solves in parallel, returning each result as a tab-separated id\tscramble\tstate line.
4
Daemon: cube555 native binary
Production runs a ~18 MB GraalVM `native-image --static --libc=musl` binary (no glibc dependency), `-Xmx512m`. With 3 workers: 12-scramble batch ≈ 14 s wall (~1.5 s/solve × 4 rounds).

Real-world bench of the "switch to random-state + click Generate(5/event)" cold path: 17.6 s → 9.69 s (-45%), first-scramble 4.7 s → 2.48 s (-47%). Full numbers in BENCHMARKS.md.

At a glance

DimensionRandom-MoveRandom-State
WCA-compliant
Length60~70
Generation time<1 ms~1.5 s
Where it runsbrowser (local)server (daemon)
State distributionnon-uniform, biased to easy solvesuniform
Needs pruning tables?none~230 MB
Needs network?noyes (fallback to random-move on failure)
Implementation complexity~50 lines of TypeScript~20 Java classes, ~5000 LoC
Use whencompetition, official timing, offline practicehome training, dataset sampling, unbiased benchmarks

References