This Sudoku solver uses a number of recursive queries, first to generate fixed data structures and then to drive the search for a solution.
This solver simply applies the rules.
- Every row, column and box (3×3) must have the digits 1 to 9 once and once only.
- If only one digit can go in a cell then it must go there.
- If a digit can go in only one place in a row, column or box then it must go there.
Here is the code.
First, the fixed data structures.
digits := {{ sdigit:= '1', ndigit := 1}} recurse( {{ sdigit:=text(ndigit+1), ndigit:=ndigit+1 }} [?(ndigit <= 9)] ) digitsx := digits union {{ sdigit := '.', ndigit := 0 }} units := {{ index := 0, row := 0, col := 0, box := 0 }} recurse( {{ index := index + 1, row := (index + 1) div 9, col := (index + 1) mod 9, box := (index + 1) div 3 mod 3 + (index + 1) div 27 * 3 }} [?(index <= 80)] ) poss := units [{ index }] join digits [{ ndigit }] possu := units join digits [{ ndigit }]
Now some useful functions.
showb(t:text) => do { seq(11)[{ N, line:= if(N mod 4 = 3, fill('-', 9), right(left(t, 9 + (N - N div 4) * 9), 9))}] } // Show a set of knowns. First fill out all index values, then convert to text showunk(k:poss) => do { t := (k union (units ajoin k)[{ index, ndigit := 0}]) join digitsx[{ ndigit, sdigit }] showb(t [$(index)][{ fold(&, sdigit) }]) }
The original raw data
inp := {{ sud := '53..7....6..195....98....6.8...6...34..8.3..17...2...6.6....28....419..5....8..79' }} //inp := {{ sud := '1....7.9..3..2...8..96..5....53..9...1..8...26....4...3......1..4......7..7...3..' }} inp board := ((units join inp) [{ * sud, sdigit := right(left(sud, index + 1), 1) }] compose digitsx) [{ index, ndigit }] knowns := board [?( ndigit <> 0)] 'Knowns=' & knowns.count showunk(knowns)
This the solver, which recurses as long as it can make progress. After this you have to guess.
solution := knowns recurse( do { // start with the 729 possiblities, progressively remove conflicts with knowns knownsu := knowns join units allowedu := possu ajoin knownsu[{ index }] ajoin knownsu[{ row, ndigit }] ajoin knownsu[{ col, ndigit }] ajoin knownsu[{ box, ndigit }] // algorithm 1 - a cell with only one possible digit must be that digit new1 := allowedu [{ index, tot:=fold(+,1) }] [?(tot=1)] join allowedu // algorithm 2 - a digit with only one place in a unit must go there new2a := allowedu [{ ndigit, row, tot:=fold(+,1) }] [?(tot=1)] join allowedu new2b := allowedu [{ ndigit, col, tot:=fold(+,1) }] [?(tot=1)] join allowedu new2c := allowedu [{ ndigit, box, tot:=fold(+,1) }] [?(tot=1)] join allowedu new1[{ index, ndigit }] union new2a union new2b union new2c } ) showunk(solution)
And here is the grid, before and after solving.
N | line ------------------ 0 | 53..7.... 1 | 6..195... 2 | .98....6. 3 | --------- 4 | 8...6...3 5 | 4..8.3..1 6 | 7...2...6 7 | --------- 8 | .6....28. 9 | ...419..5 10 | ....8..79 N | line ------------------ 0 | 534678912 1 | 672195348 2 | 198342567 3 | --------- 4 | 859761423 5 | 426853791 6 | 713924856 7 | --------- 8 | 961537284 9 | 287419635 10 | 345286179