Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

8-Puzzle Problem — Uninformed Search Algorithms

Open In Colab

Overview

The 8-puzzle is a classic AI problem consisting of a 3×3 grid with tiles numbered 1–8 and one blank space.
The goal is to slide tiles until the board matches the goal configuration.

Initial State       Goal State
┌───┬───┬───┐      ┌───┬───┬───┐
│ 1 │ 2 │ 5 │      │ 1 │ 2 │ 3 │
├───┼───┼───┤  →   ├───┼───┼───┤
│ 3 │ 4 │   │      │ 4 │ 5 │ 6 │
├───┼───┼───┤      ├───┼───┼───┤
│ 6 │ 7 │ 8 │      │ 7 │ 8 │   │
└───┴───┴───┘      └───┴───┴───┘

Algorithms Covered

AlgorithmStrategyCompleteOptimalSpace
BFSLevel-by-level (FIFO)✅ Yes✅ YesExponential
DFSDepth-first (LIFO)⚠️ With limit❌ NoLinear
UCSLowest cost first✅ Yes✅ YesExponential
Dependencies ready.
All imports successful ✓

Part 1 — State Representation & Puzzle Core

A state is represented as a tuple of 9 integers, read row-by-row (left-to-right, top-to-bottom).
0 represents the blank tile.

State tuple:  (1, 2, 5, 3, 4, 0, 6, 7, 8)
Board layout:
  1  2  5
  3  4  _
  6  7  8

Moves are defined by how the blank (index of 0) can swap with adjacent tiles:

MoveBlank shifts byValid when
Up−3row > 0
Down+3row < 2
Left−1col > 0
Right+1col < 2
  Sample initial state
  1  2  5
  3  4  _
  6  7  8

Blank at: (1, 2)
Neighbors:
  Move Up    → (1, 2, 0, 3, 4, 5, 6, 7, 8)
  Move Down  → (1, 2, 5, 3, 4, 8, 6, 7, 0)
  Move Left  → (1, 2, 5, 3, 0, 4, 6, 7, 8)
<Figure size 240x240 with 1 Axes>

Part 2 — Breadth-First Search (BFS)

How it works

BFS explores states level by level using a FIFO queue.
All states at depth dd are examined before any state at depth d+1d+1.

Queue: [start]
while queue not empty:
    node = queue.popleft()        # dequeue from front
    if goal(node): return path
    for each neighbor of node:
        if not visited:
            visited.add(neighbor)
            queue.append(neighbor)

Properties:

  • Complete — guaranteed to find a solution if one exists

  • Optimal — finds the shallowest (shortest) solution

  • Time/Space — O(bd)O(b^d) where bb = branching factor, dd = solution depth

=== BFS ===
  Initial State
  1  2  5
  3  4  _
  6  7  8

  Solution depth    : 21 moves
  Nodes expanded    : 49,595
  Max frontier size : 18,252
  Time              : 0.2126 s

  Move sequence: Down → Left → Up → Left → Down → Right → Right → Up → Left → Left → Up → Right → Right → Down → Left → Up → Left → Down → Down → Right → Right
<Figure size 2400x280 with 12 Axes>

Part 3 — Depth-First Search (DFS)

How it works

DFS explores states by diving as deep as possible before backtracking.
It uses a LIFO stack and a depth limit to avoid infinite loops.

Stack: [start]
while stack not empty:
    node, depth = stack.pop()         # pop from top
    if goal(node): return path
    if depth >= limit: continue       # depth cut-off
    for each neighbor of node (reversed):
        if not visited:
            stack.append((neighbor, depth+1))

Properties:

  • Complete — only with a depth limit and visited set

  • Optimal — ❌ may find a longer path first

  • Time — O(bm)O(b^m) where mm = max depth

  • Space — O(b⋅m)O(b \cdot m) — much more memory-efficient than BFS

Fetching long content....
<Figure size 2400x280 with 12 Axes>

Part 4 — Uniform Cost Search (UCS)

How it works

UCS always expands the node with the lowest cumulative path cost g(n)g(n).
It uses a min-heap priority queue ordered by g(n)g(n).

PQ: [(cost=0, start)]
while PQ not empty:
    cost, node = heappop(PQ)          # cheapest node
    if goal(node): return path
    for each (neighbor, step_cost):
        new_cost = cost + step_cost
        if neighbor not seen or cheaper:
            heappush(PQ, (new_cost, neighbor))

Since every step has cost = 1 in the standard 8-puzzle, UCS behaves identically to BFS.
The implementation below uses general step costs so you can experiment with non-uniform costs.

Properties:

  • Complete — yes (positive step costs)

  • Optimal — yes, finds minimum-cost solution

  • Time/Space — O(b1+⌊C∗/ε⌋)O(b^{1 + \lfloor C^*/\varepsilon \rfloor}) where C∗C^* = optimal cost

