Applied Coding › Guides › Backtracking

Backtracking, discovered — the Sudoku solver

You don't need to know the right digit. You need a way to recover from the wrong one. One board, one dead end, and the technique that turns "I guessed wrong" into a plan.

Pattern: Backtracking · Language: Python · Reading time ≈ 16 min · Video ≈ 8 min
The video's key frame: the top row of the board filled 5 3 1 2 7 4 9 with the next cell stamped NO VALID MOVE, the narrator below it with an empty tray

Watch the video version

Three parts in eight minutes: what Sudoku is, the story of the first row told by hand, and the code built piece by piece. The written version below keeps the whole program in one place and lets you run it.

Watch on YouTube

1 · The problemThe puzzle and its three rules

A nine-by-nine grid. Some cells already hold a digit; the rest are empty. Your job is to fill every empty cell with a digit from 1 to 9 so that three rules hold at once: each digit appears once in its row, once in its column, and once in its three-by-three box.

A nine-by-nine Sudoku board with its given digits, and the narrator asking: have you ever seen this board game?
The board we will use for the whole guide: 30 digits given, 51 cells empty.

The rules are what make a digit wrong. Put a 3 in the fourth cell of the top row and it clashes with the 3 already in that row. The rules reject it before you have gone any further — remember that, because it is the only thing the computer will ever "know" about the puzzle.

A 3 placed in the top row is ringed red, joined by a dotted line to the 3 already in that row; the row is tinted red
A digit that repeats in its row. The column and the box have the same veto.

A person solving this looks for cells where only one digit can go. A computer could do that too, but we are after something more general: a way to solve a puzzle when there is no clever next step, only choices.

2 · The obvious ideaMake a choice, keep going

Start at the first empty cell: the third one in the top row. Which digits are not ruled out? The row already has 5, 3 and 7; the column has an 8; the box has 5, 3, 6, 9 and 8. What is left is 1, 2 or 4.

We don't know which one is right. So take the first that fits: 1. Then move on to the next empty cell and do the same thing. Just make a choice… and keep going.

The narrator at the first empty cell holds a tray with the digits 1, 2 and 4 and says: One.
Three digits fit the first empty cell. He takes the first one.

It goes well. The next empty cell takes a 2, the one after it a 4, the one after that a 9. Four cells filled, no rule broken. It feels like it is working.

The top row now reads 5 3 1 2 7 4 with the placed digits in blue; the narrator says: Just make a choice…
Each digit chosen is the first one the rules allow. Confidence is high.

3 · The failureNothing fits

Then the next empty cell. Try 1: the row has one. 2, 3, 4, 5: all in the row already. 6: in the column. 7: the row. 8: the column. 9: the row. Every digit from 1 to 9 is ruled out. The tray is empty.

The eighth cell of the top row stamped NO VALID MOVE; every digit 1 to 9 is ringed red where it already appears in the row or column; the narrator's tray reads EMPTY
A dead end: the cell exists, it is empty, and nothing is allowed in it.

This is the moment the obvious idea breaks, and it breaks in an interesting way. Nothing is wrong with this cell. Every digit we placed was legal when we placed it. And yet here we are, with an empty cell that cannot be filled. The contradiction is real, but its cause is somewhere behind us.

4 · The observationWhich choice was wrong?

Wait. The problem is not necessarily the last thing we did. One of the earlier choices was wrong — and we have no idea which. The 9? The 4? The 2? The 1 at the very start?

Arrows run back along the top row from the red X over the placed digits 9, 4, 2 and 1; the narrator says: This isn't necessarily the problem.
The dead end points backwards. Any of the four choices behind it could be the one to blame.

We cannot tell from here. So do the only honest thing: go back. Undo the 9. Is there another digit for that cell? If not, undo the 4. And so on — back to a choice where something else can still be tried.

The narrator walks backwards along the row of posts; the top row has lost its last placed digits, and the first cell's tray shows 1, 2 and 4 again
Walking back. Each step undoes one choice and returns its cell to empty.

