Sudoku: Difference between revisions
Content deleted Content added
Added Uiua solution |
|||
(57 intermediate revisions by 14 users not shown) | |||
Line 12: | Line 12: | ||
{{trans|Kotlin}} |
{{trans|Kotlin}} |
||
< |
<syntaxhighlight lang="11l">T Sudoku |
||
solved = 0B |
solved = 0B |
||
grid = [0] * 81 |
grid = [0] * 81 |
||
Line 83: | Line 83: | ||
‘000036040’] |
‘000036040’] |
||
Sudoku(rows).solve()</ |
Sudoku(rows).solve()</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
Line 118: | Line 118: | ||
=={{header|8th}}== |
=={{header|8th}}== |
||
< |
<syntaxhighlight lang="8th"> |
||
\ |
\ |
||
\ Simple iterative backtracking Sudoku solver for 8th |
\ Simple iterative backtracking Sudoku solver for 8th |
||
Line 265: | Line 265: | ||
"No solution!\n" . |
"No solution!\n" . |
||
then ; |
then ; |
||
</syntaxhighlight> |
|||
</lang> |
|||
=={{header|Ada}}== |
=={{header|Ada}}== |
||
{{trans|C++}} |
{{trans|C++}} |
||
< |
<syntaxhighlight lang="ada"> |
||
with Ada.Text_IO; |
with Ada.Text_IO; |
||
Line 378: | Line 378: | ||
solve( sudoku_ar ); |
solve( sudoku_ar ); |
||
end Sudoku; |
end Sudoku; |
||
</syntaxhighlight> |
|||
</lang> |
|||
{{out}} |
{{out}} |
||
Line 401: | Line 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].}} |
{{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''.}} |
{{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''.}} |
||
< |
<syntaxhighlight lang="algol68">MODE AVAIL = [9]BOOL; |
||
MODE BOX = [3, 3]CHAR; |
MODE BOX = [3, 3]CHAR; |
||
Line 495: | Line 495: | ||
"__1__6__9")) |
"__1__6__9")) |
||
END CO |
END CO |
||
)</ |
)</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre> |
<pre> |
||
Line 515: | Line 515: | ||
=={{header|AutoHotkey}}== |
=={{header|AutoHotkey}}== |
||
< |
<syntaxhighlight lang="autohotkey">#SingleInstance, Force |
||
SetBatchLines, -1 |
SetBatchLines, -1 |
||
SetTitleMatchMode, 3 |
SetTitleMatchMode, 3 |
||
Line 658: | Line 658: | ||
r .= SubStr(p, A_Index, 1) . "|" |
r .= SubStr(p, A_Index, 1) . "|" |
||
return r |
return r |
||
}</ |
}</syntaxhighlight> |
||
=={{header|AWK}}== |
=={{header|AWK}}== |
||
<syntaxhighlight lang="awk"> |
|||
<lang AWK> |
|||
# syntax: GAWK -f SUDOKU_RC.AWK |
# syntax: GAWK -f SUDOKU_RC.AWK |
||
BEGIN { |
BEGIN { |
||
Line 849: | Line 849: | ||
} |
} |
||
function error(message) { printf("error: %s\n",message) ; errors++ } |
function error(message) { printf("error: %s\n",message) ; errors++ } |
||
</syntaxhighlight> |
|||
</lang> |
|||
{{out}} |
{{out}} |
||
<pre> |
<pre> |
||
Line 886: | Line 886: | ||
{{works with|BBC BASIC for Windows}} |
{{works with|BBC BASIC for Windows}} |
||
[[Image:sudoku_bbc.gif|right]] |
[[Image:sudoku_bbc.gif|right]] |
||
< |
<syntaxhighlight lang="bbcbasic"> VDU 23,22,453;453;8,20,16,128 |
||
*FONT Arial,28 |
*FONT Arial,28 |
||
Line 990: | Line 990: | ||
ENDIF |
ENDIF |
||
NEXT |
NEXT |
||
= D%</ |
= D%</syntaxhighlight> |
||
=={{header|BCPL}}== |
=={{header|BCPL}}== |
||
< |
<syntaxhighlight lang="bcpl">// This can be run using Cintcode BCPL freely available from www.cl.cam.ac.uk/users/mr10. |
||
// Implemented by Martin Richards. |
// Implemented by Martin Richards. |
||
Line 1,388: | Line 1,388: | ||
{ count := count + 1 |
{ count := count + 1 |
||
prboard() |
prboard() |
||
}</ |
}</syntaxhighlight> |
||
=={{header|Befunge}}== |
=={{header|Befunge}}== |
||
Line 1,394: | Line 1,394: | ||
Input should be provided as a sequence of 81 digits (optionally separated by whitespace), with zero representing an unknown value. |
Input should be provided as a sequence of 81 digits (optionally separated by whitespace), with zero representing an unknown value. |
||
< |
<syntaxhighlight lang="befunge">99*>1-:0>:#$"0"\# #~`#$_"0"-\::9%:9+00p3/\9/:99++10p3vv%2g\g01< |
||
2%v|:p+9/9\%9:\p\g02\1p\g01\1:p\g00\1:+8:\p02+*93+*3/<>\20g\g#: |
2%v|:p+9/9\%9:\p\g02\1p\g01\1:p\g00\1:+8:\p02+*93+*3/<>\20g\g#: |
||
v<+>:0\`>v >\::9%:9+00p3/\9/:99++10p3/3*+39*+20p\:8+::00g\g2%\^ |
v<+>:0\`>v >\::9%:9+00p3/\9/:99++10p3/3*+39*+20p\:8+::00g\g2%\^ |
||
Line 1,401: | Line 1,401: | ||
p|<$0.0^!g+:#9/9<^@ ^,>#+5<5_>#!<>#$0"------+-------+-----":#<^ |
p|<$0.0^!g+:#9/9<^@ ^,>#+5<5_>#!<>#$0"------+-------+-----":#<^ |
||
<>v$v1:::0<>"P"`!^>0g#0v#p+9/9\%9:p04:\pg03g021pg03g011pg03g001 |
<>v$v1:::0<>"P"`!^>0g#0v#p+9/9\%9:p04:\pg03g021pg03g011pg03g001 |
||
::>^_:#<0#!:p#-\#1:#g0<>30g010g30g020g30g040g:9%\:9/9+\01-\1+0:</ |
::>^_:#<0#!:p#-\#1:#g0<>30g010g30g020g30g040g:9%\:9/9+\01-\1+0:</syntaxhighlight> |
||
{{in}} |
{{in}} |
||
Line 1,431: | Line 1,431: | ||
=={{header|Bracmat}}== |
=={{header|Bracmat}}== |
||
The program: |
The program: |
||
< |
<syntaxhighlight lang="bracmat">{sudokuSolver.bra |
||
Solves any 9x9 sudoku, using backtracking. |
Solves any 9x9 sudoku, using backtracking. |
||
Line 1,619: | Line 1,619: | ||
. new$((its.sudoku),!arg):?puzzle |
. new$((its.sudoku),!arg):?puzzle |
||
& (puzzle..Display)$ |
& (puzzle..Display)$ |
||
);</ |
);</syntaxhighlight> |
||
Solve a sudoku that is hard for a brute force solver: |
Solve a sudoku that is hard for a brute force solver: |
||
< |
<syntaxhighlight lang="bracmat">new'( sudokuSolver |
||
, (.- - - - - - - - -) |
, (.- - - - - - - - -) |
||
(.- - - - - 3 - 8 5) |
(.- - - - - 3 - 8 5) |
||
Line 1,631: | Line 1,631: | ||
(.- - 2 - 1 - - - -) |
(.- - 2 - 1 - - - -) |
||
(.- - - - 4 - - - 9) |
(.- - - - 4 - - - 9) |
||
);</ |
);</syntaxhighlight> |
||
Solution: |
Solution: |
||
<pre>|~~~|~~~|~~~| |
<pre>|~~~|~~~|~~~| |
||
Line 1,651: | Line 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. |
The following code is really only good for size 3 puzzles. A longer, even less readable version [[Sudoku/C|here]] could handle size 4s. |
||
< |
<syntaxhighlight lang="c">#include <stdio.h> |
||
void show(int *x) |
void show(int *x) |
||
Line 1,717: | Line 1,717: | ||
return 0; |
return 0; |
||
}</ |
}</syntaxhighlight> |
||
=={{header|C sharp|C#}}== |
=={{header|C sharp|C#}}== |
||
===Backtracking=== |
|||
===Simple Backtrack Solution=== |
|||
{{trans|Java}} |
{{trans|Java}} |
||
< |
<syntaxhighlight lang="csharp">using System; |
||
class SudokuSolver |
class SudokuSolver |
||
Line 1,824: | Line 1,824: | ||
Console.Read(); |
Console.Read(); |
||
} |
} |
||
}</ |
}</syntaxhighlight> |
||
=== |
=== Best First Search=== |
||
<!-- By Martin Freedman, 20/11/2021 --> |
<!-- By Martin Freedman, 20/11/2021 --> |
||
< |
<syntaxhighlight lang="csharp">using System.Linq; |
||
using static System.Linq.Enumerable; |
using static System.Linq.Enumerable; |
||
using System.Collections.Generic; |
using System.Collections.Generic; |
||
Line 1,834: | Line 1,834: | ||
using System.Runtime.CompilerServices; |
using System.Runtime.CompilerServices; |
||
namespace |
namespace SodukoFastMemoBFS { |
||
internal |
internal readonly record struct Square (int Row, int Col); |
||
internal record Constraints (IEnumerable<int> ConstrainedRange, Square Square); |
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
internal class Cache : Dictionary<Square, Constraints> { }; |
|||
private static int RowCol(int rc) => rc <= 2 ? 0 : rc <= 5 ? 3 : 6; |
|||
internal record CacheGrid (int[][] Grid, Cache Cache); |
|||
private static IEnumerable<int> GetBox(this int[][] grid, int row, int col) => |
|||
from r in Range(RowCol(row), 3) |
|||
from c in Range(RowCol(col), 3) |
|||
select grid[r][c]; |
|||
internal static class SudokuFastMemoBFS { |
|||
private static readonly int[] range = Range(1, 9).ToArray(); |
|||
internal static U Fwd<T, U>(this T data, Func<T, U> f) => f(data); |
|||
if (idx == 81) |
|||
return true; |
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
var (r, c) = cells[idx]; |
|||
private static int RowCol(int rc) => rc <= 2 ? 0 : rc <= 5 ? 3 : 6; |
|||
foreach (var i in range.Except(grid.Hints(r,c))) { |
|||
grid[r][c] = i; |
|||
private static bool Solve(this CacheGrid cg, Constraints constraints, int finished) { |
|||
if (grid.Solve(cells, idx + 1)) |
|||
var (row, col) = constraints.Square; |
|||
foreach (var i in constraints.ConstrainedRange) { |
|||
cg.Grid[row][col] = i; |
|||
if (cg.Cache.Count == finished || cg.Solve(cg.Next(constraints.Square), finished)) |
|||
return true; |
|||
} |
} |
||
cg.Grid[row][col] = 0; |
|||
return false; |
return false; |
||
} |
} |
||
private static readonly int[] Unmarked = new[] { 0 }; |
|||
private static readonly int[] domain = Range(0, 9).ToArray(); |
private static readonly int[] domain = Range(0, 9).ToArray(); |
||
private static readonly int[] range = Range(1, 9).ToArray(); |
|||
private static |
private static bool Valid(this int[][] grid, int row, int col, int val) { |
||
for (var i = 0; i < 9; i++) |
|||
if (grid[row][i] == val || grid[i][col] == val) |
|||
return false; |
|||
for (var r = RowCol(row); r < RowCol(row) + 3; r++) |
|||
for (var c = RowCol(col); c < RowCol(col) + 3; c++) |
|||
if (grid[r][c] == val) |
|||
return false; |
|||
return true; |
|||
} |
|||
private static IEnumerable< |
private static IEnumerable<int> Constraints(this int[][] grid, int row, int col) => |
||
range.Where(val => grid.Valid(row, col, val)); |
|||
private static Constraints Next(this CacheGrid cg, Square square) => |
|||
cg.Cache.ContainsKey(square) |
|||
? cg.Cache[square] |
|||
: cg.Cache[square]=cg.Grid.SortedCells(); |
|||
private static Constraints SortedCells(this int[][] grid) => |
|||
(from row in domain |
|||
from col in domain |
from col in domain |
||
where grid[row][col] == 0 |
|||
let cell = new Constraints(grid.Constraints(row, col), new Square(row, col)) |
|||
orderby cell.count descending |
|||
orderby cell.ConstrainedRange.Count() ascending |
|||
select cell).First(); |
|||
private static |
private static CacheGrid Parse(string input) => |
||
input |
input |
||
.Select((c, i) => (index: i, val: int.Parse(c.ToString()))) |
.Select((c, i) => (index: i, val: int.Parse(c.ToString()))) |
||
.GroupBy(id => id.index / 9) |
.GroupBy(id => id.index / 9) |
||
.Select(grp => grp.Select(id => id.val).ToArray()) |
.Select(grp => grp.Select(id => id.val).ToArray()) |
||
.ToArray() |
.ToArray() |
||
.Fwd(grid => new CacheGrid(grid, new Cache())); |
|||
public static string AsString(this int[][] grid) => |
public static string AsString(this int[][] grid) => |
||
string.Join('\n', grid.Select(row => string.Concat(row))); |
string.Join('\n', grid.Select(row => string.Concat(row))); |
||
public static int[][] Run(string input) { |
public static int[][] Run(string input) { |
||
var |
var cg = Parse(input); |
||
var |
var marked = cg.Grid.SelectMany(row => row.Where(c => c > 0)).Count(); |
||
return cg.Solve(cg.Grid.SortedCells(), 80 - marked) ? cg.Grid : new int[][] { Array.Empty<int>() }; |
|||
return grid.Solve(sorted, hits) ? grid : new int[][] { Array.Empty<int>() }; |
|||
} |
} |
||
} |
} |
||
}</ |
}</syntaxhighlight> |
||
Usage |
Usage |
||
<syntaxhighlight lang="csharp">using System.Linq; |
|||
<lang csharp> |
|||
using static System.Linq.Enumerable; |
|||
using static System.Console; |
using static System.Console; |
||
using System.IO; |
|||
namespace Sudoku { |
|||
static class Program { |
|||
namespace SodukoFastMemoBFS { |
|||
static void Main(string[] args) { |
|||
static class Program { |
|||
//https://staffhome.ecm.uwa.edu.au/~00013890/sudoku17 format |
|||
var puzzle = "000028000800010000000000700000600403200004000100700000030400500000000010060000000"; |
|||
static void Main(string[] args) { |
|||
WriteLine(Sudoku.Run(puzzle).AsString()); |
|||
var num = int.Parse(args[0]); |
|||
var puzzles = File.ReadLines(@"sudoku17.txt").Take(num); |
|||
} |
|||
var single = puzzles.First(); |
|||
} |
|||
}</lang> |
|||
var watch = new System.Diagnostics.Stopwatch(); |
|||
watch.Start(); |
|||
WriteLine(SudokuFastMemoBFS.Run(single).AsString()); |
|||
watch.Stop(); |
|||
WriteLine($"{single}: {watch.ElapsedMilliseconds} ms"); |
|||
WriteLine($"Doing {num} puzzles"); |
|||
var total = 0.0; |
|||
watch.Start(); |
|||
foreach (var puzzle in puzzles) { |
|||
watch.Reset(); |
|||
watch.Start(); |
|||
SudokuFastMemoBFS.Run(puzzle); |
|||
watch.Stop(); |
|||
total += watch.ElapsedMilliseconds; |
|||
Write("."); |
|||
} |
|||
watch.Stop(); |
|||
WriteLine($"\nPuzzles:{num}, Total:{total} ms, Average:{total / num:0.00} ms"); |
|||
ReadKey(); |
|||
} |
|||
} |
|||
}</syntaxhighlight> |
|||
Output |
Output |
||
<pre> |
<pre>693784512 |
||
487512936 |
|||
617328945 |
|||
125963874 |
|||
894517236 |
|||
932651487 |
|||
325946781 |
|||
568247391 |
|||
978651423 |
|||
741398625 |
|||
256834179 |
|||
319475268 |
|||
143792658 |
|||
856129743 |
|||
731489562 |
|||
274836159 |
|||
489265317 |
|||
000000010400000000020000000000050407008000300001090000300400200050100000000806000: 336 ms |
|||
562173894 |
|||
Doing 100 puzzles |
|||
</pre> |
|||
.................................................................................................... |
|||
Puzzles:100, Total:5316 ms, Average:53.16 ms</pre> |
|||
===Solver=== |
|||
===“Automatic” Solution=== |
|||
{{libheader|Microsoft Solver Foundation}} |
{{libheader|Microsoft Solver Foundation}} |
||
<!-- By Nigel Galloway, Jan 29, 2012 --> |
<!-- By Nigel Galloway, Jan 29, 2012 --> |
||
< |
<syntaxhighlight lang="csharp">using Microsoft.SolverFoundation.Solvers; |
||
namespace Sudoku |
namespace Sudoku |
||
Line 1,994: | Line 2,032: | ||
} |
} |
||
} |
} |
||
}</ |
}</syntaxhighlight> |
||
Produces: |
Produces: |
||
<pre> |
<pre> |
||
Line 2,010: | Line 2,048: | ||
</pre> |
</pre> |
||
=== |
==="Dancing Links"/Algorithm X=== |
||
< |
<syntaxhighlight lang="csharp">using System; |
||
using System.Collections.Generic; |
using System.Collections.Generic; |
||
using System.Text; |
using System.Text; |
||
Line 2,289: | Line 2,327: | ||
public static string DelimitWith<T>(this IEnumerable<T> source, string separator) => string.Join(separator, source); |
public static string DelimitWith<T>(this IEnumerable<T> source, string separator) => string.Join(separator, source); |
||
}</ |
}</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre> |
<pre> |
||
Line 2,314: | Line 2,352: | ||
=={{header|C++}}== |
=={{header|C++}}== |
||
{{trans|Java}} |
{{trans|Java}} |
||
< |
<syntaxhighlight lang="cpp">#include <iostream> |
||
using namespace std; |
using namespace std; |
||
Line 2,405: | Line 2,443: | ||
ss.solve(); |
ss.solve(); |
||
return EXIT_SUCCESS; |
return EXIT_SUCCESS; |
||
}</ |
}</syntaxhighlight> |
||
=={{header|Clojure}}== |
=={{header|Clojure}}== |
||
< |
<syntaxhighlight lang="clojure">(ns rosettacode.sudoku |
||
(:use [clojure.pprint :only (cl-format)])) |
(:use [clojure.pprint :only (cl-format)])) |
||
Line 2,431: | Line 2,469: | ||
(if (= x (dec c)) |
(if (= x (dec c)) |
||
(recur ng 0 (inc y)) |
(recur ng 0 (inc y)) |
||
(recur ng (inc x) y)))))))</ |
(recur ng (inc x) y)))))))</syntaxhighlight> |
||
< |
<syntaxhighlight lang="clojure">sudoku>(cl-format true "~{~{~a~^ ~}~%~}" |
||
(solve [[3 9 4 0 0 2 6 7 0] |
(solve [[3 9 4 0 0 2 6 7 0] |
||
[0 0 0 3 0 0 4 0 0] |
[0 0 0 3 0 0 4 0 0] |
||
Line 2,453: | Line 2,491: | ||
8 2 6 4 1 9 7 3 5 |
8 2 6 4 1 9 7 3 5 |
||
nil</ |
nil</syntaxhighlight> |
||
=={{header|Common Lisp}}== |
=={{header|Common Lisp}}== |
||
A simple solver without optimizations (except for pre-computing the possible entries of a cell). |
A simple solver without optimizations (except for pre-computing the possible entries of a cell). |
||
< |
<syntaxhighlight lang="lisp">(defun row-neighbors (row column grid &aux (neighbors '())) |
||
(dotimes (i 9 neighbors) |
(dotimes (i 9 neighbors) |
||
(let ((x (aref grid row i))) |
(let ((x (aref grid row i))) |
||
Line 2,496: | Line 2,534: | ||
(setf (aref grid row column) choice) |
(setf (aref grid row column) choice) |
||
(when (eq grid (solve grid row (1+ column))) |
(when (eq grid (solve grid row (1+ column))) |
||
(return grid))))))</ |
(return grid))))))</syntaxhighlight> |
||
Example: |
Example: |
||
<pre>> (defparameter *puzzle* |
<pre>> (defparameter *puzzle* |
||
Line 2,523: | Line 2,561: | ||
(7 5 9 2 3 8 1 4 6) |
(7 5 9 2 3 8 1 4 6) |
||
(8 2 6 4 1 9 7 3 5))</pre> |
(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}}== |
=={{header|Curry}}== |
||
Copied from [http://www.informatik.uni-kiel.de/~curry/examples/ Curry: Example Programs]. |
Copied from [http://www.informatik.uni-kiel.de/~curry/examples/ Curry: Example Programs]. |
||
< |
<syntaxhighlight lang="curry">----------------------------------------------------------------------------- |
||
--- Solving Su Doku puzzles in Curry with FD constraints |
--- Solving Su Doku puzzles in Curry with FD constraints |
||
--- |
--- |
||
Line 2,588: | Line 2,728: | ||
" 5 7 921 ", |
" 5 7 921 ", |
||
" 64 9 ", |
" 64 9 ", |
||
" 2 438"]</ |
" 2 438"]</syntaxhighlight> |
||
Line 2,594: | Line 2,734: | ||
{{Works with|PAKCS}} |
{{Works with|PAKCS}} |
||
Minimal w/o read or show utilities. |
Minimal w/o read or show utilities. |
||
< |
<syntaxhighlight lang="curry">import CLPFD |
||
import Constraint (allC) |
import Constraint (allC) |
||
import List (transpose) |
import List (transpose) |
||
Line 2,627: | Line 2,767: | ||
, [7,_,_,6,_,_,5,_,_] |
, [7,_,_,6,_,_,5,_,_] |
||
] |
] |
||
main | sudoku xs = xs where xs = test</ |
main | sudoku xs = xs where xs = test</syntaxhighlight> |
||
{{Out}} |
{{Out}} |
||
<pre>Execution time: 0 msec. / elapsed: 10 msec. |
<pre>Execution time: 0 msec. / elapsed: 10 msec. |
||
Line 2,635: | Line 2,775: | ||
{{trans|C++}} |
{{trans|C++}} |
||
A little over-engineered solution, that shows some strong static typing useful in larger programs. |
A little over-engineered solution, that shows some strong static typing useful in larger programs. |
||
< |
<syntaxhighlight lang="d">import std.stdio, std.range, std.string, std.algorithm, std.array, |
||
std.ascii, std.typecons; |
std.ascii, std.typecons; |
||
Line 2,761: | Line 2,901: | ||
else |
else |
||
solution.get.representSudoku.writeln; |
solution.get.representSudoku.writeln; |
||
}</ |
}</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre>8 5 . | . . 2 | 4 . . |
<pre>8 5 . | . . 2 | 4 . . |
||
Line 2,789: | Line 2,929: | ||
===Short Version=== |
===Short Version=== |
||
Adapted from: http://code.activestate.com/recipes/576725-brute-force-sudoku-solver/ |
Adapted from: http://code.activestate.com/recipes/576725-brute-force-sudoku-solver/ |
||
< |
<syntaxhighlight lang="d">import std.stdio, std.algorithm, std.range; |
||
const(int)[] solve(immutable int[] s) pure nothrow @safe { |
const(int)[] solve(immutable int[] s) pure nothrow @safe { |
||
Line 2,822: | Line 2,962: | ||
0, 0, 0, 0, 3, 6, 0, 4, 0]; |
0, 0, 0, 0, 3, 6, 0, 4, 0]; |
||
writefln("%(%s\n%)", problem.solve.chunks(9)); |
writefln("%(%s\n%)", problem.solve.chunks(9)); |
||
}</ |
}</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre>[8, 5, 9, 6, 1, 2, 4, 3, 7] |
<pre>[8, 5, 9, 6, 1, 2, 4, 3, 7] |
||
Line 2,836: | Line 2,976: | ||
===No-Heap Version=== |
===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. |
This version is similar to the precedent one, but it shows idioms to avoid memory allocations on the heap. This is enforced by the use of the @nogc attribute. |
||
< |
<syntaxhighlight lang="d">import std.stdio, std.algorithm, std.range, std.typecons; |
||
Nullable!(const ubyte[81]) solve(in ubyte[81] s) pure nothrow @safe @nogc { |
Nullable!(const ubyte[81]) solve(in ubyte[81] s) pure nothrow @safe @nogc { |
||
Line 2,877: | Line 3,017: | ||
0, 0, 0, 0, 3, 6, 0, 4, 0]; |
0, 0, 0, 0, 3, 6, 0, 4, 0]; |
||
writefln("%(%s\n%)", problem.solve.get[].chunks(9)); |
writefln("%(%s\n%)", problem.solve.get[].chunks(9)); |
||
}</ |
}</syntaxhighlight> |
||
Same output. |
Same output. |
||
=={{header|Delphi}}== |
=={{header|Delphi}}== |
||
Example taken from C++ |
Example taken from C++ |
||
< |
<syntaxhighlight lang="delphi">type |
||
TIntArray = array of Integer; |
TIntArray = array of Integer; |
||
Line 3,006: | Line 3,146: | ||
ShowMessage('Solved!'); |
ShowMessage('Solved!'); |
||
end; |
end; |
||
end;</ |
end;</syntaxhighlight> |
||
Usage: |
Usage: |
||
< |
<syntaxhighlight lang="delphi">var |
||
SudokuSolver: TSudokuSolver; |
SudokuSolver: TSudokuSolver; |
||
begin |
begin |
||
Line 3,025: | Line 3,165: | ||
FreeAndNil(SudokuSolver); |
FreeAndNil(SudokuSolver); |
||
end; |
end; |
||
end;</ |
end;</syntaxhighlight> |
||
=={{header|EasyLang}}== |
=={{header|EasyLang}}== |
||
<syntaxhighlight lang="text"> |
|||
<lang>len row[] 810 |
|||
len |
len row[] 90 |
||
len |
len col[] 90 |
||
len box[] 90 |
|||
len grid[] 82 |
len grid[] 82 |
||
# |
# |
||
proc init . . |
|||
for pos |
for pos = 1 to 81 |
||
if pos mod 9 = |
if pos mod 9 = 1 |
||
s$ |
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 |
for i = 1 to 81 |
||
write grid[i] & " " |
write grid[i] & " " |
||
if i mod 3 = |
if i mod 3 = 0 |
||
write " " |
write " " |
||
. |
. |
||
if i mod 9 = |
if i mod 9 = 0 |
||
print "" |
print "" |
||
. |
. |
||
if i mod 27 = |
if i mod 27 = 0 |
||
print "" |
print "" |
||
. |
. |
||
. |
. |
||
. |
. |
||
# |
# |
||
proc solve pos . . |
|||
while grid[pos] <> 0 |
while grid[pos] <> 0 |
||
pos += 1 |
pos += 1 |
||
. |
. |
||
if pos |
if pos > 81 |
||
# solved |
# solved |
||
display |
|||
return |
|||
. |
. |
||
r = pos div 9 |
r = (pos - 1) div 9 |
||
c = pos mod 9 |
c = (pos - 1) mod 9 |
||
b = r div 3 * 3 + c div 3 |
b = r div 3 * 3 + c div 3 |
||
r *= 10 |
r *= 10 |
||
c *= 10 |
c *= 10 |
||
b *= 10 |
b *= 10 |
||
for d = 1 to 9 |
for d = 1 to 9 |
||
if row[r + d] = 0 and col[c + d] = 0 and box[b + d] = 0 |
if row[r + d] = 0 and col[c + d] = 0 and box[b + d] = 0 |
||
grid[pos] = d |
grid[pos] = d |
||
row[r + d] = 1 |
row[r + d] = 1 |
||
col[c + d] = 1 |
col[c + d] = 1 |
||
box[b + d] = 1 |
box[b + d] = 1 |
||
solve pos + 1 |
|||
row[r + d] = 0 |
row[r + d] = 0 |
||
col[c + d] = 0 |
col[c + d] = 0 |
||
box[b + d] = 0 |
box[b + d] = 0 |
||
. |
. |
||
. |
. |
||
grid[pos] = 0 |
grid[pos] = 0 |
||
. |
. |
||
solve 1 |
|||
# |
# |
||
input_data |
input_data |
||
5 3 0 0 2 4 7 0 0 |
5 3 0 0 2 4 7 0 0 |
||
0 0 2 0 0 0 8 0 0 |
0 0 2 0 0 0 8 0 0 |
||
1 0 0 7 0 3 9 0 2 |
1 0 0 7 0 3 9 0 2 |
||
0 0 8 0 7 2 0 4 9 |
|||
0 |
0 0 8 0 7 2 0 4 9 |
||
0 2 0 9 8 0 0 7 0 |
|||
0 0 0 0 |
7 9 0 0 0 0 0 8 0 |
||
9 6 0 0 1 0 3 0 0 |
|||
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}}== |
=={{header|Elixir}}== |
||
{{trans|Erlang}} |
{{trans|Erlang}} |
||
< |
<syntaxhighlight lang="elixir">defmodule Sudoku do |
||
def display( grid ), do: ( for y <- 1..9, do: display_row(y, grid) ) |
def display( grid ), do: ( for y <- 1..9, do: display_row(y, grid) ) |
||
Line 3,265: | Line 3,421: | ||
{{3, 8}, 2}, {{5, 8}, 1}, |
{{3, 8}, 2}, {{5, 8}, 1}, |
||
{{5, 9}, 4}, {{9, 9}, 9}] |
{{5, 9}, 4}, {{9, 9}, 9}] |
||
Sudoku.task( difficult )</ |
Sudoku.task( difficult )</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
Line 3,325: | Line 3,481: | ||
=={{header|Erlang}}== |
=={{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. |
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 ). |
-module( sudoku ). |
||
Line 3,488: | Line 3,644: | ||
display( Solved ), |
display( Solved ), |
||
io:nl(). |
io:nl(). |
||
</syntaxhighlight> |
|||
</lang> |
|||
{{out}} |
{{out}} |
||
<pre> |
<pre> |
||
Line 3,572: | Line 3,728: | ||
0 is the empty cell. |
0 is the empty cell. |
||
<syntaxhighlight lang="erre"> |
|||
<lang ERRE> |
|||
!-------------------------------------------------------------------- |
!-------------------------------------------------------------------- |
||
! risolve Sudoku: in input il file SUDOKU.TXT |
! risolve Sudoku: in input il file SUDOKU.TXT |
||
Line 3,979: | Line 4,135: | ||
</syntaxhighlight> |
|||
</lang> |
|||
=={{header|F_Sharp|F#}}== |
=={{header|F_Sharp|F#}}== |
||
=== |
===Backtracking=== |
||
<!-- By Martin Freedman, 26/11/2021 --> |
<!-- By Martin Freedman, 26/11/2021 --> |
||
< |
<syntaxhighlight lang="fsharp">module SudokuBacktrack |
||
//Helpers |
//Helpers |
||
Line 4,013: | Line 4,169: | ||
[for s in squares do s, [| for u in unitList do if u |> Array.contains s then u |] ] |> Map.ofSeq |
[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 = |
let peers = |
||
[for s in squares do units[s] |> Array.concat |> Array.distinct |> Array.except [s] |> tuple2 s] |> Map.ofSeq |
[for s in squares do units[s] |> Array.concat |> Array.distinct |> Array.except [s] |> tuple2 s] |> Map.ofSeq |
||
Line 4,040: | Line 4,196: | ||
let next s = squares |> Array.tryFindIndex ((=)s) |> function Some i when i + 1 < 81 -> Some squares[i + 1] | _ -> None |
let next s = squares |> Array.tryFindIndex ((=)s) |> function Some i when i + 1 < 81 -> Some squares[i + 1] | _ -> None |
||
/// Backtrack |
/// Backtrack recursively and immutably from index |
||
let rec backtracker (values:Map< |
let rec backtracker (values:Map<_,_>) = function |
||
| None -> Some values // solved! |
| None -> Some values // solved! |
||
| Some s when values[s] > 0 -> backtracker values (next s) // square not empty |
| Some s when values[s] > 0 -> backtracker values (next s) // square not empty |
||
Line 4,057: | Line 4,213: | ||
/// solve sudoku using simple backtracking |
/// solve sudoku using simple backtracking |
||
let solve grid = grid |> parseGrid >>= flip backtracker (Some "A1")</ |
let solve grid = grid |> parseGrid >>= flip backtracker (Some "A1")</syntaxhighlight> |
||
'''Usage:''' |
'''Usage:''' |
||
< |
<syntaxhighlight lang="fsharp">open System |
||
open SudokuBacktrack |
open SudokuBacktrack |
||
Line 4,071: | Line 4,227: | ||
printfn "Press any key to exit" |
printfn "Press any key to exit" |
||
Console.ReadKey() |> ignore |
Console.ReadKey() |> ignore |
||
0</ |
0</syntaxhighlight> |
||
{{Output}}<pre> |
{{Output}}<pre> |
||
Puzzle: |
Puzzle: |
||
Line 4,098: | Line 4,254: | ||
</pre> |
</pre> |
||
=== |
===Constraint Satisfaction (Norvig)=== |
||
<!-- By Martin Freedman, 27/11/2021 --> |
|||
<lang fsharp> |
|||
<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 |
// Solve Sudoku Like Puzzles. Nigel Galloway: September 6th., 2018 |
||
let fN y n g=let _q n' g'=[for n in n*n'..n*n'+n-1 do for g in g*g'..g*g'+g-1 do yield (n,g)] |
let 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 4,128: | Line 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.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 "") |
|>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:''' |
'''Usage:''' |
||
Given sud1.csv: |
Given sud1.csv: |
||
Line 4,143: | Line 4,532: | ||
</pre> |
</pre> |
||
then |
then |
||
< |
<syntaxhighlight lang="fsharp"> |
||
let n=SLPsolve (fE ([1..9]|>List.map(string)) 9 3 3 "sud1.csv") |
let n=SLPsolve (fE ([1..9]|>List.map(string)) 9 3 3 "sud1.csv") |
||
printSLP ([1..9]|>List.map(string)) (Seq.item 0 n) |
printSLP ([1..9]|>List.map(string)) (Seq.item 0 n) |
||
</syntaxhighlight> |
|||
</lang> |
|||
{{out}} |
{{out}} |
||
<pre> |
<pre> |
||
Line 4,162: | Line 4,551: | ||
=={{header|Forth}}== |
=={{header|Forth}}== |
||
{{works with|4tH|3.60.0}} |
{{works with|4tH|3.60.0}} |
||
< |
<syntaxhighlight lang="forth">include lib/interprt.4th |
||
include lib/istype.4th |
include lib/istype.4th |
||
include lib/argopen.4th |
include lib/argopen.4th |
||
Line 4,525: | Line 4,914: | ||
; |
; |
||
sudoku</ |
sudoku</syntaxhighlight> |
||
=={{header|Fortran}}== |
=={{header|Fortran}}== |
||
{{works with|Fortran|90 and later}} |
{{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. |
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. |
||
< |
<syntaxhighlight lang="fortran">program sudoku |
||
implicit none |
implicit none |
||
Line 4,627: | Line 5,016: | ||
end subroutine pretty_print |
end subroutine pretty_print |
||
end program sudoku</ |
end program sudoku</syntaxhighlight> |
||
{{out}}<pre> |
{{out}}<pre> |
||
+-----+-----+-----+ |
+-----+-----+-----+ |
||
Line 4,660: | Line 5,049: | ||
=={{header|FreeBASIC}}== |
=={{header|FreeBASIC}}== |
||
{{trans|VBA}} |
{{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 |
Function isSafe(i As Integer, j As Integer, n As Integer) As Boolean |
||
Line 4,746: | Line 5,135: | ||
If (i Mod 3 = 0) Then Print !"\n---------+---------+---------" Else Print |
If (i Mod 3 = 0) Then Print !"\n---------+---------+---------" Else Print |
||
Next i |
Next i |
||
Sleep</ |
Sleep</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre> |
<pre> |
||
Line 4,768: | Line 5,157: | ||
=={{header|FutureBasic}}== |
=={{header|FutureBasic}}== |
||
First is a short version: |
First is a short version: |
||
< |
<syntaxhighlight lang="futurebasic"> |
||
include "ConsoleWindow" |
|||
include "NSLog.incl" |
|||
include "Util_Containers.incl" |
include "Util_Containers.incl" |
||
begin globals |
begin globals |
||
container gC |
|||
end globals |
end globals |
||
BeginCDeclaration |
BeginCDeclaration |
||
short solve_sudoku(short i); |
short solve_sudoku(short i); |
||
short check_sudoku(short r, short c); |
short check_sudoku(short r, short c); |
||
CFMutableStringRef print_sudoku(); |
CFMutableStringRef print_sudoku(); |
||
EndC |
EndC |
||
BeginCFunction |
BeginCFunction |
||
short sudoku[9][9] = { |
short sudoku[9][9] = { |
||
{3,0,0,0,0,1,4,0,9}, |
{3,0,0,0,0,1,4,0,9}, |
||
{7,0,0,0,0,4,2,0,0}, |
{7,0,0,0,0,4,2,0,0}, |
||
{0,5,0,2,0,0,0,1,0}, |
{0,5,0,2,0,0,0,1,0}, |
||
{5,7,0,0,4,3,0,6,0}, |
{5,7,0,0,4,3,0,6,0}, |
||
{0,9,0,0,0,0,0,3,0}, |
{0,9,0,0,0,0,0,3,0}, |
||
{0,6,0,7,9,0,0,8,5}, |
{0,6,0,7,9,0,0,8,5}, |
||
{0,8,0,0,0,5,0,4,0}, |
{0,8,0,0,0,5,0,4,0}, |
||
{0,0,6,4,0,0,0,0,7}, |
{0,0,6,4,0,0,0,0,7}, |
||
{9,0,5,6,0,0,0,0,3}, |
{9,0,5,6,0,0,0,0,3}, |
||
}; |
}; |
||
short check_sudoku( short r, short c ) |
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; |
|||
for (i = 0; i < 9; i++) |
|||
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 ( |
if (i != c && sudoku[r][i] == sudoku[r][c]) return 0; |
||
if (i != r && sudoku[i][c] == sudoku[r][c]) return 0; |
|||
rr = r/3 * 3 + i/3; |
|||
cc = c/3 * 3 + i%3; |
|||
if ((rr != r || cc != c) && sudoku[rr][cc] == sudoku[r][c]) return 0; |
|||
} |
} |
||
return |
return -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 |
EndC |
||
Line 4,858: | Line 5,244: | ||
toolbox fn print_sudoku() = CFMutableStringRef |
toolbox fn print_sudoku() = CFMutableStringRef |
||
short solution |
|||
CFMutableStringRef cfRef |
|||
gC = " " |
gC = " " |
||
Line 4,870: | Line 5,256: | ||
print : print "Sudoku solved:" : print |
print : print "Sudoku solved:" : print |
||
if ( solution ) |
if ( solution ) |
||
gC = " " |
gC = " " |
||
cfRef = fn print_sudoku() |
cfRef = fn print_sudoku() |
||
fn ContainerCreateWithCFString( cfRef, gC ) |
fn ContainerCreateWithCFString( cfRef, gC ) |
||
print gC |
print gC |
||
else |
else |
||
print "No solution found" |
print "No solution found" |
||
end if |
end if |
||
</lang> |
|||
HandleEvents |
|||
</syntaxhighlight> |
|||
Output: |
Output: |
||
Line 4,909: | Line 5,297: | ||
More code in this one, but faster execution: |
More code in this one, but faster execution: |
||
<pre> |
<pre> |
||
include "ConsoleWindow" |
|||
include "Tlbx Timer.incl" |
|||
begin globals |
begin globals |
||
_digits = 9 |
_digits = 9 |
||
Line 4,920: | Line 5,305: | ||
begin record Board |
begin record Board |
||
Boolean f(_digits,_digits,_digits) |
|||
char match(_digits,_digits) |
|||
pointer previousBoard // singly-linked list used to discover repetitions |
|||
dim && |
dim && |
||
end record |
end record |
||
Board quiz |
|||
CFTimeInterval t |
|||
dim as long t |
|||
dim as double sProgStartTime |
|||
end globals |
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 mode |
||
local fn CopyBoard( source as ^Board, dest as ^Board ) |
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 |
end fn |
||
local fn prepare( b as ^Board ) |
local fn prepare( b as ^Board ) |
||
short i, j, n |
|||
'~'1 |
|||
dim as short i, j, n |
|||
for i = 1 to _digits |
|||
for |
for j = 1 to _digits |
||
for |
for n = 1 to _digits |
||
b.match[i, j] = 0 |
|||
for n = 1 to _digits |
|||
b. |
b.f[i, j, n] = _true |
||
next n |
|||
b.f[i, j, n] = _true |
|||
next |
next j |
||
next |
next i |
||
next i |
|||
end fn |
end fn |
||
local fn printBoard( b as ^Board ) |
local fn printBoard( b as ^Board ) |
||
short i, j |
|||
'~'1 |
|||
dim as short i, j |
|||
for i = 1 to _digits |
|||
for |
for j = 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 |
end fn |
||
local fn verifica( b as ^Board ) |
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 |
for j = 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 |
next i |
||
next i |
|||
check = _true |
|||
for j = 1 to _digits |
|||
check = _true |
|||
for |
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 |
|||
if ( first == 0 ) |
|||
first = i |
|||
else |
|||
first = i |
|||
check = _false |
|||
xelse |
|||
exit fn |
|||
check = _false |
|||
end if |
|||
exit fn |
|||
end if |
end if |
||
next i |
|||
end if |
|||
next |
next n |
||
next |
next j |
||
next j |
|||
for i = 1 to _digits |
|||
for |
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 |
|||
if ( first == 0 ) |
|||
first = j |
|||
else |
|||
first = j |
|||
check = _false |
|||
xelse |
|||
exit fn |
|||
check = _false |
|||
end if |
|||
exit fn |
|||
end if |
end if |
||
next j |
|||
end if |
|||
next |
next n |
||
next |
next i |
||
next i |
|||
for x = 0 to ( _nSetH - 1 ) |
|||
for |
for y = 0 to ( _nSetV - 1 ) |
||
first = 0 |
|||
for ii = 0 to ( _digits - 1 ) |
|||
first = 0 |
|||
i = x * _setH + ii mod _setH + 1 |
|||
for ii = 0 to ( _digits - 1 ) |
|||
j = y * _setV + ii / _setH + 1 |
|||
if ( b.match[i, j] == n ) |
|||
if ( first == 0 ) |
|||
first = j |
|||
else |
|||
first = j |
|||
check = _false |
|||
xelse |
|||
exit fn |
|||
check = _false |
|||
end if |
|||
exit fn |
|||
end if |
end if |
||
next ii |
|||
end if |
|||
next |
next y |
||
next |
next x |
||
next x |
|||
end fn = check |
end fn = check |
||
local fn setCell( b as ^Board, x as short, y as short, n as short) as boolean |
local fn setCell( b as ^Board, x as short, y as short, n as short) as boolean |
||
short i, j, rx, ry |
|||
Boolean check |
|||
b.match[x, y] = n |
b.match[x, y] = n |
||
for i = 1 to _digits |
for i = 1 to _digits |
||
b.f[x, i, n] = _false |
b.f[x, i, n] = _false |
||
b.f[i, y, n] = _false |
b.f[i, y, n] = _false |
||
next i |
next i |
||
rx = (x - 1) / _setH |
rx = (x - 1) / _setH |
||
ry = (y - 1) / _setV |
ry = (y - 1) / _setV |
||
for i = 1 to _setH |
for i = 1 to _setH |
||
for j = 1 to _setV |
for j = 1 to _setV |
||
b.f[ rx * _setH + i, ry * _setV + j, n ] = _false |
b.f[ rx * _setH + i, ry * _setV + j, n ] = _false |
||
next j |
next j |
||
next i |
next i |
||
check = fn verifica( #b ) |
check = fn verifica( #b ) |
||
if ( check == _false ) then exit fn |
if ( check == _false ) then exit fn |
||
end fn = check |
end fn = check |
||
local fn solve( b as ^Board ) |
local fn solve( b as ^Board ) |
||
short i, j, n, first, x, y, ii, ppi, ppj |
|||
Boolean check |
|||
check = _true |
check = _true |
||
for i = 1 to _digits |
for i = 1 to _digits |
||
for j = 1 to _digits |
for j = 1 to _digits |
||
if ( b.match[i, j] == 0 ) |
|||
first = 0 |
first = 0 |
||
for n = 1 to _digits |
for n = 1 to _digits |
||
if ( b.f[i, j, n] != _false ) |
|||
if ( first == 0 ) |
|||
first = n |
first = n |
||
else |
|||
xelse |
|||
first = -1 |
first = -1 |
||
exit for |
exit for |
||
end if |
end if |
||
end if |
end if |
||
next n |
next n |
||
if ( first > 0 ) |
|||
check = fn setCell( #b, i, j, first ) |
check = fn setCell( #b, i, j, first ) |
||
if ( check == _false ) then exit fn |
if ( check == _false ) then exit fn |
||
check = fn solve(#b) |
check = fn solve(#b) |
||
if ( check == _false ) then exit fn |
if ( check == _false ) then exit fn |
||
end if |
end if |
||
end if |
end if |
||
next j |
next j |
||
next i |
next i |
||
for i = 1 to _digits |
for i = 1 to _digits |
||
for n = 1 to _digits |
for n = 1 to _digits |
||
first = 0 |
first = 0 |
||
for j = 1 to _digits |
for j = 1 to _digits |
||
if ( b.match[i, j] == n ) then exit for |
if ( b.match[i, j] == n ) then exit for |
||
if ( b.f[i, j, n] != _false ) and ( b.match[i, j] == 0 ) |
|||
if ( first == 0 ) |
|||
first = j |
first = j |
||
else |
|||
xelse |
|||
first = -1 |
first = -1 |
||
exit for |
exit for |
||
end if |
end if |
||
end if |
end if |
||
next j |
next j |
||
if ( first > 0 ) |
|||
check = fn setCell( #b, i, first, n ) |
check = fn setCell( #b, i, first, n ) |
||
if ( check == _false ) then exit fn |
if ( check == _false ) then exit fn |
||
check = fn solve(#b) |
check = fn solve(#b) |
||
if ( check == _false ) then exit fn |
if ( check == _false ) then exit fn |
||
end if |
end if |
||
next n |
next n |
||
next i |
next i |
||
for j = 1 to _digits |
for j = 1 to _digits |
||
for n = 1 to _digits |
for n = 1 to _digits |
||
first = 0 |
first = 0 |
||
for i = 1 to _digits |
for i = 1 to _digits |
||
if ( b.match[i, j] == n ) then exit for |
if ( b.match[i, j] == n ) then exit for |
||
if ( b.f[i, j, n] != _false ) and ( b.match[i, j] == 0 ) |
|||
if ( first == 0 ) |
|||
first = i |
first = i |
||
else |
|||
xelse |
|||
first = -1 |
first = -1 |
||
exit for |
exit for |
||
end if |
end if |
||
end if |
end if |
||
next i |
next i |
||
if ( first > 0 ) |
|||
check = fn setCell( #b, first, j, n ) |
check = fn setCell( #b, first, j, n ) |
||
if ( check == _false ) then exit fn |
if ( check == _false ) then exit fn |
||
check = fn solve(#b) |
check = fn solve(#b) |
||
if ( check == _false ) then exit fn |
if ( check == _false ) then exit fn |
||
end if |
end if |
||
next n |
next n |
||
next j |
next j |
||
for x = 0 to ( _nSetH - 1 ) |
for x = 0 to ( _nSetH - 1 ) |
||
for y = 0 to ( _nSetV - 1 ) |
for y = 0 to ( _nSetV - 1 ) |
||
for n = 1 to _digits |
for n = 1 to _digits |
||
first = 0 |
first = 0 |
||
for ii = 0 to ( _digits - 1 ) |
for ii = 0 to ( _digits - 1 ) |
||
i = x * _setH + ii mod _setH + 1 |
i = x * _setH + ii mod _setH + 1 |
||
j = y * _setV + ii / _setH + 1 |
j = y * _setV + ii / _setH + 1 |
||
if ( b.match[i, j] == n ) then exit for |
if ( b.match[i, j] == n ) then exit for |
||
if ( b.f[i, j, n] != _false ) and ( b.match[i, j] == 0 ) |
|||
if ( first == 0 ) |
|||
first = n |
first = n |
||
ppi = i |
ppi = i |
||
ppj = j |
ppj = j |
||
else |
|||
xelse |
|||
first = -1 |
first = -1 |
||
exit for |
exit for |
||
end if |
end if |
||
end if |
end if |
||
next ii |
next ii |
||
if ( first > 0 ) |
|||
check = fn setCell( #b, ppi, ppj, n ) |
check = fn setCell( #b, ppi, ppj, n ) |
||
if ( check == _false ) then exit fn |
if ( check == _false ) then exit fn |
||
check = fn solve(#b) |
check = fn solve(#b) |
||
if ( check == _false ) then exit fn |
if ( check == _false ) then exit fn |
||
end if |
end if |
||
next n |
next n |
||
next y |
next y |
||
next x |
next x |
||
end fn = check |
end fn = check |
||
local fn resolve( b as ^Board ) |
local fn resolve( b as ^Board ) |
||
Boolean check, daFinire |
|||
long i, j, n |
|||
Board localBoard |
|||
check = fn solve(b) |
check = fn solve(b) |
||
if ( check == _false ) |
|||
exit fn |
exit fn |
||
end if |
end if |
||
daFinire = _false |
daFinire = _false |
||
for i = 1 to _digits |
for i = 1 to _digits |
||
for j = 1 to _digits |
for j = 1 to _digits |
||
if ( b.match[i, j] == 0 ) |
|||
daFinire = _true |
daFinire = _true |
||
for n = 1 to _digits |
for n = 1 to _digits |
||
if ( b.f[i, j, n] != _false ) |
|||
fn CopyBoard( b, @localBoard ) |
fn CopyBoard( b, @localBoard ) |
||
check = fn setCell(@localBoard, i, j, n) |
check = fn setCell(@localBoard, i, j, n) |
||
if ( check != _false ) |
|||
check = fn resolve( @localBoard ) |
check = fn resolve( @localBoard ) |
||
if ( check == -1 ) |
|||
fn CopyBoard( @localBoard, b ) |
fn CopyBoard( @localBoard, b ) |
||
exit fn |
exit fn |
||
end if |
end if |
||
end if |
end if |
||
end if |
end if |
||
next n |
next n |
||
end if |
end if |
||
next j |
next j |
||
next i |
next i |
||
if daFinire |
|||
else |
|||
xelse |
|||
check = -1 |
check = -1 |
||
end if |
end if |
||
end fn = check |
end fn = check |
||
fn InitMilliseconds |
|||
fn prepare( @quiz ) |
fn prepare( @quiz ) |
||
Line 5,282: | Line 5,642: | ||
DATA 2,8,0,1,3,0,0,0,0 |
DATA 2,8,0,1,3,0,0,0,0 |
||
short i, j, d |
|||
for i = 1 to _digits |
for i = 1 to _digits |
||
for j = 1 to _digits |
for j = 1 to _digits |
||
read d |
read d |
||
fn setCell(@quiz, j, i, d) |
fn setCell(@quiz, j, i, d) |
||
next j |
next j |
||
next i |
next i |
||
Line 5,293: | Line 5,653: | ||
fn printBoard( @quiz ) |
fn printBoard( @quiz ) |
||
print : print "-------------------" : print |
print : print "-------------------" : print |
||
Boolean check |
|||
t = fn |
t = fn CACurrentMediaTime |
||
check = fn resolve(@quiz) |
check = fn resolve(@quiz) |
||
t = fn |
t = (fn CACurrentMediaTime - t) * 1000 |
||
if ( check ) |
if ( check ) |
||
print "solution:"; str$( t |
print "solution:"; str$( t ) + " ms" |
||
else |
else |
||
print "No solution found" |
print "No solution found" |
||
end if |
end if |
||
fn printBoard( @quiz ) |
fn printBoard( @quiz ) |
||
HandleEvents |
|||
</pre> |
</pre> |
||
Line 5,339: | Line 5,701: | ||
Input to function solve is an 81 character string. |
Input to function solve is an 81 character string. |
||
This seems to be a conventional computer representation for Sudoku puzzles. |
This seems to be a conventional computer representation for Sudoku puzzles. |
||
< |
<syntaxhighlight lang="go">package main |
||
import "fmt" |
import "fmt" |
||
Line 5,540: | Line 5,902: | ||
} |
} |
||
c.r.l, c.l.r = &c.x, &c.x |
c.r.l, c.l.r = &c.x, &c.x |
||
}</ |
}</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre> |
<pre> |
||
Line 5,573: | Line 5,935: | ||
Imprime todas las soluciones posibles, sale con un error, pero funciona. |
Imprime todas las soluciones posibles, sale con un error, pero funciona. |
||
< |
<syntaxhighlight lang="golfscript"> |
||
'Solution:' |
'Solution:' |
||
;'2 8 4 3 7 5 1 6 9 |
;'2 8 4 3 7 5 1 6 9 |
||
Line 5,587: | Line 5,949: | ||
~]{:@0?:^~!{@p}*10,@9/^9/=-@^9%>9%-@3/^9%3/>3%3/^27/={+}*-{@^<\+@1^+>+}/1}do |
~]{:@0?:^~!{@p}*10,@9/^9/=-@^9%>9%-@3/^9%3/>3%3/^27/={+}*-{@^<\+@1^+>+}/1}do |
||
</syntaxhighlight> |
|||
</lang> |
|||
=={{header|Groovy}}== |
=={{header|Groovy}}== |
||
Line 5,595: | Line 5,957: | ||
I consider this a "brute force" solution of sorts, in that it is the same method I use when solving Sudokus manually. |
I consider this a "brute force" solution of sorts, in that it is the same method I use when solving Sudokus manually. |
||
< |
<syntaxhighlight lang="groovy">final CELL_VALUES = ('1'..'9') |
||
class GridException extends Exception { |
class GridException extends Exception { |
||
Line 5,662: | Line 6,024: | ||
} |
} |
||
grid |
grid |
||
}</ |
}</syntaxhighlight> |
||
'''Test/Benchmark Cases''' |
'''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]] |
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]] |
||
< |
<syntaxhighlight lang="groovy">def sudokus = [ |
||
//Used in Curry solution: ~ 0.1 seconds |
//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', |
'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 5,729: | Line 6,091: | ||
solution.each { println it } |
solution.each { println it } |
||
println "\nELAPSED: ${elapsed} seconds" |
println "\nELAPSED: ${elapsed} seconds" |
||
}</ |
}</syntaxhighlight> |
||
{{out}} (last only): |
{{out}} (last only): |
||
Line 5,763: | Line 6,125: | ||
=={{header|Java}}== |
=={{header|Java}}== |
||
< |
<syntaxhighlight lang="java">public class Sudoku |
||
{ |
{ |
||
private int mBoard[][]; |
private int mBoard[][]; |
||
Line 5,881: | Line 6,243: | ||
} |
} |
||
} |
} |
||
}</ |
}</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
Line 5,920: | Line 6,282: | ||
====ES6==== |
====ES6==== |
||
< |
<syntaxhighlight lang="javascript">//-------------------------------------------[ Dancing Links and Algorithm X ]-- |
||
/** |
/** |
||
* The doubly-doubly circularly linked data object. |
* The doubly-doubly circularly linked data object. |
||
Line 6,193: | Line 6,555: | ||
search(H, []); |
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', |
'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.', |
'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 6,220: | Line 6,582: | ||
let s = new Array(Math.pow(n, 4)).fill('.').join(''); |
let s = new Array(Math.pow(n, 4)).fill('.').join(''); |
||
reduceGrid(s); |
reduceGrid(s); |
||
</syntaxhighlight> |
|||
</lang> |
|||
<pre>+-------+-------+-------+ |
<pre>+-------+-------+-------+ |
||
Line 6,249: | Line 6,611: | ||
| 7 8 2 | 6 9 3 | 5 4 1 | |
| 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> |
</pre> |
||
=={{header|Julia}}== |
=={{header|Julia}}== |
||
< |
<syntaxhighlight lang="julia">function check(i, j) |
||
id, im = div(i, 9), mod(i, 9) |
id, im = div(i, 9), mod(i, 9) |
||
jd, jm = div(j, 9), mod(j, 9) |
jd, jm = div(j, 9), mod(j, 9) |
||
Line 6,275: | Line 6,818: | ||
for i in 1:81 |
for i in 1:81 |
||
if grid[i] == 0 |
if grid[i] == 0 |
||
t = Dict{Int64, |
t = Dict{Int64, Nothing}() |
||
for j in 1:81 |
for j in 1:81 |
||
Line 6,318: | Line 6,861: | ||
0, 5, 0, 6, 9, 0, 0, 1, 0] |
0, 5, 0, 6, 9, 0, 0, 1, 0] |
||
solve_sudoku(display, grid)</ |
solve_sudoku(display, grid)</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre> |
<pre> |
||
Line 6,336: | Line 6,879: | ||
=={{header|Kotlin}}== |
=={{header|Kotlin}}== |
||
{{trans|C++}} |
{{trans|C++}} |
||
< |
<syntaxhighlight lang="scala">// version 1.2.10 |
||
class Sudoku(rows: List<String>) { |
class Sudoku(rows: List<String>) { |
||
Line 6,419: | Line 6,962: | ||
) |
) |
||
Sudoku(rows).solve() |
Sudoku(rows).solve() |
||
}</ |
}</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
Line 6,454: | Line 6,997: | ||
=={{header|Lua}}== |
=={{header|Lua}}== |
||
===without FFI, slow=== |
===without FFI, slow=== |
||
< |
<syntaxhighlight lang="lua">--9x9 sudoku solver in lua |
||
--based on a branch and bound solution |
--based on a branch and bound solution |
||
--fields are not tried in plain order |
--fields are not tried in plain order |
||
Line 6,636: | Line 7,179: | ||
if x then |
if x then |
||
return printer(x) |
return printer(x) |
||
end</ |
end</syntaxhighlight> |
||
Input: |
Input: |
||
<pre> |
<pre> |
||
Line 6,668: | Line 7,211: | ||
Time with luajit: 9.245s |
Time with luajit: 9.245s |
||
===with FFI, fast=== |
===with FFI, fast=== |
||
< |
<syntaxhighlight lang="lua">#!/usr/bin/env luajit |
||
ffi=require"ffi" |
ffi=require"ffi" |
||
local printf=function(fmt, ...) io.write(string.format(fmt, ...)) end |
local printf=function(fmt, ...) io.write(string.format(fmt, ...)) end |
||
Line 6,736: | Line 7,279: | ||
... .8. .79 |
... .8. .79 |
||
]]) |
]]) |
||
end</ |
end</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre>> time ./sudoku_fast.lua |
<pre>> time ./sudoku_fast.lua |
||
Line 6,755: | Line 7,298: | ||
=={{header|Mathematica}}/{{header|Wolfram Language}}== |
=={{header|Mathematica}}/{{header|Wolfram Language}}== |
||
< |
<syntaxhighlight lang="mathematica">solve[sudoku_] := |
||
NestWhile[ |
NestWhile[ |
||
Join @@ Table[ |
Join @@ Table[ |
||
Line 6,764: | Line 7,307: | ||
Extract[Partition[s, {3, 3}], Quotient[#, 3, -2]]]} & /@ |
Extract[Partition[s, {3, 3}], Quotient[#, 3, -2]]]} & /@ |
||
Position[s, 0, {2}], |
Position[s, 0, {2}], |
||
Length@Last@# &], {s, #}] &, {sudoku}, ! FreeQ[#, 0] &]</ |
Length@Last@# &], {s, #}] &, {sudoku}, ! FreeQ[#, 0] &]</syntaxhighlight> |
||
Example: |
Example: |
||
<lang>solve[{{9, 7, 0, 3, 0, 0, 0, 6, 0}, |
<syntaxhighlight lang="text">solve[{{9, 7, 0, 3, 0, 0, 0, 6, 0}, |
||
{0, 6, 0, 7, 5, 0, 0, 0, 0}, |
{0, 6, 0, 7, 5, 0, 0, 0, 0}, |
||
{0, 0, 0, 0, 0, 8, 0, 5, 0}, |
{0, 0, 0, 0, 0, 8, 0, 5, 0}, |
||
Line 6,774: | Line 7,317: | ||
{7, 0, 0, 0, 2, 5, 0, 0, 0}, |
{7, 0, 0, 0, 2, 5, 0, 0, 0}, |
||
{0, 0, 2, 0, 1, 0, 0, 0, 8}, |
{0, 0, 2, 0, 1, 0, 0, 0, 8}, |
||
{0, 4, 0, 0, 0, 7, 3, 0, 0}}]</ |
{0, 4, 0, 0, 0, 7, 3, 0, 0}}]</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre>{{{9, 7, 5, 3, 4, 2, 8, 6, 1}, {8, 6, 1, 7, 5, 9, 4, 3, 2}, {3, 2, 4, |
<pre>{{{9, 7, 5, 3, 4, 2, 8, 6, 1}, {8, 6, 1, 7, 5, 9, 4, 3, 2}, {3, 2, 4, |
||
Line 6,785: | Line 7,328: | ||
For this to work, this code must be placed in a file named "sudokuSolver.m" |
For this to work, this code must be placed in a file named "sudokuSolver.m" |
||
< |
<syntaxhighlight lang="matlab">function solution = sudokuSolver(sudokuGrid) |
||
%Define what each of the sub-boxes of the sudoku grid are by defining |
%Define what each of the sub-boxes of the sudoku grid are by defining |
||
Line 7,137: | Line 7,680: | ||
%% End of program |
%% End of program |
||
end %end sudokuSolver</ |
end %end sudokuSolver</syntaxhighlight> |
||
[http://www.menneske.no/sudoku/eng/showpuzzle.html?number=6903541 Test Input]: |
[http://www.menneske.no/sudoku/eng/showpuzzle.html?number=6903541 Test Input]: |
||
All empty cells must have a value of NaN. |
All empty cells must have a value of NaN. |
||
< |
<syntaxhighlight lang="matlab">sudoku = [NaN NaN NaN NaN 8 3 9 NaN NaN |
||
1 NaN NaN NaN NaN NaN NaN 3 NaN |
1 NaN NaN NaN NaN NaN NaN 3 NaN |
||
NaN NaN 4 NaN NaN NaN NaN 7 NaN |
NaN NaN 4 NaN NaN NaN NaN 7 NaN |
||
Line 7,148: | Line 7,691: | ||
NaN 2 NaN NaN NaN NaN NaN NaN NaN |
NaN 2 NaN NaN NaN NaN NaN NaN NaN |
||
NaN 8 NaN NaN NaN 9 2 NaN NaN |
NaN 8 NaN NaN NaN 9 2 NaN NaN |
||
NaN NaN NaN 2 5 NaN NaN NaN 6]</ |
NaN NaN NaN 2 5 NaN NaN NaN 6]</syntaxhighlight> |
||
[http://www.menneske.no/sudoku/eng/solution.html?number=6903541 Output]: |
[http://www.menneske.no/sudoku/eng/solution.html?number=6903541 Output]: |
||
< |
<syntaxhighlight lang="matlab">solution = |
||
7 6 5 4 8 3 9 2 1 |
7 6 5 4 8 3 9 2 1 |
||
Line 7,160: | Line 7,703: | ||
9 2 6 1 4 7 5 8 3 |
9 2 6 1 4 7 5 8 3 |
||
5 8 1 3 6 9 2 4 7 |
5 8 1 3 6 9 2 4 7 |
||
4 7 3 2 5 8 1 9 6</ |
4 7 3 2 5 8 1 9 6</syntaxhighlight> |
||
=={{header|Nim}}== |
=={{header|Nim}}== |
||
{{trans|Kotlin}} |
{{trans|Kotlin}} |
||
< |
<syntaxhighlight lang="nim">{.this: self.} |
||
type |
type |
||
Line 7,238: | Line 7,781: | ||
var puzzle = Sudoku() |
var puzzle = Sudoku() |
||
puzzle.init(rows) |
puzzle.init(rows) |
||
puzzle.solve()</ |
puzzle.solve()</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
Line 7,271: | Line 7,814: | ||
=={{header|OCaml}}== |
=={{header|OCaml}}== |
||
uses the library [http://ocamlgraph.lri.fr/index.en.html ocamlgraph] |
uses the library [http://ocamlgraph.lri.fr/index.en.html ocamlgraph] |
||
< |
<syntaxhighlight lang="ocaml">(* Ocamlgraph demo program: solving the Sudoku puzzle using graph coloring |
||
Copyright 2004-2007 Sylvain Conchon, Jean-Christophe Filliatre, Julien Signoles |
Copyright 2004-2007 Sylvain Conchon, Jean-Christophe Filliatre, Julien Signoles |
||
Line 7,340: | Line 7,883: | ||
module C = Coloring.Mark(G) |
module C = Coloring.Mark(G) |
||
let () = C.coloring g 9; display ()</ |
let () = C.coloring g 9; display ()</syntaxhighlight> |
||
=={{header|Oz}}== |
=={{header|Oz}}== |
||
Using built-in constraint propagation and search. |
Using built-in constraint propagation and search. |
||
< |
<syntaxhighlight lang="oz">declare |
||
%% a puzzle is a function that returns an initial board configuration |
%% a puzzle is a function that returns an initial board configuration |
||
fun {Puzzle1} |
fun {Puzzle1} |
||
Line 7,427: | Line 7,970: | ||
end |
end |
||
in |
in |
||
{Inspect {Solve Puzzle1}.1}</ |
{Inspect {Solve Puzzle1}.1}</syntaxhighlight> |
||
=={{header|PARI/GP}}== |
=={{header|PARI/GP}}== |
||
Build plugin for PARI's function interface from C code: sudoku.c |
Build plugin for PARI's function interface from C code: sudoku.c |
||
< |
<syntaxhighlight lang="c">#include <pari/pari.h> |
||
typedef int SUDOKU [9][9]; |
typedef int SUDOKU [9][9]; |
||
Line 7,502: | Line 8,045: | ||
return gen_0; /* no solution */ |
return gen_0; /* no solution */ |
||
} |
} |
||
</syntaxhighlight> |
|||
</lang> |
|||
Compile plugin: gcc -O2 -Wall -fPIC -shared sudoku.c -o libsudoku.so -lpari |
Compile plugin: gcc -O2 -Wall -fPIC -shared sudoku.c -o libsudoku.so -lpari |
||
Install plugin from home directory and play: |
Install plugin from home directory and play: |
||
< |
<syntaxhighlight lang="parigp">install("plug_sudoku", "G", "sudoku", "~/libsudoku.so")</syntaxhighlight> |
||
Output:<pre> gp > S=[5,3,0,0,7,0,0,0,0;6,0,0,1,9,5,0,0,0;0,9,8,0,0,0,0,6,0;8,0,0,0,6,0,0,0,3;4,0,0,8,0,3,0,0,1;7,0,0,0,2,0,0,0,6;0,6,0,0,0,0,2,8,0;0,0,0,4,1,9,0,0,5;0,0,0,0,8,0,0,7,9] |
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 7,534: | Line 8,077: | ||
{{works with|Free Pascal}} |
{{works with|Free Pascal}} |
||
Simple backtracking implimentation, therefor it must be fast to be competetive.With doReverse = true same sequence for trycell. nearly 5 times faster than [[Sudoku#C|C]]-Version. |
Simple backtracking implimentation, therefor it must be fast to be competetive.With doReverse = true same sequence for trycell. nearly 5 times faster than [[Sudoku#C|C]]-Version. |
||
< |
<syntaxhighlight lang="pascal">Program soduko; |
||
{$IFDEF FPC} |
{$IFDEF FPC} |
||
{$CODEALIGN proc=16,loop=8} |
{$CODEALIGN proc=16,loop=8} |
||
Line 7,790: | Line 8,333: | ||
Outfield(solF); |
Outfield(solF); |
||
writeln(86400*1000*(T1-T0)/k:10:3,' ms Test calls :',callCnt/k:8:0); |
writeln(86400*1000*(T1-T0)/k:10:3,' ms Test calls :',callCnt/k:8:0); |
||
end.</ |
end.</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre> |
<pre> |
||
Line 7,826: | Line 8,369: | ||
=={{header|Perl}}== |
=={{header|Perl}}== |
||
< |
<syntaxhighlight lang="perl">#!/usr/bin/perl |
||
use integer; |
use integer; |
||
use strict; |
use strict; |
||
Line 7,865: | Line 8,408: | ||
} |
} |
||
} |
} |
||
solve();</ |
solve();</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre> |
<pre> |
||
Line 7,883: | Line 8,426: | ||
=={{header|Phix}}== |
=={{header|Phix}}== |
||
Simple brute force solution. Generally quite good but will struggle on some puzzles (eg see "the beast" below) |
Simple brute force solution. Generally quite good but will struggle on some puzzles (eg see "the beast" below) |
||
<!--<syntaxhighlight lang="phix">(phixonline)--> |
|||
<lang Phix>sequence board = split(""" |
|||
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span> |
|||
.......39 |
|||
<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;">""" |
|||
.....1..5 |
|||
.. |
.......39 |
||
.. |
.....1..5 |
||
. |
..3.5.8.. |
||
..8.9...6 |
|||
.. |
.7...2... |
||
. |
1..4..... |
||
..9.8..5. |
|||
.2....6.. |
|||
4..7....."""</span><span style="color: #0000FF;">,</span><span style="color: #008000;">'\n'</span><span style="color: #0000FF;">)</span> |
|||
function valid_move(integer y, integer x, integer ch) |
|||
for i=1 to 9 do |
|||
<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> |
|||
if ch=board[i][x] then return 0 end if |
|||
<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> |
|||
if ch=board[y][i] then return 0 end if |
|||
<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> |
|||
end for |
|||
<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> |
|||
y -= mod(y-1,3) |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span> |
|||
x -= mod(x-1,3) |
|||
<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> |
|||
for ys=y to y+2 do |
|||
<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> |
|||
for xs=x to x+2 do |
|||
<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> |
|||
if ch=board[ys][xs] then return 0 end if |
|||
<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> |
|||
end for |
|||
<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> |
|||
end for |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span> |
|||
return 1 |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span> |
|||
end function |
|||
<span style="color: #008080;">return</span> <span style="color: #004600;">true</span> |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span> |
|||
sequence solution = {} |
|||
<span style="color: #004080;">sequence</span> <span style="color: #000000;">solution</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{}</span> |
|||
procedure brute_solve() |
|||
for y=1 to 9 do |
|||
<span style="color: #008080;">procedure</span> <span style="color: #000000;">brute_solve</span><span style="color: #0000FF;">()</span> |
|||
for x=1 to 9 do |
|||
<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> |
|||
if board[y][x]<='0' then |
|||
<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> |
|||
for ch='1' to '9' do |
|||
<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> |
|||
if valid_move(y,x,ch) then |
|||
<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> |
|||
board[y][x] = ch |
|||
<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> |
|||
brute_solve() |
|||
<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> |
|||
board[y][x] = ' ' |
|||
<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> |
|||
end if |
|||
<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> |
|||
end for |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span> |
|||
return |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span> |
|||
end if |
|||
<span style="color: #008080;">return</span> |
|||
end for |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span> |
|||
end for |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span> |
|||
solution = board -- (already solved case) |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span> |
|||
end procedure |
|||
<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> |
|||
atom t0 = time() |
|||
brute_solve() |
|||
<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> |
|||
printf(1,"%s\n(solved in %3.2fs)\n",{join(solution,"\n"),time()-t0})</lang> |
|||
<span style="color: #000000;">brute_solve</span><span style="color: #0000FF;">()</span> |
|||
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"%s\n(solved in %3.2fs)\n"</span><span style="color: #0000FF;">,{</span><span style="color: #7060A8;">join</span><span style="color: #0000FF;">(</span><span style="color: #000000;">solution</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"\n"</span><span style="color: #0000FF;">),</span><span style="color: #7060A8;">time</span><span style="color: #0000FF;">()-</span><span style="color: #000000;">t0</span><span style="color: #0000FF;">})</span> |
|||
<!--</syntaxhighlight>--> |
|||
{{out}} |
{{out}} |
||
<pre> |
<pre> |
||
Line 7,950: | Line 8,496: | ||
contains 339 puzzles, can be run as a command-line or gui program, check for multiple solutions, and produce |
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). |
a more readable single-puzzle output (example below). |
||
<!--<syntaxhighlight lang="phix">(phixonline)--> |
|||
<lang Phix>-- Working directly on 81-character strings ultimately proves easier: Originally I |
|||
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span> |
|||
-- just wanted to simplify the final display, but later I realised that a 9x9 grid |
|||
<span style="color: #000080;font-style:italic;">-- Working directly on 81-character strings ultimately proves easier: Originally I |
|||
-- encourages laborious indexing/looping everwhere whereas using a flat 81-element |
|||
-- just wanted to simplify the final display, but later I realised that a 9x9 grid |
|||
-- approach encourages precomputation of index sets, and once you commit to that, |
|||
-- encourages laborious indexing/looping everwhere whereas using a flat 81-element |
|||
-- the rest of the code starts to get a whole lot cleaner. Below we create 27+18 |
|||
-- approach encourages precomputation of index sets, and once you commit to that, |
|||
-- sets and 5 tables of lookup indexes to locate them quickly. |
|||
-- the rest of the code starts to get a whole lot cleaner. Below we create 27+18 |
|||
-- sets and 5 tables of lookup indexes to locate them quickly.</span> |
|||
sequence nines = {}, -- will be 27 in total |
|||
cols = repeat(0,9*9), -- remainder(i-1,9)+1 |
|||
<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> |
|||
rows = repeat(0,9*9), -- floor((i-1)/9)+10 |
|||
<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> |
|||
squares = repeat(0,9*9), |
|||
<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> |
|||
sixes = {}, -- will be 18 in total |
|||
<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> |
|||
dotcol = repeat(0,9*9), -- same col, diff square |
|||
<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> |
|||
dotrow = repeat(0,9*9) -- same row, diff square |
|||
<span style="color: #000000;">dotcol</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">9</span><span style="color: #0000FF;">*</span><span style="color: #000000;">9</span><span style="color: #0000FF;">),</span> <span style="color: #000080;font-style:italic;">-- same col, diff square</span> |
|||
<span style="color: #000000;">dotrow</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">9</span><span style="color: #0000FF;">*</span><span style="color: #000000;">9</span><span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">-- same row, diff square</span> |
|||
procedure set_nines() |
|||
sequence nine, six |
|||
<span style="color: #008080;">procedure</span> <span style="color: #000000;">set_nines</span><span style="color: #0000FF;">()</span> |
|||
integer idx, ndx |
|||
<span style="color: #004080;">sequence</span> <span style="color: #000000;">nine</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">six</span> |
|||
for x=0 to 8 do -- columns |
|||
<span style="color: #004080;">integer</span> <span style="color: #000000;">idx</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">ndx</span> |
|||
nine = {} |
|||
<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> |
|||
ndx = length(nines)+1 |
|||
<span style="color: #000000;">nine</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{}</span> |
|||
for y=1 to 81 by 9 do |
|||
<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> |
|||
idx = y+x |
|||
<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> |
|||
nine = append(nine,idx) |
|||
<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> |
|||
cols[idx] = ndx |
|||
<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> |
|||
end for |
|||
<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> |
|||
nines = append(nines,nine) |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span> |
|||
end for |
|||
<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 y=1 to 81 by 9 do -- rows |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span> |
|||
nine = {} |
|||
<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> |
|||
ndx = length(nines)+1 |
|||
<span style="color: #000000;">nine</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{}</span> |
|||
for x=0 to 8 do |
|||
<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> |
|||
idx = y+x |
|||
<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> |
|||
nine = append(nine,idx) |
|||
<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> |
|||
rows[idx] = ndx |
|||
<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> |
|||
end for |
|||
<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> |
|||
nines = append(nines,nine) |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span> |
|||
end for |
|||
<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> |
|||
if length(nines)!=18 then ?9/0 end if |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span> |
|||
for y=0 to 8 by 3 do -- small squares [19..27] |
|||
<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> |
|||
for x=0 to 8 by 3 do |
|||
<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> |
|||
nine = {} |
|||
<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> |
|||
ndx = length(nines)+1 |
|||
<span style="color: #000000;">nine</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{}</span> |
|||
for sy=y*9 to y*9+18 by 9 do |
|||
<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> |
|||
for sx=x to x+2 do |
|||
<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> |
|||
idx = sy+sx+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> |
|||
nine = append(nine,idx) |
|||
<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> |
|||
squares[idx] = ndx |
|||
<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> |
|||
end for |
|||
<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> |
|||
end for |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span> |
|||
nines = append(nines,nine) |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span> |
|||
end for |
|||
<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> |
|||
end for |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span> |
|||
if length(nines)!=27 then ?9/0 end if |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span> |
|||
for i=1 to 9*9 do |
|||
<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> |
|||
six = {} |
|||
<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> |
|||
nine = nines[cols[i]] -- dotcol |
|||
<span style="color: #000000;">six</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{}</span> |
|||
for j=1 to length(nine) do |
|||
<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> |
|||
if squares[i]!=squares[nine[j]] then |
|||
<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> |
|||
six = append(six,nine[j]) |
|||
<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> |
|||
end if |
|||
<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> |
|||
end for |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span> |
|||
ndx = find(six,sixes) |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span> |
|||
if ndx=0 then |
|||
<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> |
|||
sixes = append(sixes,six) |
|||
<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> |
|||
ndx = length(sixes) |
|||
<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> |
|||
end if |
|||
<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> |
|||
dotcol[i] = ndx |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span> |
|||
six = {} |
|||
<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> |
|||
nine = nines[rows[i]] -- dotrow |
|||
<span style="color: #000000;">six</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{}</span> |
|||
for j=1 to length(nine) do |
|||
<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> |
|||
if squares[i]!=squares[nine[j]] then |
|||
<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> |
|||
six = append(six,nine[j]) |
|||
<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> |
|||
end if |
|||
<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> |
|||
end for |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span> |
|||
ndx = find(six,sixes) |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span> |
|||
if ndx=0 then |
|||
<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> |
|||
sixes = append(sixes,six) |
|||
<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> |
|||
ndx = length(sixes) |
|||
<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> |
|||
end if |
|||
<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> |
|||
dotrow[i] = ndx |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span> |
|||
end for |
|||
<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> |
|||
end procedure |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span> |
|||
set_nines() |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span> |
|||
<span style="color: #000000;">set_nines</span><span style="color: #0000FF;">()</span> |
|||
integer improved = 0 |
|||
<span style="color: #004080;">integer</span> <span style="color: #000000;">improved</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span> |
|||
function eliminate_in(sequence valid, sequence set, integer ch) |
|||
for i=1 to length(set) do |
|||
<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> |
|||
integer idx = set[i] |
|||
<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> |
|||
if string(valid[idx]) then |
|||
<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> |
|||
integer k = find(ch,valid[idx]) |
|||
<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> |
|||
if k!=0 then |
|||
<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> |
|||
valid[idx][k..k] = "" |
|||
<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> |
|||
improved = 1 |
|||
<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> |
|||
end if |
|||
<span style="color: #000000;">improved</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">1</span> |
|||
end if |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span> |
|||
end for |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span> |
|||
return valid |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span> |
|||
end function |
|||
<span style="color: #008080;">return</span> <span style="color: #000000;">valid</span> |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span> |
|||
function test_comb(sequence chosen, sequence pool, sequence valid) |
|||
-- |
|||
<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> |
|||
-- (see deep_logic()/set elimination) |
|||
<span style="color: #000080;font-style:italic;">-- |
|||
-- chosen is a sequence of length 2..4 of integers 1..9: ordered elements of pool. |
|||
-- (see deep_logic()/set elimination) |
|||
-- pool is a set of elements of the sequence valid, each of which is a sequence. |
|||
-- chosen is a sequence of length 2..4 of integers 1..9: ordered elements of pool. |
|||
-- (note that elements of valid in pool not in chosen are not necessarily sequences) |
|||
-- 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) |
|||
--</span> |
|||
integer ccount = 0, ch |
|||
<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> |
|||
object set |
|||
<span style="color: #004080;">integer</span> <span style="color: #000000;">ccount</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">ch</span> |
|||
<span style="color: #004080;">object</span> <span style="color: #000000;">set</span> |
|||
for i=1 to length(chosen) do |
|||
set = valid[pool[chosen[i]]] |
|||
<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> |
|||
for j=1 to length(set) do |
|||
<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> |
|||
ch = set[j]-'0' |
|||
<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> |
|||
if contains[ch]=0 then |
|||
<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> |
|||
contains[ch] = 1 |
|||
<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> |
|||
ccount += 1 |
|||
<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> |
|||
end if |
|||
<span style="color: #000000;">ccount</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">1</span> |
|||
end for |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span> |
|||
end for |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span> |
|||
if ccount=length(chosen) then |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span> |
|||
for i=1 to length(pool) do |
|||
<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> |
|||
if find(i,chosen)=0 then |
|||
<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> |
|||
set = valid[pool[i]] |
|||
<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> |
|||
if sequence(set) then |
|||
<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> |
|||
-- (reverse order so deletions don't foul indexes) |
|||
<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> |
|||
for j=length(set) to 1 by -1 do |
|||
<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> |
|||
ch = set[j]-'0' |
|||
<span style="color: #000080;font-style:italic;">-- (reverse order so deletions don't foul indexes)</span> |
|||
if contains[ch] then |
|||
<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> |
|||
valid[pool[i]][j..j] = "" |
|||
<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> |
|||
improved = 1 |
|||
<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> |
|||
end if |
|||
<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> |
|||
end for |
|||
<span style="color: #000000;">improved</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">1</span> |
|||
end if |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span> |
|||
end if |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span> |
|||
end for |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span> |
|||
end if |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span> |
|||
return valid |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span> |
|||
end function |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span> |
|||
<span style="color: #008080;">return</span> <span style="color: #000000;">valid</span> |
|||
-- from [[Combinations#Phix|Combinations]] |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span> |
|||
-- from http://rosettacode.org/wiki/Combinations#Phix |
|||
function comb(sequence pool, valid, integer needed, done=0, sequence chosen={}) |
|||
<span style="color: #000080;font-style:italic;">-- from [[Combinations#Phix|Combinations]] |
|||
-- (used by deep_logic()/set elimination) |
|||
-- from http://rosettacode.org/wiki/Combinations#Phix</span> |
|||
if needed=0 then -- got a full set |
|||
<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> |
|||
return test_comb(chosen,pool,valid) |
|||
<span style="color: #000080;font-style:italic;">-- (used by deep_logic()/set elimination)</span> |
|||
end if |
|||
<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> |
|||
if done+needed>length(pool) then return valid end if -- cannot fulfil |
|||
<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> |
|||
-- get all combinations with and without the next item: |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span> |
|||
done += 1 |
|||
<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 |
|||
if sequence(valid[pool[done]]) then |
|||
-- get all combinations with and without the next item:</span> |
|||
valid = comb(pool,valid,needed-1,done,append(chosen,done)) |
|||
<span style="color: #000000;">done</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">1</span> |
|||
end if |
|||
<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> |
|||
return comb(pool,valid,needed,done,chosen) |
|||
<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> |
|||
end function |
|||
<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> |
|||
function deep_logic(string board, sequence valid) |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span> |
|||
-- |
|||
-- Create a grid of valid moves. Note this does not modify board, but instead creates |
|||
<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> |
|||
-- sets of permitted values for each cell, which can also be and are used for hints. |
|||
<span style="color: #000080;font-style:italic;">-- |
|||
-- Apply standard eliminations of known cells, then try some more advanced tactics: |
|||
-- 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. |
|||
-- 1) row/col elimination |
|||
-- Apply standard eliminations of known cells, then try some more advanced tactics: |
|||
-- 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 |
|||
-- 1) row/col elimination |
|||
-- small squares. Example (this one with significant practical benefit): |
|||
-- If in any of the 9 small squares a number can only occur in one row or column, |
|||
-- 000|000|036 |
|||
-- then that number cannot occur in that row or column in two other corresponding |
|||
-- 840|000|000 |
|||
-- small squares. Example (this one with significant practical benefit): |
|||
-- 000|000|020 |
|||
-- |
-- 000|000|036 |
||
-- |
-- 840|000|000 |
||
-- |
-- 000|000|020 |
||
-- |
-- ---+---+--- |
||
-- |
-- 000|203|000 |
||
-- |
-- 010|000|700 |
||
-- |
-- 000|600|400 |
||
-- |
-- ---+---+--- |
||
-- |
-- 000|410|050 |
||
-- 003|000|200 |
|||
-- Naively, the br can contain a 3 in the four corners, but looking at mid-right and |
|||
-- 600|000|000 <-- 3 |
|||
-- mid-bottom leads us to eliminating 3s in column 9 and row 9, leaving 7,7 as the |
|||
-- |
-- ^-- 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. |
|||
-- 2) set elimination |
|||
-- Without this, brute force on the above takes ~8s, but with it ~0s |
|||
-- 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): |
|||
-- 2) set elimination |
|||
-- 75.|.9.|.46 |
|||
-- If in any 9-set there is a set of n blank squares that can only contain n digits, |
|||
-- 961|...|352 |
|||
-- then no other squares can contain those digits. Example (with some benefit): |
|||
-- 4..|...|79. |
|||
-- |
-- 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 |
|||
-- (Relies on plain_logic to spot that "must be a 1", and serves as a clear example |
|||
-- |
-- 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.) |
|||
-- strategy. However I think that would be harder to code and cannot imagine a case |
|||
-- |
-- (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 |
|||
-- 3) x-wings |
|||
-- said complementary logic covers, that the above does not, cmiiw.) |
|||
-- 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 |
|||
-- 3) x-wings |
|||
-- cannot occur elsewhere in those two columns/rows. Example (with a benefit): |
|||
-- |
-- 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 |
|||
-- 6..|425|... |
|||
-- cannot occur elsewhere in those two columns/rows. Example (with a benefit): |
|||
-- 2..|..1|.94 |
|||
-- -- |
-- .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] |
|||
-- (we also eliminate 6 from [4,9], [7,6] and [8,6] to no great use) |
|||
-- |
-- 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 |
|||
-- 4) swordfish (not attempted) |
|||
-- obviously trying either 6 in row 1 or 9 immediately pinpoints that 9 anyway. |
|||
-- 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: |
|||
-- 4) swordfish (not attempted) |
|||
-- 8-1|-5-|-3- |
|||
-- There is an extension to x-wings known as swordfish: three (or more) pairs form |
|||
-- 953|-68|--- |
|||
-- a staggered pair (or more) of rectangles that exhibit similar properties, eg: |
|||
-- -4-|-*3|5*8 |
|||
-- --- |
-- 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 |
|||
-- It is not a swordfish if the 3 pairs are on >3 rows, I trust that is obvious. |
|||
-- -3-|82-|1-- |
|||
-- Logically you can extend this to N pairs on N rows, however I cannot imagine a |
|||
-- ^---^---^-- 3 pairs of 9s (marked with *) on 3 rows (only) |
|||
-- case where this is not immediately solved by a single trial-step being invalid. |
|||
-- |
-- 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 |
|||
-- goes for [6,8]:=9 and [7,2]:=9, since they are all entirely inter-dependent.) |
|||
-- |
-- 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 |
|||
-- Likewise there are "Alternate Pairs" and "Hook or X-Y wing" strategies, which |
|||
-- goes for [6,8]:=9 and [7,2]:=9, since they are all entirely inter-dependent.) |
|||
-- are easily solved with a single trial-and-error step, and of course the brute |
|||
-- |
-- 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 |
|||
-- it selects shortest - I've noted the possible improvement below.] |
|||
-- 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, |
|||
integer col, row |
|||
-- it selects shortest - I've noted the possible improvement below.] |
|||
sequence c, r |
|||
--</span> |
|||
sequence nine, prevsets, set |
|||
<span style="color: #004080;">integer</span> <span style="color: #000000;">k</span> <span style="color: #000080;font-style:italic;">-- (scratch)</span> |
|||
object vj |
|||
<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> |
|||
integer ch, k, idx, sx, sy, count |
|||
<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> |
|||
if length(valid)=0 then |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span> |
|||
-- initialise/start again from scratch |
|||
<span style="color: #000080;font-style:italic;">-- |
|||
valid = repeat("123456789",9*9) |
|||
-- First perform standard eliminations of any known cells: |
|||
end if |
|||
-- (repeated every time so plain_logic() does not have to worry about it) |
|||
-- |
|||
--</span> |
|||
-- First perform standard eliminations of any known cells: |
|||
<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> |
|||
-- (repeated every time so plain_logic() does not have to worry about it) |
|||
<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> |
|||
for i=1 to 9*9 do |
|||
<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> |
|||
ch = board[i] |
|||
<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> |
|||
if ch>'0' |
|||
<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> |
|||
and string(valid[i]) then |
|||
<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> |
|||
valid[i] = ch |
|||
<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> |
|||
valid = eliminate_in(valid,nines[cols[i]],ch) |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span> |
|||
valid = eliminate_in(valid,nines[rows[i]],ch) |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span> |
|||
valid = eliminate_in(valid,nines[squares[i]],ch) |
|||
<span style="color: #000080;font-style:italic;">-- |
|||
end if |
|||
-- 1) row/col elimination |
|||
end for |
|||
-- |
--</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> |
|||
-- 1) row/col elimination |
|||
<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: >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> |
|||
for s=19 to 27 do |
|||
<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> |
|||
c = repeat(0,9) -- 0 = none seen, 1..9 this col only, -1: >1 col |
|||
<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> |
|||
r = repeat(0,9) -- "" row row |
|||
<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> |
|||
nine = nines[s] |
|||
<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> |
|||
for n=1 to 9 do |
|||
<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> |
|||
k = nine[n] |
|||
<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> |
|||
vj = valid[k] |
|||
<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> |
|||
if string(vj) then |
|||
<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> |
|||
for i=1 to length(vj) do |
|||
<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> |
|||
ch = vj[i]-'0' |
|||
<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> |
|||
col = dotcol[k] |
|||
<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> |
|||
row = dotrow[k] |
|||
<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> |
|||
c[ch] = iff(find(c[ch],{0,col})!=0?col:-1) |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span> |
|||
r[ch] = iff(find(r[ch],{0,row})!=0?row:-1) |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span> |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span> |
|||
end if |
|||
<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> |
|||
end for |
|||
<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> |
|||
for i=1 to 9 do |
|||
<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> |
|||
ch = i+'0' |
|||
<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> |
|||
col = c[i] |
|||
<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> |
|||
if col>0 then |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span> |
|||
valid = eliminate_in(valid,sixes[col],ch) |
|||
<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> |
|||
end if |
|||
<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> |
|||
row = r[i] |
|||
<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> |
|||
if row>0 then |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span> |
|||
valid = eliminate_in(valid,sixes[row],ch) |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span> |
|||
end if |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span> |
|||
end for |
|||
<span style="color: #000080;font-style:italic;">-- |
|||
end for |
|||
-- |
-- 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;">-- |
|||
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. |
|||
-- Practical note: Meticulously counting empties to eliminate larger set sizes |
|||
--</span> |
|||
-- would at best reduce 6642 tests to 972, not deemed worth it. |
|||
<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)>=set_size then -- (untested)</span> |
|||
for set_size=2 to 4 do |
|||
<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> |
|||
--if floor(count_empties(nines[i])/2)>=set_size then -- (untested) |
|||
<span style="color: #000080;font-style:italic;">--end if</span> |
|||
valid = comb(nines[i],valid,set_size) |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span> |
|||
--end if |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span> |
|||
end for |
|||
<span style="color: #000080;font-style:italic;">-- |
|||
end for |
|||
-- |
-- 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> |
|||
for ch='1' to '9' do |
|||
<span style="color: #004080;">integer</span> <span style="color: #000000;">count</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">idx</span> |
|||
prevsets = repeat(0,9) |
|||
<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> |
|||
for x=1 to 9 do |
|||
<span style="color: #000000;">count</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span> |
|||
count = 0 |
|||
<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> |
|||
set = repeat(0,9) |
|||
<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> |
|||
for y=0 to 8 do |
|||
<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> |
|||
idx = y*9+x |
|||
<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> |
|||
if sequence(valid[idx]) and find(ch,valid[idx]) then |
|||
<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> |
|||
set[y+1] = 1 |
|||
count += 1 |
<span style="color: #000000;">count</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">1</span> |
||
end if |
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span> |
||
end for |
<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> |
|||
if count=2 then |
|||
<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> |
|||
k = find(set,prevsets) |
|||
<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> |
|||
if k!=0 then |
|||
<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> |
|||
for y=0 to 8 do |
|||
<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> |
|||
if set[y+1]=1 then |
|||
<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> |
|||
for sx=1 to 9 do |
|||
<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> |
|||
if sx!=k and sx!=x then |
|||
<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> |
|||
valid = eliminate_in(valid,{y*9+sx},ch) |
|||
end if |
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span> |
||
end for |
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span> |
||
end if |
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span> |
||
end for |
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span> |
||
else |
<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> |
|||
prevsets[x] = set |
|||
end if |
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span> |
||
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span> |
|||
end if |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span> |
|||
end for |
|||
<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> |
|||
prevsets = repeat(0,9) |
|||
<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> |
|||
for y=0 to 8 do |
|||
<span style="color: #000000;">count</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span> |
|||
count = 0 |
|||
<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> |
|||
set = repeat(0,9) |
|||
<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> |
|||
for x=1 to 9 do |
|||
<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> |
|||
idx = y*9+x |
|||
<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> |
|||
if sequence(valid[idx]) and find(ch,valid[idx]) then |
|||
<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> |
|||
set[x] = 1 |
|||
count += 1 |
<span style="color: #000000;">count</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">1</span> |
||
end if |
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span> |
||
end for |
<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> |
|||
if count=2 then |
|||
<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> |
|||
k = find(set,prevsets) |
|||
<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> |
|||
if k!=0 then |
|||
<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> |
|||
for x=1 to 9 do |
|||
<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> |
|||
if set[x]=1 then |
|||
<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> |
|||
for sy=0 to 8 do |
|||
<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> |
|||
if sy+1!=k and sy!=y then |
|||
<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> |
|||
valid = eliminate_in(valid,{sy*9+x},ch) |
|||
end if |
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span> |
||
end for |
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span> |
||
end if |
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span> |
||
end for |
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span> |
||
else |
<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> |
|||
prevsets[y+1] = set |
|||
end if |
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span> |
||
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span> |
|||
end if |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span> |
|||
end for |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span> |
|||
end for |
|||
<span style="color: #008080;">return</span> <span style="color: #000000;">valid</span> |
|||
return valid |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span> |
|||
end function |
|||
<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> |
|||
function permitted_in(string board, sequence sets, sequence valid, integer ch) |
|||
<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> |
|||
sequence set |
|||
<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> |
|||
integer pos, idx, bch |
|||
<span style="color: #004080;">integer</span> <span style="color: #000000;">pos</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span> |
|||
for i=1 to 9 do |
|||
<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> |
|||
set = nines[sets[i]] |
|||
<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> |
|||
pos = 0 |
|||
<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> |
|||
for j=1 to 9 do |
|||
<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> |
|||
idx = set[j] |
|||
<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> |
|||
bch = board[idx] |
|||
<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> |
|||
if bch>'0' then |
|||
<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> |
|||
if bch=ch then pos = -1 exit end if |
|||
<span style="color: #000000;">pos</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">idx</span> |
|||
elsif find(ch,valid[idx]) then |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span> |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span> |
|||
pos = idx |
|||
<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> |
|||
end if |
|||
<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> |
|||
end for |
|||
<span style="color: #000000;">improved</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">1</span> |
|||
if pos>0 then |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span> |
|||
board[pos] = ch |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span> |
|||
improved = 1 |
|||
<span style="color: #008080;">return</span> <span style="color: #000000;">board</span> |
|||
end if |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span> |
|||
end for |
|||
return board |
|||
<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> |
|||
end function |
|||
<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> |
|||
enum INVALID = -1, INCOMPLETE = 0, SOLVED = 1, MULTIPLE = 2, BRUTE = 3 |
|||
<span style="color: #000080;font-style:italic;">-- |
|||
-- Responsible for: |
|||
function plain_logic(string board) |
|||
-- 1) cells with only one option |
|||
-- |
|||
-- 2) numbers with only one home |
|||
-- Responsible for: |
|||
--</span> |
|||
-- 1) cells with only one option |
|||
<span style="color: #004080;">integer</span> <span style="color: #000000;">solved</span> |
|||
-- 2) numbers with only one home |
|||
<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> |
|||
integer solved |
|||
<span style="color: #000000;">solved</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">SOLVED</span> |
|||
sequence valid = {} |
|||
<span style="color: #000000;">improved</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span> |
|||
object vi |
|||
<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> |
|||
while 1 do |
|||
<span style="color: #000080;font-style:italic;">-- 1) cells with only one option:</span> |
|||
solved = SOLVED |
|||
<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> |
|||
improved = 0 |
|||
<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> |
|||
valid = deep_logic(board,valid) |
|||
<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> |
|||
-- 1) cells with only one option: |
|||
<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> |
|||
for i=1 to length(valid) do |
|||
<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> |
|||
vi = valid[i] |
|||
<span style="color: #000000;">improved</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">1</span> |
|||
if string(vi) then |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span> |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span> |
|||
if length(vi)=1 then |
|||
<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> |
|||
board[i] = vi[1] |
|||
<span style="color: #000000;">solved</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">INCOMPLETE</span> |
|||
improved = 1 |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span> |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span> |
|||
end if |
|||
<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> |
|||
if board[i]<='0' then |
|||
solved = INCOMPLETE |
|||
<span style="color: #000080;font-style:italic;">-- 2) numbers with only one home</span> |
|||
end if |
|||
<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> |
|||
end for |
|||
<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> |
|||
if solved=SOLVED then return {board,{},SOLVED} end if |
|||
<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> |
|||
-- 2) numbers with only one home |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span> |
|||
for ch='1' to '9' do |
|||
<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> |
|||
board = permitted_in(board,cols,valid,ch) |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">while</span> |
|||
board = permitted_in(board,rows,valid,ch) |
|||
<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> |
|||
board = permitted_in(board,squares,valid,ch) |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span> |
|||
end for |
|||
if not improved then exit end if |
|||
<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> |
|||
end while |
|||
<span style="color: #000080;font-style:italic;">-- (sum9 should be sufficient - if you want, get rid of nine/nines)</span> |
|||
return {board,valid,solved} |
|||
<span style="color: #004080;">integer</span> <span style="color: #000000;">ch</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">sum9</span> |
|||
end function |
|||
<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> |
|||
function validate(string board) |
|||
<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> |
|||
-- (sum9 should be sufficient - if you want, get rid of nine/nines) |
|||
<span style="color: #000000;">sum9</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span> |
|||
integer ch, sum9 |
|||
<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> |
|||
sequence nine, nines = tagset(9) |
|||
<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> |
|||
for x=0 to 8 do -- columns |
|||
<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> |
|||
sum9 = 0 |
|||
<span style="color: #000000;">sum9</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">ch</span> |
|||
nine = repeat(0,9) |
|||
<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> |
|||
for y=1 to 81 by 9 do |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span> |
|||
ch = board[y+x]-'0' |
|||
<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> |
|||
if ch<1 or ch>9 then return 0 end if |
|||
<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> |
|||
sum9 += ch |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span> |
|||
nine[ch] = ch |
|||
<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> |
|||
end for |
|||
<span style="color: #000000;">sum9</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span> |
|||
if sum9!=45 then return 0 end if |
|||
<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> |
|||
if nine!=nines then return 0 end if |
|||
<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> |
|||
end for |
|||
<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> |
|||
for y=1 to 81 by 9 do -- rows |
|||
<span style="color: #000000;">sum9</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">ch</span> |
|||
sum9 = 0 |
|||
<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> |
|||
nine = repeat(0,9) |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span> |
|||
for x=0 to 8 do |
|||
<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> |
|||
ch = board[y+x]-'0' |
|||
<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> |
|||
sum9 += ch |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span> |
|||
nine[ch] = ch |
|||
<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> |
|||
end for |
|||
<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> |
|||
if sum9!=45 then return 0 end if |
|||
<span style="color: #000000;">sum9</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span> |
|||
if nine!=nines then return 0 end if |
|||
<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> |
|||
end for |
|||
<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 y=0 to 8 by 3 do -- small squares |
|||
<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> |
|||
for x=0 to 8 by 3 do |
|||
<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> |
|||
sum9 = 0 |
|||
<span style="color: #000000;">sum9</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">ch</span> |
|||
nine = repeat(0,9) |
|||
<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> |
|||
for sy=y*9 to y*9+18 by 9 do |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span> |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span> |
|||
ch = board[sy+sx+1]-'0' |
|||
<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> |
|||
sum9 += ch |
|||
<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> |
|||
nine[ch] = ch |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span> |
|||
end for |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span> |
|||
end for |
|||
<span style="color: #008080;">return</span> <span style="color: #004600;">true</span> |
|||
if sum9!=45 then return 0 end if |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span> |
|||
if nine!=nines then return 0 end if |
|||
end for |
|||
<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> |
|||
end for |
|||
<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> |
|||
return 1 |
|||
<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> |
|||
end function |
|||
<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> |
|||
function solve(string board, sequence valid={}) |
|||
<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> |
|||
sequence solution, solutions |
|||
<span style="color: #000080;font-style:italic;">-- find the cell with the fewest options: |
|||
integer solved |
|||
-- (a possible improvement here would be to select the shortest |
|||
integer minopt, mindx |
|||
-- with the "most pairs" set, see swordfish etc above.)</span> |
|||
object vi |
|||
<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> |
|||
{solution,valid,solved} = plain_logic(board) |
|||
<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> |
|||
if solved=INVALID then return {{},INVALID} end if |
|||
<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> |
|||
if solved=SOLVED then return {{solution},SOLVED} end if |
|||
<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> |
|||
if solved=BRUTE then return {{solution},BRUTE} end if |
|||
<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> |
|||
if solved!=INCOMPLETE then ?9/0 end if |
|||
<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> |
|||
-- find the cell with the fewest options: |
|||
<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> |
|||
-- (a possible improvement here would be to select the shortest |
|||
<span style="color: #000000;">mindx</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">i</span> |
|||
-- with the "most pairs" set, see swordfish etc above.) |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span> |
|||
minopt = 10 |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span> |
|||
for i=1 to 9*9 do |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span> |
|||
vi = valid[i] |
|||
<span style="color: #004080;">sequence</span> <span style="color: #000000;">solutions</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{}</span> |
|||
if string(vi) then |
|||
<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> |
|||
if length(vi)<=1 then ?9/0 end if -- should be caught above |
|||
<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> |
|||
if length(vi)<minopt then |
|||
<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> |
|||
minopt = length(vi) |
|||
<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> |
|||
mindx = i |
|||
<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> |
|||
end if |
|||
<span style="color: #008080;">elsif</span> <span style="color: #000000;">solved</span><span style="color: #0000FF;">=</span><span style="color: #000000;">SOLVED</span> |
|||
end if |
|||
<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> |
|||
end for |
|||
<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> |
|||
solutions = {} |
|||
<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> |
|||
for i=1 to minopt do |
|||
<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> |
|||
board[mindx] = valid[mindx][i] |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span> |
|||
{solution,solved} = solve(board,valid) |
|||
<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> |
|||
if solved=MULTIPLE then |
|||
<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> |
|||
return {solution,MULTIPLE} |
|||
<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> |
|||
elsif solved=SOLVED |
|||
<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> |
|||
or solved=BRUTE then |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span> |
|||
if not find(solution[1],solutions) |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span> |
|||
and validate(solution[1]) then |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span> |
|||
solutions = append(solutions,solution[1]) |
|||
<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> |
|||
end if |
|||
<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> |
|||
if length(solutions)>1 then |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span> |
|||
return {solutions,MULTIPLE} |
|||
<span style="color: #008080;">return</span> <span style="color: #0000FF;">{{},</span><span style="color: #000000;">INVALID</span><span style="color: #0000FF;">}</span> |
|||
elsif length(solutions) then |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span> |
|||
return {solutions,BRUTE} |
|||
end if |
|||
<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> |
|||
end if |
|||
<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> |
|||
end for |
|||
<span style="color: #004080;">string</span> <span style="color: #000000;">solution</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">desc</span> |
|||
if length(solutions)=1 then |
|||
<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> |
|||
return {solutions,BRUTE} |
|||
<span style="color: #000000;">desc</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">"(logic)"</span> |
|||
end if |
|||
<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> |
|||
return {{},INVALID} |
|||
<span style="color: #000000;">desc</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">"(brute force)"</span> |
|||
end function |
|||
<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> |
|||
function test_one(string board) |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span> |
|||
sequence solutions |
|||
<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> |
|||
string solution, desc |
|||
<span style="color: #000000;">solution</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">board</span> |
|||
integer solved |
|||
<span style="color: #000000;">desc</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">"*** NO SOLUTIONS ***"</span> |
|||
{solutions,solved} = solve(board) |
|||
<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> |
|||
if solved=SOLVED then |
|||
<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> |
|||
desc = "(logic)" |
|||
<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> |
|||
elsif solved=BRUTE then |
|||
<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> |
|||
desc = "(brute force)" |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span> |
|||
else |
|||
<span style="color: #008080;">else</span> |
|||
desc = "???" -- INVALID/INCOMPLETE/MULTIPLE |
|||
<span style="color: #000000;">solution</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">board</span> |
|||
end if |
|||
<span style="color: #000000;">desc</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">"*** MULTIPLE SOLUTIONS ***"</span> |
|||
if length(solutions)=0 then |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span> |
|||
solution = board |
|||
<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> |
|||
desc = "*** NO SOLUTIONS ***" |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span> |
|||
elsif length(solutions)=1 then |
|||
solution = solutions[1] |
|||
<span style="color: #000080;font-style:italic;">--NB Blank cells can be represented by any character <'1'. Spaces are not recommended since |
|||
if not validate(solution) then |
|||
-- they can all too easily be converted to tabs by copy/paste/save. In particular, ? and |
|||
desc = "*** ERROR ***" -- (should never happen) |
|||
-- _ are NOT valid characters for representing a blank square. Use any of .0-* instead.</span> |
|||
end if |
|||
<span style="color: #008080;">constant</span> <span style="color: #000000;">tests</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span> |
|||
solution = board |
|||
<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)) |
|||
desc = "*** MULTIPLE SOLUTIONS ***" |
|||
-- row/col elimination (was 8s w/o logic first)</span> |
|||
end if |
|||
<span style="color: #008000;">"000000036840000000000000020000203000010000700000600400000410050003000200600000000"</span><span style="color: #0000FF;">,</span> <span style="color: #000080;font-style:italic;">-- (0.04s, (brute force))</span> |
|||
return {solution,desc} |
|||
<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> |
|||
end function |
|||
<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> |
|||
--NB Blank cells can be represented by any character <'1'. Spaces are not recommended since |
|||
<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)) |
|||
-- they can all too easily be converted to tabs by copy/paste/save. In particular, ? and |
|||
-- (the following takes ~8s when checking for multiple solutions)</span> |
|||
-- _ are NOT valid characters for representing a blank square. Use any of .0-* instead. |
|||
<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> |
|||
constant tests = { |
|||
<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)) |
|||
"..............3.85..1.2.......5.7.....4...1...9.......5......73..2.1........4...9", -- (0.01s, (logic)) |
|||
-- x-wings</span> |
|||
-- row/col elimination (was 8s w/o logic first) |
|||
<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> |
|||
"000000036840000000000000020000203000010000700000600400000410050003000200600000000", -- (0.04s, (brute force)) |
|||
"....... |
<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> |
|||
"000037600000600090008000004090000001600000009300000040700000800010009000002540000", -- (0.00s, (logic)) |
|||
".... |
<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> |
|||
-- (the following takes ~8s when checking for multiple solutions) |
|||
<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> |
|||
"--3------4---8--36--8---1---4--6--73---9----------2--5--4-7--686--------7--6--5--", -- (0.01s, (brute force)) |
|||
".. |
<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> |
|||
"--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)) |
|||
<span style="color: #008000;">"503600009010002600900000080000700005006804100200003000030000008004300050800006702"</span><span style="color: #0000FF;">,</span> <span style="color: #000080;font-style:italic;">-- (0.00s, (logic))</span> |
|||
-- x-wings |
|||
". |
<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)) |
|||
".9...4..7.....79..8........4.58.....3.......2.....97.6........4..35.....2..6...8.", -- (0.00s, (logic)) |
|||
-- set exclusion</span> |
|||
-- "AL Escargot", so-called "hardest sudoku" |
|||
" |
<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> |
|||
"12.3....435....1....4........54..2..6...7.........8.9...31..5.......9.7.....6...8", -- (0.48s, (brute force)) |
|||
<span style="color: #008000;">"800000000003600000070090200050007000000045700000100030001000068008500010090000400"</span><span style="color: #0000FF;">,</span> <span style="color: #000080;font-style:italic;">-- (0.21s, (brute force))</span> |
|||
"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)) |
|||
<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> |
|||
"394..267....3..4..5..69..2..45...9..6.......7..7...58..1..67..8..9..8....264..735", -- (0.00s, (logic)) |
|||
" |
<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)) |
|||
"503600009010002600900000080000700005006804100200003000030000008004300050800006702", -- (0.00s, (logic)) |
|||
-- "the beast" (an earlier algorithm took 318s (5min 18s) on this):</span> |
|||
"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)) |
|||
<span style="color: #008000;">"000060080020000000001000000070000102500030000000000400004201000300700600000000050"</span><span style="color: #0000FF;">,</span> <span style="color: #000080;font-style:italic;">-- (0.03s, (brute force))</span> |
|||
"530070000600195000098000060800060003400803001700020006060000280000419005000080079", -- (0.00s, (logic)) |
|||
<span style="color: #0000FF;">$},</span> |
|||
-- 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)) |
|||
<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> |
|||
-- Worlds hardest sudoku: |
|||
<span style="color: #000000;">run_one_test</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span> |
|||
"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)) |
|||
<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> |
|||
"85...24..72......9..4.........1.7..23.5...9...4...........8..7..17..........36.4.", -- (0.01s, (logic)) |
|||
<span style="color: #000000;">s</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">"-------+-------+-------"</span><span style="color: #0000FF;">,</span> |
|||
"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)) |
|||
<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> |
|||
"97.3...6..6.75.........8.5.......67.....3.....539..2..7...25.....2.1...8.4...73..", -- (0.00s, (logic)) |
|||
<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> |
|||
-- "the beast" (an earlier algorithm took 318s (5min 18s) on this): |
|||
"000060080020000000001000000070000102500030000000000400004201000300700600000000050", -- (0.03s, (brute force)) |
|||
<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> |
|||
lt = length(tests), |
|||
<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> |
|||
run_one_test = 0 |
|||
<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> |
|||
constant l = " x x x | x x x | x x x ", |
|||
<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> |
|||
s = "-------+-------+-------", |
|||
<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> |
|||
l3 = join({l,l,l},"\n"), |
|||
<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> |
|||
fmt = substitute(join({l3,s,l3,s,l3},"\n"),"x","%c")&"\n" |
|||
<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> |
|||
procedure print_board(string board) |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span> |
|||
printf(1,fmt,board) |
|||
<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> |
|||
end procedure |
|||
<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> |
|||
procedure test() |
|||
<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> |
|||
string board -- (81 characters) |
|||
<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> |
|||
string solution, desc |
|||
<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> |
|||
atom t0 = time() |
|||
<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> |
|||
if run_one_test then |
|||
<span style="color: #000080;font-style:italic;">-- printf(1," \"%s\", -- (%3.2fs, %s)\n",{solution,time()-t1,desc})</span> |
|||
board = tests[run_one_test] |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span> |
|||
print_board(board) |
|||
<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> |
|||
{solution,desc} = test_one(board) |
|||
<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> |
|||
if length(solution)!=0 then |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span> |
|||
printf(1,"solution:\n") |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span> |
|||
print_board(solution) |
|||
<span style="color: #000000;">test</span><span style="color: #0000FF;">()</span> |
|||
end if |
|||
<!--</syntaxhighlight>--> |
|||
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}} |
{{out}} |
||
<pre> |
<pre> |
||
Line 8,676: | Line 9,209: | ||
=={{header|PHP}}== |
=={{header|PHP}}== |
||
{{trans|C++}} |
{{trans|C++}} |
||
< |
<syntaxhighlight lang="php"> class SudokuSolver { |
||
protected $grid = []; |
protected $grid = []; |
||
protected $emptySymbol; |
protected $emptySymbol; |
||
Line 8,800: | Line 9,333: | ||
$solver = new SudokuSolver('009170000020600001800200000200006053000051009005040080040000700006000320700003900'); |
$solver = new SudokuSolver('009170000020600001800200000200006053000051009005040080040000700006000320700003900'); |
||
$solver->solve(); |
$solver->solve(); |
||
$solver->display();</ |
$solver->display();</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre> |
<pre> |
||
Line 8,815: | Line 9,348: | ||
7 8 2 | 5 6 3 | 9 1 4 |
7 8 2 | 5 6 3 | 9 1 4 |
||
(solved in 0.027s) |
(solved in 0.027s) |
||
</pre> |
|||
=={{header|Picat}}== |
|||
Using constraint programming. |
|||
<syntaxhighlight lang="picat">import util. |
|||
import cp. |
|||
main => go. |
|||
go => |
|||
sudokus(Sudokus), |
|||
foreach([Comment,SudokuS] in Sudokus) |
|||
println(SudokuS), |
|||
println(Comment), |
|||
% Convert string to numbers and "." to _ (unknown) |
|||
Sudoku = [ [cond(S == '.',_,S.to_integer()) : |
|||
S in slice(SudokuS,(I*9)+1,(I+1)*9)] : I in 0..8], |
|||
print_board(Sudoku), |
|||
% Ensure unicity of the solution (check that it is a unique solution) |
|||
All = findall(Sudoku,sudoku(Sudoku)), |
|||
if All.length > 1 then |
|||
printf("Problem has %d solutions!\n", All.length) |
|||
end, |
|||
print("Solution:") |
|||
foreach(A in All) |
|||
print_board(A) |
|||
end, |
|||
nl |
|||
end, |
|||
nl. |
|||
sudoku(Board) => |
|||
N = ceiling(sqrt(Board.len)), |
|||
N2 = N*N, |
|||
Vars = Board.vars(), |
|||
Vars :: 1..N2, |
|||
foreach(Row in Board) all_different(Row) end, |
|||
foreach(Column in transpose(Board)) all_different(Column) end, |
|||
foreach(I in 1..N..N2, J in 1..N..N2) |
|||
all_different([Board[I+K,J+L] : K in 0..N-1, L in 0..N-1]) |
|||
end, |
|||
solve([ffd,inout], Vars). |
|||
print_board(Board) => |
|||
N = Board.length, |
|||
foreach(I in 1..N) |
|||
foreach(J in 1..N) |
|||
X = Board[I,J], |
|||
if var(X) then printf(" _") else printf(" %w", X) end |
|||
end, |
|||
nl |
|||
end, |
|||
nl. |
|||
% (Problems from the Groovy implementation) |
|||
sudokus(Sudokus) => Sudokus = |
|||
[ |
|||
"819..5.....2...75..371.4.6.4..59.1..7..3.8..2..3.62..7.5.7.921..64...9.....2..438", |
|||
"53..247....2...8..1..7.39.2..8.72.49.2.98..7.79.....8.....3.5.696..1.3...5.69..1.", |
|||
"..3.2.6..9..3.5..1..18.64....81.29..7.......8..67.82....26.95..8..2.3..9..5.1.3..", |
|||
"394..267....3..4..5..69..2..45...9..6.......7..7...58..1..67..8..9..8....264..735", |
|||
"97.3...6..6.75.........8.5.......67.....3.....539..2..7...25.....2.1...8.4...73..", |
|||
"4......6.5...8.9..3....1....2.7....1.9.....4.8....3.5....2....7..6.5...8.1......6", |
|||
"85...24..72......9..4.........1.7..23.5...9...4...........8..7..17..........36.4.", |
|||
"..1..5.7.92.6.......8...6...9..2.4.1.........3.4.8..9...7...3.......7.69.1.8..7..", |
|||
".9...4..7.....79..8........4.58.....3.......2.....97.6........4..35.....2..6...8.", |
|||
"12.3....435....1....4........54..2..6...7.........8.9...31..5.......9.7.....6...8", |
|||
"9..2..5...4..6..3...3.....6...9..2......5..8...7..4..37.....1...5..2..4...1..6..9", |
|||
"1....7.9..3..2...8..96..5....53..9...1..8...26....4...3......1..4......7..7...3..", |
|||
"12.4..3..3...1..5...6...1..7...9.....4.6.3.....3..2...5...8.7....7.....5.......98", |
|||
"..............3.85..1.2.......5.7.....4...1...9.......5......73..2.1........4...9", |
|||
".......39.....1..5..3.5.8....8.9...6.7...2...1..4.......9.8..5..2....6..4..7.....", |
|||
"....839..1......3...4....7..42.3....6.......4....7..1..2........8...92.....25...6", |
|||
"..3......4...8..36..8...1...4..6..73...9..........2..5..4.7..686........7..6..5.." |
|||
].</syntaxhighlight> |
|||
{{out}} |
|||
All problems are solved (and proved/checked for unicity) in 0.043s. |
|||
<pre> |
|||
819..5.....2...75..371.4.6.4..59.1..7..3.8..2..3.62..7.5.7.921..64...9.....2..438 |
|||
8 1 9 _ _ 5 _ _ _ |
|||
_ _ 2 _ _ _ 7 5 _ |
|||
_ 3 7 1 _ 4 _ 6 _ |
|||
4 _ _ 5 9 _ 1 _ _ |
|||
7 _ _ 3 _ 8 _ _ 2 |
|||
_ _ 3 _ 6 2 _ _ 7 |
|||
_ 5 _ 7 _ 9 2 1 _ |
|||
_ 6 4 _ _ _ 9 _ _ |
|||
_ _ _ 2 _ _ 4 3 8 |
|||
Solution: |
|||
8 1 9 6 7 5 3 2 4 |
|||
6 4 2 9 8 3 7 5 1 |
|||
5 3 7 1 2 4 8 6 9 |
|||
4 2 6 5 9 7 1 8 3 |
|||
7 9 5 3 1 8 6 4 2 |
|||
1 8 3 4 6 2 5 9 7 |
|||
3 5 8 7 4 9 2 1 6 |
|||
2 6 4 8 3 1 9 7 5 |
|||
9 7 1 2 5 6 4 3 8 |
|||
... |
|||
</pre> |
</pre> |
||
=={{header|PicoLisp}}== |
=={{header|PicoLisp}}== |
||
< |
<syntaxhighlight lang="picolisp">(load "lib/simul.l") |
||
### Fields/Board ### |
### Fields/Board ### |
||
Line 8,899: | Line 9,536: | ||
(0 6 0 0 0 0 2 8 0) |
(0 6 0 0 0 0 2 8 0) |
||
(0 0 0 4 1 9 0 0 5) |
(0 0 0 4 1 9 0 0 5) |
||
(0 0 0 0 8 0 0 7 9) ) )</ |
(0 0 0 0 8 0 0 7 9) ) )</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre> +---+---+---+---+---+---+---+---+---+ |
<pre> +---+---+---+---+---+---+---+---+---+ |
||
Line 8,921: | Line 9,558: | ||
+---+---+---+---+---+---+---+---+---+ |
+---+---+---+---+---+---+---+---+---+ |
||
a b c d e f g h i</pre> |
a b c d e f g h i</pre> |
||
<lang |
<syntaxhighlight lang="picolisp">(go)</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre> +---+---+---+---+---+---+---+---+---+ |
<pre> +---+---+---+---+---+---+---+---+---+ |
||
Line 8,946: | Line 9,583: | ||
=={{header|PL/I}}== |
=={{header|PL/I}}== |
||
Working PL/I version, derived from the Rosetta Fortran version. |
Working PL/I version, derived from the Rosetta Fortran version. |
||
< |
<syntaxhighlight lang="pli">sudoku: procedure options (main); /* 27 July 2014 */ |
||
declare grid (9,9) fixed (1) static initial ( |
declare grid (9,9) fixed (1) static initial ( |
||
Line 9,029: | Line 9,666: | ||
end sudoku; |
end sudoku; |
||
</syntaxhighlight> |
|||
</lang> |
|||
{{out}} |
{{out}} |
||
<pre> |
<pre> |
||
Line 9,063: | Line 9,700: | ||
Another PL/I version, reads sudoku from the text data file as 81 character record. |
Another PL/I version, reads sudoku from the text data file as 81 character record. |
||
< |
<syntaxhighlight lang="pli"> |
||
*PROCESS MARGINS(1,120) LIBS(SINGLE,STATIC); |
*PROCESS MARGINS(1,120) LIBS(SINGLE,STATIC); |
||
*PROCESS OPTIMIZE(2) DFT(REORDER); |
*PROCESS OPTIMIZE(2) DFT(REORDER); |
||
Line 9,202: | Line 9,839: | ||
end sudoku; |
end sudoku; |
||
</syntaxhighlight> |
|||
</lang> |
|||
=={{header|Prolog}}== |
=={{header|Prolog}}== |
||
< |
<syntaxhighlight lang="prolog">:- use_module(library(clpfd)). |
||
sudoku(Rows) :- |
sudoku(Rows) :- |
||
Line 9,230: | Line 9,867: | ||
[5,_,_,_,_,_,_,7,3], |
[5,_,_,_,_,_,_,7,3], |
||
[_,_,2,_,1,_,_,_,_], |
[_,_,2,_,1,_,_,_,_], |
||
[_,_,_,_,4,_,_,_,9]]).</ |
[_,_,_,_,4,_,_,_,9]]).</syntaxhighlight> |
||
===GNU Prolog version=== |
===GNU Prolog version=== |
||
{{works with|GNU Prolog|1.4.4}} |
{{works with|GNU Prolog|1.4.4}} |
||
< |
<syntaxhighlight lang="prolog">:- initialization(main). |
||
Line 9,287: | Line 9,924: | ||
main :- test(T), solve(T), maplist(show,T), halt. |
main :- test(T), solve(T), maplist(show,T), halt. |
||
show(X) :- write(X), nl.</ |
show(X) :- write(X), nl.</syntaxhighlight> |
||
{{Out}} |
{{Out}} |
||
<pre>[1,2,3,4,5,6,7,8,9] |
<pre>[1,2,3,4,5,6,7,8,9] |
||
Line 9,302: | Line 9,939: | ||
=={{header|PureBasic}}== |
=={{header|PureBasic}}== |
||
A brute force method is used, it seemed the fastest as well as the simplest. |
A brute force method is used, it seemed the fastest as well as the simplest. |
||
< |
<syntaxhighlight lang="purebasic">DataSection |
||
puzzle: |
puzzle: |
||
Data.s "394002670" |
Data.s "394002670" |
||
Line 9,412: | Line 10,049: | ||
Input() |
Input() |
||
CloseConsole() |
CloseConsole() |
||
EndIf</ |
EndIf</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre>+-----+-----+-----+ |
<pre>+-----+-----+-----+ |
||
Line 9,444: | Line 10,081: | ||
=={{header|Python}}== |
=={{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. |
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 |
A simple backtrack algorithm -- Quick but may take longer if the grid had been more than 9 x 9 |
||
< |
<syntaxhighlight lang="python"> |
||
def initiate(): |
def initiate(): |
||
box.append([0, 1, 2, 9, 10, 11, 18, 19, 20]) |
box.append([0, 1, 2, 9, 10, 11, 18, 19, 20]) |
||
Line 9,530: | Line 10,169: | ||
print grid[i*9:i*9+9] |
print grid[i*9:i*9+9] |
||
raw_input() |
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}}== |
=={{header|Racket}}== |
||
Line 9,539: | Line 10,245: | ||
===Brute Force=== |
===Brute Force=== |
||
{{trans|Perl}} |
{{trans|Perl}} |
||
<lang |
<syntaxhighlight lang="raku" line>my @A = < |
||
5 3 0 0 2 4 7 0 0 |
5 3 0 0 2 4 7 0 0 |
||
0 0 2 0 0 0 8 0 0 |
0 0 2 0 0 0 8 0 0 |
||
Line 9,579: | Line 10,285: | ||
} |
} |
||
} |
} |
||
solve;</ |
solve;</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
Line 9,597: | Line 10,303: | ||
This is an alternative solution that uses a more ellaborate set of choices instead of brute-forcing it. |
This is an alternative solution that uses a more ellaborate set of choices instead of brute-forcing it. |
||
<lang |
<syntaxhighlight lang="raku" line># |
||
# In this code, a sudoku puzzle is represented as a two-dimentional |
# In this code, a sudoku puzzle is represented as a two-dimentional |
||
# array. The cells that are not yet solved are represented by yet |
# array. The cells that are not yet solved are represented by yet |
||
Line 9,818: | Line 10,524: | ||
} |
} |
||
} |
} |
||
}</ |
}</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
Line 9,836: | Line 10,542: | ||
A sudoku is represented as a matrix, see Rascal solutions to matrix related problems for examples. |
A sudoku is represented as a matrix, see Rascal solutions to matrix related problems for examples. |
||
< |
<syntaxhighlight lang="rascal">import Prelude; |
||
import vis::Figure; |
import vis::Figure; |
||
import vis::Render; |
import vis::Render; |
||
Line 9,919: | Line 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,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> |
<0,8,0>, <1,8,2>, <2,8,6>, <3,8,4>, <4,8,0>, <5,8,0>, <6,8,7>, <7,8,3>, <8,8,5> |
||
};</ |
};</syntaxhighlight> |
||
Example |
Example |
||
Line 10,212: | Line 10,918: | ||
Example of a back-tracking solver, from [[wp:Algorithmics of sudoku]] |
Example of a back-tracking solver, from [[wp:Algorithmics of sudoku]] |
||
{{works with|Ruby|2.0+}} |
{{works with|Ruby|2.0+}} |
||
< |
<syntaxhighlight lang="ruby">def read_matrix(data) |
||
lines = data.lines |
lines = data.lines |
||
9.times.collect { |i| 9.times.collect { |j| lines[i][j].to_i } } |
9.times.collect { |i| 9.times.collect { |j| lines[i][j].to_i } } |
||
Line 10,302: | Line 11,008: | ||
print_matrix(matrix) |
print_matrix(matrix) |
||
puts |
puts |
||
print_matrix(solve_sudoku(matrix))</ |
print_matrix(solve_sudoku(matrix))</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
Line 10,336: | Line 11,042: | ||
=={{header|Rust}}== |
=={{header|Rust}}== |
||
{{trans|Ada}} |
{{trans|Ada}} |
||
< |
<syntaxhighlight lang="rust">type Sudoku = [u8; 81]; |
||
fn is_valid(val: u8, x: usize, y: usize, sudoku_ar: &mut Sudoku) -> bool { |
fn is_valid(val: u8, x: usize, y: usize, sudoku_ar: &mut Sudoku) -> bool { |
||
Line 10,399: | Line 11,105: | ||
println!("Unsolvable"); |
println!("Unsolvable"); |
||
} |
} |
||
}</ |
}</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
Line 10,421: | Line 11,127: | ||
Use CLP solver in SAS/OR: |
Use CLP solver in SAS/OR: |
||
< |
<syntaxhighlight lang="sas">/* define SAS data set */ |
||
data Indata; |
data Indata; |
||
input C1-C9; |
input C1-C9; |
||
Line 10,467: | Line 11,173: | ||
/* print solution */ |
/* print solution */ |
||
print X; |
print X; |
||
quit;</ |
quit;</syntaxhighlight> |
||
Output: |
Output: |
||
Line 10,488: | Line 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. |
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}} |
{{works with|Scala|2.9.1}} |
||
< |
<syntaxhighlight lang="scala">object SudokuSolver extends App { |
||
class Solver { |
class Solver { |
||
Line 10,619: | Line 11,325: | ||
println(solution match {case Nil => "no solution!!!" case _ => f2Str(solution)}) |
println(solution match {case Nil => "no solution!!!" case _ => f2Str(solution)}) |
||
}</ |
}</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre>riddle: |
<pre>riddle: |
||
Line 10,653: | Line 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: |
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}} |
{{works with|Scala|2.9.1}} |
||
< |
<syntaxhighlight lang="scala">object SudokuSolver extends App { |
||
object Solver { |
object Solver { |
||
Line 10,770: | Line 11,476: | ||
+("\n"*2)) |
+("\n"*2)) |
||
} |
} |
||
}</ |
}</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre>riddle used in Ada section: |
<pre>riddle used in Ada section: |
||
Line 10,901: | Line 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. |
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. |
||
<lang>Init_board=[... |
<syntaxhighlight lang="text">Init_board=[... |
||
5 3 0 0 7 0 0 0 0;... |
5 3 0 0 7 0 0 0 0;... |
||
6 0 0 1 9 5 0 0 0;... |
6 0 0 1 9 5 0 0 0;... |
||
Line 11,073: | Line 11,779: | ||
disp('Invalid solution found.'); |
disp('Invalid solution found.'); |
||
disp_board(Solved_board); |
disp_board(Solved_board); |
||
end</ |
end</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
Line 11,133: | Line 11,839: | ||
=={{header|Sidef}}== |
=={{header|Sidef}}== |
||
{{trans|Raku}} |
{{trans|Raku}} |
||
< |
<syntaxhighlight lang="ruby">func check(i, j) is cached { |
||
var (id, im) = i.divmod(9) |
var (id, im) = i.divmod(9) |
||
var (jd, jm) = j.divmod(9) |
var (jd, jm) = j.divmod(9) |
||
Line 11,181: | Line 11,887: | ||
) |
) |
||
solve(grid)</ |
solve(grid)</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre>5 3 9 8 2 4 7 6 1 |
<pre>5 3 9 8 2 4 7 6 1 |
||
Line 11,196: | Line 11,902: | ||
=={{header|Shale}}== |
=={{header|Shale}}== |
||
< |
<syntaxhighlight lang="shale"> |
||
#!/usr/local/bin/shale |
#!/usr/local/bin/shale |
||
Line 11,726: | Line 12,432: | ||
// I'd like to see an irregular sudoku with a knight's move constraint. Any takers... |
// I'd like to see an irregular sudoku with a knight's move constraint. Any takers... |
||
</syntaxhighlight> |
|||
</lang> |
|||
'''Output''' |
'''Output''' |
||
Line 11,767: | Line 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'''. |
The input and output are presented as strings of 81 characters, where each character is either a digit or a space (indicating an empty cell in the grid). The translation between grids and such strings is trivial (convert grid to string by concatenating rows, reading left to right and then top to bottom), and not covered in the solution. The input is given as a bind variable, ''':game'''. |
||
< |
<syntaxhighlight lang="sql">with |
||
symbols (d) as (select to_char(level) from dual connect by level <= 9) |
symbols (d) as (select to_char(level) from dual connect by level <= 9) |
||
, board (i) as (select level from dual connect by level <= 81) |
, board (i) as (select level from dual connect by level <= 81) |
||
Line 11,795: | Line 12,501: | ||
from r |
from r |
||
where pos = 0 |
where pos = 0 |
||
;</ |
;</syntaxhighlight> |
||
A better (faster) approach - taking advantage of database-specific features - is to create a '''table''' NEIGHBORS (similar to the inline view in the WITH clause) and an index on column I of that table; then the query execution time drops by more than half in most cases. |
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 11,819: | Line 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. |
The example grid given below is taken from [https://en.wikipedia.org/wiki/Sudoku_solving_algorithms Wikipedia]. It does not require any recursive call (it's entirely filled in the first step of ''solve''), as can be seen with additional ''printf'' in the code to follow the algorithm. |
||
< |
<syntaxhighlight lang="stata">mata |
||
function sudoku(a) { |
function sudoku(a) { |
||
s = J(81,20,.) |
s = J(81,20,.) |
||
Line 11,919: | Line 12,625: | ||
sudoku(a) |
sudoku(a) |
||
a |
a |
||
end</ |
end</syntaxhighlight> |
||
'''Output''' |
'''Output''' |
||
Line 11,940: | Line 12,646: | ||
Two more examples, from [http://www.7sudoku.com/very-difficult here] and [http://www.extremesudoku.info/sudoku.html there]. |
Two more examples, from [http://www.7sudoku.com/very-difficult here] and [http://www.extremesudoku.info/sudoku.html there]. |
||
< |
<syntaxhighlight lang="stata">a = 7,9,.,.,.,3,.,.,2\ |
||
.,6,.,5,1,.,.,.,.\ |
.,6,.,5,1,.,.,.,.\ |
||
.,.,.,.,.,2,.,.,6\ |
.,.,.,.,.,2,.,.,6\ |
||
Line 11,992: | Line 12,698: | ||
8 | 3 8 5 4 7 9 2 1 6 | |
8 | 3 8 5 4 7 9 2 1 6 | |
||
9 | 7 6 9 3 2 1 4 5 8 | |
9 | 7 6 9 3 2 1 4 5 8 | |
||
+-------------------------------------+</ |
+-------------------------------------+</syntaxhighlight> |
||
=={{header|Swift}}== |
=={{header|Swift}}== |
||
{{trans|Java}} |
{{trans|Java}} |
||
< |
<syntaxhighlight lang="swift">import Foundation |
||
typealias SodukuPuzzle = [[Int]] |
typealias SodukuPuzzle = [[Int]] |
||
Line 12,119: | Line 12,825: | ||
let puzzle = Soduku(board: board) |
let puzzle = Soduku(board: board) |
||
puzzle.solve() |
puzzle.solve() |
||
puzzle.printBoard()</ |
puzzle.printBoard()</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre> |
<pre> |
||
Line 12,139: | Line 12,845: | ||
{{works with|Swift 3}} |
{{works with|Swift 3}} |
||
<syntaxhighlight lang="swift"> |
|||
<lang Swift> |
|||
func solving(board: [[Int]]) -> [[Int]] { |
func solving(board: [[Int]]) -> [[Int]] { |
||
var board = board |
var board = board |
||
Line 12,204: | Line 12,910: | ||
print(solving(board: puzzle)) |
print(solving(board: puzzle)) |
||
</syntaxhighlight> |
|||
</lang> |
|||
{{out}} |
{{out}} |
||
<pre> |
<pre> |
||
Line 12,223: | Line 12,929: | ||
< |
<syntaxhighlight lang="systemverilog"> |
||
////////////////////////////////////////////////////////////////////////////// |
////////////////////////////////////////////////////////////////////////////// |
||
Line 12,353: | Line 13,059: | ||
end |
end |
||
endprogram |
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. |
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 12,408: | Line 13,114: | ||
=={{header|Tailspin}}== |
=={{header|Tailspin}}== |
||
There is a blog post about how this code was developed: https://tobega.blogspot.com/2020/05/creating-algorithm.html |
|||
<lang tailspin> |
|||
<syntaxhighlight lang="tailspin"> |
|||
templates deduceRemainingDigits |
templates deduceRemainingDigits |
||
data row <"1">, col <"1"> local |
|||
templates findOpenPosition |
templates findOpenPosition |
||
@:{options: 10}; |
@:{options: 10"1"}; |
||
$ -> \[i;j](when <[](..~$@findOpenPosition.options)> do @findOpenPosition: {row: $i, col: $j, options: $::length}; \) -> !VOID |
$ -> \[i;j](when <[]?($::length <..~$@findOpenPosition.options::raw>)> do @findOpenPosition: {row: $i, col: $j, options: ($::length)"1"}; \) -> !VOID |
||
$@ ! |
$@ ! |
||
end findOpenPosition |
end findOpenPosition |
||
templates selectFirst&{pos:} |
templates selectFirst&{pos:} |
||
def digit: $($pos.row;$pos.col) -> $(1); |
def digit: $($pos.row;$pos.col) -> $(1); |
||
Line 12,423: | Line 13,129: | ||
when <[]?($i <=$pos.row>) |
when <[]?($i <=$pos.row>) |
||
|[]?($j <=$pos.col>) |
|[]?($j <=$pos.col>) |
||
|[]?(($i-1)~/3 <=($pos.row-1)~/3>)?(($j-1)~/3 <=($pos.col-1)~/3>)> do [$... -> \(when <~=$digit> do $! \)] ! |
|[]?(($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 |
end selectFirst |
||
@: $; |
@: $; |
||
$ -> findOpenPosition -> # |
$ -> findOpenPosition -> # |
||
when <{options: <=0>}> do [] ! |
when <{options: <=0"1">}> do row´1:[] ! |
||
when <{options: <=10>}> do $@ ! |
when <{options: <=10"1">}> do $@ ! |
||
when <> do def next: $; |
|||
$@ -> selectFirst&{pos: $next} -> deduceRemainingDigits |
$@ -> selectFirst&{pos: $next} -> deduceRemainingDigits |
||
-> \(when <~=[]> do @deduceRemainingDigits: $; {options: 10} ! |
-> \(when <~=row´1:[]> do @deduceRemainingDigits: $; {options: 10"1"} ! |
||
when <=[]> do ^@deduceRemainingDigits($next.row;$next.col;1) |
when <=row´1:[]> do ^@deduceRemainingDigits($next.row;$next.col;1) |
||
-> { $next..., options: $next.options |
-> { $next..., options: $next.options-1"1"} ! \) -> # |
||
end deduceRemainingDigits |
end deduceRemainingDigits |
||
test 'internal solver' |
test 'internal solver' |
||
def sample: [ |
def sample: row´1:[ |
||
[5,3,4,6,7,8,9,1,2], |
col´1:[5,3,4,6,7,8,9,1,2], |
||
[6,7,2,1,9,5,3,4,8], |
col´1:[6,7,2,1,9,5,3,4,8], |
||
[1,9,8,3,4,2,5,6,7], |
col´1:[1,9,8,3,4,2,5,6,7], |
||
[8,5,9,7,6,1,4,2,3], |
col´1:[8,5,9,7,6,1,4,2,3], |
||
[4,2,6,8,5,3,7,9,1], |
col´1:[4,2,6,8,5,3,7,9,1], |
||
[7,1,3,9,2,4,8,5,6], |
col´1:[7,1,3,9,2,4,8,5,6], |
||
[9,6,1,5,3,7,2,8,4], |
col´1:[9,6,1,5,3,7,2,8,4], |
||
[2,8,7,4,1,9,6,3,5], |
col´1:[2,8,7,4,1,9,6,3,5], |
||
[3,4,5,2,8,6,1,7,9] |
col´1:[3,4,5,2,8,6,1,7,9] |
||
]; |
]; |
||
assert $sample -> deduceRemainingDigits <=$sample> 'completed puzzle unchanged' |
assert $sample -> deduceRemainingDigits <=$sample> 'completed puzzle unchanged' |
||
assert [ |
assert row´1:[ |
||
[[5],3,4,6,7,8,9,1,2], |
col´1:[[5],3,4,6,7,8,9,1,2], |
||
$sample(2..last)...] -> deduceRemainingDigits <=$sample> 'final digit gets placed' |
$sample(row´2..last)...] -> deduceRemainingDigits <=$sample> 'final digit gets placed' |
||
assert [ |
assert row´1:[ |
||
[[],3,4,6,7,8,9,1,2], |
col´1:[[],3,4,6,7,8,9,1,2], |
||
$sample(2..last)...] -> deduceRemainingDigits <=[]> 'no remaining options returns empty' |
$sample(row´2..last)...] -> deduceRemainingDigits <=row´1:[]> 'no remaining options returns empty' |
||
assert [ |
assert row´1:[ |
||
[[5],3,4,6,[2,5,7],8,9,1,[2,5]], |
col´1:[[5],3,4,6,[2,5,7],8,9,1,[2,5]], |
||
$sample(2..last)...] -> deduceRemainingDigits <=$sample> 'solves 3 digits on row' |
$sample(row´2..last)...] -> deduceRemainingDigits <=$sample> 'solves 3 digits on row' |
||
assert [ |
assert row´1:[ |
||
[5,3,4,6,7,8,9,1,2], |
col´1:[5,3,4,6,7,8,9,1,2], |
||
[[6,7,9],7,2,1,9,5,3,4,8], |
col´1:[[6,7,9],7,2,1,9,5,3,4,8], |
||
[1,9,8,3,4,2,5,6,7], |
col´1:[1,9,8,3,4,2,5,6,7], |
||
[8,5,9,7,6,1,4,2,3], |
col´1:[8,5,9,7,6,1,4,2,3], |
||
[4,2,6,8,5,3,7,9,1], |
col´1:[4,2,6,8,5,3,7,9,1], |
||
[[7],1,3,9,2,4,8,5,6], |
col´1:[[7],1,3,9,2,4,8,5,6], |
||
[[7,9],6,1,5,3,7,2,8,4], |
col´1:[[7,9],6,1,5,3,7,2,8,4], |
||
[2,8,7,4,1,9,6,3,5], |
col´1:[2,8,7,4,1,9,6,3,5], |
||
[3,4,5,2,8,6,1,7,9] |
col´1:[3,4,5,2,8,6,1,7,9] |
||
] -> deduceRemainingDigits <=$sample> 'solves 3 digits on column' |
] -> deduceRemainingDigits <=$sample> 'solves 3 digits on column' |
||
assert [ |
assert row´1:[ |
||
[5,3,[4,6],6,7,8,9,1,2], |
col´1:[5,3,[4,6],6,7,8,9,1,2], |
||
[[6],7,2,1,9,5,3,4,8], |
col´1:[[6],7,2,1,9,5,3,4,8], |
||
[1,[4,6,9],8,3,4,2,5,6,7], |
col´1:[1,[4,6,9],8,3,4,2,5,6,7], |
||
$sample(4..last)... |
$sample(row´4..last)... |
||
] -> deduceRemainingDigits <=$sample> 'solves 3 digits in block' |
] -> deduceRemainingDigits <=$sample> 'solves 3 digits in block' |
||
// This gives a contradiction if 3 gets chosen out of [3,5] |
// This gives a contradiction if 3 gets chosen out of [3,5] |
||
assert [ |
assert row´1:[ |
||
[[3,5],[3,4,6],[3,4,6],[3,4,6],7,8,9,1,2], |
col´1:[[3,5],[3,4,6],[3,4,6],[3,4,6],7,8,9,1,2], |
||
$sample(2..last)...] -> deduceRemainingDigits <=$sample> 'contradiction is backtracked' |
$sample(row´2..last)...] -> deduceRemainingDigits <=$sample> 'contradiction is backtracked' |
||
end 'internal solver' |
end 'internal solver' |
||
composer parseSudoku |
composer parseSudoku |
||
[<section>=3] |
row´1:[<section>=3] |
||
rule section: <row>=3 (<'-+'>? <WS>?) |
rule section: <row>=3 (<'-+'>? <WS>?) |
||
rule row: [<triple>=3] (<WS>?) |
rule row: col´1:[<triple>=3] (<WS>?) |
||
rule triple: <digit|dot>=3 (<'\|'>?) |
rule triple: <digit|dot>=3 (<'\|'>?) |
||
rule digit: [<'\d'>] |
rule digit: [<'\d'>] |
||
rule dot: <'\.'> -> [1..9 -> '$;'] |
rule dot: <'\.'> -> [1..9 -> '$;'] |
||
end parseSudoku |
end parseSudoku |
||
test 'input sudoku' |
test 'input sudoku' |
||
def parsed: |
def parsed: |
||
Line 12,513: | Line 13,219: | ||
...|419|..5 |
...|419|..5 |
||
...|.8.|.79' -> parseSudoku; |
...|.8.|.79' -> parseSudoku; |
||
assert $parsed <[<[<[]>=9](9)>=9](9)> 'parsed sudoku has 9 rows containing 9 columns of lists' |
assert $parsed <[<[<[]>=9](9)>=9](9)> 'parsed sudoku has 9 rows containing 9 columns of lists' |
||
assert $parsed(1;1) <=['5']> 'a digit' |
assert $parsed(row´1;col´1) <=['5']> 'a digit' |
||
assert $parsed(1;3) <=['1','2','3','4','5','6','7','8','9']> 'a dot' |
assert $parsed(row´1;col´3) <=['1','2','3','4','5','6','7','8','9']> 'a dot' |
||
end 'input sudoku' |
end 'input sudoku' |
||
templates solveSudoku |
templates solveSudoku |
||
$ -> parseSudoku -> deduceRemainingDigits -> # |
$ -> parseSudoku -> deduceRemainingDigits -> # |
||
when <=[]> do 'No result found' ! |
when <=row´1:[]> do 'No result found' ! |
||
when <> do $ -> \[i]( |
when <> do $ -> \[i]( |
||
'$(1..3)...;|$(4..6)...;|$(7..9)...;$#10;' ! |
'$(col´1..col´3)...;|$(col´4..col´6)...;|$(col´7..col´9)...;$#10;' ! |
||
$i -> \(when <=3|=6> do '-----------$#10;' !\) ! |
$i -> \(when <=row´3|=row´6> do '-----------$#10;' !\) ! |
||
\) -> '$...;' ! |
\) -> '$...;' ! |
||
end solveSudoku |
end solveSudoku |
||
test 'sudoku solver' |
test 'sudoku solver' |
||
assert |
assert |
||
Line 12,555: | Line 13,261: | ||
'> 'solves sudoku and outputs pretty solution' |
'> 'solves sudoku and outputs pretty solution' |
||
end 'sudoku solver' |
end 'sudoku solver' |
||
</syntaxhighlight> |
|||
</lang> |
|||
=={{header|Tcl}}== |
=={{header|Tcl}}== |
||
Line 12,562: | Line 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. |
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}} |
{{works with|Tcl|8.6}} or {{libheader|TclOO}} |
||
< |
<syntaxhighlight lang="tcl">package require Tcl 8.6 |
||
oo::class create Sudoku { |
oo::class create Sudoku { |
||
variable idata |
variable idata |
||
Line 12,810: | Line 13,516: | ||
return 0 |
return 0 |
||
} |
} |
||
}</ |
}</syntaxhighlight> |
||
Demonstration code: |
Demonstration code: |
||
< |
<syntaxhighlight lang="tcl">SudokuSolver create sudoku |
||
sudoku load { |
sudoku load { |
||
{3 9 4 @ @ 2 6 7 @} |
{3 9 4 @ @ 2 6 7 @} |
||
Line 12,835: | Line 13,541: | ||
} |
} |
||
} |
} |
||
sudoku destroy</ |
sudoku destroy</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre>+-----+-----+-----+ |
<pre>+-----+-----+-----+ |
||
Line 12,851: | Line 13,557: | ||
+-----+-----+-----+</pre> |
+-----+-----+-----+</pre> |
||
If we'd added a logger method (after creating the <code>sudoku</code> object but before running the solver) like this: |
If we'd added a logger method (after creating the <code>sudoku</code> object but before running the solver) like this: |
||
< |
<syntaxhighlight lang="tcl">oo::objdefine sudoku method Log msg {puts $msg}</syntaxhighlight> |
||
Then this additional logging output would have been produced prior to the result being printed: |
Then this additional logging output would have been produced prior to the result being printed: |
||
<pre>::RuleOnlyChoice solved ::sudoku at 8,0 for 1 |
<pre>::RuleOnlyChoice solved ::sudoku at 8,0 for 1 |
||
Line 12,904: | Line 13,610: | ||
Finished solving!</pre> |
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}}== |
=={{header|Ursala}}== |
||
< |
<syntaxhighlight lang="ursala">#import std |
||
#import nat |
#import nat |
||
Line 12,917: | Line 13,668: | ||
~&rgg&& ~&irtPFXlrjrXPS; ~&lrK2tkZ2g&& ~&llrSL2rDrlPrrPljXSPTSL)+-, |
~&rgg&& ~&irtPFXlrjrXPS; ~&lrK2tkZ2g&& ~&llrSL2rDrlPrrPljXSPTSL)+-, |
||
//~&p ^|DlrDSLlrlPXrrPDSL(~&,num*+ rep2 block3)*= num block27 ~&iiK0 iota9, |
//~&p ^|DlrDSLlrlPXrrPDSL(~&,num*+ rep2 block3)*= num block27 ~&iiK0 iota9, |
||
* `0?=\~&iNC ! ~&t digits+-</ |
* `0?=\~&iNC ! ~&t digits+-</syntaxhighlight> |
||
test program: |
test program: |
||
< |
<syntaxhighlight lang="ursala">#show+ |
||
example = |
example = |
||
Line 12,934: | Line 13,685: | ||
010067008 |
010067008 |
||
009008000 |
009008000 |
||
026400735]-</ |
026400735]-</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre> |
<pre> |
||
Line 12,952: | Line 13,703: | ||
=={{header|VBA}}== |
=={{header|VBA}}== |
||
{{trans|Fortran}} |
{{trans|Fortran}} |
||
< |
<syntaxhighlight lang="vb">Dim grid(9, 9) |
||
Dim gridSolved(9, 9) |
Dim gridSolved(9, 9) |
||
Line 13,053: | Line 13,804: | ||
Debug.Print |
Debug.Print |
||
Next i |
Next i |
||
End Sub</ |
End Sub</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre> |
<pre> |
||
Line 13,072: | Line 13,823: | ||
{{trans|VBA}} |
{{trans|VBA}} |
||
To run in console mode with cscript. |
To run in console mode with cscript. |
||
< |
<syntaxhighlight lang="vb">Dim grid(9, 9) |
||
Dim gridSolved(9, 9) |
Dim gridSolved(9, 9) |
||
Line 13,173: | Line 13,924: | ||
End Sub 'Sudoku |
End Sub 'Sudoku |
||
Call sudoku</ |
Call sudoku</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre>Problem: |
<pre>Problem: |
||
Line 13,195: | Line 13,946: | ||
2 4 3 1 5 7 8 6 9 |
2 4 3 1 5 7 8 6 9 |
||
5 1 9 8 3 6 7 2 4</pre> |
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}}== |
=={{header|Wren}}== |
||
{{trans|Kotlin}} |
{{trans|Kotlin}} |
||
< |
<syntaxhighlight lang="wren">class Sudoku { |
||
construct new(rows) { |
construct new(rows) { |
||
if (rows.count != 9 || rows.any { |r| r.count != 9 }) { |
if (rows.count != 9 || rows.any { |r| r.count != 9 }) { |
||
Line 13,275: | Line 14,184: | ||
"000036040" |
"000036040" |
||
] |
] |
||
Sudoku.new(rows).solve()</ |
Sudoku.new(rows).solve()</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
Line 13,312: | Line 14,221: | ||
can be verified by several other examples. |
can be verified by several other examples. |
||
{{trans|C}} |
{{trans|C}} |
||
< |
<syntaxhighlight lang="xpl0">code ChOut=8, CrLf=9, IntOut=11, Text=12; |
||
proc Show(X); |
proc Show(X); |
||
Line 13,382: | Line 14,291: | ||
..9 ..8 ... |
..9 ..8 ... |
||
.26 4.. 735 "); |
.26 4.. 735 "); |
||
]</ |
]</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
Line 13,401: | Line 14,310: | ||
=={{header|zkl}}== |
=={{header|zkl}}== |
||
{{trans|C}} Note: Unlike in the C solution, 1<<-1 is defined (as 0). |
{{trans|C}} Note: Unlike in the C solution, 1<<-1 is defined (as 0). |
||
< |
<syntaxhighlight lang="zkl">fcn trycell(sdku,pos=0){ |
||
row,col:=pos/9, pos%9; |
row,col:=pos/9, pos%9; |
||
Line 13,422: | Line 14,331: | ||
sdku[pos]=0; |
sdku[pos]=0; |
||
return(False); |
return(False); |
||
}</ |
}</syntaxhighlight> |
||
< |
<syntaxhighlight lang="zkl">problem:= |
||
#<<< |
#<<< |
||
" 5 3 0 0 7 0 0 0 0 |
" 5 3 0 0 7 0 0 0 0 |
||
Line 13,441: | Line 14,350: | ||
s[n*27,27].pump(Console.println,T(Void.Read,8),("| " + "%s%s%s | "*3).fmt); // 3 lines |
s[n*27,27].pump(Console.println,T(Void.Read,8),("| " + "%s%s%s | "*3).fmt); // 3 lines |
||
println("+-----+-----+-----+"); |
println("+-----+-----+-----+"); |
||
}</ |
}</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre> |
<pre> |