第2講 試行錯誤法でヒント数0数独の解答を作る(1)
第6話 n次順列をSubプロシージャで自動生成させるための考え方
Subプロシージャでn次順列を自動生成させるためのヒントを説明するために、
第4話の5次順列自動生成ソフトの主要部分に色を付けて再掲しましょう。
Sub f()

  Dim i As Integer, j As Integer, k As Integer
  Dim l As Integer, m As Integer, n As Integer
  Dim cn As Integer
  Dim a(5) As Integer
  cn = 0
  
For i = 1 To 5
    
a(0) = i
    
For j = 1 To 5
      If j <> a(0) Then
        a(1) = j

        
For k = 1 To 5
          If k <> a(0) And k <> a(1) Then
            a(2) = k

            
For l = 1 To 5
              If l <> a(0) And l <> a(1) And l <> a(2) Then
                a(3) = l

                
For m = 1 To 5
                  If m <> a(0) And m <> a(1) And m <> a(2) And m <> a(3) Then
                    a(4) = m
                    Call g(cn, a())
                    cn = cn + 1
                  End If
                Next

             
 End If
            Next

          
End If
        Next

      
End If
    Next

  
Next
  
End Sub

色を付けたのは同じことを繰り返していることを強調するためです。
同じことの繰り返しだからこそプロシージャの再帰的使用が向いているわけです。
a(0) = i
 a(1) = j  a(2) = k a(3) = l a(4) = m 

を再帰的使用でやるときには、i,j,k,l,mの部分はすべて同じiでよいことになります。
問題は引数を何にするかです。
引数は()中の数字です。
(0) (1)  (2) (3) (4) 
は何を表しているかと申しますと、
セル(ます)の順番です。
順列12345を例に説明しますと、

0 1 2 3 4
1 2 3 4 5

のピンクに対応します。
プログラミングの世界では順番は普通0から数え始めます。
ですから、普通の意味での
1番目2番目3番目4番目5番目
は、プログラミングの世界では、
0番目1番目2番目3番目4番目
となるのでしたね。
大切なことはセルを表す番号(順番)とセルの内容である数字を区別することです。
これ以降はセルを箱で比喩することにしますと、
箱の番号と箱の中身を区別するという意味になります。

0 1 2 3 4
1 2 3 4 5

番目の箱にはという数字が入り、
番目の箱にはという数字が入り、
          ・
          ・
番目の箱にはという数字が入る
ということです。
ピンクと青は似ているのでうっかりすると混同します。
ですが、箱の番号と箱の中身を明確に区別しないと頭が混乱します。
くどいようですが、繰り返します。
箱の番号と箱に入っている中身の数字を明確に区別してください。

でないと再帰的使用によってn次順列自動生成を成功させることは出来ません。

引数は箱(セル)の番号にすればよいのです。
そして、Subプロシージャの中で中身である数字を箱に埋めていけばよいのです。
x(15)(箱に相当)というByte型のグローバル配列を用意して、Subプロシージャの中で数字を入れていってください。
今回もグローバルにするのはなるべくコードを簡単にするためです。
1から9までの数字を入れていくのが数独ですから、
本来は要素数は8で充分ですが、
要素数を15にしておくのは、
数独の自動生成のスピードをアップさせるために、
魔方陣の自動生成を参考にするからです。
3次魔方陣は簡単にできますが、
4次になると時間がかかります。
全部で7040個も存在することが理由の1つです。
これを高速に生成することに成功すれば、
数独に応用して高速の数独自動生成アプリを作ることが出来るのです。

サイトによっては32ビット処理であるから容量の小さな変数を用意する必要はないと書いてありますが、
私の実験によると変数の容量に反比例するのです。
ですから、なるべく容量の小さな変数を用意した方がよいので、すべてByte型にします。
反比例と書きましたが、スピードアップは数倍のレベルではありません。
かなり速くなります。
ただし、順列数を数える変数はInteger型にします。
9!=362880であるからです。
これもコードを簡単にするためにグロバール変数にしておきましょう。
では皆さん、プロシージャの再帰的使用によってn次順列自動生成ソフトを開発してください。

001

x(15)としましたので理論的には、10次以上の順列が自動生成できますが、
時間がかかりすぎますので現実的には9次辺りが限界です。




第5話へ 第7話へ


トップへ