第6話 再帰的呼び出しプログラムの解説その2
いよいよ佳境に入ります。
Sub jyunretusakusei(g As Integer)
Dim i As Integer, j As Integer, h As Integer
For i = 1 To n
jyn(g) = i
h = 1
If g > 1 Then
For j = 1 To g - 1
If jyn(g) = jyn(j) Then
h = 0
Exit For
End If
Next
End If
If h = 1 Then
If g < n Then
jyunretusakusei (g + 1)
Else
hyouji
End If
End If
Next
End Sub
この部分こそが、再帰的呼び出しと呼ばれる所以です。
n=3を前提に解説を進めましょう。
前回予告したgの意味ですが、
1 | 2 | 3 |
gは順列を作っていく際のマスの位置を示しています。
最初は、1番目のマスに1から3まで数字を入れたいので、
1 | 2 | 3 |
g=1となっているわけです。
それがメインプロシージャ内で記述がjyunretusakusei (1)となっていた理由です。
つまり、1番目のマスを対象にSubプロシージャjyunretusakusei (g As Integer)を
実行しなさいと命じているわけです。
私はすべての魔方陣プログラムにおいてマスの位置をgで表しています
(もっとも1番目は0としています。配列は0から始まるからです。
ここでは、初心者の方が混乱しないように1番目のマスを1で表しています。)。
これは、私が最初C言語から魔方陣プログラムに入ったと言うことが背景にあります。
できた魔方陣をディスプレイの画面に表示させていたので、
画面位置のつもりでgを当てていたのです。
本当は、1字だけの変数名はよろしくありません。
他の人が見たときに何の変数だかわからないからです。
現在でもそうですが特にC言語でプログラムを書いていたときは、
タイピングの腕が悪く(本サイトにおいてミスが多いのはそれが原因です。)、
変数名が長いと打つのに時間がかかるし、
タイピングミスをするので、
短い変数名を使う悪癖がついてしまったのです。
皆さんは、この点については是非見習わないで頂きたいと思います。
Visual Basicでは変数名に漢字を使うこともできますので、
gは「順列位置」などの変数名を使うといいかもしれませんね。
さて、
For i = 1 To n
・
・
Next
では
1 | 2 | 3 |
の緑の位置に1からn(今の前提では3)の数字を入れています。
ですからループの1番目で、jyn(1) = 1が実行され、
1 | 2 | 3 |
となるわけです。
現在gは1ですから
h = 1
If g > 1 Then
For j = 1 To g - 1
If jyn(g) = jyn(j) Then
h = 0
Exit For
End If
Next
End If
のピンク部分は実行されませんのでhは1のままで、
If h = 1 Then
If g < n Then
jyunretusakusei (g + 1)
Else
hyouji
End If
End If
が実行されます。
そしてもちろん、g < nは1 < 3で満たしていますので、
jyunretusakusei (g + 1)すなわちjyunretusakusei (2)が呼び出されます。
再帰的呼び出しでは現在jyunretusakusei (2)の世界にいるのか、
jyunretusakusei (1)の世界にいるのか常に意識していないと訳がわからなくなります。
とにかく、jyunretusakusei (2)によって、
1 | 2 | 3 |
の青の世界(=jyunretusakusei (2)の世界)に入ります。
青の世界の
For i = 1 To n
・
・
Next
によって、1番目のループが実行され、
jyn(2) = 1となります。
gは現在2(つまり青の世界)ですから
h = 1
If g > 1 Then
For j = 1 To g - 1
If jyn(g) = jyn(j) Then
h = 0
Exit For
End If
Next
End If
のピンクが実行されます。
そして、jyn(2) もjyn(1)も1ですから
If jyn(g) = jyn(j) Then
h = 0
Exit For
End If
によって、h = 0となり
If h = 1 Then
If g < n Then
jyunretusakusei (g + 1)
Else
hyouji
End If
End If
は実行されません。
そして、Nextによって青世界の2番目のループに入ります。
そして、jyn(2) = 2となり
1 | 2 | 3 |
If jyn(g) = jyn(j) Then
h = 0
Exit For
End If
をクリアして
If h = 1 Then
If g < n Then
jyunretusakusei (g + 1)
Else
hyouji
End If
End If
が実行され、
最後のピンクの世界(すなわち、jyunretusakusei (3)の世界)に入ります。
そして、 ピンクの世界の
For i = 1 To n
・
・
Next
ループ文の1番目と2番目でjyn(3) = 1、jyn(3) = 2
1 | 2 | 1 |
1 | 2 | 2 |
となりますが、もちろん
If jyn(g) = jyn(j) Then
h = 0
Exit For
End
によって、h = 0で
If h = 1 Then
If g < n Then
jyunretusakusei (g + 1)
Else
hyouji
End If
End If
は実行されず、3番目のループによって、jyn(3) = 2
1 | 2 | 3 |
となり、最初の順列ができあがります。
gは3ですから、
If g < n Then
jyunretusakusei (g + 1)
Else
hyouji
End I
はhyoujiの部分が実行されシートに表示されます。
そして1回目のピンクの世界(すなわち、jyunretusakusei (3)の世界)は終了となり、
青の世界(すなわち、jyunretusakusei (2)の世界)に戻ります。
青世界のnextによって、jyn(2) = 3
1 | 3 | 3 |
となります。
If jyn(g) = jyn(j) Then
h = 0
Exit For
End
をクリアして再びピンクの世界(すなわち、jyunretusakusei (3)の世界)に飛びます。
for文の1度目によりjyn(3) = 1
1 | 3 | 1 |
になりますが、もちろん
If jyn(g) = jyn(j) Then
h = 0
Exit For
End
によって、h = 0となり、2度目のループになりjyn(3) = 2
1 | 3 | 2 |
で2個目の順列ができあがります。
ピンク世界のnextによって、jyn(3) = 3
1 | 3 | 3 |
ですが、
If jyn(g) = jyn(j) Then
h = 0
Exit For
End
をクリアできずピンク世界2回目のループが終了となり、青世界に戻ります。
青世界も1回目のループが終わり
緑の世界(すなわち、jyunretusakusei (1)の世界)に戻ります。
緑世界2度目のループのよってjyn(1) = 2
2 | 3 | 3 |
となった後、再び青世界に飛びます。
2回目の青世界の1度目のループによってjyn(2) = 1
2 | 1 | 3 |
これは
If jyn(g) = jyn(j) Then
h = 0
Exit For
End
をクリアし、ピンク世界(すなわち、jyunretusakusei (3)の世界)への3回目の跳躍となります。
ピンク世界の1度目、2度目のループでそれぞれjyn(2) = 1、jyn(2) = 2
2 | 1 | 1 |
2 | 1 | 2 |
If jyn(g) = jyn(j) Then
h = 0
Exit For
End
によって、h = 0ですぐに3回目ピンク世界の3度目のループによってjyn(3) = 3
2 | 1 | 3 |
となりまして3個目の順列が完成します。
ピンク世界のループは終わり、
2回目の青世界の2度目のループでjyn(2) = 2
2 | 2 | 3 |
If jyn(g) = jyn(j) Then
h = 0
Exit For
End
によって3度目のループになりjyn(2) = 3
2 | 3 | 3 |
If jyn(g) = jyn(j) Then
h = 0
Exit For
End
をクリアしてピンク世界への4回目の跳躍となります。
4回目のピンク世界の1度目のループによってjyn(3) = 1
2 | 3 | 1 |
で4個目の順列の完成です。
2度目、3度目のループでjyn(3) = 2、jyn(3) = 3
2 | 3 | 2 |
2 | 3 | 3 |
If jyn(g) = jyn(j) Then
h = 0
Exit For
End
をクリアできず、2回目の青世界へ戻り2回目の青世界は終了となり、また直ちに緑世界に戻ります。
そして、3度目のループによってjyn(1) = 3
3 | 3 | 2 |
で3回目の青世界に跳躍し、1度目のループでjyn(2) = 1
3 | 1 | 2 |
5回目のピンク世界の2度目のループでjyn(3) = 2
3 | 1 | 2 |
5個目の順列
3回目の青世界の2度目のループと6回目の1度目のループによって
3 | 2 | 1 |
で6個目の順列ができます。
残りは
If jyn(g) = jyn(j) Then
h = 0
Exit For
End
をクリアできないので、
これが最後の順列と言うことになります。
残りのhyoujiの部分は実質的に説明を終了していますので(第11講第4話参照)、
以上で再帰的呼び出しの解説を終わりにしたいと思います。
長い間おつきあいいただきありがとうございます。