第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 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
dhs(3,5,i3) | × | × | × | ○ | × | ○ | × | × | × |
となります。そして、パーツAによってさらに列
*4 |
** |
** |
** |
5 |
** |
** |
** |
** |
に4,5が入っているという認識が加わり、
i3+1 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
dhs(3,5,i3) | × | × | × | ○ | ○ | ○ | × | × | × |
となります。さらに、パーツBによって
** |
の入っているブロック
** | 4 | ** |
1 | ** | 5 |
** | 8 | ** |
には1,8が入っているという認識が加わり、
i3+1 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
*dhs(3,5,i3) | ○ | × | × | ○ | ○ | ○ | × | ○ | × |
となります。○×を反転させると候補リストになります。
i3+1 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
*候補リスト | × | ○ | ○ | × | × | × | ○ | × | ○ |
そして、問題解析の最後のパーツ
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
によって、座標(3,5)のセルの候補リスト
i3 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
dhs1(3,5,i3) | 2 | 3 | 7 | 9 | 0 | 0 | 0 | 0 | 0 |
ができあがります。cnn(3, 5)は、実際に入れることのできる数字の最大個数
(これは結局2つ上の表の○の個数)で4です。
実際には、
i3+1 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
*dhs(3,5,i3) | ○ | × | × | ○ | ○ | ○ | × | ○ | × |
は、プログラム上では
i3 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
*dhs(3,5,i3) | 1 | 0 | 0 | 1 | 1 | 1 | 0 | 1 | 0 |
であることに注意して、トレースしてみましょう。
まず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 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
dhs1(3,5,i3) | 2 | 3 | 7 | 9 | 0 | 0 | 0 | 0 | 0 |
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では、問題解析をした結果、座標(3,5)のセルには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)
現在座標(3,5)のセルにいて、mx = cnn(3, 5) = 4です。したがって、mx - 1=3なので、
For文で試行されるのは
k | 0 | 1 | 2 | 3 |
dhs1(3,5,k) | 2 | 3 | 7 | 9 |
の部分だけで、2,3,7,9だけが試行されるわけです。
Ver(−1)では1,4,5,6,8も試行されていたので、Ver0でかなり無駄が排除され効率的になっていることがわかります。
第6話へ 第11講第1話へ
VB入門講義応用編トップへ
VB入門講義トップへ