第10講 数独の問題を解くプログラムVer0
第7話 まとめ
ここでは問題解析のまとめをして、Sub sakuseiの変更点について説明して第10講の締めとします。
For i3 = 0 To 8
  If i2 <> i3 And mah(i1, i3) > 0 Then dhs(i1, i2, mah(i1, i3) - 1) = 1          ・・・@
Next
For i3 = 0 To 8
  If i1 <> i3 And mah(i3, i2) > 0 Then dhs(i1, i2, mah(i3, i2) - 1) = 1          ・・・A     
Next

i1s = Int(i1 / 3)
i2s = Int(i2 / 3)
For i3 = 0 To 2
  For i4 = 0 To 2
    If 3 * i1s + i3 <> i1 And 3 * i2s + i4 <> i2  *(実際にはここで改行はなし)
    And mah(3 * i1s + i3, 3 * i2s + i4) > 0 Then *(実際にはここで改行はなし)  ・・・B
    dhs(i1, i2, mah(3 * i1s + i3, 3 * i2s + i4) - 1) = 1
  Next
Next

まずパーツ@によって

**

の入っている行には

*6 ** ** ** *4 ** ** ** **

6,4が入っていることが認識され

i3+1
dhs(3,5,i3) × × × × × × ×

となります。そして、パーツAによってさらに列

*4
**
**
**
5
**
**
**
**

に4,5が入っているという認識が加わり、

i3+1
dhs(3,5,i3) × × × × × ×

となります。さらに、パーツBによって

**

の入っているブロック

** 4 **
1 ** 5
** 8 **

には1,8が入っているという認識が加わり、

i3+1
*dhs(3,5,i3) × × × ×

となります。○×を反転させると候補リストになります。

i3+1
*候補リスト × × × × ×


そして、問題解析の最後のパーツ
For i3 = 0 To 8
  If dhs(i1, i2, i3) = 0 Then
   w = cnn(i1, i2)
   dhs1(i1, i2, w) = i3 + 1
   cnn(i1, i2) = cnn(i1, i2) + 1
  End If
Next

によって、座標()のセルの候補リスト

i3
dhs1(3,5,i3)

ができあがります。cnn(3, 5)は、実際に入れることのできる数字の最大個数
(これは結局2つ上の表の○の個数)で4です。

実際には、

i3+1
*dhs(3,5,i3) × × × ×

は、プログラム上では

i3
*dhs(3,5,i3)

であることに注意して、トレースしてみましょう。
まずi3=0のとき、dhs(3,5,0)=1で条件dhs(i1, i2, i3) = 0をクリアできず、
  If dhs(i1, i2, i3) = 0 Then
   w = cnn(i1, i2)
   dhs1(i1, i2, w) = i3 + 1
   cnn(i1, i2) = cnn(i1, i2) + 1
  End If

は実行されません。次にi3=1となり、dhs(3,5,1)=0で条件dhs(i1, i2, i3) = 0をクリアし、
初期化によってcnn(i1, i2)は0だったので、w = 0となります。よって、次の2行で、
dhs1(3, 5, 0) = 2(なぜならi3+1=1+1=2),cnn(i1, i2) = 1となります。
3回目のループでi3=2となり、dhs(3,5,2)=0で条件dhs(i1, i2, i3) = 0をクリアし、w = 1,dhs1(3, 5, 1) = 3,cnn(i1, i2) = 2
以下
i3=3でdhs(3,5,3)=1で条件dhs(i1, i2, i3) = 0をクリアできずIf文は実行されません。
i3=4でdhs(3,5,4)=1で条件dhs(i1, i2, i3) = 0をクリアできずIf文は実行されません。
i3=5でdhs(3,5,5)=1で条件dhs(i1, i2, i3) = 0をクリアできずIf文は実行されません。
i3=6でdhs(3,5,6)=0で条件dhs(i1, i2, i3) = 0をクリアし、If文が実行され
    w = 2,dhs1(3, 5, 2) = 7,cnn(i1, i2) = 3
i3=7でdhs(3,5,7)=1で条件dhs(i1, i2, i3) = 0をクリアできずIf文は実行されません。
i3=8でdhs(3,5,6)=0で条件dhs(i1, i2, i3) = 0をクリアし、If文が実行され
    w = 3,dhs1(3, 5, 3) = 9,cnn(i1, i2) = 4
のように処理され、最終的に

i3
dhs1(3,5,i3)

cnn(i1, i2) = 4となるのです。


さて、Sub sakuseiの変更点の意味は何でしょう。
Sub sakusei(g As Integer)
           ・
           ・
           ・ 
  mx = cnn(i, j)
  For k = 0 To mx - 1
    mah(i, j) = dhs1(i, j, k)
          ・
          ・
          ・
End Sub

Ver(−1)では
For k = 1 To 9        (n*nとなっていますがn=3ですので、実際にはn*nは9です。)
  mah(i, j) = k
でそれぞれのセルに1から9までの数字を入れていました。
Ver0では、問題解析をした結果、座標()のセルには2,3,7,9しか入れられないことがわかっています。
したがって、1,4,5,6,8の試行はする必要がないのです。
mx = cnn(i, j)
For k = 0 To mx - 1
  mah(i, j) = dhs1(i, j, k)

現在座標()のセルにいて、mx = cnn(3, 5) = 4です。したがって、mx - 1=3なので、
For文で試行されるのは

k
dhs1(3,5,k)

の部分だけで、2,3,7,9だけが試行されるわけです。
Ver(−1)では1,4,5,6,8も試行されていたので、Ver0でかなり無駄が排除され効率的になっていることがわかります。


第6話へ 第11講第1話へ
VB入門講義応用編トップへ

VB入門講義トップへ