Jaipur--°C
Back to Projects
CompletedC++CMakeIDA*+3 more

Rubik's Cube Solver

A high-performance C++ cube solver with three interchangeable state models and four search strategies, culminating in Korf's IDA* search driven by a 4-bit packed corner pattern database.

Timeline

Oct — Nov 2025

Role

Solo — data structures, search algorithms, heuristic database

Status
Completed

Technology Stack

C++
CMake
IDA*
Pattern Databases
Bitboards
Algorithms

Key Challenges

  • Branching factor of 18 causes unpruned searches to explode in memory beyond shallow depths
  • Creating an admissible heuristic database that fits entirely in cache-friendly memory
  • Optimizing state rotations using bitwise operations

Key Learnings

  • Templating search algorithms over state models allows seamless benchmarking across representations
  • In-place state mutation with inverse moves eliminates copy overhead during tree traversal
  • A 4-bit nibble array halves heuristic database memory footprint

Overview

A standard 3×3 Rubik's Cube has approximately 4.3 × 10¹⁹ reachable states. With 18 legal face turns per position, brute-force search quickly exhausts system memory.

This project explores efficient state representations in modern C++ and implements Iterative Deepening A* (IDA*) with an admissible pattern database to solve scrambles in seconds.

Core State Representations

An abstract RubiksCube interface decouples the game logic from underlying memory representations:

ModelRepresentationCharacteristics
RubiksCube3dArray[6][3][3] face matrixIntuitive and human-readable, ideal for debugging
RubiksCube1dArrayFlat 54-element arrayContiguous memory with reduced cache misses
RubiksCubeBitboardSix 64-bit integers (uint64_t)State rotations computed via bitwise shifts and masks

Search Strategies

Solvers are templated over the cube representation (template<typename T, typename H> class IDAstarSolver), allowing the same search logic to run across any model:

  1. Breadth-First Search (BFS): Finds optimal shortest paths for scrambles up to ~6 moves before memory limits.
  2. Depth-First Search (DFS): Memory-efficient bounded depth exploration; yields non-optimal paths.
  3. Iterative Deepening DFS (IDDFS): Guarantees shortest path while maintaining low linear memory usage.
  4. IDA* (Iterative Deepening A*): Prunes subtrees using a cost function f(n) = g(n) + h(n) powered by an admissible pattern database.

Corner Pattern Database & Bit Packing

To guide IDA* efficiently without exploring irrelevant branches, an admissible heuristic estimates remaining distance by solving only the 8 corner cubies:

  • Breadth-First Generation: Precomputed via BFS from the solved state to record optimal corner solve depths.
  • 4-Bit Nibble Array: Since corner distances never exceed 11 moves, each entry is packed into a 4-bit nibble (2 entries per byte), reducing the in-memory database footprint by 50%.
  • Permutation Indexing: Maps corner configurations directly into dense array offsets without dynamic hash map lookups.

Performance & Build

  • 8-move scrambles: Solved in under 3 seconds using uninformed search.
  • 13-move scrambles: Solved in under 10 seconds using IDA* with bitboards.
mkdir build && cd build
cmake ..
make
./RubiksCubeSolver

Tech Stack Summary

  • Language: C++17 / C++20
  • Build System: CMake, Make
  • Techniques: Bit Manipulation (Bitboards), Heuristic Search (IDA*), Pattern Databases, Data Packing

built by shiv ratan
© 2026. All rights reserved.