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

From sasCommunity
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;