Sudoku: Difference between revisions

183,040 bytes added ,  9 days ago
Added Uiua solution
(Added another C# solution)
(Added Uiua solution)
 
(122 intermediate revisions by 27 users not shown)
Line 4:
Solve a partially filled-in normal   9x9   [[wp:Sudoku|Sudoku]] grid   and display the result in a human-readable format.
 
;references:
 
* [[wp:Algorithmics_of_sudoku|Algorithmics of Sudoku]]   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++}}
<langsyntaxhighlight lang="ada">
with Ada.Text_IO;
 
Line 119 ⟶ 378:
solve( sudoku_ar );
end Sudoku;
</syntaxhighlight>
</lang>
 
{{out}}
Line 142 ⟶ 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 236 ⟶ 495:
"__1__6__9"))
END CO
)</langsyntaxhighlight>
{{out}}
<pre>
Line 256 ⟶ 515:
 
=={{header|AutoHotkey}}==
<langsyntaxhighlight AutoHotkeylang="autohotkey">#SingleInstance, Force
SetBatchLines, -1
SetTitleMatchMode, 3
Line 399 ⟶ 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]]
<langsyntaxhighlight lang="bbcbasic"> VDU 23,22,453;453;8,20,16,128
*FONT Arial,28
Line 508 ⟶ 990:
ENDIF
NEXT
= D%</langsyntaxhighlight>
 
=={{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 SuDoku problems. Even so it is usually quite fast.
Line 898 ⟶ 1,388:
{ count := count + 1
prboard()
}</langsyntaxhighlight>
 
=={{header|Befunge}}==
Line 904 ⟶ 1,394:
Input should be provided as a sequence of 81 digits (optionally separated by whitespace), with zero representing an unknown value.
 
<langsyntaxhighlight 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%\^
Line 911 ⟶ 1,401:
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:</langsyntaxhighlight>
 
{{in}}
Line 941 ⟶ 1,431:
=={{header|Bracmat}}==
The program:
<langsyntaxhighlight lang="bracmat">{sudokuSolver.bra
 
Solves any 9x9 sudoku, using backtracking.
Line 1,129 ⟶ 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,141 ⟶ 1,631:
(.- - 2 - 1 - - - -)
(.- - - - 4 - - - 9)
);</langsyntaxhighlight>
Solution:
<pre>|~~~|~~~|~~~|
Line 1,161 ⟶ 1,651:
 
The following code is really only good for size 3 puzzles. A longer, even less readable version [[Sudoku/C|here]] could handle size 4s.
<langsyntaxhighlight lang="c">#include <stdio.h>
 
void show(int *x)
Line 1,227 ⟶ 1,717:
 
return 0;
}</langsyntaxhighlight>
 
=={{header|C sharp|C#}}==
===“Manual” SolutionBacktracking===
{{trans|Java}}
<langsyntaxhighlight lang="csharp">using System;
 
class SudokuSolver
Line 1,334 ⟶ 1,824:
Console.Read();
}
}</langsyntaxhighlight>
 
===“Amb” Solution===
=== Best First Search===
This uses the second version of the [https://rosettacode.org/wiki/Amb#C.23 Amb C# class] in the Amb challenge
<!-- By Martin Freedman, 20/11/2021 -->
{{works with|C sharp|C#|7.1}}
<syntaxhighlight lang="csharp">using System.Linq;
<!-- By Martin Freedman, 9/02/2018 -->
<lang csharp>using System.Linq;
using static System.Linq.Enumerable;
using static System.ConsoleCollections.Generic;
using AmbSystem;
using System.Runtime.CompilerServices;
 
namespace SudokuSodukoFastMemoBFS {
internal readonly record struct Square (int Row, int Col);
{
internal record Constraints (IEnumerable<int> ConstrainedRange, Square Square);
static class Program
internal class Cache : Dictionary<Square, Constraints> { };
{
internal record CacheGrid (int[][] Grid, Cache Cache);
static void Main(string[] args)
{
var challenge = new string[]{ "970 340 060",
"861 750 000",
"324 168 957",
"219 584 673",
"487 236 519",
"653 971 284",
"738 425 196",
"002 010 048",
"040 007 300" };
 
internal static class SudokuFastMemoBFS {
var Solve = challenge
internal static U Fwd<T, .Select(r =U> r.Where(cthis =>T cdata, !=Func<T, 'U> 'f).Select(c => f(int)c - '0').ToArray()data);
.ToArray();
 
[MethodImpl(MethodImplOptions.AggressiveInlining)]
var amb = new Amb.Amb();
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 matrix = new IValue<int>[9][];
var domain = new []{0(row, 1,col) 2, 3, 4, 5, 6, 7, 8, 9= }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();
void IsUnequal(IValue<int>[] values) => amb.Require(()=> values.Select(v => v.Value).Distinct().Count() == 9);
private static readonly int[] range = Range(1, 9).ToArray();
 
private static bool Valid(this IValue<int>[] GetBox(IValue<int>[][] sudokugrid, int Rarow, int Rbcol, int Ca,val) int Cb){
{for (var i = 0; i < 9; i++)
varif slice(grid[row][i] == newval IValue<int>|| grid[9i];[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 icol) = 0;>
for range.Where(int rowval => Ra; grid.Valid(row, <=col, Rbval)); row++)
for (int col = Ca; col <= Cb; col++)
slice[i++] = sudoku[row][col];
return slice;
}
 
private static Constraints Next(this //CacheGrid rowscg, Square square) =>
foreach cg.Cache.ContainsKey(var r in Range(0,9)square)
{? cg.Cache[square]
: matrixcg.Cache[rsquare] = new IValue<int>[9]cg.Grid.SortedCells();
var exclude = Solve[r].Where(i => i > 0).Prepend(0).ToArray(); // dont forget 0!
foreach (var c in Range(0,9))
{
// int cell and cell constraints
matrix[r][c] = amb.Choose<int>(domain);
if (Solve[r][c] > 0)
amb.Require(() => matrix[r][c].Value == Solve[r][c]);
else
amb.Require(() => !exclude.Contains(matrix[r][c].Value));
 
private static Constraints SortedCells(this int[][] grid) =>
// boxes
if ((r ==2 || r==5 || r==8) && (c==2 ||from c==5row ||in c==8))domain
from col in domain
IsUnequal(GetBox(matrix, r -2, r, c -2, c));
where grid[row][col] == }0
let cell = new IsUnequalConstraints(Rangegrid.Constraints(0row,9 col).Select(i=>matrix[r][i]).ToArray, new Square(row, col));
}orderby cell.ConstrainedRange.Count() ascending
//colsselect cell).First();
 
foreach (var c in Range(0, 9))
private static CacheGrid Parse(string {input) =>
input
IsUnequal(Range(0, 9).Select(j => matrix[j][c]).ToArray());
.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) {
if (amb.Disambiguate())
{var cg = Parse(input);
var marked = cg.Grid.SelectMany(row for=> row.Where(var rc => 0;c r> < 9; r++0)).Count();
return cg.Solve(cg.Grid.SortedCells(), 80 - marked) ? cg.Grid : new int[][] { Array.Empty<int>() };
{
}
for (var c = 0; c < 9; c++)
}
{
}</syntaxhighlight>
Write($"{matrix[r][c].Value}");
Usage
}
<syntaxhighlight lang="csharp">using System.Linq;
Write("\n");
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(".");
}
elsewatch.Stop();
WriteLine($"\nPuzzles:{num}, Total:{total} ms, Average:{total / num:0.00} ms");
{
WriteLineReadKey("Amb is angry!");
}
Read();
}
}
}</langsyntaxhighlight>
Output
<pre>975342861693784512
487512936
861759432
125963874
324168957
932651487
219584673
568247391
487236519
741398625
653971284
319475268
738425196
856129743
592613748
274836159
146897325
000000010400000000020000000000050407008000300001090000300400200050100000000806000: 336 ms
</pre>
Doing 100 puzzles
 
....................................................................................................
Puzzles:100, Total:5316 ms, Average:53.16 ms</pre>
 
===Solver===
===“Automatic” Solution===
{{libheader|Microsoft Solver Foundation}}
<!-- By Nigel Galloway, Jan 29, 2012 -->
<langsyntaxhighlight lang="csharp">using Microsoft.SolverFoundation.Solvers;
 
namespace Sudoku
Line 1,515 ⟶ 2,032:
}
}
}</langsyntaxhighlight>
Produces:
<pre>
Line 1,531 ⟶ 2,048:
</pre>
 
===Using the "Dancing Links"/Algorithm algorithmX===
<langsyntaxhighlight lang="csharp">using System;
using System.Collections.Generic;
using System.Text;
Line 1,810 ⟶ 2,327:
 
public static string DelimitWith<T>(this IEnumerable<T> source, string separator) => string.Join(separator, source);
}</langsyntaxhighlight>
{{out}}
<pre>
Line 1,835 ⟶ 2,352:
=={{header|C++}}==
{{trans|Java}}
<langsyntaxhighlight lang="cpp">#include <iostream>
using namespace std;
 
Line 1,915 ⟶ 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.pprint :only (cl-format)]))
 
Line 1,953 ⟶ 2,469:
(if (= x (dec c))
(recur ng 0 (inc y))
(recur ng (inc x) y)))))))</langsyntaxhighlight>
 
<langsyntaxhighlight lang="clojure">sudoku>(cl-format true "~{~{~a~^ ~}~%~}"
(solve [[3 9 4 0 0 2 6 7 0]
[0 0 0 3 0 0 4 0 0]
Line 1,975 ⟶ 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 2,018 ⟶ 2,534:
(setf (aref grid row column) choice)
(when (eq grid (solve grid row (1+ column)))
(return grid))))))</langsyntaxhighlight>
Example:
<pre>> (defparameter *puzzle*
Line 2,045 ⟶ 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 2,110 ⟶ 2,728:
" 5 7 921 ",
" 64 9 ",
" 2 438"]</langsyntaxhighlight>
 
 
Line 2,116 ⟶ 2,734:
{{Works with|PAKCS}}
Minimal w/o read or show utilities.
<langsyntaxhighlight lang="curry">import CLPFD
import Constraint (allC)
import List (transpose)
Line 2,149 ⟶ 2,767:
, [7,_,_,6,_,_,5,_,_]
]
main | sudoku xs = xs where xs = test</langsyntaxhighlight>
{{Out}}
<pre>Execution time: 0 msec. / elapsed: 10 msec.
Line 2,157 ⟶ 2,775:
{{trans|C++}}
A little over-engineered solution, that shows some strong static typing useful in larger programs.
<langsyntaxhighlight lang="d">import std.stdio, std.range, std.string, std.algorithm, std.array,
std.ascii, std.typecons;
 
Line 2,283 ⟶ 2,901:
else
solution.get.representSudoku.writeln;
}</langsyntaxhighlight>
{{out}}
<pre>8 5 . | . . 2 | 4 . .
Line 2,311 ⟶ 2,929:
===Short Version===
Adapted from: http://code.activestate.com/recipes/576725-brute-force-sudoku-solver/
<langsyntaxhighlight lang="d">import std.stdio, std.algorithm, std.range;
 
const(int)[] solve(immutable int[] s) pure nothrow @safe {
Line 2,344 ⟶ 2,962:
0, 0, 0, 0, 3, 6, 0, 4, 0];
writefln("%(%s\n%)", problem.solve.chunks(9));
}</langsyntaxhighlight>
{{out}}
<pre>[8, 5, 9, 6, 1, 2, 4, 3, 7]
Line 2,358 ⟶ 2,976:
===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.
<langsyntaxhighlight lang="d">import std.stdio, std.algorithm, std.range, std.typecons;
 
Nullable!(const ubyte[81]) solve(in ubyte[81] s) pure nothrow @safe @nogc {
Line 2,399 ⟶ 3,017:
0, 0, 0, 0, 3, 6, 0, 4, 0];
writefln("%(%s\n%)", problem.solve.get[].chunks(9));
}</langsyntaxhighlight>
Same output.
 
=={{header|Delphi}}==
Example taken from C++
<langsyntaxhighlight lang="delphi">type
TIntArray = array of Integer;
 
Line 2,528 ⟶ 3,146:
ShowMessage('Solved!');
end;
end;</langsyntaxhighlight>
Usage:
<langsyntaxhighlight lang="delphi">var
SudokuSolver: TSudokuSolver;
begin
Line 2,547 ⟶ 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}}
<langsyntaxhighlight lang="elixir">defmodule Sudoku do
def display( grid ), do: ( for y <- 1..9, do: display_row(y, grid) )
Line 2,707 ⟶ 3,421:
{{3, 8}, 2}, {{5, 8}, 1},
{{5, 9}, 4}, {{9, 9}, 9}]
Sudoku.task( difficult )</langsyntaxhighlight>
 
