As the first step in the decommissioning of sasCommunity.org the site has been converted to read-only mode.

Here are some tips for How to share your SAS knowledge with your professional network.

# Sudoku Solver in DATA Step

Jump to: navigation, search

This solver was not presented at SGF 2007.

The code solves the puzzle using the process of elimination. It will halt if a guess is needed.

### SAS Code

```/* Richard A. DeVenezia
* Sudoku solver
* April 20, 2007
*/

data solution (keep=id puzzlestring s1-s81);

set sasuser.sudokus;
where id = 7;

/*
* A [ d, r, c ] - Available candidate items
* N [    r, c ] - Number of available candidates
* S [    r, c ] - Placed items
* M - relative offsets for other cells in block
*/

array A[9,9,9] a1-a729 (81*1,81*2,81*3,81*4,81*5,81*6,81*7,81*8,81*9);
array N[9,9]   n1-n81  (81*9);
array S[9,9]   s1-s81  (81*.);
array M[0:2,2] _temporary_ (-2,-1,+1,+2,-1,+1);

* validate puzzle;

index = 0;
do r = 1 to 9;
do c = 1 to 9;
index + 1;
length vc \$1;
vc = substr(puzzleString,index);
if verify (vc,'123456789') then continue;
vn = input (vc,1.);
row = r;
col = c;
digit = vn;
link SetCell;
if status = -1 then do;
put "Invalid puzzle string detected at " row= col= digit=;
link renderPuzzleString;
stop;
end;
end;
end;

* report puzzle to log;

put 'Initial conditions:';
put (s[*]) (9*3. /) /;

* elimination core;

do until (status < 0);
status = -2;
max = 0;
min = 10;
do row = 1 to 9 while (status = -2);
do col = 1 to 9 while (status = -2);
remain = N [ row, col ];
if remain = 1 then do;
do digit = 1 to 9;
if A [ digit, row, col ] eq . then continue;
link SetCell;
leave;
end;
end;
else do;
max = max (max, N [ row, col ]);
if 0 < remain < min then min = remain;
end;
end;
end;
end;

* when core is done the puzzle is finished or a guess is needed;

if status = -2 and max = 0 then do;
put / 'Solution:';
put (n[*]) (9*3. /) /;
put (s[*]) (9*3. /);
end;
else do;
put 'Solution indeterminate, guessing is required';
put 'Determined cells exhausted at ' setcount=;
*   put (a[*]) (9*3. /) /;
put (n[*]) (9*3. /) /;
put (s[*]) (9*3. /);
end;

output;

stop;
return;

SetCell:
* put digit= row= col= n[row,col]=;

status = -1;

if A [ digit, row, col ] = . then return;

setcount + 1;

* clear cell possibilities;
do _d = 1 to 9;
if A [ _d, row, col ] = . then continue;
A [ _d, row, col ] = .;
N [     row, col ] + (-1);
end;

* clear row possibilities;
do _c = 1 to 9;
if A [ digit, row, _c ] = . then continue;
if N [ row, _c ] = 1 and S [ row, _c ] = . then do;
put "Invalid elimination: " digit= row= col= _c=;
put (a[*]) (9*3. /) /;
stop;
end;

A [ digit, row, _c ] = .;
N [        row, _c ] + (-1);
end;

* clear col possibilities;
do _r = 1 to 9;
if A [ digit, _r, col ] = . then continue;
if N [ _r, col ] = 1 and S [ _r, col ] = . then do;
put "Invalid elimination: " digit= row= col= _r=;
put (a[*]) (9*3. /) /;
stop;
end;

A [ digit, _r, col ] = .;
N [        _r, col ] + (-1);
end;

* clear block possibilities;
_rm = mod (row,3);
_cm = mod (col,3);

do _ro = M[_rm,1] , M[_rm,2]; _r = row + _ro;
do _co = M[_cm,1] , M[_cm,2]; _c = col + _co;
if A [ digit, _r, _c ] = . then continue;
if N [ _r, _c ] = 1 and S [ _r, _c ] = . then do;
put "Invalid elimination: " digit= row= col= _r= _c=;
put (a[*]) (9*3. /) /;
stop;
end;

A [ digit, _r, _c ] = .;
N [        _r, _c ] + (-1);
end;
end;

* set cell;
S [ row, col ] = digit;

status = 0;
return;

renderPuzzleString:
index = 0;
do r = 1 to 9;  if mod(r,3)=1 then put;
do c = 1 to 9;  if mod(c,3)=1 then put ' ' @;
index + 1;
length vc \$1;
vc = substr(puzzleString,index);
put vc @;
end; put;
end; put;
return;

run;
```