{"id":"dsa-backtracking-sudoku","slug":"sudoku","title":"A sudoku solver","text":"In a **sudoku**, some cells of a 9 × 9 grid hold digits from the start, and you fill in the rest. Each row, each column and each of the nine 3 × 3 boxes must end up with all the digits from 1 to 9, none of them twice. A person looks for a cell where only one digit can go. A program can get away with far less thought: it guesses, and takes the guess back when it leads nowhere. One call of the solver does this:\n\n1. Look for an empty cell. When there's none left, every cell holds a digit, and the puzzle is solved.\n2. Collect the digits that are **allowed** in that cell: the ones its row, its column and its box don't have yet.\n3. For each of them in turn, write it in the cell (choose) and call the solver on the grid as it is now (explore). If that call solves the puzzle, stop and report success.\n4. Otherwise rub the digit out (un-choose) before trying the next one. If none of the digits leads to a solution, report failure (`False`) at once: some digit written earlier, in another cell, was wrong, and the call that wrote it goes on to its next digit.\n\nHere is the whole recipe on a 4 × 4 sudoku, with the digits 1 to 4 and 2 × 2 boxes. The grid is a list of lists, with 0 for an empty cell:\n\n```python\ndef allowed(grid, row, col):\n    used = set(grid[row])                          # the row\n    used.update(grid[r][col] for r in range(4))    # the column\n    top = row // 2 * 2\n    left = col // 2 * 2\n    for r in range(top, top + 2):                  # the box\n        used.update(grid[r][left:left + 2])\n    return [d for d in range(1, 5) if d not in used]\n\n\ndef solve(grid):\n    for row in range(4):\n        for col in range(4):\n            if grid[row][col] == 0:\n                for digit in allowed(grid, row, col):\n                    grid[row][col] = digit         # choose\n                    if solve(grid):                # explore\n                        return True\n                    grid[row][col] = 0             # un-choose\n                return False                       # nothing fits here\n    return True                                    # no empty cell: solved\n\n\ngrid = [[0, 0, 0, 0],\n        [0, 1, 4, 0],\n        [3, 0, 0, 2],\n        [0, 0, 0, 0]]\nprint(solve(grid))\nfor line in grid:\n    print(*line)\n```\n\n```output\nTrue\n4 3 2 1\n2 1 4 3\n3 4 1 2\n1 2 3 4\n```\n\nOnly 4 digits are given, so the solver guesses a lot: it writes a digit 26 times and hits a dead end 14 times before every cell fits.\n\n### How it works\n\n`allowed` collects the digits in the cell's row, column and box in a set. `used.update(...)` adds every item it's given to the set, as `add` does for one item. The 0s of the empty cells go in too, which does no harm: 0 is never a digit to try. The box of a cell starts at row `row // 2 * 2` and column `col // 2 * 2`: `//` rounds down, so the rows 0 and 1 give 0, and the rows 2 and 3 give 2. On a 9 × 9 board the boxes are 3 × 3, so it's `// 3 * 3`, and cell (7, 4), in the eighth row and the fifth column, is in the box that starts at (6, 3):\n\n```pycon\n>>> [row // 3 * 3 for row in range(9)]\n[0, 0, 0, 3, 3, 3, 6, 6, 6]\n>>> row, col = 7, 4\n>>> row // 3 * 3, col // 3 * 3\n(6, 3)\n```\n\nTwo lines of `solve` are easy to get wrong:\n\n- `return False` stands right after the loop over the digits, **inside** the `if`. Leave it out, and when nothing fits a cell, the loops go on to the next empty cell, and the `return True` at the end reports a grid with holes in it as solved.\n- `grid[row][col] = 0` is the un-choose. Leave it out, and a failed digit stays in its cell, so the search treats that cell as filled from then on.\n\n### Which empty cell first?\n\nThe recipe fills the empty cells in reading order, which can be a very bad order. A smarter solver first looks at **every** empty cell and takes the one with the **fewest** allowed digits. A cell with one allowed digit is a forced move, with no guessing. A cell with none means this branch is already dead, and the solver backs up at once, where the reading order might find out only millions of placements later. On a typical 9 × 9 puzzle with 56 empty cells, the reading order writes a digit 6,649 times; fewest-first writes 56, one per cell, with no wrong guess at all. On some puzzles the reading order needs tens of millions of placements, minutes of Python, and fewest-first still needs about 60.\n\n### What it costs\n\nChecking a digit looks at the 27 cells of a row, a column and a box: on a 9 × 9 board that's O(1). What can explode is the number of placements: in the worst case, the search tries every digit in every empty cell, exponential in the number of empty cells. The givens and good choices prune nearly all of it. The recursion goes one call deeper per filled cell, at most 81, far from Python's limit.\n","task":"Write `solve(grid)` for a 9 × 9 sudoku: a list of 9 lists of 9 numbers, with 0 for an empty cell. Fill the grid in place, and return `True`, or `False` when the puzzle has no solution. Try the empty cells in reading order and the digits from 1 to 9. The tests write a puzzle as a string of its 9 rows and turn it into a grid. For example, this program:\n\n```python\npuzzle = \"000654001 103000050 000020000 200871000 540200170 000009000 305000090 010008060 008000007\"\ngrid = [[int(ch) for ch in line] for line in puzzle.split()]\nprint(solve(grid))\nfor line in grid:\n    print(\"\".join(str(d) for d in line))\n```\n\nprints:\n\n```\nTrue\n987654321\n123987456\n654123789\n236871945\n549236178\n871549632\n365712894\n712498563\n498365217\n```\n","kind":"code","seed":"def solve(grid):\n    pass\n\n\nif __name__ == \"__main__\":\n    puzzle = \"000654001 103000050 000020000 200871000 540200170 000009000 305000090 010008060 008000007\"\n    grid = [[int(ch) for ch in line] for line in puzzle.split()]\n    print(solve(grid))\n    for line in grid:\n        print(\"\".join(str(d) for d in line))\n","solution":"def allowed(grid, row, col):\n    used = set(grid[row])\n    used.update(grid[r][col] for r in range(9))\n    top = row // 3 * 3\n    left = col // 3 * 3\n    for r in range(top, top + 3):\n        used.update(grid[r][left:left + 3])\n    return [d for d in range(1, 10) if d not in used]\n\n\ndef solve(grid):\n    for row in range(9):\n        for col in range(9):\n            if grid[row][col] == 0:\n                for digit in allowed(grid, row, col):\n                    grid[row][col] = digit\n                    if solve(grid):\n                        return True\n                    grid[row][col] = 0\n                return False\n    return True\n\n\nif __name__ == \"__main__\":\n    puzzle = \"000654001 103000050 000020000 200871000 540200170 000009000 305000090 010008060 008000007\"\n    grid = [[int(ch) for ch in line] for line in puzzle.split()]\n    print(solve(grid))\n    for line in grid:\n        print(\"\".join(str(d) for d in line))\n","hints":["Start with `allowed(grid, row, col)` from the lesson, with 9 for 4 and 3 for 2: the box starts at `row // 3 * 3` and `col // 3 * 3`.","`solve` loops over the rows and columns to the first cell that holds 0. If the loops finish without finding one, the grid is full: return `True`.","For that cell, try each allowed digit: write it, `if solve(grid): return True`, otherwise write 0 back. After the loop over the digits, return `False` at once: don't go on to the next empty cell."],"tests":[{"name":"Test 1","stdin":"","call":"puzzle = \"000654001 103000050 000020000 200871000 540200170 000009000 305000090 010008060 008000007\"\ngrid = [[int(ch) for ch in line] for line in puzzle.split()]\nprint(solve(grid))\nfor line in grid:\n    print(\"\".join(str(d) for d in line))\n","expect":"True\n987654321\n123987456\n654123789\n236871945\n549236178\n871549632\n365712894\n712498563\n498365217","hidden":false},{"name":"Test 2","stdin":"","call":"puzzle = \"980000001 020708540 000000900 015020000 860500073 000000000 658410700 100009000 000800000\"\ngrid = [[int(ch) for ch in line] for line in puzzle.split()]\nprint(solve(grid))\nfor line in grid:\n    print(\"\".join(str(d) for d in line))\n","expect":"True\n987654321\n321798546\n546132987\n415327869\n869541273\n273986415\n658413792\n134279658\n792865134","hidden":true},{"name":"Test 3","stdin":"","call":"puzzle = \"907050020 400200000 310080400 500001002 029400006 100900000 040002000 008500600 005000083\"\ngrid = [[int(ch) for ch in line] for line in puzzle.split()]\nprint(solve(grid))\nprint(\"\".join(str(d) for d in grid[0]), \"\".join(str(d) for d in grid[8]))\n","expect":"True\n987654321 795146283","hidden":true},{"name":"Test 4","stdin":"","call":"grid = [[0] * 9 for i in range(9)]\nprint(solve(grid))\nrows_ok = all(sorted(line) == list(range(1, 10)) for line in grid)\ncols_ok = all(sorted(grid[r][c] for r in range(9)) == list(range(1, 10)) for c in range(9))\nboxes_ok = all(sorted(grid[r][c] for r in range(t, t + 3) for c in range(l, l + 3)) == list(range(1, 10)) for t in (0, 3, 6) for l in (0, 3, 6))\nprint(rows_ok, cols_ok, boxes_ok)\n","expect":"True\nTrue True True","hidden":true},{"name":"Test 5","stdin":"","call":"puzzle = \"001234567 008000000 000000000 000000000 000000000 000000000 000000000 000000000 000000000\"\ngrid = [[int(ch) for ch in line] for line in puzzle.split()]\nprint(solve(grid))\n","expect":"False","hidden":true}],"require":[],"forbid":[],"more":[{"task":"Whoever makes a new sudoku has to check that it has exactly one solution: with two, a player couldn't tell which one is meant. Counting every solution could take forever (an empty grid has about 6.7 × 10²¹ of them), but the puzzle maker only needs to know whether there are none, one or more. Write `count_solutions(grid, limit)`: the number of solutions of the puzzle, or `limit` when it has `limit` or more. It never returns more than `limit`, and it stops searching as soon as it has found that many.\n\nSearch like the solver, but when the grid is full, count 1 and go on with the next digit instead of stopping. A deeper call should look for only as many solutions as this call still wants, and the loop over the digits stops once the count reaches `limit`. Write 0 back after each digit, so the grid ends up as it was.\n\nFor example, this program (the second grid is empty, so it has far more than 3 solutions):\n\n```python\npuzzle = \"980000001 020708540 000000900 015020000 860500073 000000000 658410700 100009000 000800000\"\ngrid = [[int(ch) for ch in line] for line in puzzle.split()]\nprint(count_solutions(grid, 2))\nprint(count_solutions([[0] * 9 for i in range(9)], 3))\n```\n\nprints:\n\n```\n1\n3\n```\n","kind":"code","seed":"def count_solutions(grid, limit):\n    pass\n\n\nif __name__ == \"__main__\":\n    puzzle = \"980000001 020708540 000000900 015020000 860500073 000000000 658410700 100009000 000800000\"\n    grid = [[int(ch) for ch in line] for line in puzzle.split()]\n    print(count_solutions(grid, 2))\n    print(count_solutions([[0] * 9 for i in range(9)], 3))\n","solution":"def allowed(grid, row, col):\n    used = set(grid[row])\n    used.update(grid[r][col] for r in range(9))\n    top = row // 3 * 3\n    left = col // 3 * 3\n    for r in range(top, top + 3):\n        used.update(grid[r][left:left + 3])\n    return [d for d in range(1, 10) if d not in used]\n\n\ndef count_solutions(grid, limit):\n    for row in range(9):\n        for col in range(9):\n            if grid[row][col] == 0:\n                found = 0\n                for digit in allowed(grid, row, col):\n                    grid[row][col] = digit\n                    found += count_solutions(grid, limit - found)\n                    grid[row][col] = 0\n                    if found >= limit:\n                        break\n                return found\n    return 1\n\n\nif __name__ == \"__main__\":\n    puzzle = \"980000001 020708540 000000900 015020000 860500073 000000000 658410700 100009000 000800000\"\n    grid = [[int(ch) for ch in line] for line in puzzle.split()]\n    print(count_solutions(grid, 2))\n    print(count_solutions([[0] * 9 for i in range(9)], 3))\n","hints":["Keep the shape of `solve`: find the first empty cell, and return 1 when there's none, since a full grid is one solution.","For the empty cell, add up the counts of the digits you try, and write 0 back after each one, so that the next digit starts from the same grid.","Pass the deeper call how many solutions are still wanted, `limit - found`, and `break` out of the loop over the digits once `found` reaches `limit`."],"tests":[{"name":"Test 1","stdin":"","call":"puzzle = \"980000001 020708540 000000900 015020000 860500073 000000000 658410700 100009000 000800000\"\ngrid = [[int(ch) for ch in line] for line in puzzle.split()]\nprint(count_solutions(grid, 2))\nprint(count_solutions([[0] * 9 for i in range(9)], 3))\n","expect":"1\n3","hidden":false},{"name":"Test 2","stdin":"","call":"puzzle = \"980000001 020708540 000000900 015020000 860500073 000000000 650410700 100009000 000800000\"\ngrid = [[int(ch) for ch in line] for line in puzzle.split()]\nprint(count_solutions(grid, 10))\n","expect":"2","hidden":true},{"name":"Test 3","stdin":"","call":"puzzle = \"980000001 020708040 000000900 015020000 860500073 000000000 658410700 100009000 000800000\"\nprint(count_solutions([[int(ch) for ch in line] for line in puzzle.split()], 10))\nprint(count_solutions([[int(ch) for ch in line] for line in puzzle.split()], 3))\n","expect":"5\n3","hidden":true},{"name":"Test 4","stdin":"","call":"puzzle = \"980000001 020708040 000000900 015020000 860500073 000000000 658410700 100009000 000800000\"\ngrid = [[int(ch) for ch in line] for line in puzzle.split()]\nprint(count_solutions(grid, 3), count_solutions(grid, 10), sum(line.count(0) for line in grid))\n","expect":"3 5 56","hidden":true},{"name":"count_solutions([[0] * 9 for i in range(9)], 4)","stdin":"","call":"count_solutions([[0] * 9 for i in range(9)], 4)\n","expect":"4","hidden":true,"returns":true},{"name":"Test 6","stdin":"","call":"puzzle = \"001234567 008000000 000000000 000000000 000000000 000000000 000000000 000000000 000000000\"\ngrid = [[int(ch) for ch in line] for line in puzzle.split()]\nprint(count_solutions(grid, 5))\n","expect":"0","hidden":true}],"require":[],"forbid":[]},{"task":"Write `solve_fast(grid)`: a solver that fills first the empty cell with the **fewest** allowed digits, as the lesson describes. It takes and returns the same as `solve`. Before each choice, look at every empty cell, keep the one with the shortest list of allowed digits, and try its digits. If that list is empty, return `False` at once. Two of the hidden tests are puzzles on which the reading order needs tens of millions of placements.\n\nFor example, this program:\n\n```python\npuzzle = \"080604021 000000780 000000054 018090000 340007006 600200007 509060000 000108000 030000000\"\ngrid = [[int(ch) for ch in line] for line in puzzle.split()]\nprint(solve_fast(grid))\nfor line in grid:\n    print(\"\".join(str(d) for d in line))\n```\n\nprints:\n\n```\nTrue\n987654321\n456321789\n123789654\n718596243\n342817596\n695243817\n579462138\n264138975\n831975462\n```\n","kind":"code","seed":"def solve_fast(grid):\n    pass\n\n\nif __name__ == \"__main__\":\n    puzzle = \"080604021 000000780 000000054 018090000 340007006 600200007 509060000 000108000 030000000\"\n    grid = [[int(ch) for ch in line] for line in puzzle.split()]\n    print(solve_fast(grid))\n    for line in grid:\n        print(\"\".join(str(d) for d in line))\n","solution":"def allowed(grid, row, col):\n    used = set(grid[row])\n    used.update(grid[r][col] for r in range(9))\n    top = row // 3 * 3\n    left = col // 3 * 3\n    for r in range(top, top + 3):\n        used.update(grid[r][left:left + 3])\n    return [d for d in range(1, 10) if d not in used]\n\n\ndef solve_fast(grid):\n    best = None\n    best_digits = None\n    for row in range(9):\n        for col in range(9):\n            if grid[row][col] == 0:\n                digits = allowed(grid, row, col)\n                if best is None or len(digits) < len(best_digits):\n                    best = (row, col)\n                    best_digits = digits\n    if best is None:\n        return True                   # no empty cell: solved\n    row, col = best\n    for digit in best_digits:         # none allowed: the loop is skipped\n        grid[row][col] = digit\n        if solve_fast(grid):\n            return True\n        grid[row][col] = 0\n    return False\n\n\nif __name__ == \"__main__\":\n    puzzle = \"080604021 000000780 000000054 018090000 340007006 600200007 509060000 000108000 030000000\"\n    grid = [[int(ch) for ch in line] for line in puzzle.split()]\n    print(solve_fast(grid))\n    for line in grid:\n        print(\"\".join(str(d) for d in line))\n","hints":["Use `allowed` from your solver. In `solve_fast`, loop over every cell, and for each empty one compare the length of its list of allowed digits with the best so far.","Keep the best cell's position and its list. If no cell was empty, the grid is solved: return `True`.","Then try the best cell's digits exactly as `solve` does: write, recurse, write 0 back, and return `False` after the loop. An empty list skips the loop, so a dead cell returns `False` straight away.","Filling the cells in reading order solves every puzzle too, but on the two big tests it writes a digit about 27 million and 59 million times."],"tests":[{"name":"Test 1","stdin":"","call":"puzzle = \"080604021 000000780 000000054 018090000 340007006 600200007 509060000 000108000 030000000\"\ngrid = [[int(ch) for ch in line] for line in puzzle.split()]\nprint(solve_fast(grid))\nfor line in grid:\n    print(\"\".join(str(d) for d in line))\n","expect":"True\n987654321\n456321789\n123789654\n718596243\n342817596\n695243817\n579462138\n264138975\n831975462","hidden":false},{"name":"Test 2","stdin":"","call":"puzzle = \"000654001 103000050 000020000 200871000 540200170 000009000 305000090 010008060 008000007\"\ngrid = [[int(ch) for ch in line] for line in puzzle.split()]\nprint(solve_fast(grid))\nprint(\"\".join(str(d) for d in grid[4]), \"\".join(str(d) for d in grid[8]))\n","expect":"True\n549236178 498365217","hidden":true},{"name":"Test 3","stdin":"","call":"puzzle = \"001234567 008000000 000000000 000000000 000000000 000000000 000000000 000000000 000000000\"\ngrid = [[int(ch) for ch in line] for line in puzzle.split()]\nprint(solve_fast(grid))\n","expect":"False","hidden":true},{"name":"Test 4","stdin":"","call":"puzzle = \"907000020 000000000 000080406 000000000 018000003 000700590 000000108 040000005 800579040\"\ngrid = [[int(ch) for ch in line] for line in puzzle.split()]\nprint(solve_fast(grid))\nfor line in grid:\n    print(\"\".join(str(d) for d in line))\n","expect":"True\n987654321\n654123789\n123987456\n495362817\n718495263\n362718594\n579246138\n246831975\n831579642","hidden":true,"big":true},{"name":"Test 5","stdin":"","call":"puzzle = \"900600000 000100000 000900004 030008000 040000090 000400010 600030008 070046002 100800050\"\ngrid = [[int(ch) for ch in line] for line in puzzle.split()]\nprint(solve_fast(grid))\nfor line in grid:\n    print(\"\".join(str(d) for d in line))\n","expect":"True\n987654321\n465123789\n312987564\n231798645\n546312897\n798465213\n654231978\n879546132\n123879456","hidden":true,"big":true}],"require":[],"forbid":[]}]}