In the story he walks all the way back to the first empty cell, where 2 and 4 are still untried, and crosses out the 1. The 1 was not illegal; it just led nowhere. That is the key distinction of this whole technique: a choice can be allowed and still be wrong, and the only way to find out is to follow it until it either works or breaks.

At the first empty cell the narrator holds a tray with the 1 crossed out and the 2 in his hand; the rest of the row is empty again
The 1 is crossed out. Next on the tray: 2.

5 · The second attemptTry another — and fail again

With a 2 in the first cell the next cell has only one digit left, a 6, so that one is forced. Then a 4, an 8, a 1 — and the last cell of the row has nothing left. Wrong again. A different dead end, one cell further along.

The top row reads 5 3 2 6 7 4 8 1 with the ninth cell stamped NO VALID MOVE; the narrator says: Wrong again.
The 2 gets one cell further than the 1 did, then dies the same way.

So back again, cross out the 2, and try the 4. This time: 6, 8, 9, 1, and a 2 in the last cell, the only digit that fits. The top row is complete, and every rule holds.

The top row complete: 5 3 4 6 7 8 9 1 2, the placed digits in blue; six trays stand on the posts, each holding the digit that was finally chosen
Third attempt, first row done: 4, 6, 8, 9, 1, 2. Two wrong guesses cost us the walk back and nothing else.

Notice what we never did: we never knew the right digit in advance, and we never needed to. We needed a way to recover from the wrong one.

6 · The discoveryYou are exploring a path

Step back and look at what the attempts form. The first cell had three choices; each of those led to a different set of choices in the next cell, and so on. Every choice opens up more possibilities, and every possibility is itself a choice. The attempts are not guesses — they are paths through a tree.

A tree with three branches from the root, labelled 1, 2 and 4; the 1-branch and the 2-branch end in a red X, the 4-branch runs on
The three attempts on the first row as a tree: the 1-path ends in a cross, the 2-path ends in a cross, the 4-path continues.

Seen like this, "go back" has a precise meaning: when a path breaks, return to the last fork where an untried branch remains, and take it. You are not guessing once. You are exploring a tree, one path at a time, and pruning the paths that break.

The key idea

Make a choice. Explore it. If it leads nowhere, undo it and try the next one. A wrong path is not a failure — it is a branch of the tree you can now rule out.

7 · The nameThis is backtracking

Only now does the technique deserve its name. Backtracking: build a solution one choice at a time; whenever the partial solution can no longer be completed, step back to the most recent choice and change it. The name is literal. When the track ends, you track back.

The word BACKTRACKING beside the board with its finished top row; the narrator says the name
Named after it is understood, not before.

The whole loop fits on one hand:

  1. Choose

    Pick the next decision to make — here, the next empty cell.

  2. Try

    Take the first option the rules still allow, and make it real on the board.

  3. Keep going

    Move to the next decision as if the choice were right. If there are no decisions left, you are done.

  4. If it fails, undo

    A dead end means some choice behind you was wrong. Take the most recent one back.

  5. Try the next option

    At that same decision, the next allowed option. If there is none, undo one more.

A flowchart: find an empty cell → try a possible choice → is it valid? yes → continue → solved? yes → done; no → backtrack, which loops to the next choice
The same loop as a flowchart. The arrow out of BACKTRACK goes to "next choice" — not to the start.

8 · The distinctionNot starting over

Backtracking does not mean wiping the board and beginning again. When the 2-path broke at the end of the row, only the choices that depended on the 2 were undone — the 6, the 4, the 8, the 1. The thirty given digits never moved, and neither would any cell filled before the bad choice. You only undo the choices that depend on the wrong decision.

Two panels side by side: START OVER in red, with a single tray on the posts, and BACKTRACK in green, with the trays 4, 6, 8, 9 kept on their posts
Start over throws away everything. Backtrack keeps every choice that was not implicated.
Honesty note

In the story he walks all the way back to the first cell and crosses out the 1. The program is more careful than the story: it goes back one choice and tries the next digit there first. With a 1 in the first cell, the program tries a 9 instead of the 8 in the seventh cell, fails again, then steps back further. It makes 333 placements before it has exhausted every path that starts with a 1, and 2,207 before it gives up on the 2 and finally places the 4. The walk back in the film is the shape of the idea; the numbers here are the program's.

