第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の意味ですが、

gは順列を作っていく際のマスの位置を示しています。
最初は、1番目のマスに1から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からn(今の前提では3)の数字を入れています。
ですからループの1番目で、jyn(1) = 1が実行され、

となるわけです。

現在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)によって、

の青の世界(=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となり

        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

となりますが、もちろん
        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

となり、最初の順列ができあがります。
gは3ですから、
      If g < n Then
        jyunretusakusei (g + 1)
      Else
        hyouji
      End I
はhyoujiの部分が実行されシートに表示されます。
そして1回目のピンクの世界(すなわち、jyunretusakusei (3)の世界)は終了となり、
青の世界(すなわち、jyunretusakusei (2)の世界)に戻ります。
青世界のnextによって、jyn(2) = 3

となります。
        If jyn(g) = jyn(j) Then
          h = 0
          Exit For
        End
をクリアして再びピンクの世界(すなわち、jyunretusakusei (3)の世界)に飛びます。
for文の1度目によりjyn(3) = 1

になりますが、もちろん
        If jyn(g) = jyn(j) Then
          h = 0
          Exit For
        End

によって、h = 0となり、2度目のループになりjyn(3) = 2

で2個目の順列ができあがります。
ピンク世界のnextによって、jyn(3) = 3

ですが、
        If jyn(g) = jyn(j) Then
          h = 0
          Exit For
        End

をクリアできずピンク世界2回目のループが終了となり、青世界に戻ります。
青世界も1回目のループが終わり
緑の世界(すなわち、jyunretusakusei (1)の世界)に戻ります。
緑世界2度目のループのよってjyn(1) = 2

となった後、再び青世界に飛びます。
2回目の青世界の1度目のループによってjyn(2) = 1

これは
        If jyn(g) = jyn(j) Then
          h = 0
          Exit For
        End

をクリアし、ピンク世界(すなわち、jyunretusakusei (3)の世界)への3回目の跳躍となります。
ピンク世界の1度目、2度目のループでそれぞれjyn(2) = 1、jyn(2) = 2

        If jyn(g) = jyn(j) Then
          h = 0
          Exit For
        End

によって、h = 0ですぐに3回目ピンク世界の3度目のループによってjyn(3) = 3

となりまして3個目の順列が完成します。
ピンク世界のループは終わり、
2回目の青世界の2度目のループでjyn(2) = 2

        If jyn(g) = jyn(j) Then
          h = 0
          Exit For
        End

によって3度目のループになりjyn(2) = 3

        If jyn(g) = jyn(j) Then
          h = 0
          Exit For
        End

をクリアしてピンク世界への4回目の跳躍となります。
4回目のピンク世界の1度目のループによってjyn(3) = 1

で4個目の順列の完成です。
2度目、3度目のループでjyn(3) = 2、jyn(3) = 3

        If jyn(g) = jyn(j) Then
          h = 0
          Exit For
        End

をクリアできず、2回目の青世界へ戻り2回目の青世界は終了となり、また直ちに緑世界に戻ります。
そして、3度目のループによってjyn(1) = 3

で3回目の青世界に跳躍し、1度目のループでjyn(2) = 1

5回目のピンク世界の2度目のループでjyn(3) = 2

5個目の順列
3回目の青世界の2度目のループと6回目の1度目のループによって

で6個目の順列ができます。
残りは
        If jyn(g) = jyn(j) Then
          h = 0
          Exit For
        End

をクリアできないので、
これが最後の順列と言うことになります。
残りのhyoujiの部分は実質的に説明を終了していますので(第11講第4話参照)、
以上で再帰的呼び出しの解説を終わりにしたいと思います。
長い間おつきあいいただきありがとうございます。


第5話へ 第7話へ