Sudoku: Difference between revisions

397,734 bytes added ,  2 months ago
m
moved commentary outside the code block.
m (<lang> needs a language)
m (moved commentary outside the code block.)
 
(301 intermediate revisions by 79 users not shown)
Line 1:
{{task|Games}}
 
Solve a partially filled-in normal 9x9 [[wp:Sudoku|Sudoku]] grid and display the result in a human-readable format. [[wp:Algorithmics_of_sudoku|Algorithmics of Sudoku]] may help implement this.
;Task:
Solve a partially filled-in normal &nbsp; 9x9 &nbsp; [[wp:Sudoku|Sudoku]] grid &nbsp; and display the result in a human-readable format.
 
;references:
* [[wp:Algorithmics_of_sudoku|Algorithmics of Sudoku]] &nbsp; may help implement this.
* [https://www.youtube.com/watch?v=G_UYXzGuqvM Python Sudoku Solver] Computerphile video.
<br><br>
 
=={{header|11l}}==
{{trans|Kotlin}}
 
<syntaxhighlight lang="11l">T Sudoku
solved = 0B
grid = [0] * 81
 
F (rows)
assert(rows.len == 9 & all(rows.map(row -> row.len == 9)), ‘Grid must be 9 x 9’)
L(i) 9
L(j) 9
.grid[9 * i + j] = Int(rows[i][j])
 
F solve()
print("Starting grid:\n\n"(.))
.placeNumber(0)
print(I .solved {"Solution:\n\n"(.)} E ‘Unsolvable!’)
 
F placeNumber(pos)
I .solved
R
I pos == 81
.solved = 1B
R
 
I .grid[pos] > 0
.placeNumber(pos + 1)
R
 
L(n) 1..9
I .checkValidity(n, pos % 9, pos I/ 9)
.grid[pos] = n
.placeNumber(pos + 1)
I .solved
R
.grid[pos] = 0
 
F checkValidity(v, x, y)
L(i) 9
I .grid[y * 9 + i] == v |
.grid[i * 9 + x] == v
R 0B
 
V startX = (x I/ 3) * 3
V startY = (y I/ 3) * 3
L(i) startY .< startY + 3
L(j) startX .< startX + 3
I .grid[i * 9 + j] == v
R 0B
 
R 1B
 
F String()
V s = ‘’
L(i) 9
L(j) 9
s ‘’= .grid[i * 9 + j]‘ ’
I j C (2, 5)
s ‘’= ‘| ’
s ‘’= "\n"
I i C (2, 5)
s ‘’= "------+-------+------\n"
R s
 
V rows = [‘850002400’,
‘720000009’,
‘004000000’,
‘000107002’,
‘305000900’,
‘040000000’,
‘000080070’,
‘017000000’,
‘000036040’]
 
Sudoku(rows).solve()</syntaxhighlight>
 
{{out}}
<pre>
Starting grid:
 
8 5 0 | 0 0 2 | 4 0 0
7 2 0 | 0 0 0 | 0 0 9
0 0 4 | 0 0 0 | 0 0 0
------+-------+------
0 0 0 | 1 0 7 | 0 0 2
3 0 5 | 0 0 0 | 9 0 0
0 4 0 | 0 0 0 | 0 0 0
------+-------+------
0 0 0 | 0 8 0 | 0 7 0
0 1 7 | 0 0 0 | 0 0 0
0 0 0 | 0 3 6 | 0 4 0
 
Solution:
 
8 5 9 | 6 1 2 | 4 3 7
7 2 3 | 8 5 4 | 1 6 9
1 6 4 | 3 7 9 | 5 2 8
------+-------+------
9 8 6 | 1 4 7 | 3 5 2
3 7 5 | 2 6 8 | 9 1 4
2 4 1 | 5 9 3 | 7 8 6
------+-------+------
4 3 2 | 9 8 1 | 6 7 5
6 1 7 | 4 2 5 | 8 9 3
5 9 8 | 7 3 6 | 2 4 1
 
</pre>
 
=={{header|8th}}==
<syntaxhighlight lang="8th">
\
\ Simple iterative backtracking Sudoku solver for 8th
\
needs array/each-slice
 
[ 00, 00, 00, 03, 03, 03, 06, 06, 06,
00, 00, 00, 03, 03, 03, 06, 06, 06,
00, 00, 00, 03, 03, 03, 06, 06, 06,
27, 27, 27, 30, 30, 30, 33, 33, 33,
27, 27, 27, 30, 30, 30, 33, 33, 33,
27, 27, 27, 30, 30, 30, 33, 33, 33,
54, 54, 54, 57, 57, 57, 60, 60, 60,
54, 54, 54, 57, 57, 57, 60, 60, 60,
54, 54, 54, 57, 57, 57, 60, 60, 60 ] constant top-left-cell
 
\ Bit number presentations
a:new 2 b:new b:clear a:push ( 2 b:new b:clear swap 1 b:bit! a:push ) 0 8 loop constant posbit
 
: posbit? \ n -- s
posbit swap a:@ nip ;
 
: search \ b -- n
null swap
( dup -rot b:bit@ if rot drop break else nip then ) 0 8 loop
swap ;
 
: b-or \ b b -- b
' n:bor b:op ;
 
: b-and \ b b -- b
' n:band b:op ;
 
: b-xor \ b b -- b
b:xor
[ xff, x01 ] b:new
b-and ;
: b-not \ b -- b
xff b:xor
[ xff, x01 ] b:new
b-and ;
 
: b-any \ a -- b
' b-or 0 posbit? a:reduce ;
 
: row \ a row -- a
9 n:* 9 a:slice ;
 
: col \ a col -- a
-1 9 a:slice+ ;
 
\ For testing sub boards
: sub \ a n -- a
top-left-cell swap a:@ nip over over 3 a:slice
-rot 9 n:+ 2dup 3 a:slice
-rot 9 n:+ 3 a:slice
a:+ a:+ ;
 
a:new 0 args "Give Sudoku text file as param" thrownull
f:slurp "Cannot read file" thrownull >s "" s:/
' >n a:map ( posbit? a:push ) a:each! drop constant board
 
: display-board
board ( search nip -1 ?: n:1+ ) a:map
"+-----+-----+-----+\n"
"|%d %d %d|%d %d %d|%d %d %d|\n" s:+
"|%d %d %d|%d %d %d|%d %d %d|\n" s:+
"|%d %d %d|%d %d %d|%d %d %d|\n" s:+
"+-----+-----+-----+\n" s:+
"|%d %d %d|%d %d %d|%d %d %d|\n" s:+
"|%d %d %d|%d %d %d|%d %d %d|\n" s:+
"|%d %d %d|%d %d %d|%d %d %d|\n" s:+
"+-----+-----+-----+\n" s:+
"|%d %d %d|%d %d %d|%d %d %d|\n" s:+
"|%d %d %d|%d %d %d|%d %d %d|\n" s:+
"|%d %d %d|%d %d %d|%d %d %d|\n" s:+
"+-----+-----+-----+\n" s:+
s:strfmt . ;
 
\ Store move history
a:new constant history
 
\ Possible numbers for a cell
: candidates? \ n -- s
dup dup 9 n:/ n:int swap 9 n:mod \ row col
board swap col b-any
board rot row b-any
b-or
board rot sub b-any
b-or
b-not ;
\ If found: -- n T
\ If not found: -- T
: find-free-cell
false
board ( 0 posbit? b:= if nip true break else drop then ) a:each drop ;
 
: validate
true
board
( dup -rot a:@ swap 2 pick 0 posbit? a:! 2 pick candidates? 2 pick b:= if
-rot a:!
else
2drop drop
false swap
break
then ) 0 80 loop drop ;
 
: solve
repeat
find-free-cell if
dup candidates?
repeat
search null? if
drop board -rot a:! drop
history a:len 0 n:= if
drop false ;;
then
a:pop nip
a:open
else
n:1+ posbit?
dup
board 4 pick rot a:! drop
b-xor
2 a:close
history swap a:push drop
break
then
again
else
validate
break
then
again ;
 
: app:main
"Sudoku puzzle:\n" .
display-board cr
solve if
"Sudoku solved:\n" .
display-board
else
"No solution!\n" .
then ;
</syntaxhighlight>
 
=={{header|Ada}}==
{{trans|C++}}
<lang Ada>with Ada.Text_IO;
<syntaxhighlight lang="ada">
with Ada.Text_IO;
 
procedure Sudoku is
subtypetype Numbersudoku_ar_t is Naturalarray ( integer range 0 ..80 ) of integer range 0..9;
FINISH_EXCEPTION : exception;
subtype Valid_Number is Number range 1 .. 9;
type Board is array (Valid_Number, Valid_Number) of Number;
 
procedure prettyprint(sudoku_ar: sudoku_ar_t);
function Check_Row (Data : in Board; Row : in Valid_Number) return Boolean is
function checkValidity( val : integer; x : integer; y : integer; sudoku_ar: in sudoku_ar_t) return Boolean;
Seen : array (Valid_Number) of Boolean := (others => False);
procedure placeNumber(pos: Integer; sudoku_ar: in out sudoku_ar_t);
The_Number : Number;
procedure solve(sudoku_ar: in out sudoku_ar_t);
begin
for Column in Data'Range (2) loop
The_Number := Data (Row, Column);
if The_Number in Valid_Number then
if Seen (The_Number) then
return False;
end if;
Seen (The_Number) := True;
end if;
end loop;
return True;
end Check_Row;
 
 
function Check_Column (Data : in Board; Column : in Valid_Number) return Boolean is
function checkValidity( val : integer; x : integer; y : integer; sudoku_ar: in sudoku_ar_t) return Boolean
Seen : array (Valid_Number) of Boolean := (others => False);
is
The_Number : Number;
begin
for Rowi in Data'Range (1)0..8 loop
 
The_Number := Data (Row, Column);
if The_Number( insudoku_ar( Valid_Numbery * 9 + i ) = val or sudoku_ar( i * 9 + x ) = val ) then
ifreturn Seen (The_Number) thenFalse;
return False;
end if;
Seen (The_Number) := True;
end if;
end loop;
return True;
end Check_Column;
 
declare
function Check_Square (Data : in Board; Row, Column : in Valid_Number) return Boolean is
Seen startX : constant integer : array= (Valid_Number) ofx Boolean/ :=3 (others) =>* False)3;
The_Number startY : Numberconstant integer := ( y / 3 ) * 3;
begin
Row_Offset : constant Number := ((Row - 1) / 3) * 3;
for i in startY..startY+2 loop
Column_Offset : constant Number := ((Column - 1) / 3) * 3;
for j in startX..startX+2 loop
begin
if ( sudoku_ar( i * 9 +j ) = val ) then
for Sub_Row in 1 .. 3 loop
for Sub_Column in 1 .. 3 loop
The_Number := Data (Row_Offset + Sub_Row, Column_Offset + Sub_Column);
if The_Number in Valid_Number then
if Seen (The_Number) then
return False;
end if;
end Seen (The_Number) := Trueloop;
end if;
end loop;
end loop return True;
return Trueend;
end Check_SquarecheckValidity;
 
function Is_Valid (Data : in Board) return Boolean is
Result : Boolean := True;
begin
for Row in Data'Range (1) loop
Result := Result and Check_Row (Data, Row);
end loop;
for Column in Data'Range (2) loop
Result := Result and Check_Column (Data, Column);
end loop;
for Square_Row in 1 .. 3 loop
for Square_Column in 1 .. 3 loop
Result := Result and Check_Square (Data, Square_Row * 3, Square_Column * 3);
end loop;
end loop;
return Result;
end Is_Valid;
 
Unsolvable : Exception;
 
procedure Solve placeNumber(Datapos: Integer; sudoku_ar: in out Boardsudoku_ar_t) is
is
Solved : Boolean := False;
-- Try all possible values for given cell and continue with next cell.
procedure Place_Number (Row, Column : Valid_Number) is
Next_Row : Valid_Number := Row;
Next_Column : Valid_Number := Column;
Last : Boolean := False;
begin
-- determine if this is the last cell or else the next cell coordinates
if Row = Data'Last (1) and then Column = Data'Last (2) then
Last := True;
elsif Row = Data'Last (1) then
Next_Row := Data'First (1);
Next_Column := Column + 1;
else
Next_Row := Row + 1;
end if;
-- only need to try values for nonvalid cell entries (0)
if Data (Row, Column) not in Valid_Number then
-- try all possible values
for Test in Valid_Number loop
-- set the cell
Data (Row, Column) := Test;
if Is_Valid (Data) then
-- the last cell was processed and lead to a valid sudoku
-- this means all cells have valid entries -> solved.
if Last then
Solved := True;
return;
else
-- try next cells
Place_Number (Next_Row, Next_Column);
-- if we have a solved sudoku, exit procedure.
if Solved then
return;
end if;
end if;
end if;
-- reset the cell, it will be tried later again
Data (Row, Column) := 0;
end loop;
elsif Last then
-- last cell, already valid, it is solved and there is nothing to do
Solved := True;
else
-- this cell already has a value, continue to next
Place_Number (Next_Row, Next_Column);
end if;
end Place_Number;
begin
--if only( acceptpos sudokus= without81 inconsistencies) then
if not Is_Valid (Data)raise thenFINISH_EXCEPTION;
raise Constraint_Error;
end if;
--if start( with firstsudoku_ar(pos) cell> 0 ) then
Place_Number (Data'First placeNumber(pos+1), Data'First (2)sudoku_ar);
return;
-- tried all combinations without success -> unsolvable.
if not Solved then
raise Unsolvable;
end if;
for n in 1..9 loop
end Solve;
if( checkValidity( n, pos mod 9, pos / 9 , sudoku_ar ) ) then
sudoku_ar(pos) := n;
placeNumber(pos + 1, sudoku_ar );
sudoku_ar(pos) := 0;
end if;
end loop;
end placeNumber;
 
 
procedure Print_Board (Data : in Board) is
procedure solve(sudoku_ar: in out sudoku_ar_t)
package Number_IO is new Ada.Text_IO.Integer_IO (Number);
is
begin
placeNumber( 0, sudoku_ar );
for X in Data'Range (1) loop
Ada.Text_IO.Put_Line("Unresolvable !");
for Y in Data'Range (2) loop
exception
Number_IO.Put (Data (X, Y));
when FINISH_EXCEPTION end loop;=>
Ada.Text_IO.New_LinePut_Line("Finished !");
prettyprint(sudoku_ar);
end solve;
 
 
 
 
procedure prettyprint(sudoku_ar: sudoku_ar_t)
is
line_sep : constant String := "------+------+------";
begin
for i in sudoku_ar'Range loop
Ada.Text_IO.Put(sudoku_ar(i)'Image);
if (i+1) mod 3 = 0 and not((i+1) mod 9 = 0) then
Ada.Text_IO.Put("|");
end if;
if (i+1) mod 9 = 0 then
Ada.Text_IO.Put_Line("");
end if;
if (i+1) mod 27 = 0 then
Ada.Text_IO.Put_Line(line_sep);
end if;
end loop;
end Print_Boardprettyprint;
 
sudoku_ar : sudoku_ar_t :=
(
8,5,0,0,0,2,4,0,0,
7,2,0,0,0,0,0,0,9,
0,0,4,0,0,0,0,0,0,
0,0,0,1,0,7,0,0,2,
3,0,5,0,0,0,9,0,0,
0,4,0,0,0,0,0,0,0,
0,0,0,0,8,0,0,7,0,
0,1,7,0,0,0,0,0,0,
0,0,0,0,3,6,0,4,0
);
 
Sample_Board : Board := (1 => (3, 9, 4, 0, 0, 2, 6, 7, 0),
2 => (0, 0, 0, 3, 0, 0, 4, 0, 0),
3 => (5, 0, 0, 6, 9, 0, 0, 2, 0),
4 => (0, 4, 5, 0, 0, 0, 9, 0, 0),
5 => (6, 0, 0, 0, 0, 0, 0, 0, 7),
6 => (0, 0, 7, 0, 0, 0, 5, 8, 0),
7 => (0, 1, 0, 0, 6, 7, 0, 0, 8),
8 => (0, 0, 9, 0, 0, 8, 0, 0, 0),
9 => (0, 2, 6, 4, 0, 0, 7, 3, 5));
begin
solve( sudoku_ar );
Ada.Text_IO.Put_Line ("Unsolved:");
end Sudoku;
Print_Board (Sample_Board);
</syntaxhighlight>
Solve (Sample_Board);
 
Ada.Text_IO.Put_Line ("Solved:");
{{out}}
Print_Board (Sample_Board);
<pre>
end Sudoku;</lang>
Finished !
Output:
8 5 9| 6 1 2| 4 3 7
<pre>Unsolved:
37 92 43| 08 05 24| 1 6 7 09
01 06 04| 3 07 09| 45 02 08
------+------+------
5 0 0 6 9 0 0 2 0
09 48 56| 01 04 07| 93 05 02
63 07 05| 02 06 08| 09 01 74
02 04 71| 05 09 03| 57 8 06
------+------+------
0 1 0 0 6 7 0 0 8
04 03 2| 9 0 0 8 01| 6 07 05
06 21 67| 4 02 05| 78 39 53
5 9 8| 7 3 6| 2 4 1
Solved:
</pre>
3 9 4 8 5 2 6 7 1
2 6 8 3 7 1 4 5 9
5 7 1 6 9 4 8 2 3
1 4 5 7 8 3 9 6 2
6 8 2 9 4 5 3 1 7
9 3 7 1 2 6 5 8 4
4 1 3 5 6 7 2 9 8
7 5 9 2 3 8 1 4 6
8 2 6 4 1 9 7 3 5</pre>
 
=={{header|ALGOL 68}}==
Line 196 ⟶ 401:
{{works with|ALGOL 68G|Any - tested with release [http://sourceforge.net/projects/algol68/files/algol68g/algol68g-1.18.0/algol68g-1.18.0-9h.tiny.el5.centos.fc11.i386.rpm/download 1.18.0-9h.tiny].}}
{{wont work with|ELLA ALGOL 68|Any (with appropriate job cards) - tested with release [http://sourceforge.net/projects/algol68/files/algol68toc/algol68toc-1.8.8d/algol68toc-1.8-8d.fc9.i386.rpm/download 1.8-8d] - due to extensive use of '''format'''[ted] ''transput''.}}
<langsyntaxhighlight lang="algol68">MODE AVAIL = [9]BOOL;
MODE BOX = [3, 3]CHAR;
 
Line 290 ⟶ 495:
"__1__6__9"))
END CO
)</langsyntaxhighlight>
{{out}}
Output:
<pre>
Completed puzzle:
Line 310 ⟶ 515:
 
=={{header|AutoHotkey}}==
<langsyntaxhighlight AutoHotkeylang="autohotkey">#SingleInstance, Force
SetBatchLines, -1
SetTitleMatchMode, 3
Line 453 ⟶ 658:
r .= SubStr(p, A_Index, 1) . "|"
return r
}</langsyntaxhighlight>
 
=={{header|AWK}}==
<syntaxhighlight lang="awk">
# syntax: GAWK -f SUDOKU_RC.AWK
BEGIN {
# row1 row2 row3 row4 row5 row6 row7 row8 row9
# puzzle = "111111111 111111111 111111111 111111111 111111111 111111111 111111111 111111111 111111111" # NG duplicate hints
# puzzle = "1........ ..274.... ...5....4 .3....... 75....... .....96.. .4...6... .......71 .....1.30" # NG can't use zero
# puzzle = "1........ ..274.... ...5....4 .3....... 75....... .....96.. .4...6... .......71 .....1.39" # no solution
# puzzle = "1........ ..274.... ...5....4 .3....... 75....... .....96.. .4...6... .......71 .....1.3." # OK
puzzle = "123456789 456789123 789123456 ......... ......... ......... ......... ......... ........." # OK
gsub(/ /,"",puzzle)
if (length(puzzle) != 81) { error("length of puzzle is not 81") }
if (puzzle !~ /^[1-9\.]+$/) { error("only 1-9 and . are valid") }
if (gsub(/[1-9]/,"&",puzzle) < 17) { error("too few hints") }
if (errors > 0) {
exit(1)
}
plot(puzzle,"unsolved")
if (dup_hints_check(puzzle) == 1) {
if (solve(puzzle) == 1) {
dup_hints_check(sos)
plot(sos,"solved")
printf("\nbef: %s\naft: %s\n",puzzle,sos)
exit(0)
}
else {
error("no solution")
}
}
exit(1)
}
function dup_hints_check(ss, esf,msg,Rarr,Carr,Barr,i,r_row,r_col,r_pos,r_hint,c_row,c_col,c_pos,c_hint,box) {
esf = errors # errors so far
for (i=0; i<81; i++) {
# row
r_row = int(i/9) + 1 # determine row: 1..9
r_col = i%9 + 1 # determine column: 1..9
r_pos = i + 1 # determine hint position: 1..81
r_hint = substr(ss,r_pos,1) # extract 1 character; the hint
Rarr[r_row,r_hint]++ # save row
# column
c_row = i%9 + 1 # determine row: 1..9
c_col = int(i/9) + 1 # determine column: 1..9
c_pos = (c_row-1) * 9 + c_col # determine hint position: 1..81
c_hint = substr(ss,c_pos,1) # extract 1 character; the hint
Carr[c_col,c_hint]++ # save column
# box (there has to be a better way)
if ((r_row r_col) ~ /[123][123]/) { box = 1 }
else if ((r_row r_col) ~ /[123][456]/) { box = 2 }
else if ((r_row r_col) ~ /[123][789]/) { box = 3 }
else if ((r_row r_col) ~ /[456][123]/) { box = 4 }
else if ((r_row r_col) ~ /[456][456]/) { box = 5 }
else if ((r_row r_col) ~ /[456][789]/) { box = 6 }
else if ((r_row r_col) ~ /[789][123]/) { box = 7 }
else if ((r_row r_col) ~ /[789][456]/) { box = 8 }
else if ((r_row r_col) ~ /[789][789]/) { box = 9 }
else { box = 0 }
Barr[box,r_hint]++ # save box
}
dup_hints_print(Rarr,"row")
dup_hints_print(Carr,"column")
dup_hints_print(Barr,"box")
return((errors == esf) ? 1 : 0)
}
function dup_hints_print(arr,rcb, hint,i) {
# rcb - Row Column Box
for (i=1; i<=9; i++) { # "i" is either the row, column, or box
for (hint=1; hint<=9; hint++) { # 1..9 only; don't care about "." place holder
if (arr[i,hint]+0 > 1) { # was a digit specified more than once
error(sprintf("duplicate hint in %s %d",rcb,i))
}
}
}
}
function plot(ss,text1,text2, a,b,c,d,ou) {
# 1st call prints the unsolved puzzle.
# 2nd call prints the solved puzzle
printf("| - - - + - - - + - - - | %s\n",text1)
for (a=0; a<3; a++) {
for (b=0; b<3; b++) {
ou = "|"
for (c=0; c<3; c++) {
for (d=0; d<3; d++) {
ou = sprintf("%s %1s",ou,substr(ss,1+d+3*c+9*b+27*a,1))
}
ou = ou " |"
}
print(ou)
}
printf("| - - - + - - - + - - - | %s\n",(a==2)?text2:"")
}
}
function solve(ss, a,b,c,d,e,r,co,ro,bi,bl,nss) {
i = 0
# first, use some simple logic to fill grid as much as possible
do {
i++
didit = 0
delete nr
delete nc
delete nb
delete ca
for (a=0; a<81; a++) {
b = substr(ss,a+1,1)
if (b == ".") { # construct row, column and block at cell
c = a % 9
r = int(a/9)
ro = substr(ss,r*9+1,9)
co = ""
for (d=0; d<9; d++) { co = co substr(ss,d*9+c+1,1) }
bi = int(c/3)*3+(int(r/3)*3)*9+1
bl = ""
for (d=0; d<3; d++) { bl = bl substr(ss,bi+d*9,3) }
e = 0
# count non-occurrences of digits 1-9 in combined row, column and block, per row, column and block, and flag cell/digit as candidate
for (d=1; d<10; d++) {
if (index(ro co bl, d) == 0) {
e++
nr[r,d]++
nc[c,d]++
nb[bi,d]++
ca[c,r,d] = bi
}
}
if (e == 0) { # in case no candidate is available, give up
return(0)
}
}
}
# go through all cell/digit candidates
# hidden singles
for (crd in ca) {
# a candidate may have been deleted after the loop started
if (ca[crd] != "") {
split(crd,spl,SUBSEP)
c = spl[1]
r = spl[2]
d = spl[3]
bi = ca[crd]
a = c + r * 9
# unique solution if at least one non-occurrence counter is exactly 1
if ((nr[r,d] == 1) || (nc[c,d] == 1) || (nb[bi,d] == 1)) {
ss = substr(ss,1,a) d substr(ss,a+2,length(ss))
didit = 1
# remove candidates from current row, column, block
for (e=0; e<9; e++) {
delete ca[c,e,d]
delete ca[e,r,d]
}
for (e=0; e<3; e++) {
for (b=0; b<3; b++) {
delete ca[int(c/3)*3+b,int(r/3)*3+e,d]
}
}
}
}
}
} while (didit == 1)
# second, pick a viable solution for the next empty cell and see if it leads to a solution
a = index(ss,".")-1
if (a == -1) { # no more empty cells, done
sos = ss
return(1)
}
else {
c = a % 9
r = int(a/9)
# concatenate current row, column and block
# row
co = substr(ss,r*9+1,9)
# column
for (d=0; d<9; d++) { co = co substr(ss,d*9+c+1,1) }
# block
c = int(c/3)*3+(int(r/3)*3)*9+1
for (d=0; d<3; d++) { co = co substr(ss,c+d*9,3) }
for (b=1; b<10; b++) { # get a viable digit
if (index(co,b) == 0) { # check if candidate digit already exists
# is viable, put in cell
nss = substr(ss,1,a) b substr(ss,a+2,length(ss))
d = solve(nss) # try to solve
if (d == 1) { # if successful, return
return(1)
}
}
}
}
return(0) # no digits viable, no solution
}
function error(message) { printf("error: %s\n",message) ; errors++ }
</syntaxhighlight>
{{out}}
<pre>
| - - - + - - - + - - - | unsolved
| 1 2 3 | 4 5 6 | 7 8 9 |
| 4 5 6 | 7 8 9 | 1 2 3 |
| 7 8 9 | 1 2 3 | 4 5 6 |
| - - - + - - - + - - - |
| . . . | . . . | . . . |
| . . . | . . . | . . . |
| . . . | . . . | . . . |
| - - - + - - - + - - - |
| . . . | . . . | . . . |
| . . . | . . . | . . . |
| . . . | . . . | . . . |
| - - - + - - - + - - - |
| - - - + - - - + - - - | solved
| 1 2 3 | 4 5 6 | 7 8 9 |
| 4 5 6 | 7 8 9 | 1 2 3 |
| 7 8 9 | 1 2 3 | 4 5 6 |
| - - - + - - - + - - - |
| 2 1 4 | 3 6 5 | 8 9 7 |
| 3 6 5 | 8 9 7 | 2 1 4 |
| 8 9 7 | 2 1 4 | 3 6 5 |
| - - - + - - - + - - - |
| 5 3 1 | 6 4 2 | 9 7 8 |
| 6 4 2 | 9 7 8 | 5 3 1 |
| 9 7 8 | 5 3 1 | 6 4 2 |
| - - - + - - - + - - - |
 
bef: 123456789456789123789123456......................................................
aft: 123456789456789123789123456214365897365897214897214365531642978642978531978531642
</pre>
 
=={{header|BBC BASIC}}==
{{works with|BBC BASIC for Windows}}
[[Image:sudoku_bbc.gif|right]]
<syntaxhighlight lang="bbcbasic"> VDU 23,22,453;453;8,20,16,128
*FONT Arial,28
DIM Board%(8,8)
Board%() = %111111111
FOR L% = 0 TO 9:P% = L%*100
LINE 2,P%+2,902,P%+2
IF (L% MOD 3)=0 LINE 2,P%,902,P% : LINE 2,P%+4,902,P%+4
LINE P%+2,2,P%+2,902
IF (L% MOD 3)=0 LINE P%,2,P%,902 : LINE P%+4,2,P%+4,902
NEXT
DATA " 4 5 6 "
DATA " 6 1 8 9"
DATA "3 7 "
DATA " 8 5 "
DATA " 4 3 "
DATA " 6 7 "
DATA " 2 6"
DATA "1 5 4 3 "
DATA " 2 7 1 "
FOR R% = 8 TO 0 STEP -1
READ A$
FOR C% = 0 TO 8
A% = ASCMID$(A$,C%+1) AND 15
IF A% Board%(R%,C%) = 1 << (A%-1)
NEXT
NEXT R%
GCOL 4
PROCshow
WAIT 200
dummy% = FNsolve(Board%(), TRUE)
GCOL 2
PROCshow
REPEAT WAIT 1 : UNTIL FALSE
END
DEF PROCshow
LOCAL C%,P%,R%
FOR C% = 0 TO 8
FOR R% = 0 TO 8
P% = Board%(R%,C%)
IF (P% AND (P%-1)) = 0 THEN
IF P% P% = LOGP%/LOG2+1.5
MOVE C%*100+30,R%*100+90
VDU 5,P%+48,4
ENDIF
NEXT
NEXT
ENDPROC
DEF FNsolve(P%(),F%)
LOCAL C%,D%,M%,N%,R%,X%,Y%,Q%()
DIM Q%(8,8)
REPEAT
Q%() = P%()
FOR R% = 0 TO 8
FOR C% = 0 TO 8
D% = P%(R%,C%)
IF (D% AND (D%-1))=0 THEN
M% = NOT D%
FOR X% = 0 TO 8
IF X%<>C% P%(R%,X%) AND= M%
IF X%<>R% P%(X%,C%) AND= M%
NEXT
FOR X% = C%DIV3*3 TO C%DIV3*3+2
FOR Y% = R%DIV3*3 TO R%DIV3*3+2
IF X%<>C% IF Y%<>R% P%(Y%,X%) AND= M%
NEXT
NEXT
ENDIF
NEXT
NEXT
Q%() -= P%()
UNTIL SUMQ%()=0
M% = 10
FOR R% = 0 TO 8
FOR C% = 0 TO 8
D% = P%(R%,C%)
IF D%=0 M% = 0
IF D% AND (D%-1) THEN
N% = 0
REPEAT N% += D% AND 1
D% DIV= 2
UNTIL D% = 0
IF N%<M% M% = N% : X% = C% : Y% = R%
ENDIF
NEXT
NEXT
IF M%=0 THEN = 0
IF M%=10 THEN = 1
D% = 0
FOR M% = 0 TO 8
IF P%(Y%,X%) AND (2^M%) THEN
Q%() = P%()
Q%(Y%,X%) = 2^M%
C% = FNsolve(Q%(),F%)
D% += C%
IF C% IF F% P%() = Q%() : = D%
ENDIF
NEXT
= D%</syntaxhighlight>
 
=={{header|BCPL}}==
<langsyntaxhighlight BCPLlang="bcpl">// This can be run using Cintcode BCPL freely available from www.cl.cam.ac.uk/users/mr10.
// Implemented by Martin Richards.
 
// If you have cintcode BCPL installed on a Linux system you can compile and run this program
// execute the following sequence of commands.
 
// cd $BCPLROOT
// cintsys
// c bc sudoku
// sudoku
 
// This is a really naive program to solve Su DokuSuDoku problems. Even so it is usually quite fast.
 
// SuDoku consists of a 9x9 grid of cells. Each cell should contain
Line 842 ⟶ 1,388:
{ count := count + 1
prboard()
}</langsyntaxhighlight>
 
=={{header|Befunge}}==
 
Input should be provided as a sequence of 81 digits (optionally separated by whitespace), with zero representing an unknown value.
 
<syntaxhighlight lang="befunge">99*>1-:0>:#$"0"\# #~`#$_"0"-\::9%:9+00p3/\9/:99++10p3vv%2g\g01<
2%v|:p+9/9\%9:\p\g02\1p\g01\1:p\g00\1:+8:\p02+*93+*3/<>\20g\g#:
v<+>:0\`>v >\::9%:9+00p3/\9/:99++10p3/3*+39*+20p\:8+::00g\g2%\^
v^+^pppp$_:|v<::<_>1-::9%\9/9+g.::9%!\3%+>>#v_>" "v..v,<<<+55<<
03!$v9:_>1v$>9%\v^|:<_v#<%<9<:<<_v#+%*93\!::<,,"|"<\/>:#^_>>>v^
p|<$0.0^!g+:#9/9<^@ ^,>#+5<5_>#!<>#$0"------+-------+-----":#<^
<>v$v1:::0<>"P"`!^>0g#0v#p+9/9\%9:p04:\pg03g021pg03g011pg03g001
::>^_:#<0#!:p#-\#1:#g0<>30g010g30g020g30g040g:9%\:9/9+\01-\1+0:</syntaxhighlight>
 
{{in}}
 
<pre>8 5 0 0 0 2 4 0 0
7 2 0 0 0 0 0 0 9
0 0 4 0 0 0 0 0 0
0 0 0 1 0 7 0 0 2
3 0 5 0 0 0 9 0 0
0 4 0 0 0 0 0 0 0
0 0 0 0 8 0 0 7 0
0 1 7 0 0 0 0 0 0
0 0 0 0 3 6 0 4 0</pre>
 
{{out}}
 
<pre>8 5 9 | 6 1 2 | 4 3 7
7 2 3 | 8 5 4 | 1 6 9
1 6 4 | 3 7 9 | 5 2 8
------+-------+------
9 8 6 | 1 4 7 | 3 5 2
3 7 5 | 2 6 8 | 9 1 4
2 4 1 | 5 9 3 | 7 8 6
------+-------+------
4 3 2 | 9 8 1 | 6 7 5
6 1 7 | 4 2 5 | 8 9 3
5 9 8 | 7 3 6 | 2 4 1</pre>
 
=={{header|Bracmat}}==
The program:
<langsyntaxhighlight lang="bracmat">{sudokuSolver.bra
 
Solves any 9x9 sudoku, using backtracking.
Line 1,034 ⟶ 1,619:
. new$((its.sudoku),!arg):?puzzle
& (puzzle..Display)$
);</langsyntaxhighlight>
Solve a sudoku that is hard for a brute force solver:
<langsyntaxhighlight lang="bracmat">new'( sudokuSolver
, (.- - - - - - - - -)
(.- - - - - 3 - 8 5)
Line 1,046 ⟶ 1,631:
(.- - 2 - 1 - - - -)
(.- - - - 4 - - - 9)
);</langsyntaxhighlight>
Solution:
<pre>|~~~|~~~|~~~|
|~~~|~~~|~~~|
|987|654|321|
|246|173|985|
Line 1,061 ⟶ 1,645:
|472|319|568|
|863|745|219|
|~~~|~~~|~~~|</pre>
</pre>
 
=={{header|C}}==
See e.g. [http://www.techfinesse.com/game/sudoku_solver.php this GPLed solver] written in C.
 
The following code is really only good for size 3 puzzles. A longer, even less readable version [[Sudoku/C|here]] could handle size 4s.
=={{header|C_sharp|C#}}==
<syntaxhighlight lang="c">#include <stdio.h>
===“Manual” Solution===
 
void show(int *x)
{
int i, j;
for (i = 0; i < 9; i++) {
if (!(i % 3)) putchar('\n');
for (j = 0; j < 9; j++)
printf(j % 3 ? "%2d" : "%3d", *x++);
putchar('\n');
}
}
 
int trycell(int *x, int pos)
{
int row = pos / 9;
int col = pos % 9;
int i, j, used = 0;
 
if (pos == 81) return 1;
if (x[pos]) return trycell(x, pos + 1);
 
for (i = 0; i < 9; i++)
used |= 1 << (x[i * 9 + col] - 1);
 
for (j = 0; j < 9; j++)
used |= 1 << (x[row * 9 + j] - 1);
 
row = row / 3 * 3;
col = col / 3 * 3;
for (i = row; i < row + 3; i++)
for (j = col; j < col + 3; j++)
used |= 1 << (x[i * 9 + j] - 1);
 
for (x[pos] = 1; x[pos] <= 9; x[pos]++, used >>= 1)
if (!(used & 1) && trycell(x, pos + 1)) return 1;
 
x[pos] = 0;
return 0;
}
 
void solve(const char *s)
{
int i, x[81];
for (i = 0; i < 81; i++)
x[i] = s[i] >= '1' && s[i] <= '9' ? s[i] - '0' : 0;
 
if (trycell(x, 0))
show(x);
else
puts("no solution");
}
 
int main(void)
{
solve( "5x..7...."
"6..195..."
".98....6."
"8...6...3"
"4..8.3..1"
"7...2...6"
".6....28."
"...419..5"
"....8..79" );
 
return 0;
}</syntaxhighlight>
 
=={{header|C sharp|C#}}==
===Backtracking===
{{trans|Java}}
<langsyntaxhighlight lang="csharp">using System;
 
class SudokuSolver
Line 1,172 ⟶ 1,824:
Console.Read();
}
}</langsyntaxhighlight>
 
===“Automatic” Solution===
=== Best First Search===
<!-- By Martin Freedman, 20/11/2021 -->
<syntaxhighlight lang="csharp">using System.Linq;
using static System.Linq.Enumerable;
using System.Collections.Generic;
using System;
using System.Runtime.CompilerServices;
 
namespace SodukoFastMemoBFS {
internal readonly record struct Square (int Row, int Col);
internal record Constraints (IEnumerable<int> ConstrainedRange, Square Square);
internal class Cache : Dictionary<Square, Constraints> { };
internal record CacheGrid (int[][] Grid, Cache Cache);
 
internal static class SudokuFastMemoBFS {
internal static U Fwd<T, U>(this T data, Func<T, U> f) => f(data);
 
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static int RowCol(int rc) => rc <= 2 ? 0 : rc <= 5 ? 3 : 6;
 
private static bool Solve(this CacheGrid cg, Constraints constraints, int finished) {
var (row, col) = constraints.Square;
foreach (var i in constraints.ConstrainedRange) {
cg.Grid[row][col] = i;
if (cg.Cache.Count == finished || cg.Solve(cg.Next(constraints.Square), finished))
return true;
}
cg.Grid[row][col] = 0;
return false;
}
 
private static readonly int[] domain = Range(0, 9).ToArray();
private static readonly int[] range = Range(1, 9).ToArray();
 
private static bool Valid(this int[][] grid, int row, int col, int val) {
for (var i = 0; i < 9; i++)
if (grid[row][i] == val || grid[i][col] == val)
return false;
for (var r = RowCol(row); r < RowCol(row) + 3; r++)
for (var c = RowCol(col); c < RowCol(col) + 3; c++)
if (grid[r][c] == val)
return false;
return true;
}
 
private static IEnumerable<int> Constraints(this int[][] grid, int row, int col) =>
range.Where(val => grid.Valid(row, col, val));
 
private static Constraints Next(this CacheGrid cg, Square square) =>
cg.Cache.ContainsKey(square)
? cg.Cache[square]
: cg.Cache[square]=cg.Grid.SortedCells();
 
private static Constraints SortedCells(this int[][] grid) =>
(from row in domain
from col in domain
where grid[row][col] == 0
let cell = new Constraints(grid.Constraints(row, col), new Square(row, col))
orderby cell.ConstrainedRange.Count() ascending
select cell).First();
 
private static CacheGrid Parse(string input) =>
input
.Select((c, i) => (index: i, val: int.Parse(c.ToString())))
.GroupBy(id => id.index / 9)
.Select(grp => grp.Select(id => id.val).ToArray())
.ToArray()
.Fwd(grid => new CacheGrid(grid, new Cache()));
public static string AsString(this int[][] grid) =>
string.Join('\n', grid.Select(row => string.Concat(row)));
 
public static int[][] Run(string input) {
var cg = Parse(input);
var marked = cg.Grid.SelectMany(row => row.Where(c => c > 0)).Count();
return cg.Solve(cg.Grid.SortedCells(), 80 - marked) ? cg.Grid : new int[][] { Array.Empty<int>() };
}
}
}</syntaxhighlight>
Usage
<syntaxhighlight lang="csharp">using System.Linq;
using static System.Linq.Enumerable;
using static System.Console;
using System.IO;
 
namespace SodukoFastMemoBFS {
static class Program {
 
static void Main(string[] args) {
var num = int.Parse(args[0]);
var puzzles = File.ReadLines(@"sudoku17.txt").Take(num);
var single = puzzles.First();
 
var watch = new System.Diagnostics.Stopwatch();
watch.Start();
WriteLine(SudokuFastMemoBFS.Run(single).AsString());
watch.Stop();
WriteLine($"{single}: {watch.ElapsedMilliseconds} ms");
 
WriteLine($"Doing {num} puzzles");
var total = 0.0;
watch.Start();
foreach (var puzzle in puzzles) {
watch.Reset();
watch.Start();
SudokuFastMemoBFS.Run(puzzle);
watch.Stop();
total += watch.ElapsedMilliseconds;
Write(".");
}
watch.Stop();
WriteLine($"\nPuzzles:{num}, Total:{total} ms, Average:{total / num:0.00} ms");
ReadKey();
}
}
}</syntaxhighlight>
Output
<pre>693784512
487512936
125963874
932651487
568247391
741398625
319475268
856129743
274836159
000000010400000000020000000000050407008000300001090000300400200050100000000806000: 336 ms
Doing 100 puzzles
....................................................................................................
Puzzles:100, Total:5316 ms, Average:53.16 ms</pre>
 
===Solver===
{{libheader|Microsoft Solver Foundation}}
<!-- By Nigel Galloway, Jan 29, 2012 -->
<langsyntaxhighlight lang="csharp">using Microsoft.SolverFoundation.Solvers;
 
namespace Sudoku
Line 1,248 ⟶ 2,032:
}
}
}</langsyntaxhighlight>
Produces:
<pre>
Line 1,263 ⟶ 2,047:
146 897 325
</pre>
 
==="Dancing Links"/Algorithm X===
<syntaxhighlight lang="csharp">using System;
using System.Collections.Generic;
using System.Text;
using static System.Linq.Enumerable;
 
public class Sudoku
{
public static void Main2() {
string puzzle = "....7.94.....9...53....5.7...74..1..463...........7.8.8........7......28.5.26....";
string solution = new Sudoku().Solutions(puzzle).FirstOrDefault() ?? puzzle;
Print(puzzle, solution);
}
 
private DLX dlx;
 
public void Build() {
const int rows = 9 * 9 * 9, columns = 4 * 9 * 9;
dlx = new DLX(rows, columns);
for (int i = 0; i < columns; i++) dlx.AddHeader();
 
for (int cell = 0, row = 0; row < 9; row++) {
for (int column = 0; column < 9; column++) {
int box = row / 3 * 3 + column / 3;
for (int digit = 0; digit < 9; digit++) {
dlx.AddRow(cell, 81 + row * 9 + digit, 2 * 81 + column * 9 + digit, 3 * 81 + box * 9 + digit);
}
cell++;
}
}
}
 
public IEnumerable<string> Solutions(string puzzle) {
if (puzzle == null) throw new ArgumentNullException(nameof(puzzle));
if (puzzle.Length != 81) throw new ArgumentException("The input is not of the correct length.");
if (dlx == null) Build();
 
for (int i = 0; i < puzzle.Length; i++) {
if (puzzle[i] == '0' || puzzle[i] == '.') continue;
if (puzzle[i] < '1' && puzzle[i] > '9') throw new ArgumentException($"Input contains an invalid character: ({puzzle[i]})");
int digit = puzzle[i] - '0' - 1;
dlx.Give(i * 9 + digit);
}
return Iterator();
 
IEnumerable<string> Iterator() {
var sb = new StringBuilder(new string('.', 81));
foreach (int[] rows in dlx.Solutions()) {
foreach (int r in rows) {
sb[r / 81 * 9 + r / 9 % 9] = (char)(r % 9 + '1');
}
yield return sb.ToString();
}
}
}
 
static void Print(string left, string right) {
foreach (string line in GetPrintLines(left).Zip(GetPrintLines(right), (l, r) => l + "\t" + r)) {
Console.WriteLine(line);
}
 
IEnumerable<string> GetPrintLines(string s) {
int r = 0;
foreach (string row in s.Cut(9)) {
yield return r == 0
? "╔═══╤═══╤═══╦═══╤═══╤═══╦═══╤═══╤═══╗"
: r % 3 == 0
? "╠═══╪═══╪═══╬═══╪═══╪═══╬═══╪═══╪═══╣"
: "╟───┼───┼───╫───┼───┼───╫───┼───┼───╢";
yield return "║ " + row.Cut(3).Select(segment => segment.DelimitWith(" │ ")).DelimitWith(" ║ ") + " ║";
r++;
}
yield return "╚═══╧═══╧═══╩═══╧═══╧═══╩═══╧═══╧═══╝";
}
}
 
}
 
public class DLX //Some functionality elided
{
private readonly Header root = new Header(null, null) { Size = int.MaxValue };
private readonly List<Header> columns;
private readonly List<Node> rows;
private readonly Stack<Node> solutionNodes = new Stack<Node>();
private int initial = 0;
 
public DLX(int rowCapacity, int columnCapacity) {
columns = new List<Header>(columnCapacity);
rows = new List<Node>(rowCapacity);
}
 
public void AddHeader() {
Header h = new Header(root.Left, root);
h.AttachLeftRight();
columns.Add(h);
}
 
public void AddRow(params int[] newRow) {
Node first = null;
if (newRow != null) {
for (int i = 0; i < newRow.Length; i++) {
if (newRow[i] < 0) continue;
if (first == null) first = AddNode(rows.Count, newRow[i]);
else AddNode(first, newRow[i]);
}
}
rows.Add(first);
}
 
private Node AddNode(int row, int column) {
Node n = new Node(null, null, columns[column].Up, columns[column], columns[column], row);
n.AttachUpDown();
n.Head.Size++;
return n;
}
 
private void AddNode(Node firstNode, int column) {
Node n = new Node(firstNode.Left, firstNode, columns[column].Up, columns[column], columns[column], firstNode.Row);
n.AttachLeftRight();
n.AttachUpDown();
n.Head.Size++;
}
 
public void Give(int row) {
solutionNodes.Push(rows[row]);
CoverMatrix(rows[row]);
initial++;
}
 
public IEnumerable<int[]> Solutions() {
try {
Node node = ChooseSmallestColumn().Down;
do {
if (node == node.Head) {
if (node == root) {
yield return solutionNodes.Select(n => n.Row).ToArray();
}
if (solutionNodes.Count > initial) {
node = solutionNodes.Pop();
UncoverMatrix(node);
node = node.Down;
}
} else {
solutionNodes.Push(node);
CoverMatrix(node);
node = ChooseSmallestColumn().Down;
}
} while(solutionNodes.Count > initial || node != node.Head);
} finally {
Restore();
}
}
 
private void Restore() {
while (solutionNodes.Count > 0) UncoverMatrix(solutionNodes.Pop());
initial = 0;
}
 
private Header ChooseSmallestColumn() {
Header traveller = root, choice = root;
do {
traveller = (Header)traveller.Right;
if (traveller.Size < choice.Size) choice = traveller;
} while (traveller != root && choice.Size > 0);
return choice;
}
 
private void CoverRow(Node row) {
Node traveller = row.Right;
while (traveller != row) {
traveller.DetachUpDown();
traveller.Head.Size--;
traveller = traveller.Right;
}
}
 
private void UncoverRow(Node row) {
Node traveller = row.Left;
while (traveller != row) {
traveller.AttachUpDown();
traveller.Head.Size++;
traveller = traveller.Left;
}
}
 
private void CoverColumn(Header column) {
column.DetachLeftRight();
Node traveller = column.Down;
while (traveller != column) {
CoverRow(traveller);
traveller = traveller.Down;
}
}
 
private void UncoverColumn(Header column) {
Node traveller = column.Up;
while (traveller != column) {
UncoverRow(traveller);
traveller = traveller.Up;
}
column.AttachLeftRight();
}
 
private void CoverMatrix(Node node) {
Node traveller = node;
do {
CoverColumn(traveller.Head);
traveller = traveller.Right;
} while (traveller != node);
}
 
private void UncoverMatrix(Node node) {
Node traveller = node;
do {
traveller = traveller.Left;
UncoverColumn(traveller.Head);
} while (traveller != node);
}
 
private class Node
{
public Node(Node left, Node right, Node up, Node down, Header head, int row) {
Left = left ?? this;
Right = right ?? this;
Up = up ?? this;
Down = down ?? this;
Head = head ?? this as Header;
Row = row;
}
 
public Node Left { get; set; }
public Node Right { get; set; }
public Node Up { get; set; }
public Node Down { get; set; }
public Header Head { get; }
public int Row { get; }
 
public void AttachLeftRight() {
this.Left.Right = this;
this.Right.Left = this;
}
 
public void AttachUpDown() {
this.Up.Down = this;
this.Down.Up = this;
}
 
public void DetachLeftRight() {
this.Left.Right = this.Right;
this.Right.Left = this.Left;
}
 
public void DetachUpDown() {
this.Up.Down = this.Down;
this.Down.Up = this.Up;
}
 
}
 
private class Header : Node
{
public Header(Node left, Node right) : base(left, right, null, null, null, -1) { }
public int Size { get; set; }
}
 
}
 
static class Extensions
{
public static IEnumerable<string> Cut(this string input, int length)
{
for (int cursor = 0; cursor < input.Length; cursor += length) {
if (cursor + length > input.Length) yield return input.Substring(cursor);
else yield return input.Substring(cursor, length);
}
}
 
public static string DelimitWith<T>(this IEnumerable<T> source, string separator) => string.Join(separator, source);
}</syntaxhighlight>
{{out}}
<pre>
╔═══╤═══╤═══╦═══╤═══╤═══╦═══╤═══╤═══╗ ╔═══╤═══╤═══╦═══╤═══╤═══╦═══╤═══╤═══╗
║ . │ . │ . ║ . │ 7 │ . ║ 9 │ 4 │ . ║ ║ 2 │ 1 │ 5 ║ 8 │ 7 │ 6 ║ 9 │ 4 │ 3 ║
╟───┼───┼───╫───┼───┼───╫───┼───┼───╢ ╟───┼───┼───╫───┼───┼───╫───┼───┼───╢
║ . │ . │ . ║ . │ 9 │ . ║ . │ . │ 5 ║ ║ 6 │ 7 │ 8 ║ 3 │ 9 │ 4 ║ 2 │ 1 │ 5 ║
╟───┼───┼───╫───┼───┼───╫───┼───┼───╢ ╟───┼───┼───╫───┼───┼───╫───┼───┼───╢
║ 3 │ . │ . ║ . │ . │ 5 ║ . │ 7 │ . ║ ║ 3 │ 4 │ 9 ║ 1 │ 2 │ 5 ║ 8 │ 7 │ 6 ║
╠═══╪═══╪═══╬═══╪═══╪═══╬═══╪═══╪═══╣ ╠═══╪═══╪═══╬═══╪═══╪═══╬═══╪═══╪═══╣
║ . │ . │ 7 ║ 4 │ . │ . ║ 1 │ . │ . ║ ║ 5 │ 8 │ 7 ║ 4 │ 3 │ 2 ║ 1 │ 6 │ 9 ║
╟───┼───┼───╫───┼───┼───╫───┼───┼───╢ ╟───┼───┼───╫───┼───┼───╫───┼───┼───╢
║ 4 │ 6 │ 3 ║ . │ . │ . ║ . │ . │ . ║ ║ 4 │ 6 │ 3 ║ 9 │ 8 │ 1 ║ 7 │ 5 │ 2 ║
╟───┼───┼───╫───┼───┼───╫───┼───┼───╢ ╟───┼───┼───╫───┼───┼───╫───┼───┼───╢
║ . │ . │ . ║ . │ . │ 7 ║ . │ 8 │ . ║ ║ 1 │ 9 │ 2 ║ 6 │ 5 │ 7 ║ 3 │ 8 │ 4 ║
╠═══╪═══╪═══╬═══╪═══╪═══╬═══╪═══╪═══╣ ╠═══╪═══╪═══╬═══╪═══╪═══╬═══╪═══╪═══╣
║ 8 │ . │ . ║ . │ . │ . ║ . │ . │ . ║ ║ 8 │ 2 │ 6 ║ 7 │ 4 │ 3 ║ 5 │ 9 │ 1 ║
╟───┼───┼───╫───┼───┼───╫───┼───┼───╢ ╟───┼───┼───╫───┼───┼───╫───┼───┼───╢
║ 7 │ . │ . ║ . │ . │ . ║ . │ 2 │ 8 ║ ║ 7 │ 3 │ 4 ║ 5 │ 1 │ 9 ║ 6 │ 2 │ 8 ║
╟───┼───┼───╫───┼───┼───╫───┼───┼───╢ ╟───┼───┼───╫───┼───┼───╫───┼───┼───╢
║ . │ 5 │ . ║ 2 │ 6 │ . ║ . │ . │ . ║ ║ 9 │ 5 │ 1 ║ 2 │ 6 │ 8 ║ 4 │ 3 │ 7 ║
╚═══╧═══╧═══╩═══╧═══╧═══╩═══╧═══╧═══╝ ╚═══╧═══╧═══╩═══╧═══╧═══╩═══╧═══╧═══╝</pre>
 
=={{header|C++}}==
{{trans|Java}}
<langsyntaxhighlight lang="cpp">#include <iostream>
using namespace std;
 
Line 1,346 ⟶ 2,432:
 
int main() {
SudokuSolver ss("850002400"
(string) "850002400720000009" +
(string) "720000009004000000" +
(string) "004000000000107002" +
(string) "000107002305000900" +
(string) "305000900040000000" +
(string) "040000000000080070" +
(string) "000080070017000000" +
(string) "017000000000036040" +);
(string) "000036040"
);
ss.solve();
return EXIT_SUCCESS;
}</lang>
}</syntaxhighlight>
 
=={{header|Clojure}}==
<langsyntaxhighlight lang="clojure">(ns rosettacode.sudoku
(:use [clojure.contrib.mathpprint :only (sqrtcl-format)]))
 
(defn print-grid compatible? [gridm x y n]
(doseqlet [yn= #(range= n (countget-in m [%1 grid%2]))]
(doseq [xor (rangen= (county grid)x)]
(printlet [c (retrievecount grid x y) " ")m)]
(and (zero? (get-in m [y x]))
(println))
(not-any? #(or (n= y %) (n= % x)) (range c))
(println))
(let [zx (* c (quot x c)), zy (* c (quot y c))]
(every? false?
(map n= (range zy (+ zy c)) (range zx (+ zx c))))))))))
 
(defn retrievesolve [grid x ym]
(getlet [c (getcount grid y) x)m)]
(loop [m m, x 0, y 0]
(if (= y c) m
(let [ng (->> (range 1 c)
(filter #(compatible? m x y %))
first
(assoc-in m [y x]))]
(if (= x (dec c))
(recur ng 0 (inc y))
(recur ng (inc x) y)))))))</syntaxhighlight>
 
<syntaxhighlight lang="clojure">sudoku>(cl-format true "~{~{~a~^ ~}~%~}"
(defn store [grid x y n]
(solve [[3 9 4 0 0 2 6 7 0]
(assoc grid y (assoc (get grid y) x n)))
[0 0 0 3 0 0 4 0 0]
 
[5 0 0 6 9 0 0 2 0]
(defn coordinates [grid x y]
[0 4 5 0 0 0 9 0 0]
(let [n (sqrt (count grid))
zx (*[6 n0 (quot0 x0 n))0 0 0 0 7]
zy (*[0 n0 (quot7 y0 n))0 0 5 8 0]
(for [x (range zx (+ zx[0 1 n))0 y0 (range6 zy7 (+0 zy0 n))8]
[x0 0 9 0 0 8 0 0 y0])))
[0 2 6 4 0 0 7 3 5]])
 
(defn compatible? [grid x y n]
(or
(= n (retrieve grid x y))
(and
(zero? (retrieve grid x y))
(every? #(and (not= n (retrieve grid % y)) (not= n (retrieve grid x %))) (range (count grid)))
(every? #(not= n (retrieve grid (first %) (second %))) (coordinates grid x y)))))
 
(defn solve [grid x y]
(let [m (count grid)]
(if (= y m)
(print-grid grid)
(doseq [n (range 1 (inc m))]
(when (compatible? grid x y n)
(let [new-grid (store grid x y n)]
(if (= x (dec m))
(solve new-grid 0 (inc y))
(solve new-grid (inc x) y))))))))</lang>
 
<lang clojure>sudoku> (solve [[3 9 4 0 0 2 6 7 0]
[0 0 0 3 0 0 4 0 0]
[5 0 0 6 9 0 0 2 0]
[0 4 5 0 0 0 9 0 0]
[6 0 0 0 0 0 0 0 7]
[0 0 7 0 0 0 5 8 0]
[0 1 0 0 6 7 0 0 8]
[0 0 9 0 0 8 0 0 0]
[0 2 6 4 0 0 7 3 5]]
0 0)
3 9 4 8 5 2 6 7 1
2 6 8 3 7 1 4 5 9
Line 1,423 ⟶ 2,491:
8 2 6 4 1 9 7 3 5
 
nil</langsyntaxhighlight>
 
=={{header|Common Lisp}}==
A simple solver without optimizations (except for pre-computing the possible entries of a cell).
<langsyntaxhighlight lang="lisp">(defun row-neighbors (row column grid &aux (neighbors '()))
(dotimes (i 9 neighbors)
(let ((x (aref grid row i)))
Line 1,466 ⟶ 2,534:
(setf (aref grid row column) choice)
(when (eq grid (solve grid row (1+ column)))
(return grid))))))</langsyntaxhighlight>
Example:
<pre>> (defparameter *puzzle*
Line 1,493 ⟶ 2,561:
(7 5 9 2 3 8 1 4 6)
(8 2 6 4 1 9 7 3 5))</pre>
=={{header|Crystal}}==
Based on the Java implementation presented in the video "[https://www.youtube.com/watch?v=mcXc8Mva2bA Create a Sudoku Solver In Java...]".
 
<syntaxhighlight lang="ruby">GRID_SIZE = 9
 
def isNumberInRow(board, number, row)
board[row].includes?(number)
end
def isNumberInColumn(board, number, column)
board.any?{|row| row[column] == number }
end
def isNumberInBox(board, number, row, column)
localBoxRow = row - row % 3
localBoxColumn = column - column % 3
(localBoxRow...(localBoxRow+3)).each do |i|
(localBoxColumn...(localBoxColumn+3)).each do |j|
return true if board[i][j] == number
end
end
false
end
 
def isValidPlacement(board, number, row, column)
return !isNumberInRow(board, number, row) &&
!isNumberInColumn(board, number, column) &&
!isNumberInBox(board, number, row, column)
end
 
def solveBoard(board)
board.each_with_index do |row, i|
row.each_with_index do |cell, j|
if(cell == 0)
(1..GRID_SIZE).each do |n|
if(isValidPlacement(board,n,i,j))
board[i][j]=n
if(solveBoard(board))
return true
else
board[i][j]=0
end
end
end
return false
end
end
end
return true
end
 
def printBoard(board)
board.each_with_index do |row, i|
row.each_with_index do |cell, j|
print cell
print '|' if j == 2 || j == 5
print '\n' if j == 8
end
print "-"*11 + '\n' if i == 2 || i == 5
end
print '\n'
end
 
board = [
[7, 0, 2, 0, 5, 0, 6, 0, 0],
[0, 0, 0, 0, 0, 3, 0, 0, 0],
[1, 0, 0, 0, 0, 9, 5, 0, 0],
[8, 0, 0, 0, 0, 0, 0, 9, 0],
[0, 4, 3, 0, 0, 0, 7, 5, 0],
[0, 9, 0, 0, 0, 0, 0, 0, 8],
[0, 0, 9, 7, 0, 0, 0, 0, 5],
[0, 0, 0, 2, 0, 0, 0, 0, 0],
[0, 0, 7, 0, 4, 0, 2, 0, 3]]
 
printBoard(board)
if(solveBoard(board))
printBoard(board)
end
</syntaxhighlight>
{{out}}
<pre>
702|050|600
000|003|000
100|009|500
-----------
800|000|090
043|000|750
090|000|008
-----------
009|700|005
000|200|000
007|040|203
 
732|458|619
956|173|824
184|629|537
-----------
871|564|392
643|892|751
295|317|468
-----------
329|786|145
418|235|976
567|941|283
</pre>
=={{header|Curry}}==
Copied from [http://www.informatik.uni-kiel.de/~curry/examples/ Curry: Example Programs].
<langsyntaxhighlight lang="curry">-----------------------------------------------------------------------------
--- Solving Su Doku puzzles in Curry with FD constraints
---
Line 1,558 ⟶ 2,728:
" 5 7 921 ",
" 64 9 ",
" 2 438"]</langsyntaxhighlight>
 
 
===Alternative version===
{{Works with|PAKCS}}
Minimal w/o read or show utilities.
<syntaxhighlight lang="curry">import CLPFD
import Constraint (allC)
import List (transpose)
 
 
sudoku :: [[Int]] -> Success
sudoku rows =
domain (concat rows) 1 9
& different rows
& different (transpose rows)
& different blocks
& labeling [] (concat rows)
where
different = allC allDifferent
 
blocks = [concat ys | xs <- each3 rows
, ys <- transpose $ map each3 xs
]
each3 xs = case xs of
(x:y:z:rest) -> [x,y,z] : each3 rest
rest -> [rest]
 
 
test = [ [_,_,3,_,_,_,_,_,_]
, [4,_,_,_,8,_,_,3,6]
, [_,_,8,_,_,_,1,_,_]
, [_,4,_,_,6,_,_,7,3]
, [_,_,_,9,_,_,_,_,_]
, [_,_,_,_,_,2,_,_,5]
, [_,_,4,_,7,_,_,6,8]
, [6,_,_,_,_,_,_,_,_]
, [7,_,_,6,_,_,5,_,_]
]
main | sudoku xs = xs where xs = test</syntaxhighlight>
{{Out}}
<pre>Execution time: 0 msec. / elapsed: 10 msec.
[[1,2,3,4,5,6,7,8,9],[4,5,7,1,8,9,2,3,6],[9,6,8,3,2,7,1,5,4],[2,4,9,5,6,1,8,7,3],[5,7,6,9,3,8,4,1,2],[8,3,1,7,4,2,6,9,5],[3,1,4,2,7,5,9,6,8],[6,9,5,8,1,4,3,2,7],[7,8,2,6,9,3,5,4,1]]</pre>
 
=={{header|D}}==
{{trans|C++}}
A little over-engineered solution, that shows some strong static typing useful in larger programs.
<lang d>import std.stdio, std.range, std.string, std.algorithm,
<syntaxhighlight lang="d">import std.stdio, std.range, std.string, std.algorithm, std.array,
std.array, std.typetuple;
std.ascii, std.typecons;
 
struct Digit {
enum int side = 9; // Sudoku grid side
immutable char d;
alias immutable(char) TableItem; // Statically in '0'...'9'
alias TableItem[side ^^ 2] SudokuTable;
 
this(in char d_) pure nothrow @safe @nogc
in { assert(d_ >= '0' && d_ <= '9'); }
body { this.d = d_; }
 
this(in int d_) pure nothrow @safe @nogc
template Range(int stop) {
staticin if{ assert(stopd_ <>= '0' && d_ <= '9'); }
body { this.d = cast(char)d_; } // Required cast.
alias TypeTuple!() Range;
 
else
alias TypeTuple!(Range!(stop-1), stop-1)d Rangethis;
}
 
enum size_t sudokuUnitSide = 3;
enum size_t sudokuSide = sudokuUnitSide ^^ 2; // Sudoku grid side.
alias SudokuTable = Digit[sudokuSide ^^ 2];
 
SudokuTable sudokuSolver(const ref SudokuTable problem)
in {
assert(problem == removechars(problem[], "^0-9"));
} out(result) {
assert(result == removechars(result[], "^0-9"));
} body {
uint[side ^^ 2] grid = array(map!q{ a - '0' }(problem[]));
 
Nullable!SudokuTable sudokuSolver(in ref SudokuTable problem)
static final class FinishedSudokuException: Exception {
this(in string msg) /*pure*/ nothrow {
alias Tgrid = super(msg)uint;
Tgrid[SudokuTable.length] grid = void;
}
problem[].map!(c => c - '0').copy(grid[]);
 
// DMD doesn't inline this function. Performance loss.
Tgrid access(in size_t x, in size_t y) nothrow @safe @nogc {
return grid[y * sudokuSide + x];
}
 
// DMD doesn't inline this function. If you want to retain
void placeNumber(in int pos) {
// the same performance as the C++ entry and you use the DMD
if (pos == side ^^ 2)
// compiler then this function must be manually inlined.
throw new FinishedSudokuException("Finished!");
bool checkValidity(in Tgrid val, in size_t x, in size_t y)
if (grid[pos] > 0) {
pure nothrow @safe @nogc {
placeNumber(pos + 1);
/*static*/ foreach (immutable i; staticIota!(0, sudokuSide))
return;
if (access(i, y) == val || access(x, i) == val)
}
return false;
 
OUTER:immutable foreachstartX = (n;x 1/ .. side+1sudokuUnitSide) {* sudokuUnitSide;
immutable startY = (y / sudokuUnitSide) * sudokuUnitSide;
// function checkValidity manually inlined
immutable int x = pos % side;
immutable int y = pos / side;
 
/*static*/ foreach (immutable i; RangestaticIota!side(0, sudokuUnitSide))
/*static*/ foreach (immutable j; staticIota!(0, sudokuUnitSide))
if (grid[y*side + i] == n || grid[i*side + x] == n)
if (access(startX + j, continuestartY OUTER;+ i) == val)
return false;
 
return true;
immutable int startX = (x / 3) * 3;
}
immutable int startY = (y / 3) * 3;
 
bool canPlaceNumbers(in size_t pos=0) nothrow @safe @nogc {
/*static*/ foreach (i; Range!3)
if (pos == /*static*/ foreach (j; Range!3SudokuTable.length)
return true;
if (grid[(startY + i) * side + (startX + j)] == n)
if (grid[pos] > continue OUTER;0)
return canPlaceNumbers(pos + 1);
 
foreach (immutable n; 1 grid[pos].. =sudokuSide n;+ 1)
placeNumberif (checkValidity(n, pos +% 1sudokuSide, pos / sudokuSide);) {
grid[pos] = 0n;
if (canPlaceNumbers(pos + 1))
}
return true;
}
grid[pos] = 0;
}
 
try { return false;
placeNumber(0);
return typeof(return).init;
} catch (FinishedSudokuException ex) {
//return array(map!q{ cast(TableItem)(a+'0') }(grid[])).idup;
const temp = array(map!q{ cast(char)(a + '0') }(grid[]));
SudokuTable result = temp.idup;
return result;
}
}
 
if (canPlaceNumbers) {
//return typeof(return)(grid[]
// .map!(c => Digit(c + '0'))
// .array);
immutable SudokuTable result = grid[]
.map!(c => Digit(c + '0'))
.array;
return typeof(return)(result);
} else
return typeof(return)();
}
 
string formatSudokurepresentSudoku(constin ref SudokuTable sudo)
pure nothrow @safe out(result) {
in {
assert(sudoresult.countchars("1-9") == removechars(sudo[],.count!q{a "^!= '0-9")'});
assert(result.countchars(".") == sudo[].count!q{a == '0'});
} out(result) {
assert(sudo == removechars(result[], "^0-9"));
} body {
static assert(sudo.length == 81,
"representSudoku works only with a 9x9 Sudoku.");
string result;
 
foreach (immutable i; 0 .. sidesudokuSide) {
foreach (immutable j; 0 .. sidesudokuSide) {
result ~= sudo[i * sidesudokuSide + j];
result ~= ' ';
if (j == 2 || j == 5)
Line 1,655 ⟶ 2,878:
}
 
return result.replace("0", ".");
}
 
void main() {
enum ValidateCells(string s) = s.map!Digit.array;
immutable SudokuTable problem =
"850002400" ~
"720000009" ~
"004000000" ~
"000107002" ~
"305000900" ~
"040000000" ~
"000080070" ~
"017000000" ~
"000036040";
writeln(formatSudoku(problem).replace("0", "."));
 
immutable solutionSudokuTable problem = sudokuSolverValidateCells!(problem);"
850002400
if (solution[0] == TableItem.init)
720000009
004000000
000107002
305000900
040000000
000080070
017000000
000036040".removechars(whitespace));
problem.representSudoku.writeln;
 
immutable solution = problem.sudokuSolver;
if (solution.isNull)
writeln("Unsolvable!");
else
writeln(formatSudoku(solution)).get.representSudoku.writeln;
}</langsyntaxhighlight>
{{out}}
Output:
<pre>8 5 . | . . 2 | 4 . .
7 2 . | . . . | . . 9
Line 1,701 ⟶ 2,926:
6 1 7 | 4 2 5 | 8 9 3
5 9 8 | 7 3 6 | 2 4 1 </pre>
 
===Short Version===
Adapted from: http://code.activestate.com/recipes/576725-brute-force-sudoku-solver/
<syntaxhighlight lang="d">import std.stdio, std.algorithm, std.range;
 
const(int)[] solve(immutable int[] s) pure nothrow @safe {
immutable i = s.countUntil(0);
if (i == -1)
return s;
 
enum B = (int i, int j) => i / 27 ^ j / 27 | (i%9 / 3 ^ j%9 / 3);
immutable c = iota(81)
.filter!(j => !((i - j) % 9 * (i/9 ^ j/9) * B(i, j)))
.map!(j => s[j]).array;
 
foreach (immutable v; 1 .. 10)
if (!c.canFind(v)) {
const r = solve(s[0 .. i] ~ v ~ s[i + 1 .. $]);
if (!r.empty)
return r;
}
return null;
}
 
void main() {
immutable problem = [
8, 5, 0, 0, 0, 2, 4, 0, 0,
7, 2, 0, 0, 0, 0, 0, 0, 9,
0, 0, 4, 0, 0, 0, 0, 0, 0,
0, 0, 0, 1, 0, 7, 0, 0, 2,
3, 0, 5, 0, 0, 0, 9, 0, 0,
0, 4, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 8, 0, 0, 7, 0,
0, 1, 7, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 3, 6, 0, 4, 0];
writefln("%(%s\n%)", problem.solve.chunks(9));
}</syntaxhighlight>
{{out}}
<pre>[8, 5, 9, 6, 1, 2, 4, 3, 7]
[7, 2, 3, 8, 5, 4, 1, 6, 9]
[1, 6, 4, 3, 7, 9, 5, 2, 8]
[9, 8, 6, 1, 4, 7, 3, 5, 2]
[3, 7, 5, 2, 6, 8, 9, 1, 4]
[2, 4, 1, 5, 9, 3, 7, 8, 6]
[4, 3, 2, 9, 8, 1, 6, 7, 5]
[6, 1, 7, 4, 2, 5, 8, 9, 3]
[5, 9, 8, 7, 3, 6, 2, 4, 1]</pre>
 
===No-Heap Version===
This version is similar to the precedent one, but it shows idioms to avoid memory allocations on the heap. This is enforced by the use of the @nogc attribute.
<syntaxhighlight lang="d">import std.stdio, std.algorithm, std.range, std.typecons;
 
Nullable!(const ubyte[81]) solve(in ubyte[81] s) pure nothrow @safe @nogc {
immutable i = s[].countUntil(0);
if (i == -1)
return typeof(return)(s);
 
static immutable B = (in int i, in int j) pure nothrow @safe @nogc =>
i / 27 ^ j / 27 | (i % 9 / 3 ^ j % 9 / 3);
 
ubyte[81] c = void;
size_t len = 0;
foreach (immutable int j; 0 .. c.length)
if (!((i - j) % 9 * (i/9 ^ j/9) * B(i, j)))
c[len++] = s[j];
 
foreach (immutable ubyte v; 1 .. 10)
if (!c[0 .. len].canFind(v)) {
ubyte[81] s2 = void;
s2[0 .. i] = s[0 .. i];
s2[i] = v;
s2[i + 1 .. $] = s[i + 1 .. $];
const r = solve(s2);
if (!r.isNull)
return typeof(return)(r);
}
return typeof(return)();
}
 
void main() {
immutable ubyte[81] problem = [
8, 5, 0, 0, 0, 2, 4, 0, 0,
7, 2, 0, 0, 0, 0, 0, 0, 9,
0, 0, 4, 0, 0, 0, 0, 0, 0,
0, 0, 0, 1, 0, 7, 0, 0, 2,
3, 0, 5, 0, 0, 0, 9, 0, 0,
0, 4, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 8, 0, 0, 7, 0,
0, 1, 7, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 3, 6, 0, 4, 0];
writefln("%(%s\n%)", problem.solve.get[].chunks(9));
}</syntaxhighlight>
Same output.
 
=={{header|Delphi}}==
Example taken from C++
<langsyntaxhighlight lang="delphi">type
TIntArray = array of Integer;
 
Line 1,715 ⟶ 3,033:
function CheckValidity(val: Integer; x: Integer; y: Integer): Boolean;
function ToString: string; reintroduce;
procedurefunction PlaceNumber(pos: Integer): Boolean;
public
constructor Create(s: string);
Line 1,785 ⟶ 3,103:
end;
 
procedurefunction TSudokuSolver.PlaceNumber(pos: Integer): Boolean;
var
n: Integer;
begin
Result := False;
if Pos = 81 then
begin
raise Exception.Create('Finished!');
Result := True;
Exit;
end;
if FGrid[pos] > 0 then
begin
Result := PlaceNumber(Succ(pos));
Exit;
end;
Line 1,801 ⟶ 3,123:
begin
FGrid[pos] := n;
Result := PlaceNumber(Succ(pos));
FGrid[pos]if :=not 0;Result then
FGrid[pos] := 0;
end;
end;
Line 1,818 ⟶ 3,141:
procedure TSudokuSolver.Solve;
begin
if not PlaceNumber(0) then
try
ShowMessage('Unsolvable')
PlaceNumber(0);
else
ShowMessage('Unsolvable');
ShowMessage('Solved!');
except
ShowMessage((ExceptObject as Exception).Message);
ShowMessage(ToString);
end;
end;</langsyntaxhighlight>
Usage:
<langsyntaxhighlight lang="delphi">var
SudokuSolver: TSudokuSolver;
begin
Line 1,844 ⟶ 3,165:
FreeAndNil(SudokuSolver);
end;
end;</langsyntaxhighlight>
 
=={{header|EasyLang}}==
<syntaxhighlight lang="text">
len row[] 90
len col[] 90
len box[] 90
len grid[] 82
#
proc init . .
for pos = 1 to 81
if pos mod 9 = 1
s$ = input
if s$ = ""
s$ = input
.
len inp[] 0
for i = 1 to len s$
if substr s$ i 1 <> " "
inp[] &= number substr s$ i 1
.
.
.
dig = number inp[(pos - 1) mod 9 + 1]
if dig > 0
grid[pos] = dig
r = (pos - 1) div 9
c = (pos - 1) mod 9
b = r div 3 * 3 + c div 3
row[r * 10 + dig] = 1
col[c * 10 + dig] = 1
box[b * 10 + dig] = 1
.
.
.
init
#
proc display . .
for i = 1 to 81
write grid[i] & " "
if i mod 3 = 0
write " "
.
if i mod 9 = 0
print ""
.
if i mod 27 = 0
print ""
.
.
.
#
proc solve pos . .
while grid[pos] <> 0
pos += 1
.
if pos > 81
# solved
display
return
.
r = (pos - 1) div 9
c = (pos - 1) mod 9
b = r div 3 * 3 + c div 3
r *= 10
c *= 10
b *= 10
for d = 1 to 9
if row[r + d] = 0 and col[c + d] = 0 and box[b + d] = 0
grid[pos] = d
row[r + d] = 1
col[c + d] = 1
box[b + d] = 1
solve pos + 1
row[r + d] = 0
col[c + d] = 0
box[b + d] = 0
.
.
grid[pos] = 0
.
solve 1
#
input_data
5 3 0 0 2 4 7 0 0
0 0 2 0 0 0 8 0 0
1 0 0 7 0 3 9 0 2
 
0 0 8 0 7 2 0 4 9
0 2 0 9 8 0 0 7 0
7 9 0 0 0 0 0 8 0
 
0 0 0 0 3 0 5 0 6
9 6 0 0 1 0 3 0 0
0 5 0 6 9 0 0 1 0
 
</syntaxhighlight>
 
=={{header|Elixir}}==
{{trans|Erlang}}
<syntaxhighlight lang="elixir">defmodule Sudoku do
def display( grid ), do: ( for y <- 1..9, do: display_row(y, grid) )
def start( knowns ), do: Enum.into( knowns, Map.new )
def solve( grid ) do
sure = solve_all_sure( grid )
solve_unsure( potentials(sure), sure )
end
def task( knowns ) do
IO.puts "start"
start = start( knowns )
display( start )
IO.puts "solved"
solved = solve( start )
display( solved )
IO.puts ""
end
defp bt( grid ), do: bt_reject( is_not_allowed(grid), grid )
defp bt_accept( true, board ), do: throw( {:ok, board} )
defp bt_accept( false, grid ), do: bt_loop( potentials_one_position(grid), grid )
defp bt_loop( {position, values}, grid ), do: ( for x <- values, do: bt( Map.put(grid, position, x) ) )
defp bt_reject( true, _grid ), do: :backtrack
defp bt_reject( false, grid ), do: bt_accept( is_all_correct(grid), grid )
defp display_row( row, grid ) do
for x <- [1, 4, 7], do: display_row_group( x, row, grid )
display_row_nl( row )
end
defp display_row_group( start, row, grid ) do
Enum.each(start..start+2, &IO.write " #{Map.get( grid, {&1, row}, ".")}")
IO.write " "
end
defp display_row_nl( n ) when n in [3,6,9], do: IO.puts "\n"
defp display_row_nl( _n ), do: IO.puts ""
defp is_all_correct( grid ), do: map_size( grid ) == 81
defp is_not_allowed( grid ) do
is_not_allowed_rows( grid ) or is_not_allowed_columns( grid ) or is_not_allowed_groups( grid )
end
defp is_not_allowed_columns( grid ), do: values_all_columns(grid) |> Enum.any?(&is_not_allowed_values/1)
defp is_not_allowed_groups( grid ), do: values_all_groups(grid) |> Enum.any?(&is_not_allowed_values/1)
defp is_not_allowed_rows( grid ), do: values_all_rows(grid) |> Enum.any?(&is_not_allowed_values/1)
defp is_not_allowed_values( values ), do: length( values ) != length( Enum.uniq(values) )
defp group_positions( {x, y} ) do
for colum <- group_positions_close(x), row <- group_positions_close(y), do: {colum, row}
end
defp group_positions_close( n ) when n < 4, do: [1,2,3]
defp group_positions_close( n ) when n < 7, do: [4,5,6]
defp group_positions_close( _n ) , do: [7,8,9]
defp positions_not_in_grid( grid ) do
keys = Map.keys( grid )
for x <- 1..9, y <- 1..9, not {x, y} in keys, do: {x, y}
end
defp potentials_one_position( grid ) do
Enum.min_by( potentials( grid ), fn {_position, values} -> length(values) end )
end
defp potentials( grid ), do: List.flatten( for x <- positions_not_in_grid(grid), do: potentials(x, grid) )
defp potentials( position, grid ) do
useds = potentials_used_values( position, grid )
{position, Enum.to_list(1..9) -- useds }
end
defp potentials_used_values( {x, y}, grid ) do
row_values = (for row <- 1..9, row != x, do: {row, y}) |> potentials_values( grid )
column_values = (for column <- 1..9, column != y, do: {x, column}) |> potentials_values( grid )
group_values = group_positions({x, y}) -- [ {x, y} ] |> potentials_values( grid )
row_values ++ column_values ++ group_values
end
defp potentials_values( keys, grid ) do
for x <- keys, val = grid[x], do: val
end
defp values_all_columns( grid ) do
for x <- 1..9, do:
( for y <- 1..9, do: {x, y} ) |> potentials_values( grid )
end
defp values_all_groups( grid ) do
[[g1,g2,g3], [g4,g5,g6], [g7,g8,g9]] = for x <- [1,4,7], do: values_all_groups(x, grid)
[g1,g2,g3,g4,g5,g6,g7,g8,g9]
end
defp values_all_groups( x, grid ) do
for x_offset <- x..x+2, do: values_all_groups(x, x_offset, grid)
end
defp values_all_groups( _x, x_offset, grid ) do
( for y_offset <- group_positions_close(x_offset), do: {x_offset, y_offset} )
|> potentials_values( grid )
end
defp values_all_rows( grid ) do
for y <- 1..9, do:
( for x <- 1..9, do: {x, y} ) |> potentials_values( grid )
end
defp solve_all_sure( grid ), do: solve_all_sure( solve_all_sure_values(grid), grid )
defp solve_all_sure( [], grid ), do: grid
defp solve_all_sure( sures, grid ) do
solve_all_sure( Enum.reduce(sures, grid, &solve_all_sure_store/2) )
end
defp solve_all_sure_values( grid ), do: (for{position, [value]} <- potentials(grid), do: {position, value} )
defp solve_all_sure_store( {position, value}, acc ), do: Map.put( acc, position, value )
defp solve_unsure( [], grid ), do: grid
defp solve_unsure( _potentials, grid ) do
try do
bt( grid )
catch
{:ok, board} -> board
end
end
end
simple = [{{1, 1}, 3}, {{2, 1}, 9}, {{3, 1},4}, {{6, 1}, 2}, {{7, 1}, 6}, {{8, 1}, 7},
{{4, 2}, 3}, {{7, 2}, 4},
{{1, 3}, 5}, {{4, 3}, 6}, {{5, 3}, 9}, {{8, 3}, 2},
{{2, 4}, 4}, {{3, 4}, 5}, {{7, 4}, 9},
{{1, 5}, 6}, {{9, 5}, 7},
{{3, 6}, 7}, {{7, 6}, 5}, {{8, 6}, 8},
{{2, 7}, 1}, {{5, 7}, 6}, {{6, 7}, 7}, {{9, 7}, 8},
{{3, 8}, 9}, {{6, 8}, 8},
{{2, 9}, 2}, {{3, 9}, 6}, {{4, 9}, 4}, {{7, 9}, 7}, {{8, 9}, 3}, {{9, 9}, 5}]
Sudoku.task( simple )
 
difficult = [{{6, 2}, 3}, {{8, 2}, 8}, {{9, 2}, 5},
{{3, 3}, 1}, {{5, 3}, 2},
{{4, 4}, 5}, {{6, 4}, 7},
{{3, 5}, 4}, {{7, 5}, 1},
{{2, 6}, 9},
{{1, 7}, 5}, {{8, 7}, 7}, {{9, 7}, 3},
{{3, 8}, 2}, {{5, 8}, 1},
{{5, 9}, 4}, {{9, 9}, 9}]
Sudoku.task( difficult )</syntaxhighlight>
 
{{out}}
<pre>
start
3 9 4 . . 2 6 7 .
. . . 3 . . 4 . .
5 . . 6 9 . . 2 .
 
. 4 5 . . . 9 . .
6 . . . . . . . 7
. . 7 . . . 5 8 .
 
. 1 . . 6 7 . . 8
. . 9 . . 8 . . .
. 2 6 4 . . 7 3 5
 
solved
3 9 4 8 5 2 6 7 1
2 6 8 3 7 1 4 5 9
5 7 1 6 9 4 8 2 3
 
1 4 5 7 8 3 9 6 2
6 8 2 9 4 5 3 1 7
9 3 7 1 2 6 5 8 4
 
4 1 3 5 6 7 2 9 8
7 5 9 2 3 8 1 4 6
8 2 6 4 1 9 7 3 5
 
 
start
. . . . . . . . .
. . . . . 3 . 8 5
. . 1 . 2 . . . .
 
. . . 5 . 7 . . .
. . 4 . . . 1 . .
. 9 . . . . . . .
 
5 . . . . . . 7 3
. . 2 . 1 . . . .
. . . . 4 . . . 9
 
solved
9 8 7 6 5 4 3 2 1
2 4 6 1 7 3 9 8 5
3 5 1 9 2 8 7 4 6
 
1 2 8 5 3 7 6 9 4
6 3 4 8 9 2 1 5 7
7 9 5 4 6 1 8 3 2
 
5 1 9 2 8 6 4 7 3
4 7 2 3 1 9 5 6 8
8 6 3 7 4 5 2 1 9
</pre>
 
=={{header|Erlang}}==
I first try to solve the Sudoku grid without guessing. For the guessing part I eschew spawning a process for each guess, instead opting for backtracking. It is fun trying new things.
<syntaxhighlight lang="erlang">
-module( sudoku ).
 
-export( [display/1, start/1, solve/1, task/0] ).
 
display( Grid ) -> [display_row(Y, Grid) || Y <- lists:seq(1, 9)].
%% A known value is {{Column, Row}, Value}
%% Top left corner is {1, 1}, Bottom right corner is {9,9}
start( Knowns ) -> dict:from_list( Knowns ).
 
solve( Grid ) ->
Sure = solve_all_sure( Grid ),
solve_unsure( potentials(Sure), Sure ).
 
task() ->
Simple = [{{1, 1}, 3}, {{2, 1}, 9}, {{3, 1},4}, {{6, 1}, 2}, {{7, 1}, 6}, {{8, 1}, 7},
{{4, 2}, 3}, {{7, 2}, 4},
{{1, 3}, 5}, {{4, 3}, 6}, {{5, 3}, 9}, {{8, 3}, 2},
{{2, 4}, 4}, {{3, 4}, 5}, {{7, 4}, 9},
{{1, 5}, 6}, {{9, 5}, 7},
{{3, 6}, 7}, {{7, 6}, 5}, {{8, 6}, 8},
{{2, 7}, 1}, {{5, 7}, 6}, {{6, 7}, 7}, {{9, 7}, 8},
{{3, 8}, 9}, {{6, 8}, 8},
{{2, 9}, 2}, {{3, 9}, 6}, {{4, 9}, 4}, {{7, 9}, 7}, {{8, 9}, 3}, {{9, 9}, 5}],
task( Simple ),
Difficult = [{{6, 2}, 3}, {{8, 2}, 8}, {{9, 2}, 5},
{{3, 3}, 1}, {{5, 3}, 2},
{{4, 4}, 5}, {{6, 4}, 7},
{{3, 5}, 4}, {{7, 5}, 1},
{{2, 6}, 9},
{{1, 7}, 5}, {{8, 7}, 7}, {{9, 7}, 3},
{{3, 8}, 2}, {{5, 8}, 1},
{{5, 9}, 4}, {{9, 9}, 9}],
task( Difficult ).
 
 
 
bt( Grid ) -> bt_reject( is_not_allowed(Grid), Grid ).
 
bt_accept( true, Board ) -> erlang:throw( {ok, Board} );
bt_accept( false, Grid ) -> bt_loop( potentials_one_position(Grid), Grid ).
 
bt_loop( {Position, Values}, Grid ) -> [bt( dict:store(Position, X, Grid) ) || X <- Values].
 
bt_reject( true, _Grid ) -> backtrack;
bt_reject( false, Grid ) -> bt_accept( is_all_correct(Grid), Grid ).
 
display_row( Row, Grid ) ->
[display_row_group( X, Row, Grid ) || X <- [1, 4, 7]],
display_row_nl( Row ).
 
display_row_group( Start, Row, Grid ) ->
[io:fwrite(" ~c", [display_value(X, Row, Grid)]) || X <- [Start, Start+1, Start+2]],
io:fwrite( " " ).
 
display_row_nl( N ) when N =:= 3; N =:= 6; N =:= 9 -> io:nl(), io:nl();
display_row_nl( _N ) -> io:nl().
 
display_value( X, Y, Grid ) -> display_value( dict:find({X, Y}, Grid) ).
 
display_value( error ) -> $.;
display_value( {ok, Value} ) -> Value + $0.
 
is_all_correct( Grid ) -> dict:size( Grid ) =:= 81.
 
is_not_allowed( Grid ) ->
is_not_allowed_rows( Grid )
orelse is_not_allowed_columns( Grid )
orelse is_not_allowed_groups( Grid ).
 
is_not_allowed_columns( Grid ) -> lists:any( fun is_not_allowed_values/1, values_all_columns(Grid) ).
 
is_not_allowed_groups( Grid ) -> lists:any( fun is_not_allowed_values/1, values_all_groups(Grid) ).
 
is_not_allowed_rows( Grid ) -> lists:any( fun is_not_allowed_values/1, values_all_rows(Grid) ).
 
is_not_allowed_values( Values ) -> erlang:length( Values ) =/= erlang:length( lists:usort(Values) ).
 
group_positions( {X, Y} ) -> [{Colum, Row} || Colum <- group_positions_close(X), Row <- group_positions_close(Y)].
 
group_positions_close( N ) when N < 4 -> [1,2,3];
group_positions_close( N ) when N < 7 -> [4,5,6];
group_positions_close( _N ) -> [7,8,9].
 
positions_not_in_grid( Grid ) ->
Keys = dict:fetch_keys( Grid ),
[{X, Y} || X <- lists:seq(1, 9), Y <- lists:seq(1, 9), not lists:member({X, Y}, Keys)].
 
potentials_one_position( Grid ) ->
[{_Shortest, Position, Values} | _T] = lists:sort( [{erlang:length(Values), Position, Values} || {Position, Values} <- potentials( Grid )] ),
{Position, Values}.
 
potentials( Grid ) -> lists:flatten( [potentials(X, Grid) || X <- positions_not_in_grid(Grid)] ).
 
potentials( Position, Grid ) ->
Useds = potentials_used_values( Position, Grid ),
{Position, [Value || Value <- lists:seq(1, 9) -- Useds]}.
 
potentials_used_values( {X, Y}, Grid ) ->
Row_positions = [{Row, Y} || Row <- lists:seq(1, 9), Row =/= X],
Row_values = potentials_values( Row_positions, Grid ),
Column_positions = [{X, Column} || Column <- lists:seq(1, 9), Column =/= Y],
Column_values = potentials_values( Column_positions, Grid ),
Group_positions = lists:delete( {X, Y}, group_positions({X, Y}) ),
Group_values = potentials_values( Group_positions, Grid ),
Row_values ++ Column_values ++ Group_values.
 
potentials_values( Keys, Grid ) ->
Row_values_unfiltered = [dict:find(X, Grid) || X <- Keys],
[Value || {ok, Value} <- Row_values_unfiltered].
 
values_all_columns( Grid ) -> [values_all_columns(X, Grid) || X <- lists:seq(1, 9)].
 
values_all_columns( X, Grid ) ->
Positions = [{X, Y} || Y <- lists:seq(1, 9)],
potentials_values( Positions, Grid ).
 
values_all_groups( Grid ) ->
[G123, G456, G789] = [values_all_groups(X, Grid) || X <- [1, 4, 7]],
[G1,G2,G3] = G123,
[G4,G5,G6] = G456,
[G7,G8,G9] = G789,
[G1,G2,G3,G4,G5,G6,G7,G8,G9].
 
values_all_groups( X, Grid ) ->[values_all_groups(X, X_offset, Grid) || X_offset <- [X, X+1, X+2]].
 
values_all_groups( _X, X_offset, Grid ) ->
Positions = [{X_offset, Y_offset} || Y_offset <- group_positions_close(X_offset)],
potentials_values( Positions, Grid ).
 
values_all_rows( Grid ) ->[values_all_rows(Y, Grid) || Y <- lists:seq(1, 9)].
 
values_all_rows( Y, Grid ) ->
Positions = [{X, Y} || X <- lists:seq(1, 9)],
potentials_values( Positions, Grid ).
 
solve_all_sure( Grid ) -> solve_all_sure( solve_all_sure_values(Grid), Grid ).
 
solve_all_sure( [], Grid ) -> Grid;
solve_all_sure( Sures, Grid ) -> solve_all_sure( lists:foldl(fun solve_all_sure_store/2, Grid, Sures) ).
 
solve_all_sure_values( Grid ) -> [{Position, Value} || {Position, [Value]} <- potentials(Grid)].
 
solve_all_sure_store( {Position, Value}, Acc ) -> dict:store( Position, Value, Acc ).
 
solve_unsure( [], Grid ) -> Grid;
solve_unsure( _Potentials, Grid ) ->
try
bt( Grid )
 
catch
_:{ok, Board} -> Board
 
end.
 
task( Knowns ) ->
io:fwrite( "Start~n" ),
Start = start( Knowns ),
display( Start ),
io:fwrite( "Solved~n" ),
Solved = solve( Start ),
display( Solved ),
io:nl().
</syntaxhighlight>
{{out}}
<pre>
5> sudoku:task().
Start
3 9 4 . . 2 6 7 .
. . . 3 . . 4 . .
5 . . 6 9 . . 2 .
 
. 4 5 . . . 9 . .
6 . . . . . . . 7
. . 7 . . . 5 8 .
 
. 1 . . 6 7 . . 8
. . 9 . . 8 . . .
. 2 6 4 . . 7 3 5
 
Solved
3 9 4 8 5 2 6 7 1
2 6 8 3 7 1 4 5 9
5 7 1 6 9 4 8 2 3
 
1 4 5 7 8 3 9 6 2
6 8 2 9 4 5 3 1 7
9 3 7 1 2 6 5 8 4
 
4 1 3 5 6 7 2 9 8
7 5 9 2 3 8 1 4 6
8 2 6 4 1 9 7 3 5
 
 
Start
. . . . . . . . .
. . . . . 3 . 8 5
. . 1 . 2 . . . .
 
. . . 5 . 7 . . .
. . 4 . . . 1 . .
. 9 . . . . . . .
 
5 . . . . . . 7 3
. . 2 . 1 . . . .
. . . . 4 . . . 9
 
Solved
9 8 7 6 5 4 3 2 1
2 4 6 1 7 3 9 8 5
3 5 1 9 2 8 7 4 6
 
1 2 8 5 3 7 6 9 4
6 3 4 8 9 2 1 5 7
7 9 5 4 6 1 8 3 2
 
5 1 9 2 8 6 4 7 3
4 7 2 3 1 9 5 6 8
8 6 3 7 4 5 2 1 9
</pre>
 
=={{header|ERRE}}==
Sudoku solver. Program solves Sudoku grid with an iterative method: it's taken from ERRE distribution disk and so comments are in Italian. Grid data are contained in the file
SUDOKU.TXT
 
Example of SUDOKU.TXT
 
503600009
 
010002600
 
900000080
 
000700005
 
006804100
 
200003000
 
030000008
 
004300050
 
800006702
 
0 is the empty cell.
 
<syntaxhighlight lang="erre">
!--------------------------------------------------------------------
! risolve Sudoku: in input il file SUDOKU.TXT
! Metodo seguito : cancellazioni successive e quando non possibile
! ricerca combinatoria sulle celle con due valori
! possibili - max. 30 livelli di ricorsione
! Non risolve se,dopo l'analisi per la cancellazione,
! restano solo celle a 4 valori
!--------------------------------------------------------------------
 
PROGRAM SUDOKU
 
LABEL 76,77,88,91,97,99
 
DIM TAV$[9,9] ! 81 caselle in nove quadranti
! cella non definita --> 0/. nel file SUDOKU.TXT
! diventa 123456789 dopo LEGGI_SCHEMA
 
!---------------------------------------------------------------------------
! tabelle per gestire la ricerca combinatoria
! (primo indice--> livelli ricorsione)
!---------------------------------------------------------------------------
DIM TAV2$[30,9,9],INFO[30,4]
 
!$INCLUDE="PC.LIB"
 
PROCEDURE MESSAGGI(MEX%)
CASE MEX% OF
1-> LOCATE(21,1) PRINT("Cancellazione successiva - liv. 1") END ->
2-> LOCATE(21,1) PRINT("Cancellazione successiva - liv. 2") END ->
3-> LOCATE(22,1) PRINT("Ricerca combinatoria - liv.";LIVELLO;" ") END ->
END CASE
END PROCEDURE
 
PROCEDURE VISUALIZZA_SCHEMA
LOCATE(1,1)
PRINT("+---+---+---+---+---+---+---+---+----+")
FOR I=1 TO 9 DO
FOR J=1 TO 9 DO
PRINT("|";)
IF LEN(TAV$[I,J])=1 THEN
PRINT(" ";TAV$[I,J];" ";)
ELSE
PRINT(" ";)
END IF
END FOR
PRINT("³")
IF I<>9 THEN PRINT("+---+---+---+---+---+---+---+---+----+") END IF
END FOR
PRINT("+---+---+---+---+---+---+---+---+----+")
END PROCEDURE
 
!------------------------------------------------------------------------
! in input la cella (riga,colonna)
! in output se ha un valore definito
!------------------------------------------------------------------------
PROCEDURE VALORE_DEFINITO
FLAG%=FALSE
IF LEN(TAV$[RIGA,COLONNA])=1 THEN FLAG%=TRUE END IF
END PROCEDURE
 
 
PROCEDURE SALVA_CONFIG
LIVELLO=LIVELLO+1
FOR R=1 TO 9 DO
FOR S=1 TO 9 DO
TAV2$[LIVELLO,R,S]=TAV$[R,S]
END FOR
END FOR
INFO[LIVELLO,0]=1 INFO[LIVELLO,1]=RIGA INFO[LIVELLO,2]=COLONNA
INFO[LIVELLO,3]=SECOND INFO[LIVELLO,4]=THIRD
END PROCEDURE
 
PROCEDURE RIPRISTINA_CONFIG
91:
LIVELLO=LIVELLO-1
IF INFO[LIVELLO,0]=3 THEN GOTO 91 END IF
FOR R=1 TO 9 DO
FOR S=1 TO 9 DO
TAV$[R,S]=TAV2$[LIVELLO,R,S]
END FOR
END FOR
RIGA=INFO[LIVELLO,1] COLONNA=INFO[LIVELLO,2]
SECOND=INFO[LIVELLO,3] THIRD=INFO[LIVELLO,4]
IF INFO[LIVELLO,0]=1 THEN
TAV$[RIGA,COLONNA]=MID$(STR$(SECOND),2)
END IF
IF INFO[LIVELLO,0]=2 THEN
IF THIRD<>0 THEN
TAV$[RIGA,COLONNA]=MID$(STR$(THIRD),2)
ELSE
GOTO 91
END IF
END IF
INFO[LIVELLO,0]=INFO[LIVELLO,0]+1
VISUALIZZA_SCHEMA
END PROCEDURE
 
PROCEDURE VERIFICA_SE_FINITO
COMPLETO%=TRUE
FOR RIGA=1 TO 9 DO
PRD#=1
FOR COLONNA=1 TO 9 DO
PRD#=PRD#*VAL(TAV$[RIGA,COLONNA])
END FOR
IF PRD#<>362880 THEN COMPLETO%=FALSE EXIT END IF
END FOR
IF NOT COMPLETO% THEN EXIT PROCEDURE END IF
FOR COLONNA=1 TO 9 DO
PRD#=1
FOR RIGA=1 TO 9 DO
PRD#=PRD#*VAL(TAV$[RIGA,COLONNA])
END FOR
IF PRD#<>362880 THEN COMPLETO%=FALSE EXIT END IF
END FOR
END PROCEDURE
 
!-------------------------------------------------------------------
! toglie i valore certi dalle celle sulla
! stessa riga-stessa colonna-stesso quadrante
!-------------------------------------------------------------------
PROCEDURE TOGLI_VALORE
 
!iniziamo a togliere il valore dalla stessa riga ....
FOR J=1 TO 9 DO
CH$=TAV$[RIGA,J] CH=VAL(Z$)
IF LEN(CH$)<>1 THEN
CHANGE(CH$,CH,"-"->CH$)
TAV$[RIGA,J]=CH$
END IF
END FOR
!... iniziamo a togliere il valore dalla stessa colonna ...
FOR I=1 TO 9 DO
CH$=TAV$[I,COLONNA] CH=VAL(Z$)
IF LEN(CH$)<>1 THEN
CHANGE(CH$,CH,"-"->CH$)
TAV$[I,COLONNA]=CH$
END IF
END FOR
!... iniziamo a togliere il valore dallo stesso quadrante
R=INT(RIGA/3.1)*3+1
S=INT(COLONNA/3.1)*3+1
FOR I=R TO R+2 DO
FOR J=S TO S+2 DO
CH$=TAV$[I,J] CH=VAL(Z$)
IF LEN(CH$)<>1 THEN
CHANGE(CH$,CH,"-"->CH$)
TAV$[I,J]=CH$
END IF
END FOR
END FOR
MESSAGGI(1)
END PROCEDURE
 
PROCEDURE ESAMINA_SCHEMA
FOR RIGA=1 TO 9 DO
FOR COLONNA=1 TO 9 DO
VALORE_DEFINITO
IF FLAG% THEN
Z$=TAV$[RIGA,COLONNA]
TOGLI_VALORE
END IF
END FOR
END FOR
END PROCEDURE
 
PROCEDURE IDENTIFICA_UNICO
FOR KL=1 TO 9 DO
KL$=MID$(STR$(KL),2)
NN=0
FOR H=1 TO LEN(ZZ$) DO
IF MID$(ZZ$,H,1)=KL$ THEN NN=NN+1 END IF
END FOR
IF NN=1 THEN Q=INSTR(ZZ$,KL$) KL=9 END IF
END FOR
END PROCEDURE
 
!----------------------------------------------------------------------------
! intercetta i valori unici per le celle ancora non definite
!----------------------------------------------------------------------------
PROCEDURE TOGLI_VALORE2
 
MESSAGGI(2)
! iniziamo dalle righe ....
OK%=FALSE
FOR RIGA=1 TO 9 DO
ZZ$=""
FOR COLONNA=1 TO 9 DO
IF LEN(TAV$[RIGA,COLONNA])<>1 THEN
ZZ$=ZZ$+TAV$[RIGA,COLONNA]
ELSE
ZZ$=ZZ$+STRING$(9," ")
END IF
END FOR
Q=0 IDENTIFICA_UNICO
IF Q<>0 THEN
COLONNA=INT(Q/9.1)+1
TAV$[RIGA,COLONNA]=KL$
OK%=TRUE EXIT
END IF
END FOR
IF OK% THEN GOTO 76 END IF
 
! .... poi dalle colonne ....
FOR COLONNA=1 TO 9 DO
ZZ$=""
FOR RIGA=1 TO 9 DO
IF LEN(TAV$[RIGA,COLONNA])<>1 THEN
ZZ$=ZZ$+TAV$[RIGA,COLONNA]
ELSE
ZZ$=ZZ$+STRING$(9," ")
END IF
END FOR
Q=0 IDENTIFICA_UNICO
IF Q<>0 THEN
RIGA=INT(Q/9.1)+1
TAV$[RIGA,COLONNA]=KL$ OK%=TRUE EXIT
END IF
END FOR
IF OK% THEN GOTO 76 END IF
 
!.... e infine i quadranti
FOR QUADRANTE=1 TO 9 DO
ZZ$=""
CASE QUADRANTE OF
1-> R=1 S=1 END ->
2-> R=1 S=4 END ->
3-> R=1 S=7 END ->
4-> R=4 S=1 END ->
5-> R=4 S=4 END ->
6-> R=4 S=7 END ->
7-> R=7 S=1 END ->
8-> R=7 S=4 END ->
9-> R=7 S=7 END ->
END CASE
FOR RIGA=R TO R+2 DO
FOR COLONNA=S TO S+2 DO
IF LEN(TAV$[RIGA,COLONNA])<>1 THEN
ZZ$=ZZ$+TAV$[RIGA,COLONNA]
ELSE
ZZ$=ZZ$+STRING$(9," ")
END IF
END FOR
END FOR
Q=0 IDENTIFICA_UNICO
IF Q<>0 THEN
CASE Q OF
1..9-> ALFA=R BETA=S END ->
10..18-> ALFA=R BETA=S+1 END ->
19..27-> ALFA=R BETA=S+2 END ->
28..36-> ALFA=R+1 BETA=S END ->
37..45-> ALFA=R+1 BETA=S+1 END ->
46..54-> ALFA=R+1 BETA=S+2 END ->
55..63-> ALFA=R+2 BETA=S END ->
64..72-> ALFA=R+2 BETA=S+1 END ->
OTHERWISE
ALFA=R+2 BETA=S+2
END CASE
77:
TAV$[ALFA,BETA]=KL$ EXIT
END IF
END FOR
76:
MESSAGGI(2)
END PROCEDURE
 
PROCEDURE CONVERTI_VALORE
FINE%=TRUE NESSUNO%=TRUE
FOR RIGA=1 TO 9 DO
FOR COLONNA=1 TO 9 DO
CH$=TAV$[RIGA,COLONNA]
IF LEN(CH$)<>1 THEN
FINE%=FALSE ! flag per fine partita -- trovati tutti
Q=0 ! conta i '-' nella stringa se ce ne sono 8,
! trovato valore
FOR Z=1 TO LEN(CH$) DO
IF MID$(CH$,Z,1)="-" THEN Q=Q+1 ELSE LAST=Z END IF
END FOR
IF Q=8 THEN
CH$=MID$(STR$(LAST),2)
TAV$[RIGA,COLONNA]=CH$
NESSUNO%=FALSE
END IF
END IF
END FOR
END FOR
END PROCEDURE
 
PROCEDURE LEGGI_SCHEMA
OPEN("I",1,"sudoku.txt")
FOR I=1 TO 9 DO
INPUT(LINE,#1,RIGA$)
FOR J=1 TO 9 DO
CH$=MID$(RIGA$,J,1)
IF CH$="0" OR CH$="." THEN
TAV$[I,J]="123456789"
ELSE
TAV$[I,J]=CH$
END IF
END FOR
END FOR
CLOSE(1)
END PROCEDURE
 
!---------------------------------------------------------------------------
! Praticamente - visita di un albero binario (caso con cella a 2 valori
! possibili)
!---------------------------------------------------------------------------
PROCEDURE RICERCA_COMBINATORIA
TRE%=TRUE
FOR RIGA=1 TO 9 DO
FOR COLONNA=1 TO 9 DO
CH$=TAV$[RIGA,COLONNA]
IF LEN(CH$)<>1 THEN
Q=0 FIRST=0 SECOND=0 THIRD=0
FOR Z=1 TO LEN(CH$) DO
IF MID$(CH$,Z,1)="-" THEN
Q=Q+1
ELSE
IF FIRST=0 THEN
FIRST=Z
ELSE
SECOND=Z
END IF
END IF
END FOR
IF Q=7 THEN
SALVA_CONFIG
TAV$[RIGA,COLONNA]=MID$(STR$(FIRST),2)
TRE%=FALSE
GOTO 97
END IF
END IF
END FOR
END FOR
IF TRE% THEN GOTO 88 END IF
97:
MESSAGGI(3)
EXIT PROCEDURE
88:
QUATTRO%=TRUE
FOR RIGA=1 TO 9 DO
FOR COLONNA=1 TO 9 DO
CH$=TAV$[RIGA,COLONNA]
IF LEN(CH$)<>1 THEN
Q=0 FIRST=0 SECOND=0 THIRD=0
FOR Z=1 TO LEN(CH$) DO
IF MID$(CH$,Z,1)="-" THEN
Q=Q+1
ELSE
IF FIRST=0 THEN
FIRST=Z
ELSE
IF SECOND=0 THEN
SECOND=Z
ELSE
THIRD=Z
END IF
END IF
END IF
END FOR
IF Q=6 THEN
SALVA_CONFIG
TAV$[RIGA,COLONNA]=MID$(STR$(FIRST),2)
QUATTRO%=FALSE
GOTO 97
END IF
END IF
END FOR
END FOR
IF QUATTRO% THEN
LIVELLO=LIVELLO+1
RIPRISTINA_CONFIG
GOTO 97
END IF
! se restano solo celle con 4 valori,forza la chiusura del ramo dell'albero
!$RCODE="STOP"
END PROCEDURE
 
BEGIN
CLS
LIVELLO=1 NZ%=0
LEGGI_SCHEMA
WHILE TRUE DO
VISUALIZZA_SCHEMA
99:
NZ%=NZ%+1
ESAMINA_SCHEMA
CONVERTI_VALORE
EXIT IF FINE%
IF NESSUNO% THEN
TOGLI_VALORE2
IF OK%=0 THEN
RICERCA_COMBINATORIA ! cerca altri celle da assegnare
END IF
END IF
END WHILE
VISUALIZZA_SCHEMA
VERIFICA_SE_FINITO
IF NOT COMPLETO% THEN
LIVELLO=LIVELLO+1
RIPRISTINA_CONFIG
GOTO 99
END IF
END PROGRAM
 
 
</syntaxhighlight>
 
=={{header|F_Sharp|F#}}==
===Backtracking===
<!-- By Martin Freedman, 26/11/2021 -->
<syntaxhighlight lang="fsharp">module SudokuBacktrack
 
//Helpers
let tuple2 a b = a,b
let flip f a b = f b a
let (>>=) f g = Option.bind g f
 
/// "A1" to "I9" squares as key in values dictionary
let key a b = $"{a}{b}"
 
/// Cross product of elements in ax and elements in bx
let cross ax bx = [| for a in ax do for b in bx do key a b |]
 
// constants
let valid = "1234567890.,"
let rows = "ABCDEFGHI"
let cols = "123456789"
let squares = cross rows cols
 
// List of all row, cols and boxes: aka units
let unitList =
[for c in cols do cross rows (string c) ]@ // row units
[for r in rows do cross (string r) cols ]@ // col units
[for rs in ["ABC";"DEF";"GHI"] do for cs in ["123";"456";"789"] do cross rs cs ] // box units
 
/// Dictionary of units for each square
let units =
[for s in squares do s, [| for u in unitList do if u |> Array.contains s then u |] ] |> Map.ofSeq
 
/// Dictionary of all peer squares in the relevant units wrt square in question
let peers =
[for s in squares do units[s] |> Array.concat |> Array.distinct |> Array.except [s] |> tuple2 s] |> Map.ofSeq
 
/// Should parse grid in many input formats or return None
let parseGrid grid =
let ints = [for c in grid do if valid |> Seq.contains c then if ",." |> Seq.contains c then 0 else (c |> string |> int)]
if Seq.length ints = 81 then ints |> Seq.zip squares |> Map.ofSeq |> Some else None
 
/// Outputs single line puzzle with 0 as empty squares
let asString = function
| Some values -> values |> Map.toSeq |> Seq.map (snd>>string) |> String.concat ""
| _ -> "No solution or Parse Failure"
 
/// Outputs puzzle in 2D format with 0 as empty squares
let prettyPrint = function
| Some (values:Map<_,_>) ->
[for r in rows do [for c in cols do (values[key r c] |> string) ] |> String.concat " " ] |> String.concat "\n"
| _ -> "No solution or Parse Failure"
 
/// Is digit allowed in the square in question? !!! hot path !!!!
/// Array/Array2D no faster and they need explicit copy since not immutable
let constraints (values:Map<_,_>) s d = peers[s] |> Seq.map (fun p -> values[p]) |> Seq.exists ((=) d) |> not
 
/// Move to next square or None if out of bounds
let next s = squares |> Array.tryFindIndex ((=)s) |> function Some i when i + 1 < 81 -> Some squares[i + 1] | _ -> None
 
/// Backtrack recursively and immutably from index
let rec backtracker (values:Map<_,_>) = function
| None -> Some values // solved!
| Some s when values[s] > 0 -> backtracker values (next s) // square not empty
| Some s ->
let rec tracker = function
| [] -> None
| d::dx ->
values
|> Map.change s (Option.map (fun _ -> d))
|> flip backtracker (next s)
|> function
| None -> tracker dx
| success -> success
[for d in 1..9 do if constraints values s d then d] |> tracker
/// solve sudoku using simple backtracking
let solve grid = grid |> parseGrid >>= flip backtracker (Some "A1")</syntaxhighlight>
'''Usage:'''
<syntaxhighlight lang="fsharp">open System
open SudokuBacktrack
 
[<EntryPoint>]
let main argv =
let puzzle = "000028000800010000000000700000600403200004000100700000030400500000000010060000000"
puzzle |> printfn "Puzzle:\n%s"
puzzle |> parseGrid |> prettyPrint |> printfn "Formatted:\n%s"
puzzle |> solve |> prettyPrint |> printfn "Solution:\n%s"
 
printfn "Press any key to exit"
Console.ReadKey() |> ignore
0</syntaxhighlight>
{{Output}}<pre>
Puzzle:
000028000800010000000000700000600403200004000100700000030400500000000010060000000
Formatted:
0 0 0 0 2 8 0 0 0
8 0 0 0 1 0 0 0 0
0 0 0 0 0 0 7 0 0
0 0 0 6 0 0 4 0 3
2 0 0 0 0 4 0 0 0
1 0 0 7 0 0 0 0 0
0 3 0 4 0 0 5 0 0
0 0 0 0 0 0 0 1 0
0 6 0 0 0 0 0 0 0
Solution:
6 1 7 3 2 8 9 4 5
8 9 4 5 1 7 2 3 6
3 2 5 9 4 6 7 8 1
9 7 8 6 5 1 4 2 3
2 5 6 8 3 4 1 7 9
1 4 3 7 9 2 6 5 8
7 3 1 4 8 9 5 6 2
4 8 9 2 6 5 3 1 7
5 6 2 1 7 3 8 9 4
Press any key to exit
</pre>
 
===Constraint Satisfaction (Norvig)===
<!-- By Martin Freedman, 27/11/2021 -->
<syntaxhighlight lang="fsharp">// https://norvig.com/sudoku.html
// using array O(1) lookup & mutable instead of map O(logn) immutable - now 6 times faster
module SudokuCPSArray
open System
 
/// from 11 to 99 as squares key maps to 0 to 80 in arrays
let key a b = (9*a + b) - 10
 
/// Keys generator
let cross ax bx = [| for a in ax do for b in bx do key a b |]
 
let digits = [|1..9|]
let rows = digits
let cols = digits
let empty = "0,."
let valid = "123456789"+empty
let boxi = [for b in 1..3..9 -> [|b..b+2|]]
let squares = cross rows cols
 
/// List of all row, cols and boxes: aka units
let unitlist =
[for c in cols -> cross rows [|c|] ]@
[for r in rows -> cross [|r|] cols ]@
[for rs in boxi do for cs in boxi do cross rs cs ]
/// Dictionary of units for each square
let units =
[|for s in squares do [| for u in unitlist do if u |> Array.contains s then u |] |]
/// Dictionary of all peer squares in the relevant units wrt square in question
let peers =
[| for s in squares do units[s] |> Array.concat |> Array.distinct |> Array.except [s] |]
 
/// folds folder returning Some on completion or returns None if not
let rec all folder state source =
match state, source with
| None, _ -> None
| Some st, [] -> Some st
| Some st , hd::rest -> folder st hd |> (fun st1 -> all folder st1 rest)
 
/// Assign digit d to values[s] and propagate (via eliminate)
/// Return Some values, except None if a contradiction is detected.
let rec assign (values:int[][]) (s) d =
values[s]
|> Array.filter ((<>)d)
|> List.ofArray |> all (fun vx d1 -> eliminate vx s d1) (Some values)
/// Eliminate digit d from values[s] and propagate when values[s] size is 1.
/// Return Some values, except return None if a contradiction is detected.
and eliminate (values:int[][]) s d =
let peerElim (values1:int[][]) = // If a square s is reduced to one value d, then *eliminate* d from the peers.
match Seq.length values1[s] with
| 0 -> None // contradiction - removed last value
| 1 -> peers[s] |> List.ofArray |> all (fun vx1 s1 -> eliminate vx1 s1 (values1[s] |> Seq.head) ) (Some values1)
| _ -> Some values1
let unitsElim values1 = // If a unit u is reduced to only one place for a value d, then *assign* it there.
units[s]
|> List.ofArray
|> all (fun (vx1:int[][]) u ->
let sx = [for s in u do if vx1[s] |> Seq.contains d then s]
match Seq.length sx with
| 0 -> None
| 1 -> assign vx1 (Seq.head sx) d
| _ -> Some vx1) (Some values1)
 
match values[s] |> Seq.contains d with
| false -> Some values // Already eliminated, nothing to do
| true ->
values[s] <- values[s]|> Array.filter ((<>)d)
values
|> peerElim
|> Option.bind unitsElim
 
/// Convert grid into a Map of {square: char} with "0","."or"," for empties.
let parseGrid grid =
let cells = [for c in grid do if valid |> Seq.contains c then if empty |> Seq.contains c then 0 else ((string>>int)c)]
if Seq.length cells = 81 then cells |> Seq.zip squares |> Map.ofSeq |> Some else None
 
/// Convert grid to a Map of constraint propagated possible values, or return None if a contradiction is detected.
let applyCPS (parsedGrid:Map<_,_>) =
let values = [| for s in squares do digits |]
parsedGrid
|> Seq.filter (fun (KeyValue(_,d)) -> digits |> Seq.contains d)
|> List.ofSeq
|> all (fun vx (KeyValue(s,d)) -> assign vx s d) (Some values)
 
/// Calculate string centre for each square - which can contain more than 1 digit when debugging
let centre s width =
let n = width - (Seq.length s)
if n <= 0 then s
else
let half = n/2 + (if (n%2>0 && width%2>0) then 1 else 0)
sprintf "%s%s%s" (String(' ',half)) s (String(' ', n - half))
 
/// Display these values as a 2-D grid. Used for debugging
let prettyPrint (values:int[][]) =
let asString = Seq.map string >> String.concat ""
let width = 1 + ([for s in squares do Seq.length values[s]] |> List.max)
let line = sprintf "%s\n" ((String('-',width*3) |> Seq.replicate 3) |> String.concat "+")
[for r in rows do
for c in cols do
sprintf "%s%s" (centre (asString values[key r c]) width) (if List.contains c [3;6] then "|" else "")
sprintf "\n%s"(if List.contains r [3;6] then line else "") ]
|> String.concat ""
 
/// Outputs single line puzzle with 0 as empty squares
let asString values = values |> Map.toSeq |> Seq.map (snd>>string) |> String.concat ""
 
let copy values = values |> Array.map Array.copy
 
/// Using depth-first search and propagation, try all possible values.
let rec search (values:int[][])=
[for s in squares do if Seq.length values[s] > 1 then Seq.length values[s] ,s]
|> function
| [] -> Some values // Solved!
| list -> // tryPick ~ Norvig's `some`
list |> List.minBy fst
|> fun (_,s) -> values[s] |> Seq.tryPick (fun d -> assign (copy values) s d |> (Option.bind search))
 
let run n g f = parseGrid >> function None -> n | Some m -> f m |> g
let solver = run "Parse Error" (Option.fold (fun _ t -> t |> prettyPrint) "No Solution")
let solveNoSearch: string -> string = solver applyCPS
let solveWithSearch: string -> string = solver (applyCPS >> (Option.bind search))
let solveWithSearchToMapOnly:string -> int[][] option = run None id (applyCPS >> (Option.bind search)) </syntaxhighlight>
'''Usage'''<syntaxhighlight lang="fsharp">open System
open SudokuCPSArray
open System.Diagnostics
open System.IO
 
[<EntryPoint>]
let main argv =
printfn "Easy board solution automatic with constraint propagation"
let easy = "..3.2.6..9..3.5..1..18.64....81.29..7.......8..67.82....26.95..8..2.3..9..5.1.3.."
easy |> solveNoSearch |> printfn "%s"
 
printfn "Simple elimination not possible"
let simple = "4.....8.5.3..........7......2.....6.....8.4......1.......6.3.7.5..2.....1.4......"
simple |> run "Parse Error" asString id |> printfn "%s"
simple |> solveNoSearch |> printfn "%s"
printfn "Try again with search:"
simple |> solveWithSearch |> printfn "%s"
let watch = Stopwatch()
 
let hard = "85...24..72......9..4.........1.7..23.5...9...4...........8..7..17..........36.4."
printfn "Hard"
watch.Start()
hard |> solveWithSearch |> printfn "%s"
watch.Stop()
printfn $"Elapsed milliseconds = {watch.ElapsedMilliseconds } ms"
watch.Reset()
let puzzles =
if Seq.length argv = 1 then
let num = argv[0] |> int
printfn $"First {num} puzzles in sudoku17 (http://staffhome.ecm.uwa.edu.au/~00013890/sudoku17)"
File.ReadLines(@"sudoku17.txt") |> Seq.take num |>Array.ofSeq
else
printfn $"All puzzles in sudoku17 (http://staffhome.ecm.uwa.edu.au/~00013890/sudoku17)"
File.ReadLines(@"sudoku17.txt") |>Array.ofSeq
watch.Start()
let result = puzzles |> Array.map solveWithSearchToMapOnly
watch.Stop()
if result |> Seq.forall Option.isSome then
let total = watch.ElapsedMilliseconds
let avg = (float total) /(float result.Length)
printfn $"\nPuzzles:{result.Length}, Total:%.2f{((float)total)/1000.0} s, Average:%.2f{avg} ms"
else
printfn "Some sudoku17 puzzles failed"
Console.ReadKey() |> ignore
0</syntaxhighlight>
{{Output}}Timings run on i7500U @2.75Ghz CPU, 16GB RAM<pre>Easy board solution automatic with constraint propagation
4 8 3 |9 2 1 |6 5 7
9 6 7 |3 4 5 |8 2 1
2 5 1 |8 7 6 |4 9 3
------+------+------
5 4 8 |1 3 2 |9 7 6
7 2 9 |5 6 4 |1 3 8
1 3 6 |7 9 8 |2 4 5
------+------+------
3 7 2 |6 8 9 |5 1 4
8 1 4 |2 5 3 |7 6 9
6 9 5 |4 1 7 |3 8 2
 
Simple elimination not possible
400000805030000000000700000020000060000080400000010000000603070500200000104000000
4 1679 12679 | 139 2369 269 | 8 1239 5
26789 3 1256789 | 14589 24569 245689 | 12679 1249 124679
2689 15689 125689 | 7 234569 245689 | 12369 12349 123469
------------------------+------------------------+------------------------
3789 2 15789 | 3459 34579 4579 | 13579 6 13789
3679 15679 15679 | 359 8 25679 | 4 12359 12379
36789 4 56789 | 359 1 25679 | 23579 23589 23789
------------------------+------------------------+------------------------
289 89 289 | 6 459 3 | 1259 7 12489
5 6789 3 | 2 479 1 | 69 489 4689
1 6789 4 | 589 579 5789 | 23569 23589 23689
 
Try again with search:
4 1 7 |3 6 9 |8 2 5
6 3 2 |1 5 8 |9 4 7
9 5 8 |7 2 4 |3 1 6
------+------+------
8 2 5 |4 3 7 |1 6 9
7 9 1 |5 8 6 |4 3 2
3 4 6 |9 1 2 |7 5 8
------+------+------
2 8 9 |6 4 3 |5 7 1
5 7 3 |2 9 1 |6 8 4
1 6 4 |8 7 5 |2 9 3
 
Hard
8 5 9 |6 1 2 |4 3 7
7 2 3 |8 5 4 |1 6 9
1 6 4 |3 7 9 |5 2 8
------+------+------
9 8 6 |1 4 7 |3 5 2
3 7 5 |2 6 8 |9 1 4
2 4 1 |5 9 3 |7 8 6
------+------+------
4 3 2 |9 8 1 |6 7 5
6 1 7 |4 2 5 |8 9 3
5 9 8 |7 3 6 |2 4 1
 
Elapsed milliseconds = 8 ms
All puzzles in sudoku17 (http://staffhome.ecm.uwa.edu.au/~00013890/sudoku17)
 
Puzzles:49151, Total:80.99 s, Average:1.65 ms</pre>
 
===SLPsolve===
<syntaxhighlight lang="fsharp">
// Solve Sudoku Like Puzzles. Nigel Galloway: September 6th., 2018
let fN y n g=let _q n' g'=[for n in n*n'..n*n'+n-1 do for g in g*g'..g*g'+g-1 do yield (n,g)]
let N=[|for n in 0..(y/n)-1 do for g in 0..(y/g)-1 do yield _q n g|]
(fun n' g'->N.[((n'/n)*n+g'/g)])
let fI n=let _q g=[for n in 0..n-1 do yield (g,n)]
let N=[|for n in 0..n-1 do yield _q n|]
(fun g (_:int)->N.[g])
let fG n=let _q g=[for n in 0..n-1 do yield (n,g)]
let N=[|for n in 0..n-1 do yield _q n|]
(fun (_:int) n->N.[n])
let fE v z n g fn=let N,G,B,fn=fI z,fG z,fN z n g,readCSV ',' fn|>List.ofSeq
let fG n g mask=List.except (N n g@G n g@B n g) mask
let b=List.except(List.map(fun n->(n.row,n.col))fn)[for n in 0..z-1 do for g in 0..z-1 do yield (n,g)]
let q=Map.ofList[for v' in v do yield ((v'),List.choose(fun n->if n.value=v' then Some(n.row,n.col) else None)fn|>List.fold(fun z (n,g)->(n,g)::fG n g z)b)]
(fG,(fun n->Map.find n q),z,v)
let SLPsolve (N,G,z,l)=
let rec nQueens col mask res=[
if col=z then yield res else
yield! List.filter(fun(n,_)->n=col)mask|>List.collect(fun(n,g)->nQueens (col+1) (N n g mask) ((n,g)::res))]
let rec sudoku l res=seq{
match l with
|h::t->let n=nQueens 0 (List.except (List.concat res) (G h)) []
yield! n|>Seq.collect(fun n->sudoku t (n::res))
|_->yield res}
sudoku l []
let printSLP n g=
List.map2(fun n g->List.map(fun(n',g')->((n',g'),n))g) (List.rev n) g|>List.concat|>List.sortBy (fun ((_,n),_)->n)|>List.groupBy(fun ((n,_),_)->n)|>List.sortBy(fun(n,_)->n)
|>List.iter(fun (_,n)->n|>Seq.fold(fun z ((_,g),v)->[z..g-1]|>Seq.iter(fun _->printf " |");printf "%s|" v; g+1 ) 0 |>ignore;printfn "")
</syntaxhighlight>
'''Usage:'''
Given sud1.csv:
<pre>
7,1,,4,,6,,2
,,,,7,,,,3
4,,,,,1,,8
,,,,1,3,,,9
,,1,,,,7
2,,,8,6
,2,,1,,,,,4
9,,,,8
,7,,6,,4,,5,2
</pre>
then
<syntaxhighlight lang="fsharp">
let n=SLPsolve (fE ([1..9]|>List.map(string)) 9 3 3 "sud1.csv")
printSLP ([1..9]|>List.map(string)) (Seq.item 0 n)
</syntaxhighlight>
{{out}}
<pre>
7|1|8|4|3|6|9|2|5|
5|6|2|9|7|8|4|1|3|
4|3|9|5|2|1|6|8|7|
6|8|5|7|1|3|2|4|9|
3|9|1|2|4|5|7|6|8|
2|4|7|8|6|9|5|3|1|
8|2|6|1|5|7|3|9|4|
9|5|4|3|8|2|1|7|6|
1|7|3|6|9|4|8|5|2|
</pre>
 
=={{header|Forth}}==
{{works with|4tH|3.60.0}}
<langsyntaxhighlight lang="forth">include lib/interprt.4th
include lib/istype.4th
include lib/argopen.4th
Line 2,211 ⟶ 4,914:
;
 
sudoku</langsyntaxhighlight>
 
=={{header|Fortran}}==
{{works with|Fortran|90 and later}}
This implementation uses a brute force method. The subroutine <code>solve</code> recursively checks valid entries using the rules defined in the function <code>is_safe</code>. When <code>solve</code> is called beyond the end of the sudoku, we know that all the currently entered values are valid. Then the result is displayed.
<langsyntaxhighlight lang="fortran">program sudoku
 
implicit none
Line 2,313 ⟶ 5,016:
end subroutine pretty_print
 
end program sudoku</langsyntaxhighlight>
{{out}}<pre>
Output:
+-----+-----+-----+
|0 0 3|0 2 0|6 0 0|
Line 2,341 ⟶ 5,044:
|8 1 4|2 5 3|7 6 9|
|6 9 5|4 1 7|3 8 2|
+-----+-----+-----+</pre>
 
 
=={{header|FreeBASIC}}==
{{trans|VBA}}
<syntaxhighlight lang="freebasic">Dim Shared As Integer cuadricula(9, 9), cuadriculaResuelta(9, 9)
 
Function isSafe(i As Integer, j As Integer, n As Integer) As Boolean
Dim As Integer iMin, jMin, f, c
If cuadricula(i, j) <> 0 Then Return (cuadricula(i, j) = n)
'cuadricula(i, j) es una celda vacía. Compruebe si n está OK
'primero revisa la fila i
For f = 1 To 9
If cuadricula(i, f) = n Then Return False
Next f
'ahora comprueba la columna j
For c = 1 To 9
If cuadricula(c, j) = n Then Return False
Next c
'finalmente, compruebe el subcuadrado de 3x3 que contiene cuadricula(i,j)
iMin = 1 + 3 * Int((i - 1) / 3)
jMin = 1 + 3 * Int((j - 1) / 3)
For c = iMin To iMin + 2
For f = jMin To jMin + 2
If cuadricula(c, f) = n Then Return False
Next f
Next c
'todas las pruebas estuvieron OK
Return True
End Function
 
Sub Resolver(i As Integer, j As Integer)
Dim As Integer f, c, n, temp
If i > 9 Then
'salir con cuadriculaResuelta = cuadricula
For c = 1 To 9
For f = 1 To 9
cuadriculaResuelta(c, f) = cuadricula(c, f)
Next f
Next c
Exit Sub
End If
For n = 1 To 9
If isSafe(i, j, n) Then
temp = cuadricula(i, j)
cuadricula(i, j) = n
If j = 9 Then
Resolver i + 1, 1
Else
Resolver i, j + 1
End If
cuadricula(i, j) = temp
End If
Next n
End Sub
 
Dim As String s(9)
'inicializar la cuadrícula usando 9 cadenas, una por fila
s(1) = "001005070"
s(2) = "920600000"
s(3) = "008000600"
s(4) = "090020401"
s(5) = "000000000"
s(6) = "304080090"
s(7) = "007000300"
s(8) = "000007069"
s(9) = "010800700"
 
Dim As Integer i, j
For i = 1 To 9
For j = 1 To 9
cuadricula(i, j) = Int(Val(Mid(s(i), j, 1)))
Next j
Next i
 
Resolver 1, 1
Print "Solucion:"
Color 12: Print "---------+---------+---------"
For i = 1 To 9
For j = 1 To 9
Color 7: Print cuadriculaResuelta(i, j); " ";
Color 12
If (j Mod 3 = 0) And (j <> 9) Then Color 12: Print "|";
Next j
If (i Mod 3 = 0) Then Print !"\n---------+---------+---------" Else Print
Next i
Sleep</syntaxhighlight>
{{out}}
<pre>
Solucion:
---------+---------+---------
6 3 1 | 2 4 5 | 9 7 8
9 2 5 | 6 7 8 | 1 4 3
4 7 8 | 3 1 9 | 6 5 2
---------+---------+---------
7 9 6 | 5 2 3 | 4 8 1
1 8 2 | 9 6 4 | 5 3 7
3 5 4 | 7 8 1 | 2 9 6
---------+---------+---------
8 6 7 | 4 9 2 | 3 1 5
2 4 3 | 1 5 7 | 8 6 9
5 1 9 | 8 3 6 | 7 2 4
---------+---------+---------
</pre>
 
 
=={{header|FutureBasic}}==
First is a short version:
<syntaxhighlight lang="futurebasic">
include "Util_Containers.incl"
 
begin globals
container gC
end globals
 
BeginCDeclaration
short solve_sudoku(short i);
short check_sudoku(short r, short c);
CFMutableStringRef print_sudoku();
EndC
 
BeginCFunction
short sudoku[9][9] = {
{3,0,0,0,0,1,4,0,9},
{7,0,0,0,0,4,2,0,0},
{0,5,0,2,0,0,0,1,0},
{5,7,0,0,4,3,0,6,0},
{0,9,0,0,0,0,0,3,0},
{0,6,0,7,9,0,0,8,5},
{0,8,0,0,0,5,0,4,0},
{0,0,6,4,0,0,0,0,7},
{9,0,5,6,0,0,0,0,3},
};
short check_sudoku( short r, short c )
{
short i;
short rr, cc;
for (i = 0; i < 9; i++)
{
if (i != c && sudoku[r][i] == sudoku[r][c]) return 0;
if (i != r && sudoku[i][c] == sudoku[r][c]) return 0;
rr = r/3 * 3 + i/3;
cc = c/3 * 3 + i%3;
if ((rr != r || cc != c) && sudoku[rr][cc] == sudoku[r][c]) return 0;
}
return -1;
}
short solve_sudoku( short i )
{
short r, c;
if (i < 0) return 0;
else if (i >= 81) return -1;
r = i / 9;
c = i % 9;
if (sudoku[r][c])
return check_sudoku(r, c) && solve_sudoku(i + 1);
else
for (sudoku[r][c] = 9; sudoku[r][c] > 0; sudoku[r][c]--)
{
if ( solve_sudoku(i) ) return -1;
}
return 0;
}
CFMutableStringRef print_sudoku()
{
short i, j;
CFMutableStringRef mutStr;
mutStr = CFStringCreateMutable( kCFAllocatorDefault, 0 );
for (i = 0; i < 9; i++)
{
for (j = 0; j < 9; j++)
{
CFStringAppendFormat( mutStr, NULL, (CFStringRef)@" %d", sudoku[i][j] );
}
CFStringAppendFormat( mutStr, NULL, (CFStringRef)@"\r" );
}
return( mutStr );
}
EndC
 
toolbox fn solve_sudoku( short i ) = short
toolbox fn check_sudoku( short r, short c ) = short
toolbox fn print_sudoku() = CFMutableStringRef
 
short solution
CFMutableStringRef cfRef
 
gC = " "
cfRef = fn print_sudoku()
fn ContainerCreateWithCFString( cfRef, gC )
print : print "Sudoku challenge:" : print : print gC
 
solution = fn solve_sudoku(0)
 
print : print "Sudoku solved:" : print
if ( solution )
gC = " "
cfRef = fn print_sudoku()
fn ContainerCreateWithCFString( cfRef, gC )
print gC
else
print "No solution found"
end if
 
HandleEvents
</syntaxhighlight>
 
Output:
<pre>
Sudoku challenge:
 
3 0 0 0 0 1 4 0 9
7 0 0 0 0 4 2 0 0
0 5 0 2 0 0 0 1 0
5 7 0 0 4 3 0 6 0
0 9 0 0 0 0 0 3 0
0 6 0 7 9 0 0 8 5
0 8 0 0 0 5 0 4 0
0 0 6 4 0 0 0 0 7
9 0 5 6 0 0 0 0 3
 
 
Sudoku solved:
 
3 2 8 5 6 1 4 7 9
7 1 9 3 8 4 2 5 6
6 5 4 2 7 9 3 1 8
5 7 1 8 4 3 9 6 2
8 9 2 1 5 6 7 3 4
4 6 3 7 9 2 1 8 5
2 8 7 9 3 5 6 4 1
1 3 6 4 2 8 5 9 7
9 4 5 6 1 7 8 2 3
</pre>
 
More code in this one, but faster execution:
<pre>
begin globals
_digits = 9
_setH = 3
_setV = 3
_nSetH = 3
_nSetV = 3
 
begin record Board
Boolean f(_digits,_digits,_digits)
char match(_digits,_digits)
pointer previousBoard // singly-linked list used to discover repetitions
dim &&
end record
 
Board quiz
CFTimeInterval t
end globals
 
 
local mode
local fn CopyBoard( source as ^Board, dest as ^Board )
BlockMoveData( source, dest, sizeof( Board ) )
dest.previousBoard = source // linked list
end fn
 
local fn prepare( b as ^Board )
short i, j, n
for i = 1 to _digits
for j = 1 to _digits
for n = 1 to _digits
b.match[i, j] = 0
b.f[i, j, n] = _true
next n
next j
next i
end fn
 
local fn printBoard( b as ^Board )
short i, j
for i = 1 to _digits
for j = 1 to _digits
Print b.match[i, j];
next j
print
next i
end fn
 
local fn verifica( b as ^Board )
short i, j, n, first, x, y, ii
Boolean check
check = _true
for i = 1 to _digits
for j = 1 to _digits
if ( b.match[i, j] == 0 )
check = _false
for n = 1 to _digits
if ( b.f[i, j, n] != _false )
check = _true
end if
next n
if ( check == _false ) then exit fn
end if
next j
next i
check = _true
for j = 1 to _digits
for n = 1 to _digits
first = 0
for i = 1 to _digits
if ( b.match[i, j] == n )
if ( first == 0 )
first = i
else
check = _false
exit fn
end if
end if
next i
next n
next j
for i = 1 to _digits
for n = 1 to _digits
first = 0
for j = 1 to _digits
if ( b.match[i, j] == n )
if ( first == 0 )
first = j
else
check = _false
exit fn
end if
end if
next j
next n
next i
for x = 0 to ( _nSetH - 1 )
for y = 0 to ( _nSetV - 1 )
first = 0
for ii = 0 to ( _digits - 1 )
i = x * _setH + ii mod _setH + 1
j = y * _setV + ii / _setH + 1
if ( b.match[i, j] == n )
if ( first == 0 )
first = j
else
check = _false
exit fn
end if
end if
next ii
next y
next x
end fn = check
 
 
local fn setCell( b as ^Board, x as short, y as short, n as short) as boolean
short i, j, rx, ry
Boolean check
b.match[x, y] = n
for i = 1 to _digits
b.f[x, i, n] = _false
b.f[i, y, n] = _false
next i
rx = (x - 1) / _setH
ry = (y - 1) / _setV
for i = 1 to _setH
for j = 1 to _setV
b.f[ rx * _setH + i, ry * _setV + j, n ] = _false
next j
next i
check = fn verifica( #b )
if ( check == _false ) then exit fn
end fn = check
 
 
local fn solve( b as ^Board )
short i, j, n, first, x, y, ii, ppi, ppj
Boolean check
check = _true
for i = 1 to _digits
for j = 1 to _digits
if ( b.match[i, j] == 0 )
first = 0
for n = 1 to _digits
if ( b.f[i, j, n] != _false )
if ( first == 0 )
first = n
else
first = -1
exit for
end if
end if
next n
if ( first > 0 )
check = fn setCell( #b, i, j, first )
if ( check == _false ) then exit fn
check = fn solve(#b)
if ( check == _false ) then exit fn
end if
end if
next j
next i
for i = 1 to _digits
for n = 1 to _digits
first = 0
for j = 1 to _digits
if ( b.match[i, j] == n ) then exit for
if ( b.f[i, j, n] != _false ) and ( b.match[i, j] == 0 )
if ( first == 0 )
first = j
else
first = -1
exit for
end if
end if
next j
if ( first > 0 )
check = fn setCell( #b, i, first, n )
if ( check == _false ) then exit fn
check = fn solve(#b)
if ( check == _false ) then exit fn
end if
next n
next i
for j = 1 to _digits
for n = 1 to _digits
first = 0
for i = 1 to _digits
if ( b.match[i, j] == n ) then exit for
if ( b.f[i, j, n] != _false ) and ( b.match[i, j] == 0 )
if ( first == 0 )
first = i
else
first = -1
exit for
end if
end if
next i
if ( first > 0 )
check = fn setCell( #b, first, j, n )
if ( check == _false ) then exit fn
check = fn solve(#b)
if ( check == _false ) then exit fn
end if
next n
next j
for x = 0 to ( _nSetH - 1 )
for y = 0 to ( _nSetV - 1 )
for n = 1 to _digits
first = 0
for ii = 0 to ( _digits - 1 )
i = x * _setH + ii mod _setH + 1
j = y * _setV + ii / _setH + 1
if ( b.match[i, j] == n ) then exit for
if ( b.f[i, j, n] != _false ) and ( b.match[i, j] == 0 )
if ( first == 0 )
first = n
ppi = i
ppj = j
else
first = -1
exit for
end if
end if
next ii
if ( first > 0 )
check = fn setCell( #b, ppi, ppj, n )
if ( check == _false ) then exit fn
check = fn solve(#b)
if ( check == _false ) then exit fn
end if
next n
next y
next x
end fn = check
 
 
local fn resolve( b as ^Board )
Boolean check, daFinire
long i, j, n
Board localBoard
check = fn solve(b)
if ( check == _false )
exit fn
end if
daFinire = _false
for i = 1 to _digits
for j = 1 to _digits
if ( b.match[i, j] == 0 )
daFinire = _true
for n = 1 to _digits
if ( b.f[i, j, n] != _false )
fn CopyBoard( b, @localBoard )
check = fn setCell(@localBoard, i, j, n)
if ( check != _false )
check = fn resolve( @localBoard )
if ( check == -1 )
fn CopyBoard( @localBoard, b )
exit fn
end if
end if
end if
next n
end if
next j
next i
if daFinire
else
check = -1
end if
end fn = check
 
 
fn prepare( @quiz )
 
DATA 0,0,0,0,2,9,0,8,7
DATA 0,9,7,3,0,0,0,0,0
DATA 0,0,2,0,0,0,4,0,9
DATA 0,0,3,9,0,1,0,0,6
DATA 0,4,0,0,0,0,0,9,0
DATA 9,0,0,7,0,3,1,0,0
DATA 0,0,9,0,0,0,6,0,0
DATA 0,0,0,0,0,5,8,2,0
DATA 2,8,0,1,3,0,0,0,0
 
short i, j, d
for i = 1 to _digits
for j = 1 to _digits
read d
fn setCell(@quiz, j, i, d)
next j
next i
 
Print : print "quiz:"
fn printBoard( @quiz )
print : print "-------------------" : print
Boolean check
 
t = fn CACurrentMediaTime
check = fn resolve(@quiz)
t = (fn CACurrentMediaTime - t) * 1000
 
if ( check )
print "solution:"; str$( t ) + " ms"
else
print "No solution found"
end if
fn printBoard( @quiz )
 
HandleEvents
</pre>
 
Output:
<pre>
quiz:
0 0 0 0 0 9 0 0 2
0 9 0 0 4 0 0 0 8
0 7 2 3 0 0 9 0 0
0 3 0 9 0 7 0 0 1
2 0 0 0 0 0 0 0 3
9 0 0 1 0 3 0 5 0
0 0 4 0 0 1 6 8 0
8 0 0 0 9 0 0 2 0
7 0 9 6 0 0 0 0 0
 
-------------------
 
solution: 6.956 ms
3 8 6 5 7 9 4 1 2
1 9 5 2 4 6 3 7 8
4 7 2 3 1 8 9 6 5
6 3 8 9 5 7 2 4 1
2 5 1 8 6 4 7 9 3
9 4 7 1 2 3 8 5 6
5 2 4 7 3 1 6 8 9
8 6 3 4 9 5 1 2 7
7 1 9 6 8 2 5 3 4
</pre>
 
=={{header|Go}}==
Solution using [http://en.wikipedia.org/wiki/Dancing_Links Knuth's DLX.] This code follows his paper fairly closely. Input to function solve is an 81 character string. This seems to be a conventional computer representation for Sudoku puzzles.
This code follows his paper fairly closely.
<lang go>package main
Input to function solve is an 81 character string.
This seems to be a conventional computer representation for Sudoku puzzles.
<syntaxhighlight lang="go">package main
 
import "fmt"
 
// sudoku puzzle representation is an 81 character string
var puzzle =
var puzzle = "" +
"394 267 " +
" 3 4 " +
Line 2,369 ⟶ 5,726:
}
 
// print grid (with title) from 81 character string
func printGrid(title, s string) {
fmt.Println(title)
for r, i := 0, 0; r < 9; r, i = r+1, i+9 {
fmt.Printf("%c %c %c | %c %c %c | %c %c %c\n", s[i], s[i+1], s[i+2],
s[i], s[i+1], s[i+2], s[i+3], s[i+4], s[i+5], s[i+6], s[i+7], s[i+8])
if r == 2 || r == 5 {
fmt.Println("------+-------+------")
}
}
}
 
// solve puzzle in 81 character string format.
// if solved, result is 81 character string.
// if not solved, result is the empty string.
func solve(u string) string {
// construct an dlx object with 324 constraint columns.
// other than the number 324, this is not specific to sudoku.
d := newDlxObject(324)
// now add constraints that define sudoku rules.
for r, i := 0, 0; r < 9; r++ {
for c := 0; c < 9; c, i = c+1, i+1 {
b := r/3*3 + c/3
n := int(u[i] - '01')
if n >= 10 && n <= 9 {
d.newRowaddRow([]int{i + 1, 81 + r*9 + n, 162 + c*9 + n, 243 + b*9 + n})
243 + b*9 + n})
} else {
for n = 10; n <= 9; n++ {
d.newRowaddRow([]int{i + 1, 81 + r*9 + n, 162 + c*9 + n, 243 + b*9 + n})
243 + b*9 + n})
}
}
}
}
// run dlx. not sudoku specific.
h := &d[0]
var o []*xd.search()
// extract the sudoku-specific 81 character result from the dlx solution.
if solution := h.search(o); solution != nil {
return d.text(solution)
}
return ""
}
 
Line 2,407 ⟶ 5,771:
c *y
u, d, l, r *x
// except x0 is not Knuth's. it's pointer to first constraint in row,
// so that the sudoku string can be constructed from the dlx solution.
x0 *x
}
 
Line 2,416 ⟶ 5,783:
}
 
// an object to hold the matrix and solution
// convenient during construction to work with all column headers in a slice.
type sparsedlx []ystruct {
ch []y // all column headers
h *y // ch[0], the root node
o []*x // solution
}
 
// constructor creates the column headers but no rows.
func newDlxObject(nCols int) sparse {
func newDlxObject(nCols int) *dlx {
d := make(sparse, nCols+1)
ch := make([]y, nCols+1)
// d[0] is Knuth's h, the root node. He mentioned h.c was unused,
h := &ch[0]
// but we need it initialized to satisfy Go's strict type checking.
d[0].c := &d[0]dlx{ch, h, nil}
d[0]h.lc = &d[nCols].xh
forh.l i := 1; i <= &ch[nCols; i++ {].x
dch[inCols].nr = i - 1&h.x
nh d[i].c := &dch[i1:]
for i := range dch[i1:].u = &d[i].x{
d[i].dhi := &dnh[i].x
d[i-1].rix := &d[i]hi.x
d[i]hi.ln = &d[i-1].x
hi.c = hi
hi.u = ix
hi.d = ix
hi.l = &h.x
h.r = ix
h = hi
}
d[nCols].r = &d[0].x
return d
}
// rows define constraints
func (d *dlx) addRow(nr []int) {
if len(nr) == 0 {
return
}
r := make([]x, len(nr))
x0 := &r[0]
for x, j := range nr {
ch := &d.ch[j+1]
ch.s++
np := &r[x]
np.c = ch
np.u = ch.u
np.d = &ch.x
np.l = &r[(x+len(r)-1)%len(r)]
np.r = &r[(x+1)%len(r)]
np.u.d, np.d.u, np.l.r, np.r.l = np, np, np, np
np.x0 = x0
}
}
 
// extracts 81 character sudoku string
func (a sparse) newRow(nr []int) {
func (d *dlx) text() string {
var rh x
rh.l, rh.rb := &rhmake([]byte, &rhlen(d.o))
for _, jr := range nrd.o {
a[j]x0 := r.s++x0
np := &x{&ab[jx0.c.n], a[j].u,= &a[j]byte(x0.r.x,c.n%9) rh.l,+ &rh}'1'
a[j].u.d, a[j].u, rh.l.r, rh.l = np, np, np, np
}
return string(b)
rh.l.r, rh.r.l = rh.r, rh.l
}
// the dlx algorithm
func (h *y) search(o []*x) []*x {
func (d *dlx) search() bool {
h := d.h
j := h.r.c
if j == h {
return otrue
}
//c choose:= columnj with min s
c := j
for minS := j.s; ; {
j = j.r.c
Line 2,466 ⟶ 5,863:
 
cover(c)
k := len(d.o)
d.o = append(d.o, nil)
for r := c.d; r != &c.x; r = r.d {
d.o[k] = append(o, r)
for j := r.r; j != r; j = j.r {
cover(j.c)
}
if solution := hd.search(o); solution != nil {
return solutiontrue
}
// Knuth resets r and c at this= pointd.o[k]
c = r.c
// they are actually still set with the correct values, but
// we need to pop the failed row from the partial solution o.
o = o[:len(o)-1]
 
for j := r.l; j != r; j = j.l {
uncover(j.c)
}
}
d.o = d.o[:len(d.o)-1]
uncover(c)
return nilfalse
}
 
Line 2,502 ⟶ 5,899:
j.c.s++
j.d.u, j.u.d = j, j
}
}
c.r.l, c.l.r = &c.x, &c.x
}</syntaxhighlight>
}
{{out}}
 
func text(o []*x) string {
b := make([]byte, 81)
for _, r := range o {
b[r.c.n] = byte(r.r.c.n%9) + '1'
}
return string(b)
}</lang>
Output:
<pre>
puzzle:
Line 2,541 ⟶ 5,930:
8 2 6 | 4 1 9 | 7 3 5
</pre>
 
=={{header|Golfscript}}==
Código sacado de http://www.golfscript.com/
 
Imprime todas las soluciones posibles, sale con un error, pero funciona.
<syntaxhighlight lang="golfscript">
'Solution:'
;'2 8 4 3 7 5 1 6 9
0 0 9 2 0 0 0 0 7
0 0 1 0 0 4 0 0 2
0 5 0 0 0 0 8 0 0
0 0 8 0 0 0 9 0 0
0 0 6 0 0 0 0 4 0
9 0 0 1 0 0 5 0 0
8 0 0 0 0 7 6 0 4
4 2 5 6 8 9 7 3 1'
{9/[n]*puts}:p; #optional formatting
 
~]{:@0?:^~!{@p}*10,@9/^9/=-@^9%>9%-@3/^9%3/>3%3/^27/={+}*-{@^<\+@1^+>+}/1}do
</syntaxhighlight>
 
=={{header|Groovy}}==
Line 2,546 ⟶ 5,955:
 
Non-guessing part is iterative. Guessing part is recursive. Implementation uses exception handling to back out of bad guesses.
<lang groovy>final CELL_VALUES = ('1'..'9')
 
I consider this a "brute force" solution of sorts, in that it is the same method I use when solving Sudokus manually.
<syntaxhighlight lang="groovy">final CELL_VALUES = ('1'..'9')
class GridException extends Exception {
GridException(String message) { super(message) }
}
 
def string2grid = { string ->
assert string.size() == 81
(0..8).collect { i -> (0..8).collect { j -> string[9*i+j] } }
}
 
def gridRow = { grid, slot -> grid[slot.i] as Set }
 
def gridCol = { grid, slot -> grid.collect { it[slot.j] } as Set }
 
def gridBox = { grid, slot ->
def t, l; (t, l) = [slot.i.intdiv(3)*3, slot.j.intdiv(3)*3]
(0..2).collect { row -> (0..2).collect { col -> grid[t+row][l+col] } }.flatten() as Set
}
 
def slotList = { grid ->
def slots = (0..8).collect { i -> (0..8).findAll { j -> ! (grid[i][j] in== CELL_VALUES)'.' } \
.collect {j -> [i: i, j: j] } }.flatten()
}
 
def assignCandidates = { grid, slots = slotList(grid) ->
slots.each { slot ->
Line 2,582 ⟶ 5,993:
slots
}
 
def isSolved = { grid -> ! (grid.flatten().find { !(it in== CELL_VALUES)'.' }) }
 
def solve
solve = { grid ->
Line 2,613 ⟶ 6,024:
}
grid
}</langsyntaxhighlight>
'''Test/Benchmark Cases'''
 
Mentions of ''"exceptionally difficult" example in Wikipedia'' refer to this (former) page: [[wphttps:Sudoku algorithms//en.wikipedia.org/w/index.php?title=Sudoku_solving_algorithms&oldid=410240496#ExceptionallyExceptionally_difficult_Sudokus_.28hardest_Sudokus.29 difficult Sudokus (hardest Sudokus)|Exceptionally difficult Sudokus]]
<langsyntaxhighlight lang="groovy">def sudokus = [
//Used in manyCurry solution: other solutions, notably Ada: ~ 0.21 seconds
'819..5.....2...75..371.4.6.4..59.1..7..3.8..2..3.62..7.5.7.921..64...9.....2..438',
//Used in Perl and PicoLisp solutions: ~ 0.1 seconds
'53..247....2...8..1..7.39.2..8.72.49.2.98..7.79.....8.....3.5.696..1.3...5.69..1.',
//Used in Fortran solution: ~ 0.1 seconds
'..3.2.6..9..3.5..1..18.64....81.29..7.......8..67.82....26.95..8..2.3..9..5.1.3..',
//Used in many other solutions, notably Algol 68: ~ 0.1 seconds
'394..267....3..4..5..69..2..45...9..6.......7..7...58..1..67..8..9..8....264..735',
 
//Used in OzC# solution: ~ 0.62 seconds
'97.3...6..6.75.........8.5.......67.....3.....539..2..7...25.....2.1...8.4...73..',
//Used in Oz solution: ~ 0.2 seconds
'4......6.5...8.9..3....1....2.7....1.9.....4.8....3.5....2....7..6.5...8.1......6',
 
//3rdUsed "exceptionallyin difficult"many exampleother insolutions, Wikipedianotably C++: ~ 60.53 seconds
'85...24..72......9..4.........1.7..23.5...9...4...........8..7..17..........36.4.',
//Used in VBA solution: ~ 0.3 seconds
'..1..5.7.92.6.......8...6...9..2.4.1.........3.4.8..9...7...3.......7.69.1.8..7..',
//Used in Forth solution: ~ 0.8 seconds
'.9...4..7.....79..8........4.58.....3.......2.....97.6........4..35.....2..6...8.',
//3rd "exceptionally difficult" example in Wikipedia: ~ 2.3 seconds
'12.3....435....1....4........54..2..6...7.........8.9...31..5.......9.7.....6...8',
 
//"ALUsed in Curry solution: Escargot", so-called "hardest sudoku" (HA!): ~ 82.4 seconds
'9..2..5...4..6..3...3.....6...9..2......5..8...7..4..37.....1...5..2..4...1..6..9',
//"AL Escargot", so-called "hardest sudoku" (HA!): ~ 3.0 seconds
'1....7.9..3..2...8..96..5....53..9...1..8...26....4...3......1..4......7..7...3..',
 
//1st "exceptionally difficult" example in Wikipedia: ~17 6.85 seconds
'12.4..3..3...1..5...6...1..7...9.....4.6.3.....3..2...5...8.7....7.....5.......98',
 
//2ndUsed "exceptionallyin difficult"Bracmat exampleand inScala Wikipediasolutions: ~24 ~ 6.7 seconds
'..............3.85..1.2.......5.7.....4...1...9.......5......73..2.1........4...9',
//2nd "exceptionally difficult" example in Wikipedia: ~ 8.8 seconds
'.......39.....1..5..3.5.8....8.9...6.7...2...1..4.......9.8..5..2....6..4..7.....',
 
//Used in MATLAB solution: ~4015 seconds
'....839..1......3...4....7..42.3....6.......4....7..1..2........8...92.....25...6',
 
//4th "exceptionally difficult" example in Wikipedia: ~8029 seconds
'..3......4...8..36..8...1...4..6..73...9..........2..5..4.7..686........7..6..5..']
 
sudokus.each { sudoku ->
def grid = string2grid(sudoku)
println '\nPUZZLE'
grid.each { println it }
println '\nSOLUTION'
def start = System.currentTimeMillis()
Line 2,653 ⟶ 6,091:
solution.each { println it }
println "\nELAPSED: ${elapsed} seconds"
}</langsyntaxhighlight>
 
Output{{out}} (last only):
<pre>PUZZLE
[., ., 3, ., ., ., ., ., .]
Line 2,678 ⟶ 6,116:
[7, 8, 2, 6, 9, 3, 5, 4, 1]
 
ELAPSED: 7628.518978 seconds</pre>
 
=={{header|Haskell}}==
Line 2,687 ⟶ 6,125:
 
=={{header|Java}}==
<langsyntaxhighlight lang="java">public class Sudoku
{
private int mBoard[][];
Line 2,695 ⟶ 6,133:
private boolean mColSubset[][];
private boolean mBoxSubset[][];
 
public Sudoku(int board[][]) {
mBoard = board;
mBoardSize = mBoard.length;
mBoxSize = (int)Math.sqrt(mBoardSize);
initSubsets();
}
 
public void initSubsets() {
mRowSubset = new boolean[mBoardSize][mBoardSize];
Line 2,709 ⟶ 6,148:
for(int j = 0; j < mBoard.length; j++) {
int value = mBoard[i][j];
if(value != 0) {
setSubsetValue(i, j, value, true);
}
}
}
}
 
private void setSubsetValue(int i, int j, int value, boolean present) {
mRowSubset[i][value - 1] = present;
Line 2,720 ⟶ 6,160:
mBoxSubset[computeBoxNo(i, j)][value - 1] = present;
}
 
public boolean solve() {
return solve(0, 0);
}
 
public boolean solve(int i, int j) {
if(i == mBoardSize) {
i = 0;
if(++j == mBoardSize) {
return true;
}
}
if(mBoard[i][j] != 0) {
return solve(i + 1, j);
}
for(int value = 1; value <= mBoardSize; value++)
for(int value = 1; value <= mBoardSize; value++) {
if(isValid(i, j, value)) {
mBoard[i][j] = value;
setSubsetValue(i, j, value, true);
if(solve(i + 1, j)) {
return true;
}
setSubsetValue(i, j, value, false);
}
}
 
mBoard[i][j] = 0;
return false;
}
 
private boolean isValid(int i, int j, int val) {
val--;
Line 2,751 ⟶ 6,195:
return !isPresent;
}
 
private int computeBoxNo(int i, int j) {
int boxRow = i / mBoxSize;
Line 2,757 ⟶ 6,201:
return boxRow * mBoxSize + boxCol;
}
 
public void print() {
for(int i = 0; i < mBoardSize; i++) {
if(i % mBoxSize == 0) {
System.out.println(" -----------------------");
}
for(int j = 0; j < mBoardSize; j++) {
if(j % mBoxSize == 0) {
System.out.print("| ");
}
System.out.print(mBoard[i][j] != 0 ? ((Object) (Integer.valueOf(mBoard[i][j]))) : " ");
System.out.print(mBoard[i][j] != 0 ? ((Object) (Integer.valueOf(mBoard[i][j]))) : "-");
System.out.print(' ');
}
 
System.out.println("|");
}
 
System.out.println(" -----------------------");
}
 
}</lang>
public static void main(String[] args) {
int[][] board = {
{8, 5, 0, 0, 0, 2, 4, 0, 0},
{7, 2, 0, 0, 0, 0, 0, 0, 9},
{0, 0, 4, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 1, 0, 7, 0, 0, 2},
{3, 0, 5, 0, 0, 0, 9, 0, 0},
{0, 4, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 8, 0, 0, 7, 0},
{0, 1, 7, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 3, 6, 0, 4, 0}
};
Sudoku s = new Sudoku(board);
System.out.print("Starting grid:\n");
s.print();
if (s.solve()) {
System.out.print("\nSolution:\n");
s.print();
} else {
System.out.println("\nUnsolvable!");
}
}
}</syntaxhighlight>
 
{{out}}
<pre>
Starting grid:
-----------------------
| 8 5 - | - - 2 | 4 - - |
| 7 2 - | - - - | - - 9 |
| - - 4 | - - - | - - - |
-----------------------
| - - - | 1 - 7 | - - 2 |
| 3 - 5 | - - - | 9 - - |
| - 4 - | - - - | - - - |
-----------------------
| - - - | - 8 - | - 7 - |
| - 1 7 | - - - | - - - |
| - - - | - 3 6 | - 4 - |
-----------------------
 
Solution:
-----------------------
| 8 5 9 | 6 1 2 | 4 3 7 |
| 7 2 3 | 8 5 4 | 1 6 9 |
| 1 6 4 | 3 7 9 | 5 2 8 |
-----------------------
| 9 8 6 | 1 4 7 | 3 5 2 |
| 3 7 5 | 2 6 8 | 9 1 4 |
| 2 4 1 | 5 9 3 | 7 8 6 |
-----------------------
| 4 3 2 | 9 8 1 | 6 7 5 |
| 6 1 7 | 4 2 5 | 8 9 3 |
| 5 9 8 | 7 3 6 | 2 4 1 |
-----------------------
</pre>
 
=={{header|JavaScript}}==
 
====ES6====
 
<syntaxhighlight lang="javascript">//-------------------------------------------[ Dancing Links and Algorithm X ]--
/**
* The doubly-doubly circularly linked data object.
* Data object X
*/
class DoX {
/**
* @param {string} V
* @param {!DoX=} H
*/
constructor(V, H) {
this.V = V;
this.L = this;
this.R = this;
this.U = this;
this.D = this;
this.S = 1;
this.H = H || this;
H && (H.S += 1);
}
}
 
/**
* Helper function to help build a horizontal doubly linked list.
* @param {!DoX} e An existing node in the list.
* @param {!DoX} n A new node to add to the right of the existing node.
* @return {!DoX}
*/
const addRight = (e, n) => {
n.R = e.R;
n.L = e;
e.R.L = n;
return e.R = n;
};
 
/**
* Helper function to help build a vertical doubly linked list.
* @param {!DoX} e An existing node in the list.
* @param {!DoX} n A new node to add below the existing node.
*/
const addBelow = (e, n) => {
n.D = e.D;
n.U = e;
e.D.U = n;
return e.D = n;
};
 
/**
* Verbatim copy of DK's search algorithm. The meat of the DLX algorithm.
* @param {!DoX} h The root node.
* @param {!Array<!DoX>} s The solution array.
*/
const search = function(h, s) {
if (h.R == h) {
printSol(s);
} else {
let c = chooseColumn(h);
cover(c);
for (let r = c.D; r != c; r = r.D) {
s.push(r);
for (let j = r.R; r !=j; j = j.R) {
cover(j.H);
}
search(h, s);
r = s.pop();
for (let j = r.R; j != r; j = j.R) {
uncover(j.H);
}
}
uncover(c);
}
};
 
/**
* Verbatim copy of DK's algorithm for choosing the next column object.
* @param {!DoX} h
* @return {!DoX}
*/
const chooseColumn = h => {
let s = Number.POSITIVE_INFINITY;
let c = h;
for(let j = h.R; j != h; j = j.R) {
if (j.S < s) {
c = j;
s = j.S;
}
}
return c;
};
 
 
/**
* Verbatim copy of DK's cover algorithm
* @param {!DoX} c
*/
const cover = c => {
c.L.R = c.R;
c.R.L = c.L;
for (let i = c.D; i != c; i = i.D) {
for (let j = i.R; j != i; j = j.R) {
j.U.D = j.D;
j.D.U = j.U;
j.H.S = j.H.S - 1;
}
}
};
 
/**
* Verbatim copy of DK's cover algorithm
* @param {!DoX} c
*/
const uncover = c => {
for (let i = c.U; i != c; i = i.U) {
for (let j = i.L; i != j; j = j.L) {
j.H.S = j.H.S + 1;
j.U.D = j;
j.D.U = j;
}
}
c.L.R = c;
c.R.L = c;
};
 
//-----------------------------------------------------------[ Print Helpers ]--
/**
* Given the standard string format of a grid, print a formatted view of it.
* @param {!string|!Array} a
*/
const printGrid = function(a) {
 
const getChar = c => {
let r = Number(c);
if (isNaN(r)) { return c }
 
let o = 48;
if (r > 9 && r < 36) { o = 55 }
if (r >= 36) { o = 61 }
return String.fromCharCode(r + o)
};
 
a = 'string' == typeof a ? a.split('') : a;
 
let U = Math.sqrt(a.length);
let N = Math.sqrt(U);
let line = new Array(N).fill('+').reduce((p, c) => {
p.push(... Array.from(new Array(1 + N*2).fill('-')));
p.push(c);
return p;
}, ['\n+']).join('') + '\n';
 
a = a.reduce(function(p, c, i) {
let d = i && !(i % U), G = i && !(i % N);
i = !(i % (U * N));
d && !i && (p += '|\n| ');
d && i && (p += '|');
i && (p = '' + p + line + '| ');
return '' + p + (G && !d ? '| ' : '') + getChar(c) + ' ';
}, '') + '|' + line;
console.log(a);
 
};
 
/**
* Given a search solution, print the resultant grid.
* @param {!Array<!DoX>} a An array of data objects
*/
const printSol = a => {
printGrid(a.reduce((p, c) => {
let [i, v] = c.V.split(':');
p[i * 1] = v;
return p;
}, new Array(a.length).fill('.')));
};
 
//----------------------------------------------[ Grid to Exact cover Matrix ]--
/**
* Helper to get some meta about the grid.
* @param {!string} s The standard string representation of a grid.
* @return {!Array}
*/
const gridMeta = s => {
const g = s.split('');
const cellCount = g.length;
const tokenCount = Math.sqrt(cellCount);
const N = Math.sqrt(tokenCount);
const g2D = g.map(e => isNaN(e * 1) ?
new Array(tokenCount).fill(1).map((_, i) => i + 1) :
[e * 1]);
return [cellCount, N, tokenCount, g2D];
};
 
/**
* Given a cell grid index, return the row, column and box indexes.
* @param {!number} n The n-value of the grid. 3 for a 9x9 sudoku.
* @return {!function(!number): !Array<!number>}
*/
const indexesN = n => i => {
let c = Math.floor(i / (n * n));
i %= n * n;
return [c, i, Math.floor(c / n) * n + Math.floor(i / n)];
};
 
/**
* Given a puzzle string, reduce it to an exact-cover matrix and use
* Donald Knuth's DLX algorithm to solve it.
* @param puzString
*/
const reduceGrid = puzString => {
 
printGrid(puzString);
const [
numCells, // The total number of cells in a grid (81 for a 9x9 grid)
N, // the 'n' value of the grid. (3 for a 9x9 grid)
U, // The total number of unique tokens to be placed.
g2D // A 2D array representation of the grid, with each element
// being an array of candidates for a cell. Known cells are
// single element arrays.
] = gridMeta(puzString);
 
const getIndex = indexesN(N);
 
/**
* The DLX Header row.
* Its length is 4 times the grid's size. This is to be able to encode
* each of the 4 Sudoku constrains, onto each of the cells of the grid.
* The array is initialised with unlinked DoX nodes, but in the next step
* those nodes are all linked.
* @type {!Array.<!DoX>}
*/
const headRow = new Array(4 * numCells)
.fill('')
.map((_, i) => new DoX(`H${i}`));
 
/**
* The header row root object. This is circularly linked to be to the left
* of the first header object in the header row array.
* It is used as the entry point into the DLX algorithm.
* @type {!DoX}
*/
let H = new DoX('ROOT');
headRow.reduce((p, c) => addRight(p, c), H);
 
/**
* Transposed the sudoku puzzle into a exact cover matrix, so it can be passed
* to the DLX algorithm to solve.
*/
for (let i = 0; i < numCells; i++) {
const [ri, ci, bi] = getIndex(i);
g2D[i].forEach(num => {
let id = `${i}:${num}`;
let candIdx = num - 1;
 
// The 4 columns that we will populate.
const A = headRow[i];
const B = headRow[numCells + candIdx + (ri * U)];
const C = headRow[(numCells * 2) + candIdx + (ci * U)];
const D = headRow[(numCells * 3) + candIdx + (bi * U)];
 
// The Row-Column Constraint
let rcc = addBelow(A.U, new DoX(id, A));
 
// The Row-Number Constraint
let rnc = addBelow(B.U, addRight(rcc, new DoX(id, B)));
 
// The Column-Number Constraint
let cnc = addBelow(C.U, addRight(rnc, new DoX(id, C)));
 
// The Block-Number Constraint
addBelow(D.U, addRight(cnc, new DoX(id, D)));
});
}
search(H, []);
};
</syntaxhighlight>
 
<syntaxhighlight lang="javascript">[
'819..5.....2...75..371.4.6.4..59.1..7..3.8..2..3.62..7.5.7.921..64...9.....2..438',
'53..247....2...8..1..7.39.2..8.72.49.2.98..7.79.....8.....3.5.696..1.3...5.69..1.',
'..3.2.6..9..3.5..1..18.64....81.29..7.......8..67.82....26.95..8..2.3..9..5.1.3..',
'394..267....3..4..5..69..2..45...9..6.......7..7...58..1..67..8..9..8....264..735',
'97.3...6..6.75.........8.5.......67.....3.....539..2..7...25.....2.1...8.4...73..',
'4......6.5...8.9..3....1....2.7....1.9.....4.8....3.5....2....7..6.5...8.1......6',
'85...24..72......9..4.........1.7..23.5...9...4...........8..7..17..........36.4.',
'..1..5.7.92.6.......8...6...9..2.4.1.........3.4.8..9...7...3.......7.69.1.8..7..',
'.9...4..7.....79..8........4.58.....3.......2.....97.6........4..35.....2..6...8.',
'12.3....435....1....4........54..2..6...7.........8.9...31..5.......9.7.....6...8',
'9..2..5...4..6..3...3.....6...9..2......5..8...7..4..37.....1...5..2..4...1..6..9',
'1....7.9..3..2...8..96..5....53..9...1..8...26....4...3......1..4......7..7...3..',
'12.4..3..3...1..5...6...1..7...9.....4.6.3.....3..2...5...8.7....7.....5.......98',
'..............3.85..1.2.......5.7.....4...1...9.......5......73..2.1........4...9',
'.......39.....1..5..3.5.8....8.9...6.7...2...1..4.......9.8..5..2....6..4..7.....',
'....839..1......3...4....7..42.3....6.......4....7..1..2........8...92.....25...6',
'..3......4...8..36..8...1...4..6..73...9..........2..5..4.7..686........7..6..5..'
].forEach(reduceGrid);
 
// Or of you want to create all the grids of a particular n-size.
// I run out of stack space at n = 9
let n = 2;
let s = new Array(Math.pow(n, 4)).fill('.').join('');
reduceGrid(s);
</syntaxhighlight>
 
<pre>+-------+-------+-------+
| . . 3 | . . . | . . . |
| 4 . . | . 8 . | . 3 6 |
| . . 8 | . . . | 1 . . |
+-------+-------+-------+
| . 4 . | . 6 . | . 7 3 |
| . . . | 9 . . | . . . |
| . . . | . . 2 | . . 5 |
+-------+-------+-------+
| . . 4 | . 7 . | . 6 8 |
| 6 . . | . . . | . . . |
| 7 . . | 6 . . | 5 . . |
+-------+-------+-------+
 
+-------+-------+-------+
| 1 2 3 | 4 5 6 | 7 8 9 |
| 4 5 7 | 1 8 9 | 2 3 6 |
| 9 6 8 | 3 2 7 | 1 5 4 |
+-------+-------+-------+
| 2 4 9 | 5 6 1 | 8 7 3 |
| 5 7 6 | 9 3 8 | 4 1 2 |
| 8 3 1 | 7 4 2 | 6 9 5 |
+-------+-------+-------+
| 3 1 4 | 2 7 5 | 9 6 8 |
| 6 9 5 | 8 1 4 | 3 2 7 |
| 7 8 2 | 6 9 3 | 5 4 1 |
+-------+-------+-------+
</pre>
 
=={{header|jq}}==
{{works with|jq}}
'''Also works with gojq, the Go implementation of jq'''
 
'''Also works with fq, a Go implementation of a large subset of jq'''
 
The two solutions presented here take advantage of jq's built-in backtracking
mechanism.
 
The first solution uses a naive backtracking algorithm which can readily be modified to include more sophisticated
strategies.
 
The second solution modifies `next_row` to use a simple greedy algorithm,
namely, "select the row with the fewest gaps".
 
For the `tarx0134` problem (taken from the
[https://en.wikipedia.org/w/index.php?title=Sudoku_solving_algorithms#Exceptionally_difficult_Sudokus_.28hardest_Sudokus.29 Wikipedia collection] but googleable by that name),
the running time (u+s) is reduced from 264s to 180s on my 3GHz machine.
The memory usage statistics as produced by `/usr/bin/time -lp`
are also shown in the output section below.
<syntaxhighlight lang=jq>
## Utility Functions
def div($b): (. - (. % $b)) / $b;
 
def count(s): reduce s as $_ (0; .+1);
 
def row($i): .[$i];
 
def col($j): transpose | row($j);
 
# pretty print
def pp: .[:3][],"", .[3:6][], "", .[6:][];
 
# Input: 9 x 9 matrix
# Output: linear array corresponding to the specified 3x3 block using IO=0:
# 0,0 0,1 0,2
# 1,0 1,1 1,2
# 2,0 2,1 2,2
def block($i;$j):
def x: range(0;3) + 3*$i;
def y: range(0;3) + 3*$j;
[.[x][y]];
 
# Output: linear block containing .[$i][$j]
def blockOf($i;$j):
block($i|div(3); $j|div(3));
 
# Input: the entire Sudoku matrix
# Output: the update matrix after solving for row $i
def solveRow($i):
def s:
(.[$i] | index(0)) as $j
| if $j
then ((( [range(1;10)] - row($i)) - col($j)) - blockOf($i;$j) ) as $candidates
| if $candidates|length == 0 then empty
else $candidates[] as $x
| .[$i][$j] = $x
| s
end
else .
end;
s;
 
def distinct: map(select(. != 0)) | length - (unique|length) == 0;
 
# Is the Sudoku valid?
def valid:
. as $in
| length as $l
| all(.[]; distinct) and
all( range(0;9); . as $i | $in | col($i) | distinct ) and
all( range(0;3); . as $i | all(range(0;3); . as $j
| $in | block($i;$j) | distinct ));
 
# input: the full puzzle in its current state
# output: null if there is no candidate next row
def next_row:
first( range(0; length) as $i | select(row($i)|index(0)) | $i) // null;
 
def solve(problem):
def s:
next_row as $ix
| if $ix then solveRow($ix) | s
else .
end;
if problem|valid then first(problem|s) | pp
else "The Sukoku puzzle is invalid."
end;
 
# Rating Program: dukuso's suexratt
# Rating: 3311
# Poster: tarek
# Label: tarx0134
# ........8..3...4...9..2..6.....79.......612...6.5.2.7...8...5...1.....2.4.5.....3
def tarx0134:
[[0,0,0,0,0,0,0,0,8],
[0,0,3,0,0,0,4,0,0],
[0,9,0,0,2,0,0,6,0],
[0,0,0,0,7,9,0,0,0],
[0,0,0,0,6,1,2,0,0],
[0,6,0,5,0,2,0,7,0],
[0,0,8,0,0,0,5,0,0],
[0,1,0,0,0,0,0,2,0],
[4,0,5,0,0,0,0,0,3]];
 
# An invalid puzzle, for checking `valid`:
def unsolvable:
[[3,9,4,3,0,2,6,7,0],
[0,0,0,3,0,0,4,0,0],
[5,0,0,6,9,0,0,2,0],
[0,4,5,0,0,0,9,0,0],
[6,0,0,0,0,0,0,0,7],
[0,0,7,0,0,0,5,8,0],
[0,1,0,0,6,7,0,0,8],
[0,0,9,0,0,8,0,0,0],
[0,2,6,4,0,0,7,3,5]] ;
 
solve(tarx0134)
</syntaxhighlight>
 
====Greedy Algorithm====
Replace `def next_row:` with the following definition:
<syntaxhighlight lang=jq>
# select a row with the fewest number of unknowns
def next_row:
length as $len
| . as $in
| reduce range(0;length) as $i ([];
. + [ [ count( $in[$i][] | select(. != 0)), $i] ] )
| map(select(.[0] != $len))
| if length == 0 then null
else max_by(.[0]) | .[1]
end ;
</syntaxhighlight>
 
{{output}}
For the naive next_row:
<pre>
[6,2,1,9,4,3,7,5,8]
[7,8,3,6,1,5,4,9,2]
[5,9,4,7,2,8,3,6,1]
 
[1,4,2,8,7,9,6,3,5]
[3,5,7,4,6,1,2,8,9]
[8,6,9,5,3,2,1,7,4]
 
[2,3,8,1,9,7,5,4,6]
[9,1,6,3,5,4,8,2,7]
[4,7,5,2,8,6,9,1,3]
 
# Summary performance statistics:
user 260.89
sys 3.32
2240512 maximum resident set size
1302528 peak memory footprint
</pre>
 
For the greedy next_row algorithm, jq produces the same solution
with the following performance statistics:
<pre>
user 177.94
sys 2.12
2224128 maximum resident set size
1277952 peak memory footprint
</pre>
gojq stats for the greedy algorithm:
<pre>
user 62.19
sys 7.44
7458418688 maximum resident set size
7683284992 peak memory footprint
</pre>
 
fq stats for the greedy algorithm:
<pre>
user 73.56
sys 5.34
6084091904 maximum resident set size
6436892672 peak memory footprint
</pre>
 
=={{header|Julia}}==
<syntaxhighlight lang="julia">function check(i, j)
id, im = div(i, 9), mod(i, 9)
jd, jm = div(j, 9), mod(j, 9)
 
jd == id && return true
jm == im && return true
 
div(id, 3) == div(jd, 3) &&
div(jm, 3) == div(im, 3)
end
 
const lookup = zeros(Bool, 81, 81)
 
for i in 1:81
for j in 1:81
lookup[i,j] = check(i-1, j-1)
end
end
 
function solve_sudoku(callback::Function, grid::Array{Int64})
(function solve()
for i in 1:81
if grid[i] == 0
t = Dict{Int64, Nothing}()
 
for j in 1:81
if lookup[i,j]
t[grid[j]] = nothing
end
end
 
for k in 1:9
if !haskey(t, k)
grid[i] = k
solve()
end
end
 
grid[i] = 0
return
end
end
 
callback(grid)
end)()
end
 
function display(grid)
for i in 1:length(grid)
print(grid[i], " ")
i % 3 == 0 && print(" ")
i % 9 == 0 && print("\n")
i % 27 == 0 && print("\n")
end
end
 
grid = Int64[5, 3, 0, 0, 2, 4, 7, 0, 0,
0, 0, 2, 0, 0, 0, 8, 0, 0,
1, 0, 0, 7, 0, 3, 9, 0, 2,
0, 0, 8, 0, 7, 2, 0, 4, 9,
0, 2, 0, 9, 8, 0, 0, 7, 0,
7, 9, 0, 0, 0, 0, 0, 8, 0,
0, 0, 0, 0, 3, 0, 5, 0, 6,
9, 6, 0, 0, 1, 0, 3, 0, 0,
0, 5, 0, 6, 9, 0, 0, 1, 0]
 
solve_sudoku(display, grid)</syntaxhighlight>
{{out}}
<pre>
5 3 9 8 2 4 7 6 1
6 7 2 1 5 9 8 3 4
1 8 4 7 6 3 9 5 2
 
3 1 8 5 7 2 6 4 9
4 2 5 9 8 6 1 7 3
7 9 6 3 4 1 2 8 5
 
8 4 1 2 3 7 5 9 6
9 6 7 4 1 5 3 2 8
2 5 3 6 9 8 4 1 7
</pre>
 
=={{header|Kotlin}}==
{{trans|C++}}
<syntaxhighlight lang="scala">// version 1.2.10
 
class Sudoku(rows: List<String>) {
private val grid = IntArray(81)
private var solved = false
 
init {
require(rows.size == 9 && rows.all { it.length == 9 }) {
"Grid must be 9 x 9"
}
for (i in 0..8) {
for (j in 0..8 ) grid[9 * i + j] = rows[i][j] - '0'
}
}
 
fun solve() {
println("Starting grid:\n\n$this")
placeNumber(0)
println(if (solved) "Solution:\n\n$this" else "Unsolvable!")
}
 
private fun placeNumber(pos: Int) {
if (solved) return
if (pos == 81) {
solved = true
return
}
if (grid[pos] > 0) {
placeNumber(pos + 1)
return
}
for (n in 1..9) {
if (checkValidity(n, pos % 9, pos / 9)) {
grid[pos] = n
placeNumber(pos + 1)
if (solved) return
grid[pos] = 0
}
}
}
 
private fun checkValidity(v: Int, x: Int, y: Int): Boolean {
for (i in 0..8) {
if (grid[y * 9 + i] == v || grid[i * 9 + x] == v) return false
}
val startX = (x / 3) * 3
val startY = (y / 3) * 3
for (i in startY until startY + 3) {
for (j in startX until startX + 3) {
if (grid[i * 9 + j] == v) return false
}
}
return true
}
 
override fun toString(): String {
val sb = StringBuilder()
for (i in 0..8) {
for (j in 0..8) {
sb.append(grid[i * 9 + j])
sb.append(" ")
if (j == 2 || j == 5) sb.append("| ")
}
sb.append("\n")
if (i == 2 || i == 5) sb.append("------+-------+------\n")
}
return sb.toString()
}
}
 
fun main(args: Array<String>) {
val rows = listOf(
"850002400",
"720000009",
"004000000",
"000107002",
"305000900",
"040000000",
"000080070",
"017000000",
"000036040"
)
Sudoku(rows).solve()
}</syntaxhighlight>
 
{{out}}
<pre>
Starting grid:
 
8 5 0 | 0 0 2 | 4 0 0
7 2 0 | 0 0 0 | 0 0 9
0 0 4 | 0 0 0 | 0 0 0
------+-------+------
0 0 0 | 1 0 7 | 0 0 2
3 0 5 | 0 0 0 | 9 0 0
0 4 0 | 0 0 0 | 0 0 0
------+-------+------
0 0 0 | 0 8 0 | 0 7 0
0 1 7 | 0 0 0 | 0 0 0
0 0 0 | 0 3 6 | 0 4 0
 
Solution:
 
8 5 9 | 6 1 2 | 4 3 7
7 2 3 | 8 5 4 | 1 6 9
1 6 4 | 3 7 9 | 5 2 8
------+-------+------
9 8 6 | 1 4 7 | 3 5 2
3 7 5 | 2 6 8 | 9 1 4
2 4 1 | 5 9 3 | 7 8 6
------+-------+------
4 3 2 | 9 8 1 | 6 7 5
6 1 7 | 4 2 5 | 8 9 3
5 9 8 | 7 3 6 | 2 4 1
</pre>
 
=={{header|Lua}}==
===without FFI, slow===
<syntaxhighlight lang="lua">--9x9 sudoku solver in lua
--based on a branch and bound solution
--fields are not tried in plain order
--but in a way to detect dead ends earlier
concat=table.concat
insert=table.insert
constraints = { } --contains a table with 3 constraints for every field
-- a contraint "cons" is a table containing all fields which must not have the same value
-- a field "f" is an integer from 1 to 81
columns = { } --contains all column-constraints variable "c"
rows = { } --contains all row-constraints variable "r"
blocks = { } --contains all block-constraints variable "b"
 
--initialize all constraints
for f = 1, 81 do
constraints[f] = { }
end
all_constraints = { } --union of colums, rows and blocks
for i = 1, 9 do
columns[i] = {
unknown = 9, --number of fields not yet solved
unknowns = { } --fields not yet solved
}
insert(all_constraints, columns[i])
rows[i] = {
unknown = 9, -- see l.15
unknowns = { } -- see l.16
}
insert(all_constraints, rows[i])
blocks[i] = {
unknown = 9, --see l.15
unknowns = { } --see l.16
}
insert(all_constraints, blocks[i])
end
constraints_by_unknown = { } --contraints sorted by their number of unknown fields
for i = 0, 9 do
constraints_by_unknown[i] = {
count = 0 --how many contraints are in here
}
end
for r = 1, 9 do
for c = 1, 9 do
local f = (r - 1) * 9 + c
insert(rows[r], f)
insert(constraints[f], rows[r])
insert(columns[c], f)
insert(constraints[f], columns[c])
end
end
for i = 1, 3 do
for j = 1, 3 do
local r = (i - 1) * 3 + j
for k = 1, 3 do
for l = 1, 3 do
local c = (k - 1) * 3 + l
local f = (r - 1) * 9 + c
local b = (i - 1) * 3 + k
insert(blocks[b], f)
insert(constraints[f], blocks[b])
end
end
end
end
working = { } --save the read values in here
function read() --read the values from stdin
local f = 1
local l = io.read("*a")
for d in l:gmatch("(%d)") do
local n = tonumber(d)
if n > 0 then
working[f] = n
for _,cons in pairs(constraints[f]) do
cons.unknown = cons.unknown - 1
end
else
for _,cons in pairs(constraints[f]) do
cons.unknowns[f] = f
end
end
f = f + 1
end
assert((f == 82), "Wrong number of digits")
end
read()
function printer(t) --helper function for printing a 1-81 table
local pattern = {1,2,3,false,4,5,6,false,7,8,9} --place seperators for better readability
for _,r in pairs(pattern) do
if r then
local function p(c)
return c and t[(r - 1) * 9 + c] or "|"
end
local line={}
for k,v in pairs(pattern) do
line[k]=p(v)
end
print(concat(line))
else
print("---+---+---")
end
end
end
order = { } --when to try a field
for _,cons in pairs(all_constraints) do --put all constraints in the corresponding constraints_by_unknown set
local level = constraints_by_unknown[cons.unknown]
level[cons] = cons
level.count = level.count + 1
end
function first(t) --helper function to get a value from a set
for k, v in pairs(t) do
if k == v then
return k
end
end
end
function establish_order() -- determine the sequence in which the fields are to be tried
local solved = constraints_by_unknown[0].count
while solved < 27 do --there 27 constraints
--contraints with no unknown fields are considered "solved"
--keep in mind the actual solving happens in function branch
local i = 1
while constraints_by_unknown[i].count == 0 do
i = i + 1
-- find a unsolved contraint with the least number of unsolved fields
end
local cons = first(constraints_by_unknown[i])
local f = first(cons.unknowns)
-- take one of its unknown fields and append it to "order"
insert(order, f)
for _,c in pairs(constraints[f]) do
--each constraint "c" of "f" is moved up one "level"
--delete "f" from the constraints unknown fields
--decrease unknown of "c"
c.unknowns[f] = nil
local level = constraints_by_unknown[c.unknown]
level[c] = nil
level.count = level.count - 1
c.unknown = c.unknown - 1
level = constraints_by_unknown[c.unknown]
level[c] = c
level.count = level.count + 1
constraints_by_unknown[c.unknown][c] = c
end
solved = constraints_by_unknown[0].count
end
end
establish_order()
max = #order --how many fields are to be solved
function bound(f,i)
for _,c in pairs(constraints[f]) do
for _,x in pairs(c) do
if i == working[x] then
return false --i is already used in fs column/row/block
end
end
end
return true
end
function branch(n)
local f = order[n] --recursively iterate over fields in order
if n > max then
return working --all fields solved without collision
else
for i = 1, 9 do --check all values
if bound(f, i) then --if there is no collision
working[f] = i
local res = branch(n + 1) --try next field
if res then
return res --all fields solved without collision
else
working[f] = nil --this lead to a dead end
end
else
working[f] = nil --reset field because of a collision
end
end
return false --this is a dead end
end
end
x = branch(1)
if x then
return printer(x)
end</syntaxhighlight>
Input:
<pre>
003 000 000
400 080 036
008 000 100
 
040 060 073
000 900 000
000 002 005
 
004 070 068
600 000 000
700 600 500
</pre>
 
{{out}}
<pre>
123|456|789
457|189|236
968|327|154
---+---+---
249|561|873
576|938|412
831|742|695
---+---+---
314|275|968
695|814|327
782|693|541
</pre>
Time with luajit: 9.245s
===with FFI, fast===
<syntaxhighlight lang="lua">#!/usr/bin/env luajit
ffi=require"ffi"
local printf=function(fmt, ...) io.write(string.format(fmt, ...)) end
local band, bor, lshift, rshift=bit.band, bit.bor, bit.lshift, bit.rshift
local function show(x)
for i=0,8 do
if i%3==0 then print() end
for j=0,8 do
printf(j%3~=0 and "%2d" or "%3d", x[j+9*i])
end
print()
end
end
local function trycell(x, pos)
local row=math.floor(pos/9)
local col=pos%9
local used=0
if pos==81 then return true end
if x[pos]~=0 then return trycell(x, pos+1) end
for i=0,8 do
used=bor(used,lshift(1,x[i*9+col]-1))
end
for j=0,8 do
used=bor(used,lshift(1,x[row*9+j]-1))
end
row=math.floor(row/3)*3
col=math.floor(col/3)*3
for i=row,row+2 do
for j=col,col+2 do
used=bor(used, lshift(1, x[i*9+j]-1))
end
end
x[pos]=1
while x[pos]<=9 do
if band(used,1)==0 and trycell(x, pos+1) then return true end
used=rshift(used,1)
x[pos]=x[pos]+1
end
x[pos]=0
return false
end
local function solve(str)
local x=ffi.new("char[?]", 81)
str=str:gsub("[%c%s]","")
for i=0,81 do
x[i]=tonumber(str:sub(i+1, i+1)) or 0
end
if trycell(x, 0) then
show(x)
else
print("no solution")
end
end
 
do -- MAIN
solve([[
5.. .7. ...
6.. 195 ...
.98 ... .6.
 
8.. .6. ..3
4.. 8.3 ..1
7.. .2. ..6
 
.6. ... 28.
... 419 ..5
... .8. .79
]])
end</syntaxhighlight>
{{out}}
<pre>> time ./sudoku_fast.lua
 
5 3 4 6 7 8 9 1 2
6 7 2 1 9 5 3 4 8
1 9 8 3 4 2 5 6 7
 
8 5 9 7 6 1 4 2 3
4 2 6 8 5 3 7 9 1
7 1 3 9 2 4 8 5 6
 
9 6 1 5 3 7 2 8 4
2 8 7 4 1 9 6 3 5
3 4 5 2 8 6 1 7 9
./sudoku_fast.lua 0,01s user 0,00s system 90% cpu 0,007 total</pre>
Speed is about the speed of unoptimized C, half as fast as optimized C (C normal=0.007 C opt=0.004)
 
=={{header|Mathematica}}/{{header|Wolfram Language}}==
<syntaxhighlight lang="mathematica">solve[sudoku_] :=
NestWhile[
Join @@ Table[
Table[ReplacePart[s, #1 -> n], {n, #2}] & @@
First@SortBy[{#,
Complement[Range@9, s[[First@#]], s[[;; , Last@#]],
Catenate@
Extract[Partition[s, {3, 3}], Quotient[#, 3, -2]]]} & /@
Position[s, 0, {2}],
Length@Last@# &], {s, #}] &, {sudoku}, ! FreeQ[#, 0] &]</syntaxhighlight>
Example:
<syntaxhighlight lang="text">solve[{{9, 7, 0, 3, 0, 0, 0, 6, 0},
{0, 6, 0, 7, 5, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 8, 0, 5, 0},
{0, 0, 0, 0, 0, 0, 6, 7, 0},
{0, 0, 0, 0, 3, 0, 0, 0, 0},
{0, 5, 3, 9, 0, 0, 2, 0, 0},
{7, 0, 0, 0, 2, 5, 0, 0, 0},
{0, 0, 2, 0, 1, 0, 0, 0, 8},
{0, 4, 0, 0, 0, 7, 3, 0, 0}}]</syntaxhighlight>
{{out}}
<pre>{{{9, 7, 5, 3, 4, 2, 8, 6, 1}, {8, 6, 1, 7, 5, 9, 4, 3, 2}, {3, 2, 4,
1, 6, 8, 9, 5, 7}, {2, 1, 9, 5, 8, 4, 6, 7, 3}, {4, 8, 7, 2, 3, 6,
5, 1, 9}, {6, 5, 3, 9, 7, 1, 2, 8, 4}, {7, 3, 8, 4, 2, 5, 1, 9,
6}, {5, 9, 2, 6, 1, 3, 7, 4, 8}, {1, 4, 6, 8, 9, 7, 3, 2, 5}}}</pre>
 
=={{header|MATLAB}}==
Line 2,780 ⟶ 7,328:
 
For this to work, this code must be placed in a file named "sudokuSolver.m"
<langsyntaxhighlight MATLABlang="matlab">function solution = sudokuSolver(sudokuGrid)
 
%Define what each of the sub-boxes of the sudoku grid are by defining
Line 3,132 ⟶ 7,680:
%% End of program
end %end sudokuSolver</langsyntaxhighlight>
[http://www.menneske.no/sudoku/eng/showpuzzle.html?number=6903541 Test Input]:
All empty cells must have a value of NaN.
<langsyntaxhighlight MATLABlang="matlab">sudoku = [NaN NaN NaN NaN 8 3 9 NaN NaN
1 NaN NaN NaN NaN NaN NaN 3 NaN
NaN NaN 4 NaN NaN NaN NaN 7 NaN
Line 3,143 ⟶ 7,691:
NaN 2 NaN NaN NaN NaN NaN NaN NaN
NaN 8 NaN NaN NaN 9 2 NaN NaN
NaN NaN NaN 2 5 NaN NaN NaN 6]</langsyntaxhighlight>
[http://www.menneske.no/sudoku/eng/solution.html?number=6903541 Output]:
<langsyntaxhighlight MATLABlang="matlab">solution =
 
7 6 5 4 8 3 9 2 1
Line 3,155 ⟶ 7,703:
9 2 6 1 4 7 5 8 3
5 8 1 3 6 9 2 4 7
4 7 3 2 5 8 1 9 6</langsyntaxhighlight>
 
=={{header|Nim}}==
{{trans|Kotlin}}
<syntaxhighlight lang="nim">{.this: self.}
 
type
Sudoku = ref object
grid : array[81, int]
solved : bool
 
proc `$`(self: Sudoku): string =
var sb: string = ""
for i in 0..8:
for j in 0..8:
sb &= $grid[i * 9 + j]
sb &= " "
if j == 2 or j == 5:
sb &= "| "
sb &= "\n"
if i == 2 or i == 5:
sb &= "------+------+------\n"
sb
 
proc init(self: Sudoku, rows: array[9, string]) =
for i in 0..8:
for j in 0..8:
grid[9 * i + j] = rows[i][j].int - '0'.int
 
proc checkValidity(self: Sudoku, v, x, y: int): bool =
for i in 0..8:
if grid[y * 9 + i] == v or grid[i * 9 + x] == v:
return false
var startX = (x div 3) * 3
var startY = (y div 3) * 3
for i in startY..startY + 2:
for j in startX..startX + 2:
if grid[i * 9 + j] == v:
return false
result = true
 
proc placeNumber(self: Sudoku, pos: int) =
if solved:
return
if pos == 81:
solved = true
return
if grid[pos] > 0:
placeNumber(pos + 1)
return
for n in 1..9:
if checkValidity(n, pos mod 9, pos div 9):
grid[pos] = n
placeNumber(pos + 1)
if solved:
return
grid[pos] = 0
 
proc solve(self: Sudoku) =
echo "Starting grid:\n\n", $self
placeNumber(0)
if solved:
echo "Solution:\n\n", $self
else:
echo "Unsolvable!"
 
var rows = ["850002400",
"720000009",
"004000000",
"000107002",
"305000900",
"040000000",
"000080070",
"017000000",
"000036040"]
 
var puzzle = Sudoku()
puzzle.init(rows)
puzzle.solve()</syntaxhighlight>
 
{{out}}
<pre>Starting grid:
 
8 5 0 | 0 0 2 | 4 0 0
7 2 0 | 0 0 0 | 0 0 9
0 0 4 | 0 0 0 | 0 0 0
------+-------+------
0 0 0 | 1 0 7 | 0 0 2
3 0 5 | 0 0 0 | 9 0 0
0 4 0 | 0 0 0 | 0 0 0
------+-------+------
0 0 0 | 0 8 0 | 0 7 0
0 1 7 | 0 0 0 | 0 0 0
0 0 0 | 0 3 6 | 0 4 0
 
Solution:
 
8 5 9 | 6 1 2 | 4 3 7
7 2 3 | 8 5 4 | 1 6 9
1 6 4 | 3 7 9 | 5 2 8
------+-------+------
9 8 6 | 1 4 7 | 3 5 2
3 7 5 | 2 6 8 | 9 1 4
2 4 1 | 5 9 3 | 7 8 6
------+-------+------
4 3 2 | 9 8 1 | 6 7 5
6 1 7 | 4 2 5 | 8 9 3
5 9 8 | 7 3 6 | 2 4 1</pre>
 
=={{header|OCaml}}==
uses the library [http://ocamlgraph.lri.fr/index.en.html ocamlgraph]
<langsyntaxhighlight lang="ocaml">(* Ocamlgraph demo program: solving the Sudoku puzzle using graph coloring
Copyright 2004-2007 Sylvain Conchon, Jean-Christophe Filliatre, Julien Signoles
 
Line 3,228 ⟶ 7,883:
module C = Coloring.Mark(G)
 
let () = C.coloring g 9; display ()</langsyntaxhighlight>
 
=={{header|Oz}}==
Using built-in constraint propagation and search.
<langsyntaxhighlight lang="oz">declare
%% a puzzle is a function that returns an initial board configuration
fun {Puzzle1}
Line 3,315 ⟶ 7,970:
end
in
{Inspect {Solve Puzzle1}.1}</langsyntaxhighlight>
 
=={{header|PARI/GP}}==
 
Build plugin for PARI's function interface from C code: sudoku.c
<syntaxhighlight lang="c">#include <pari/pari.h>
 
typedef int SUDOKU [9][9];
 
static inline int check_num(SUDOKU s, int row, int col, int num)
{
int i, r = (row/3)*3, c = (col/3)*3;
 
for (i = 0; i < 9; i++)
if (s[row][i] == num || s[i][col] == num || s[i%3 + r][i/3 + c] == num)
return 0;
 
return 1;
}
 
static int sudoku_solve(SUDOKU s, int row, int col)
{
int num;
 
if (row < 9 && col < 9) {
if (s[row][col]) {
if (col < 8)
return sudoku_solve(s, row, col+1);
if (row < 8)
return sudoku_solve(s, row+1, 0);
return 1;
}
else
for (num = 1; num < 10; num++)
if (check_num(s, row, col, num)) {
s[row][col] = num;
if (sudoku_solve(s, row, col))
return 1;
else
s[row][col] = 0;
}
return 0;
}
return 1;
}
 
GEN plug_sudoku(GEN M)
{
SUDOKU s;
GEN S;
int i, k;
 
if (typ(M) != t_MAT)
pari_err(e_MISC, "parameter not matrix");
 
S = matsize(M);
 
if (itos(gel(S, 1)) < 9 || itos(gel(S, 2)) < 9)
pari_err(e_MISC, "parameter not 9x9 matrix");
 
for (i = 0; i < 9; i++)
for (k = 0; k < 9; k++)
s[i][k] = itos(gcoeff(M, i+1, k+1)); /* get sudoku */
 
if (sudoku_solve(s, 0, 0)) { /* solve sudoku */
S = cgetg(10, t_MAT);
for (k = 0; k < 9; k++) { /* create 9x9 matrix */
gel(S, k+1) = cgetg(10, t_COL);
for (i = 0; i < 9; i++)
gcoeff(S, i+1, k+1) = stoi(s[i][k]); /* fill in elements */
}
return S;
}
return gen_0; /* no solution */
}
</syntaxhighlight>
Compile plugin: gcc -O2 -Wall -fPIC -shared sudoku.c -o libsudoku.so -lpari
 
Install plugin from home directory and play:
<syntaxhighlight lang="parigp">install("plug_sudoku", "G", "sudoku", "~/libsudoku.so")</syntaxhighlight>
 
Output:<pre> gp > S=[5,3,0,0,7,0,0,0,0;6,0,0,1,9,5,0,0,0;0,9,8,0,0,0,0,6,0;8,0,0,0,6,0,0,0,3;4,0,0,8,0,3,0,0,1;7,0,0,0,2,0,0,0,6;0,6,0,0,0,0,2,8,0;0,0,0,4,1,9,0,0,5;0,0,0,0,8,0,0,7,9]
[5 3 0 0 7 0 0 0 0]
[6 0 0 1 9 5 0 0 0]
[0 9 8 0 0 0 0 6 0]
[8 0 0 0 6 0 0 0 3]
[4 0 0 8 0 3 0 0 1]
[7 0 0 0 2 0 0 0 6]
[0 6 0 0 0 0 2 8 0]
[0 0 0 4 1 9 0 0 5]
[0 0 0 0 8 0 0 7 9]
 
gp > sudoku(S)
[5 3 4 6 7 8 9 1 2]
[6 7 2 1 9 5 3 4 8]
[1 9 8 3 4 2 5 6 7]
[8 5 9 7 6 1 4 2 3]
[4 2 6 8 5 3 7 9 1]
[7 1 3 9 2 4 8 5 6]
[9 6 1 5 3 7 2 8 4]
[2 8 7 4 1 9 6 3 5]
[3 4 5 2 8 6 1 7 9]
</pre>
 
=={{header|Pascal}}==
{{works with|Free Pascal}}
Simple backtracking implimentation, therefor it must be fast to be competetive.With doReverse = true same sequence for trycell. nearly 5 times faster than [[Sudoku#C|C]]-Version.
<syntaxhighlight lang="pascal">Program soduko;
{$IFDEF FPC}
{$CODEALIGN proc=16,loop=8}
{$ENDIF}
uses
sysutils,crt;
const
carreeSize = 3;
maxCoor = carreeSize*carreeSize;
maxValue = maxCoor;
maxMask = 1 shl (maxCoor+1)-1;
type
tLimit = 0..maxCoor-1;
tValue = 0..maxCoor;
tSteps = 0..maxCoor*maxCoor;
tValField = array[tLimit,tLimit] of NativeInt;//tValue;
tBitrepr = 0..maxMask;
tcol = array[tLimit] of NativeInt;// tBitrepr;
trow = array[tLimit] of NativeInt;// tBitrepr;
tcar = array[tLimit] of NativeInt;// tBitrepr;
tpValue = ^NativeInt;//^tValue;
tpLimit = ^tLimit;
tpBitrepr= ^NativeInt;//^tBitrepr;
tchgVal = record
cvCol,
cvRow,
cvCar : tpBitrepr;
cvVal : tpValue;
end;
tpChgVal = ^tchgVal;
tchgList = array[tSteps] of tchgVal;
 
tField = record
fdChgList: tchgList;
fdCol : tcol;
fdRow : trow;
fdcar : tcar;
fdVal : tValField;
fdChgIdx : tSteps;
 
end;
const
Expl0:tValField = ((9,0,7,0,0,0,3,0,0),
(0,0,0,1,0,0,2,0,0),
(6,0,0,0,0,8,0,0,0),
(0,0,5,0,3,0,0,0,0),
(0,0,0,0,0,0,0,8,4),
(0,0,0,0,0,0,0,6,0),
(0,0,0,2,7,0,0,0,0),
(8,4,0,0,0,0,0,0,0),
(0,6,0,0,0,0,0,0,0));
Expl1:tValField=((0,0,0,1,0,0,0,3,8),
(2,0,0,0,0,5,0,0,0),
(0,0,0,0,0,0,0,0,0),
(0,5,0,0,0,0,4,0,0),
(4,0,0,0,3,0,0,0,0),
(0,0,0,7,0,0,0,0,6),
(0,0,1,0,0,0,0,5,0),
(0,0,0,0,6,0,2,0,0),
(0,6,0,0,0,4,0,0,0));
 
var
F,
solF : TField;
solCnt,
callCnt: NativeUint;
solFound : Boolean;
 
procedure OutField(const F:tField);
var
rw,cl : tLimit;
rowS: AnsiString;
Begin
GotoXy(1,1);
For rw := low(tLimit) to High(tLimit) do
Begin
rowS := ' ';
For cl := low(tLimit) to High(tLimit) do
RowS :=RowS+IntToStr(F.fdVal[rw,cl]);
writeln(RowS);
end;
end;
 
function CarIdx(rw,cl: NativeInt):NativeInt;
begin
CarIdx:= (rw DIV carreeSize)*carreeSize +cl DIV carreeSize;
end;
function InsertTest(const F:tField;rw,cl:tLimit;value:tValue):boolean;
var
msk: tBitrepr;
Begin
result := (Value = 0);
IF result then
EXIT;
msk := 1 shl (value-1);
with F do
Begin
result := fdRow[rw] AND msk = 0;
result := result AND (fdCol[cl] AND msk = 0);
rw :=CarIdx(rw,cl);
result := result AND (fdCar[rw] AND msk = 0);
end;
end;
 
function InitField(var F:tField;const InFd:tValField;DoReverse:boolean):boolean;
var
TmpchgVal:tchgVal;
rw,cl,
value,
msk : NativeInt;
leftSteps:tSteps;
Begin
Fillchar(F,SizeOf(F),#0);
leftSteps := High(tSteps)-1;
//unknown fields inserted from end
For rw := low(tLimit) to High(tLimit) do
For cl := low(tLimit) to High(tLimit) do
Begin
value := InFd[rw,cl];
IF InsertTest(F,rw,cl,value) then
Begin
with F do
Begin
if value > 0 then
Begin
msk := 1 shl (value-1);
//given state
//use pointer to the relevant places and mark as occupied
with fdChgList[fdChgIdx] do
begin
cvCol := @fdCol[cl];
cvCol^ +=Msk;
cvRow := @fdRow[rw];
cvRow^ +=Msk;
cvCar := @fdCar[CarIdx(rw,cl)];
cvCar^ +=Msk;
cvVal := @fdVal[rw,cl];
cvVal^ := value;
end;
inc(fdChgIdx);
end
else
Begin
//use pointer to the relevant places
with fdChgList[leftSteps] do
begin
cvCol := @fdCol[cl];
cvRow := @fdRow[rw];
cvCar := @fdCar[CarIdx(rw,cl)];
cvVal := @fdVal[rw,cl];
end;
dec(leftSteps);
end;
end
end
else
Begin
writeln(rw:10,cl:10,value:10);
Writeln(' not solvable SuDoKu ');
delay(2000);
result := false;
EXIT;
end;
end;
//reverse direction of left over
IF DoReverse then
Begin
leftSteps := High(tSteps)-1;
rw := F.fdChgIdx;
repeat
TmpchgVal:= F.fdChgList[leftSteps];
F.fdChgList[leftSteps]:= F.fdChgList[rw];
F.fdChgList[rw] :=TmpchgVal;
dec(leftSteps);
inc(rw);
until rw>=leftSteps;
end;
//OutField(F);
solFound := false;
result := true;
end;
procedure SolIsFound;
begin
solF := F;
inc(solCnt);
solFound := True;
end;
 
procedure TryCell(var ChgVal:tpchgVal);
var
value :NativeInt;
poss,msk: NativeInt;
Begin
IF solFound then EXIT;
with ChgVal^ do
poss:= (cvRow^ OR cvCol^ OR cvCar^) XOR maxMask;
IF Poss = 0 then
EXIT;
 
value := 1;
msk := 1;
 
repeat
IF Poss AND MSK <>0 then
Begin
inc(callCnt);
//insert test value
with ChgVal^ do
Begin
cvCol^ := cvCol^ OR msk;
cvRow^ := cvRow^ OR msk;
cvCar^ := cvCar^ OR msk;
cvVAl^ := value;
end;
//try next in list, if beyond last
inc(ChgVal);
 
IF ChgVal^.cvCol <> NIL then
TryCell(ChgVal)
else
SolIsFound;
//remove test value
dec(ChgVal);
with ChgVal^ do
Begin
cvCol^ := cvCol^ XOR msk;
cvRow^ := cvRow^ XOR msk;
cvCar^ := cvCar^ XOR msk;
cvVAl^ := 0;
end;
end;
inc(msk,msk);
inc(value);
until value> maxValue;
end;
 
var
ChangeBegin : tpChgVal;
k : NativeInt;
T1,T0: TDateTime;
begin
randomize;
ClrScr;
solCnt := 0;
callCnt:= 0;
T0 := time;
k := 0;
repeat
InitField(F,Expl1,FALSE);
ChangeBegin := @F.fdChgList[F.fdChgIdx];
TryCell(ChangeBegin);
inc(k);
until k >= 5;
T1 := time;
Outfield(solF);
writeln(86400*1000*(T1-T0)/k:10:3,' ms Test calls :',callCnt/k:8:0);
end.</syntaxhighlight>
{{out}}
<pre>
 
Expl0
927465318
458193276
613728459
185634792
376912584
294587163
539276841
841359627
762841935
// InitField doReverse = true
9.850 ms Test calls : 532466
// InitField doReverse = false
2609.000 ms Test calls :135196346
...
Expl1
594126738
237895164
618473925
859612473
476539812
123748596
341287659
985361247
762954381
// InitField doReverse = true
857.600 ms Test calls :40980572
// InitField doReverse = false
21.400 ms Test calls : 1089986
</pre>
 
=={{header|Perl}}==
<langsyntaxhighlight Perllang="perl">#!/usr/bin/perl
use integer;
use strict;
Line 3,357 ⟶ 8,408:
}
}
solve();</langsyntaxhighlight>
{{out}}
Output:
<pre>
5 3 9|8 2 4|7 6 1
Line 3,371 ⟶ 8,422:
9 6 7|4 1 5|3 2 8
2 5 3|6 9 8|4 1 7
</pre>
 
=={{header|Phix}}==
Simple brute force solution. Generally quite good but will struggle on some puzzles (eg see "the beast" below)
<!--<syntaxhighlight lang="phix">(phixonline)-->
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">board</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">split</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"""
.......39
.....1..5
..3.5.8..
..8.9...6
.7...2...
1..4.....
..9.8..5.
.2....6..
4..7....."""</span><span style="color: #0000FF;">,</span><span style="color: #008000;">'\n'</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">valid_move</span><span style="color: #0000FF;">(</span><span style="color: #004080;">integer</span> <span style="color: #000000;">y</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">x</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">ch</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">9</span> <span style="color: #008080;">do</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">ch</span><span style="color: #0000FF;">=</span><span style="color: #000000;">board</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">][</span><span style="color: #000000;">x</span><span style="color: #0000FF;">]</span> <span style="color: #008080;">then</span> <span style="color: #008080;">return</span> <span style="color: #004600;">false</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">ch</span><span style="color: #0000FF;">=</span><span style="color: #000000;">board</span><span style="color: #0000FF;">[</span><span style="color: #000000;">y</span><span style="color: #0000FF;">][</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span> <span style="color: #008080;">then</span> <span style="color: #008080;">return</span> <span style="color: #004600;">false</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #000000;">y</span> <span style="color: #0000FF;">-=</span> <span style="color: #7060A8;">mod</span><span style="color: #0000FF;">(</span><span style="color: #000000;">y</span><span style="color: #0000FF;">-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">3</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">x</span> <span style="color: #0000FF;">-=</span> <span style="color: #7060A8;">mod</span><span style="color: #0000FF;">(</span><span style="color: #000000;">x</span><span style="color: #0000FF;">-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">3</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">ys</span><span style="color: #0000FF;">=</span><span style="color: #000000;">y</span> <span style="color: #008080;">to</span> <span style="color: #000000;">y</span><span style="color: #0000FF;">+</span><span style="color: #000000;">2</span> <span style="color: #008080;">do</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">xs</span><span style="color: #0000FF;">=</span><span style="color: #000000;">x</span> <span style="color: #008080;">to</span> <span style="color: #000000;">x</span><span style="color: #0000FF;">+</span><span style="color: #000000;">2</span> <span style="color: #008080;">do</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">ch</span><span style="color: #0000FF;">=</span><span style="color: #000000;">board</span><span style="color: #0000FF;">[</span><span style="color: #000000;">ys</span><span style="color: #0000FF;">][</span><span style="color: #000000;">xs</span><span style="color: #0000FF;">]</span> <span style="color: #008080;">then</span> <span style="color: #008080;">return</span> <span style="color: #004600;">false</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">return</span> <span style="color: #004600;">true</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">solution</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{}</span>
<span style="color: #008080;">procedure</span> <span style="color: #000000;">brute_solve</span><span style="color: #0000FF;">()</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">y</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">9</span> <span style="color: #008080;">do</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">x</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">9</span> <span style="color: #008080;">do</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">board</span><span style="color: #0000FF;">[</span><span style="color: #000000;">y</span><span style="color: #0000FF;">][</span><span style="color: #000000;">x</span><span style="color: #0000FF;">]<=</span><span style="color: #008000;">'0'</span> <span style="color: #008080;">then</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">ch</span><span style="color: #0000FF;">=</span><span style="color: #008000;">'1'</span> <span style="color: #008080;">to</span> <span style="color: #008000;">'9'</span> <span style="color: #008080;">do</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">valid_move</span><span style="color: #0000FF;">(</span><span style="color: #000000;">y</span><span style="color: #0000FF;">,</span><span style="color: #000000;">x</span><span style="color: #0000FF;">,</span><span style="color: #000000;">ch</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">board</span><span style="color: #0000FF;">[</span><span style="color: #000000;">y</span><span style="color: #0000FF;">][</span><span style="color: #000000;">x</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">ch</span>
<span style="color: #000000;">brute_solve</span><span style="color: #0000FF;">()</span>
<span style="color: #000000;">board</span><span style="color: #0000FF;">[</span><span style="color: #000000;">y</span><span style="color: #0000FF;">][</span><span style="color: #000000;">x</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">' '</span>
<span style="color: #008080;">if</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">solution</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span> <span style="color: #008080;">return</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">return</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #000000;">solution</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">deep_copy</span><span style="color: #0000FF;">(</span><span style="color: #000000;">board</span><span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">-- (already solved case)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span>
<span style="color: #004080;">atom</span> <span style="color: #000000;">t0</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">time</span><span style="color: #0000FF;">()</span>
<span style="color: #000000;">brute_solve</span><span style="color: #0000FF;">()</span>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"%s\n(solved in %3.2fs)\n"</span><span style="color: #0000FF;">,{</span><span style="color: #7060A8;">join</span><span style="color: #0000FF;">(</span><span style="color: #000000;">solution</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"\n"</span><span style="color: #0000FF;">),</span><span style="color: #7060A8;">time</span><span style="color: #0000FF;">()-</span><span style="color: #000000;">t0</span><span style="color: #0000FF;">})</span>
<!--</syntaxhighlight>-->
{{out}}
<pre>
751846239
892371465
643259871
238197546
974562318
165438927
319684752
527913684
486725193
(solved in 0.95s)
</pre>
OTT solution. Implements line/col and set exclusion, and x-wings. Blisteringly fast<BR>
The included program demo\rosetta\Sudoku.exw is an extended version of this that performs extended validation,
contains 339 puzzles, can be run as a command-line or gui program, check for multiple solutions, and produce
a more readable single-puzzle output (example below).
<!--<syntaxhighlight lang="phix">(phixonline)-->
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>
<span style="color: #000080;font-style:italic;">-- Working directly on 81-character strings ultimately proves easier: Originally I
-- just wanted to simplify the final display, but later I realised that a 9x9 grid
-- encourages laborious indexing/looping everwhere whereas using a flat 81-element
-- approach encourages precomputation of index sets, and once you commit to that,
-- the rest of the code starts to get a whole lot cleaner. Below we create 27+18
-- sets and 5 tables of lookup indexes to locate them quickly.</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">nines</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{},</span> <span style="color: #000080;font-style:italic;">-- will be 27 in total</span>
<span style="color: #000000;">cols</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">9</span><span style="color: #0000FF;">*</span><span style="color: #000000;">9</span><span style="color: #0000FF;">),</span> <span style="color: #000080;font-style:italic;">-- remainder(i-1,9)+1</span>
<span style="color: #000000;">rows</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">9</span><span style="color: #0000FF;">*</span><span style="color: #000000;">9</span><span style="color: #0000FF;">),</span> <span style="color: #000080;font-style:italic;">-- floor((i-1)/9)+10</span>
<span style="color: #000000;">squares</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">9</span><span style="color: #0000FF;">*</span><span style="color: #000000;">9</span><span style="color: #0000FF;">),</span>
<span style="color: #000000;">sixes</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{},</span> <span style="color: #000080;font-style:italic;">-- will be 18 in total</span>
<span style="color: #000000;">dotcol</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">9</span><span style="color: #0000FF;">*</span><span style="color: #000000;">9</span><span style="color: #0000FF;">),</span> <span style="color: #000080;font-style:italic;">-- same col, diff square</span>
<span style="color: #000000;">dotrow</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">9</span><span style="color: #0000FF;">*</span><span style="color: #000000;">9</span><span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">-- same row, diff square</span>
<span style="color: #008080;">procedure</span> <span style="color: #000000;">set_nines</span><span style="color: #0000FF;">()</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">nine</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">six</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">idx</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">ndx</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">x</span><span style="color: #0000FF;">=</span><span style="color: #000000;">0</span> <span style="color: #008080;">to</span> <span style="color: #000000;">8</span> <span style="color: #008080;">do</span> <span style="color: #000080;font-style:italic;">-- columns</span>
<span style="color: #000000;">nine</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{}</span>
<span style="color: #000000;">ndx</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">nines</span><span style="color: #0000FF;">)+</span><span style="color: #000000;">1</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">y</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">81</span> <span style="color: #008080;">by</span> <span style="color: #000000;">9</span> <span style="color: #008080;">do</span>
<span style="color: #000000;">idx</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">y</span><span style="color: #0000FF;">+</span><span style="color: #000000;">x</span>
<span style="color: #000000;">nine</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">append</span><span style="color: #0000FF;">(</span><span style="color: #000000;">nine</span><span style="color: #0000FF;">,</span><span style="color: #000000;">idx</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">cols</span><span style="color: #0000FF;">[</span><span style="color: #000000;">idx</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">ndx</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #000000;">nines</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">append</span><span style="color: #0000FF;">(</span><span style="color: #000000;">nines</span><span style="color: #0000FF;">,</span><span style="color: #000000;">nine</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">y</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">81</span> <span style="color: #008080;">by</span> <span style="color: #000000;">9</span> <span style="color: #008080;">do</span> <span style="color: #000080;font-style:italic;">-- rows</span>
<span style="color: #000000;">nine</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{}</span>
<span style="color: #000000;">ndx</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">nines</span><span style="color: #0000FF;">)+</span><span style="color: #000000;">1</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">x</span><span style="color: #0000FF;">=</span><span style="color: #000000;">0</span> <span style="color: #008080;">to</span> <span style="color: #000000;">8</span> <span style="color: #008080;">do</span>
<span style="color: #000000;">idx</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">y</span><span style="color: #0000FF;">+</span><span style="color: #000000;">x</span>
<span style="color: #000000;">nine</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">append</span><span style="color: #0000FF;">(</span><span style="color: #000000;">nine</span><span style="color: #0000FF;">,</span><span style="color: #000000;">idx</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">rows</span><span style="color: #0000FF;">[</span><span style="color: #000000;">idx</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">ndx</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #000000;">nines</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">append</span><span style="color: #0000FF;">(</span><span style="color: #000000;">nines</span><span style="color: #0000FF;">,</span><span style="color: #000000;">nine</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">if</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">nines</span><span style="color: #0000FF;">)!=</span><span style="color: #000000;">18</span> <span style="color: #008080;">then</span> <span style="color: #0000FF;">?</span><span style="color: #000000;">9</span><span style="color: #0000FF;">/</span><span style="color: #000000;">0</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">y</span><span style="color: #0000FF;">=</span><span style="color: #000000;">0</span> <span style="color: #008080;">to</span> <span style="color: #000000;">8</span> <span style="color: #008080;">by</span> <span style="color: #000000;">3</span> <span style="color: #008080;">do</span> <span style="color: #000080;font-style:italic;">-- small squares [19..27]</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">x</span><span style="color: #0000FF;">=</span><span style="color: #000000;">0</span> <span style="color: #008080;">to</span> <span style="color: #000000;">8</span> <span style="color: #008080;">by</span> <span style="color: #000000;">3</span> <span style="color: #008080;">do</span>
<span style="color: #000000;">nine</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{}</span>
<span style="color: #000000;">ndx</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">nines</span><span style="color: #0000FF;">)+</span><span style="color: #000000;">1</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">sy</span><span style="color: #0000FF;">=</span><span style="color: #000000;">y</span><span style="color: #0000FF;">*</span><span style="color: #000000;">9</span> <span style="color: #008080;">to</span> <span style="color: #000000;">y</span><span style="color: #0000FF;">*</span><span style="color: #000000;">9</span><span style="color: #0000FF;">+</span><span style="color: #000000;">18</span> <span style="color: #008080;">by</span> <span style="color: #000000;">9</span> <span style="color: #008080;">do</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">sx</span><span style="color: #0000FF;">=</span><span style="color: #000000;">x</span> <span style="color: #008080;">to</span> <span style="color: #000000;">x</span><span style="color: #0000FF;">+</span><span style="color: #000000;">2</span> <span style="color: #008080;">do</span>
<span style="color: #000000;">idx</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">sy</span><span style="color: #0000FF;">+</span><span style="color: #000000;">sx</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span>
<span style="color: #000000;">nine</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">append</span><span style="color: #0000FF;">(</span><span style="color: #000000;">nine</span><span style="color: #0000FF;">,</span><span style="color: #000000;">idx</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">squares</span><span style="color: #0000FF;">[</span><span style="color: #000000;">idx</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">ndx</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #000000;">nines</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">append</span><span style="color: #0000FF;">(</span><span style="color: #000000;">nines</span><span style="color: #0000FF;">,</span><span style="color: #000000;">nine</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">if</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">nines</span><span style="color: #0000FF;">)!=</span><span style="color: #000000;">27</span> <span style="color: #008080;">then</span> <span style="color: #0000FF;">?</span><span style="color: #000000;">9</span><span style="color: #0000FF;">/</span><span style="color: #000000;">0</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">9</span><span style="color: #0000FF;">*</span><span style="color: #000000;">9</span> <span style="color: #008080;">do</span>
<span style="color: #000000;">six</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{}</span>
<span style="color: #000000;">nine</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">nines</span><span style="color: #0000FF;">[</span><span style="color: #000000;">cols</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]]</span> <span style="color: #000080;font-style:italic;">-- dotcol</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">j</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">nine</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">squares</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]!=</span><span style="color: #000000;">squares</span><span style="color: #0000FF;">[</span><span style="color: #000000;">nine</span><span style="color: #0000FF;">[</span><span style="color: #000000;">j</span><span style="color: #0000FF;">]]</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">six</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">append</span><span style="color: #0000FF;">(</span><span style="color: #000000;">six</span><span style="color: #0000FF;">,</span><span style="color: #000000;">nine</span><span style="color: #0000FF;">[</span><span style="color: #000000;">j</span><span style="color: #0000FF;">])</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #000000;">ndx</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #000000;">six</span><span style="color: #0000FF;">,</span><span style="color: #000000;">sixes</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">ndx</span><span style="color: #0000FF;">=</span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">sixes</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">append</span><span style="color: #0000FF;">(</span><span style="color: #000000;">sixes</span><span style="color: #0000FF;">,</span><span style="color: #000000;">six</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">ndx</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">sixes</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #000000;">dotcol</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">ndx</span>
<span style="color: #000000;">six</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{}</span>
<span style="color: #000000;">nine</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">nines</span><span style="color: #0000FF;">[</span><span style="color: #000000;">rows</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]]</span> <span style="color: #000080;font-style:italic;">-- dotrow</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">j</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">nine</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">squares</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]!=</span><span style="color: #000000;">squares</span><span style="color: #0000FF;">[</span><span style="color: #000000;">nine</span><span style="color: #0000FF;">[</span><span style="color: #000000;">j</span><span style="color: #0000FF;">]]</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">six</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">append</span><span style="color: #0000FF;">(</span><span style="color: #000000;">six</span><span style="color: #0000FF;">,</span><span style="color: #000000;">nine</span><span style="color: #0000FF;">[</span><span style="color: #000000;">j</span><span style="color: #0000FF;">])</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #000000;">ndx</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #000000;">six</span><span style="color: #0000FF;">,</span><span style="color: #000000;">sixes</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">ndx</span><span style="color: #0000FF;">=</span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">sixes</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">append</span><span style="color: #0000FF;">(</span><span style="color: #000000;">sixes</span><span style="color: #0000FF;">,</span><span style="color: #000000;">six</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">ndx</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">sixes</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #000000;">dotrow</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">ndx</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span>
<span style="color: #000000;">set_nines</span><span style="color: #0000FF;">()</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">improved</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">eliminate_in</span><span style="color: #0000FF;">(</span><span style="color: #004080;">sequence</span> <span style="color: #000000;">valid</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">set</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">integer</span> <span style="color: #000000;">ch</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">set</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">idx</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">set</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span>
<span style="color: #008080;">if</span> <span style="color: #004080;">string</span><span style="color: #0000FF;">(</span><span style="color: #000000;">valid</span><span style="color: #0000FF;">[</span><span style="color: #000000;">idx</span><span style="color: #0000FF;">])</span> <span style="color: #008080;">then</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">k</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #000000;">ch</span><span style="color: #0000FF;">,</span><span style="color: #000000;">valid</span><span style="color: #0000FF;">[</span><span style="color: #000000;">idx</span><span style="color: #0000FF;">])</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">k</span><span style="color: #0000FF;">!=</span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">valid</span><span style="color: #0000FF;">[</span><span style="color: #000000;">idx</span><span style="color: #0000FF;">][</span><span style="color: #000000;">k</span><span style="color: #0000FF;">..</span><span style="color: #000000;">k</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">""</span>
<span style="color: #000000;">improved</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">1</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">valid</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">test_comb</span><span style="color: #0000FF;">(</span><span style="color: #004080;">sequence</span> <span style="color: #000000;">chosen</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">pool</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">valid</span><span style="color: #0000FF;">)</span>
<span style="color: #000080;font-style:italic;">--
-- (see deep_logic()/set elimination)
-- chosen is a sequence of length 2..4 of integers 1..9: ordered elements of pool.
-- pool is a set of elements of the sequence valid, each of which is a sequence.
-- (note that elements of valid in pool not in chosen are not necessarily sequences)
--</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">contains</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">9</span><span style="color: #0000FF;">)</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">ccount</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">ch</span>
<span style="color: #004080;">object</span> <span style="color: #000000;">set</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">chosen</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
<span style="color: #000000;">set</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">valid</span><span style="color: #0000FF;">[</span><span style="color: #000000;">pool</span><span style="color: #0000FF;">[</span><span style="color: #000000;">chosen</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]]]</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">j</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">set</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
<span style="color: #000000;">ch</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">set</span><span style="color: #0000FF;">[</span><span style="color: #000000;">j</span><span style="color: #0000FF;">]-</span><span style="color: #008000;">'0'</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">contains</span><span style="color: #0000FF;">[</span><span style="color: #000000;">ch</span><span style="color: #0000FF;">]=</span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">contains</span><span style="color: #0000FF;">[</span><span style="color: #000000;">ch</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">1</span>
<span style="color: #000000;">ccount</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">1</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">ccount</span><span style="color: #0000FF;">=</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">chosen</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">valid</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">deep_copy</span><span style="color: #0000FF;">(</span><span style="color: #000000;">valid</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">pool</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
<span style="color: #008080;">if</span> <span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #000000;">i</span><span style="color: #0000FF;">,</span><span style="color: #000000;">chosen</span><span style="color: #0000FF;">)=</span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">set</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">valid</span><span style="color: #0000FF;">[</span><span style="color: #000000;">pool</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]]</span>
<span style="color: #008080;">if</span> <span style="color: #004080;">sequence</span><span style="color: #0000FF;">(</span><span style="color: #000000;">set</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span>
<span style="color: #000080;font-style:italic;">-- (reverse order so deletions don't foul indexes)</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">j</span><span style="color: #0000FF;">=</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">set</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">to</span> <span style="color: #000000;">1</span> <span style="color: #008080;">by</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">1</span> <span style="color: #008080;">do</span>
<span style="color: #000000;">ch</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">set</span><span style="color: #0000FF;">[</span><span style="color: #000000;">j</span><span style="color: #0000FF;">]-</span><span style="color: #008000;">'0'</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">contains</span><span style="color: #0000FF;">[</span><span style="color: #000000;">ch</span><span style="color: #0000FF;">]</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">valid</span><span style="color: #0000FF;">[</span><span style="color: #000000;">pool</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]][</span><span style="color: #000000;">j</span><span style="color: #0000FF;">..</span><span style="color: #000000;">j</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">""</span>
<span style="color: #000000;">improved</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">1</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">valid</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #000080;font-style:italic;">-- from [[Combinations#Phix|Combinations]]
-- from http://rosettacode.org/wiki/Combinations#Phix</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">comb</span><span style="color: #0000FF;">(</span><span style="color: #004080;">sequence</span> <span style="color: #000000;">pool</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">valid</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">integer</span> <span style="color: #000000;">needed</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">done</span><span style="color: #0000FF;">=</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">sequence</span> <span style="color: #000000;">chosen</span><span style="color: #0000FF;">={})</span>
<span style="color: #000080;font-style:italic;">-- (used by deep_logic()/set elimination)</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">needed</span><span style="color: #0000FF;">=</span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span> <span style="color: #000080;font-style:italic;">-- got a full set</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">test_comb</span><span style="color: #0000FF;">(</span><span style="color: #000000;">chosen</span><span style="color: #0000FF;">,</span><span style="color: #000000;">pool</span><span style="color: #0000FF;">,</span><span style="color: #000000;">valid</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">done</span><span style="color: #0000FF;">+</span><span style="color: #000000;">needed</span><span style="color: #0000FF;">></span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">pool</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span> <span style="color: #008080;">return</span> <span style="color: #000000;">valid</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span> <span style="color: #000080;font-style:italic;">-- cannot fulfil
-- get all combinations with and without the next item:</span>
<span style="color: #000000;">done</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">1</span>
<span style="color: #008080;">if</span> <span style="color: #004080;">sequence</span><span style="color: #0000FF;">(</span><span style="color: #000000;">valid</span><span style="color: #0000FF;">[</span><span style="color: #000000;">pool</span><span style="color: #0000FF;">[</span><span style="color: #000000;">done</span><span style="color: #0000FF;">]])</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">valid</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">comb</span><span style="color: #0000FF;">(</span><span style="color: #000000;">pool</span><span style="color: #0000FF;">,</span><span style="color: #000000;">valid</span><span style="color: #0000FF;">,</span><span style="color: #000000;">needed</span><span style="color: #0000FF;">-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">done</span><span style="color: #0000FF;">,</span><span style="color: #7060A8;">append</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">deep_copy</span><span style="color: #0000FF;">(</span><span style="color: #000000;">chosen</span><span style="color: #0000FF;">),</span><span style="color: #000000;">done</span><span style="color: #0000FF;">))</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">comb</span><span style="color: #0000FF;">(</span><span style="color: #000000;">pool</span><span style="color: #0000FF;">,</span><span style="color: #000000;">valid</span><span style="color: #0000FF;">,</span><span style="color: #000000;">needed</span><span style="color: #0000FF;">,</span><span style="color: #000000;">done</span><span style="color: #0000FF;">,</span><span style="color: #000000;">chosen</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">deep_logic</span><span style="color: #0000FF;">(</span><span style="color: #004080;">string</span> <span style="color: #000000;">board</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">sequence</span> <span style="color: #000000;">valid</span><span style="color: #0000FF;">)</span>
<span style="color: #000080;font-style:italic;">--
-- Create a grid of valid moves. Note this does not modify board, but instead creates
-- sets of permitted values for each cell, which can also be and are used for hints.
-- Apply standard eliminations of known cells, then try some more advanced tactics:
--
-- 1) row/col elimination
-- If in any of the 9 small squares a number can only occur in one row or column,
-- then that number cannot occur in that row or column in two other corresponding
-- small squares. Example (this one with significant practical benefit):
-- 000|000|036
-- 840|000|000
-- 000|000|020
-- ---+---+---
-- 000|203|000
-- 010|000|700
-- 000|600|400
-- ---+---+---
-- 000|410|050
-- 003|000|200
-- 600|000|000 &lt;-- 3
-- ^-- 3
-- Naively, the br can contain a 3 in the four corners, but looking at mid-right and
-- mid-bottom leads us to eliminating 3s in column 9 and row 9, leaving 7,7 as the
-- only square in the br that can be a 3. Uses dotcol and dotrow.
-- Without this, brute force on the above takes ~8s, but with it ~0s
--
-- 2) set elimination
-- If in any 9-set there is a set of n blank squares that can only contain n digits,
-- then no other squares can contain those digits. Example (with some benefit):
-- 75.|.9.|.46
-- 961|...|352
-- 4..|...|79.
-- ---+---+---
-- 2..|6.1|..7
-- .8.|...|.2.
-- 1..|328|.65
-- ---+---+---
-- ...|...|... &lt;-- [7,8] is {1,3,8}, [7,9] is {1,3,8}
-- 3.9|...|2.4 &lt;-- [8,8] is {1,8}
-- 84.|.3.|.79
-- The three cells above the br 479 can only contain {1,3,8}, so the .. of the .2.
-- in column 7 of that square are {5,6} (not 1) and hence [9,4] must be a 1.
-- (Relies on plain_logic to spot that "must be a 1", and serves as a clear example
-- of why this routine should not bother to attempt updating the board itself - as
-- it spends almost all of its time looking in a completely different place.)
-- (One could argue that [7,7] and [9,7] are the only places that can hold {5,6} and
-- therefore we should eliminate all non-{5,6} from those squares, as an alternative
-- strategy. However I think that would be harder to code and cannot imagine a case
-- said complementary logic covers, that the above does not, cmiiw.)
--
-- 3) x-wings
-- If a pair of rows or columns can only contain a given number in two matching places,
-- then once filled they will occupy opposite diagonal corners, hence that said number
-- cannot occur elsewhere in those two columns/rows. Example (with a benefit):
-- .43|98.|25. &lt;-- 6 in [1,{6,9}]
-- 6..|425|...
-- 2..|..1|.94
-- ---+---+---
-- 9..|..4|.7. &lt;-- hence 6 not in [4,9]
-- 3..|6.8|...
-- 41.|2.9|..3
-- ---+---+---
-- 82.|5..|... &lt;-- hence 6 not in [7,6],[7,9]
-- ...|.4.|..5 &lt;-- hence 6 not in [8,6]
-- 534|89.|71. &lt;-- 6 in [9,{6,9}]
-- A 6 must be in [1,6] or [1,9] and [9,6] or [9,9], hence [7,9] is not 6 and must be 9.
-- (we also eliminate 6 from [4,9], [7,6] and [8,6] to no great use)
-- In practice this offers little benefit over a single trial-and-error step, as
-- obviously trying either 6 in row 1 or 9 immediately pinpoints that 9 anyway.
--
-- 4) swordfish (not attempted)
-- There is an extension to x-wings known as swordfish: three (or more) pairs form
-- a staggered pair (or more) of rectangles that exhibit similar properties, eg:
-- 8-1|-5-|-3-
-- 953|-68|---
-- -4-|-*3|5*8
-- ---+---+---
-- 6--|9-2|---
-- -8-|-3-|-4-
-- 3*-|5-1|-*7 &lt;-- hence [6,3] is not 9, must be 4
-- ---+---+---
-- 5*2|-*-|-8-
-- --8|37-|--9
-- -3-|82-|1--
-- ^---^---^-- 3 pairs of 9s (marked with *) on 3 rows (only)
-- It is not a swordfish if the 3 pairs are on &gt;3 rows, I trust that is obvious.
-- Logically you can extend this to N pairs on N rows, however I cannot imagine a
-- case where this is not immediately solved by a single trial-step being invalid.
-- (eg above if you try [3,5]:=9 it is quickly proved to be invalid, and the same
-- goes for [6,8]:=9 and [7,2]:=9, since they are all entirely inter-dependent.)
-- Obviously where I have said rows, the same concept can be applied to columns.
-- Likewise there are "Alternate Pairs" and "Hook or X-Y wing" strategies, which
-- are easily solved with a single trial-and-error step, and of course the brute
-- force algorithm is going to select pairs first anyway. [Erm, no it doesn't,
-- it selects shortest - I've noted the possible improvement below.]
--</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">k</span> <span style="color: #000080;font-style:italic;">-- (scratch)</span>
<span style="color: #008080;">if</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">valid</span><span style="color: #0000FF;">)=</span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span>
<span style="color: #000080;font-style:italic;">-- initialise/start again from scratch</span>
<span style="color: #000000;">valid</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"123456789"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">9</span><span style="color: #0000FF;">*</span><span style="color: #000000;">9</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #000080;font-style:italic;">--
-- First perform standard eliminations of any known cells:
-- (repeated every time so plain_logic() does not have to worry about it)
--</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">9</span><span style="color: #0000FF;">*</span><span style="color: #000000;">9</span> <span style="color: #008080;">do</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">ch</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">board</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">ch</span><span style="color: #0000FF;">></span><span style="color: #008000;">'0'</span>
<span style="color: #008080;">and</span> <span style="color: #004080;">string</span><span style="color: #0000FF;">(</span><span style="color: #000000;">valid</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">])</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">valid</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">ch</span>
<span style="color: #000000;">valid</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">eliminate_in</span><span style="color: #0000FF;">(</span><span style="color: #000000;">valid</span><span style="color: #0000FF;">,</span><span style="color: #000000;">nines</span><span style="color: #0000FF;">[</span><span style="color: #000000;">cols</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]],</span><span style="color: #000000;">ch</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">valid</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">eliminate_in</span><span style="color: #0000FF;">(</span><span style="color: #000000;">valid</span><span style="color: #0000FF;">,</span><span style="color: #000000;">nines</span><span style="color: #0000FF;">[</span><span style="color: #000000;">rows</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]],</span><span style="color: #000000;">ch</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">valid</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">eliminate_in</span><span style="color: #0000FF;">(</span><span style="color: #000000;">valid</span><span style="color: #0000FF;">,</span><span style="color: #000000;">nines</span><span style="color: #0000FF;">[</span><span style="color: #000000;">squares</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]],</span><span style="color: #000000;">ch</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #000080;font-style:italic;">--
-- 1) row/col elimination
--</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">s</span><span style="color: #0000FF;">=</span><span style="color: #000000;">19</span> <span style="color: #008080;">to</span> <span style="color: #000000;">27</span> <span style="color: #008080;">do</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">c</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">9</span><span style="color: #0000FF;">),</span> <span style="color: #000080;font-style:italic;">-- 0 = none seen, 1..9 this col only, -1: &gt;1 col</span>
<span style="color: #000000;">r</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">9</span><span style="color: #0000FF;">),</span> <span style="color: #000080;font-style:italic;">-- "" row row</span>
<span style="color: #000000;">nine</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">nines</span><span style="color: #0000FF;">[</span><span style="color: #000000;">s</span><span style="color: #0000FF;">]</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">row</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">col</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">ch</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">n</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">9</span> <span style="color: #008080;">do</span>
<span style="color: #000000;">k</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">nine</span><span style="color: #0000FF;">[</span><span style="color: #000000;">n</span><span style="color: #0000FF;">]</span>
<span style="color: #004080;">object</span> <span style="color: #000000;">vk</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">valid</span><span style="color: #0000FF;">[</span><span style="color: #000000;">k</span><span style="color: #0000FF;">]</span>
<span style="color: #008080;">if</span> <span style="color: #004080;">string</span><span style="color: #0000FF;">(</span><span style="color: #000000;">vk</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">vk</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
<span style="color: #000000;">ch</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">vk</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]-</span><span style="color: #008000;">'0'</span>
<span style="color: #000000;">col</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">dotcol</span><span style="color: #0000FF;">[</span><span style="color: #000000;">k</span><span style="color: #0000FF;">]</span>
<span style="color: #000000;">row</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">dotrow</span><span style="color: #0000FF;">[</span><span style="color: #000000;">k</span><span style="color: #0000FF;">]</span>
<span style="color: #000000;">c</span><span style="color: #0000FF;">[</span><span style="color: #000000;">ch</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #008080;">iff</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #000000;">c</span><span style="color: #0000FF;">[</span><span style="color: #000000;">ch</span><span style="color: #0000FF;">],{</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">col</span><span style="color: #0000FF;">})!=</span><span style="color: #000000;">0</span><span style="color: #0000FF;">?</span><span style="color: #000000;">col</span><span style="color: #0000FF;">:-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">r</span><span style="color: #0000FF;">[</span><span style="color: #000000;">ch</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #008080;">iff</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #000000;">r</span><span style="color: #0000FF;">[</span><span style="color: #000000;">ch</span><span style="color: #0000FF;">],{</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">row</span><span style="color: #0000FF;">})!=</span><span style="color: #000000;">0</span><span style="color: #0000FF;">?</span><span style="color: #000000;">row</span><span style="color: #0000FF;">:-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">9</span> <span style="color: #008080;">do</span>
<span style="color: #000000;">ch</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">+</span><span style="color: #008000;">'0'</span>
<span style="color: #000000;">col</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">c</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">col</span><span style="color: #0000FF;">></span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">valid</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">eliminate_in</span><span style="color: #0000FF;">(</span><span style="color: #000000;">valid</span><span style="color: #0000FF;">,</span><span style="color: #000000;">sixes</span><span style="color: #0000FF;">[</span><span style="color: #000000;">col</span><span style="color: #0000FF;">],</span><span style="color: #000000;">ch</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #000000;">row</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">r</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">row</span><span style="color: #0000FF;">></span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">valid</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">eliminate_in</span><span style="color: #0000FF;">(</span><span style="color: #000000;">valid</span><span style="color: #0000FF;">,</span><span style="color: #000000;">sixes</span><span style="color: #0000FF;">[</span><span style="color: #000000;">row</span><span style="color: #0000FF;">],</span><span style="color: #000000;">ch</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #000080;font-style:italic;">--
-- 2) set elimination
--</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">nines</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
<span style="color: #000080;font-style:italic;">--
-- Practical note: Meticulously counting empties to eliminate larger set sizes
-- would at best reduce 6642 tests to 972, not deemed worth it.
--</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">set_size</span><span style="color: #0000FF;">=</span><span style="color: #000000;">2</span> <span style="color: #008080;">to</span> <span style="color: #000000;">4</span> <span style="color: #008080;">do</span>
<span style="color: #000080;font-style:italic;">--if floor(count_empties(nines[i])/2)&gt;=set_size then -- (untested)</span>
<span style="color: #000000;">valid</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">comb</span><span style="color: #0000FF;">(</span><span style="color: #000000;">nines</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">],</span><span style="color: #000000;">valid</span><span style="color: #0000FF;">,</span><span style="color: #000000;">set_size</span><span style="color: #0000FF;">)</span>
<span style="color: #000080;font-style:italic;">--end if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #000080;font-style:italic;">--
-- 3) x-wings
--</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">ch</span><span style="color: #0000FF;">=</span><span style="color: #008000;">'1'</span> <span style="color: #008080;">to</span> <span style="color: #008000;">'9'</span> <span style="color: #008080;">do</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">prevsets</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">9</span><span style="color: #0000FF;">),</span> <span style="color: #000000;">set</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">count</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">idx</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">x</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">9</span> <span style="color: #008080;">do</span>
<span style="color: #000000;">count</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span>
<span style="color: #000000;">set</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">9</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">y</span><span style="color: #0000FF;">=</span><span style="color: #000000;">0</span> <span style="color: #008080;">to</span> <span style="color: #000000;">8</span> <span style="color: #008080;">do</span>
<span style="color: #000000;">idx</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">y</span><span style="color: #0000FF;">*</span><span style="color: #000000;">9</span><span style="color: #0000FF;">+</span><span style="color: #000000;">x</span>
<span style="color: #008080;">if</span> <span style="color: #004080;">sequence</span><span style="color: #0000FF;">(</span><span style="color: #000000;">valid</span><span style="color: #0000FF;">[</span><span style="color: #000000;">idx</span><span style="color: #0000FF;">])</span> <span style="color: #008080;">and</span> <span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #000000;">ch</span><span style="color: #0000FF;">,</span><span style="color: #000000;">valid</span><span style="color: #0000FF;">[</span><span style="color: #000000;">idx</span><span style="color: #0000FF;">])</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">set</span><span style="color: #0000FF;">[</span><span style="color: #000000;">y</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">1</span>
<span style="color: #000000;">count</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">1</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">count</span><span style="color: #0000FF;">=</span><span style="color: #000000;">2</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">k</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #000000;">set</span><span style="color: #0000FF;">,</span><span style="color: #000000;">prevsets</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">k</span><span style="color: #0000FF;">!=</span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">y</span><span style="color: #0000FF;">=</span><span style="color: #000000;">0</span> <span style="color: #008080;">to</span> <span style="color: #000000;">8</span> <span style="color: #008080;">do</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">set</span><span style="color: #0000FF;">[</span><span style="color: #000000;">y</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]=</span><span style="color: #000000;">1</span> <span style="color: #008080;">then</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">sx</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">9</span> <span style="color: #008080;">do</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">sx</span><span style="color: #0000FF;">!=</span><span style="color: #000000;">k</span> <span style="color: #008080;">and</span> <span style="color: #000000;">sx</span><span style="color: #0000FF;">!=</span><span style="color: #000000;">x</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">valid</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">eliminate_in</span><span style="color: #0000FF;">(</span><span style="color: #000000;">valid</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">y</span><span style="color: #0000FF;">*</span><span style="color: #000000;">9</span><span style="color: #0000FF;">+</span><span style="color: #000000;">sx</span><span style="color: #0000FF;">},</span><span style="color: #000000;">ch</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">else</span>
<span style="color: #000000;">prevsets</span><span style="color: #0000FF;">[</span><span style="color: #000000;">x</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">set</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #000000;">prevsets</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">9</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">y</span><span style="color: #0000FF;">=</span><span style="color: #000000;">0</span> <span style="color: #008080;">to</span> <span style="color: #000000;">8</span> <span style="color: #008080;">do</span>
<span style="color: #000000;">count</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span>
<span style="color: #000000;">set</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">9</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">x</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">9</span> <span style="color: #008080;">do</span>
<span style="color: #000000;">idx</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">y</span><span style="color: #0000FF;">*</span><span style="color: #000000;">9</span><span style="color: #0000FF;">+</span><span style="color: #000000;">x</span>
<span style="color: #008080;">if</span> <span style="color: #004080;">sequence</span><span style="color: #0000FF;">(</span><span style="color: #000000;">valid</span><span style="color: #0000FF;">[</span><span style="color: #000000;">idx</span><span style="color: #0000FF;">])</span> <span style="color: #008080;">and</span> <span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #000000;">ch</span><span style="color: #0000FF;">,</span><span style="color: #000000;">valid</span><span style="color: #0000FF;">[</span><span style="color: #000000;">idx</span><span style="color: #0000FF;">])</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">set</span><span style="color: #0000FF;">[</span><span style="color: #000000;">x</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">1</span>
<span style="color: #000000;">count</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">1</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">count</span><span style="color: #0000FF;">=</span><span style="color: #000000;">2</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">k</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #000000;">set</span><span style="color: #0000FF;">,</span><span style="color: #000000;">prevsets</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">k</span><span style="color: #0000FF;">!=</span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">x</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">9</span> <span style="color: #008080;">do</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">set</span><span style="color: #0000FF;">[</span><span style="color: #000000;">x</span><span style="color: #0000FF;">]=</span><span style="color: #000000;">1</span> <span style="color: #008080;">then</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">sy</span><span style="color: #0000FF;">=</span><span style="color: #000000;">0</span> <span style="color: #008080;">to</span> <span style="color: #000000;">8</span> <span style="color: #008080;">do</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">sy</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">!=</span><span style="color: #000000;">k</span> <span style="color: #008080;">and</span> <span style="color: #000000;">sy</span><span style="color: #0000FF;">!=</span><span style="color: #000000;">y</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">valid</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">eliminate_in</span><span style="color: #0000FF;">(</span><span style="color: #000000;">valid</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">sy</span><span style="color: #0000FF;">*</span><span style="color: #000000;">9</span><span style="color: #0000FF;">+</span><span style="color: #000000;">x</span><span style="color: #0000FF;">},</span><span style="color: #000000;">ch</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">else</span>
<span style="color: #000000;">prevsets</span><span style="color: #0000FF;">[</span><span style="color: #000000;">y</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">set</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">valid</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">permitted_in</span><span style="color: #0000FF;">(</span><span style="color: #004080;">string</span> <span style="color: #000000;">board</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">sequence</span> <span style="color: #000000;">sets</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">valid</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">integer</span> <span style="color: #000000;">ch</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">9</span> <span style="color: #008080;">do</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">set</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">nines</span><span style="color: #0000FF;">[</span><span style="color: #000000;">sets</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]]</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">pos</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">j</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">9</span> <span style="color: #008080;">do</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">idx</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">set</span><span style="color: #0000FF;">[</span><span style="color: #000000;">j</span><span style="color: #0000FF;">],</span>
<span style="color: #000000;">bch</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">board</span><span style="color: #0000FF;">[</span><span style="color: #000000;">idx</span><span style="color: #0000FF;">]</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">bch</span><span style="color: #0000FF;">></span><span style="color: #008000;">'0'</span> <span style="color: #008080;">then</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">bch</span><span style="color: #0000FF;">=</span><span style="color: #000000;">ch</span> <span style="color: #008080;">then</span> <span style="color: #000000;">pos</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">1</span> <span style="color: #008080;">exit</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">elsif</span> <span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #000000;">ch</span><span style="color: #0000FF;">,</span><span style="color: #000000;">valid</span><span style="color: #0000FF;">[</span><span style="color: #000000;">idx</span><span style="color: #0000FF;">])</span> <span style="color: #008080;">then</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">pos</span><span style="color: #0000FF;">!=</span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span> <span style="color: #000000;">pos</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">1</span> <span style="color: #008080;">exit</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #000000;">pos</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">idx</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">pos</span><span style="color: #0000FF;">></span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">board</span><span style="color: #0000FF;">[</span><span style="color: #000000;">pos</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">ch</span>
<span style="color: #000000;">improved</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">1</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">board</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">enum</span> <span style="color: #000000;">INVALID</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">INCOMPLETE</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">SOLVED</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">MULTIPLE</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">2</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">BRUTE</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">3</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">plain_logic</span><span style="color: #0000FF;">(</span><span style="color: #004080;">string</span> <span style="color: #000000;">board</span><span style="color: #0000FF;">)</span>
<span style="color: #000080;font-style:italic;">--
-- Responsible for:
-- 1) cells with only one option
-- 2) numbers with only one home
--</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">solved</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">valid</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{}</span>
<span style="color: #008080;">while</span> <span style="color: #004600;">true</span> <span style="color: #008080;">do</span>
<span style="color: #000000;">solved</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">SOLVED</span>
<span style="color: #000000;">improved</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span>
<span style="color: #000000;">valid</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">deep_logic</span><span style="color: #0000FF;">(</span><span style="color: #000000;">board</span><span style="color: #0000FF;">,</span><span style="color: #000000;">valid</span><span style="color: #0000FF;">)</span>
<span style="color: #000080;font-style:italic;">-- 1) cells with only one option:</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">valid</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
<span style="color: #004080;">object</span> <span style="color: #000000;">vi</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">valid</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span>
<span style="color: #008080;">if</span> <span style="color: #004080;">string</span><span style="color: #0000FF;">(</span><span style="color: #000000;">vi</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span>
<span style="color: #008080;">if</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">vi</span><span style="color: #0000FF;">)=</span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span> <span style="color: #008080;">return</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">board</span><span style="color: #0000FF;">,{},</span><span style="color: #000000;">INVALID</span><span style="color: #0000FF;">}</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">if</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">vi</span><span style="color: #0000FF;">)=</span><span style="color: #000000;">1</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">board</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">vi</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span>
<span style="color: #000000;">improved</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">1</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">board</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]<=</span><span style="color: #008000;">'0'</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">solved</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">INCOMPLETE</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">solved</span><span style="color: #0000FF;">=</span><span style="color: #000000;">SOLVED</span> <span style="color: #008080;">then</span> <span style="color: #008080;">return</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">board</span><span style="color: #0000FF;">,{},</span><span style="color: #000000;">SOLVED</span><span style="color: #0000FF;">}</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #000080;font-style:italic;">-- 2) numbers with only one home</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">ch</span><span style="color: #0000FF;">=</span><span style="color: #008000;">'1'</span> <span style="color: #008080;">to</span> <span style="color: #008000;">'9'</span> <span style="color: #008080;">do</span>
<span style="color: #000000;">board</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">permitted_in</span><span style="color: #0000FF;">(</span><span style="color: #000000;">board</span><span style="color: #0000FF;">,</span><span style="color: #000000;">cols</span><span style="color: #0000FF;">,</span><span style="color: #000000;">valid</span><span style="color: #0000FF;">,</span><span style="color: #000000;">ch</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">board</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">permitted_in</span><span style="color: #0000FF;">(</span><span style="color: #000000;">board</span><span style="color: #0000FF;">,</span><span style="color: #000000;">rows</span><span style="color: #0000FF;">,</span><span style="color: #000000;">valid</span><span style="color: #0000FF;">,</span><span style="color: #000000;">ch</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">board</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">permitted_in</span><span style="color: #0000FF;">(</span><span style="color: #000000;">board</span><span style="color: #0000FF;">,</span><span style="color: #000000;">squares</span><span style="color: #0000FF;">,</span><span style="color: #000000;">valid</span><span style="color: #0000FF;">,</span><span style="color: #000000;">ch</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">if</span> <span style="color: #008080;">not</span> <span style="color: #000000;">improved</span> <span style="color: #008080;">then</span> <span style="color: #008080;">exit</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">while</span>
<span style="color: #008080;">return</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">board</span><span style="color: #0000FF;">,</span><span style="color: #000000;">valid</span><span style="color: #0000FF;">,</span><span style="color: #000000;">solved</span><span style="color: #0000FF;">}</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">validate</span><span style="color: #0000FF;">(</span><span style="color: #004080;">string</span> <span style="color: #000000;">board</span><span style="color: #0000FF;">)</span>
<span style="color: #000080;font-style:italic;">-- (sum9 should be sufficient - if you want, get rid of nine/nines)</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">ch</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">sum9</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">nine</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">nines</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">tagset</span><span style="color: #0000FF;">(</span><span style="color: #000000;">9</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">x</span><span style="color: #0000FF;">=</span><span style="color: #000000;">0</span> <span style="color: #008080;">to</span> <span style="color: #000000;">8</span> <span style="color: #008080;">do</span> <span style="color: #000080;font-style:italic;">-- columns</span>
<span style="color: #000000;">sum9</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span>
<span style="color: #000000;">nine</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">9</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">y</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">81</span> <span style="color: #008080;">by</span> <span style="color: #000000;">9</span> <span style="color: #008080;">do</span>
<span style="color: #000000;">ch</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">board</span><span style="color: #0000FF;">[</span><span style="color: #000000;">y</span><span style="color: #0000FF;">+</span><span style="color: #000000;">x</span><span style="color: #0000FF;">]-</span><span style="color: #008000;">'0'</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">ch</span><span style="color: #0000FF;"><</span><span style="color: #000000;">1</span> <span style="color: #008080;">or</span> <span style="color: #000000;">ch</span><span style="color: #0000FF;">></span><span style="color: #000000;">9</span> <span style="color: #008080;">then</span> <span style="color: #008080;">return</span> <span style="color: #004600;">false</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #000000;">sum9</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">ch</span>
<span style="color: #000000;">nine</span><span style="color: #0000FF;">[</span><span style="color: #000000;">ch</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">ch</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">sum9</span><span style="color: #0000FF;">!=</span><span style="color: #000000;">45</span> <span style="color: #008080;">then</span> <span style="color: #008080;">return</span> <span style="color: #004600;">false</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">nine</span><span style="color: #0000FF;">!=</span><span style="color: #000000;">nines</span> <span style="color: #008080;">then</span> <span style="color: #008080;">return</span> <span style="color: #004600;">false</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">y</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">81</span> <span style="color: #008080;">by</span> <span style="color: #000000;">9</span> <span style="color: #008080;">do</span> <span style="color: #000080;font-style:italic;">-- rows</span>
<span style="color: #000000;">sum9</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span>
<span style="color: #000000;">nine</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">9</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">x</span><span style="color: #0000FF;">=</span><span style="color: #000000;">0</span> <span style="color: #008080;">to</span> <span style="color: #000000;">8</span> <span style="color: #008080;">do</span>
<span style="color: #000000;">ch</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">board</span><span style="color: #0000FF;">[</span><span style="color: #000000;">y</span><span style="color: #0000FF;">+</span><span style="color: #000000;">x</span><span style="color: #0000FF;">]-</span><span style="color: #008000;">'0'</span>
<span style="color: #000000;">sum9</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">ch</span>
<span style="color: #000000;">nine</span><span style="color: #0000FF;">[</span><span style="color: #000000;">ch</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">ch</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">sum9</span><span style="color: #0000FF;">!=</span><span style="color: #000000;">45</span> <span style="color: #008080;">then</span> <span style="color: #008080;">return</span> <span style="color: #004600;">false</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">nine</span><span style="color: #0000FF;">!=</span><span style="color: #000000;">nines</span> <span style="color: #008080;">then</span> <span style="color: #008080;">return</span> <span style="color: #004600;">false</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">y</span><span style="color: #0000FF;">=</span><span style="color: #000000;">0</span> <span style="color: #008080;">to</span> <span style="color: #000000;">8</span> <span style="color: #008080;">by</span> <span style="color: #000000;">3</span> <span style="color: #008080;">do</span> <span style="color: #000080;font-style:italic;">-- small squares</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">x</span><span style="color: #0000FF;">=</span><span style="color: #000000;">0</span> <span style="color: #008080;">to</span> <span style="color: #000000;">8</span> <span style="color: #008080;">by</span> <span style="color: #000000;">3</span> <span style="color: #008080;">do</span>
<span style="color: #000000;">sum9</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span>
<span style="color: #000000;">nine</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">9</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">sy</span><span style="color: #0000FF;">=</span><span style="color: #000000;">y</span><span style="color: #0000FF;">*</span><span style="color: #000000;">9</span> <span style="color: #008080;">to</span> <span style="color: #000000;">y</span><span style="color: #0000FF;">*</span><span style="color: #000000;">9</span><span style="color: #0000FF;">+</span><span style="color: #000000;">18</span> <span style="color: #008080;">by</span> <span style="color: #000000;">9</span> <span style="color: #008080;">do</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">sx</span><span style="color: #0000FF;">=</span><span style="color: #000000;">x</span> <span style="color: #008080;">to</span> <span style="color: #000000;">x</span><span style="color: #0000FF;">+</span><span style="color: #000000;">2</span> <span style="color: #008080;">do</span>
<span style="color: #000000;">ch</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">board</span><span style="color: #0000FF;">[</span><span style="color: #000000;">sy</span><span style="color: #0000FF;">+</span><span style="color: #000000;">sx</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]-</span><span style="color: #008000;">'0'</span>
<span style="color: #000000;">sum9</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">ch</span>
<span style="color: #000000;">nine</span><span style="color: #0000FF;">[</span><span style="color: #000000;">ch</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">ch</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">sum9</span><span style="color: #0000FF;">!=</span><span style="color: #000000;">45</span> <span style="color: #008080;">then</span> <span style="color: #008080;">return</span> <span style="color: #004600;">false</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">nine</span><span style="color: #0000FF;">!=</span><span style="color: #000000;">nines</span> <span style="color: #008080;">then</span> <span style="color: #008080;">return</span> <span style="color: #004600;">false</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">return</span> <span style="color: #004600;">true</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">solve</span><span style="color: #0000FF;">(</span><span style="color: #004080;">string</span> <span style="color: #000000;">board</span><span style="color: #0000FF;">)</span>
<span style="color: #0000FF;">{</span><span style="color: #004080;">sequence</span> <span style="color: #000000;">solution</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">sequence</span> <span style="color: #000000;">valid</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">integer</span> <span style="color: #000000;">solved</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">plain_logic</span><span style="color: #0000FF;">(</span><span style="color: #000000;">board</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">solved</span><span style="color: #0000FF;">=</span><span style="color: #000000;">INVALID</span> <span style="color: #008080;">then</span> <span style="color: #008080;">return</span> <span style="color: #0000FF;">{{},</span><span style="color: #000000;">INVALID</span><span style="color: #0000FF;">}</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">solved</span><span style="color: #0000FF;">=</span><span style="color: #000000;">SOLVED</span> <span style="color: #008080;">then</span> <span style="color: #008080;">return</span> <span style="color: #0000FF;">{{</span><span style="color: #000000;">solution</span><span style="color: #0000FF;">},</span><span style="color: #000000;">SOLVED</span><span style="color: #0000FF;">}</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">solved</span><span style="color: #0000FF;">=</span><span style="color: #000000;">BRUTE</span> <span style="color: #008080;">then</span> <span style="color: #008080;">return</span> <span style="color: #0000FF;">{{</span><span style="color: #000000;">solution</span><span style="color: #0000FF;">},</span><span style="color: #000000;">BRUTE</span><span style="color: #0000FF;">}</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">solved</span><span style="color: #0000FF;">!=</span><span style="color: #000000;">INCOMPLETE</span> <span style="color: #008080;">then</span> <span style="color: #0000FF;">?</span><span style="color: #000000;">9</span><span style="color: #0000FF;">/</span><span style="color: #000000;">0</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #000080;font-style:italic;">-- find the cell with the fewest options:
-- (a possible improvement here would be to select the shortest
-- with the "most pairs" set, see swordfish etc above.)</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">minopt</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">10</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">mindx</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">9</span><span style="color: #0000FF;">*</span><span style="color: #000000;">9</span> <span style="color: #008080;">do</span>
<span style="color: #004080;">object</span> <span style="color: #000000;">vi</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">valid</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span>
<span style="color: #008080;">if</span> <span style="color: #004080;">string</span><span style="color: #0000FF;">(</span><span style="color: #000000;">vi</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span>
<span style="color: #008080;">if</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">vi</span><span style="color: #0000FF;">)<=</span><span style="color: #000000;">1</span> <span style="color: #008080;">then</span> <span style="color: #0000FF;">?</span><span style="color: #000000;">9</span><span style="color: #0000FF;">/</span><span style="color: #000000;">0</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span> <span style="color: #000080;font-style:italic;">-- should be caught above</span>
<span style="color: #008080;">if</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">vi</span><span style="color: #0000FF;">)<</span><span style="color: #000000;">minopt</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">minopt</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">vi</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">mindx</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">i</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">solutions</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{}</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">minopt</span> <span style="color: #008080;">do</span>
<span style="color: #000000;">board</span><span style="color: #0000FF;">[</span><span style="color: #000000;">mindx</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">valid</span><span style="color: #0000FF;">[</span><span style="color: #000000;">mindx</span><span style="color: #0000FF;">][</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span>
<span style="color: #0000FF;">{</span><span style="color: #000000;">solution</span><span style="color: #0000FF;">,</span><span style="color: #000000;">solved</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">solve</span><span style="color: #0000FF;">(</span><span style="color: #000000;">board</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">solved</span><span style="color: #0000FF;">=</span><span style="color: #000000;">MULTIPLE</span> <span style="color: #008080;">then</span>
<span style="color: #008080;">return</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">solution</span><span style="color: #0000FF;">,</span><span style="color: #000000;">MULTIPLE</span><span style="color: #0000FF;">}</span>
<span style="color: #008080;">elsif</span> <span style="color: #000000;">solved</span><span style="color: #0000FF;">=</span><span style="color: #000000;">SOLVED</span>
<span style="color: #008080;">or</span> <span style="color: #000000;">solved</span><span style="color: #0000FF;">=</span><span style="color: #000000;">BRUTE</span> <span style="color: #008080;">then</span>
<span style="color: #008080;">if</span> <span style="color: #008080;">not</span> <span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #000000;">solution</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">],</span><span style="color: #000000;">solutions</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">and</span> <span style="color: #000000;">validate</span><span style="color: #0000FF;">(</span><span style="color: #000000;">solution</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">])</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">solutions</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">append</span><span style="color: #0000FF;">(</span><span style="color: #000000;">solutions</span><span style="color: #0000FF;">,</span><span style="color: #000000;">solution</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">])</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">if</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">solutions</span><span style="color: #0000FF;">)></span><span style="color: #000000;">1</span> <span style="color: #008080;">then</span>
<span style="color: #008080;">return</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">solutions</span><span style="color: #0000FF;">,</span><span style="color: #000000;">MULTIPLE</span><span style="color: #0000FF;">}</span>
<span style="color: #008080;">elsif</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">solutions</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span>
<span style="color: #008080;">return</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">solutions</span><span style="color: #0000FF;">,</span><span style="color: #000000;">BRUTE</span><span style="color: #0000FF;">}</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">if</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">solutions</span><span style="color: #0000FF;">)=</span><span style="color: #000000;">1</span> <span style="color: #008080;">then</span>
<span style="color: #008080;">return</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">solutions</span><span style="color: #0000FF;">,</span><span style="color: #000000;">BRUTE</span><span style="color: #0000FF;">}</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">return</span> <span style="color: #0000FF;">{{},</span><span style="color: #000000;">INVALID</span><span style="color: #0000FF;">}</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">test_one</span><span style="color: #0000FF;">(</span><span style="color: #004080;">string</span> <span style="color: #000000;">board</span><span style="color: #0000FF;">)</span>
<span style="color: #0000FF;">{</span><span style="color: #004080;">sequence</span> <span style="color: #000000;">solutions</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">integer</span> <span style="color: #000000;">solved</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">solve</span><span style="color: #0000FF;">(</span><span style="color: #000000;">board</span><span style="color: #0000FF;">)</span>
<span style="color: #004080;">string</span> <span style="color: #000000;">solution</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">desc</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">solved</span><span style="color: #0000FF;">=</span><span style="color: #000000;">SOLVED</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">desc</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">"(logic)"</span>
<span style="color: #008080;">elsif</span> <span style="color: #000000;">solved</span><span style="color: #0000FF;">=</span><span style="color: #000000;">BRUTE</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">desc</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">"(brute force)"</span>
<span style="color: #008080;">else</span>
<span style="color: #000000;">desc</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">"???"</span> <span style="color: #000080;font-style:italic;">-- INVALID/INCOMPLETE/MULTIPLE</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">if</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">solutions</span><span style="color: #0000FF;">)=</span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">solution</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">board</span>
<span style="color: #000000;">desc</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">"*** NO SOLUTIONS ***"</span>
<span style="color: #008080;">elsif</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">solutions</span><span style="color: #0000FF;">)=</span><span style="color: #000000;">1</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">solution</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">solutions</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span>
<span style="color: #008080;">if</span> <span style="color: #008080;">not</span> <span style="color: #000000;">validate</span><span style="color: #0000FF;">(</span><span style="color: #000000;">solution</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">desc</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">"*** ERROR ***"</span> <span style="color: #000080;font-style:italic;">-- (should never happen)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">else</span>
<span style="color: #000000;">solution</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">board</span>
<span style="color: #000000;">desc</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">"*** MULTIPLE SOLUTIONS ***"</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">return</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">solution</span><span style="color: #0000FF;">,</span><span style="color: #000000;">desc</span><span style="color: #0000FF;">}</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #000080;font-style:italic;">--NB Blank cells can be represented by any character &lt;'1'. Spaces are not recommended since
-- they can all too easily be converted to tabs by copy/paste/save. In particular, ? and
-- _ are NOT valid characters for representing a blank square. Use any of .0-* instead.</span>
<span style="color: #008080;">constant</span> <span style="color: #000000;">tests</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span>
<span style="color: #008000;">"..............3.85..1.2.......5.7.....4...1...9.......5......73..2.1........4...9"</span><span style="color: #0000FF;">,</span> <span style="color: #000080;font-style:italic;">-- (0.01s, (logic))
-- row/col elimination (was 8s w/o logic first)</span>
<span style="color: #008000;">"000000036840000000000000020000203000010000700000600400000410050003000200600000000"</span><span style="color: #0000FF;">,</span> <span style="color: #000080;font-style:italic;">-- (0.04s, (brute force))</span>
<span style="color: #008000;">".......39.....1..5..3.5.8....8.9...6.7...2...1..4.......9.8..5..2....6..4..7....."</span><span style="color: #0000FF;">,</span> <span style="color: #000080;font-style:italic;">-- (1.12s, (brute force))</span>
<span style="color: #008000;">"000037600000600090008000004090000001600000009300000040700000800010009000002540000"</span><span style="color: #0000FF;">,</span> <span style="color: #000080;font-style:italic;">-- (0.00s, (logic))</span>
<span style="color: #008000;">"....839..1......3...4....7..42.3....6.......4....7..1..2........8...92.....25...6"</span><span style="color: #0000FF;">,</span> <span style="color: #000080;font-style:italic;">-- (0.04s, (brute force))</span>
<span style="color: #008000;">"..1..5.7.92.6.......8...6...9..2.4.1.........3.4.8..9...7...3.......7.69.1.8..7.."</span><span style="color: #0000FF;">,</span> <span style="color: #000080;font-style:italic;">-- (0.00s, (logic))
-- (the following takes ~8s when checking for multiple solutions)</span>
<span style="color: #008000;">"--3------4---8--36--8---1---4--6--73---9----------2--5--4-7--686--------7--6--5--"</span><span style="color: #0000FF;">,</span> <span style="color: #000080;font-style:italic;">-- (0.01s, (brute force))</span>
<span style="color: #008000;">"..3.2.6..9..3.5..1..18.64....81.29..7.......8..67.82....26.95..8..2.3..9..5.1.3.."</span><span style="color: #0000FF;">,</span> <span style="color: #000080;font-style:italic;">-- (0.00s, (logic))</span>
<span style="color: #008000;">"--4-5--6--6-1--8-93----7----8----5-----4-3-----6----7----2----61-5--4-3--2--7-1--"</span><span style="color: #0000FF;">,</span> <span style="color: #000080;font-style:italic;">-- (0.00s, (logic))
-- x-wings</span>
<span style="color: #008000;">".4398.25.6..425...2....1.949....4.7.3..6.8...41.2.9..382.5.........4...553489.71."</span><span style="color: #0000FF;">,</span> <span style="color: #000080;font-style:italic;">-- (0.00s, (logic))</span>
<span style="color: #008000;">".9...4..7.....79..8........4.58.....3.......2.....97.6........4..35.....2..6...8."</span><span style="color: #0000FF;">,</span> <span style="color: #000080;font-style:italic;">-- (0.00s, (logic))
-- "AL Escargot", so-called "hardest sudoku"</span>
<span style="color: #008000;">"1....7.9..3..2...8..96..5....53..9...1..8...26....4...3......1..4......7..7...3.."</span><span style="color: #0000FF;">,</span> <span style="color: #000080;font-style:italic;">-- (0.26s, (brute force))</span>
<span style="color: #008000;">"12.3....435....1....4........54..2..6...7.........8.9...31..5.......9.7.....6...8"</span><span style="color: #0000FF;">,</span> <span style="color: #000080;font-style:italic;">-- (0.48s, (brute force))</span>
<span style="color: #008000;">"12.4..3..3...1..5...6...1..7...9.....4.6.3.....3..2...5...8.7....7.....5.......98"</span><span style="color: #0000FF;">,</span> <span style="color: #000080;font-style:italic;">-- (1.07s, (brute force))</span>
<span style="color: #008000;">"394..267....3..4..5..69..2..45...9..6.......7..7...58..1..67..8..9..8....264..735"</span><span style="color: #0000FF;">,</span> <span style="color: #000080;font-style:italic;">-- (0.00s, (logic))</span>
<span style="color: #008000;">"4......6.5...8.9..3....1....2.7....1.9.....4.8....3.5....2....7..6.5...8.1......6"</span><span style="color: #0000FF;">,</span> <span style="color: #000080;font-style:italic;">-- (0.01s, (brute force))</span>
<span style="color: #008000;">"5...7....6..195....98....6.8...6...34..8.3..17...2...6.6....28....419..5....8..79"</span><span style="color: #0000FF;">,</span> <span style="color: #000080;font-style:italic;">-- (0.00s, (logic))</span>
<span style="color: #008000;">"503600009010002600900000080000700005006804100200003000030000008004300050800006702"</span><span style="color: #0000FF;">,</span> <span style="color: #000080;font-style:italic;">-- (0.00s, (logic))</span>
<span style="color: #008000;">"53..247....2...8..1..7.39.2..8.72.49.2.98..7.79.....8.....3.5.696..1.3...5.69..1."</span><span style="color: #0000FF;">,</span> <span style="color: #000080;font-style:italic;">-- (0.00s, (logic))</span>
<span style="color: #008000;">"530070000600195000098000060800060003400803001700020006060000280000419005000080079"</span><span style="color: #0000FF;">,</span> <span style="color: #000080;font-style:italic;">-- (0.00s, (logic))
-- set exclusion</span>
<span style="color: #008000;">"75..9..46961...3524.....79.2..6.1..7.8.....2.1..328.65.........3.9...2.484..3..79"</span><span style="color: #0000FF;">,</span> <span style="color: #000080;font-style:italic;">-- (0.00s, (logic))
-- Worlds hardest sudoku:</span>
<span style="color: #008000;">"800000000003600000070090200050007000000045700000100030001000068008500010090000400"</span><span style="color: #0000FF;">,</span> <span style="color: #000080;font-style:italic;">-- (0.21s, (brute force))</span>
<span style="color: #008000;">"819--5-----2---75--371-4-6-4--59-1--7--3-8--2--3-62--7-5-7-921--64---9-----2--438"</span><span style="color: #0000FF;">,</span> <span style="color: #000080;font-style:italic;">-- (0.00s, (logic))</span>
<span style="color: #008000;">"85...24..72......9..4.........1.7..23.5...9...4...........8..7..17..........36.4."</span><span style="color: #0000FF;">,</span> <span style="color: #000080;font-style:italic;">-- (0.01s, (logic))</span>
<span style="color: #008000;">"9..2..5...4..6..3...3.....6...9..2......5..8...7..4..37.....1...5..2..4...1..6..9"</span><span style="color: #0000FF;">,</span> <span style="color: #000080;font-style:italic;">-- (0.17s, (brute force))</span>
<span style="color: #008000;">"97.3...6..6.75.........8.5.......67.....3.....539..2..7...25.....2.1...8.4...73.."</span><span style="color: #0000FF;">,</span> <span style="color: #000080;font-style:italic;">-- (0.00s, (logic))
-- "the beast" (an earlier algorithm took 318s (5min 18s) on this):</span>
<span style="color: #008000;">"000060080020000000001000000070000102500030000000000400004201000300700600000000050"</span><span style="color: #0000FF;">,</span> <span style="color: #000080;font-style:italic;">-- (0.03s, (brute force))</span>
<span style="color: #0000FF;">$},</span>
<span style="color: #000000;">lt</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">tests</span><span style="color: #0000FF;">),</span>
<span style="color: #000000;">run_one_test</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span>
<span style="color: #008080;">constant</span> <span style="color: #000000;">l</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">" x x x | x x x | x x x "</span><span style="color: #0000FF;">,</span>
<span style="color: #000000;">s</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">"-------+-------+-------"</span><span style="color: #0000FF;">,</span>
<span style="color: #000000;">l3</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">join</span><span style="color: #0000FF;">({</span><span style="color: #000000;">l</span><span style="color: #0000FF;">,</span><span style="color: #000000;">l</span><span style="color: #0000FF;">,</span><span style="color: #000000;">l</span><span style="color: #0000FF;">},</span><span style="color: #008000;">"\n"</span><span style="color: #0000FF;">),</span>
<span style="color: #000000;">fmt</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">substitute</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">join</span><span style="color: #0000FF;">({</span><span style="color: #000000;">l3</span><span style="color: #0000FF;">,</span><span style="color: #000000;">s</span><span style="color: #0000FF;">,</span><span style="color: #000000;">l3</span><span style="color: #0000FF;">,</span><span style="color: #000000;">s</span><span style="color: #0000FF;">,</span><span style="color: #000000;">l3</span><span style="color: #0000FF;">},</span><span style="color: #008000;">"\n"</span><span style="color: #0000FF;">),</span><span style="color: #008000;">"x"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"%c"</span><span style="color: #0000FF;">)&</span><span style="color: #008000;">"\n"</span>
<span style="color: #008080;">procedure</span> <span style="color: #000000;">test</span><span style="color: #0000FF;">()</span>
<span style="color: #004080;">string</span> <span style="color: #000000;">board</span><span style="color: #0000FF;">,</span> <span style="color: #000080;font-style:italic;">-- (81 characters)</span>
<span style="color: #000000;">solution</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">desc</span>
<span style="color: #004080;">atom</span> <span style="color: #000000;">t0</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">time</span><span style="color: #0000FF;">()</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">run_one_test</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">board</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">tests</span><span style="color: #0000FF;">[</span><span style="color: #000000;">run_one_test</span><span style="color: #0000FF;">]</span>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">fmt</span><span style="color: #0000FF;">,</span><span style="color: #000000;">board</span><span style="color: #0000FF;">)</span>
<span style="color: #0000FF;">{</span><span style="color: #000000;">solution</span><span style="color: #0000FF;">,</span><span style="color: #000000;">desc</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">test_one</span><span style="color: #0000FF;">(</span><span style="color: #000000;">board</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">if</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">solution</span><span style="color: #0000FF;">)!=</span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"solution:\n"</span><span style="color: #0000FF;">)</span>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">fmt</span><span style="color: #0000FF;">,</span><span style="color: #000000;">solution</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"%s, %3.2fs\n"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">desc</span><span style="color: #0000FF;">,</span><span style="color: #7060A8;">time</span><span style="color: #0000FF;">()-</span><span style="color: #000000;">t0</span><span style="color: #0000FF;">})</span>
<span style="color: #008080;">else</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">lt</span> <span style="color: #008080;">do</span>
<span style="color: #004080;">atom</span> <span style="color: #000000;">t1</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">time</span><span style="color: #0000FF;">()</span>
<span style="color: #000000;">board</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">tests</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span>
<span style="color: #0000FF;">{</span><span style="color: #000000;">solution</span><span style="color: #0000FF;">,</span><span style="color: #000000;">desc</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">test_one</span><span style="color: #0000FF;">(</span><span style="color: #000000;">board</span><span style="color: #0000FF;">)</span>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">" \"%s\", -- (%3.2fs, %s)\n"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">board</span><span style="color: #0000FF;">,</span><span style="color: #7060A8;">time</span><span style="color: #0000FF;">()-</span><span style="color: #000000;">t1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">desc</span><span style="color: #0000FF;">})</span>
<span style="color: #000080;font-style:italic;">-- printf(1," \"%s\", -- (%3.2fs, %s)\n",{solution,time()-t1,desc})</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #000000;">t0</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">time</span><span style="color: #0000FF;">()-</span><span style="color: #000000;">t0</span>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"%d puzzles solved in %3.2fs (av %3.2fs)\n"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">lt</span><span style="color: #0000FF;">,</span><span style="color: #000000;">t0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">t0</span><span style="color: #0000FF;">/</span><span style="color: #000000;">lt</span><span style="color: #0000FF;">})</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span>
<span style="color: #000000;">test</span><span style="color: #0000FF;">()</span>
<!--</syntaxhighlight>-->
{{out}}
<pre>
"..............3.85..1.2.......5.7.....4...1...9.......5......73..2.1........4...9", -- (0.02s, (logic))
"000000036840000000000000020000203000010000700000600400000410050003000200600000000", -- (0.03s, (brute force))
".......39.....1..5..3.5.8....8.9...6.7...2...1..4.......9.8..5..2....6..4..7.....", -- (1.31s, (brute force))
"000037600000600090008000004090000001600000009300000040700000800010009000002540000", -- (0.00s, (logic))
"....839..1......3...4....7..42.3....6.......4....7..1..2........8...92.....25...6", -- (0.03s, (brute force))
"..1..5.7.92.6.......8...6...9..2.4.1.........3.4.8..9...7...3.......7.69.1.8..7..", -- (0.00s, (logic))
"--3------4---8--36--8---1---4--6--73---9----------2--5--4-7--686--------7--6--5--", -- (0.03s, (brute force))
"..3.2.6..9..3.5..1..18.64....81.29..7.......8..67.82....26.95..8..2.3..9..5.1.3..", -- (0.00s, (logic))
"--4-5--6--6-1--8-93----7----8----5-----4-3-----6----7----2----61-5--4-3--2--7-1--", -- (0.01s, (logic))
".4398.25.6..425...2....1.949....4.7.3..6.8...41.2.9..382.5.........4...553489.71.", -- (0.00s, (logic))
".9...4..7.....79..8........4.58.....3.......2.....97.6........4..35.....2..6...8.", -- (0.00s, (logic))
"1....7.9..3..2...8..96..5....53..9...1..8...26....4...3......1..4......7..7...3..", -- (0.26s, (brute force))
"12.3....435....1....4........54..2..6...7.........8.9...31..5.......9.7.....6...8", -- (0.40s, (brute force))
"12.4..3..3...1..5...6...1..7...9.....4.6.3.....3..2...5...8.7....7.....5.......98", -- (1.12s, (brute force))
"394..267....3..4..5..69..2..45...9..6.......7..7...58..1..67..8..9..8....264..735", -- (0.00s, (logic))
"4......6.5...8.9..3....1....2.7....1.9.....4.8....3.5....2....7..6.5...8.1......6", -- (0.03s, (brute force))
"5...7....6..195....98....6.8...6...34..8.3..17...2...6.6....28....419..5....8..79", -- (0.00s, (logic))
"503600009010002600900000080000700005006804100200003000030000008004300050800006702", -- (0.01s, (logic))
"53..247....2...8..1..7.39.2..8.72.49.2.98..7.79.....8.....3.5.696..1.3...5.69..1.", -- (0.00s, (logic))
"530070000600195000098000060800060003400803001700020006060000280000419005000080079", -- (0.00s, (logic))
"75..9..46961...3524.....79.2..6.1..7.8.....2.1..328.65.........3.9...2.484..3..79", -- (0.01s, (logic))
"800000000003600000070090200050007000000045700000100030001000068008500010090000400", -- (0.21s, (brute force))
"819--5-----2---75--371-4-6-4--59-1--7--3-8--2--3-62--7-5-7-921--64---9-----2--438", -- (0.00s, (logic))
"85...24..72......9..4.........1.7..23.5...9...4...........8..7..17..........36.4.", -- (0.01s, (logic))
"9..2..5...4..6..3...3.....6...9..2......5..8...7..4..37.....1...5..2..4...1..6..9", -- (0.18s, (brute force))
"97.3...6..6.75.........8.5.......67.....3.....539..2..7...25.....2.1...8.4...73..", -- (0.00s, (logic))
"000060080020000000001000000070000102500030000000000400004201000300700600000000050", -- (0.01s, (brute force))
27 puzzles solved in 3.74s (av 0.14s)
</pre>
Running the fuller version mentioned above:
<pre>
"008002000000600040064000092017005004200000008800100730470000910080001000000900200", -- (0.05s, *** MULTIPLE SOLUTIONS ***)
338 puzzles solved in 36.20s (av 0.11s)
--or
338 puzzles solved in 16.46s (av 0.05s) (w/o check for multiple solutions)
</pre>
Running a single puzzle (run_one_test set non-zero) produces:
<pre>
. . . | . . . | . . .
. . . | . . 3 | . 8 5
. . 1 | . 2 . | . . .
-------+-------+-------
. . . | 5 . 7 | . . .
. . 4 | . . . | 1 . .
. 9 . | . . . | . . .
-------+-------+-------
5 . . | . . . | . 7 3
. . 2 | . 1 . | . . .
. . . | . 4 . | . . 9
solution:
9 8 7 | 6 5 4 | 3 2 1
2 4 6 | 1 7 3 | 9 8 5
3 5 1 | 9 2 8 | 7 4 6
-------+-------+-------
1 2 8 | 5 3 7 | 6 9 4
6 3 4 | 8 9 2 | 1 5 7
7 9 5 | 4 6 1 | 8 3 2
-------+-------+-------
5 1 9 | 2 8 6 | 4 7 3
4 7 2 | 3 1 9 | 5 6 8
8 6 3 | 7 4 5 | 2 1 9
(logic), 0.02s
</pre>
 
=={{header|PHP}}==
{{trans|C++}}
<syntaxhighlight lang="php"> class SudokuSolver {
protected $grid = [];
protected $emptySymbol;
public static function parseString($str, $emptySymbol = '0')
{
$grid = str_split($str);
foreach($grid as &$v)
{
if($v == $emptySymbol)
{
$v = 0;
}
else
{
$v = (int)$v;
}
}
return $grid;
}
public function __construct($str, $emptySymbol = '0') {
if(strlen($str) !== 81)
{
throw new \Exception('Error sudoku');
}
$this->grid = static::parseString($str, $emptySymbol);
$this->emptySymbol = $emptySymbol;
}
public function solve()
{
try
{
$this->placeNumber(0);
return false;
}
catch(\Exception $e)
{
return true;
}
}
protected function placeNumber($pos)
{
if($pos == 81)
{
throw new \Exception('Finish');
}
if($this->grid[$pos] > 0)
{
$this->placeNumber($pos+1);
return;
}
for($n = 1; $n <= 9; $n++)
{
if($this->checkValidity($n, $pos%9, floor($pos/9)))
{
$this->grid[$pos] = $n;
$this->placeNumber($pos+1);
$this->grid[$pos] = 0;
}
}
}
protected function checkValidity($val, $x, $y)
{
for($i = 0; $i < 9; $i++)
{
if(($this->grid[$y*9+$i] == $val) || ($this->grid[$i*9+$x] == $val))
{
return false;
}
}
$startX = (int) ((int)($x/3)*3);
$startY = (int) ((int)($y/3)*3);
 
for($i = $startY; $i<$startY+3;$i++)
{
for($j = $startX; $j<$startX+3;$j++)
{
if($this->grid[$i*9+$j] == $val)
{
return false;
}
}
}
return true;
}
 
public function display() {
$str = '';
for($i = 0; $i<9; $i++)
{
for($j = 0; $j<9;$j++)
{
$str .= $this->grid[$i*9+$j];
$str .= " ";
if($j == 2 || $j == 5)
{
$str .= "| ";
}
}
$str .= PHP_EOL;
if($i == 2 || $i == 5)
{
$str .= "------+-------+------".PHP_EOL;
}
}
echo $str;
}
public function __toString() {
foreach ($this->grid as &$item)
{
if($item == 0)
{
$item = $this->emptySymbol;
}
}
return implode('', $this->grid);
}
}
$solver = new SudokuSolver('009170000020600001800200000200006053000051009005040080040000700006000320700003900');
$solver->solve();
$solver->display();</syntaxhighlight>
{{out}}
<pre>
3 6 9 | 1 7 5 | 8 4 2
4 2 7 | 6 8 9 | 5 3 1
8 5 1 | 2 3 4 | 6 9 7
------+-------+------
2 1 8 | 7 9 6 | 4 5 3
6 3 4 | 8 5 1 | 2 7 9
9 7 5 | 3 4 2 | 1 8 6
------+-------+------
1 4 3 | 9 2 8 | 7 6 5
5 9 6 | 4 1 7 | 3 2 8
7 8 2 | 5 6 3 | 9 1 4
(solved in 0.027s)
</pre>
 
=={{header|Picat}}==
Using constraint programming.
 
<syntaxhighlight lang="picat">import util.
import cp.
 
main => go.
 
go =>
sudokus(Sudokus),
foreach([Comment,SudokuS] in Sudokus)
println(SudokuS),
println(Comment),
% Convert string to numbers and "." to _ (unknown)
Sudoku = [ [cond(S == '.',_,S.to_integer()) :
S in slice(SudokuS,(I*9)+1,(I+1)*9)] : I in 0..8],
print_board(Sudoku),
% Ensure unicity of the solution (check that it is a unique solution)
All = findall(Sudoku,sudoku(Sudoku)),
if All.length > 1 then
printf("Problem has %d solutions!\n", All.length)
end,
print("Solution:")
foreach(A in All)
print_board(A)
end,
nl
end,
nl.
 
sudoku(Board) =>
N = ceiling(sqrt(Board.len)),
N2 = N*N,
Vars = Board.vars(),
Vars :: 1..N2,
foreach(Row in Board) all_different(Row) end,
foreach(Column in transpose(Board)) all_different(Column) end,
foreach(I in 1..N..N2, J in 1..N..N2)
all_different([Board[I+K,J+L] : K in 0..N-1, L in 0..N-1])
end,
solve([ffd,inout], Vars).
 
print_board(Board) =>
N = Board.length,
foreach(I in 1..N)
foreach(J in 1..N)
X = Board[I,J],
if var(X) then printf(" _") else printf(" %w", X) end
end,
nl
end,
nl.
 
% (Problems from the Groovy implementation)
sudokus(Sudokus) => Sudokus =
[
"819..5.....2...75..371.4.6.4..59.1..7..3.8..2..3.62..7.5.7.921..64...9.....2..438",
"53..247....2...8..1..7.39.2..8.72.49.2.98..7.79.....8.....3.5.696..1.3...5.69..1.",
"..3.2.6..9..3.5..1..18.64....81.29..7.......8..67.82....26.95..8..2.3..9..5.1.3..",
"394..267....3..4..5..69..2..45...9..6.......7..7...58..1..67..8..9..8....264..735",
"97.3...6..6.75.........8.5.......67.....3.....539..2..7...25.....2.1...8.4...73..",
"4......6.5...8.9..3....1....2.7....1.9.....4.8....3.5....2....7..6.5...8.1......6",
"85...24..72......9..4.........1.7..23.5...9...4...........8..7..17..........36.4.",
"..1..5.7.92.6.......8...6...9..2.4.1.........3.4.8..9...7...3.......7.69.1.8..7..",
".9...4..7.....79..8........4.58.....3.......2.....97.6........4..35.....2..6...8.",
"12.3....435....1....4........54..2..6...7.........8.9...31..5.......9.7.....6...8",
"9..2..5...4..6..3...3.....6...9..2......5..8...7..4..37.....1...5..2..4...1..6..9",
"1....7.9..3..2...8..96..5....53..9...1..8...26....4...3......1..4......7..7...3..",
"12.4..3..3...1..5...6...1..7...9.....4.6.3.....3..2...5...8.7....7.....5.......98",
"..............3.85..1.2.......5.7.....4...1...9.......5......73..2.1........4...9",
".......39.....1..5..3.5.8....8.9...6.7...2...1..4.......9.8..5..2....6..4..7.....",
"....839..1......3...4....7..42.3....6.......4....7..1..2........8...92.....25...6",
"..3......4...8..36..8...1...4..6..73...9..........2..5..4.7..686........7..6..5.."
].</syntaxhighlight>
 
{{out}}
All problems are solved (and proved/checked for unicity) in 0.043s.
<pre>
819..5.....2...75..371.4.6.4..59.1..7..3.8..2..3.62..7.5.7.921..64...9.....2..438
8 1 9 _ _ 5 _ _ _
_ _ 2 _ _ _ 7 5 _
_ 3 7 1 _ 4 _ 6 _
4 _ _ 5 9 _ 1 _ _
7 _ _ 3 _ 8 _ _ 2
_ _ 3 _ 6 2 _ _ 7
_ 5 _ 7 _ 9 2 1 _
_ 6 4 _ _ _ 9 _ _
_ _ _ 2 _ _ 4 3 8
 
Solution:
8 1 9 6 7 5 3 2 4
6 4 2 9 8 3 7 5 1
5 3 7 1 2 4 8 6 9
4 2 6 5 9 7 1 8 3
7 9 5 3 1 8 6 4 2
1 8 3 4 6 2 5 9 7
3 5 8 7 4 9 2 1 6
2 6 4 8 3 1 9 7 5
9 7 1 2 5 6 4 3 8
 
...
 
</pre>
 
=={{header|PicoLisp}}==
<langsyntaxhighlight PicoLisplang="picolisp">(load "lib/simul.l")
 
### Fields/Board ###
Line 3,455 ⟶ 9,536:
(0 6 0 0 0 0 2 8 0)
(0 0 0 4 1 9 0 0 5)
(0 0 0 0 8 0 0 7 9) ) )</langsyntaxhighlight>
{{out}}
Output:
<pre> +---+---+---+---+---+---+---+---+---+
9 | 5 3 | 7 | |
Line 3,477 ⟶ 9,558:
+---+---+---+---+---+---+---+---+---+
a b c d e f g h i</pre>
<syntaxhighlight lang PicoLisp="picolisp">(go)</langsyntaxhighlight>
{{out}}
Output:
<pre> +---+---+---+---+---+---+---+---+---+
9 | 5 3 4 | 6 7 8 | 9 1 2 |
Line 3,499 ⟶ 9,580:
+---+---+---+---+---+---+---+---+---+
a b c d e f g h i</pre>
 
=={{header|PL/I}}==
Working PL/I version, derived from the Rosetta Fortran version.
<syntaxhighlight lang="pli">sudoku: procedure options (main); /* 27 July 2014 */
 
declare grid (9,9) fixed (1) static initial (
0, 0, 3, 0, 2, 0, 6, 0, 0,
9, 0, 0, 3, 0, 5, 0, 0, 1,
0, 0, 1, 8, 0, 6, 4, 0, 0,
0, 0, 8, 1, 0, 2, 9, 0, 0,
7, 0, 0, 0, 0, 0, 0, 0, 8,
0, 0, 6, 7, 0, 8, 2, 0, 0,
0, 0, 2, 6, 0, 9, 5, 0, 0,
8, 0, 0, 2, 0, 3, 0, 0, 9,
0, 0, 5, 0, 1, 0, 3, 0, 0 );
 
declare grid_solved (9,9) fixed (1);
 
call print_sudoku (grid);
call solve (1, 1);
put skip (2);
call print_sudoku (grid_solved);
 
solve: procedure (i, j) recursive options (reorder);
declare (i, j) fixed binary;
declare (n, n_tmp) fixed binary;
 
if i > 9 then
grid_solved = grid;
else
do n = 1 to 9;
if is_safe (i, j, n) then
do;
n_tmp = grid (i, j);
grid (i, j) = n;
if j = 9 then
call solve (i + 1, 1);
else
call solve (i, j + 1);
grid (i, j) = n_tmp;
end;
end;
 
end solve;
 
is_safe: procedure (i, j, n) returns (bit(1) aligned) options (reorder);
declare (i, j, n) fixed binary;
declare (true value ('1'b), false value ('0'b) ) bit (1);
declare (i_min, j_min, ii, jj) fixed binary;
declare kk bit(1) aligned;
 
if grid (i, j) = n then return (true);
if grid (i, j) ^= 0 then return (false);
if any (grid (i, *) = n) then return (false);
if any (grid (*, j) = n) then return (false);
 
/* i_min and j_min are the co-ordinates of the top left-hand corner */
/* of 3 x 3 grid in which element (i,j) exists. */
i_min = 1 + 3 * trunc((i - 1) / 3);
j_min = 1 + 3 * trunc((j - 1) / 3);
 
begin;
declare sub_grid(3,3) fixed (1) defined grid(1sub+i_min-1,2sub+j_min-1);
 
kk = true;
if any(sub_grid = n) then kk = false;
end;
return (kk);
end is_safe;
 
print_sudoku: procedure (grid);
declare grid (*,*) fixed (1);
declare ( i, j, ii) fixed binary;
declare bar character (19) initial ( '+-----+-----+-----+' );
declare frame (9) character (1) initial (' ', ' ', '|', ' ', ' ', '|', ' ', ' ', '|' );
 
put skip list (bar);
do i = 1 to 7 by 3;
do ii = i to i + 2;
put skip edit ( '|', (grid (ii, j), frame(j) do j = 1 to 9) ) (a, f(1));
end;
put skip list (bar);
end;
end print_sudoku;
 
end sudoku;
</syntaxhighlight>
{{out}}
<pre>
+-----+-----+-----+
|0 0 3|0 2 0|6 0 0|
|9 0 0|3 0 5|0 0 1|
|0 0 1|8 0 6|4 0 0|
+-----+-----+-----+
|0 0 8|1 0 2|9 0 0|
|7 0 0|0 0 0|0 0 8|
|0 0 6|7 0 8|2 0 0|
+-----+-----+-----+
|0 0 2|6 0 9|5 0 0|
|8 0 0|2 0 3|0 0 9|
|0 0 5|0 1 0|3 0 0|
+-----+-----+-----+
 
 
+-----+-----+-----+
|4 8 3|9 2 1|6 5 7|
|9 6 7|3 4 5|8 2 1|
|2 5 1|8 7 6|4 9 3|
+-----+-----+-----+
|5 4 8|1 3 2|9 7 6|
|7 2 9|5 6 4|1 3 8|
|1 3 6|7 9 8|2 4 5|
+-----+-----+-----+
|3 7 2|6 8 9|5 1 4|
|8 1 4|2 5 3|7 6 9|
|6 9 5|4 1 7|3 8 2|
+-----+-----+-----+
</pre>
 
Another PL/I version, reads sudoku from the text data file as 81 character record.
<syntaxhighlight lang="pli">
*PROCESS MARGINS(1,120) LIBS(SINGLE,STATIC);
*PROCESS OPTIMIZE(2) DFT(REORDER);
 
 
sudoku: proc(parms) options(main);
dcl parms char (100) var;
 
define alias bits bit (9) aligned;
dcl total (81) type bits;
dcl matrix (9, 9) type bits based(addr(total));
dcl box (9, 3, 3) type bits defined (total(trunc((1sub-1) /3) * 27 + mod(1sub-1, 3) * 3 + (2sub-1) * 9 + 3sub));
 
dcl posbit (0:9) type bits init('000000000'b, '100000000'b, '010000000'b, '001000000'b,
'000100000'b, '000010000'b, '000001000'b, '000000100'b,
'000000010'b, '000000001'b);
 
dcl (i, j, k) fixed bin(31);
dcl (start, finish) float(18);
dcl result fixed dec(5,3);
 
dcl buffer char(81);
dcl in file;
 
/* ON UNIT for the Sudoku data conversion */
on conversion
begin;
put skip
list('Sudoku data not valid.');
stop;
end;
 
/* ON UNIT to display info about the usage */
on undefinedfile(in)
begin;
put skip
list('Usage: ' || procedurename() || ' /filename');
stop;
end;
 
open file(in)
title ('/'||parms||',type(fixed), recsize(81)') record input;
 
/* Ignore the endfile condition */
on endfile(in);
 
/* Read the Sudoku data into buffer as one record */
read file(in) into(buffer);
close file(in);
 
/* Convert numbers -> position bit presentation and assign into the Sudoku board */
do k = 1 to 81;
total(k) = posbit(substr(buffer, k, 1));
end;
 
/* Start solving the Sudoku */
start = secs();
if solve() then
do;
finish = secs();
result = finish - start + 0.0005;
put skip list('Sudoku solved! Time: ' || trim(result) || ' seconds');
put skip(2);
 
/* display the solved Sudoku if solution exist */
do i = 1 to 9;
do j = 1 to 9;
put edit(trim(index(matrix(i, j), '1'b))) (a(3));
end;
put skip(2);
end;
end;
else put skip list('Impossible!');
 
 
/*************************************/
/* Simple backtracking sudoku solver */
/*************************************/
solve: proc recursive returns(bit(1));
dcl (i, j, k) fixed bin(31);
dcl result type bits;
 
/* find free cell */
do i = 1 to 9;
do j = 1 to 9;
if matrix(i, j) = posbit(0) then goto skip;
end;
end;
 
/* No more free cells. Check if the completed Sudoku is valid. */
/* Number in the cell is valid if the matching position bit is set. */
do i = 1 to 9;
do j = 1 to 9;
k = index(matrix(i, j), '1'b);
matrix(i, j) = posbit(0);
result = ^(any(matrix(i, *)) | any(matrix(*, j)) | any(box(numbox(i, j), *, *)));
if substr(result, k, 1) = '0'b then return('0'b);
matrix(i, j) = posbit(k);
end;
end;
 
return('1'b);
skip:
 
/* Go through and test possible values for the free cell untill the Sudoku is completed */
result = ^(any(matrix(i, *)) | any(matrix(*, j)) | any(box(numbox(i, j), *, *)));
k = 0;
do forever;
k = search(result, '1'b, k+1);
if k = 0 then leave;
matrix(i, j) = posbit(k);
if solve() then return('1'b);
else matrix(i, j) = posbit(0);
end;
 
return('0'b);
end solve;
 
 
/********************************************/
/* Returns box number for the sudoku coords */
/********************************************/
numbox: proc(i, j) returns(fixed bin(31));
dcl (i, j) fixed bin(31);
 
dcl lookup (9, 9) fixed bin(31) static init( (3)1, (3)2, (3)3,
(3)1, (3)2, (3)3,
(3)1, (3)2, (3)3,
(3)4, (3)5, (3)6,
(3)4, (3)5, (3)6,
(3)4, (3)5, (3)6,
(3)7, (3)8, (3)9,
(3)7, (3)8, (3)9,
(3)7, (3)8, (3)9 );
 
return(lookup(i, j));
end numbox;
 
end sudoku;
</syntaxhighlight>
 
=={{header|Prolog}}==
<syntaxhighlight lang="prolog">:- use_module(library(clpfd)).
sudoku(Rows) :-
length(Rows, 9), maplist(length_(9), Rows),
append(Rows, Vs), Vs ins 1..9,
maplist(all_distinct, Rows),
transpose(Rows, Columns), maplist(all_distinct, Columns),
Rows = [A,B,C,D,E,F,G,H,I],
blocks(A, B, C), blocks(D, E, F), blocks(G, H, I).
length_(L, Ls) :- length(Ls, L).
blocks([], [], []).
blocks([A,B,C|Bs1], [D,E,F|Bs2], [G,H,I|Bs3]) :-
all_distinct([A,B,C,D,E,F,G,H,I]),
blocks(Bs1, Bs2, Bs3).
problem(1, [[_,_,_,_,_,_,_,_,_],
[_,_,_,_,_,3,_,8,5],
[_,_,1,_,2,_,_,_,_],
[_,_,_,5,_,7,_,_,_],
[_,_,4,_,_,_,1,_,_],
[_,9,_,_,_,_,_,_,_],
[5,_,_,_,_,_,_,7,3],
[_,_,2,_,1,_,_,_,_],
[_,_,_,_,4,_,_,_,9]]).</syntaxhighlight>
 
===GNU Prolog version===
{{works with|GNU Prolog|1.4.4}}
<syntaxhighlight lang="prolog">:- initialization(main).
 
 
solve(Rows) :-
maplist(domain_1_9, Rows)
, different(Rows)
, transpose(Rows,Cols), different(Cols)
, blocks(Rows,Blocks) , different(Blocks)
, maplist(fd_labeling, Rows)
.
 
domain_1_9(Rows) :- fd_domain(Rows,1,9).
different(Rows) :- maplist(fd_all_different, Rows).
 
blocks(Rows,Blocks) :-
maplist(split3,Rows,Xs), transpose(Xs,Ys)
, concat(Ys,Zs), concat_map(split3,Zs,Blocks)
. % where
split3([X,Y,Z|L],[[X,Y,Z]|R]) :- split3(L,R).
split3([],[]).
 
 
% utils/list
concat_map(F,Xs,Ys) :- call(F,Xs,Zs), maplist(concat,Zs,Ys).
 
concat([],[]).
concat([X|Xs],Ys) :- append(X,Zs,Ys), concat(Xs,Zs).
 
transpose([],[]).
transpose([[X]|Col], [[X|Row]]) :- transpose(Col,[Row]).
transpose([[X|Row]], [[X]|Col]) :- transpose([Row],Col).
transpose([[X|Row]|Xs], [[X|Col]|Ys]) :-
maplist(bind_head, Row, Ys, YX)
, maplist(bind_head, Col, Xs, XY)
, transpose(XY,YX)
. % where
bind_head(H,[H|T],T).
bind_head([],[],[]).
 
 
% tests
test([ [_,_,3,_,_,_,_,_,_]
, [4,_,_,_,8,_,_,3,6]
, [_,_,8,_,_,_,1,_,_]
, [_,4,_,_,6,_,_,7,3]
, [_,_,_,9,_,_,_,_,_]
, [_,_,_,_,_,2,_,_,5]
, [_,_,4,_,7,_,_,6,8]
, [6,_,_,_,_,_,_,_,_]
, [7,_,_,6,_,_,5,_,_]
]).
 
main :- test(T), solve(T), maplist(show,T), halt.
show(X) :- write(X), nl.</syntaxhighlight>
{{Out}}
<pre>[1,2,3,4,5,6,7,8,9]
[4,5,7,1,8,9,2,3,6]
[9,6,8,3,2,7,1,5,4]
[2,4,9,5,6,1,8,7,3]
[5,7,6,9,3,8,4,1,2]
[8,3,1,7,4,2,6,9,5]
[3,1,4,2,7,5,9,6,8]
[6,9,5,8,1,4,3,2,7]
[7,8,2,6,9,3,5,4,1]</pre>
[http://ideone.com/OCstmf Runs in: time: 0.02 memory: 68352 (adapted for gprolog 1.3.1)]
 
=={{header|PureBasic}}==
A brute force method is used, it seemed the fastest as well as the simplest.
<langsyntaxhighlight PureBasiclang="purebasic">DataSection
puzzle:
Data.s "394002670"
Line 3,612 ⟶ 10,049:
Input()
CloseConsole()
EndIf</langsyntaxhighlight>
{{out}}
Sample output:
<pre>+-----+-----+-----+
|3 9 4|. . 2|6 7 .|
Line 3,645 ⟶ 10,082:
See [http://www2.warwick.ac.uk/fac/sci/moac/currentstudents/peter_cock/python/sudoku/ Solving Sudoku puzzles with Python] for GPL'd solvers of increasing complexity of algorithm.
 
=={{header|Ruby}}=Backtrack===
 
Example of a back-tracking solver, from [[wp:Algorithmics of sudoku]]
A simple backtrack algorithm -- Quick but may take longer if the grid had been more than 9 x 9
{{works with|Ruby|1.8.7+}}
<syntaxhighlight lang="python">
<lang ruby>def read_matrix(fh)
def initiate():
matrix = []
box.append([0, 1, 2, 9, 10, 11, 18, 19, 20])
box.append([3, 4, 5, 12, 13, 14, 21, 22, 23])
box.append([6, 7, 8, 15, 16, 17, 24, 25, 26])
box.append([27, 28, 29, 36, 37, 38, 45, 46, 47])
box.append([30, 31, 32, 39, 40, 41, 48, 49, 50])
box.append([33, 34, 35, 42, 43, 44, 51, 52, 53])
box.append([54, 55, 56, 63, 64, 65, 72, 73, 74])
box.append([57, 58, 59, 66, 67, 68, 75, 76, 77])
box.append([60, 61, 62, 69, 70, 71, 78, 79, 80])
for i in range(0, 81, 9):
row.append(range(i, i+9))
for i in range(9):
column.append(range(i, 80+i, 9))
 
def valid(n, pos):
current_row = pos/9
current_col = pos%9
current_box = (current_row/3)*3 + (current_col/3)
for i in row[current_row]:
if (grid[i] == n):
return False
for i in column[current_col]:
if (grid[i] == n):
return False
for i in box[current_box]:
if (grid[i] == n):
return False
return True
 
def solve():
i = 0
proceed = 1
while(i < 81):
if given[i]:
if proceed:
i += 1
else:
i -= 1
else:
n = grid[i]
prev = grid[i]
while(n < 9):
if (n < 9):
n += 1
if valid(n, i):
grid[i] = n
proceed = 1
break
if (grid[i] == prev):
grid[i] = 0
proceed = 0
if proceed:
i += 1
else:
i -=1
 
def inputs():
nextt = 'T'
number = 0
pos = 0
while(not(nextt == 'N' or nextt == 'n')):
print "Enter the position:",
pos = int(raw_input())
given[pos - 1] = True
print "Enter the numerical:",
number = int(raw_input())
grid[pos - 1] = number
print "Do you want to enter another given?(Y, for yes: N, for no)"
nextt = raw_input()
 
 
grid = [0]*81
given = [False]*81
box = []
row = []
column = []
initiate()
inputs()
solve()
for i in range(9):
print grid[i*9:i*9+9]
raw_input()
</syntaxhighlight>
 
===Search + Wave Function Collapse===
 
A Sudoku solver using search guided by the principles of wave function collapse.
<syntaxhighlight lang="python">
 
 
sudoku = [
# cell value # cell number
0, 0, 4, 0, 5, 0, 0, 0, 0, # 0, 1, 2, 3, 4, 5, 6, 7, 8,
9, 0, 0, 7, 3, 4, 6, 0, 0, # 9, 10, 11, 12, 13, 14, 15, 16, 17,
0, 0, 3, 0, 2, 1, 0, 4, 9, # 18, 19, 20, 21, 22, 23, 24, 25, 26,
0, 3, 5, 0, 9, 0, 4, 8, 0, # 27, 28, 29, 30, 31, 32, 33, 34, 35,
0, 9, 0, 0, 0, 0, 0, 3, 0, # 36, 37, 38, 39, 40, 41, 42, 43, 44,
0, 7, 6, 0, 1, 0, 9, 2, 0, # 45, 46, 47, 48, 49, 50, 51, 52, 53,
3, 1, 0, 9, 7, 0, 2, 0, 0, # 54, 55, 56, 57, 58, 59, 60, 61, 62,
0, 0, 9, 1, 8, 2, 0, 0, 3, # 63, 64, 65, 66, 67, 68, 69, 70, 71,
0, 0, 0, 0, 6, 0, 1, 0, 0, # 72, 73, 74, 75, 76, 77, 78, 79, 80
# zero = empty.
]
 
numbers = {1,2,3,4,5,6,7,8,9}
 
def options(cell,sudoku):
""" determines the degree of freedom for a cell. """
column = {v for ix, v in enumerate(sudoku) if ix % 9 == cell % 9}
row = {v for ix, v in enumerate(sudoku) if ix // 9 == cell // 9}
box = {v for ix, v in enumerate(sudoku) if (ix // (9 * 3) == cell // (9 * 3)) and ((ix % 9) // 3 == (cell % 9) // 3)}
return numbers - (box | row | column)
 
initial_state = sudoku[:] # the sudoku is our initial state.
 
job_queue = [initial_state] # we need the jobqueue in case of ambiguity of choice.
 
while job_queue:
state = job_queue.pop(0)
if not any(i==0 for i in state): # no missing values means that the sudoku is solved.
break
 
# determine the degrees of freedom for each cell.
degrees_of_freedom = [0 if v!=0 else len(options(ix,state)) for ix,v in enumerate(state)]
# find cell with least freedom.
least_freedom = min(v for v in degrees_of_freedom if v > 0)
cell = degrees_of_freedom.index(least_freedom)
 
for option in options(cell, state): # for each option we add the new state to the queue.
new_state = state[:]
new_state[cell] = option
job_queue.append(new_state)
 
# finally - print out the solution
for i in range(9):
print(state[i*9:i*9+9])
 
# [2, 6, 4, 8, 5, 9, 3, 1, 7]
# [9, 8, 1, 7, 3, 4, 6, 5, 2]
# [7, 5, 3, 6, 2, 1, 8, 4, 9]
# [1, 3, 5, 2, 9, 7, 4, 8, 6]
# [8, 9, 2, 5, 4, 6, 7, 3, 1]
# [4, 7, 6, 3, 1, 8, 9, 2, 5]
# [3, 1, 8, 9, 7, 5, 2, 6, 4]
# [6, 4, 9, 1, 8, 2, 5, 7, 3]
# [5, 2, 7, 4, 6, 3, 1, 9, 8]
 
</syntaxhighlight>
 
This solver found the 45 unknown values in 45 steps.
 
=={{header|Racket}}==
A [http://schemecookbook.org/view/Cookbook/SudokuSolver Sudoku Solver in Racket].
 
=={{header|Raku}}==
(formerly Perl 6)
===Brute Force===
{{trans|Perl}}
<syntaxhighlight lang="raku" line>my @A = <
5 3 0 0 2 4 7 0 0
0 0 2 0 0 0 8 0 0
1 0 0 7 0 3 9 0 2
0 0 8 0 7 2 0 4 9
(0..8).each { |i|
0 2 0 9 8 0 0 7 0
l = fh.readline
7 9 0 0 0 0 0 8 0
matrix[i] = []
(0..8).each { |j|
0 0 matrix[i][j]0 = l[j..j].to_i0 3 0 5 0 6
9 6 0 0 1 0 3 0 0
0 5 0 6 9 0 0 1 0
>;
my &I = * div 9; # line number
my &J = * % 9; # column number
my &K = { ($_ div 27) * 3 + $_ % 9 div 3 }; # bloc number
 
sub solve {
for ^@A -> $i {
next if @A[$i];
my @taken-values = @A[
grep {
I($_) == I($i) || J($_) == J($i) || K($_) == K($i)
}, ^@A
];
for grep none(@taken-values), 1..9 {
@A[$i] = $_;
solve;
}
return @A[$i] = 0;
}
my $i = 1;
}
for ^@A {
matrix
print "@A[$_] ";
print " " if $i %% 3;
print "\n" if $i %% 9;
print "\n" if $i++ %% 27;
}
}
solve;</syntaxhighlight>
 
{{out}}
<pre>5 3 9 8 2 4 7 6 1
6 7 2 1 5 9 8 3 4
1 8 4 7 6 3 9 5 2
 
3 1 8 5 7 2 6 4 9
4 2 5 9 8 6 1 7 3
7 9 6 3 4 1 2 8 5
 
8 4 1 2 3 7 5 9 6
9 6 7 4 1 5 3 2 8
2 5 3 6 9 8 4 1 7</pre>
 
===Finesse It===
This is an alternative solution that uses a more ellaborate set of choices instead of brute-forcing it.
 
<syntaxhighlight lang="raku" line>#
# In this code, a sudoku puzzle is represented as a two-dimentional
# array. The cells that are not yet solved are represented by yet
# another array of all the possible values.
#
# This implementation is not a simple brute force evaluation of all
# the options, but rather makes four extra attempts to guide the
# solution:
#
# 1) For every change in the grid, usually made by an attempt at a
# solution, we will reduce the search space of the possible values
# in all the other cells before going forward.
#
# 2) When a cell that is not yet resolved is the only one that can
# hold a specific value, resolve it immediately instead of
# performing the regular search.
#
# 3) Instead of trying from cell 1,1 and moving in sequence, this
# implementation will start trying on the cell that is the closest
# to being solved already.
#
# 4) Instead of trying all possible values in sequence, start with
# the value that is the most unique. I.e.: If the options for this
# cell are 1,4,6 and 6 is only a candidate for two of the
# competing cells, we start with that one.
#
 
# keep a list with all the cells, handy for traversal
my @cells = do for (flat 0..8 X 0..8) -> $x, $y { [ $x, $y ] };
 
#
# Try to solve this puzzle and return the resolved puzzle if it is at
# all solvable in this configuration.
sub solve($sudoku, Int $level) {
# cleanup the impossible values first,
if (cleanup-impossible-values($sudoku, $level)) {
# try to find implicit answers
while (find-implicit-answers($sudoku, $level)) {
# and every time you find some, re-do the cleanup and try again
cleanup-impossible-values($sudoku, $level);
}
# Now let's actually try to solve a new value. But instead of
# going in sequence, we select the cell that is the closest to
# being solved already. This will reduce the overall number of
# guesses.
for sort { solution-complexity-factor($sudoku, $_[0], $_[1]) },
grep { $sudoku[$_[0]][$_[1]] ~~ Array },
@cells -> $cell
{
my Int ($x, $y) = @($cell);
# Now let's try the possible values in the order of
# uniqueness.
for sort { matches-in-competing-cells($sudoku, $x, $y, $_) }, @($sudoku[$x][$y]) -> $val {
trace $level, "Trying $val on "~($x+1)~","~($y+1)~" "~$sudoku[$x][$y].raku;
my $solution = clone-sudoku($sudoku);
$solution[$x][$y] = $val;
my $solved = solve($solution, $level+1);
if $solved {
trace $level, "Solved... ($val on "~($x+1)~","~($y+1)~")";
return $solved;
}
}
# if we fell through, it means that we found no valid
# value for this cell
trace $level, "Backtrack, path unsolvable... (on "~($x+1)~" "~($y+1)~")";
return False;
}
# all cells are already solved.
return $sudoku;
} else {
# if the cleanup failed, it means this is an invalid grid.
return False;
}
}
 
# This function reduces the search space from values that are already
# assigned to competing cells.
sub cleanup-impossible-values($sudoku, Int $level = 1) {
my Bool $resolved;
repeat {
$resolved = False;
for grep { $sudoku[$_[0]][$_[1]] ~~ Array },
@cells -> $cell {
my Int ($x, $y) = @($cell);
# which block is this cell in
my Int $bx = Int($x / 3);
my Int $by = Int($y / 3);
# A unfilled cell is not resolved, so it shouldn't match
my multi match-resolved-cell(Array $other, Int $this) {
return False;
}
my multi match-resolved-cell(Int $other, Int $this) {
return $other == $this;
}
 
# Reduce the possible values to the ones that are still
# valid
my @r =
grep { !match-resolved-cell($sudoku[any(0..2)+3*$bx][any(0..2)+3*$by], $_) }, # same block
grep { !match-resolved-cell($sudoku[any(0..8)][$y], $_) }, # same line
grep { !match-resolved-cell($sudoku[$x][any(0..8)], $_) }, # same column
@($sudoku[$x][$y]);
if (@r.elems == 1) {
# if only one element is left, then make it resolved
$sudoku[$x][$y] = @r[0];
$resolved = True;
} elsif (@r.elems == 0) {
# This is an invalid grid
return False;
} else {
$sudoku[$x][$y] = @r;
}
}
} while $resolved; # repeat if there was any change
return True;
}
 
sub solution-complexity-factor($sudoku, Int $x, Int $y) {
my Int $bx = Int($x / 3); # this block
my Int $by = Int($y / 3);
my multi count-values(Array $val) {
return $val.elems;
}
my multi count-values(Int $val) {
return 1;
}
# the number of possible values should take precedence
my Int $f = 1000 * count-values($sudoku[$x][$y]);
for (flat 0..2 X 0..2) -> $lx, $ly {
$f += count-values($sudoku[$lx+$bx*3][$ly+$by*3])
}
for 0..^($by*3), (($by+1)*3)..8 -> $ly {
$f += count-values($sudoku[$x][$ly])
}
for 0..^($bx*3), (($bx+1)*3)..8 -> $lx {
$f += count-values($sudoku[$lx][$y])
}
return $f;
}
 
sub matches-in-competing-cells($sudoku, Int $x, Int $y, Int $val) {
my Int $bx = Int($x / 3); # this block
my Int $by = Int($y / 3);
# Function to decide which possible value to try first
my multi cell-matching(Int $cell) {
return $val == $cell ?? 1 !! 0;
}
my multi cell-matching(Array $cell) {
return $cell.grep({ $val == $_ }) ?? 1 !! 0;
}
my Int $c = 0;
for (flat 0..2 X 0..2) -> $lx, $ly {
$c += cell-matching($sudoku[$lx+$bx*3][$ly+$by*3])
}
for 0..^($by*3), (($by+1)*3)..8 -> $ly {
$c += cell-matching($sudoku[$x][$ly])
}
for 0..^($bx*3), (($bx+1)*3)..8 -> $lx {
$c += cell-matching($sudoku[$lx][$y])
}
return $c;
}
 
sub find-implicit-answers($sudoku, Int $level) {
my Bool $resolved = False;
for grep { $sudoku[$_[0]][$_[1]] ~~ Array },
@cells -> $cell {
my Int ($x, $y) = @($cell);
for @($sudoku[$x][$y]) -> $val {
# If this is the only cell with this val as a possibility,
# just make it resolved already
if (matches-in-competing-cells($sudoku, $x, $y, $val) == 1) {
$sudoku[$x][$y] = $val;
$resolved = True;
}
}
}
return $resolved;
}
 
my $puzzle =
map { [ map { $_ == 0 ?? [1..9] !! $_+0 }, @($_) ] },
[ 0,0,0,0,3,7,6,0,0 ],
[ 0,0,0,6,0,0,0,9,0 ],
[ 0,0,8,0,0,0,0,0,4 ],
[ 0,9,0,0,0,0,0,0,1 ],
[ 6,0,0,0,0,0,0,0,9 ],
[ 3,0,0,0,0,0,0,4,0 ],
[ 7,0,0,0,0,0,8,0,0 ],
[ 0,1,0,0,0,9,0,0,0 ],
[ 0,0,2,5,4,0,0,0,0 ];
 
my $solved = solve($puzzle, 0);
if $solved {
print-sudoku($solved,0);
} else {
say "unsolvable.";
}
 
# Utility functions, not really part of the solution
 
sub trace(Int $level, Str $message) {
# say '.' x $level, $message; # un-comment for verbose logging
}
 
sub clone-sudoku($sudoku) {
my $clone;
for (flat 0..8 X 0..8) -> $x, $y {
$clone[$x][$y] = $sudoku[$x][$y];
}
return $clone;
}
 
sub print-sudoku($sudoku, Int $level = 1) {
trace $level, '-' x 5*9;
for @($sudoku) -> $row {
trace $level, join " ", do for @($row) -> $cell {
$cell ~~ Array ?? "#{$cell.elems}#" !! " $cell "
}
}
}</syntaxhighlight>
 
{{out}}
<pre> 9 5 4 1 3 7 6 8 2
2 7 3 6 8 4 1 9 5
1 6 8 2 9 5 7 3 4
4 9 5 7 2 8 3 6 1
6 8 1 4 5 3 2 7 9
3 2 7 9 6 1 5 4 8
7 4 9 3 1 2 8 5 6
5 1 6 8 7 9 4 2 3
8 3 2 5 4 6 9 1 7
</pre>
 
=={{header|Rascal}}==
[[File:sudoku.jpeg||200px|thumb|right]]
A sudoku is represented as a matrix, see Rascal solutions to matrix related problems for examples.
 
<syntaxhighlight lang="rascal">import Prelude;
import vis::Figure;
import vis::Render;
 
public rel[int,int,int] sudoku(rel[int x, int y, int v] sudoku){
annotated= annotateGrid(sudoku);
solved = {<0,0,0,0,{0}>};
while(!isEmpty(solved)){
for (n <- [0 ..8]){
column = domainR(annotated, {n});
annotated -= column;
annotated += reduceOptions(column);
row = {<x,y,v,g,p> | <x,y,v,g,p> <- annotated, y==n};
annotated -= row;
annotated += reduceOptions(row);
grid1 = {<x,y,v,g,p> | <x,y,v,g,p> <- annotated, g==n};
annotated -= grid1;
annotated += reduceOptions(grid1);
}
solved = {<x,y,v,g,p> | <x,y,v,g,p> <- annotated, size(p)==1};
annotated -= solved;
annotated += {<x,y,getOneFrom(p),g,{*[1 .. 9]}> | <x,y,v,g,p> <- solved};
}
 
result = {<x,y,v> | <x,y,v,g,p> <- annotated};
return result;
}
 
 
//adds gridnumber and default set of options
public rel[int,int,int,int,set[int]] annotateGrid(rel[int x, int y, int v] sudoku){
result = {};
for (<x, y, v> <- sudoku){
g = 0;
if (x<3 && y<3) g = 0;
if (2<x && x<6 && y<3) g = 1;
if (x>5 && y<3) g = 2;
if (x<3 && 2<y && y<6) g = 3;
if (2<x && x<6 && 2<y && y<6) g = 4;
if (x>5 && 2<y && y<6) g = 5;
if (x<3 && y>5) g=6;
if (2<x && x<6 && y>5) g=7;
if (x>5 && y>5) g=8;
result += <x,y,v,g,{*[1 .. 9]}>;
}
return result;
}
 
//reduces set of options
public rel[int,int,int,int,set[int]] reduceOptions(rel[int x, int y, int v, int g, set[int] p] subSudoku){
solved = {<x,y,v,g,p> | <x,y,v,g,p> <- subSudoku, v!=0};
numbers = {*[1 .. 9]} - {v | <x,y,v,g,p> <- solved};
remaining = {<x,y,v,g,numbers&p> | <x,y,v,g,p> <- subSudoku-solved};
result = remaining + solved;
return result;
}
 
//a function to visualize the result
public void displaySudoku(rel[int x, int y, int v] sudoku){
points = [box(text("<v>"), align(0.111111*(x+1),0.111111*(y+1)),shrink(0.1)) | <x,y,v> <- sudoku];
print(points);
render(overlay([*points], aspectRatio(1.0)));
}
 
//a sudoku
public rel[int, int, int] sudokuA =
{
<0,0,3>, <1,0,9>, <2,0,4>, <3,0,0>, <4,0,0>, <5,0,2>, <6,0,6>, <7,0,7>, <8,0,0>,
<0,1,0>, <1,1,0>, <2,1,0>, <3,1,3>, <4,1,0>, <5,1,0>, <6,1,4>, <7,1,0>, <8,1,0>,
<0,2,5>, <1,2,0>, <2,2,0>, <3,2,6>, <4,2,9>, <5,2,0>, <6,2,0>, <7,2,2>, <8,2,0>,
<0,3,0>, <1,3,4>, <2,3,5>, <3,3,0>, <4,3,0>, <5,3,0>, <6,3,9>, <7,3,0>, <8,3,0>,
<0,4,6>, <1,4,0>, <2,4,0>, <3,4,0>, <4,4,0>, <5,4,0>, <6,4,0>, <7,4,0>, <8,4,7>,
<0,5,0>, <1,5,0>, <2,5,7>, <3,5,0>, <4,5,0>, <5,5,0>, <6,5,5>, <7,5,8>, <8,5,0>,
<0,6,0>, <1,6,1>, <2,6,0>, <3,6,0>, <4,6,6>, <5,6,7>, <6,6,0>, <7,6,0>, <8,6,8>,
<0,7,0>, <1,7,0>, <2,7,9>, <3,7,0>, <4,7,0>, <5,7,8>, <6,7,0>, <7,7,0>, <8,7,0>,
<0,8,0>, <1,8,2>, <2,8,6>, <3,8,4>, <4,8,0>, <5,8,0>, <6,8,7>, <7,8,3>, <8,8,5>
};</syntaxhighlight>
 
Example
<pre>rascal>displaySudoku(sudoku(sudokuA))
 
See picture</pre>
 
=={{header|REXX}}==
The &nbsp; '''SUDOKU''' &nbsp; REXX programs (and output) are included here &nbsp; ──► &nbsp; [[Sudoku/REXX]].
<br><br>
 
=={{header|RPN (HP-15c)}}==
 
This is a back-tracking solver written in RPN for the HP-15C calculator. It is highly optimized for size, rather than speed, as the target platform only has 448 bytes of memory for code and data combined.
 
Latest version and usage notes kept at: [[http://neural-noise.blogspot.com/2013/01/a-sudoku-solver-for-hp-15c.html Sudoku Solver for the HP 15-C]]
 
<pre>
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Register And Flag Usage
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; 0 General purpose variable used for miscelaneous purposes
; 1 Current index (0-80) in the pseudo-recursion
; 2 Row (0-8) of current index
; 3 Column (0-8) of current index
; 4 Block # (0-8) of current index
; 5 Power of 10 of current column index
; 6 Value in the test solution at current index
; 7 Value of start clue at current index (0 if not set)
; 8 – 16 Starting row data
; 17 – 25 Current test solution
; 26 – 34 Flag matrix (bit set if digit used in a row/column/block)
;
; Flag 2 Indicates that a digit has been used in cur row/column/block
; Flag 3 Input to Subroutine B (whether to set or clear flags)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; setU(x)
; Set/clear flag matrix values (show that x is used in a row/column/block)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
LBL D
GSB 5 ; calc bit value we need to set/clear in existing row
RCL 2 ; Get the current row index into x
GSB B ; set flag matrix value and calc new bit value for the column
RCL 3 ; Get the current column index into x
GSB B ; set flag matrix values and calc new bit value for the block
RCL 4 ; Get the current block index into x
; MUST IMMEDIATELY FOLLOW PRECEEDING SUBROUTINE
; utility subroutine for setting flag matrix values
 
LBL B
GSB 1 ; get the current flag matrix row at index x
RCL 0 ; get temp register (holds the bit value we will be setting)
F? 3 ; flag 3 indicates if we are setting or clearing the flag
CHS ; if we are clearing, we will do a subtraction instead
+ ; set/clear the flag
X<>Y ; bring the row index back into x
2 ; 26 is the starting register for the flag matrix
6
GSB 3 ; set I so that we are ready to store the new value
STO (i) ; store the new value into the flag matrix
RDN ; get rid of the new value to restore the stack
9 ; the next bit value will be 9 bits to the left
+ ; set the next bit index
GTO 5 ; calculate the value with that bit set
; we GTO instead of GSB and it will do the RTN
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; putA(x)
; Set the value x into the current row/column in the trial solution.
; Does it by subtracting the previous value and adding the new one.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
LBL 7
X<>6 ; swap new value with register that holds current value
STO 0 ; store the old value in the temp register
RCL 2 ; Get the current row index into x
1 ; 17 is the starting register for the current trial solution
7
GSB 3 ; Set the indirect register
RCL (i) ; Get the current value for the entire row
RCL 6 ; Get the new value
RCL- 0 ; subtract the old value from the new value
RCL* 5 ; shift the power of 10 to the appropriate column
+ ; add to the old value
STO (i) ; store the new row value from where we got it
RTN
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; change(x)
; Increments or decrements the current position in the trial solution.
; Updates the registers containing the current row, column and block index,
; and the one with the power of 10 factor for the current column and others
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
LBL 6
STO+ 1 ; x holds +1 or -1; Register 1 is the current index
RCL 1 ; get the current index (0 to 80)
RCL 1 ; get the current index (0 to 80)
9 ; integer divide by 9 to get the row index (0 to 8)
/ ; no integer divide on 15c so do a floating point divide
INT ; use the INT operator to finish of the integer divide
STO 2 ; register 2 contains the current row index
9
*
- ; col = index - 9 * row
STO 3 ; register 3 contains the current column index
3 ; calculate the block index from the row & column indexes
/ ; TODO: save a couple of bytes in this section of code
RCL 2
3
/
INT
3
*
+
STO 4 ; register 4 holds the block index
8 ; now calculate the power of 10 of the current column
RCL- 3 ; Get the digit (from right) based on the column
10^X ; calculate the exponent
STO 5 ; save in register 5 which is used throughout the code
RCL 2 ; get the current row
1 ; 17 is the start register of the current trial solution
7
GSB 4 ; extract the value at the current column
STO 6 ; reg 6: the current trial value at the current row/column
RCL 2 ; get the current row
8 ; 8 is the start register of the input data from the user
GSB 4 ; extract the value at the current column
STO 7 ; reg 7: starting value at the current row/column (0 if none)
RTN
; Extract value at the current column from the matrix indirectly specified by x&y
LBL 4
GSB 3 ; set the indirect register based on x & y
RCL (i) ; get the row from the matrix passed in
RCL / 5 ; shift the row to the right
INT ; trim off the digits shifted to the right of the decimal
1 ; we will do a modulus 10 to extract the last digit
0
/ ; do the equivalent of a mod 10
FRAC
1
0
*
RTN
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; main()
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
LBL A
CF 2 ; make sure flag 2 is unset - CLR REG does not do this
CF 3 ; make sure flag 3 is unset - CLR REG does not do this
1 ; start with a index in register 1 of -1 (0 to 80)
CHS ; that way we can start with an increment operation
STO 1 ; and actually start at 0 where we want.
LBL 2 ; set the flags to show the input values are set
1 ; go forward one position at a time
GSB 6 ; go to the next position in the trial solution
RCL 7 ; get the starting input value at this row/col
GSB 7 ; set the value in the trial solution
RCL 7 ; get starting input value because the last call destroyed it
TEST 1 ; if > 0 then the user input a value for this row/col
GSB D ; set the flags to indicate this value is set
8 ; 80 is the upper bound of the indexes (9x9 = 80 = 0:80)
0
RCL 1 ; get the current index
TEST 6 ; if the current index hasn't reached 80
GTO 2 ; do the next value
1 ; reset the starting value
CHS ; to -1 as we did at the beginning of the program
STO 1 ; register 1 holds the current index
LBL E ; main solution loop
8 ; when we reach the last index (80) we are done
0
RCL 1 ; register 1 holds the current index
TEST 5 ; see if we are at the end
RTN ; finished ; woohoo - we are done!
1 ; Go forward one spot
GSB 6 ; Do the position increment
RCL 7 ; get the starting input value at this row/col
TEST 1 ; if it's > 0, the user specified a value here
GTO E ; go forward, since this value was specified by the user
GSB 7 ; Set the value in the trial solution
LBL 8
9 ; check the possible digits in order 1-9.
RCL 6 ; Get the current trial solution value
TEST 5 ; Check to see if it is 9
GTO C ; If it is, backup one step
1 ; We weren't at 9 yet, so increment the value by 1
+
GSB 7 ; Set the value in the trial solution
RCL 6 ; Get the current trial solution value
GSB 5 ; Calc 2^x-1 to get the bit mask
CF 2 ; Clear the flag thats used as a return value
RCL 2 ; Get the current row index into x
GSB 9 ; see if the current value has already been used in the row
F? 2 ; If number has been used in the block, try the next value
GTO 8
RCL 3 ; Get the current column index into x
GSB 9 ; see if current value has already been used in the column
F? 2 ; If number has been used in the block, try the next value
GTO 8
RCL 4 ; Get the current block index into x
GSB 9 ; see if the current value has already been used in the block
F? 2 ; If number has been used in the block, try the next value
GTO 8
RCL 6 ; Get the current trial solution value
GSB D ; set the flags to indicate this value is set
GTO E ; move on to the next position in the puzzle
LBL C ; Come here to back up to the previous position
1 ; We will go one spot backwards
CHS
GSB 6 ; Set the new current position and all temp values
TEST 1 ; previous call leaves the starting value in X
GTO C ; if value is > 0, it was set, backup one more spot
RCL 6 ; Get the current trial solution value
SF 3 ; flag 3: clear the flag matrix bits, instead of setting them
GSB D ; Set/Clear the flag matrix bits
CF 3 ; unset the 3 flag
GTO 8 ; check the next digit
LBL 9
GSB 1 ; get the appropriate row (x) from the flag matrix
RCL / 0 ; divide by the temp register - right shifts value
INT
2 ; if bit is set, fractional part will be non 0 when / 2
/
FRAC
TEST 1 ; if bit is set, set flag 2 which is used as a return value
SF 2
RDN ; move the stack down to prepare the caller for the next call
RDN ; move the stack down to prepare the caller for the next call
9 ; bit flags for row/col/block are << by 9 from each other
+ ; calculates the appropriate bit offset for the next call
GTO 5 ; calc 2^x-1 to get the bit mask
; do a GTO instead of GSB and it will return for us
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; setPow2(x)
; Sets the utility temp register to 2^(x-1). Leaves x in place.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
LBL 5
STO 0 ; store the input X in the temp register
1 ; we want to subtract 1 from the exponent
- ; calculate x-1
2 ; set the base as 2
X<>Y ; the y^x function wants x and y reversed
y^x ; calculate the value
X<>0 ; stuff result in temp register and restore the input x
RTN
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; getPart(x)
; Returns the integer representing the entire Xth row of the flag matrix
; Row numbers start at 0.
; returns value in x - input parameter x ends up in y
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
LBL 1
ENTER
ENTER ; duplicate the parameter so we can leave it for the caller
2 ; 26 is the starting register for the flag matrix
6
GSB 3 ; set the indirect register to the row specified by x
RCL (i) ; retrieve the entire row from the flag matrix
RTN
; Set the indirect register and remove the parameters from the stack
LBL 3
+ ; x+y is the memory offset we want
STO I ; put it in the indirect register
RDN ; get rid of the sum from the stack
RTN
</pre>
 
=={{header|Ruby}}==
Example of a back-tracking solver, from [[wp:Algorithmics of sudoku]]
{{works with|Ruby|2.0+}}
<syntaxhighlight lang="ruby">def read_matrix(data)
lines = data.lines
9.times.collect { |i| 9.times.collect { |j| lines[i][j].to_i } }
end
 
def permissible(matrix, i, j)
ok = [true]nil, * 1..9]
check = ->(x,y) { ok[matrix[x][y]] = nil if matrix[x][y].nonzero? }
# Same as another in the column isn't permissible...
(09..8).eachtimes { |i2x| check[x, j] }
next if matrix[i2][j] == 0
ok[matrix[i2][j] - 1] = false
}
# Same as another in the row isn't permissible...
(09..8).eachtimes { |j2y| check[i, y] }
next if matrix[i][j2] == 0
ok[matrix[i][j2] - 1] = false
}
# Same as another in the 3x3 block isn't permissible...
igroupxary = [ *(x = (i / 3) * 3) .. x + 2 ] #=> [0,1,2], [3,4,5] or [6,7,8]
jgroupyary = [ *(y = (j / 3) * 3) .. y + 2 ]
(igroup.xary.product(igroup + 2)yary).each { |i2x, y| check[x, y] }
# Gathering only permitted one
(jgroup..(jgroup + 2)).each { |j2|
ok.compact
next if matrix[i2][j2] == 0
ok[matrix[i2][j2] - 1] = false
}
}
# Convert to the array format...
(1..9).select { |i2| ok[i2-1] }
end
 
def deep_copy_sudoku(matrix)
matrix.collect { |row| row.dup }
end
 
def solve_sudoku(matrix)
loop do
options = []
(09..8).eachtimes {do |i|
(09..8).eachtimes {do |j|
next if matrix[i][j] != 0.nonzero?
p = permissible(matrix, i, j)
# If nothing is permissible, there is no solution at this level.
return nil if p.lengthempty? == 0 # return nil
options.push({:i =><< [i, :j => j, :permissible => p})]
}end
}end
# If the matrix is complete, we have a solution...
return matrix if options.length == 0empty?
omini, j, permissible = options.min_by { |x| x[:permissible].last.length }
# If there is an option with only one solution, set it and re-check permissibility
if omin[:permissible].length == 1
matrix[omin[:i]][omin[:j]] = omin[:permissible][0]
next
end
# We have two or more choices. We need to search both...
omin[:permissible].each {do |v|
mtmp = deep_copy_sudoku(matrix)
mtmp[omin[:i]][omin[:j]] = v
ret = solve_sudoku(mtmp)
return ret if ret
}end
# We did an exhaustive search on this branch and nothing worked out.
return nil
end
end
 
def print_matrix(matrix)
ifputs not"Impossible" or return unless matrix
puts "Impossible"
return
end
border = "+-----+-----+-----+"
(09..8).eachtimes {do |i|
puts border if i%3 == 0
(09..8).eachtimes {do |j|
print( j%3 == 0 ? "|" : " ")
print( matrix[i][j] == 0 ? "." : matrix[i][j])
}end
printputs "|\n"
}end
puts border
end
matrix = read_matrix(DATA)
print_matrix(matrix)
puts
print_matrix(solve_sudoku(matrix))
 
data = <<EOS
__END__
394__267_
___3__4__
Line 3,758 ⟶ 11,002:
_1__67__8
__9__8___
_264__735</lang>
EOS
Output:
 
<pre>+-----+-----+-----+
matrix = read_matrix(data)
print_matrix(matrix)
puts
print_matrix(solve_sudoku(matrix))</syntaxhighlight>
 
{{out}}
<pre>
+-----+-----+-----+
|3 9 4|. . 2|6 7 .|
|. . .|3 . .|4 . .|
Line 3,787 ⟶ 11,039:
|8 2 6|4 1 9|7 3 5|
+-----+-----+-----+</pre>
 
=={{header|Rust}}==
{{trans|Ada}}
<syntaxhighlight lang="rust">type Sudoku = [u8; 81];
 
fn is_valid(val: u8, x: usize, y: usize, sudoku_ar: &mut Sudoku) -> bool {
(0..9).all(|i| sudoku_ar[y * 9 + i] != val && sudoku_ar[i * 9 + x] != val) && {
let (start_x, start_y) = ((x / 3) * 3, (y / 3) * 3);
(start_y..start_y + 3).all(|i| (start_x..start_x + 3).all(|j| sudoku_ar[i * 9 + j] != val))
}
}
 
fn place_number(pos: usize, sudoku_ar: &mut Sudoku) -> bool {
(pos..81).find(|&p| sudoku_ar[p] == 0).map_or(true, |pos| {
let (x, y) = (pos % 9, pos / 9);
for n in 1..10 {
if is_valid(n, x, y, sudoku_ar) {
sudoku_ar[pos] = n;
if place_number(pos + 1, sudoku_ar) {
return true;
}
sudoku_ar[pos] = 0;
}
}
false
})
}
 
fn pretty_print(sudoku_ar: Sudoku) {
let line_sep = "------+-------+------";
println!("{}", line_sep);
for (i, e) in sudoku_ar.iter().enumerate() {
print!("{} ", e);
if (i + 1) % 3 == 0 && (i + 1) % 9 != 0 {
print!("| ");
}
if (i + 1) % 9 == 0 {
println!(" ");
}
if (i + 1) % 27 == 0 {
println!("{}", line_sep);
}
}
}
 
fn solve(sudoku_ar: &mut Sudoku) -> bool {
place_number(0, sudoku_ar)
}
 
fn main() {
let mut sudoku_ar: Sudoku = [
8, 5, 0, 0, 0, 2, 4, 0, 0,
7, 2, 0, 0, 0, 0, 0, 0, 9,
0, 0, 4, 0, 0, 0, 0, 0, 0,
0, 0, 0, 1, 0, 7, 0, 0, 2,
3, 0, 5, 0, 0, 0, 9, 0, 0,
0, 4, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 8, 0, 0, 7, 0,
0, 1, 7, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 3, 6, 0, 4, 0
];
if solve(&mut sudoku_ar) {
pretty_print(sudoku_ar);
} else {
println!("Unsolvable");
}
}</syntaxhighlight>
 
{{out}}
<pre>
------+-------+------
8 5 9 | 6 1 2 | 4 3 7
7 2 3 | 8 5 4 | 1 6 9
1 6 4 | 3 7 9 | 5 2 8
------+-------+------
9 8 6 | 1 4 7 | 3 5 2
3 7 5 | 2 6 8 | 9 1 4
2 4 1 | 5 9 3 | 7 8 6
------+-------+------
4 3 2 | 9 8 1 | 6 7 5
6 1 7 | 4 2 5 | 8 9 3
5 9 8 | 7 3 6 | 2 4 1
------+-------+------
</pre>
 
=={{header|SAS}}==
Use CLP solver in SAS/OR:
 
<syntaxhighlight lang="sas">/* define SAS data set */
data Indata;
input C1-C9;
datalines;
. . 5 . . 7 . . 1
. 7 . . 9 . . 3 .
. . . 6 . . . . .
. . 3 . . 1 . . 5
. 9 . . 8 . . 2 .
1 . . 2 . . 4 . .
. . 2 . . 6 . . 9
. . . . 4 . . 8 .
8 . . 1 . . 5 . .
;
 
/* call OPTMODEL procedure in SAS/OR */
proc optmodel;
/* declare variables */
set ROWS = 1..9;
set COLS = ROWS;
var X {ROWS, COLS} >= 1 <= 9 integer;
 
/* declare nine row constraints */
con RowCon {i in ROWS}:
alldiff({j in COLS} X[i,j]);
 
/* declare nine column constraints */
con ColCon {j in COLS}:
alldiff({i in ROWS} X[i,j]);
 
/* declare nine 3x3 block constraints */
con BlockCon {s in 0..2, t in 0..2}:
alldiff({i in 3*s+1..3*s+3, j in 3*t+1..3*t+3} X[i,j]);
 
/* fix variables to cell values */
/* X[i,j] = c[i,j] if c[i,j] is not missing */
num c {ROWS, COLS};
read data indata into [_N_] {j in COLS} <c[_N_,j]=col('C'||j)>;
for {i in ROWS, j in COLS: c[i,j] ne .}
fix X[i,j] = c[i,j];
 
/* call CLP solver */
solve;
 
/* print solution */
print X;
quit;</syntaxhighlight>
 
Output:
<pre>
X
1 2 3 4 5 6 7 8 9
1 9 8 5 3 2 7 6 4 1
2 6 7 1 5 9 4 2 3 8
3 3 2 4 6 1 8 9 5 7
4 2 4 3 7 6 1 8 9 5
5 5 9 7 4 8 3 1 2 6
6 1 6 8 2 5 9 4 7 3
7 4 5 2 8 3 6 7 1 9
8 7 1 6 9 4 5 3 8 2
9 8 3 9 1 7 2 5 6 4
</pre>
 
=={{header|Scala}}==
Line 3,792 ⟶ 11,194:
This solver works with normally 9x9 sudokus as well as with sudokus of jigsaw type or sudokus with additional condition like diagonal constraint.
{{works with|Scala|2.9.1}}
<langsyntaxhighlight lang="scala">object SudokuSolver extends App {
 
class Solver {
Line 3,923 ⟶ 11,325:
println(solution match {case Nil => "no solution!!!" case _ => f2Str(solution)})
}</langsyntaxhighlight>
{{out}}
Output:
<pre>riddle:
+---+---+---+
Line 3,957 ⟶ 11,359:
The implementation above doesn't work so effective for sudokus like Bracmat version, therefore I implemented a second version inspired by Java section:
{{works with|Scala|2.9.1}}
<langsyntaxhighlight lang="scala">object SudokuSolver extends App {
 
object Solver {
Line 4,074 ⟶ 11,476:
+("\n"*2))
}
}</langsyntaxhighlight>
{{out}}
Output:
<pre>riddle used in Ada section:
+---+---+---+
Line 4,201 ⟶ 11,603:
solution:
no solution!!!</pre>
 
=={{header|Scilab}}==
The grid should be input in <code>Init_board</code> as a 9x9 matrix. The blanks should be represented by 0. A rule that the initial game should have at least 17 givens is enforced, for it guarantees a unique solution. It is also possible to set a maximum number of steps to the solver using <code>break_point</code>. If it is set to 0, there will be no break until it finds the solution.
 
<syntaxhighlight lang="text">Init_board=[...
5 3 0 0 7 0 0 0 0;...
6 0 0 1 9 5 0 0 0;...
0 9 8 0 0 0 0 6 0;...
8 0 0 0 6 0 0 0 3;...
4 0 0 8 0 3 0 0 1;...
7 0 0 0 2 0 0 0 6;...
0 6 0 0 0 0 2 8 0;...
0 0 0 4 1 9 0 0 5;...
0 0 0 0 8 0 0 7 9];
 
break_point=1.0d5; //if 0 there will be no break
 
function []=disp_board(board)
StringBoard=string(board);
for i=1:9
for j=1:9
if board(i,j)==0 then
StringBoard(i,j)='×';
end
end
end
StringBoard=[StringBoard, string(zeros(9,2))];
StringBoard=[StringBoard; string(zeros(2,11))];
for i=1:9
StringBoard(i,:)=[StringBoard(i,1:3), '|', StringBoard(i,4:6), '|', StringBoard(i,7:9)]
end
StringBoard(9:11,:)=StringBoard(7:9,:);
StringBoard(8,:)=strsplit('-----------');
StringBoard(5:7,:)=StringBoard(4:6,:);
StringBoard(4,:)=strsplit('-----------');
disp(StringBoard)
endfunction
 
function varargout=validate_input(input,position,board)
row=board(position(1),:);
column=board(:,position(2));
block=zeros(3,3);
if position(1)>=1 & position(1)<=3 then
i=0;
elseif position(1)>=4 & position(1)<=6 then
i=3;
else
i=6;
end
if position(2)>=1 & position(2)<=3 then
j=0;
elseif position(2)>=4 & position(2)<=6 then
j=3;
else
j=6;
end
block=board(i+1:i+3,j+1:j+3)
valid_input=%F;
valid_row=%F;
valid_col=%F;
valid_block=%F;
if find(input==row)==[] then
valid_row=%T;
end
if find(input==column)==[] then
valid_col=%T;
end
if find(input==block)==[] then
valid_block=%T;
end
if valid_row & valid_col & valid_block then
valid_input=%T;
end
varargout=list(valid_input,valid_row,valid_col,valid_block)
endfunction
 
function varargout=validate_board(board)
valid_flag1=%T;
for i=1:9
for j=1:9
if board(i,j)~= 0 then
check_board=Init_board;
check_board(i,j)=0;
valid_flag1=validate_input(board(i,j),[i j],check_board);
if ~valid_flag1 then
break
end
end
end
if ~valid_flag1 then
break
end
end
valid_flag2 = (length( find(board) ) >= 17); //enforces rule of minimum of 17 givens
//set it to always %T to ignore this rule
valid_board = (valid_flag1 & valid_flag2);
varargout=list(valid_board)
endfunction
 
disp('Initial board:');
disp_board(Init_board);
 
valid_init_board=validate_board(Init_board);
 
if ~valid_init_board then
error('Invalid initial board. Should follow sudoku rules and have at least 17 clues.');
end
 
blank=[];
for i=1:9
for j=1:9
if Init_board(i,j)== 0 then
blank=[blank; i j];
end
end
end
 
Solved_board=Init_board;
 
tic();
i=0; counter=0; breaked=%F;
while i<size(blank,'r')
i=i+1;
counter=counter+1;
pos=blank(i,:);
value=Solved_board(pos(1),pos(2));
valid_value=%F;
while valid_value==%F
value=value+1;
if value>=10
break
else
valid_value=validate_input(value,pos,Solved_board);
end
end
if valid_value & value<10 then
Solved_board(pos(1),pos(2))=value
else
Solved_board(pos(1),pos(2))=0;
i=i-2;
end
if counter==break_point
breaked=%T;
break
end
end
 
valid_solved_board=validate_board(Solved_board);
t2=toc();
 
if valid_solved_board & ~breaked then
disp('Solved!');
disp('Solution:');
disp_board(Solved_board);
disp('Time: '+string(t2)+'s.');
disp('Steps: '+string(counter)+'.');
elseif breaked
disp('Break point reached.');
disp('Time: '+string(t2)+'s.');
disp_board(Solved_board);
elseif ~valid_solved_board & ~breaked
disp('Invalid solution found.');
disp_board(Solved_board);
end</syntaxhighlight>
 
{{out}}
 
<pre> Initial board:
 
!5 3 × | × 7 × | × × × !
! !
!6 × × | 1 9 5 | × × × !
! !
!× 9 8 | × × × | × 6 × !
! !
!- - - - - - - - - - - !
! !
!8 × × | × 6 × | × × 3 !
! !
!4 × × | 8 × 3 | × × 1 !
! !
!7 × × | × 2 × | × × 6 !
! !
!- - - - - - - - - - - !
! !
!× 6 × | × × × | 2 8 × !
! !
!× × × | 4 1 9 | × × 5 !
! !
!× × × | × 8 × | × 7 9 !
 
Solved!
 
Solution:
 
!5 3 4 | 6 7 8 | 9 1 2 !
! !
!6 7 2 | 1 9 5 | 3 4 8 !
! !
!1 9 8 | 3 4 2 | 5 6 7 !
! !
!- - - - - - - - - - - !
! !
!8 5 9 | 7 6 1 | 4 2 3 !
! !
!4 2 6 | 8 5 3 | 7 9 1 !
! !
!7 1 3 | 9 2 4 | 8 5 6 !
! !
!- - - - - - - - - - - !
! !
!9 6 1 | 5 3 7 | 2 8 4 !
! !
!2 8 7 | 4 1 9 | 6 3 5 !
! !
!3 4 5 | 2 8 6 | 1 7 9 !
 
Time: 1.7142502s.
 
Steps: 8365.</pre>
 
=={{header|Sidef}}==
{{trans|Raku}}
<syntaxhighlight lang="ruby">func check(i, j) is cached {
var (id, im) = i.divmod(9)
var (jd, jm) = j.divmod(9)
 
jd == id && return true
jm == im && return true
 
(id//3 == jd//3) &&
(jm//3 == im//3)
}
 
func solve(grid) {
for i in ^grid {
grid[i] && next
var t = [grid[{|j| check(i, j) }.grep(^grid)]].freq
 
{ |k|
t.has_key(k) && next
grid[i] = k
solve(grid)
} << 1..9
 
grid[i] = 0
return nil
}
 
for i in ^grid {
print "#{grid[i]} "
print " " if (3 -> divides(i+1))
print "\n" if (9 -> divides(i+1))
print "\n" if (27 -> divides(i+1))
}
}
 
var grid = %i(
5 3 0 0 2 4 7 0 0
0 0 2 0 0 0 8 0 0
1 0 0 7 0 3 9 0 2
 
0 0 8 0 7 2 0 4 9
0 2 0 9 8 0 0 7 0
7 9 0 0 0 0 0 8 0
 
0 0 0 0 3 0 5 0 6
9 6 0 0 1 0 3 0 0
0 5 0 6 9 0 0 1 0
)
 
solve(grid)</syntaxhighlight>
{{out}}
<pre>5 3 9 8 2 4 7 6 1
6 7 2 1 5 9 8 3 4
1 8 4 7 6 3 9 5 2
 
3 1 8 5 7 2 6 4 9
4 2 5 9 8 6 1 7 3
7 9 6 3 4 1 2 8 5
 
8 4 1 2 3 7 5 9 6
9 6 7 4 1 5 3 2 8
2 5 3 6 9 8 4 1 7 </pre>
 
=={{header|Shale}}==
<syntaxhighlight lang="shale">
#!/usr/local/bin/shale
 
time library
 
// This solves a sudoku with:
// row/column/3x3box constraints (standard sudoku)
// row/column/irregular, or jigsaw, region constraints
// optionally with a Chess Knight's move constraint.
// It is based on the python code from the Computerphile video
// https://www.youtube.com/watch?v=G_UYXzGuqvM
// The sudoku example from this video is used below, along with
// a couple of Cracking The Cryptic examples and one from Andrew Stuart.
 
// The sudoku grid is stored in a multi-dimensional array under the grid:: namespace.
// The row and column of each cell is represented by:
//
// row column:: grid::
//
// A 0 value represents an empty cell, and a 1 to 9 value represents a cell value.
 
// You can specify which of the sudokus to solve by specifying s={n} on the command line.
// If it is not specified then you get a text explaining how to specify an option
// and what the options are and the default (s=1) option is solved.
 
startTime dup var now time::() =
 
whichSudoku var
 
s initialised {
whichSudoku s =
} {
"You can choose to solve one of several sudokus by adding s=n to the command line," println
"where n is" println
" 1: standard sudoku from Computerphile (the default)" println
" 2: standard sudoku from Cracking The Cryptic" println
" 3: standard sudoku from Cracking The Cryptic, with Knight's move constraint" println
" 4: standard sudoku from Cracking The Cryptic" println
" 5: irregular sudoku from Cracking The Cryptic" println
" 6: irregular sudoku from Andrew Stuart" println
"" println
"You can also enable colour output by adding colour=true or color=true to the command line." println
"" println
"For example," println
file arg:: shale:: " %s s=3 colour=true\n" printf
"will solve the CTC sudoku with the Knight's move constraint" println
"" println
whichSudoku 1 =
} if
 
// Prints the sudoku grid.
printGrid dup var {
r var
c var
doColour var
irregular var
region var
 
colour initialised {
doColour colour =
} {
color initialised {
doColour color =
} {
doColour false =
} if
} if
irregular 0 0:: regions:: initialised =
 
r 0 =
{ r 9 < } {
c 0 =
{ c 9 < } {
doColour {
irregular {
region r.value c.value:: regions:: =
region.value colour:: 0x1b "%c[1;%dm" printf
} {
r 3 / c 3 / + 1 + 2 % 3 * 31 + 0x1b "%c[1;%dm" printf
} if
} ifthen
r.value c.value:: grid:: dup 0 == { pop " ." } { " %d" } if printf
doColour {
0x1b "%c[0m" printf
} ifthen
c++
} while
"" println
r++
} while
} =
 
// This sets up the colour map for irregular sudokus.
1 colour:: dup var 30 =
2 colour:: dup var 31 =
3 colour:: dup var 32 =
4 colour:: dup var 33 =
5 colour:: dup var 34 =
6 colour:: dup var 35 =
7 colour:: dup var 36 =
8 colour:: dup var 30 = // skip 37 (too light) and reuse 30 and 31 (with luck they won't be close to regions 1 and 2).
9 colour:: dup var 31 =
 
// Assign the cell values to one row of the grid.
setRow dup var {
8$ dup var swap = // cell 9 of the row
7$ dup var swap = // cell 8 of the row
6$ dup var swap = // ...
5$ dup var swap =
4$ dup var swap =
3$ dup var swap =
2$ dup var swap =
1$ dup var swap = // ...
0$ dup var swap = // cell 1 of the row
r dup var swap = // the row number
ns dup var swap &= // the namespace to use
i var // loop counter
 
r 0 < r 8 > or {
r "Illegal row %d\n" printf
1 exit
} ifthen
 
i 0 =
{ i 9 < } {
i.value$ 0 < i.value$ 9 > or {
i r i.value$ "Illegal value %d specified for r%dc%d\n" printf
1 exit
} ifthen
r.value i.value:: ns->:: defined not { // define this grid cell if not already defined
r.value i.value:: ns->:: var
} ifthen
r.value i.value:: ns->:: i.value$ = // assign the value to the grid cell
i++
} while
} =
 
// Standard 3x3 box region checker.
// This only works when called from within possible().
standardRegions dup var {
r0 var
c0 var
 
r0 r 3 / 3 * =
c0 c 3 / 3 * =
i 0 =
{ i 3 < } {
j 0 =
{ j 3 < } {
r0 i + c0 j +:: grid:: n == {
false return
} ifthen
j++
} while
i++
} while
} =
 
// Irregular region checker.
// This only works when called from within possible().
irregularRegions dup var {
region var
i var
 
region r.value c.value:: regions:: = // The region we are in.
 
i 0 =
{ i 9 < } {
i.value r:: region.value:: region:: value i.value c:: region.value:: region:: value:: grid:: n == {
false return
} ifthen
i++
} while
} =
 
// Convert the regions:: namespace into something a little more cpu-time friendly.
// Only optimise if there are irregular regions defined.
optimiseRegions dup var {
0 0:: regions:: initialised {
region var
r var
c var
i var
 
region 1 =
{ region 10 < } {
i 0 =
r 0 =
{ r 9 < } {
c 0 =
{ c 9 < } {
r.value c.value:: regions:: region == {
i.value r:: region.value:: region:: dup var r =
i.value c:: region.value:: region:: dup var c =
i++
} ifthen
c++
} while
r++
} while
i 9 != {
i region "Region %d contains the wrong number of cells (%d)\n" printf
1 exit
} ifthen
region++
} while
} ifthen
} =
 
// Is it possible to place a digit in a given cell?
possible dup var { function
n dup var swap =
c dup var swap =
r dup var swap =
i var
j var
 
// Check the column doesn't already contain this value.
i 0 =
{ i 9 < } {
r.value i.value:: grid:: n == {
false return
} ifthen
i++
} while
 
// Check the row doesn't already contain this value.
i 0 =
{ i 9 < } {
i.value c.value:: grid:: n == {
false return
} ifthen
i++
} while
 
// Check that the region doesn't already contain this value.
regionChecker()
 
// Check for any other constraint.
constraint initialised { r c n constraint() not } and {
false return
} ifthen
 
true
} =
 
// This is a Knight's move constraint.
knightsMoveConstraint dup var { function
0$ dup var swap = // n
1$ dup var swap = // column
2$ dup var swap = // row
nr var
nc var
 
// Check Knight's move 2 left and 1 up and down.
nc 1$ 2 - =
nc 0 >= {
nr 2$ 1 - =
nr 0 >= {
nr.value nc.value:: grid:: 0$ == {
false return
} ifthen
} ifthen
nr 2$ 1 + =
nr 9 < {
nr.value nc.value:: grid:: 0$ == {
false return
} ifthen
} ifthen
} ifthen
 
// Check Knight's move 1 left and 2 up and down.
nc 1$ 1 - =
nc 0 >= {
nr 2$ 2 - =
nr 0 >= {
nr.value nc.value:: grid:: 0$ == {
false return
} ifthen
} ifthen
nr 2$ 2 + =
nr 9 < {
nr.value nc.value:: grid:: 0$ == {
false return
} ifthen
} ifthen
} ifthen
 
// Check Knight's move 1 right and 2 up and down.
nc 1$ 1 + =
nc 9 < {
nr 2$ 2 - =
nr 0 >= {
nr.value nc.value:: grid:: 0$ == {
false return
} ifthen
} ifthen
nr 2$ 2 + =
nr 9 < {
nr.value nc.value:: grid:: 0$ == {
false return
} ifthen
} ifthen
} ifthen
 
// Check Knight's move 2 right and 1 up and down.
nc 1$ 2 + =
nc 9 < {
nr 2$ 1 - =
nr 0 >= {
nr.value nc.value:: grid:: 0$ == {
false return
} ifthen
} ifthen
nr 2$ 1 + =
nr 9 < {
nr.value nc.value:: grid:: 0$ == {
false return
} ifthen
} ifthen
} ifthen
 
true
} =
 
// Set this to standardRegions for the usual 3x3 boxes,
// or irregularRegions to handle irregular, or jigsaw, regions.
regionChecker var
 
// Leave this undefined to get the standard sudoku rules, or set this
// to constraint code such as knightsMoveConstraint defined above.
constraint var
 
solve dup var { function
r var
c var
n var
 
r 0 =
{ r 9 < } {
c 0 =
{ c 9 < } {
r.value c.value:: grid:: dup 0 == { // dup r.value c.value:: grid:: so we don't have to recalculate it in the inner loop.
n 1 =
{ n 10 < } {
r.value c.value n.value possible() {
dup n = // picking up r.value c.value:: grid:: again.
solve()
dup 0 = // picking up r.value c.value:: grid:: again.
} ifthen
n++
} while
pop // get rid of r.value c.value:: grid::
return
} ifthen
pop // get rid of r.value c.value:: grid::
c++
} while
r++
} while
 
"" println
printGrid()
now time::() startTime - 1000.0 / "Solution in %0.3f seconds\n" printf
} =
 
found var
found false =
 
// As mentioned above, this is the example taken from the Computerphile video.
// Raspberry Pi3 Model A time: 17s to the solution, 19s to finish.
// The time spent between the solution and the finish is the script searching
// of other, non-existant, soultion.
whichSudoku 1 == {
found true =
"From Computerphile: https://www.youtube.com/watch?v=G_UYXzGuqvM" println
regionChecker standardRegions =
grid 0 5 3 0 0 7 0 0 0 0 setRow()
grid 1 6 0 0 1 9 5 0 0 0 setRow()
grid 2 0 9 8 0 0 0 0 6 0 setRow()
grid 3 8 0 0 0 6 0 0 0 3 setRow()
grid 4 4 0 0 8 0 3 0 0 1 setRow()
grid 5 7 0 0 0 2 0 0 0 6 setRow()
grid 6 0 6 0 0 0 0 2 8 0 setRow()
grid 7 0 0 0 4 1 9 0 0 5 setRow()
grid 8 0 0 0 0 8 0 0 7 9 setRow()
} ifthen
 
// From https://www.youtube.com/watch?v=MXUgYxHmKq4&t=0s
// This sudoku was featured on Cracking The Cryptic, and takes considerably longer than the one above.
// Pi3 Model A time: 3m 23s to the solution, 15m 11s to finish.
whichSudoku 2 == {
found true =
"From Cracking The Cryptic: https://www.youtube.com/watch?v=MXUgYxHmKq4&t=0s" println
regionChecker standardRegions =
grid 0 0 6 8 0 0 0 0 1 3 setRow()
grid 1 0 0 0 9 0 1 0 0 0 setRow()
grid 2 0 0 0 0 0 8 0 0 4 setRow()
grid 3 0 1 0 0 4 0 5 0 0 setRow()
grid 4 0 3 0 0 0 9 0 0 0 setRow()
grid 5 0 8 5 0 0 0 0 7 0 setRow()
grid 6 0 2 0 0 0 7 3 0 0 setRow()
grid 7 0 0 0 0 9 4 0 0 6 setRow()
grid 8 4 0 0 0 6 0 0 0 0 setRow()
} ifthen
 
// From https://www.youtube.com/watch?v=rQHV-gIAG_0
// Another Cracking The Cryptic video, this one with a Knight's move constraint.
// Pi3 Model A time: 48s to the solution, 6m 10s to finish.
whichSudoku 3 == {
found true =
"From Cracking The Cryptic: https://www.youtube.com/watch?v=rQHV-gIAG_0" println
"This includes a Chess Knight's move constraint." println
regionChecker standardRegions =
constraint knightsMoveConstraint =
grid 0 0 0 0 0 0 6 0 0 0 setRow()
grid 1 0 0 3 0 0 0 0 0 7 setRow()
grid 2 2 0 0 3 0 0 4 9 0 setRow()
grid 3 6 0 0 0 0 0 0 4 5 setRow()
grid 4 0 0 2 0 0 0 8 0 0 setRow()
grid 5 0 0 0 1 0 0 0 0 0 setRow()
grid 6 3 0 0 0 0 0 0 0 0 setRow()
grid 7 7 0 0 0 0 1 0 0 9 setRow()
grid 8 0 0 0 0 0 0 5 0 0 setRow()
} ifthen
 
// Another CTC sudoku: https://www.youtube.com/watch?v=vH-JooV8RA4&t=0s
// Pi3 Model A time: 1m 6s to the solution, 48m 35s to finish.
whichSudoku 4 == {
found true =
"From Cracking The Cryptic: https://www.youtube.com/watch?v=vH-JooV8RA4&t=0s" println
regionChecker standardRegions =
grid 0 0 0 0 0 0 0 0 0 0 setRow()
grid 1 0 0 9 8 0 0 0 0 7 setRow()
grid 2 0 8 0 0 6 0 0 5 0 setRow()
grid 3 0 5 0 0 4 0 0 3 0 setRow()
grid 4 0 0 7 9 0 0 0 0 2 setRow()
grid 5 0 0 0 0 0 0 0 0 0 setRow()
grid 6 0 0 2 7 0 0 0 0 9 setRow()
grid 7 0 4 0 0 5 0 0 6 0 setRow()
grid 8 3 0 0 0 0 6 2 0 0 setRow()
} ifthen
 
// Another Cracking The Cryptic sudoku: https://www.youtube.com/watch?v=eJIu8w3ZXo8
// This is an irregular (jigsaw) sudoku.
// Pi3 Model A time: 2m 5s to the solution, 7m 5s to finish.
whichSudoku 5 == {
found true =
"From Cracking The Cryptic: https://www.youtube.com/watch?v=eJIu8w3ZXo8" println
"An irregular sudoku." println
regionChecker irregularRegions =
regions 0 1 1 1 1 1 2 2 2 2 setRow()
regions 1 1 3 3 3 6 6 2 2 2 setRow()
regions 2 1 3 3 3 6 7 7 7 2 setRow()
regions 3 1 3 3 3 6 7 7 7 2 setRow()
regions 4 1 6 6 6 6 7 7 7 8 setRow()
regions 5 9 6 4 4 4 8 8 8 8 setRow()
regions 6 9 9 4 4 4 8 5 5 5 setRow()
regions 7 9 9 4 4 4 8 5 5 5 setRow()
regions 8 9 9 9 9 8 8 5 5 5 setRow()
grid 0 3 0 0 0 0 0 0 0 1 setRow()
grid 1 0 9 0 1 7 2 0 0 0 setRow()
grid 2 0 0 3 0 0 0 9 0 0 setRow()
grid 3 0 7 0 0 0 0 0 4 0 setRow()
grid 4 0 4 0 0 3 0 0 6 0 setRow()
grid 5 0 5 0 0 0 0 0 9 0 setRow()
grid 6 0 0 6 0 0 0 5 0 0 setRow()
grid 7 0 0 0 8 5 6 0 2 0 setRow()
grid 8 7 0 0 0 0 0 0 0 8 setRow()
} ifthen
 
// This is taken from Andrew Stuart's web site https://www.sudokuwiki.org/Daily_Jigsaw_Sudoku
// No. 4294, dated 13 Nov 2020. It is rated 5-star out of 6: Diabolical.
// The archived version is here: https://www.sudokuwiki.org/Print_Daily_Jigsaw.asp?day=13/11/2020
// At the time of writing, Andrew only archives sudoku's for 31 days, then they are deleted.
// The region layout is called "Andrew Stuart 24" and the numbering is taken directly
// from Andrew's solver page. A big thanks goes to Andrew for giving me permission to include this sudoku.
// The region numbers must be between 1 and 9 inclusive.
// Pi3 Model A time: 26m 23s to the solution, 1h 15m 20s to finish.
whichSudoku 6 == {
found true =
"From Andrew Stuart's web page: https://www.sudokuwiki.org/Daily_Jigsaw_Sudoku" println
"No. 4294, dated 13 Nov 2020" println
regionChecker irregularRegions =
regions 0 1 1 2 2 2 2 3 3 4 setRow()
regions 1 1 1 2 2 2 3 3 3 4 setRow()
regions 2 1 1 1 2 3 3 3 4 4 setRow()
regions 3 1 1 5 2 3 7 4 4 4 setRow()
regions 4 5 5 5 6 6 7 7 4 4 setRow()
regions 5 5 5 5 6 6 7 7 7 9 setRow()
regions 6 8 5 5 6 6 7 7 7 9 setRow()
regions 7 8 8 6 6 6 9 9 9 9 setRow()
regions 8 8 8 8 8 8 8 9 9 9 setRow()
grid 0 0 0 0 0 0 0 0 9 0 setRow()
grid 1 5 0 0 0 8 1 0 0 0 setRow()
grid 2 0 0 0 9 0 4 5 0 0 setRow()
grid 3 0 0 0 0 0 0 0 0 5 setRow()
grid 4 0 1 0 0 0 8 0 0 0 setRow()
grid 5 7 0 6 0 0 0 0 0 0 setRow()
grid 6 0 0 0 1 0 0 6 0 0 setRow()
grid 7 1 0 0 7 2 0 0 0 0 setRow()
grid 8 0 9 0 0 0 0 0 0 0 setRow()
} ifthen
 
// If you want to add your own sudoku, add it here.
whichSudoku 7 == {
found true =
// add it here
// regionChecker standardRegions = // Include a region checker
// regionChecker irregularRegions =
// constraint knightsMoveConstraint = // Include any extra contraints, as appropriate
} ifthen
 
// Don't change anything from here to the end.
 
found {
optimiseRegions()
 
"" println
"Initial grid" println
printGrid()
 
solve()
 
now time::() startTime - 1000.0 / "Total runtime was %0.3f seconds\n" printf
} {
whichSudoku "Sudoku %d not found\n" printf
} if
 
// I'd like to see an irregular sudoku with a knight's move constraint. Any takers...
</syntaxhighlight>
 
'''Output'''
 
<pre>
From Cracking The Cryptic: https://www.youtube.com/watch?v=rQHV-gIAG_0
This includes a Chess Knight's move constraint.
 
Initial grid
. . . . . 6 . . .
. . 3 . . . . . 7
2 . . 3 . . 4 9 .
6 . . . . . . 4 5
. . 2 . . . 8 . .
. . . 1 . . . . .
3 . . . . . . . .
7 . . . . 1 . . 9
. . . . . . 5 . .
 
1 9 7 8 4 6 2 5 3
8 4 3 5 9 2 6 1 7
2 6 5 3 1 7 4 9 8
6 1 9 2 3 8 7 4 5
5 7 2 4 6 9 8 3 1
4 3 8 1 7 5 9 2 6
3 8 6 9 5 4 1 7 2
7 5 4 6 2 1 3 8 9
9 2 1 7 8 3 5 6 4
Solution in 7.241 seconds
Total runtime was 53.995 seconds
</pre>
 
=={{header|SQL}}==
{{works with|oracle|11.2 and higher}}
 
The implementation below uses a recursive WITH clause (aka recursive CTE, recursive query, recursive factored subquery). This is supported - with minimal syntactical differences - by some (perhaps many) but not all SQL dialects. The code was written and tested in Oracle SQL; Oracle has supported recursive subqueries since version 11.2.
 
The code implements a brute force algorithm. It can solve most problems in less than half a second (depending on hardware too), although I found a few that take 2-3 and up to 6 seconds. The output may either be empty (when the problem is impossible), a single completed grid (for a "correct" problem), or all the correct solutions to problems that admit more than one solution.
 
The input and output are presented as strings of 81 characters, where each character is either a digit or a space (indicating an empty cell in the grid). The translation between grids and such strings is trivial (convert grid to string by concatenating rows, reading left to right and then top to bottom), and not covered in the solution. The input is given as a bind variable, ''':game'''.
 
<syntaxhighlight lang="sql">with
symbols (d) as (select to_char(level) from dual connect by level <= 9)
, board (i) as (select level from dual connect by level <= 81)
, neighbors (i, j) as (
select b1.i, b2.i
from board b1 inner join board b2
on b1.i != b2.i
and (
mod(b1.i - b2.i, 9) = 0
or ceil(b1.i / 9) = ceil(b2.i / 9)
or ceil(b1.i / 27) = ceil(b2.i / 27) and trunc(mod(b1.i - 1, 9) / 3) = trunc(mod(b2.i - 1, 9) / 3)
)
)
, r (str, pos) as (
select :game, instr(:game, ' ')
from dual
union all
select substr(r.str, 1, r.pos - 1) || s.d || substr(r.str, r.pos + 1), instr(r.str, ' ', r.pos + 1)
from r inner join symbols s
on r.pos > 0 and not exists (
select *
from neighbors n
where r.pos = n.i and s.d = substr(r.str, n.j, 1)
)
)
select str
from r
where pos = 0
;</syntaxhighlight>
 
A better (faster) approach - taking advantage of database-specific features - is to create a '''table''' NEIGHBORS (similar to the inline view in the WITH clause) and an index on column I of that table; then the query execution time drops by more than half in most cases.
 
=={{header|Stata}}==
 
In this implementation, a Sudoku is a 9x9 matrix a, with either digits 1-9 or missing values. A cell is any element of a. A cell can be reference with indices i,j, or with a single index n between 1 and 81.
 
Three functions are defined:
* sudoku(a) will return 0 if there is no solution, 1 if there is '''at least''' one solution, and then a is modified in place with the solution found. This function builds several tables before calling the main "solver" function.
* solve(a,s,t,v,w) is made of two parts: first, all cells that can be filled without any assumption are considered known. Then, if not all cells are known, a cell with minimal number of choices is found, and a recursive call to solve is made with all possibilities in turn for this cell.
* push(a,s,t,v,w,n,z) is an auxiliary function, which pushes the value z in the nth cell of matrix a. Here n is a value between 1 and 81.
 
Fixed tables:
* t(n,.) is a row i,j,k: the cell n (1-81) has row index i, column index j, and square index k, where i, j, k are all in 1-9.
* s(n,.) is a row that contains the indices of the 20 "neighbors" of cell n: these are the cells in the same row, column or square.
 
Varying tables:
* v(n,z)=1 if the cell n may have the value z, otherwise 0. When a value z is pushed into the matrix, all neighboring cells are updated, as they can't take the value z anymore.
* w(n)=1 if cell n is not yet known, otherwise 0.
* In the initialization step of the sudoku() function, w has another meaning: it stores the column index of the last entry in row n of the array s while it is built. When it's done, every element of w is thus twenty.
 
The example grid given below is taken from [https://en.wikipedia.org/wiki/Sudoku_solving_algorithms Wikipedia]. It does not require any recursive call (it's entirely filled in the first step of ''solve''), as can be seen with additional ''printf'' in the code to follow the algorithm.
 
<syntaxhighlight lang="stata">mata
function sudoku(a) {
s = J(81,20,.)
t = J(81,3,.)
v = J(81,9,1)
w = J(81,1,0)
for (i=1; i<=9; i++) {
for (j=1; j<=9; j++) {
n = (i-1)*9+j
k = floor((i-1)/3)*3+floor((j-1)/3)+1
t[n,.] = i,j,k
}
}
for (i=1; i<=81; i++) {
for (j=i+1; j<=81; j++) {
if (any(t[i,.]:==t[j,.])) {
w[i]=w[i]+1
w[j]=w[j]+1
s[i,w[i]] = j
s[j,w[j]] = i
}
}
}
w = J(81,1,1)
for (i=1; i<=9; i++) {
for (j=1; j<=9; j++) {
if (a[i,j]<.) {
push(a,s,t,v,w,(i-1)*9+j,a[i,j])
}
}
}
return(solve(a,s,t,v,w))
}
 
function solve(a,s,t,v,w) {
for (q=1; q;) {
q = 0
for (n=1; n<=81; n++) {
if (w[n]) {
r = sum(v[n,.])
if (r==0) {
return(0)
}
else if (r==1) {
q = 1
push(a,s,t,v,w,n,selectindex(v[n,.]))
}
}
}
}
if (all(w:==0)) {
return(1)
}
else {
m0 = n0 = .
for (n=1; n<=81; n++) {
m = sum(v[n,.])
if (w[n] & m>1 & m<m0) {
m0 = m
n0 = n
}
}
z = selectindex(v[n0,.])
for (i=1; i<=m0; i++) {
a2 = a
v2 = v
w2 = w
push(a2,s,t,v2,w2,n0,z[i])
if (solve(a2,s,t,v2,w2)) {
a = a2
return(1)
}
}
return(0)
}
}
 
function push(a,s,t,v,w,n,z) {
w[n] = 0
i = t[n,1]
j = t[n,2]
a[i,j] = z
for (k=1; k<=20; k++) {
v[s[n,k],z] = 0
}
}
 
a = 5,3,.,.,7,.,.,.,.\
6,.,.,1,9,5,.,.,.\
.,9,8,.,.,.,.,6,.\
8,.,.,.,6,.,.,.,3\
4,.,.,8,.,3,.,.,1\
7,.,.,.,2,.,.,.,6\
.,6,.,.,.,.,2,8,.\
.,.,.,4,1,9,.,.,5\
.,.,.,.,8,.,.,7,9
 
sudoku(a)
a
end</syntaxhighlight>
 
'''Output'''
 
<pre>1
 
1 2 3 4 5 6 7 8 9
+-------------------------------------+
1 | 5 3 4 6 7 8 9 1 2 |
2 | 6 7 2 1 9 5 3 4 8 |
3 | 1 9 8 3 4 2 5 6 7 |
4 | 8 5 9 7 6 1 4 2 3 |
5 | 4 2 6 8 5 3 7 9 1 |
6 | 7 1 3 9 2 4 8 5 6 |
7 | 9 6 1 5 3 7 2 8 4 |
8 | 2 8 7 4 1 9 6 3 5 |
9 | 3 4 5 2 8 6 1 7 9 |
+-------------------------------------+</pre>
 
Two more examples, from [http://www.7sudoku.com/very-difficult here] and [http://www.extremesudoku.info/sudoku.html there].
 
<syntaxhighlight lang="stata">a = 7,9,.,.,.,3,.,.,2\
.,6,.,5,1,.,.,.,.\
.,.,.,.,.,2,.,.,6\
.,.,.,8,.,1,.,4,.\
.,.,.,.,.,.,1,.,3\
5,.,.,.,2,.,.,.,.\
.,.,.,.,.,.,.,7,4\
.,.,1,.,.,.,.,6,5\
.,.,8,.,9,7,.,.,.
 
sudoku(a)
a
 
 
1 2 3 4 5 6 7 8 9
+-------------------------------------+
1 | 7 9 5 6 8 3 4 1 2 |
2 | 2 6 4 5 1 9 7 3 8 |
3 | 1 8 3 7 4 2 5 9 6 |
4 | 9 3 6 8 5 1 2 4 7 |
5 | 8 4 2 9 7 6 1 5 3 |
6 | 5 1 7 3 2 4 6 8 9 |
7 | 3 2 9 1 6 5 8 7 4 |
8 | 4 7 1 2 3 8 9 6 5 |
9 | 6 5 8 4 9 7 3 2 1 |
+-------------------------------------+
 
a = .,.,4,1,.,.,.,.,9\
.,9,.,.,8,.,.,6,.\
6,.,.,.,.,3,7,.,.\
5,.,.,.,.,2,8,.,.\
.,4,.,.,3,.,.,2,.\
.,.,1,8,.,.,.,.,5\
.,.,2,5,.,.,.,.,3\
.,8,.,.,7,.,.,1,.\
7,.,.,.,.,1,4,.,.
 
sudoku(a)
a
 
 
1 2 3 4 5 6 7 8 9
+-------------------------------------+
1 | 2 7 4 1 5 6 3 8 9 |
2 | 1 9 3 7 8 4 5 6 2 |
3 | 6 5 8 2 9 3 7 4 1 |
4 | 5 3 7 6 1 2 8 9 4 |
5 | 8 4 6 9 3 5 1 2 7 |
6 | 9 2 1 8 4 7 6 3 5 |
7 | 4 1 2 5 6 8 9 7 3 |
8 | 3 8 5 4 7 9 2 1 6 |
9 | 7 6 9 3 2 1 4 5 8 |
+-------------------------------------+</syntaxhighlight>
 
=={{header|Swift}}==
{{trans|Java}}
<syntaxhighlight lang="swift">import Foundation
 
typealias SodukuPuzzle = [[Int]]
 
class Soduku {
let mBoardSize:Int!
let mBoxSize:Int!
var mBoard:SodukuPuzzle!
var mRowSubset:[[Bool]]!
var mColSubset:[[Bool]]!
var mBoxSubset:[[Bool]]!
init(board:SodukuPuzzle) {
mBoard = board
mBoardSize = board.count
mBoxSize = Int(sqrt(Double(mBoardSize)))
mRowSubset = [[Bool]](count: mBoardSize, repeatedValue: [Bool](count: mBoardSize, repeatedValue: false))
mColSubset = [[Bool]](count: mBoardSize, repeatedValue: [Bool](count: mBoardSize, repeatedValue: false))
mBoxSubset = [[Bool]](count: mBoardSize, repeatedValue: [Bool](count: mBoardSize, repeatedValue: false))
initSubsets()
}
func computeBoxNo(i:Int, _ j:Int) -> Int {
let boxRow = i / mBoxSize
let boxCol = j / mBoxSize
return boxRow * mBoxSize + boxCol
}
func initSubsets() {
for i in 0..<mBoard.count {
for j in 0..<mBoard.count {
let value = mBoard[i][j]
if value != 0 {
setSubsetValue(i, j, value, true);
}
}
}
}
func isValid(i:Int, _ j:Int, var _ val:Int) -> Bool {
val--
let isPresent = mRowSubset[i][val] || mColSubset[j][val] || mBoxSubset[computeBoxNo(i, j)][val]
return !isPresent
}
func printBoard() {
for i in 0..<mBoardSize {
if i % mBoxSize == 0 {
println(" -----------------------")
}
for j in 0..<mBoardSize {
if j % mBoxSize == 0 {
print("| ")
}
print(mBoard[i][j] != 0 ? String(mBoard[i][j]) : " ")
print(" ")
}
println("|")
}
println(" -----------------------")
}
func setSubsetValue(i:Int, _ j:Int, _ value:Int, _ present:Bool) {
mRowSubset[i][value - 1] = present
mColSubset[j][value - 1] = present
mBoxSubset[computeBoxNo(i, j)][value - 1] = present
}
func solve() {
solve(0, 0)
}
func solve(var i:Int, var _ j:Int) -> Bool {
if i == mBoardSize {
i = 0
j++
if j == mBoardSize {
return true
}
}
if mBoard[i][j] != 0 {
return solve(i + 1, j)
}
for value in 1...mBoardSize {
if isValid(i, j, value) {
mBoard[i][j] = value
setSubsetValue(i, j, value, true)
if solve(i + 1, j) {
return true
}
setSubsetValue(i, j, value, false)
}
}
mBoard[i][j] = 0
return false
}
}
 
let board = [
[4, 0, 0, 0, 0, 0, 0, 6, 0],
[5, 0, 0, 0, 8, 0, 9, 0, 0],
[3, 0, 0, 0, 0, 1, 0, 0, 0],
[0, 2, 0, 7, 0, 0, 0, 0, 1],
[0, 9, 0, 0, 0, 0, 0, 4, 0],
[8, 0, 0, 0, 0, 3, 0, 5, 0],
[0, 0, 0, 2, 0, 0, 0, 0, 7],
[0, 0, 6, 0, 5, 0, 0, 0, 8],
[0, 1, 0, 0, 0, 0, 0, 0, 6]
]
 
let puzzle = Soduku(board: board)
puzzle.solve()
puzzle.printBoard()</syntaxhighlight>
{{out}}
<pre>
-----------------------
| 4 8 2 | 9 7 5 | 1 6 3 |
| 5 6 1 | 3 8 2 | 9 7 4 |
| 3 7 9 | 6 4 1 | 8 2 5 |
-----------------------
| 6 2 5 | 7 9 4 | 3 8 1 |
| 1 9 3 | 5 6 8 | 7 4 2 |
| 8 4 7 | 1 2 3 | 6 5 9 |
-----------------------
| 9 5 8 | 2 1 6 | 4 3 7 |
| 7 3 6 | 4 5 9 | 2 1 8 |
| 2 1 4 | 8 3 7 | 5 9 6 |
-----------------------
</pre>
 
{{works with|Swift 3}}
 
<syntaxhighlight lang="swift">
func solving(board: [[Int]]) -> [[Int]] {
var board = board
var isSolved = false
while !isSolved {
for x in 0 ..< 9 {
for y in 0 ..< 9 {
if board[x][y] == 0 {
let known = Set(board.map { $0[y] } + board[x] + subgrid(board, pos: (x, y)))
let possible = Set(Array(1...9)).subtracting(known)
if possible.count == 1 {
board[x][y] = possible.first!
}
}
}
isSolved = 45 == board[x].reduce(0, +)
}
}
return board
}
 
func subgrid(_ board: [[Int]], pos: (Int, Int)) -> [Int] {
var r = [Int]()
var (x, y) = pos
x = x / 3 * 3
y = y / 3 * 3
for i in x ..< x + 3 {
for j in y ..< y + 3 {
r.append(board[i][j])
}
}
return r
}
 
func print(_ board: [[Int]]) {
for i in board.indices {
if i % 9 == 0 {
print(" -------------------")
}
for j in board.indices {
if j % board.count == 0 {
print("| ", terminator: "")
}
let digit = board[i][j]
print(digit != 0 ? digit : " ", terminator: "")
print(" ", terminator: "")
}
print("|")
}
print(" -------------------")
}
 
let puzzle = [
[0,2,0,4,5,0,7,0,9],
[0,0,0,1,0,9,0,3,0],
[0,0,8,0,0,0,1,0,4],
[0,4,0,0,6,1,0,7,0],
[5,0,6,0,3,0,0,1,0],
[0,3,0,0,0,2,0,9,0],
[3,0,4,0,7,5,0,6,8],
[0,9,0,0,1,0,3,0,7],
[0,0,2,0,0,3,0,0,1]
]
 
print(solving(board: puzzle))
</syntaxhighlight>
{{out}}
<pre>
-------------------
| 1 2 3 4 5 6 7 8 9 |
| 4 5 7 1 8 9 2 3 6 |
| 9 6 8 3 2 7 1 5 4 |
| 2 4 9 5 6 1 8 7 3 |
| 5 7 6 9 3 8 4 1 2 |
| 8 3 1 7 4 2 6 9 5 |
| 3 1 4 2 7 5 9 6 8 |
| 6 9 5 8 1 4 3 2 7 |
| 7 8 2 6 9 3 5 4 1 |
-------------------
</pre>
 
=={{header|SystemVerilog}}==
 
 
<syntaxhighlight lang="systemverilog">
 
//////////////////////////////////////////////////////////////////////////////
/// SudokuSolver ///
/// A class that fills up a sudoku board, the initial board is given ///
/// as an array preset_rows, the positions where preset_rows is zero ///
/// are to be determined. Three views of the sudoku board are created ///
/// and the uniqueness of its elements are defined by on constraint for ///
/// each view, one constraint ensures that the values are between 1 and ///
/// 9, and two other constraints are used to ensure that the values in ///
/// all three views agree to each other. ///
/// ///
/// ///
/// A solution using only the "rows" array would be possible, however ///
/// this illustrates better how one can relate different variables in ///
/// SystemVerilog Constrained randomization. ///
//////////////////////////////////////////////////////////////////////////////
class SudokuSolver;
rand int tiles[0:8][0:8];
rand int rows[0:8][0:8];
rand int cols[0:8][0:8];
int preset_rows[0:8][0:8];
constraint board_input {
foreach(preset_rows[i])foreach(preset_rows[i][j])
if(preset_rows[i][j] != 0) rows[i][j] == preset_rows[i][j];
}
constraint range {
foreach(rows[i]) foreach(rows[i][j])
rows[i][j] inside {[1:9]};
}
////////////////////////////////////////////////
/// Every number in a row is unique ///
////////////////////////////////////////////////
constraint rows_permutation {
foreach(rows[i]) foreach(rows[i][j1])
foreach(rows[i][j2])
if(j1 != j2) rows[i][j1] != rows[i][j2];
}
///////////////////////////////////////////////
/// Every number in a column is unique ///
///////////////////////////////////////////////
constraint cols_permutation {
foreach(cols[i]) foreach(cols[i][j1])
foreach(cols[i][j2])
if(j1 != j2) cols[i][j1] != cols[i][j2];
}
/////////////////////////////////////////////////
/// Every number in a tile (square) is unique ///
/////////////////////////////////////////////////
constraint tiles_permutation {
foreach(tiles[i]) foreach(tiles[i][j1])
foreach(tiles[i][j2])
if(j1 != j2) tiles[i][j1] != tiles[i][j2];
}
///////////////////////////////////////////////////
/// Makes sure that sure that the numbers in ///
/// each view agree with other views ///
///////////////////////////////////////////////////
constraint rows_vs_tiles {
foreach(tiles[i]) foreach(tiles[i][j])
tiles[i][j] == rows[(i/3) * 3 + (j/3)][3*(i%3)+(j%3)];
}
constraint rows_vs_cols {
foreach(cols[i]) foreach(cols[i][j])
cols[i][j] == rows[j][i];
}
///////////////////////////////////////////////////
/// Print the current state of the board in the ///
/// standard output ///
///////////////////////////////////////////////////
function void printBoard;
int i, j;
for(i = 0; i < 9; ++i) begin
if(i % 3 == 0)$display(" -------------");
$write(" ");
for(j = 0; j < 9; ++j) begin
if(j % 3 == 0) $write("|");
$write("%c", "0" + rows[i][j]);
end
$display("|");
end
$display(" -------------");
endfunction
function void printInitial;
int i, j;
for(i = 0; i < 9; ++i) begin
if(i % 3 == 0)$display("-------------");
for(j = 0; j < 9; ++j) begin
if(j % 3 == 0) $write("|");
if(preset_rows[i][j]) begin
$write("%c", "0" + preset_rows[i][j]);
end
else begin
$write(".");
end
end
$display("|");
end
$display("-------------");
endfunction
 
endclass
 
//////////////////////////////////////////////////////
/// Simple program instantiating the sudoku object ///
//////////////////////////////////////////////////////
program SudokuTest;
SudokuSolver board;
initial begin
board = new;
foreach(board.preset_rows[0][i]) board.preset_rows[i][i] = i+1;
$display("Initial Board:");
board.printInitial();
// Generate two different solutions for the board
if(board.randomize())begin
$display("One solution:");
board.printBoard();
end
else begin
$display("ERROR: Failed to generate first solution");
end
if(board.randomize())begin
$display("Another solution:");
board.printBoard();
end
else begin
$display("ERROR: Failed to generate second solution");
end
end
endprogram
</syntaxhighlight>
 
It can be seen that SystemVerilog randomization is a very powerfull tool, in this implementation I directly described the game constraints and the randomization engine takes care of producing solutions, and when multiple solutions are possible they will be chosen at random.
 
 
Running the above code using Cadence ncverilog I get
 
<pre>
> ncverilog +sv sudoku.sv
 
Initial Board:
-------------
|1..|...|...|
|.2.|...|...|
|..3|...|...|
-------------
|...|4..|...|
|...|.5.|...|
|...|..6|...|
-------------
|...|...|7..|
|...|...|.8.|
|...|...|..9|
-------------
One solution:
-------------
|168|547|392|
|925|631|478|
|743|928|156|
-------------
|832|479|561|
|671|852|934|
|459|316|827|
-------------
|396|284|715|
|214|795|683|
|587|163|249|
-------------
Another solution:
-------------
|197|642|358|
|425|389|176|
|683|715|294|
-------------
|956|431|827|
|842|957|631|
|731|826|945|
-------------
|214|598|763|
|569|173|482|
|378|264|519|
-------------
</pre>
 
=={{header|Tailspin}}==
There is a blog post about how this code was developed: https://tobega.blogspot.com/2020/05/creating-algorithm.html
<syntaxhighlight lang="tailspin">
templates deduceRemainingDigits
templates findOpenPosition
@:{options: 10"1"};
$ -> \[i;j](when <[]?($::length <..~$@findOpenPosition.options::raw>)> do @findOpenPosition: {row: $i, col: $j, options: ($::length)"1"}; \) -> !VOID
$@ !
end findOpenPosition
 
templates selectFirst&{pos:}
def digit: $($pos.row;$pos.col) -> $(1);
$ -> \[i;j](
when <?($i <=$pos.row>)?($j <=$pos.col>)> do $digit !
when <[]?($i <=$pos.row>)
|[]?($j <=$pos.col>)
|[]?(($i::raw-1)~/3 <=($pos.row::raw-1)~/3>)?(($j::raw-1)~/3 <=($pos.col::raw-1)~/3>)> do [$... -> \(when <~=$digit> do $! \)] !
when <> do $ !
\) !
end selectFirst
 
@: $;
$ -> findOpenPosition -> #
when <{options: <=0"1">}> do row´1:[] !
when <{options: <=10"1">}> do $@ !
when <> do def next: $;
$@ -> selectFirst&{pos: $next} -> deduceRemainingDigits
-> \(when <~=row´1:[]> do @deduceRemainingDigits: $; {options: 10"1"} !
when <=row´1:[]> do ^@deduceRemainingDigits($next.row;$next.col;1)
-> { $next..., options: $next.options-1"1"} ! \) -> #
end deduceRemainingDigits
 
test 'internal solver'
def sample: row´1:[
col´1:[5,3,4,6,7,8,9,1,2],
col´1:[6,7,2,1,9,5,3,4,8],
col´1:[1,9,8,3,4,2,5,6,7],
col´1:[8,5,9,7,6,1,4,2,3],
col´1:[4,2,6,8,5,3,7,9,1],
col´1:[7,1,3,9,2,4,8,5,6],
col´1:[9,6,1,5,3,7,2,8,4],
col´1:[2,8,7,4,1,9,6,3,5],
col´1:[3,4,5,2,8,6,1,7,9]
];
 
assert $sample -> deduceRemainingDigits <=$sample> 'completed puzzle unchanged'
 
assert row´1:[
col´1:[[5],3,4,6,7,8,9,1,2],
$sample(row´2..last)...] -> deduceRemainingDigits <=$sample> 'final digit gets placed'
 
assert row´1:[
col´1:[[],3,4,6,7,8,9,1,2],
$sample(row´2..last)...] -> deduceRemainingDigits <=row´1:[]> 'no remaining options returns empty'
 
assert row´1:[
col´1:[[5],3,4,6,[2,5,7],8,9,1,[2,5]],
$sample(row´2..last)...] -> deduceRemainingDigits <=$sample> 'solves 3 digits on row'
 
assert row´1:[
col´1:[5,3,4,6,7,8,9,1,2],
col´1:[[6,7,9],7,2,1,9,5,3,4,8],
col´1:[1,9,8,3,4,2,5,6,7],
col´1:[8,5,9,7,6,1,4,2,3],
col´1:[4,2,6,8,5,3,7,9,1],
col´1:[[7],1,3,9,2,4,8,5,6],
col´1:[[7,9],6,1,5,3,7,2,8,4],
col´1:[2,8,7,4,1,9,6,3,5],
col´1:[3,4,5,2,8,6,1,7,9]
] -> deduceRemainingDigits <=$sample> 'solves 3 digits on column'
 
assert row´1:[
col´1:[5,3,[4,6],6,7,8,9,1,2],
col´1:[[6],7,2,1,9,5,3,4,8],
col´1:[1,[4,6,9],8,3,4,2,5,6,7],
$sample(row´4..last)...
] -> deduceRemainingDigits <=$sample> 'solves 3 digits in block'
 
// This gives a contradiction if 3 gets chosen out of [3,5]
assert row´1:[
col´1:[[3,5],[3,4,6],[3,4,6],[3,4,6],7,8,9,1,2],
$sample(row´2..last)...] -> deduceRemainingDigits <=$sample> 'contradiction is backtracked'
end 'internal solver'
 
composer parseSudoku
row´1:[<section>=3]
rule section: <row>=3 (<'-+'>? <WS>?)
rule row: col´1:[<triple>=3] (<WS>?)
rule triple: <digit|dot>=3 (<'\|'>?)
rule digit: [<'\d'>]
rule dot: <'\.'> -> [1..9 -> '$;']
end parseSudoku
 
test 'input sudoku'
def parsed:
'53.|.7.|...
6..|195|...
.98|...|.67
-----------
8..|.6.|..3
4..|8.3|..1
7..|.2.|..6
-----------
.6.|...|28.
...|419|..5
...|.8.|.79' -> parseSudoku;
 
assert $parsed <[<[<[]>=9](9)>=9](9)> 'parsed sudoku has 9 rows containing 9 columns of lists'
assert $parsed(row´1;col´1) <=['5']> 'a digit'
assert $parsed(row´1;col´3) <=['1','2','3','4','5','6','7','8','9']> 'a dot'
end 'input sudoku'
 
templates solveSudoku
$ -> parseSudoku -> deduceRemainingDigits -> #
when <=row´1:[]> do 'No result found' !
when <> do $ -> \[i](
'$(col´1..col´3)...;|$(col´4..col´6)...;|$(col´7..col´9)...;$#10;' !
$i -> \(when <=row´3|=row´6> do '-----------$#10;' !\) !
\) -> '$...;' !
end solveSudoku
 
test 'sudoku solver'
assert
'53.|.7.|...
6..|195|...
.98|...|.67
-----------
8..|.6.|..3
4..|8.3|..1
7..|.2.|..6
-----------
.6.|...|28.
...|419|..5
...|.8.|.79'
-> solveSudoku <=
'534|678|912
672|195|348
198|342|567
-----------
859|761|423
426|853|791
713|924|856
-----------
961|537|284
287|419|635
345|286|179
'> 'solves sudoku and outputs pretty solution'
end 'sudoku solver'
</syntaxhighlight>
 
=={{header|Tcl}}==
Line 4,207 ⟶ 13,268:
Note that you can implement more rules if you want. Just make another subclass of <code>Rule</code> and the solver will pick it up and use it automatically.
{{works with|Tcl|8.6}} or {{libheader|TclOO}}
<langsyntaxhighlight lang="tcl">package require Tcl 8.6
oo::class create Sudoku {
variable idata
Line 4,455 ⟶ 13,516:
return 0
}
}</langsyntaxhighlight>
Demonstration code:
<langsyntaxhighlight lang="tcl">SudokuSolver create sudoku
sudoku load {
{3 9 4 @ @ 2 6 7 @}
Line 4,480 ⟶ 13,541:
}
}
sudoku destroy</langsyntaxhighlight>
{{out}}
Sample output:
<pre>+-----+-----+-----+
|3 9 4|8 5 2|6 7 1|
Line 4,496 ⟶ 13,557:
+-----+-----+-----+</pre>
If we'd added a logger method (after creating the <code>sudoku</code> object but before running the solver) like this:
<langsyntaxhighlight lang="tcl">oo::objdefine sudoku method Log msg {puts $msg}</langsyntaxhighlight>
Then this additional logging output would have been produced prior to the result being printed:
<pre>::RuleOnlyChoice solved ::sudoku at 8,0 for 1
Line 4,550 ⟶ 13,611:
 
=={{header|Ursala}}==
<langsyntaxhighlight Ursalalang="ursala">#import std
#import nat
 
Line 4,562 ⟶ 13,623:
~&rgg&& ~&irtPFXlrjrXPS; ~&lrK2tkZ2g&& ~&llrSL2rDrlPrrPljXSPTSL)+-,
//~&p ^|DlrDSLlrlPXrrPDSL(~&,num*+ rep2 block3)*= num block27 ~&iiK0 iota9,
* `0?=\~&iNC ! ~&t digits+-</langsyntaxhighlight>
test program:
<langsyntaxhighlight Ursalalang="ursala">#show+
 
example =
Line 4,579 ⟶ 13,640:
010067008
009008000
026400735]-</langsyntaxhighlight>
{{out}}
output:
<pre>
394 852 671
Line 4,595 ⟶ 13,656:
</pre>
 
=={{Headerheader|VBA}}==
{{trans|Fortran}}
<langsyntaxhighlight VBAlang="vb">Dim grid(9, 9)
Dim gridSolved(9, 9)
 
Line 4,698 ⟶ 13,759:
Debug.Print
Next i
End Sub</langsyntaxhighlight>
{{out}}
Output:
<pre>
Sudoku
Line 4,712 ⟶ 13,773:
2 4 3 1 5 7 8 6 9
5 1 9 8 3 6 7 2 4
</pre>
 
=={{header|VBScript}}==
{{trans|VBA}}
To run in console mode with cscript.
<syntaxhighlight lang="vb">Dim grid(9, 9)
Dim gridSolved(9, 9)
Public Sub Solve(i, j)
If i > 9 Then
'exit with gridSolved = Grid
For r = 1 To 9
For c = 1 To 9
gridSolved(r, c) = grid(r, c)
Next 'c
Next 'r
Exit Sub
End If
For n = 1 To 9
If isSafe(i, j, n) Then
nTmp = grid(i, j)
grid(i, j) = n
If j = 9 Then
Solve i + 1, 1
Else
Solve i, j + 1
End If
grid(i, j) = nTmp
End If
Next 'n
End Sub 'Solve
Public Function isSafe(i, j, n)
If grid(i, j) <> 0 Then
isSafe = (grid(i, j) = n)
Exit Function
End If
'grid(i,j) is an empty cell. Check if n is OK
'first check the row i
For c = 1 To 9
If grid(i, c) = n Then
isSafe = False
Exit Function
End If
Next 'c
'now check the column j
For r = 1 To 9
If grid(r, j) = n Then
isSafe = False
Exit Function
End If
Next 'r
'finally, check the 3x3 subsquare containing grid(i,j)
iMin = 1 + 3 * Int((i - 1) / 3)
jMin = 1 + 3 * Int((j - 1) / 3)
For r = iMin To iMin + 2
For c = jMin To jMin + 2
If grid(r, c) = n Then
isSafe = False
Exit Function
End If
Next 'c
Next 'r
'all tests were OK
isSafe = True
End Function 'isSafe
Public Sub Sudoku()
'main routine
Dim s(9)
s(1) = "001005070"
s(2) = "920600000"
s(3) = "008000600"
s(4) = "090020401"
s(5) = "000000000"
s(6) = "304080090"
s(7) = "007000300"
s(8) = "000007069"
s(9) = "010800700"
For i = 1 To 9
For j = 1 To 9
grid(i, j) = Int(Mid(s(i), j, 1))
Next 'j
Next 'j
'print problem
Wscript.echo "Problem:"
For i = 1 To 9
c=""
For j = 1 To 9
c=c & grid(i, j) & " "
Next 'j
Wscript.echo c
Next 'i
'solve it!
Solve 1, 1
'print solution
Wscript.echo "Solution:"
For i = 1 To 9
c=""
For j = 1 To 9
c=c & gridSolved(i, j) & " "
Next 'j
Wscript.echo c
Next 'i
End Sub 'Sudoku
 
Call sudoku</syntaxhighlight>
{{out}}
<pre>Problem:
0 0 1 0 0 5 0 7 0
9 2 0 6 0 0 0 0 0
0 0 8 0 0 0 6 0 0
0 9 0 0 2 0 4 0 1
0 0 0 0 0 0 0 0 0
3 0 4 0 8 0 0 9 0
0 0 7 0 0 0 3 0 0
0 0 0 0 0 7 0 6 9
0 1 0 8 0 0 7 0 0
Solution:
6 3 1 2 4 5 9 7 8
9 2 5 6 7 8 1 4 3
4 7 8 3 1 9 6 5 2
7 9 6 5 2 3 4 8 1
1 8 2 9 6 4 5 3 7
3 5 4 7 8 1 2 9 6
8 6 7 4 9 2 3 1 5
2 4 3 1 5 7 8 6 9
5 1 9 8 3 6 7 2 4</pre>
 
===Alternate version===
A faster version adapted from the C solution
<syntaxhighlight lang="vb">
'VBScript Sudoku solver. Fast recursive algorithm adapted from the C version
'It can read a problem passed in the command line or from a file /f:textfile
'if no problem passed it solves a hardwired problem (See the prob0 string)
'problem string can have 0's or dots in the place of unknown values. All chars different from .0123456789 are ignored
 
Option explicit
Sub print(s):
On Error Resume Next
WScript.stdout.Write (s)
If err= &h80070006& Then WScript.Echo " Please run this script with CScript": WScript.quit
End Sub
 
function parseprob(s)'problem string to array
Dim i,j,m
print "parsing: " & s & vbCrLf & vbcrlf
j=0
For i=1 To Len(s)
m=Mid(s,i,1)
Select Case m
Case "0","1","2","3","4","5","6","7","8","9"
sdku(j)=cint(m)
j=j+1
Case "."
sdku(j)=0
j=j+1
Case Else 'all other chars are ignored as separators
End Select
Next
' print j
If j<>81 Then parseprob=false Else parseprob=True
End function
 
sub getprob 'get problem from file or from command line or from
Dim s,s1
With WScript.Arguments.Named
If .exists("f") Then
s1=.item("f")
If InStr(s1,"\")=0 Then s1= Left(WScript.ScriptFullName, InStrRev(WScript.ScriptFullName, "\"))&s1
On Error Resume Next
s= CreateObject("Scripting.FileSystemObject").OpenTextFile (s1, 1).readall
If err Then print "can't open file " & s1 : parseprob(prob0): Exit sub
If parseprob(s) =True Then Exit sub
End if
End With
With WScript.Arguments.Unnamed
If .count<>0 Then
s1=.Item(0)
If parseprob(s1)=True Then exit sub
End if
End With
parseprob(prob0)
End sub
 
function solve(x,ByVal pos)
'print pos & vbcrlf
'display(x)
Dim row,col,i,j,used
solve=False
If pos=81 Then solve= true :Exit function
row= pos\9
col=pos mod 9
If x(pos) Then solve=solve(x,pos+1):Exit Function
used=0
For i=0 To 8
used=used Or pwr(x(i * 9 + col))
Next
For i=0 To 8
used=used Or pwr(x(row*9 + i))
next
row = (row\ 3) * 3
col = (col \3) * 3
For i=row To row+2
For j=col To col+2
' print i & " " & j &vbcrlf
used = used Or pwr(x(i*9+j))
Next
Next
'print pos & " " & Hex(used) & vbcrlf
For i=1 To 9
If (used And pwr(i))=0 Then
x(pos)=i
'print pos & " " & i & " " & num2bin((used)) & vbcrlf
solve= solve(x,pos+1)
If solve=True Then Exit Function
'x(pos)=0
End If
Next
x(pos)=0
solve=False
End Function
 
Sub display(x)
Dim i,s
For i=0 To 80
If i mod 9=0 Then print s & vbCrLf :s=""
If i mod 27=0 Then print vbCrLf
If i mod 3=0 Then s=s & " "
s=s& x(i)& " "
Next
print s & vbCrLf
End Sub
 
Dim pwr:pwr=Array(1,2,4,8,16,32,64,128,256,512,1024,2048)
Dim prob0:prob0= "001005070"&"920600000"& "008000600"&"090020401"& "000000000" & "304080090" & "007000300" & "000007069" & "010800700"
Dim sdku(81),Time
getprob
print "The problem"
display(sdku)
Time=Timer
If solve (sdku,0) Then
print vbcrlf &"solution found" & vbcrlf
display(sdku)
Else
print "no solution found " & vbcrlf
End if
print vbcrlf & "time: " & Timer-Time & " seconds" & vbcrlf
</syntaxhighlight>
{{out}}
<small>
<pre>
parsing: 001005070920600000008000600090020401000000000304080090007000300000007069010800700
 
The problem
 
0 0 1 0 0 5 0 7 0
9 2 0 6 0 0 0 0 0
0 0 8 0 0 0 6 0 0
 
0 9 0 0 2 0 4 0 1
0 0 0 0 0 0 0 0 0
3 0 4 0 8 0 0 9 0
 
0 0 7 0 0 0 3 0 0
0 0 0 0 0 7 0 6 9
0 1 0 8 0 0 7 0 0
 
solution found
 
6 3 1 2 4 5 9 7 8
9 2 5 6 7 8 1 4 3
4 7 8 3 1 9 6 5 2
 
7 9 6 5 2 3 4 8 1
1 8 2 9 6 4 5 3 7
3 5 4 7 8 1 2 9 6
 
8 6 7 4 9 2 3 1 5
2 4 3 1 5 7 8 6 9
5 1 9 8 3 6 7 2 4
 
time: 0.3710938 seconds
</pre>
</small>
 
=={{header|Wren}}==
{{trans|Kotlin}}
<syntaxhighlight lang="wren">class Sudoku {
construct new(rows) {
if (rows.count != 9 || rows.any { |r| r.count != 9 }) {
Fiber.abort("Grid must be 9 x 9")
}
_grid = List.filled(81, null)
for (i in 0..8) {
for (j in 0..8 ) _grid[9 * i + j] = rows[i][j]
}
_solved = false
}
 
checkValidity_(v, x, y) {
for (i in 0..8) {
if (_grid[y * 9 + i] == v || _grid[i * 9 + x] == v) return false
}
var startX = (x / 3).floor * 3
var startY = (y / 3).floor * 3
for (i in startY...startY + 3) {
for (j in startX...startX + 3) {
if (_grid[i * 9 + j] == v) return false
}
}
return true
}
 
placeNumber_(pos) {
if (_solved) return
if (pos == 81) {
_solved = true
return
}
if (_grid[pos].bytes[0] > 48) {
placeNumber_(pos + 1)
return
}
for (n in 1..9) {
if (checkValidity_(n.toString, pos % 9, (pos/9).floor)) {
_grid[pos] = n.toString
placeNumber_(pos + 1)
if (_solved) return
_grid[pos] = "0"
}
}
}
 
solve() {
System.print("Starting grid:\n\n%(this)")
placeNumber_(0)
System.print(_solved ? "Solution:\n\n%(this)" : "Unsolvable!")
}
 
toString {
var sb = ""
for (i in 0..8) {
for (j in 0..8) {
sb = sb + _grid[i * 9 + j] + " "
if (j == 2 || j == 5) sb = sb + "| "
}
sb = sb + "\n"
if (i == 2 || i == 5) sb = sb + "------+-------+------\n"
}
return sb
}
}
 
var rows = [
"850002400",
"720000009",
"004000000",
"000107002",
"305000900",
"040000000",
"000080070",
"017000000",
"000036040"
]
Sudoku.new(rows).solve()</syntaxhighlight>
 
{{out}}
<pre>
Starting grid:
 
8 5 0 | 0 0 2 | 4 0 0
7 2 0 | 0 0 0 | 0 0 9
0 0 4 | 0 0 0 | 0 0 0
------+-------+------
0 0 0 | 1 0 7 | 0 0 2
3 0 5 | 0 0 0 | 9 0 0
0 4 0 | 0 0 0 | 0 0 0
------+-------+------
0 0 0 | 0 8 0 | 0 7 0
0 1 7 | 0 0 0 | 0 0 0
0 0 0 | 0 3 6 | 0 4 0
 
Solution:
 
8 5 9 | 6 1 2 | 4 3 7
7 2 3 | 8 5 4 | 1 6 9
1 6 4 | 3 7 9 | 5 2 8
------+-------+------
9 8 6 | 1 4 7 | 3 5 2
3 7 5 | 2 6 8 | 9 1 4
2 4 1 | 5 9 3 | 7 8 6
------+-------+------
4 3 2 | 9 8 1 | 6 7 5
6 1 7 | 4 2 5 | 8 9 3
5 9 8 | 7 3 6 | 2 4 1
</pre>
 
=={{header|XPL0}}==
This is a translation of the C example, but with a solution that
can be verified by several other examples.
{{trans|C}}
<syntaxhighlight lang="xpl0">code ChOut=8, CrLf=9, IntOut=11, Text=12;
 
proc Show(X);
char X;
int I, J;
[for I:= 0 to 8 do
[if rem(I/3) = 0 then CrLf(0);
for J:= 0 to 8 do
[if rem(J/3) = 0 then ChOut(0, ^ );
ChOut(0, ^ ); IntOut(0, X(0));
X:= X+1;
];
CrLf(0);
];
];
 
func TryCell(X, Pos);
char X;
int Pos;
int Row, Col, I, J, Used;
[Row:= Pos/9;
Col:= rem(0);
Used:= 0;
 
if Pos = 81 then return true;
if X(Pos) then return TryCell(X, Pos+1);
 
for I:= 0 to 8 do Used:= Used ! 1 << (X(I*9+Col)-1);
for J:= 0 to 8 do Used:= Used ! 1 << (X(Row*9+J)-1);
 
Row:= Row/3*3;
Col:= Col/3*3;
for I:= Row to Row+2 do
for J:= Col to Col+2 do
Used:= Used ! 1 << (X(I*9+J)-1);
 
for I:= 1 to 9 do
[X(Pos):= I;
if (Used&1)=0 & TryCell(X, Pos+1) then return true;
Used:= Used>>1;
];
X(Pos):= 0;
return false;
];
 
proc Solve(S);
char S;
int I, J, C;
char X(81);
[J:= 0;
for I:= 0 to 80 do
[repeat C:= S(J);
J:= J+1;
until C>=^1 & C<=^9 ! C=^.;
X(I):= if C=^. then 0 else C-^0;
];
 
if TryCell(X, 0) then Show(X)
else Text(0, "No solution");
];
 
[Solve("394 ..2 67.
... 3.. 4..
5.. 69. .2.
.45 ... 9..
6.. ... ..7
..7 ... 58.
.1. .67 ..8
..9 ..8 ...
.26 4.. 735 ");
]</syntaxhighlight>
 
{{out}}
<pre>
3 9 4 8 5 2 6 7 1
2 6 8 3 7 1 4 5 9
5 7 1 6 9 4 8 2 3
 
1 4 5 7 8 3 9 6 2
6 8 2 9 4 5 3 1 7
9 3 7 1 2 6 5 8 4
 
4 1 3 5 6 7 2 9 8
7 5 9 2 3 8 1 4 6
8 2 6 4 1 9 7 3 5
</pre>
 
=={{header|zkl}}==
{{trans|C}} Note: Unlike in the C solution, 1<<-1 is defined (as 0).
<syntaxhighlight lang="zkl">fcn trycell(sdku,pos=0){
row,col:=pos/9, pos%9;
if(pos==81) return(True);
if(sdku[pos]) return(trycell(sdku, pos + 1));
used:=0;
foreach r in (9){ used=used.bitOr((1).shiftLeft(sdku[r*9 + col] - 1)) }
foreach c in (9){ used=used.bitOr((1).shiftLeft(sdku[row*9 + c] - 1)) }
row,col = row/3*3, col/3*3;
foreach r,c in ([row..row+2], [col..col+2])
{ used=used.bitOr((1).shiftLeft(sdku[r*9 + c] - 1)) }
 
sdku[pos]=1; while(sdku[pos]<=9){
if(used.isEven and trycell(sdku, pos + 1)) return(True);
sdku[pos]+=1; used/=2;
}
sdku[pos]=0;
return(False);
}</syntaxhighlight>
<syntaxhighlight lang="zkl">problem:=
#<<<
" 5 3 0 0 7 0 0 0 0
6 0 0 1 9 5 0 0 0
0 9 8 0 0 0 0 6 0
8 0 0 0 6 0 0 0 3
4 0 0 8 0 3 0 0 1
7 0 0 0 2 0 0 0 6
0 6 0 0 0 0 2 8 0
0 0 0 4 1 9 0 0 5
0 0 0 0 8 0 0 7 9";
#<<<
s:=problem.split().apply("toInt").copy(); // writable list of 81 ints
trycell(s).println();
println("+-----+-----+-----+");
foreach n in (3){
s[n*27,27].pump(Console.println,T(Void.Read,8),("| " + "%s%s%s | "*3).fmt); // 3 lines
println("+-----+-----+-----+");
}</syntaxhighlight>
{{out}}
<pre>
True
+-----+-----+-----+
| 534 | 678 | 912 |
| 672 | 195 | 348 |
| 198 | 342 | 567 |
+-----+-----+-----+
| 859 | 761 | 423 |
| 426 | 853 | 791 |
| 713 | 924 | 856 |
+-----+-----+-----+
| 961 | 537 | 284 |
| 287 | 419 | 635 |
| 345 | 286 | 179 |
+-----+-----+-----+
</pre>
 
6

edits