第10講 数独の問題を解くプログラムVer0
第6話 「If mah(i1, i2) = 0 Then ・・・ End Ifでは何がなされているの?」その3
For i3 = 0 To 8
If i1 <> i3 And mah(i3, i2) > 0 Then dhs(i1,
i2, mah(i3, i2) - 1) = 1
Next
で何をしているかはもうおわかりでしょう。前は、対象のセルの行についての処理でしたが、
今回は列についての処理です。
同じく(3,5)を例に取ると、今回は
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | |
0 | ** | ** | ** | ** | ** | *4 | *5 | *8 | ** |
1 | 4 | 9 | ** | ** | ** | ** | ** | 6 | ** |
2 | 8 | ** | 1 | ** | 2 | ** | 4 | ** | ** |
3 | 6 | ** | ** | ** | 4 | ** | ** | ** | ** |
4 | ** | ** | 2 | 1 | ** | 5 | 8 | ** | ** |
5 | ** | ** | ** | ** | 8 | ** | ** | ** | 9 |
6 | ** | ** | 8 | ** | 5 | ** | 3 | ** | 7 |
7 | ** | 7 | ** | ** | ** | ** | ** | 4 | 6 |
8 | ** | 4 | 9 | 2 | ** | ** | ** | ** | ** |
の
*4 |
** |
** |
** |
5 |
** |
** |
** |
** |
4と5のところを動いていきます。
** |
が除かれる理由はIf i1 <> i3 And mah(i3, i2) > 0 Then dhs(i1, i2, mah(i3, i2) - 1) = 1
のピンクにあります。また、空欄
** |
が除かれるはIf i1 <> i3 And mah(i3, i2) > 0 Then dhs(i1, i2, mah(i3, i2) - 1) = 1
の青によります。
For i3 = 0 To 8
If i2 <> i3 And mah(i1, i3) > 0 Then dhs(i1,
i2, mah(i1, i3) - 1) = 1
Next
のときにすでに
i3 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
dhs(3,5,i3) | 0 | 0 | 0 | 1 | 0 | 1 | 0 | 0 | 0 |
になっているので今回の動きでdhs(3,5,4)=1が加わり、
i3 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
dhs(3,5,i3) | 0 | 0 | 0 | 1 | 1 | 1 | 0 | 0 | 0 |
となります。
そして、次に一番難解な
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 dhs(i1, i2, mah(3 * i1s + i3, 3 * i2s + i4) - 1) = 1
Next
Next
の部分に到達しました。同じ例(3,5)で考えてみましょう。
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | |
0 | ** | ** | ** | ** | ** | *4 | *5 | *8 | ** |
1 | 4 | 9 | ** | ** | ** | ** | ** | 6 | ** |
2 | 8 | ** | 1 | ** | 2 | ** | 4 | ** | ** |
3 | 6 | ** | ** | ** | 4 | ** | ** | ** | ** |
4 | ** | ** | 2 | 1 | ** | 5 | 8 | ** | ** |
5 | ** | ** | ** | ** | 8 | ** | ** | ** | 9 |
6 | ** | ** | 8 | ** | 5 | ** | 3 | ** | 7 |
7 | ** | 7 | ** | ** | ** | ** | ** | 4 | 6 |
8 | ** | 4 | 9 | 2 | ** | ** | ** | ** | ** |
今回は
1 | ** |
** | 8 |
の1,8の部分を動いていきます。
非常に理解困難な場所だと思いますので、一つ一つトレースしていきます。
現在i1=3,i2=5なので、i1s = Int(i1 / 3)はInt(3/3)=Int(1)=1になり、
i2s = Int(i2 / 3)もInt(5/3)=Int(1)=1です。
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 dhs(i1, i2, mah(3 * i1s + i3, 3 * i2s + i4) - 1) = 1
Next
Next
の部分の展開を一つ一つ追ってみましょう。まず、i3 = 0,i4 = 0ですから
3 * i1s + i3 = 3*1+0 =3
3 * i2s + i4 = 3*1+0 = 3
で3 * i1s + i3 <> i1 And 3 * i2s + i4 <> i2の条件の赤のところをクリアできません。
現在i1=3であったからです。
よって、For文によりi3 = 0,i4 = 1となります。すると、
3 * i1s + i3 = 3*1+0 =3
3 * i2s + i4 = 3*1+1 =4
となりますが、これも3 * i1s + i3 <> i1 And 3 * i2s + i4 <> i2の赤に抵触します。
同様にi3 = 0,i4 = 2も条件に反し、i4の1回目のループが終わます。
要するにi3 = 0のときは
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | |
0 | ** | ** | ** | ** | ** | *4 | *5 | *8 | ** |
1 | 4 | 9 | ** | ** | ** | ** | ** | 6 | ** |
2 | 8 | ** | 1 | ** | 2 | ** | 4 | ** | ** |
3 | 6 | ** | ** | ** | 4 | ** | ** | ** | ** |
4 | ** | ** | 2 | 1 | ** | 5 | 8 | ** | ** |
5 | ** | ** | ** | ** | 8 | ** | ** | ** | 9 |
6 | ** | ** | 8 | ** | 5 | ** | 3 | ** | 7 |
7 | ** | 7 | ** | ** | ** | ** | ** | 4 | 6 |
8 | ** | 4 | 9 | 2 | ** | ** | ** | ** | ** |
*6 | ** | ** | ** | *4 | ** | ** | ** | ** |
の行に対応しますが、ここでは処理は行われないようしているのです。なぜなら、この行についてはすでに
For i3 = 0 To 8
If i2 <> i3 And mah(i1, i3) > 0 Then dhs(i1,
i2, mah(i1, i3) - 1) = 1
Next
ですでに処理されているからです。
2重チェックしても問題はありませんが、スピード優先のため2重チェックしないようにしているのです。
そして、i3の2回目のループが始まりi3 = 1,i4 = 0となり、
3 * i1s + i3 = 3*1+1 =4
3 * i2s + i4 = 3*1+0 =3
となりはじめて条件3 * i1s + i3 <> i1 And 3 * i2s + i4 <> i2をクリアします。
そして、mah(3 * i1s + i3, 3 * i2s + i4)=mah(4, 3)=1より条件
mah(3 * i1s + i3, 3 * i2s + i4) > 0もクリアして、If分がはじめて実行されます。
そして、dhs(i1, i2, mah(3 * i1s + i3, 3 * i2s + i4) - 1) = dhs(3, 5,1 - 1) = dhs(i1,
i2, mah(4, 3) - 1) = = dhs(3, 5,0) = 1
となるのです。つまり、
** |
の入っているブロック
** | 4 | ** |
1 | ** | 5 |
** | 8 | ** |
には、
*1 |
の1(=0+1)が入っていることが認識されたのです。
次のi3 = 1,i4 = 1だと
3 * i1s + i3 = 3*1+1 =4
3 * i2s + i4 = 3*1+1 =4
で
** | 4 | ** |
1 | ** | 5 |
** | 8 | ** |
1の右隣で空欄なので条件mah(3 * i1s + i3, 3 * i2s + i4) > 0
をクリアできず、If文は実行されません。
i3 = 1,i4 = 2だと
3 * i1s + i3 = 3*1+1 =4
3 * i2s + i4 = 3*1+2 =5
条件で3 * i2s + i4 <> i2(i2は5でした。)をクリせず、If文は実行されません。
i4の2回目のループが終わり、
i3 = 2,i4 = 0
これは1の下(すなわち8の左隣)で空欄ですからmah(3 * i1s + i3, 3 * i2s + i4) > 0
をクリアできず
i3 = 2,i4 = 1となり
3 * i1s + i3 = 3*1+2 =5
3 * i2s + i4 = 3*1+1 =4より
*8 |
の欄に対応してmah(3 * i1s + i3, 3 * i2s + i4)=mah(5, 4)=8
となりIf文が実行されdhs(i1, i2, mah(3 * i1s + i3, 3 * i2s + i4) - 1) = dhs(5, 4,8 - 1) = dhs(i1,
i2, mah(5, 4) - 1) == dhs(3, 5,8) = 1
となり
** |
の入っているブロック
** | 4 | ** |
1 | ** | 5 |
** | 8 | ** |
には、
*8 |
の8(=8+1)が入っていることが認識されます。
最後のi3 = 2,i4 = 2は8の右隣で、3 * i2s + i4 <> i2
をクリアせず実行されません。
i4 = 2は
*4 |
** |
** |
** |
5 |
** |
** |
** |
** |
に対応するわけですが、ここの部分についても条件3 * i2s + i4 <> i2によって処理を行わないようにしています。
For i3 = 0 To 8
If i1 <> i3 And mah(i3, i2) > 0 Then dhs(i1,
i2, mah(i3, i2) - 1) = 1
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 dhs(i1, i2, mah(3 * i1s + i3, 3 * i2s + i4) - 1) = 1
Next
Next
では
1 | ** |
** | 8 |
の1と8のところだけを動いていくことがおわかり頂けたでしょうか。
第5話へ 第7話へ
VB入門講義応用編トップへ
VB入門講義トップへ