Both SQL-server and MySQL didn't cope with Recursive solvers. The flattened solver works, albeit a bit slow.
CREATE PROCEDURE [sudokuflat](
@given Char(81)
)
as
begin
declare @r0 int = 0;
declare @c0 int = 0;/*can be negative*/
declare @r1 int = 0;
declare @c1 int = 0;
declare @rb int = 0;
declare @cb int = 0;
declare @r2 int = 0;
declare @c2 int = 0;
declare @n int = 0;
declare @nprev int = 0;/*convert from char*/
declare @fnd int = 0;
declare @fnd2 int = 0;
declare @tmp Char(81) = @given;
while @r0 < 9
begin
set @c0 = 0;
while @c0 < 9
begin
if substring(@tmp,@r0*9+@c0+1,1)='0'
begin
/*reset booleans TinyInt*/
set @fnd2 = 0;
set @n = 0;
/*set to last highest tested*/
if @nprev <> 0
begin
set @n = @nprev;
set @nprev = 0;/*reset immediately*/
end
labelN: while @n < 9
begin
set @n = @n + 1;/*because of "continue" increase here*/
set @fnd = 0;
/*checks*/
set @r1 = 0;
while @r1<9
begin
if @r0<>@r1 and substring(@tmp,@r1*9+@c0+1,1)=@n
begin
set @fnd = 1;
break;
end
set @r1 = @r1 + 1;
end
if @fnd=1 and @n<9
begin
continue;
end
set @c1 = 0;
while @c1<9
begin
if @c0<>@c1 and substring(@tmp,@r0*9+@c1+1,1)=@n
begin
set @fnd = 1;
break;
end
set @c1 = @c1 + 1;
end
if @fnd=1 and @n<9
begin
continue;
end
set @rb = FLOOR(@r0/3)*3;
set @cb = FLOOR(@c0/3)*3;
set @r2 = @rb;
while @r2<@rb+3 begin
set @c2 = @cb;
while @c2<@cb+3 begin
if (@r0<>@r2 or @c0<>@c2) and substring(@tmp,@r2*9+@c2+1,1)=@n
begin
set @fnd = 1;
break;
end
if @fnd = 1 break;
set @c2 = @c2 + 1;
end
set @r2 = @r2 + 1;
end
if @fnd=1 and @n<9
begin
continue;
end
/*try it*/
if @fnd=1
begin
break;/*n must be 9*/
end
set @tmp = CONCAT(substring(@tmp,1,@r0*9+@c0),@n,substring(@tmp,@r0*9+@c0+2,81));
set @fnd2 = 1;
break;/*and continue*/
/*intelligent undo below; with recursion it was undone here*/
end
if @fnd2=0 and @fnd=1 and @n=9
begin
/*undo current position*/
set @tmp = CONCAT(substring(@tmp,1,@r0*9+@c0),'0',substring(@tmp,@r0*9+@c0+2,81));
/*extra step back*/
if @c0=0
begin
set @r0 = @r0 - 1;
set @c0 = 8; /*see below*/
end
else
begin
set @c0 = @c0 - 1;
end
while substring(@given,@r0*9+@c0+1,1)<>'0' or substring(@tmp,@r0*9+@c0+1,1)='9'
begin
/*if the last entered number was a 9, go even further back*/
if substring(@given,@r0*9+@c0+1,1)='0' and substring(@tmp,@r0*9+@c0+1,1)='9'
begin
set @tmp = CONCAT(substring(@tmp,1,@r0*9+@c0),'0',substring(@tmp,@r0*9+@c0+2,81));
end
/*extra step back*/
if @c0=0
begin
set @r0 = @r0 - 1;
set @c0 = 8; /*see below*/
end
else
begin
set @c0 = @c0 - 1;
end
end
set @nprev = cast(substring(@tmp,@r0*9+@c0+1,1) as int);
/*undo backtrack also */
set @tmp = CONCAT(substring(@tmp,1,@r0*9+@c0),'0',substring(@tmp,@r0*9+@c0+2,81));
set @c0 = @c0 - 1;/*contra below*/
end
end
set @c0 = @c0 + 1;/*this is meant by below*/
end
set @r0 = @r0 + 1;
end
if charindex('0',@tmp)=0
begin
INSERT INTO sudokutable(sudoku) VALUES(@tmp);
end
end
DELETE FROM [sudokutable]
GO
DECLARE @return_value int
EXEC @return_value = [dbo].[sudokuflat]
@given = N'000000030050607004008903760000000520000216000042000000087302100200108090030000000'
SELECT TOP 1000 [sudoku] FROM [sudokutable]
GO
Takes a few seconds...