第5話 再帰的呼び出しプログラムの解説その4

やっと「再帰的呼び出しプログラム」の解説にたどりつくことができました。
解説対象は、改良版の
再帰的呼び出しによる順列の作成
としたいと思います。
こちらの方が、普遍性があって1から12までの順列の作成ができるからです。理論的には上限の方は12にする必要はなく、
20ぐらいでもいいのですが作成時間がかかりますので、
とりあえず12としてあります。
プログラムソースを見てみましょう。

Dim jyn(12), n As Integer
Dim sousuu As Long

Private Sub CommandButton1_Click()

  n = Cells(2, 11)
  sousuu = 0
  jyunretusakusei (1)

End Sub

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

Sub hyouji()
  sousuua = sousuu Mod 20
  sousuus = Int(sousuu / 20)
  sousuu = sousuu + 1
  If sousuu = 1 Then
    Range("m3:o3").Select
    With Selection
      .HorizontalAlignment = xlGeneral
      .VerticalAlignment = xlCenter
      .WrapText = False
      .Orientation = 0
      .AddIndent = False
      .IndentLevel = 0
      .ShrinkToFit = False
      .ReadingOrder = xlContext
      .MergeCells = True
    End With
    Cells(3, 10) = "順列総数"
    Cells(2, 1).Select
  End If
  Cells(3, 13) = sousuu
  For j = 1 To n
    Cells(5 + sousuus * 2, 1 + j + sousuua * (n + 1)) = jyn(j)
  Next

End Sub

とfor文タイプに比べると著しく簡単です。
しかも、最初に述べたように
for文タイプが3次のみであるのに対して
1次から12次まで順列を作ることができるという普遍性があります。
さらに加えて、for文タイプは
例えば3次から4次に変更するにはプログラムソースをいじらなければなりません。
12次にしてしまうと、
12次元ループで記述が大変面倒になります。
それに比べて、再帰的呼び出しの方は著しく簡単です。

さて、1行1行解説していきましょう。
Dim jyn(12) As Integer, n As Integer
Dim sousuu As Long
はメインのプログラムの前に記述されています。
これはjyn(12)、n、sousuuをグローバル変数にするためです。
Visual Basicでは構造化プログラミングが徹底していて、
メインプロシージャもSubプロシージャも個々の部品として独立していて、
変数のそれぞれのプロシージャ内で変数を宣言しても、
他のプロシージャの中でその同名の変数を使おうとすると、
その変数は宣言されていませんとエラー表示が出てきてしまいます。
不便なようですが、
他のプロシージャで変数の値が書き換えられる心配がないので、
そのプロシージャのみの開発に専念できます。
かつてのBasicでは変数の値が
他のSnbプログラムで書き換えられてしまうので、
プログラム全体を見ていないと個々のSubプログラムを組むことができなかったのです。
全体がスパゲティのように入り組みわかりにくいプログラムになるし、
多数の人がSubを担当して分業することができないという欠点があったのです。
変数がたとえ同名であったとしてもプロシージャ内だけでしか通用しないという点は、
以上のような利点があるわけですが、
場合によってはすべてのプロシージャ内で通用する変数が必要なときもあります。
つまり、プログラム全体で通用する変数を使いたい場合もあるわけです。
プログラム全体で通用する変数をグローバル変数といいます。
グローバル変数を宣言するには、
プログラムの冒頭で上のように記述すればよいのです。
次にメインプロシージャ
Private Sub CommandButton1_Click()

  n = Cells(2, 11)
  sousuu = 0
  jyunretusakusei (1)

End Sub
を見ましょう。
n = Cells(2, 11)はいちいちプログラムソースを
いじらなくてもエクセルのシート上から何次かを指定できるようにしたものです。
Cells(2, 11)はエクセルのシート上ではK2ですから、
ここに例えば、8の入力して実行ボタンを押せば、
変数nに8が収納され、8次順列が作成されるようになっています。
sousuu = 0
はsousuuの初期値を0としています。
ただし、記述がない場合デフォルトは0と見なされますので、
この1行はカットしても差し支えありません。
しかし、0であってもなるべく最初に書いておきたいところです。
理由は、前にプログラムを走らせたときの記憶が残り、
0以外の値が入ってしまう場合があるからです。
jyunretusakusei (1)
ではSubプロシージャjyunretusakusei (g As Integer)
を呼び出しています。
引数gの値は1としています。
引数gの意味が何で、何故1なのかの説明は
Sub jyunretusakusei(g As Integer)

   ・
   ・
   ・

End Sub
の部分の説明のときにしたいと思います。

ではかなり長くなったので、本日はここまでとしたいと思います。
明日もぜひお越しいただければと思います。


第4話へ 第6話へ