数独

 投稿者:永野護  投稿日:2014年 9月22日(月)14時22分11秒
  private  bool  判定(int ix,int iy)  //ナンプレ条件の判定(行と列のみ判定)
{  int i,j;int  x=tb[ix,iy];
for(i=0;i<9;i++) if (ix  !=i  && x==tb[i,iy]) return  (false);
for(i=0;i<9;i++) if (iy  !=i  && x==tb[ix,i]) return  (false);
return  numpre();  //  ここが再帰的になる
}


private  bool  numpre()
{  int i,j,k;
for (i=0;i<9;i++)
  for (j=0;j<9;j++)
   if (tb[i,j]==0)
{ for (k=1;k<10;k++)
  {tb[i,j]=k;
   if  (判定(i,j)) return true;
}
tb[i,j]=0; return false;
}
return true;
}

以上はVisual  C#.NETによるアルゴリズムとデーター構造(白井豊 著:ゆたか創造社)に掲載されていた
ナンプレを解くプログラムの一部です。結果出力部などは省略しています。
これを十進BASICで書き直せばどのようになるのでしょうか。
よろしくお願いします。

 
 

Re: 数独

 投稿者:山中和義  投稿日:2014年 9月23日(火)10時02分29秒
  > No.3507[元記事へ]

永野護さんへのお返事です。

> private  bool  判定(int ix,int iy)  //ナンプレ条件の判定(行と列のみ判定)
> {  int i,j;int  x=tb[ix,iy];
> for(i=0;i<9;i++) if (ix  !=i  && x==tb[i,iy]) return  (false);
> for(i=0;i<9;i++) if (iy  !=i  && x==tb[ix,i]) return  (false);
> return  numpre();  //  ここが再帰的になる
> }
>
>
> private  bool  numpre()
> {  int i,j,k;
> for (i=0;i<9;i++)
>   for (j=0;j<9;j++)
>    if (tb[i,j]==0)
> { for (k=1;k<10;k++)
>   {tb[i,j]=k;
>    if  (判定(i,j)) return true;
> }
> tb[i,j]=0; return false;
> }
> return true;
> }


PUBLIC NUMERIC FALSE,TRUE !システム定数
LET FALSE=0
LET TRUE=-1

DATA 0,7,0, 0,0,0, 0,0,5 !難問
DATA 0,0,6, 0,2,0, 0,0,0
DATA 0,9,0, 1,0,0, 3,0,0

DATA 0,0,0, 0,0,4, 0,0,2
DATA 0,8,0, 0,0,0, 0,1,0
DATA 5,0,0, 3,0,0, 0,0,0

DATA 0,0,4, 0,0,7, 0,6,0
DATA 0,0,0, 0,8,0, 1,0,0
DATA 2,0,0, 0,0,0, 0,9,0

PUBLIC NUMERIC tb(0 TO 8, 0 TO 8)
MAT READ tb

LET dummy=numpre(dummy)

END

EXTERNAL FUNCTION check(ix,iy) !ナンプレ条件の判定
LET x=tb(ix,iy)
FOR i=0 TO 8 !行
   IF ix<>i AND x=tb(i,iy) THEN
      LET check=FALSE
      EXIT FUNCTION
   END IF
NEXT i
FOR i=0 TO 8 !列
   IF iy<>i AND x=tb(ix,i) THEN
      LET check=FALSE
      EXIT FUNCTION
   END IF
NEXT i
LET bx=INT(ix/3)*3 !ブロック
LET by=INT(iy/3)*3
FOR i=0 TO 2
   FOR J=0 TO 2
      IF (ix<>bx+i OR iy<>by+J) AND x=tb(bx+i,by+J) THEN
         LET check=FALSE
         EXIT FUNCTION
      END IF
   NEXT J
NEXT i

LET check=numpre(dummy) !ここが再帰的になる
END FUNCTION

EXTERNAL FUNCTION numpre(dummy)
FOR i=0 TO 8 !9×9
   FOR J=0 TO 8
      IF tb(i,J)=0 THEN !未定義なら
         FOR k=1 TO 9 !1から9までの数を置いてみる
            LET tb(i,J)=k
            IF check(i,J)<>FALSE THEN !この数でよいなら
               LET numpre=TRUE
               EXIT FUNCTION
            END IF
         NEXT k
         LET tb(i,J)=0 !元に戻す
         LET numpre=FALSE
         EXIT FUNCTION
      END IF
   NEXT J
NEXT i
MAT PRINT tb; !結果を表示する
LET numpre=TRUE
END FUNCTION

 

数独

 投稿者:永野護  投稿日:2014年 9月24日(水)10時03分18秒
  わかりやすい解説ありがとうございました。
お忙しい中、恐縮です。
敬具
 

Re: 数独

 投稿者:SECOND  投稿日:2014年10月 2日(木)16時43分55秒
  > No.3508[元記事へ]

エピソード
先の投稿「山中 氏 投稿から引用」文でも、以下の様に、完成結果を、
false で帰してやると、 複数個の解を全て表示できます。

1個の解の表示しか出来ないプログラムでも「最後の枡を埋める」局面をみると、
1つ手前までの全ての解を展開して、再試行しており、それを1段延長させる。
「最後の枡で完成」していても、表示だけに留め、常に失敗したように帰す。と、
取り得る完成 全てを果す、ついには、枡(0,0) より食み出て 探索しようとするが、
再帰の場合、リターンスタックは、メインだけになり、false で、正常終了する。

(
  )
EXTERNAL FUNCTION numpre(dummy)
(
  )
!1個の解の表示で終らせる
!------------------------------
MAT PRINT tb; !結果を表示する
LET numpre=TRUE      !←構造的には、これを、false にするのみ
END FUNCTION         !↓見やすくするだけの意味。
!------------------------------

! 複数個の解を全て表示
!------------------------------
LET cnt=cnt+1        !メイン側に、PUBLIC NUMERIC cnt を追加しないと、
PRINT cnt            !外部関数内の変数は、原則 localで、cnt 累計不能
MAT PRINT tb;        !結果を表示する
PRINT "次の探索中";
!
LET numpre=FALSE     !完成しなかった事にして、再サーチさせる
END FUNCTION
!------------------------------

!------------------------------
「lark12_long 氏 投稿から引用」このサンプルは、短時間で70個、テストに好適
!例題2 複数解あり
DATA 2,8,4,0,0,0,0,7,9
DATA 1,0,0,0,4,8,5,0,6
DATA 0,9,0,0,0,2,0,0,1
DATA 0,4,8,0,0,0,0,0,0
DATA 0,2,0,0,0,0,0,3,0
DATA 0,0,0,0,0,0,1,0,0
DATA 0,0,0,3,0,0,0,9,0
DATA 0,0,7,6,8,0,0,0,4
DATA 0,5,0,0,0,0,6,1,3
 

戻る