{{out}}
Line 2,767 ⟶ 3,481:
=={{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">
<lang Erlang>
-module( sudoku ).
 
Line 2,930 ⟶ 3,644:
display( Solved ),
io:nl().
</syntaxhighlight>
</lang>
{{out}}
<pre>
Line 3,014 ⟶ 3,728:
0 is the empty cell.
 
<syntaxhighlight lang="erre">
<lang ERRE>
!--------------------------------------------------------------------
! risolve Sudoku: in input il file SUDOKU.TXT
Line 3,421 ⟶ 4,135:
 
 
</syntaxhighlight>
</lang>
 
=={{header|F_Sharp|F#}}==
===The Function SLPsolveBacktracking===
<!-- By Martin Freedman, 26/11/2021 -->
<lang fsharp>
<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)]
Line 3,454 ⟶ 4,517:
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>
</lang>
'''Usage:'''
===Demonstration===
Given sud1.csv:
<pre>
Line 3,469 ⟶ 4,532:
</pre>
then
<langsyntaxhighlight 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>
</lang>
{{out}}
<pre>
Line 3,485 ⟶ 4,548:
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 3,850 ⟶ 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 3,952 ⟶ 5,016:
end subroutine pretty_print
 
end program sudoku</langsyntaxhighlight>
{{out}}<pre>
+-----+-----+-----+
Line 3,981 ⟶ 5,045:
|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:
<langsyntaxhighlight lang="futurebasic">
include "ConsoleWindow"
include "NSLog.incl"
include "Util_Containers.incl"
 
begin globals
dim as 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++)
{
short i;
if (i != c && sudoku[r][i] == sudoku[r][c]) return 0;
short rr, cc;
if (i != r && sudoku[i][c] == sudoku[r][c]) return 0;
rr = r/3 * 3 + i/3;
ccfor (i = c/30; *i 3< +9; 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 (i solve_sudoku(!= c && sudoku[r][i)] == sudoku[r][c]) return -10;
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 0-1;
}
 
 
CFMutableStringRef print_sudoku()
{
short i, j;
CFMutableStringRef mutStr;
mutStr = CFStringCreateMutable( kCFAllocatorDefault, 0 );
short solve_sudoku( short i )
 
{
for (i = 0; i < 9; i++)
short {r, c;
for (j = 0; j < 9; j++)
if (i < 0) return {0;
else if (i >= 81) return -1;
CFStringAppendFormat( mutStr, NULL, (CFStringRef)@" %d", sudoku[i][j] );
}
r = i / 9;
CFStringAppendFormat( mutStr, NULL, (CFStringRef)@"\r" );
c }= i % 9;
return( mutStr );
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
 
Line 4,074 ⟶ 5,244:
toolbox fn print_sudoku() = CFMutableStringRef
 
dim as short solution
dim as CFMutableStringRef cfRef
 
gC = " "
Line 4,086 ⟶ 5,256:
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
 
</lang>
HandleEvents
</syntaxhighlight>
 
Output:
Line 4,125 ⟶ 5,297:
More code in this one, but faster execution:
<pre>
include "ConsoleWindow"
include "Tlbx Timer.incl"
 
begin globals
_digits = 9
Line 4,136 ⟶ 5,305:
 
begin record Board
dim as booleanBoolean f(_digits,_digits,_digits)
dim as char match(_digits,_digits)
dim as pointer previousBoard // singly-linked list used to discover repetitions
dim &&
end record
 
dimBoard quiz as board
CFTimeInterval t
dim as long t
dim as double sProgStartTime
 
end globals
 
// 'ordinary' timer used for playing
local fn Milliseconds as long // time in ms since prog start
'~'1
dim as UnsignedWide us
 
long if ( sProgStartTime == 0.0 )
Microseconds( @us )
sProgStartTime = 4294967296.0*us.hi + us.lo
end if
Microseconds( @us )
end fn = (4294967296.0*us.hi + us.lo - sProgStartTime)'*1e-3
 
local fn InitMilliseconds
'~'1
sProgStartTime = 0.0
fn Milliseconds
end fn
 
local mode
local fn CopyBoard( source as ^Board, dest as ^Board )
BlockMoveData( source, dest, sizeof( Board ) )
'~'1
dest.previousBoard = source // linked list
BlockMoveData( source, dest, sizeof( Board ) )
dest.previousBoard = source // linked list
end fn
 
local fn prepare( b as ^Board )
short i, j, n
'~'1
dim as short i, j, n
for i = 1 to _digits
 
for ij = 1 to _digits
for jn = 1 to _digits
b.match[i, j] = 0
for n = 1 to _digits
b.matchf[i, j, n] = 0_true
next n
b.f[i, j, n] = _true
next nj
next ji
next i
end fn
 
local fn printBoard( b as ^Board )
short i, j
'~'1
dim as short i, j
for i = 1 to _digits
 
for ij = 1 to _digits
Print b.match[i, j];
for j = 1 to _digits
next j
Print b.match[i, j];
print
next j
next i
print
next i
end fn
 
local fn verifica( b as ^Board )
short i, j, n, first, x, y, ii
'~'1
Boolean check
dim as short i, j, n, first, x, y, ii
dim as boolean check
check = _true
 
check = _true
for i = 1 to _digits
 
for ij = 1 to _digits
if ( b.match[i, j] == 0 )
for j = 1 to _digits
check = _false
long if ( b.match[i, j] == 0 )
for n = 1 to _digits
check = _false
if ( b.f[i, j, n] != _false )
for n = 1 to _digits
check = _true
long if ( b.f[i, j, n] != _false )
end if
check = _true
next n
end if
if ( check == _false ) then exit fn
next n
end if
if ( check == _false ) then exit fn
next j
end if
next ji
next i
check = _true
 
for j = 1 to _digits
check = _true
for jn = 1 to _digits
for n = 1 to _digits first = 0
for i = 1 to _digits
first = 0
if ( b.match[i, j] == n )
for i = 1 to _digits
long if ( b.match[i, j]first == n0 )
long if ( first == 0 )i
else
first = i
check = _false
xelse
exit fn
check = _false
end if
exit fn
end if
next i
end if
next in
next nj
next j
for i = 1 to _digits
 
for in = 1 to _digits
for n = 1 to _digits first = 0
for j = 1 to _digits
first = 0
if ( b.match[i, j] == n )
for j = 1 to _digits
long if ( b.match[i, j]first == n0 )
long if ( first == 0 )j
else
first = j
check = _false
xelse
exit fn
check = _false
end if
exit fn
end if
next j
end if
next jn
next ni
next i
for x = 0 to ( _nSetH - 1 )
 
for xy = 0 to ( _nSetH_nSetV - 1 )
for y = 0 to ( _nSetVfirst -= 1 )0
for ii = 0 to ( _digits - 1 )
first = 0
i = x * _setH + ii mod _setH + 1
for ii = 0 to ( _digits - 1 )
i j = xy * _setH_setV + ii mod/ _setH + 1
j = y * _setV + ii / _setHif ( b.match[i, j] == +n 1)
long if ( b.match[i, j]first == n0 )
long if ( first == 0 )j
else
first = j
check = _false
xelse
exit fn
check = _false
end if
exit fn
end if
next ii
end if
next iiy
next yx
next x
 
end fn = check
 
 
local fn setCell( b as ^Board, x as short, y as short, n as short) as boolean
dim as short i, j, rx, ry
dim as booleanBoolean 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 )
dim as short i, j, n, first, x, y, ii, ppi, ppj
dim as booleanBoolean check
 
check = _true
 
for i = 1 to _digits
for j = 1 to _digits
long if ( b.match[i, j] == 0 )
first = 0
for n = 1 to _digits
long if ( b.f[i, j, n] != _false )
long if ( first == 0 )
first = n
else
xelse
first = -1
exit for
end if
end if
next n
 
long 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
 
long if ( b.f[i, j, n] != _false ) and ( b.match[i, j] == 0 )
long if ( first == 0 )
first = j
else
xelse
first = -1
exit for
end if
 
end if
 
next j
 
long 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
 
long if ( b.f[i, j, n] != _false ) and ( b.match[i, j] == 0 )
long if ( first == 0 )
first = i
else
xelse
first = -1
exit for
end if
 
end if
 
next i
 
long 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
 
long if ( b.f[i, j, n] != _false ) and ( b.match[i, j] == 0 )
long if ( first == 0 )
first = n
ppi = i
ppj = j
else
xelse
first = -1
exit for
end if
end if
 
 
next ii
 
long 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 )
dim as booleanBoolean check, daFinire
dim as long i, j, n
dim as boardBoard localBoard
 
check = fn solve(b)
 
long if ( check == _false )
exit fn
end if
 
daFinire = _false
 
for i = 1 to _digits
for j = 1 to _digits
long if ( b.match[i, j] == 0 )
 
daFinire = _true
 
for n = 1 to _digits
long if ( b.f[i, j, n] != _false )
 
fn CopyBoard( b, @localBoard )
 
check = fn setCell(@localBoard, i, j, n)
 
long if ( check != _false )
check = fn resolve( @localBoard )
long if ( check == -1 )
fn CopyBoard( @localBoard, b )
 
exit fn
end if
end if
 
end if
 
next n
 
end if
next j
next i
 
long if daFinire
else
xelse
check = -1
end if
 
end fn = check
 
 
fn InitMilliseconds
 
fn prepare( @quiz )
Line 4,498 ⟶ 5,642:
DATA 2,8,0,1,3,0,0,0,0
 
dim as 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
 
Line 4,509 ⟶ 5,653:
fn printBoard( @quiz )
print : print "-------------------" : print
dim as booleanBoolean check
 
t = fn MillisecondsCACurrentMediaTime
check = fn resolve(@quiz)
t = (fn MillisecondsCACurrentMediaTime - t) * 1000
 
if ( check )
print "solution:"; str$( t/1000.0 ) + " ms"
else
print "No solution found"
end if
fn printBoard( @quiz )
 
HandleEvents
</pre>
 
Line 4,555 ⟶ 5,701:
Input to function solve is an 81 character string.
This seems to be a conventional computer representation for Sudoku puzzles.
<langsyntaxhighlight lang="go">package main
 
import "fmt"
Line 4,756 ⟶ 5,902:
}
c.r.l, c.l.r = &c.x, &c.x
}</langsyntaxhighlight>
{{out}}
<pre>
Line 4,784 ⟶ 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 4,791 ⟶ 5,957:
 
I consider this a "brute force" solution of sorts, in that it is the same method I use when solving Sudokus manually.
<langsyntaxhighlight lang="groovy">final CELL_VALUES = ('1'..'9')
class GridException extends Exception {
Line 4,858 ⟶ 6,024:
}
grid
}</langsyntaxhighlight>
'''Test/Benchmark Cases'''
 
Mentions of ''"exceptionally difficult" example in Wikipedia'' refer to this (former) page: [[https://en.wikipedia.org/w/index.php?title=Sudoku_solving_algorithms&oldid=410240496#Exceptionally_difficult_Sudokus_.28hardest_Sudokus.29 Exceptionally difficult Sudokus]]
<langsyntaxhighlight lang="groovy">def sudokus = [
//Used in Curry solution: ~ 0.1 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',
Line 4,925 ⟶ 6,091:
solution.each { println it }
println "\nELAPSED: ${elapsed} seconds"
}</langsyntaxhighlight>
 
{{out}} (last only):
Line 4,959 ⟶ 6,125:
 
=={{header|Java}}==
<langsyntaxhighlight lang="java">public class Sudoku
{
private int mBoard[][];
Line 4,967 ⟶ 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 4,987 ⟶ 6,154:
}
}
 
private void setSubsetValue(int i, int j, int value, boolean present) {
mRowSubset[i][value - 1] = present;
Line 4,993 ⟶ 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) {
Line 5,018 ⟶ 6,185:
}
}
 
mBoard[i][j] = 0;
return false;
}
 
private boolean isValid(int i, int j, int val) {
val--;
Line 5,028 ⟶ 6,195:
return !isPresent;
}
 
private int computeBoxNo(int i, int j) {
int boxRow = i / mBoxSize;
Line 5,034 ⟶ 6,201:
return boxRow * mBoxSize + boxCol;
}
 
public void print() {
for(int i = 0; i < mBoardSize; i++) {
Line 5,044 ⟶ 6,211:
System.out.print("| ");
}
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}}==
Line 5,061 ⟶ 6,282:
====ES6====
 