9 · The codeTranslate what we did into Python

The board is a nine-by-nine list of lists of characters: a digit, or '.' for an empty cell. The board itself is the whole state — there is no separate record of the path, because the path is the digits currently on the board.

Build the solver from the loop above, one piece at a time.

Find an empty cell

Scan row by row, cell by cell. A cell that already holds a digit is skipped. The first empty cell found is the decision to make now.

    def solve():        for r in range(9):            for c in range(9):                if board[r][c] != '.':                    continue

Try every digit

For that cell, go through the digits 1 to 9 in order. A digit that breaks a rule is skipped before anything else happens — this is the tray with some digits missing.

                for num in "123456789":                    if not valid(r, c, num):                        continue

What makes a digit valid?

Three loops, one per rule: the row, the column, the three-by-three box. The box's top-left corner is found by rounding the row and column down to a multiple of three.

    def valid(r, c, num):        for j in range(9):            if board[r][j] == num:                return False         for i in range(9):            if board[i][c] == num:                return False         box_r = (r // 3) * 3        box_c = (c // 3) * 3         for i in range(box_r, box_r + 3):            for j in range(box_c, box_c + 3):                if board[i][j] == num:                    return False         return True

Place it, go deeper, and if that fails, undo

This is where the story becomes recursion. Put the digit on the board, then call solve() again to fill the rest. If that call comes back True, the rest got filled and we are done — pass the True upward. If it comes back False, every path through this digit broke somewhere ahead, so take the digit back off the board and let the loop try the next one.

                    board[r][c] = num                     if solve():                        return True                     board[r][c] = '.'

Line 36 is the single most important line in the file: board[r][c] = '.'. It is the digit lifted off the board. Without it, the board would still show the wrong digit when the loop tried the next one, and the "walk back" would never happen.

No digit works

If the loop finishes without any digit leading to a solution, this cell cannot be filled with the board as it stands — someone before us chose wrongly. Say so: return False. And if the scan never found an empty cell at all, the board is full and every rule held along the way: return True.

                return False         return True

The whole thing

def solve_sudoku(board):    def valid(r, c, num):        for j in range(9):            if board[r][j] == num:                return False         for i in range(9):            if board[i][c] == num:                return False         box_r = (r // 3) * 3        box_c = (c // 3) * 3         for i in range(box_r, box_r + 3):            for j in range(box_c, box_c + 3):                if board[i][j] == num:                    return False         return True     def solve():        for r in range(9):            for c in range(9):                if board[r][c] != '.':                    continue                 for num in "123456789":                    if not valid(r, c, num):                        continue                     board[r][c] = num                     if solve():                        return True                     board[r][c] = '.'                 return False         return True     solve()

Every line is something that happened on the board. The table the video ends on says the same thing twice:

In the storyIn the code
Find an empty cellif board[r][c] != '.': continue
Try a choicefor num in "123456789":
Check if it is possiblevalid(r, c, num)
Make the choiceboard[r][c] = num
Keep goingsolve()
It workedif solve(): return True
It failedsolve() returned False
Undoboard[r][c] = '.'
Try anotherthe next turn of the for num loop
No choice worksreturn False
Everything solvedreturn True
The board stamped UNDO beside a code editor with the line board[r][c] = '.' highlighted; the narrator stands at the posts with trays 1, 2, 4, 8
The lifted digit and its line of code, side by side. If a line has no physical meaning to you, you are memorizing, not understanding.

10 · The programming insightWho walks back? The call stack

In the story, the walk back is a thing he does: a step at a time, lifting a digit at each post. In the code there is no "walk back" anywhere. So who does it?

Python does. Every solve() call that places a digit calls solve() again for the rest of the board, which calls solve() again, and so on — a stack of calls, one per placed digit. When the deepest call returns False, control goes back to the call before it, which is still standing on its own line 34 with its own r, c and num. That call lifts its digit on line 36 and tries the next one. If it runs out, it returns False too, and control steps back once more.

Above: the narrator at post B, a red X at post C, saying: In the animation, I walked backward. Below: two nested solve() calls, the inner one highlighted, with an arrow pointing back up
The character walking backwards is a picture of calls returning. Each return is one step back.

So failure travels backwards through the stack on its own, one level per False, until it reaches a call that still has digits to try. The recursion is not a trick to make the code short. It is the data structure that remembers where every fork was and what has been tried at each — for free.

11 · The costWhat it costs

Up to nine choices at each of the empty cells, one after another: in the worst case the tree has 9 × 9 × 9 … paths, one factor per empty cell — 9E for E empty cells. Our board has 51, and 951 is a number with 49 digits. Nothing can explore that.

Nothing has to. Every valid() that says no cuts off a whole branch before a single step is taken down it. On this board the program places a digit 4,208 times in total — wrong placements included — and arrives at the solution.

Two chips, O(9^E) and E = 51; the 49-digit value of 9 to the 51st; below it THE REAL RUN: 4,208 placements
The worst case and the real run on this board. The difference is the rules saying no early.
A wide tree of choices with most branches faded to grey and the surviving branches drawn dark
The grey branches were never visited. Rejecting a digit at a cell rejects every path that would have passed through it.

That is the lesson about cost, and it is the same lesson as the technique: backtracking becomes practical exactly to the degree that you can reject bad paths early. Sudoku is generous here — three rules, each a cheap check. A problem with weaker rules prunes less and costs more.

A thought to carry forward

4,208 placements for 51 cells is still eighty tries per cell. The program always picks the first empty cell. What if it picked the cell with the fewest allowed digits instead? That one change takes the run from 4,208 placements to 51 — one per cell, no wrong guess at all. That is part 2.

12 · Watch it runThe program, live

The real run on the real board

This is the Python above, translated to run in your browser, on the same board. Placed digits are purple; the yellow cell is the one being decided; a red flash is a dead end about to be undone. Speed it up to see the shape of the search, slow it down to see single choices.

placements 0undone 0dead ends 0empty cells left 51

13 · The lessonTwo questions for any problem like this

The important part of this problem is not the Sudoku, and not the recursion. It is realizing that you can make progress on a problem whose right answer you cannot see, as long as you can recognize a wrong one and take it back. Don't start by writing code. Answer two things first:

  1. What are my choices?

    At each step, what are the options I could take? Here: a digit from 1 to 9 for the current empty cell. In another problem: a letter for a position, a queen for a column, a coin for a slot.

  2. What makes a choice impossible?

    The rule that lets me reject an option early, before exploring it. Here: a repeat in the row, the column or the box. The stronger this rule, the smaller the tree you actually walk.

Answer those and the code is the loop from section 7 with your answers filled in: choose, try, go deeper, undo, next. If you can also say when you are done — here, no empty cell left — you have everything.

14 · PracticeFour problems, same shape

None of these mention a board. For each, write down your choices and your rejection rule before touching the keyboard.

  • Warm-upPermutations

    Given a few distinct numbers, list every possible order of them. The choice is "which unused number comes next"; the rejection rule is "already used". No dead ends here — every path reaches the end — which makes it the cleanest place to feel the undo.

  • PracticeThe Sudoku solver, from scratch

    Close this page and write valid and solve yourself. Then count the placements on this board; you should get 4,208. If you get a different number, your loop visits cells in a different order — find out why.

  • VariationWord search

    A grid of letters and a word: can the word be spelled by a path of neighbouring cells, each used once? The choice is "which neighbour next"; the rejection rule is "wrong letter, or already on the path". Same undo, different board.

  • ChallengeN queens

    Place N queens on an N-by-N chessboard so that none attacks another. Decide what one "choice" is (a whole column makes it easy), what a clash is, and how early you can detect one. Then count your dead ends.

The board completely filled, the placed digits in blue, the narrator beside it

Next — Part 2: the same solver, a smarter order →

4,208 placements to fill 51 cells is a lot of wrong guesses. Part 2 keeps every idea of this program and changes one decision — which empty cell to fill first — and watches the search shrink to 51 placements.

Make a choice. If it fails, go back. Try again. Don't fear the wrong path.