Recursive algorithm to solve sudoku
A Pascal edition of a solution presented in a YouTube video. The solution presented was in Python and is the simplest brute force solution possible.
The search for a solution is very dependent on the number of possible values in each cell. The more, in the early cells, the longer the back-tracking. I realised that it isn't necessary to progress linearly in the grid. You can go in any order. It can be optimised by sorting the grid cells based on how many possible values each cell can have. The fewer, the earlier they get tried out. It finds the first solution faster, but finding all solutions will take the same time. First comes the simple solution, then the optimised one.
Simple Pascal edition
{$L1500 - Stack size in bytes }
{ Solve sudoku with recursive algoritm }
PROGRAM sudoko;
VAR
grid : ARRAY [0..8,0..8] OF integer;
PROCEDURE fillgrid;
VAR
i,j : integer;
BEGIN
FOR j := 0 TO 8 DO
FOR i := 0 TO 8 DO
grid[j,i] := 0;
grid[0,0] := 5; grid[0,1] := 3; grid[0,4] := 7;
grid[1,0] := 6; grid[1,3] := 1; grid[1,4] := 9; grid[1,5] := 5;
grid[2,1] := 9; grid[2,2] := 8; grid[2,7] := 6;
grid[3,0] := 8; grid[3,4] := 6; grid[3,8] := 3;
grid[4,0] := 4; grid[4,3] := 8; grid[4,5] := 3; grid[4,8] := 1;
grid[5,0] := 7; grid[5,4] := 2; grid[5,8] := 6;
grid[6,1] := 6; grid[6,6] := 2; grid[6,7] := 8;
grid[7,3] := 4; grid[7,4] := 1; grid[7,5] := 9; grid[7,8] := 5;
grid[8,4] := 8; grid[8,7] := 7; grid[8,8] := 9
END;
PROCEDURE printgrid;
VAR
i,j : integer;
BEGIN
FOR j := 0 TO 8 DO
BEGIN
FOR i := 0 TO 8 DO
write(grid[j,i]:2);
writeln
END;
writeln
END;
FUNCTION possible(y,x,n : integer):boolean;
LABEL
100;
VAR
i,j,x0,y0 : integer;
BEGIN
possible := false;
FOR i := 0 TO 8 DO
IF grid[y,i] = n THEN
GOTO 100;
FOR i := 0 TO 8 DO
IF grid[i,x] = n THEN
GOTO 100;
x0 := (x DIV 3) * 3;
y0 := (y DIV 3) * 3;
FOR i := 0 TO 2 DO
FOR j := 0 TO 2 DO
IF grid[y0+i,x0+j] = n THEN
GOTO 100;
possible := true;
100:
END;
PROCEDURE solve;
LABEL 200;
VAR
n,x,y : integer;
BEGIN
FOR y := 0 TO 8 DO
FOR x := 0 TO 8 DO
IF grid[y,x] = 0 THEN
BEGIN
FOR n := 1 TO 9 DO
IF possible(y,x,n) THEN
BEGIN
grid[y,x] := n;
solve;
grid[y,x] := 0
END;
GOTO 200
END;
printgrid;
200:
END;
BEGIN
fillgrid;
writeln('Initial grid:');
printgrid;
writeln('Solutions:');
solve
END.
Edition with sorting of the grid
{$L5500 - Stack size in bytes }
{ Solve sudoku with recursive algoritm.
But first sort the grid on number of guides to
shorten the search.
}
PROGRAM sudoko;
TYPE
valset = SET OF 1..9;
state = RECORD
row,col,numelm : integer;
guides : valset
END;
statearr = ARRAY [0..80] OF state;
VAR
grid : ARRAY [0..8,0..8] OF integer;
scanorder : statearr;
{ Bubble sort of 81 values }
PROCEDURE sort(VAR list: statearr);
VAR
i,j: integer;
t: state;
BEGIN
FOR i := 80 DOWNTO 2 DO
FOR j := 0 TO i - 1 DO
IF list[j].numelm < list[j + 1].numelm THEN
BEGIN
t := list[j];
list[j] := list[j + 1];
list[j + 1] := t;
END;
END;
PROCEDURE fillgrid;
VAR
i,j : integer;
BEGIN
FOR j := 0 TO 8 DO
FOR i := 0 TO 8 DO
grid[j,i] := 0;
grid[0,0] := 5; grid[0,1] := 3; grid[0,4] := 7;
grid[1,0] := 6; grid[1,3] := 1; grid[1,4] := 9; grid[1,5] := 5;
grid[2,1] := 9; grid[2,2] := 8; grid[2,7] := 6;
grid[3,0] := 8; grid[3,4] := 6; grid[3,8] := 3;
grid[4,0] := 4; grid[4,3] := 8; grid[4,5] := 3; grid[4,8] := 1;
grid[5,0] := 7; grid[5,4] := 2; grid[5,8] := 6;
grid[6,1] := 6; grid[6,6] := 2; grid[6,7] := 8;
grid[7,3] := 4; grid[7,4] := 1; grid[7,5] := 9; grid[7,8] := 5;
grid[8,4] := 8; grid[8,7] := 7; grid[8,8] := 9
END;
PROCEDURE printgrid;
VAR
i,j : integer;
BEGIN
FOR j := 0 TO 8 DO
BEGIN
FOR i := 0 TO 8 DO
write(grid[j,i]:2);
writeln
END;
writeln
END;
PROCEDURE scancell(y,x : integer; VAR n : valset);
VAR
i,j,x0,y0 : integer;
BEGIN
n := [];
FOR i := 0 TO 8 DO
IF grid[y,i] <> 0 THEN
n := n + [grid[y,i]];
FOR i := 0 TO 8 DO
IF grid[i,x] <> 0 THEN
n := n + [grid[i,x]];
x0 := (x DIV 3) * 3;
y0 := (y DIV 3) * 3;
FOR i := 0 TO 2 DO
FOR j := 0 TO 2 DO
IF grid[y0+i,x0+j] <> 0 THEN
n := n + [grid[y0+i,x0+j]];
END;
PROCEDURE scangrid;
VAR
n,x,y,z : integer;
BEGIN
FOR y := 0 TO 8 DO
FOR x := 0 TO 8 DO
BEGIN
z := y*9 + x;
scanorder[z].col := x;
scanorder[z].row := y;
scancell(y,x,scanorder[z].guides);
scanorder[z].numelm := 0;
FOR n := 1 TO 9 DO
IF n IN scanorder[z].guides THEN
scanorder[z].numelm := scanorder[z].numelm + 1;
END;
sort(scanorder);
END;
FUNCTION possible(y,x,n : integer):boolean;
LABEL
100;
VAR
i,j,x0,y0 : integer;
BEGIN
possible := false;
FOR i := 0 TO 8 DO
IF grid[y,i] = n THEN
GOTO 100;
FOR i := 0 TO 8 DO
IF grid[i,x] = n THEN
GOTO 100;
x0 := (x DIV 3) * 3;
y0 := (y DIV 3) * 3;
FOR i := 0 TO 2 DO
FOR j := 0 TO 2 DO
IF grid[y0+i,x0+j] = n THEN
GOTO 100;
possible := true;
100:
END;
PROCEDURE solve;
LABEL 200;
VAR
n,x,y,z : integer;
BEGIN
FOR z := 0 TO 80 DO
BEGIN
x := scanorder[z].col;
y := scanorder[z].row;
IF grid[y,x] = 0 THEN
BEGIN
FOR n := 1 TO 9 DO
IF possible(y,x,n) THEN
BEGIN
grid[y,x] := n;
solve;
grid[y,x] := 0
END;
GOTO 200
END
END;
printgrid;
200:
END;
BEGIN
fillgrid;
writeln('Initial grid:');
printgrid;
writeln('Solutions:');
scangrid;
solve
END.