<langsyntaxhighlight JavaScriptlang="javascript">//-------------------------------------------[ Dancing Links and Algorithm X ]--
/**
* The doubly-doubly circularly linked data object.
Line 5,334 ⟶ 6,555:
search(H, []);
};
</syntaxhighlight>
</lang>
 
<syntaxhighlight lang="javascript">[
<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.',
Line 5,361 ⟶ 6,582:
let s = new Array(Math.pow(n, 4)).fill('.').join('');
reduceGrid(s);
</syntaxhighlight>
</lang>
 
<pre>+-------+-------+-------+
Line 5,390 ⟶ 6,611:
| 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}}==
<langsyntaxhighlight lang="julia">function check(i, j)
id, im = div(i, 9), mod(i, 9)
jd, jm = div(j, 9), mod(j, 9)
Line 5,416 ⟶ 6,818:
for i in 1:81
if grid[i] == 0
t = Dict{Int64, VoidNothing}()
 
for j in 1:81
Line 5,459 ⟶ 6,861:
0, 5, 0, 6, 9, 0, 0, 1, 0]
 
solve_sudoku(display, grid)</langsyntaxhighlight>
{{out}}
<pre>
Line 5,477 ⟶ 6,879:
=={{header|Kotlin}}==
{{trans|C++}}
<langsyntaxhighlight lang="scala">// version 1.2.10
 
class Sudoku(rows: List<String>) {
Line 5,560 ⟶ 6,962:
)
Sudoku(rows).solve()
}</langsyntaxhighlight>
 
{{out}}
Line 5,592 ⟶ 6,994:
5 9 8 | 7 3 6 | 2 4 1
</pre>
 
=={{header|Nim}}==
{{trans|Kotlin}}
<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()</lang>
 
{{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===
<lang lua>--9x9 sudoku solver in lua
<syntaxhighlight lang="lua">--9x9 sudoku solver in lua
--based on a branch and bound solution
--fields are not tried in plain order
Line 5,883 ⟶ 7,179:
if x then
return printer(x)
end</langsyntaxhighlight>
Input:
<pre>
Line 5,914 ⟶ 7,210:
</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}}==
<langsyntaxhighlight lang="mathematica">solve[sudoku_] :=
NestWhile[
Join @@ Table[
Line 5,925 ⟶ 7,307:
Extract[Partition[s, {3, 3}], Quotient[#, 3, -2]]]} & /@
Position[s, 0, {2}],
Length@Last@# &], {s, #}] &, {sudoku}, ! FreeQ[#, 0] &]</langsyntaxhighlight>
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},
Line 5,935 ⟶ 7,317:
{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}}]</langsyntaxhighlight>
{{out}}
<pre>{{{9, 7, 5, 3, 4, 2, 8, 6, 1}, {8, 6, 1, 7, 5, 9, 4, 3, 2}, {3, 2, 4,
Line 5,946 ⟶ 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 6,298 ⟶ 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 6,309 ⟶ 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 6,321 ⟶ 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 6,394 ⟶ 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 6,481 ⟶ 7,970:
end
in
{Inspect {Solve Puzzle1}.1}</langsyntaxhighlight>
 
 
=={{header|PARI/GP}}==
 
Build plugin for PARI's function interface from C code: sudoku.c
<langsyntaxhighlight Clang="c">#include <pari/pari.h>
 
typedef int SUDOKU [9][9];
Line 6,557 ⟶ 8,045:
return gen_0; /* no solution */
}
</syntaxhighlight>
</lang>
Compile plugin: gcc -O2 -Wall -fPIC -shared sudoku.c -o libsudoku.so -lpari
 
Install plugin from home directory and play:
<langsyntaxhighlight lang="parigp">install("plug_sudoku", "G", "sudoku", "~/libsudoku.so")</langsyntaxhighlight>
 
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]
Line 6,589 ⟶ 8,077:
{{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.
<langsyntaxhighlight lang="pascal">Program soduko;
{$IFDEF FPC}
{$CODEALIGN proc=16,loop=8}
Line 6,845 ⟶ 8,333:
Outfield(solF);
writeln(86400*1000*(T1-T0)/k:10:3,' ms Test calls :',callCnt/k:8:0);
end.</langsyntaxhighlight>
{{out}}
<pre>
Line 6,881 ⟶ 8,369:
 
=={{header|Perl}}==
<langsyntaxhighlight Perllang="perl">#!/usr/bin/perl
use integer;
use strict;
Line 6,920 ⟶ 8,408:
}
}
solve();</langsyntaxhighlight>
{{out}}
<pre>
Line 6,936 ⟶ 8,424:
</pre>
 
=={{header|Perl 6Phix}}==
Simple brute force solution. Generally quite good but will struggle on some puzzles (eg see "the beast" below)
{{trans|Perl}}
<!--<syntaxhighlight lang="phix">(phixonline)-->
 
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>
<lang perl6>use v6;
<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;">"""
my @A = <
.......39
5 3 0 0 2 4 7 0 0
.....1..5
0 0 2 0 0 0 8 0 0
..3.5.8..
1 0 0 7 0 3 9 0 2
..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>
0 0 8 0 7 2 0 4 9
<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>
0 2 0 9 8 0 0 7 0
<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>
7 9 0 0 0 0 0 8 0
<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>
0 0 0 0 3 0 5 0 6
9 6 0 0 1 0 3 0 0
<span style="color: #008080;">procedure</span> <span style="color: #000000;">brute_solve</span><span style="color: #0000FF;">()</span>
0 5 0 6 9 0 0 1 0
<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>
my &I = * div 9; # line number
<span style="color: #000000;">brute_solve</span><span style="color: #0000FF;">()</span>
my &J = * % 9; # column number
<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>
my &K = { ($_ div 27) * 3 + $_ % 9 div 3 }; # bloc number
<!--</syntaxhighlight>-->
 
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 {
print "@A[$_] ";
print " " if $i %% 3;
print "\n" if $i %% 9;
print "\n" if $i++ %% 27;
}
}
solve;</lang>
 
{{out}}
<pre>
<pre>5 3 9 8 2 4 7 6 1
751846239
6 7 2 1 5 9 8 3 4
892371465
1 8 4 7 6 3 9 5 2
643259871
 
238197546
3 1 8 5 7 2 6 4 9
974562318
4 2 5 9 8 6 1 7 3
165438927
7 9 6 3 4 1 2 8 5
319684752
 
527913684
8 4 1 2 3 7 5 9 6
486725193
9 6 7 4 1 5 3 2 8
(solved in 0.95s)
2 5 3 6 9 8 4 1 7</pre>
</pre>
 
