Below is a non recursive sudoku solver in PL/SQL, converted from MySQL version.
CREATE OR REPLACE PROCEDURE sudokuflat(
given in varchar2
)
is
r0 int := 0;
c0 int := 0;/*can be negative*/
r1 int := 0;
c1 int := 0;
rb int := 0;
cb int := 0;
r2 int := 0;
c2 int := 0;
n int := 0;
nprev int := 0;/*convert from char*/
fnd int := 0;
fnd2 int := 0;
tmp varchar2(81) := given;
begin
while r0 < 9
loop
c0 := 0;
while c0 < 9
loop
if substr(tmp,r0*9+c0+1,1)='0' then
/*reset booleans TinyInt*/
fnd2 := 0;
n := 0;
/*set to last highest tested*/
if nprev <> 0 then
n := nprev;
nprev := 0;/*reset immediately*/
end if;
<>
while n < 9
loop
n := n + 1;/*because of "continue" increase here*/
fnd := 0;
/*checks*/
r1 := 0;
<>
while r1<9
loop
if r0<>r1 and substr(tmp,r1*9+c0+1,1)=n then
fnd := 1;
exit labelA;
end if;
r1 := r1 + 1;
end loop;
if fnd=1 and n<9 then
continue;
end if;
c1 := 0;
<>
while c1<9
loop
if c0<>c1 and substr(tmp,r0*9+c1+1,1)=n then
fnd := 1;
exit labelB;
end if;
c1 := c1 + 1;
end loop;
if fnd=1 and n<9 then
continue;
end if;
rb := FLOOR(r0/3)*3;
cb := FLOOR(c0/3)*3;
r2 := rb;
<>
while rb+3>r2
loop
c2 := cb;
while cb+3>c2
loop
if (r0<>r2 or c0<>c2) and substr(tmp,r2*9+c2+1,1)=n then
fnd := 1;
exit labelC;
end if;
c2 := c2 + 1;
end loop;
r2 := r2 + 1;
end loop;
if fnd=1 and n<9 then
continue;
end if;
/*try it*/
if fnd=1 then
exit labelN;/*n must be 9*/
end if;
tmp := substr(tmp,1,r0*9+c0)||n||substr(tmp,r0*9+c0+2,81);
fnd2 := 1;
exit labelN;/*and continue*/
/*intelligent undo below; with recursion it was undone here*/
end loop;
if fnd2=0 and fnd=1 and n=9 then
/*undo current position*/
tmp := substr(tmp,1,r0*9+c0)||'0'||substr(tmp,r0*9+c0+2,81);
/*extra step back*/
if c0=0 then
r0 := r0 - 1;
c0 := 8; /*see below*/
else c0 := c0 - 1;
end if;
while substr(given,r0*9+c0+1,1)<>'0' or substr(tmp,r0*9+c0+1,1)='9'
loop
/*if the last entered number was a 9, go even further back*/
if substr(given,r0*9+c0+1,1)='0' and substr(tmp,r0*9+c0+1,1)='9' then
tmp := substr(tmp,1,r0*9+c0)||'0'||substr(tmp,r0*9+c0+2,81);
end if;
/*extra step back*/
if c0=0 then
r0 := r0 - 1;
c0 := 8; /*see below*/
else c0 := c0 - 1;
end if;
end loop;
nprev := cast(substr(tmp,r0*9+c0+1,1) as int);
/*undo backtrack also */
tmp := substr(tmp,1,r0*9+c0)||'0'||substr(tmp,r0*9+c0+2,81);
c0 := c0 - 1;/*contra below*/
end if;
end if;
c0 := c0 + 1;/*this is meant by below*/
end loop;
r0 := r0 + 1;
end loop;
if instr(tmp,'0')=0 then
dbms_output.put_line(tmp);
end if;
end;
/
SHOW ERRORS
set linesize 100
begin
sudokuflat('000000030050607004008903760000000520000216000042000000087302100200108090030000000');
end;
/