Sudoku

Problem Statement

A simple sudoku solving problem.

Full example scenario

A standard 9x9 Sudoku puzzle needs solving: filling in the missing digits so that every row, every column and every 3x3 sub-grid contains each of the digits 1 through 9 exactly once. Which digits belong in the empty cells below, marked with periods?

.284763..
...839.2.
7..512.8.
..179..4.
3........
..9...1..
.5..8....
..692...5
..2645..8
  • The grid has 33 pre-filled cells and 48 empty ones.

  • Every row, column and 3x3 sub-grid must end up containing each of 1-9 exactly once.

  • Any cell already filled in above must keep that exact digit in the solution.

  • The same 33 pre-filled cells can be found in sudoku.csv, with the columns row,col,value.

What an optimal solution looks like

928476351
514839627
763512984
281793546
375164892
649258173
457381269
836927415
192645738
Given (33 cells) Filled by the solver (48 cells)

The solver re-solved with the first solution excluded and found no second one — this grid is the puzzle's only valid completion.

Built with Modeler

The problem above is stated as a single shot: you hand over the whole problem and get a model back. Modeler takes the other route — you start with the business question you actually have, and it works with you until the problem is pinned down, the data is in, the code runs, and the answer holds up when the problem changes.

The tabs below walk the same sudoku problem through that route, one Modeler capability at a time.

Instead of writing the whole prompt up front, you start with the business question you actually have. Modeler searches the knowledge base, asks one clarifying question at a time — always the most important one first — and tells you which parts of the model are still missing. The options it offers come from examples in the knowledge base and from how similar problems are usually modeled, so you can answer with a number instead of prose.

I’ve got a sudoku puzzle I’d like solved automatically. Can you help me build a model for that?

Sudoku is a well-known constraint-satisfaction problem, but the grid size and the exact input/output shape are not fixed by the term alone. Let me check the knowledge base for how this is usually modeled, then ask about grid size first, since it determines every constraint family before anything else can be pinned down.

Question 1: What grid size are you targeting for the puzzle?

  1. 9x9 (standard Sudoku) — 9 rows, 9 columns, nine 3x3 sub-grids, digits 1-9

  2. 4x4 (mini Sudoku) — 4 rows, 4 columns, four 2x2 sub-grids, digits 1-4

  3. 16x16 (super Sudoku) — 16 rows, 16 columns, sixteen 4x4 sub-grids, digits 1-16

  4. General N x N — parameterised so any valid square size works

Learn More:
• Sudoku Examples ★★★
• sudoku_c.c ★★☆

Standard 9x9 sudoku.

Grid size is fixed. Next open question is how the puzzle itself will arrive — that shapes the parsing logic in the implementation, so it is worth settling before anything else.

Noted — a standard 9x9 Sudoku it is.

Question 2: How would you like to provide the puzzle input (the pre-filled “given” cells)?

  1. Flat string of 81 characters — e.g. "530070000600195000...", 0 for empty

  2. 9x9 nested list / 2D array — 0 for empty

  3. List of (row, col, value) tuples — only the non-empty cells listed

  4. Pandas DataFrame — columns row, col, value for the pre-filled cells only

A 9x9 grid works, but the raw puzzle I have is text-based — 9 lines of 9 characters, using periods for the empty cells instead of 0. Can the model read that directly, or should I convert it first?

The user’s actual format is close to option 2 but uses periods rather than zeros — no reason to make them convert it by hand, the parser can just read that directly. That still leaves open how the solver should behave on a puzzle with no valid solution at all, which matters for the output contract.

The model can read your text format directly — no conversion needed. The implementation will include a parser that reads the 9-line string and treats . as an empty cell.

Question 3: How should the solver handle the case where the puzzle has no valid solution (e.g. an invalid or contradictory input)?

  1. Return a result dictionary with is_feasible=False and solution=None, no exception

  2. Raise an exception with a descriptive error message

  3. Print a warning message and return None

1. A result dictionary with is_feasible=False and solution=None sounds good, no exceptions. Also, I’d like the output to flag if the puzzle had more than one valid solution, not just return the first one it finds — I want to know if the puzzle is well-posed.

That is a real fifth constraint, not just an output preference — the solver needs to search for a second solution after finding the first, which changes the solve procedure itself. Recording it as C5. Still open: what shape the completed grid comes back in.

Specification updated. That is a great requirement — checking for uniqueness is very useful, and the solver will handle it automatically by searching for a second solution after finding the first one.

Question 4: How would you like the completed solution grid to be returned in the output?

  1. 9x9 nested list of integers

  2. Same text format as the input — 9 lines of 9 characters

  3. Both — include both representations in the result dictionary

  4. Pandas DataFrame — columns row, col, value

Both formats would be great — the nested list for programmatic use and the text version for printing. One more thing: the puzzle I actually have is fairly tricky (very few givens), so please make sure whatever test data you use to validate this reflects that — I don’t want the tests to only cover easy puzzles with lots of clues.

Noted for the test scenarios rather than the model itself — a hard, low-clue puzzle exercises the uniqueness check much harder than an easy one does, since presolve alone rarely closes a near-empty grid. One more open question: whether the second solve, for uniqueness, needs a time guard.

Specification updated. The test scenarios now include a hard puzzle with very few givens, a multi-solution case, an infeasible case, and a fully solved edge case.

Question 5: For the uniqueness check, once a first solution is found, the solver will search for a second one. Should there be a time limit applied to this second search, to protect against very long solve times on ambiguous puzzles?

  1. Yes, apply a short fixed time limit (e.g. 10 seconds), reporting is_unique=True conservatively if none is found in time

  2. No time limit — always run the full second search

  3. Make it configurable — accept an optional time_limit parameter with a sensible default

3. Let’s make it configurable with a time_limit parameter, defaulting to something reasonable like 10 seconds.

That was the last open modeling question. Everything needed to implement is now recorded, except the puzzle itself hasn’t arrived as a file yet — worth asking for one, since a file is easier to get right than dictating 81 characters over chat.

That completes the specification. One last thing before I generate the specification document in full: could you attach the puzzle itself as a file, rather than pasting it into the chat? A file is easier to double-check for typos than 81 characters typed by hand.

Sure — attaching it now.

Modeler updates the specification after every answer, even while it is still incomplete — so you can always see what it has understood and what it is still waiting on.