OTT solution. Implements line/col and set exclusion, and x-wings. Blisteringly fast<BR>
This is an alternative solution that uses a more ellaborate set of choices instead of brute-forcing it.
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
<lang perl6>#!/usr/bin/env perl6
a more readable single-puzzle output (example below).
use v6;
<!--<syntaxhighlight lang="phix">(phixonline)-->
#
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>
# In this code, a sudoku puzzle is represented as a two-dimentional
<span style="color: #000080;font-style:italic;">-- Working directly on 81-character strings ultimately proves easier: Originally I
# array. The cells that are not yet solved are represented by yet
-- just wanted to simplify the final display, but later I realised that a 9x9 grid
# another array of all the possible values.
-- encourages laborious indexing/looping everwhere whereas using a flat 81-element
#
-- approach encourages precomputation of index sets, and once you commit to that,
# This implementation is not a simple brute force evaluation of all
-- the rest of the code starts to get a whole lot cleaner. Below we create 27+18
# the options, but rather makes four extra attempts to guide the
-- sets and 5 tables of lookup indexes to locate them quickly.</span>
# solution:
#
<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>
# 1) For every change in the grid, usually made by an attempt at a
<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>
# solution, we will reduce the search space of the possible values
<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>
# in all the other cells before going forward.
<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>
# 2) When a cell that is not yet resolved is the only one that can
<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>
# hold a specific value, resolve it immediately instead of
<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>
# performing the regular search.
#
<span style="color: #008080;">procedure</span> <span style="color: #000000;">set_nines</span><span style="color: #0000FF;">()</span>
# 3) Instead of trying from cell 1,1 and moving in sequence, this
<span style="color: #004080;">sequence</span> <span style="color: #000000;">nine</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">six</span>
# implementation will start trying on the cell that is the closest
<span style="color: #004080;">integer</span> <span style="color: #000000;">idx</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">ndx</span>
# to being solved already.
<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>
# 4) Instead of trying all possible values in sequence, start with
<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>
# the value that is the most unique. I.e.: If the options for this
<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>
# cell are 1,4,6 and 6 is only a candidate for two of the
<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>
# competing cells, we start with that one.
<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>
# keep a list with all the cells, handy for traversal
<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>
my @cells = do for (flat 0..8 X 0..8) -> $x, $y { [ $x, $y ] };
<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>
# Try to solve this puzzle and return the resolved puzzle if it is at
<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>
# all solvable in this configuration.
<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>
sub solve($sudoku, Int $level) {
<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>
# cleanup the impossible values first,
<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>
if (cleanup-impossible-values($sudoku, $level)) {
<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>
# try to find implicit answers
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
while (find-implicit-answers($sudoku, $level)) {
<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>
# and every time you find some, re-do the cleanup and try again
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
cleanup-impossible-values($sudoku, $level);
<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>
# Now let's actually try to solve a new value. But instead of
<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>
# going in sequence, we select the cell that is the closest to
<span style="color: #000000;">nine</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{}</span>
# being solved already. This will reduce the overall number of
<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>
# guesses.
<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>
for sort { solution-complexity-factor($sudoku, $_[0], $_[1]) },
<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>
grep { $sudoku[$_[0]][$_[1]] ~~ Array },
<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>
@cells -> $cell
<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>
my Int ($x, $y) = @($cell);
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
# Now let's try the possible values in the order of
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
# uniqueness.
<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>
for sort { matches-in-competing-cells($sudoku, $x, $y, $_) }, @($sudoku[$x][$y]) -> $val {
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
trace $level, "Trying $val on "~($x+1)~","~($y+1)~" "~$sudoku[$x][$y].perl;
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
my $solution = clone-sudoku($sudoku);
<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>
$solution[$x][$y] = $val;
<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>
my $solved = solve($solution, $level+1);
<span style="color: #000000;">six</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{}</span>
if $solved {
<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>
trace $level, "Solved... ($val on "~($x+1)~","~($y+1)~")";
<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>
return $solved;
<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>
# if we fell through, it means that we found no valid
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
# value for this cell
<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>
trace $level, "Backtrack, path unsolvable... (on "~($x+1)~" "~($y+1)~")";
<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>
return 0;
<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>
# all cells are already solved.
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
return $sudoku;
<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>
} else {
<span style="color: #000000;">six</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{}</span>
# if the cleanup failed, it means this is an invalid grid.
<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>
return False;
<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>
# This function reduces the search space from values that are already
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
# assigned to competing cells.
<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>
sub cleanup-impossible-values($sudoku, Int $level = 1) {
<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>
my Bool $resolved;
<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>
repeat {
<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>
$resolved = False;
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
for grep { $sudoku[$_[0]][$_[1]] ~~ Array },
<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>
@cells -> $cell {
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
my Int ($x, $y) = @($cell);
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span>
# which block is this cell in
<span style="color: #000000;">set_nines</span><span style="color: #0000FF;">()</span>
my Int $bx = Int($x / 3);
my Int $by = Int($y / 3);
<span style="color: #004080;">integer</span> <span style="color: #000000;">improved</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span>
# A unfilled cell is not resolved, so it shouldn't match
<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>
my multi match-resolved-cell(Array $other, Int $this) {
<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>
return 0;
<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>
my multi match-resolved-cell(Int $other, Int $this) {
<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>
return $other == $this;
<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>
# Reduce the possible values to the ones that are still
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
# valid
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
my @r =
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
grep { !match-resolved-cell($sudoku[any(0..2)+3*$bx][any(0..2)+3*$by], $_) }, # same block
<span style="color: #008080;">return</span> <span style="color: #000000;">valid</span>
grep { !match-resolved-cell($sudoku[any(0..8)][$y], $_) }, # same line
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
grep { !match-resolved-cell($sudoku[$x][any(0..8)], $_) }, # same column
@($sudoku[$x][$y]);
<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>
if (@r.elems == 1) {
<span style="color: #000080;font-style:italic;">--
# if only one element is left, then make it resolved
-- (see deep_logic()/set elimination)
$sudoku[$x][$y] = @r[0];
-- chosen is a sequence of length 2..4 of integers 1..9: ordered elements of pool.
$resolved = True;
-- pool is a set of elements of the sequence valid, each of which is a sequence.
} elsif (@r.elems == 0) {
-- (note that elements of valid in pool not in chosen are not necessarily sequences)
# This is an invalid grid
--</span>
return 0;
<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>
} else {
<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>
$sudoku[$x][$y] = @r;
<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>
} while $resolved; # repeat if there was any change
<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>
return 1;
<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>
sub solution-complexity-factor($sudoku, Int $x, Int $y) {
<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>
my Int $bx = Int($x / 3); # this block
<span style="color: #000000;">ccount</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">1</span>
my Int $by = Int($y / 3);
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
my multi count-values(Array $val) {
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
return $val.elems;
<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>
my multi count-values(Int $val) {
<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>
return 1;
<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>
# the number of possible values should take precedence
<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>
my Int $f = 1000 * count-values($sudoku[$x][$y]);
<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>
for (flat 0..2 X 0..2) -> $lx, $ly {
<span style="color: #000080;font-style:italic;">-- (reverse order so deletions don't foul indexes)</span>
$f += count-values($sudoku[$lx+$bx*3][$ly+$by*3])
<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>
for 0..^($by*3), (($by+1)*3)..8 -> $ly {
<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>
$f += count-values($sudoku[$x][$ly])
<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>
for 0..^($bx*3), (($bx+1)*3)..8 -> $lx {
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
$f += count-values($sudoku[$lx][$y])
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
}
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
return $f;
<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>
sub matches-in-competing-cells($sudoku, Int $x, Int $y, Int $val) {
<span style="color: #008080;">return</span> <span style="color: #000000;">valid</span>
my Int $bx = Int($x / 3); # this block
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
my Int $by = Int($y / 3);
# Function to decide which possible value to try first
<span style="color: #000080;font-style:italic;">-- from [[Combinations#Phix|Combinations]]
my multi cell-matching(Int $cell) {
-- from http://rosettacode.org/wiki/Combinations#Phix</span>
return $val == $cell ?? 1 !! 0;
<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>
my multi cell-matching(Array $cell) {
<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>
return $cell.grep({ $val == $_ }) ?? 1 !! 0;
<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>
my Int $c = 0;
<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
for (flat 0..2 X 0..2) -> $lx, $ly {
-- get all combinations with and without the next item:</span>
$c += cell-matching($sudoku[$lx+$bx*3][$ly+$by*3])
<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>
for 0..^($by*3), (($by+1)*3)..8 -> $ly {
<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>
$c += cell-matching($sudoku[$x][$ly])
<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>
for 0..^($bx*3), (($bx+1)*3)..8 -> $lx {
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
$c += cell-matching($sudoku[$lx][$y])
}
<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>
return $c;
<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.
sub find-implicit-answers($sudoku, Int $level) {
-- Apply standard eliminations of known cells, then try some more advanced tactics:
my Bool $resolved = False;
--
for grep { $sudoku[$_[0]][$_[1]] ~~ Array },
-- 1) row/col elimination
@cells -> $cell {
-- If in any of the 9 small squares a number can only occur in one row or column,
my Int ($x, $y) = @($cell);
-- then that number cannot occur in that row or column in two other corresponding
for @($sudoku[$x][$y]) -> $val {
-- small squares. Example # If (this is the only cellone with this val assignificant apractical possibility,benefit):
-- # just make it resolved already000|000|036
-- 840|000|000
if (matches-in-competing-cells($sudoku, $x, $y, $val) == 1) {
-- $sudoku[$x][$y] = $val;000|000|020
-- $resolved = True;---+---+---
-- } 000|203|000
-- } 010|000|700
-- 000|600|400
}
-- ---+---+---
return $resolved;
-- 000|410|050
}
-- 003|000|200
 
-- 600|000|000 &lt;-- 3
my $puzzle =
-- map { [ map { $_ == 0 ?? [1..9] !! $_+0 }, @($_) ] }, ^-- 3
-- Naively, the br can contain a 3 in the four corners, but looking at mid-right and
[ 0,0,0,0,3,7,6,0,0 ],
-- mid-bottom leads us to eliminating 3s in column 9 and row 9, leaving 7,7 as the
[ 0,0,0,6,0,0,0,9,0 ],
-- only square in the br that can be a 3. Uses dotcol and dotrow.
[ 0,0,8,0,0,0,0,0,4 ],
-- Without this, brute force on the above takes ~8s, but with it ~0s
[ 0,9,0,0,0,0,0,0,1 ],
-- [ 6,0,0,0,0,0,0,0,9 ],
-- 2) set elimination
[ 3,0,0,0,0,0,0,4,0 ],
-- If in any 9-set there is a set of n blank squares that can only contain n digits,
[ 7,0,0,0,0,0,8,0,0 ],
-- then no other squares can contain those digits. Example (with some benefit):
[ 0,1,0,0,0,9,0,0,0 ],
-- 75.|.9.|.46
[ 0,0,2,5,4,0,0,0,0 ];
-- 961|...|352
 
-- 4..|...|79.
my $solved = solve($puzzle, 0);
-- ---+---+---
if $solved {
-- 2..|6.1|..7
print-sudoku($solved,0);
-- .8.|...|.2.
} else {
-- 1..|328|.65
say "unsolvable.";
-- ---+---+---
}
-- ...|...|... &lt;-- [7,8] is {1,3,8}, [7,9] is {1,3,8}
 
-- 3.9|...|2.4 &lt;-- [8,8] is {1,8}
# Utility functions, not really part of the solution
-- 84.|.3.|.79
 
-- The three cells above the br 479 can only contain {1,3,8}, so the .. of the .2.
sub trace(Int $level, Str $message) {
-- in column 7 of that square are {5,6} (not 1) and hence [9,4] must be a 1.
say '.' x $level, $message;
-- (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.)
sub clone-sudoku($sudoku) {
-- (One could argue that [7,7] and [9,7] are the only places that can hold {5,6} and
my $clone;
-- therefore we should eliminate all non-{5,6} from those squares, as an alternative
for (flat 0..8 X 0..8) -> $x, $y {
-- strategy. However I think that would be harder to code and cannot imagine a case
$clone[$x][$y] = $sudoku[$x][$y];
-- said complementary logic covers, that the above does not, cmiiw.)
}
--
return $clone;
-- 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
sub print-sudoku($sudoku, Int $level = 1) {
-- cannot occur elsewhere in those two columns/rows. Example (with a benefit):
trace $level, '-' x 5*9;
-- .43|98.|25. &lt;-- 6 in [1,{6,9}]
for @($sudoku) -> $row {
-- 6..|425|...
trace $level, join " ", do for @($row) -> $cell {
-- $cell ~~ Array ?? "#{$cell2.elems}#" !! " $cell " .|..1|.94
-- } ---+---+---
-- 9..|..4|.7. &lt;-- hence 6 not in [4,9]
}
-- 3..|6.8|...
}</lang>
-- 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))
Trying 8 on 9,1 [8, 9]
"000000036840000000000000020000203000010000700000600400000410050003000200600000000", -- (0.03s, (brute force))
.Trying 6 on 9,2 [3, 6]
".......39.....1..5..3.5.8....8.9...6.7...2...1..4.......9.8..5..2....6..4..7.....", -- (1.31s, (brute force))
..Trying 7 on 9,9 [3, 7]
"000037600000600090008000004090000001600000009300000040700000800010009000002540000", -- (0.00s, (logic))
...Trying 1 on 9,8 [1, 3]
"....839..1......3...4....7..42.3....6.......4....7..1..2........8...92.....25...6", -- (0.03s, (brute force))
....Trying 4 on 8,1 [4, 5]
"..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))
.....Trying 3 on 7,2 [3, 5]
"--3------4---8--36--8---1---4--6--73---9----------2--5--4-7--686--------7--6--5--", -- (0.03s, (brute force))
......Trying 3 on 8,7 [2, 3]
"..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))
.......Trying 6 on 8,9 [2, 6]
"--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))
.......Trying 2 on 8,9 [2, 6]
".4398.25.6..425...2....1.949....4.7.3..6.8...41.2.9..382.5.........4...553489.71.", -- (0.00s, (logic))
.......Backtrack, path unsolvable... (on 8 9)
".9...4..7.....79..8........4.58.....3.......2.....97.6........4..35.....2..6...8.", -- (0.00s, (logic))
......Trying 2 on 8,7 [2, 3]
"1....7.9..3..2...8..96..5....53..9...1..8...26....4...3......1..4......7..7...3..", -- (0.26s, (brute force))
.......Trying 3 on 8,9 [3, 6]
"12.3....435....1....4........54..2..6...7.........8.9...31..5.......9.7.....6...8", -- (0.40s, (brute force))
.......Trying 6 on 8,9 [3, 6]
"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))
.......Backtrack, path unsolvable... (on 8 9)
"394..267....3..4..5..69..2..45...9..6.......7..7...58..1..67..8..9..8....264..735", -- (0.00s, (logic))
......Backtrack, path unsolvable... (on 8 7)
"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))
.....Trying 5 on 7,2 [3, 5]
"5...7....6..195....98....6.8...6...34..8.3..17...2...6.6....28....419..5....8..79", -- (0.00s, (logic))
......Trying 5 on 8,7 [2, 5]
"503600009010002600900000080000700005006804100200003000030000008004300050800006702", -- (0.01s, (logic))
.......Trying 6 on 8,9 [2, 6]
"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))
.......Trying 2 on 8,9 [2, 6]
"530070000600195000098000060800060003400803001700020006060000280000419005000080079", -- (0.00s, (logic))
.......Backtrack, path unsolvable... (on 8 9)
"75..9..46961...3524.....79.2..6.1..7.8.....2.1..328.65.........3.9...2.484..3..79", -- (0.01s, (logic))
......Trying 2 on 8,7 [2, 5]
"800000000003600000070090200050007000000045700000100030001000068008500010090000400", -- (0.21s, (brute force))
.......Trying 5 on 8,9 [5, 6]
"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))
.......Trying 6 on 8,9 [5, 6]
"85...24..72......9..4.........1.7..23.5...9...4...........8..7..17..........36.4.", -- (0.01s, (logic))
.......Backtrack, path unsolvable... (on 8 9)
"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))
......Backtrack, path unsolvable... (on 8 7)
"97.3...6..6.75.........8.5.......67.....3.....539..2..7...25.....2.1...8.4...73..", -- (0.00s, (logic))
.....Backtrack, path unsolvable... (on 7 2)
"000060080020000000001000000070000102500030000000000400004201000300700600000000050", -- (0.01s, (brute force))
....Trying 5 on 8,1 [4, 5]
27 puzzles solved in 3.74s (av 0.14s)
.....Trying 3 on 8,3 [3, 4]
</pre>
......Trying 6 on 8,9 [2, 6]
Running the fuller version mentioned above:
.......Trying 3 on 7,9 [3, 5]
<pre>
........Trying 5 on 1,9 [2, 5]
"008002000000600040064000092017005004200000008800100730470000910080001000000900200", -- (0.05s, *** MULTIPLE SOLUTIONS ***)
.........Trying 3 on 3,8 [3, 7]
338 puzzles solved in 36.20s (av 0.11s)
..........Trying 4 on 2,1 [1, 4]
--or
..........Trying 1 on 2,1 [1, 4]
338 puzzles solved in 16.46s (av 0.05s) (w/o check for multiple solutions)
..........Backtrack, path unsolvable... (on 2 1)
</pre>
.........Trying 7 on 3,8 [3, 7]
Running a single puzzle (run_one_test set non-zero) produces:
..........Trying 3 on 3,7 [1, 3]
<pre>
..........Trying 1 on 3,7 [1, 3]
. . ........Backtrack, path| unsolvable. . . (on| 3. 7). .
. . . | . . 3 | . 8 5
.........Backtrack, path unsolvable... (on 3 8)
. . 1 | ......Trying 2 on. 1,9| [2,. 5]. .
-------+-------+-------
.........Trying 3 on 3,8 [3, 7]
. . . | 5 .......Trying 7 on| 2,7. [1,. 7].
. . 4 | . . .......Trying 9| on 3,1 [2,. 9].
. 9 . | . . .......Trying 2| on. 3,1. [2, 9].
-------+-------+-------
...........Backtrack, path unsolvable... (on 3 1)
5 . . | . . ......Trying 1| on. 2,7 [1, 7]3
. . 2 | . 1 . | . . .
..........Backtrack, path unsolvable... (on 2 7)
. . . | ......Trying 74 on. 3,8| [3,. . 7]9
solution:
..........Trying 3 on 3,7 [1, 3]
9 8 7 | 6 5 4 | 3 2 1
..........Trying 1 on 3,7 [1, 3]
2 4 6 | 1 7 3 | 9 8 5
...........Trying 9 on 3,1 [2, 9]
3 5 1 | 9 2 8 | 7 4 6
...........Trying 2 on 3,1 [2, 9]
-------+-------+-------
...........Backtrack, path unsolvable... (on 3 1)
1 2 8 | 5 3 7 | 6 9 4
..........Backtrack, path unsolvable... (on 3 7)
6 3 4 | 8 9 2 | 1 5 7
.........Backtrack, path unsolvable... (on 3 8)
7 9 5 | 4 6 1 | 8 3 2
........Backtrack, path unsolvable... (on 1 9)
-------+-------+-------
.......Trying 5 on 7,9 [3, 5]
5 1 9 | 2 8 6 | 4 7 3
........Trying 8 on 1,9 [2, 8]
.........Trying 4 7 2 on| 3,7 [1, 2]9 | 5 6 8
8 6 3 | 7 4 5 | 2 1 9
.........Trying 1 on 3,7 [1, 2]
(logic), 0.02s
.........Backtrack, path unsolvable... (on 3 7)
........Trying 2 on 1,9 [2, 8]
.........Trying 7 on 3,8 [5, 7]
..........Trying 5 on 3,7 [1, 5]
...........Trying 2 on 2,1 [2, 4]
...........Trying 4 on 2,1 [2, 4]
...........Backtrack, path unsolvable... (on 2 1)
..........Trying 1 on 3,7 [1, 5]
...........Trying 9 on 3,1 [2, 9]
...........Trying 2 on 3,1 [2, 9]
...........Backtrack, path unsolvable... (on 3 1)
..........Backtrack, path unsolvable... (on 3 7)
.........Trying 5 on 3,8 [5, 7]
..........Trying 7 on 3,7 [1, 7]
...........Trying 2 on 2,1 [2, 4]
...........Trying 4 on 2,1 [2, 4]
...........Backtrack, path unsolvable... (on 2 1)
..........Trying 1 on 3,7 [1, 7]
..........Backtrack, path unsolvable... (on 3 7)
.........Backtrack, path unsolvable... (on 3 8)
........Backtrack, path unsolvable... (on 1 9)
.......Backtrack, path unsolvable... (on 7 9)
......Trying 2 on 8,9 [2, 6]
.......Trying 3 on 7,9 [3, 5]
........Trying 8 on 1,9 [5, 8]
.........Trying 3 on 3,8 [3, 7]
..........Trying 4 on 1,3 [1, 4]
...........Trying 9 on 1,1 [1, 9]
............Trying 1 on 3,1 [1, 2]
............Trying 2 on 3,1 [1, 2]
............Backtrack, path unsolvable... (on 3 1)
...........Trying 1 on 1,1 [1, 9]
...........Backtrack, path unsolvable... (on 1 1)
..........Trying 1 on 1,3 [1, 4]
...........Trying 9 on 1,1 [4, 9]
...........Trying 4 on 1,1 [4, 9]
...........Backtrack, path unsolvable... (on 1 1)
..........Backtrack, path unsolvable... (on 1 3)
.........Trying 7 on 3,8 [3, 7]
..........Trying 3 on 3,7 [1, 3]
..........Trying 1 on 3,7 [1, 3]
...........Trying 9 on 3,1 [2, 9]
...........Trying 2 on 3,1 [2, 9]
...........Backtrack, path unsolvable... (on 3 1)
..........Backtrack, path unsolvable... (on 3 7)
.........Backtrack, path unsolvable... (on 3 8)
........Trying 5 on 1,9 [5, 8]
........Backtrack, path unsolvable... (on 1 9)
.......Trying 5 on 7,9 [3, 5]
........Trying 5 on 1,8 [2, 5]
.........Trying 7 on 3,8 [2, 7]
..........Trying 4 on 1,3 [1, 4]
..........Trying 1 on 1,3 [1, 4]
..........Backtrack, path unsolvable... (on 1 3)
.........Trying 2 on 3,8 [2, 7]
..........Trying 9 on 3,1 [1, 9]
..........Trying 1 on 3,1 [1, 9]
..........Backtrack, path unsolvable... (on 3 1)
.........Backtrack, path unsolvable... (on 3 8)
........Trying 2 on 1,8 [2, 5]
.........Trying 7 on 3,8 [5, 7]
..........Trying 4 on 1,3 [1, 4]
...........Trying 9 on 1,1 [1, 9]
............Trying 1 on 3,1 [1, 2]
............Trying 2 on 3,1 [1, 2]
............Backtrack, path unsolvable... (on 3 1)
...........Trying 1 on 1,1 [1, 9]
...........Backtrack, path unsolvable... (on 1 1)
..........Trying 1 on 1,3 [1, 4]
...........Trying 9 on 1,1 [4, 9]
...........Trying 4 on 1,1 [4, 9]
...........Backtrack, path unsolvable... (on 1 1)
..........Backtrack, path unsolvable... (on 1 3)
.........Trying 5 on 3,8 [5, 7]
..........Trying 7 on 3,7 [1, 7]
...........Trying 2 on 2,1 [2, 4]
...........Trying 4 on 2,1 [2, 4]
...........Backtrack, path unsolvable... (on 2 1)
..........Trying 1 on 3,7 [1, 7]
..........Backtrack, path unsolvable... (on 3 7)
.........Backtrack, path unsolvable... (on 3 8)
........Backtrack, path unsolvable... (on 1 8)
.......Backtrack, path unsolvable... (on 7 9)
......Backtrack, path unsolvable... (on 8 9)
.....Trying 4 on 8,3 [3, 4]
......Trying 3 on 8,7 [2, 3]
.......Trying 6 on 8,9 [2, 6]
.......Trying 2 on 8,9 [2, 6]
.......Backtrack, path unsolvable... (on 8 9)
......Trying 2 on 8,7 [2, 3]
.......Trying 3 on 8,9 [3, 6]
.......Trying 6 on 8,9 [3, 6]
.......Backtrack, path unsolvable... (on 8 9)
......Backtrack, path unsolvable... (on 8 7)
.....Backtrack, path unsolvable... (on 8 3)
....Backtrack, path unsolvable... (on 8 1)
...Trying 3 on 9,8 [1, 3]
....Trying 4 on 8,1 [4, 5]
.....Trying 3 on 7,2 [3, 5]
.....Trying 5 on 7,2 [3, 5]
......Trying 6 on 7,9 [2, 6]
......Trying 2 on 7,9 [2, 6]
......Backtrack, path unsolvable... (on 7 9)
.....Backtrack, path unsolvable... (on 7 2)
....Trying 5 on 8,1 [4, 5]
.....Trying 6 on 8,9 [2, 6]
......Trying 8 on 1,9 [2, 8]
.......Trying 1 on 3,7 [1, 2]
.......Trying 2 on 3,7 [1, 2]
.......Backtrack, path unsolvable... (on 3 7)
......Trying 2 on 1,9 [2, 8]
.......Trying 7 on 3,8 [5, 7]
........Trying 5 on 3,7 [1, 5]
.........Trying 9 on 3,1 [1, 9]
.........Trying 1 on 3,1 [1, 9]
.........Backtrack, path unsolvable... (on 3 1)
........Trying 1 on 3,7 [1, 5]
.........Trying 9 on 3,1 [2, 9]
.........Trying 2 on 3,1 [2, 9]
.........Backtrack, path unsolvable... (on 3 1)
........Backtrack, path unsolvable... (on 3 7)
.......Trying 5 on 3,8 [5, 7]
........Trying 7 on 3,7 [1, 7]
.........Trying 9 on 3,1 [1, 9]
.........Trying 1 on 3,1 [1, 9]
.........Backtrack, path unsolvable... (on 3 1)
........Trying 1 on 3,7 [1, 7]
........Backtrack, path unsolvable... (on 3 7)
.......Backtrack, path unsolvable... (on 3 8)
......Backtrack, path unsolvable... (on 1 9)
.....Trying 2 on 8,9 [2, 6]
......Trying 5 on 1,8 [2, 5]
.......Trying 7 on 3,8 [2, 7]
........Trying 4 on 2,1 [1, 4]
........Trying 1 on 2,1 [1, 4]
........Backtrack, path unsolvable... (on 2 1)
.......Trying 2 on 3,8 [2, 7]
........Trying 9 on 3,1 [1, 9]
........Trying 1 on 3,1 [1, 9]
........Backtrack, path unsolvable... (on 3 1)
.......Backtrack, path unsolvable... (on 3 8)
......Trying 2 on 1,8 [2, 5]
.......Trying 7 on 3,8 [5, 7]
........Trying 1 on 3,7 [1, 5]
.........Trying 9 on 3,1 [2, 9]
.........Trying 2 on 3,1 [2, 9]
.........Backtrack, path unsolvable... (on 3 1)
........Trying 5 on 3,7 [1, 5]
.........Trying 9 on 3,1 [1, 9]
.........Trying 1 on 3,1 [1, 9]
.........Backtrack, path unsolvable... (on 3 1)
........Backtrack, path unsolvable... (on 3 7)
.......Trying 5 on 3,8 [5, 7]
........Trying 9 on 3,1 [1, 9]
........Trying 1 on 3,1 [1, 9]
........Backtrack, path unsolvable... (on 3 1)
.......Backtrack, path unsolvable... (on 3 8)
......Backtrack, path unsolvable... (on 1 8)
.....Backtrack, path unsolvable... (on 8 9)
....Backtrack, path unsolvable... (on 8 1)
...Backtrack, path unsolvable... (on 9 8)
..Trying 3 on 9,9 [3, 7]
...Trying 4 on 8,1 [4, 5]
....Trying 3 on 7,2 [3, 5]
....Trying 5 on 7,2 [3, 5]
.....Trying 6 on 7,9 [2, 6]
.....Trying 2 on 7,9 [2, 6]
.....Backtrack, path unsolvable... (on 7 9)
....Backtrack, path unsolvable... (on 7 2)
...Trying 5 on 8,1 [4, 5]
....Trying 6 on 8,9 [2, 6]
.....Trying 8 on 1,9 [2, 8]
......Trying 7 on 2,9 [2, 7]
.......Trying 1 on 3,7 [1, 2]
.......Trying 2 on 3,7 [1, 2]
.......Backtrack, path unsolvable... (on 3 7)
......Trying 2 on 2,9 [2, 7]
.......Trying 4 on 2,1 [1, 4]
.......Trying 1 on 2,1 [1, 4]
.......Backtrack, path unsolvable... (on 2 1)
......Backtrack, path unsolvable... (on 2 9)
.....Trying 2 on 1,9 [2, 8]
......Trying 3 on 3,8 [3, 5]
.......Trying 5 on 2,7 [1, 5]
........Trying 9 on 3,1 [2, 9]
........Trying 2 on 3,1 [2, 9]
........Backtrack, path unsolvable... (on 3 1)
.......Trying 1 on 2,7 [1, 5]
.......Backtrack, path unsolvable... (on 2 7)
......Trying 5 on 3,8 [3, 5]
.......Trying 3 on 3,7 [1, 3]
.......Trying 1 on 3,7 [1, 3]
.......Backtrack, path unsolvable... (on 3 7)
......Backtrack, path unsolvable... (on 3 8)
.....Backtrack, path unsolvable... (on 1 9)
....Trying 2 on 8,9 [2, 6]
.....Trying 5 on 1,8 [2, 5]
......Trying 3 on 3,8 [2, 3]
.......Trying 4 on 2,1 [1, 4]
.......Trying 1 on 2,1 [1, 4]
.......Backtrack, path unsolvable... (on 2 1)
......Trying 2 on 3,8 [2, 3]
.......Trying 9 on 3,1 [1, 9]
.......Trying 1 on 3,1 [1, 9]
.......Backtrack, path unsolvable... (on 3 1)
......Backtrack, path unsolvable... (on 3 8)
.....Trying 2 on 1,8 [2, 5]
......Trying 3 on 3,8 [3, 5]
.......Trying 4 on 1,3 [1, 4]
.......Trying 1 on 1,3 [1, 4]
.......Backtrack, path unsolvable... (on 1 3)
......Trying 5 on 3,8 [3, 5]
.......Trying 9 on 3,1 [1, 9]
.......Trying 1 on 3,1 [1, 9]
.......Backtrack, path unsolvable... (on 3 1)
......Backtrack, path unsolvable... (on 3 8)
.....Backtrack, path unsolvable... (on 1 8)
....Backtrack, path unsolvable... (on 8 9)
...Backtrack, path unsolvable... (on 8 1)
..Backtrack, path unsolvable... (on 9 9)
.Trying 3 on 9,2 [3, 6]
..Trying 7 on 9,9 [6, 7]
...Trying 1 on 9,8 [1, 6]
....Trying 4 on 8,1 [4, 5]
.....Trying 6 on 7,2 [5, 6]
......Trying 3 on 8,7 [2, 3]
.......Trying 6 on 8,9 [2, 6]
.......Trying 2 on 8,9 [2, 6]
.......Backtrack, path unsolvable... (on 8 9)
......Trying 2 on 8,7 [2, 3]
.......Trying 6 on 8,9 [3, 6]
.......Trying 3 on 8,9 [3, 6]
.......Backtrack, path unsolvable... (on 8 9)
......Backtrack, path unsolvable... (on 8 7)
.....Trying 5 on 7,2 [5, 6]
......Trying 4 on 1,2 [2, 4]
.......Trying 1 on 1,3 [1, 5]
........Trying 2 on 2,1 [2, 5]
........Trying 5 on 2,1 [2, 5]
........Backtrack, path unsolvable... (on 2 1)
.......Trying 5 on 1,3 [1, 5]
........Trying 1 on 2,1 [1, 2]
.........Trying 9 on 1,1 [2, 9]
..........Trying 8 on 1,9 [2, 8]
..........Trying 2 on 1,9 [2, 8]
..........Backtrack, path unsolvable... (on 1 9)
.........Trying 2 on 1,1 [2, 9]
.........Backtrack, path unsolvable... (on 1 1)
........Trying 2 on 2,1 [1, 2]
.........Trying 9 on 1,1 [1, 9]
..........Trying 8 on 1,9 [2, 8]
...........Trying 2 on 8,9 [2, 3]
...........Trying 3 on 8,9 [2, 3]
...........Backtrack, path unsolvable... (on 8 9)
..........Trying 2 on 1,9 [2, 8]
..........Backtrack, path unsolvable... (on 1 9)
.........Trying 1 on 1,1 [1, 9]
..........Trying 8 on 1,9 [2, 8]
...........Trying 2 on 8,9 [2, 3]
...........Trying 3 on 8,9 [2, 3]
...........Backtrack, path unsolvable... (on 8 9)
..........Trying 2 on 1,9 [2, 8]
..........Backtrack, path unsolvable... (on 1 9)
.........Backtrack, path unsolvable... (on 1 1)
........Backtrack, path unsolvable... (on 2 1)
.......Backtrack, path unsolvable... (on 1 3)
......Trying 2 on 1,2 [2, 4]
.......Trying 1 on 2,1 [1, 5]
........Trying 9 on 1,1 [5, 9]
.........Trying 8 on 1,9 [5, 8]
.........Trying 5 on 1,9 [5, 8]
.........Backtrack, path unsolvable... (on 1 9)
........Trying 5 on 1,1 [5, 9]
........Backtrack, path unsolvable... (on 1 1)
.......Trying 5 on 2,1 [1, 5]
........Trying 9 on 1,1 [1, 9]
.........Trying 8 on 1,9 [5, 8]
..........Trying 6 on 7,9 [3, 6]
..........Trying 3 on 7,9 [3, 6]
..........Backtrack, path unsolvable... (on 7 9)
.........Trying 5 on 1,9 [5, 8]
.........Backtrack, path unsolvable... (on 1 9)
........Trying 1 on 1,1 [1, 9]
.........Trying 8 on 1,9 [5, 8]
..........Trying 5 on 8,9 [3, 5]
..........Trying 3 on 8,9 [3, 5]
..........Backtrack, path unsolvable... (on 8 9)
.........Trying 5 on 1,9 [5, 8]
.........Backtrack, path unsolvable... (on 1 9)
........Backtrack, path unsolvable... (on 1 1)
.......Backtrack, path unsolvable... (on 2 1)
......Backtrack, path unsolvable... (on 1 2)
.....Backtrack, path unsolvable... (on 7 2)
....Trying 5 on 8,1 [4, 5]
.....Trying 6 on 8,3 [4, 6]
......Trying 3 on 8,9 [2, 3]
.......Trying 6 on 7,9 [5, 6]
........Trying 5 on 1,9 [2, 5]
.........Trying 3 on 3,8 [3, 7]
..........Trying 4 on 2,1 [1, 4]
..........Trying 1 on 2,1 [1, 4]
..........Backtrack, path unsolvable... (on 2 1)
.........Trying 7 on 3,8 [3, 7]
..........Trying 3 on 3,7 [1, 3]
..........Trying 1 on 3,7 [1, 3]
..........Backtrack, path unsolvable... (on 3 7)
.........Backtrack, path unsolvable... (on 3 8)
........Trying 2 on 1,9 [2, 5]
.........Trying 3 on 3,8 [3, 7]
..........Trying 7 on 2,7 [1, 7]
..........Trying 1 on 2,7 [1, 7]
...........Trying 4 on 2,1 [2, 4]
...........Trying 2 on 2,1 [2, 4]
...........Solved... (2 on 2,1)
..........Solved... (1 on 2,7)
.........Solved... (3 on 3,8)
........Solved... (2 on 1,9)
.......Solved... (6 on 7,9)
......Solved... (3 on 8,9)
.....Solved... (6 on 8,3)
....Solved... (5 on 8,1)
...Solved... (1 on 9,8)
..Solved... (7 on 9,9)
.Solved... (3 on 9,2)
Solved... (8 on 9,1)
---------------------------------------------
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|PHP}}==
{{trans|C++}}
<langsyntaxhighlight lang="php"> class SudokuSolver {
protected $grid = [];
protected $emptySymbol;
Line 7,748 ⟶ 9,333:
$solver = new SudokuSolver('009170000020600001800200000200006053000051009005040080040000700006000320700003900');
$solver->solve();
$solver->display();</langsyntaxhighlight>
{{out}}
<pre>
Line 7,765 ⟶ 9,350:
</pre>
 
=={{header|PhixPicat}}==
Using constraint programming.
Simple brute force solution. Generally quite good but will struggle on some puzzles (eg see "the beast" below)
<lang Phix>sequence board = split("""
.......39
.....1..5
..3.5.8..
..8.9...6
.7...2...
1..4.....
..9.8..5.
.2....6..
4..7.....""",'\n')
 
<syntaxhighlight lang="picat">import util.
function valid_move(integer y, integer x, integer ch)
import cp.
for i=1 to 9 do
if ch=board[i][x] then return 0 end if
if ch=board[y][i] then return 0 end if
end for
y -= mod(y-1,3)
x -= mod(x-1,3)
for ys=y to y+2 do
for xs=x to x+2 do
if ch=board[ys][xs] then return 0 end if
end for
end for
return 1
end function
 
main => go.
sequence solution = {}
 
go =>
procedure brute_solve()
sudokus(Sudokus),
for y=1 to 9 do
foreach([Comment,SudokuS] in Sudokus)
for x=1 to 9 do
println(SudokuS),
if board[y][x]<='0' then
println(Comment),
for ch='1' to '9' do
% Convert string to numbers and "." to _ (unknown)
if valid_move(y,x,ch) then
Sudoku = [ [cond(S == '.',_,S.to_integer()) :
board[y][x] = ch
S in slice(SudokuS,(I*9)+1,(I+1)*9)] : I in brute_solve()0..8],
print_board(Sudoku),
board[y][x] = ' '
% Ensure unicity of the solution (check that it is a unique if length(solution) then return end if
All = findall(Sudoku,sudoku(Sudoku)),
end if
if All.length > 1 end forthen
printf("Problem has %d solutions!\n", All.length)
return
end if,
print("Solution:")
end for
endforeach(A forin All)
print_board(A)
solution = board -- (already solved case)
end,
end procedure
nl
end,
nl.
 
sudoku(Board) =>
atom t0 = time()
N = ceiling(sqrt(Board.len)),
brute_solve()
N2 = N*N,
printf(1,"%s\n(solved in %3.2fs)\n",{join(solution,"\n"),time()-t0})</lang>
Vars = Board.vars(),
{{out}}
Vars :: 1..N2,
<pre>
foreach(Row in Board) all_different(Row) end,
751846239
foreach(Column in transpose(Board)) all_different(Column) end,
892371465
foreach(I in 1..N..N2, J in 1..N..N2)
643259871
all_different([Board[I+K,J+L] : K in 0..N-1, L in 0..N-1])
238197546
end,
974562318
solve([ffd,inout], Vars).
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).
<lang Phix>-- 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.
 
print_board(Board) =>
sequence nines = {}, -- will be 27 in total
N = Board.length,
cols = repeat(0,9*9), -- remainder(i-1,9)+1
foreach(I in 1..N)
rows = repeat(0,9*9), -- floor((i-1)/9)+10
foreach(J in squares = repeat(0,9*91..N),
X = Board[I,J],
sixes = {}, -- will be 18 in total
dotcolif = repeatvar(0,9*9X), then printf(" --_") sameelse colprintf(" %w", diffX) squareend
end,
dotrow = repeat(0,9*9) -- same row, diff square
nl
end,
nl.
 
% (Problems from the Groovy implementation)
procedure set_nines()
sudokus(Sudokus) => Sudokus =
sequence nine, six
[
integer idx, ndx
"819..5.....2...75..371.4.6.4..59.1..7..3.8..2..3.62..7.5.7.921..64...9.....2..438",
for x=0 to 8 do -- columns
"53..247....2...8..1..7.39.2..8.72.49.2.98..7.79.....8.....3.5.696..1.3...5.69..1.",
nine = {}
"..3.2.6..9..3.5..1..18.64....81.29..7.......8..67.82....26.95..8..2.3..9..5.1.3..",
ndx = length(nines)+1
"394..267....3..4..5..69..2..45...9..6.......7..7...58..1..67..8..9..8....264..735",
for y=1 to 81 by 9 do
"97.3...6..6.75.........8.5.......67.....3.....539..2..7...25.....2.1...8.4...73..",
idx = y+x
"4......6.5...8.9..3....1....2.7....1.9.....4.8....3.5....2....7..6.5...8.1......6",
nine = append(nine,idx)
"85...24..72......9..4.........1.7..23.5...9...4...........8..7..17..........36.4.",
cols[idx] = ndx
"..1..5.7.92.6.......8...6...9..2.4.1.........3.4.8..9...7...3.......7.69.1.8..7..",
end for
".9...4..7.....79..8........4.58.....3.......2.....97.6........4..35.....2..6...8.",
nines = append(nines,nine)
"12.3....435....1....4........54..2..6...7.........8.9...31..5.......9.7.....6...8",
end for
"9..2..5...4..6..3...3.....6...9..2......5..8...7..4..37.....1...5..2..4...1..6..9",
for y=1 to 81 by 9 do -- rows
"1....7.9..3..2...8..96..5....53..9...1..8...26....4...3......1..4......7..7...3..",
nine = {}
"12.4..3..3...1..5...6...1..7...9.....4.6.3.....3..2...5...8.7....7.....5.......98",
ndx = length(nines)+1
"..............3.85..1.2.......5.7.....4...1...9.......5......73..2.1........4...9",
for x=0 to 8 do
".......39.....1..5..3.5.8....8.9...6.7...2...1..4.......9.8..5..2....6..4..7.....",
idx = y+x
"....839..1......3...4....7..42.3....6.......4....7..1..2........8...92.....25...6",
nine = append(nine,idx)
"..3......4...8..36..8...1...4..6..73...9..........2..5..4.7..686........7..6..5.."
rows[idx] = ndx
].</syntaxhighlight>
end for
nines = append(nines,nine)
end for
if length(nines)!=18 then ?9/0 end if
for y=0 to 8 by 3 do -- small squares [19..27]
for x=0 to 8 by 3 do
nine = {}
ndx = length(nines)+1
for sy=y*9 to y*9+18 by 9 do
for sx=x to x+2 do
idx = sy+sx+1
nine = append(nine,idx)
squares[idx] = ndx
end for
end for
nines = append(nines,nine)
end for
end for
if length(nines)!=27 then ?9/0 end if
for i=1 to 9*9 do
six = {}
nine = nines[cols[i]] -- dotcol
for j=1 to length(nine) do
if squares[i]!=squares[nine[j]] then
six = append(six,nine[j])
end if
end for
ndx = find(six,sixes)
if ndx=0 then
sixes = append(sixes,six)
ndx = length(sixes)
end if
dotcol[i] = ndx
six = {}
nine = nines[rows[i]] -- dotrow
for j=1 to length(nine) do
if squares[i]!=squares[nine[j]] then
six = append(six,nine[j])
end if
end for
ndx = find(six,sixes)
if ndx=0 then
sixes = append(sixes,six)
ndx = length(sixes)
end if
dotrow[i] = ndx
end for
end procedure
set_nines()
 
{{out}}
integer improved = 0
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:
function eliminate_in(sequence valid, sequence set, integer ch)
8 for i=1 to length(set)9 6 7 5 3 2 do4
6 4 2 integer9 idx =8 set[i] 3 7 5 1
5 3 7 if1 string(valid[idx]) then2 4 8 6 9
4 2 6 5 9 integer7 k =1 find(ch,valid[idx]) 8 3
7 9 5 3 1 if8 k!=0 then6 4 2
1 8 3 4 6 2 5 valid[idx][k..k]9 = ""7
3 5 8 7 4 9 2 improved1 = 16
2 6 4 8 3 end1 if 9 7 5
9 7 1 end2 if 5 6 4 3 8
end for
return valid
end function
 
...
function test_comb(sequence chosen, sequence pool, sequence valid)
--
-- (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)
--
sequence contains = repeat(0,9)
integer ccount = 0, ch
object set
 
for i=1 to length(chosen) do
set = valid[pool[chosen[i]]]
for j=1 to length(set) do
ch = set[j]-'0'
if contains[ch]=0 then
contains[ch] = 1
ccount += 1
end if
end for
end for
if ccount=length(chosen) then
for i=1 to length(pool) do
if find(i,chosen)=0 then
set = valid[pool[i]]
if sequence(set) then
-- (reverse order so deletions don't foul indexes)
for j=length(set) to 1 by -1 do
ch = set[j]-'0'
if contains[ch] then
valid[pool[i]][j..j] = ""
improved = 1
end if
end for
end if
end if
end for
end if
return valid
end function
 
-- from [[Combinations#Phix|Combinations]]
-- from http://rosettacode.org/wiki/Combinations#Phix
function comb(sequence pool, valid, integer needed, done=0, sequence chosen={})
-- (used by deep_logic()/set elimination)
if needed=0 then -- got a full set
return test_comb(chosen,pool,valid)
end if
if done+needed>length(pool) then return valid end if -- cannot fulfil
-- get all combinations with and without the next item:
done += 1
if sequence(valid[pool[done]]) then
valid = comb(pool,valid,needed-1,done,append(chosen,done))
end if
return comb(pool,valid,needed,done,chosen)
end function
 
function deep_logic(string board, sequence valid)
--
-- 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 <-- 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
-- ---+---+---
-- ...|...|... <-- [7,8] is {1,3,8}, [7,9] is {1,3,8}
-- 3.9|...|2.4 <-- [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. <-- 6 in [1,{6,9}]
-- 6..|425|...
-- 2..|..1|.94
-- ---+---+---
-- 9..|..4|.7. <-- hence 6 not in [4,9]
-- 3..|6.8|...
-- 41.|2.9|..3
-- ---+---+---
-- 82.|5..|... <-- hence 6 not in [7,6],[7,9]
-- ...|.4.|..5 <-- hence 6 not in [8,6]
-- 534|89.|71. <-- 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 <-- 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 >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.]
--
integer col, row
sequence c, r
sequence nine, prevsets, set
object vj
integer ch, k, idx, sx, sy, count
 
if length(valid)=0 then
-- initialise/start again from scratch
valid = repeat("123456789",9*9)
end if
--
-- First perform standard eliminations of any known cells:
-- (repeated every time so plain_logic() does not have to worry about it)
--
for i=1 to 9*9 do
ch = board[i]
if ch>'0'
and string(valid[i]) then
valid[i] = ch
valid = eliminate_in(valid,nines[cols[i]],ch)
valid = eliminate_in(valid,nines[rows[i]],ch)
valid = eliminate_in(valid,nines[squares[i]],ch)
end if
end for
--
-- 1) row/col elimination
--
for s=19 to 27 do
c = repeat(0,9) -- 0 = none seen, 1..9 this col only, -1: >1 col
r = repeat(0,9) -- "" row row
nine = nines[s]
for n=1 to 9 do
k = nine[n]
vj = valid[k]
if string(vj) then
for i=1 to length(vj) do
ch = vj[i]-'0'
col = dotcol[k]
row = dotrow[k]
c[ch] = iff(find(c[ch],{0,col})!=0?col:-1)
r[ch] = iff(find(r[ch],{0,row})!=0?row:-1)
end for
end if
end for
for i=1 to 9 do
ch = i+'0'
col = c[i]
if col>0 then
valid = eliminate_in(valid,sixes[col],ch)
end if
row = r[i]
if row>0 then
valid = eliminate_in(valid,sixes[row],ch)
end if
end for
end for
--
-- 2) set elimination
--
for i=1 to length(nines) do
--
-- Practical note: Meticulously counting empties to eliminate larger set sizes
-- would at best reduce 6642 tests to 972, not deemed worth it.
--
for set_size=2 to 4 do
--if floor(count_empties(nines[i])/2)>=set_size then -- (untested)
valid = comb(nines[i],valid,set_size)
--end if
end for
end for
--
-- 3) x-wings
--
for ch='1' to '9' do
prevsets = repeat(0,9)
for x=1 to 9 do
count = 0
set = repeat(0,9)
for y=0 to 8 do
idx = y*9+x
if sequence(valid[idx]) and find(ch,valid[idx]) then
set[y+1] = 1
count += 1
end if
end for
if count=2 then
k = find(set,prevsets)
if k!=0 then
for y=0 to 8 do
if set[y+1]=1 then
for sx=1 to 9 do
if sx!=k and sx!=x then
valid = eliminate_in(valid,{y*9+sx},ch)
end if
end for
end if
end for
else
prevsets[x] = set
end if
end if
end for
prevsets = repeat(0,9)
for y=0 to 8 do
count = 0
set = repeat(0,9)
for x=1 to 9 do
idx = y*9+x
if sequence(valid[idx]) and find(ch,valid[idx]) then
set[x] = 1
count += 1
end if
end for
if count=2 then
k = find(set,prevsets)
if k!=0 then
for x=1 to 9 do
if set[x]=1 then
for sy=0 to 8 do
if sy+1!=k and sy!=y then
valid = eliminate_in(valid,{sy*9+x},ch)
end if
end for
end if
end for
else
prevsets[y+1] = set
end if
end if
end for
end for
return valid
end function
 
function permitted_in(string board, sequence sets, sequence valid, integer ch)
sequence set
integer pos, idx, bch
for i=1 to 9 do
set = nines[sets[i]]
pos = 0
for j=1 to 9 do
idx = set[j]
bch = board[idx]
if bch>'0' then
if bch=ch then pos = -1 exit end if
elsif find(ch,valid[idx]) then
if pos!=0 then pos = -1 exit end if
pos = idx
end if
end for
if pos>0 then
board[pos] = ch
improved = 1
end if
end for
return board
end function
 
enum INVALID = -1, INCOMPLETE = 0, SOLVED = 1, MULTIPLE = 2, BRUTE = 3
 
function plain_logic(string board)
--
-- Responsible for:
-- 1) cells with only one option
-- 2) numbers with only one home
--
integer solved
sequence valid = {}
object vi
 
while 1 do
solved = SOLVED
improved = 0
valid = deep_logic(board,valid)
 
-- 1) cells with only one option:
for i=1 to length(valid) do
vi = valid[i]
if string(vi) then
if length(vi)=0 then return {board,{},INVALID} end if
if length(vi)=1 then
board[i] = vi[1]
improved = 1
end if
end if
if board[i]<='0' then
solved = INCOMPLETE
end if
end for
if solved=SOLVED then return {board,{},SOLVED} end if
 
-- 2) numbers with only one home
for ch='1' to '9' do
board = permitted_in(board,cols,valid,ch)
board = permitted_in(board,rows,valid,ch)
board = permitted_in(board,squares,valid,ch)
end for
if not improved then exit end if
end while
return {board,valid,solved}
end function
 
function validate(string board)
-- (sum9 should be sufficient - if you want, get rid of nine/nines)
integer ch, sum9
sequence nine, nines = tagset(9)
 
for x=0 to 8 do -- columns
sum9 = 0
nine = repeat(0,9)
for y=1 to 81 by 9 do
ch = board[y+x]-'0'
if ch<1 or ch>9 then return 0 end if
sum9 += ch
nine[ch] = ch
end for
if sum9!=45 then return 0 end if
if nine!=nines then return 0 end if
end for
for y=1 to 81 by 9 do -- rows
sum9 = 0
nine = repeat(0,9)
for x=0 to 8 do
ch = board[y+x]-'0'
sum9 += ch
nine[ch] = ch
end for
if sum9!=45 then return 0 end if
if nine!=nines then return 0 end if
end for
for y=0 to 8 by 3 do -- small squares
for x=0 to 8 by 3 do
sum9 = 0
nine = repeat(0,9)
for sy=y*9 to y*9+18 by 9 do
for sx=x to x+2 do
ch = board[sy+sx+1]-'0'
sum9 += ch
nine[ch] = ch
end for
end for
if sum9!=45 then return 0 end if
if nine!=nines then return 0 end if
end for
end for
return 1
end function
 
function solve(string board, sequence valid={})
sequence solution, solutions
integer solved
integer minopt, mindx
object vi
{solution,valid,solved} = plain_logic(board)
if solved=INVALID then return {{},INVALID} end if
if solved=SOLVED then return {{solution},SOLVED} end if
if solved=BRUTE then return {{solution},BRUTE} end if
if solved!=INCOMPLETE then ?9/0 end if
-- 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.)
minopt = 10
for i=1 to 9*9 do
vi = valid[i]
if string(vi) then
if length(vi)<=1 then ?9/0 end if -- should be caught above
if length(vi)<minopt then
minopt = length(vi)
mindx = i
end if
end if
end for
solutions = {}
for i=1 to minopt do
board[mindx] = valid[mindx][i]
{solution,solved} = solve(board,valid)
if solved=MULTIPLE then
return {solution,MULTIPLE}
elsif solved=SOLVED
or solved=BRUTE then
if not find(solution[1],solutions)
and validate(solution[1]) then
solutions = append(solutions,solution[1])
end if
if length(solutions)>1 then
return {solutions,MULTIPLE}
elsif length(solutions) then
return {solutions,BRUTE}
end if
end if
end for
if length(solutions)=1 then
return {solutions,BRUTE}
end if
return {{},INVALID}
end function
 
function test_one(string board)
sequence solutions
string solution, desc
integer solved
{solutions,solved} = solve(board)
if solved=SOLVED then
desc = "(logic)"
elsif solved=BRUTE then
desc = "(brute force)"
else
desc = "???" -- INVALID/INCOMPLETE/MULTIPLE
end if
if length(solutions)=0 then
solution = board
desc = "*** NO SOLUTIONS ***"
elsif length(solutions)=1 then
solution = solutions[1]
if not validate(solution) then
desc = "*** ERROR ***" -- (should never happen)
end if
else
solution = board
desc = "*** MULTIPLE SOLUTIONS ***"
end if
return {solution,desc}
end function
 
--NB Blank cells can be represented by any character <'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.
 
constant tests = {
"..............3.85..1.2.......5.7.....4...1...9.......5......73..2.1........4...9", -- (0.01s, (logic))
-- row/col elimination (was 8s w/o logic first)
"000000036840000000000000020000203000010000700000600400000410050003000200600000000", -- (0.04s, (brute force))
".......39.....1..5..3.5.8....8.9...6.7...2...1..4.......9.8..5..2....6..4..7.....", -- (1.12s, (brute force))
"000037600000600090008000004090000001600000009300000040700000800010009000002540000", -- (0.00s, (logic))
"....839..1......3...4....7..42.3....6.......4....7..1..2........8...92.....25...6", -- (0.04s, (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))
-- (the following takes ~8s when checking for multiple solutions)
"--3------4---8--36--8---1---4--6--73---9----------2--5--4-7--686--------7--6--5--", -- (0.01s, (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.00s, (logic))
-- x-wings
".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))
-- "AL Escargot", so-called "hardest sudoku"
"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.48s, (brute force))
"12.4..3..3...1..5...6...1..7...9.....4.6.3.....3..2...5...8.7....7.....5.......98", -- (1.07s, (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.01s, (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.00s, (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))
-- set exclusion
"75..9..46961...3524.....79.2..6.1..7.8.....2.1..328.65.........3.9...2.484..3..79", -- (0.00s, (logic))
-- Worlds hardest sudoku:
"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.17s, (brute force))
"97.3...6..6.75.........8.5.......67.....3.....539..2..7...25.....2.1...8.4...73..", -- (0.00s, (logic))
-- "the beast" (an earlier algorithm took 318s (5min 18s) on this):
"000060080020000000001000000070000102500030000000000400004201000300700600000000050", -- (0.03s, (brute force))
$},
 
lt = length(tests),
run_one_test = 0
 
constant l = " x x x | x x x | x x x ",
s = "-------+-------+-------",
l3 = join({l,l,l},"\n"),
fmt = substitute(join({l3,s,l3,s,l3},"\n"),"x","%c")&"\n"
 
procedure print_board(string board)
printf(1,fmt,board)
end procedure
 
procedure test()
string board -- (81 characters)
string solution, desc
atom t0 = time()
if run_one_test then
board = tests[run_one_test]
print_board(board)
{solution,desc} = test_one(board)
if length(solution)!=0 then
printf(1,"solution:\n")
print_board(solution)
end if
printf(1,"%s, %3.2fs\n",{desc,time()-t0})
else
for i=1 to lt do
atom t1 = time()
board = tests[i]
{solution,desc} = test_one(board)
printf(1," \"%s\", -- (%3.2fs, %s)\n",{board,time()-t1,desc})
-- printf(1," \"%s\", -- (%3.2fs, %s)\n",{solution,time()-t1,desc})
end for
t0 = time()-t0
printf(1,"%d puzzles solved in %3.2fs (av %3.2fs)\n",{lt,t0,t0/lt})
end if
end procedure
test()</lang>
{{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|PicoLisp}}==
<langsyntaxhighlight PicoLisplang="picolisp">(load "lib/simul.l")
 
### Fields/Board ###
Line 8,640 ⟶ 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}}
<pre> +---+---+---+---+---+---+---+---+---+
Line 8,662 ⟶ 9,558:
+---+---+---+---+---+---+---+---+---+
a b c d e f g h i</pre>
<syntaxhighlight lang PicoLisp="picolisp">(go)</langsyntaxhighlight>
{{out}}
<pre> +---+---+---+---+---+---+---+---+---+
Line 8,687 ⟶ 9,583:
=={{header|PL/I}}==
Working PL/I version, derived from the Rosetta Fortran version.
<langsyntaxhighlight lang="pli">sudoku: procedure options (main); /* 27 July 2014 */
 
declare grid (9,9) fixed (1) static initial (
Line 8,770 ⟶ 9,666:
 
end sudoku;
</syntaxhighlight>
</lang>
{{out}}
<pre>
Line 8,804 ⟶ 9,700:
 
Another PL/I version, reads sudoku from the text data file as 81 character record.
<langsyntaxhighlight lang="pli">
*PROCESS MARGINS(1,120) LIBS(SINGLE,STATIC);
*PROCESS OPTIMIZE(2) DFT(REORDER);
Line 8,943 ⟶ 9,839:
 
end sudoku;
</syntaxhighlight>
</lang>
 
=={{header|Prolog}}==
<langsyntaxhighlight Prologlang="prolog">:- use_module(library(clpfd)).
sudoku(Rows) :-
Line 8,971 ⟶ 9,867:
[5,_,_,_,_,_,_,7,3],
[_,_,2,_,1,_,_,_,_],
[_,_,_,_,4,_,_,_,9]]).</langsyntaxhighlight>
 
===GNU Prolog version===
{{works with|GNU Prolog|1.4.4}}
<langsyntaxhighlight Prologlang="prolog">:- initialization(main).
 
 
Line 9,028 ⟶ 9,924:
 
main :- test(T), solve(T), maplist(show,T), halt.
show(X) :- write(X), nl.</langsyntaxhighlight>
{{Out}}
<pre>[1,2,3,4,5,6,7,8,9]
Line 9,043 ⟶ 9,939:
=={{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 9,153 ⟶ 10,049:
Input()
CloseConsole()
EndIf</langsyntaxhighlight>
{{out}}
<pre>+-----+-----+-----+
Line 9,185 ⟶ 10,081:
=={{header|Python}}==
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.
 
===Backtrack===
 
A simple backtrack algorithm -- Quick but may take longer if the grid had been more than 9 x 9
<langsyntaxhighlight lang="python">
def initiate():
box.append([0, 1, 2, 9, 10, 11, 18, 19, 20])
Line 9,271 ⟶ 10,169:
print grid[i*9:i*9+9]
raw_input()
</syntaxhighlight>
</lang>
 
===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 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
>;
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 {
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}}==
Line 9,280 ⟶ 10,542:
A sudoku is represented as a matrix, see Rascal solutions to matrix related problems for examples.
 
<langsyntaxhighlight Rascallang="rascal">import Prelude;
import vis::Figure;
import vis::Render;
Line 9,363 ⟶ 10,625:
<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>
};</langsyntaxhighlight>
 
Example
Line 9,651 ⟶ 10,913:
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+}}
<langsyntaxhighlight lang="ruby">def read_matrix(data)
lines = data.lines
9.times.collect { |i| 9.times.collect { |j| lines[i][j].to_i } }
Line 9,746 ⟶ 11,008:
print_matrix(matrix)
puts
print_matrix(solve_sudoku(matrix))</langsyntaxhighlight>
 
{{out}}
Line 9,780 ⟶ 11,042:
=={{header|Rust}}==
{{trans|Ada}}
<syntaxhighlight lang="rust">type Sudoku = [u8; 81];
<lang rust>
type SudokuArType = [u8; 81];
 
fn is_valid(val: u8, x: usize, y: usize, sudoku_ar: &mut Sudoku) -> bool {
 
fn check_validity( val : u8,(0..9).all(|i| xsudoku_ar[y :* usize,9 y+ :i] usize,!= val && sudoku_ar[i :* &mut9 SudokuArType+ x] != val) ->&& bool{
let (start_x, start_y) = ((x / 3) * 3, (y / 3) * 3);
for i in 0..=8 {
if ( sudoku_ar[y * 9(start_y..start_y + 3).all(|i]| ==(start_x..start_x val+ 3) .all(|j| ( sudoku_ar[i * 9 + xj] =!= val ) {)
return false }
}
}
let startx : usize = ( x / 3 ) * 3;
let starty : usize = ( y / 3 ) * 3;
for i in starty..=(starty + 2) {
for j in startx..=(startx + 2) {
if sudoku_ar[i * 9 + j] == val {
return false
}
}
}
true
}
 
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);
fn place_number( pos: usize, sudoku_ar: &mut SudokuArType ) -> bool {
for n in 1..10 {
let mut ret : bool;
if posis_valid(n, x, ==y, 81sudoku_ar) {
sudoku_ar[pos] = n;
return true
if place_number(pos + 1, sudoku_ar) {
}
return true;
}
if sudoku_ar[pos] >= 0 {;
}
ret = place_number( pos + 1, sudoku_ar );
}
if ret == true {
false
return true
})
} else {
return false
}
}
for n in 1..=9 {
if check_validity(n, pos % 9, pos / 9, sudoku_ar) == true {
sudoku_ar[pos] = n;
ret = place_number( pos + 1, sudoku_ar );
if ret == true{
return true;
}
sudoku_ar[pos] = 0;
}
}
false
}
 
fn pretty_print(sudoku_ar: Sudoku) {
 
let line_sep = "------+-------+------";
 
println!("{}", line_sep);
fn pretty_print( sudoku_ar : SudokuArType ) {
for (i, e) in sudoku_ar.iter().enumerate() {
let line_sep = "------+------+------";
println print!("{} ",line_sep e);
if (i + 1) % 3 == 0 && (i + 1) % 9 != 0 {
for i in 0..sudoku_ar.len() {
print!("{}| ", sudoku_ar[i] );
}
if (i + 1) % 3 == 0 && !( (i + 1) % 9 == 0 ) {
print! if ("|i "+ 1); % 9 == 0 {
}
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 solve( sudoku_ar : &mut SudokuArType) -> bool {
place_number( 0, sudoku_ar )
}
 
 
fn main() {
let mut sudoku_ar: SudokuArTypeSudoku = [
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) {
if solve( &mut pretty_print(sudoku_ar ) == false {;
} else {
println!("Unsolvable");
println!("Unsolvable");
} else {
}
pretty_print( sudoku_ar );
}</syntaxhighlight>
}
}</lang>
 
{{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>
 
Line 9,899 ⟶ 11,127:
Use CLP solver in SAS/OR:
 
<langsyntaxhighlight lang="sas">/* define SAS data set */
data Indata;
input C1-C9;
Line 9,945 ⟶ 11,173:
/* print solution */
print X;
quit;</langsyntaxhighlight>
 
Output:
Line 9,966 ⟶ 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 10,097 ⟶ 11,325:
println(solution match {case Nil => "no solution!!!" case _ => f2Str(solution)})
}</langsyntaxhighlight>
{{out}}
<pre>riddle:
Line 10,131 ⟶ 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 10,248 ⟶ 11,476:
+("\n"*2))
}
}</langsyntaxhighlight>
{{out}}
<pre>riddle used in Ada section:
Line 10,379 ⟶ 11,607:
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;...
Line 10,551 ⟶ 11,779:
disp('Invalid solution found.');
disp_board(Solved_board);
end</langsyntaxhighlight>
 
{{out}}
Line 10,610 ⟶ 11,838:
 
=={{header|Sidef}}==
{{trans|Perl 6Raku}}
<langsyntaxhighlight lang="ruby">func check(i, j) is cached {
var (id, im) = i.divmod(9)
var (jd, jm) = j.divmod(9)
Line 10,659 ⟶ 11,887:
)
 
solve(grid)</langsyntaxhighlight>
{{out}}
<pre>5 3 9 8 2 4 7 6 1
Line 10,672 ⟶ 11,900:
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}}==
Line 10,682 ⟶ 12,473:
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'''.
 
<langsyntaxhighlight 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)
Line 10,710 ⟶ 12,501:
from r
where pos = 0
;</langsyntaxhighlight>
 
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.
Line 10,734 ⟶ 12,525:
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.
 
<langsyntaxhighlight lang="stata">mata
function sudoku(a) {
s = J(81,20,.)
Line 10,834 ⟶ 12,625:
sudoku(a)
a
end</langsyntaxhighlight>
 
'''Output'''
Line 10,855 ⟶ 12,646:
Two more examples, from [http://www.7sudoku.com/very-difficult here] and [http://www.extremesudoku.info/sudoku.html there].
 
<langsyntaxhighlight lang="stata">a = 7,9,.,.,.,3,.,.,2\
.,6,.,5,1,.,.,.,.\
.,.,.,.,.,2,.,.,6\
Line 10,907 ⟶ 12,698:
8 | 3 8 5 4 7 9 2 1 6 |
9 | 7 6 9 3 2 1 4 5 8 |
+-------------------------------------+</langsyntaxhighlight>
 
=={{header|Swift}}==
{{trans|Java}}
<langsyntaxhighlight Swiftlang="swift">import Foundation
 
typealias SodukuPuzzle = [[Int]]
Line 11,034 ⟶ 12,825:
let puzzle = Soduku(board: board)
puzzle.solve()
puzzle.printBoard()</langsyntaxhighlight>
{{out}}
<pre>
Line 11,054 ⟶ 12,845:
{{works with|Swift 3}}
 
<syntaxhighlight lang="swift">
<lang Swift>
func solving(board: [[Int]]) -> [[Int]] {
var board = board
Line 11,119 ⟶ 12,910:
 
print(solving(board: puzzle))
</syntaxhighlight>
</lang>
{{out}}
<pre>
Line 11,138 ⟶ 12,929:
 
 
<langsyntaxhighlight lang="systemverilog">
 
//////////////////////////////////////////////////////////////////////////////
Line 11,268 ⟶ 13,059:
end
endprogram
</syntaxhighlight>
</lang>
 
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.
Line 11,321 ⟶ 13,112:
-------------
</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 11,327 ⟶ 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 11,575 ⟶ 13,516:
return 0
}
}</langsyntaxhighlight>
Demonstration code:
<langsyntaxhighlight lang="tcl">SudokuSolver create sudoku
sudoku load {
{3 9 4 @ @ 2 6 7 @}
Line 11,600 ⟶ 13,541:
}
}
sudoku destroy</langsyntaxhighlight>
{{out}}
<pre>+-----+-----+-----+
Line 11,616 ⟶ 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 11,669 ⟶ 13,610:
Finished solving!</pre>
 
=={{header|Uiua}}==
{{Works with |Uiua|0.12.0-dev.1}}
Uses experimental '''⮌ orient''' and '''astar''' (only as a lazy way of managing the iteration :-).
<syntaxhighlight lang="uiua">
# Solves Sudoku using brute force.
# Experimental!
S ← [[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]]
Ps ← ⊞⊟.⇡9
Boxes ← ↯∞_9_2 ⊡⊞⊂.0_3_6 ◫3_3Ps
Nines ← ⊂Boxes⊂⟜(⮌1_0)Ps # 27 lists of pos's: one per row, col, box.
IsIn ← ☇1▽:⟜≡(∊:)Nines ¤ # (pos) -> pos's of all peers for a pos.
Peers ← ⊞(IsIn ⊟).⇡9 # For each pos, the pos of every peer (by row, col, box)
 
Free ← ▽:⟜(¬∊)+1⇡9◴▽⊸(>0)⊡⊡:Peers # Free values at pos (pos board) -> [n]
Next ← (
=/↧.≡(⧻Free) ⊙¤,,⊚=0. # Find most constrained pos.
Free,,⊙◌⊢▽⊙. # Get free values at pos.
≡(⍜⊡⋅∘)λBCa # Generate node for each.
)
End ← =0/+/+=0
astar(⍣Next⋅[]|0|End)S
↙¯1°□⊢⊙◌
</syntaxhighlight>
{{out}}
<pre>
╭─
╷ 8 5 1 3 9 2 4 6 7
╷ 7 2 3 4 6 1 5 8 9
6 9 4 7 5 8 2 3 1
9 6 8 1 4 7 3 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>
=={{header|Ursala}}==
<langsyntaxhighlight Ursalalang="ursala">#import std
#import nat
 
Line 11,682 ⟶ 13,668:
~&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 11,699 ⟶ 13,685:
010067008
009008000
026400735]-</langsyntaxhighlight>
{{out}}
<pre>
Line 11,715 ⟶ 13,701:
</pre>
 
=={{Headerheader|VBA}}==
{{trans|Fortran}}
<langsyntaxhighlight VBlang="vb">Dim grid(9, 9)
Dim gridSolved(9, 9)
 
Line 11,818 ⟶ 13,804:
Debug.Print
Next i
End Sub</langsyntaxhighlight>
{{out}}
<pre>
Line 11,837 ⟶ 13,823:
{{trans|VBA}}
To run in console mode with cscript.
<langsyntaxhighlight lang="vb">Dim grid(9, 9)
Dim gridSolved(9, 9)
Line 11,938 ⟶ 13,924:
End Sub 'Sudoku
 
Call sudoku</langsyntaxhighlight>
{{out}}
<pre>Problem:
Line 11,960 ⟶ 13,946:
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}}==
Line 11,965 ⟶ 14,221:
can be verified by several other examples.
{{trans|C}}
<langsyntaxhighlight XPL0lang="xpl0">code ChOut=8, CrLf=9, IntOut=11, Text=12;
 
proc Show(X);
Line 12,035 ⟶ 14,291:
..9 ..8 ...
.26 4.. 735 ");
]</langsyntaxhighlight>
 
{{out}}
Line 12,054 ⟶ 14,310:
=={{header|zkl}}==
{{trans|C}} Note: Unlike in the C solution, 1<<-1 is defined (as 0).
<langsyntaxhighlight lang="zkl">fcn trycell(sdku,pos=0){
row,col:=pos/9, pos%9;
Line 12,075 ⟶ 14,331:
sdku[pos]=0;
return(False);
}</langsyntaxhighlight>
<langsyntaxhighlight lang="zkl">problem:=
#<<<
" 5 3 0 0 7 0 0 0 0
Line 12,094 ⟶ 14,350:
s[n*27,27].pump(Console.println,T(Void.Read,8),("| " + "%s%s%s | "*3).fmt); // 3 lines
println("+-----+-----+-----+");
}</langsyntaxhighlight>
{{out}}
<pre>
171

edits