=== UCS (uniform step cost = 1) ===
  Initial State
  1  2  5
  3  4  _
  6  7  8

  Solution depth    : 21 moves
  Total path cost   : 21
  Nodes expanded    : 105,848
  Max frontier size : 44,729
  Time              : 0.6586 s

  Move sequence: Down → Left → Up → Left → Down → Right → Right → Up → Left → Left → Up → Right → Right → Down → Left → Up → Left → Down → Down → Right → Right
<Figure size 2400x280 with 12 Axes>

Part 5 — Interactive Comparison

Use the widget below to:

  1. Enter any starting configuration (a permutation of 0–8, where 0 = blank)

  2. Choose a DFS depth limit

  3. Run all three algorithms and compare results side-by-side

⚠️ Not every tile arrangement is solvable. The widget will warn you if your puzzle is unsolvable.

Loading...

Part 6 — Scalability Analysis

Run all three algorithms on a range of puzzles at increasing solution depths and plot how each metric scales.

 Depth  Seed  Algo      Nodes    Path    Time(s)
--------------------------------------------------
     4     0   BFS          2       2     0.0000
     4     0   DFS          3       2     0.0000
     4     0   UCS          4       2     0.0001
     4     1   BFS          3       2     0.0001
     4     1   DFS     14,696      60     0.0709
     4     1   UCS          9       2     0.0000
     4     2   BFS         52       6     0.0002
     4     2   DFS     14,690      60     0.0328
     4     2   UCS         99       6     0.0003
     8     0   BFS          8       4     0.0000
     8     0   DFS    144,103       4     0.3346
     8     0   UCS         17       4     0.0001
     8     1   BFS          2       2     0.0000
     8     1   DFS          3       2     0.0000
     8     1   UCS          4       2     0.0000
     8     2   BFS         92       8     0.0004
     8     2   DFS      4,785      58     0.0099
     8     2   UCS        160       8     0.0004
    12     0   BFS      1,081      12     0.0025
    12     0   DFS      5,343      56     0.0118
    12     0   UCS      2,035      12     0.0095
    12     1   BFS        991      12     0.0027
    12     1   DFS     41,374      50     0.0997
    12     1   UCS      1,837      12     0.0094
    12     2   BFS         54       6     0.0002
    12     2   DFS     26,722      60     0.0546
    12     2   UCS        103       6     0.0004
    16     0   BFS      2,698      14     0.0119
    16     0   DFS    111,308      60     0.2829
    16     0   UCS      5,130      14     0.0249
    16     1   BFS     12,368      18     0.0545
    16     1   DFS     19,631      60     0.0437
    16     1   UCS     23,522      18     0.1081
    16     2   BFS      2,622      14     0.0066
    16     2   DFS     47,943      60     0.1021
    16     2   UCS      4,916      14     0.0208
    20     0   BFS        878      12     0.0017
    20     0   DFS    143,051      -1     0.3568
    20     0   UCS      1,583      12     0.0061
    20     1   BFS        415      10     0.0008
    20     1   DFS     36,133      60     0.0653
    20     1   UCS        755      10     0.0018
    20     2   BFS        837      12     0.0014
    20     2   DFS    104,019      58     0.2103
    20     2   UCS      1,493      12     0.0056

Benchmark complete.
<Figure size 1400x400 with 3 Axes>

Part 7 — Summary & Key Takeaways

PropertyBFSDFSUCS
Data structureQueue (FIFO)Stack (LIFO)Min-heap
Completeness✅ Yes⚠️ With depth limit✅ Yes
Optimality✅ Shortest path❌ No✅ Min-cost path
Time complexityO(bd)O(b^d)O(bm)O(b^m)O(b1+⌊C∗/ε⌋)O(b^{1+\lfloor C^*/\varepsilon\rfloor})
Space complexityO(bd)O(b^d)O(b⋅m)O(b \cdot m)O(b1+⌊C∗/ε⌋)O(b^{1+\lfloor C^*/\varepsilon\rfloor})
Best use caseShallow solutionsMemory-constrainedNon-uniform step costs

When to choose which algorithm?

  • BFS — when you need the guaranteed shortest solution and memory is not a constraint

  • DFS — when memory is limited or you just need any valid solution quickly (not necessarily shortest)

  • UCS — when step costs vary (e.g., different tiles have different move costs); generalises BFS

Next steps

  • Try Iterative Deepening DFS (IDDFS) — combines BFS optimality with DFS space efficiency

  • Add heuristics → A* search (informed search, much faster for hard puzzles)

  • Extend to the 15-puzzle (4×4) where uninformed search becomes impractical