第9講 プロシージャの再帰的使用

第4話 for文版順列作成の解説その1

お約束の通り、3次順列のおけるfor文版の解説を行います。
かなり難解だからです。
Public Class Form1

   Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
     '変数の宣言と初期化
     Dim h1, h2, s As Integer
     Dim a(12) As Integer
     s = 0

     'データグリッドビューのデータのクリア
     DataGridView1.Rows.Clear()

     '順列の作成
     For i = 1 To 3  '1番最初のセル
       a(0) = i
       For j = 1 To 3  '2番目のセル
         a(1) = j
         h1 = 1
         If a(0) = a(1) Then h1 = 0  '1番目のセルと2番目のセルの重複検査
         If h1 = 1 Then
           For k = 1 To 3  '3番目のセル
             a(2) = k
             h2 = 1
             For l = 0 To 1 '3番目のセルと1,2番目のセルの重複検査
               If a(l) = a(2) Then
                 h2 = 0
                 Exit For
               End If
             Next
             If h2 = 1 Then  'DataGridViewへの表示と総数カウント
               DataGridView1.Rows.Add()  '1行追加
               For l = 0 To 2
                 DataGridView1(l, s).Value = a(l).ToString  '順列の表示
               Next
               s = s + 1  '総数カウント
             End If
           Next
         End If
       Next
     Next

     DataGridView1.Rows.Add()  '1行追加

     DataGridView1(12, s + 1).Value() = s '総数の表示

   End Sub

End Class
プログラムを読むときに、絶対欠かすことのできないことは、各変数の役割がなんなのかを理解することです。
各変数の枠割りを理解しないと、プログラミングコードは何度読んでもさっぱり意味のわからないものになります。
4次元ループになっているので、for文を制御する変数はi、j、k、lの4つです。
3次配列なのになぜ4次元なのでしょうか。
ここの理解が、次の自己再帰型を理解する際の要になります。
さて、i、j、kの役割は比較的はっきりしています。つまり、最初の3つの次元は比較的に理解が容易です。

最初の3つの次元は、セルの3に対応しています。
言い換えれば、3次配列の3に対応しています。
つまり、i、j、kはそれぞれセルに入る数字1,2,3に対応します。
各セルには1,2,3の数字が入ります。









つまり、色を対応させると

ijk 

となります。iは一番目のセルに入る数字1,2,3
jは2番目のセルに入る数字1,2,3
kは3番目のセルに入る数字1,2,3に対応しています。
では、lの役割はなんでしょうか。
実は、自己再帰型ではこれが枢要な役割を果たします。
(ただし、次話で示すコーティング例ではlはgの名称になっています。)


実は、lはセルの位置を示しています。
つまりセル番号を意味しています。
プログラミングを理解するときに、セル番号とセルに入る数字を明確に区別しなければなりません。
変数を理解するときに箱のラベルと箱の内容を区別しなければならなかったのと同じです。

ビール瓶でたとえれば、ラベルは『一番搾り』で内容は『ビール』です。
セル番号lは、箱のラベルに相当します。
入っている数字i、j、kは、箱の内容の相当します。

具体的には

では役割を明確にしたところで、トレースしてみましょう。
以下は、色を対応させながら見てください。

    i=1のとき、
   a(0) = i から番目のセルに内容1が入ります。

セルの内容 
セル番号 

   そして、
       For j = 1 To 3  '2番目のセル
   2次元目のループすなわちセル番号の世界に入り、
   a(1) = j から

セルの内容 
セル番号 

   セル番号1のセルに内容1が入ります。次に、
         h1 = 1
         If a(0) = a(1) Then h1 = 0  '1番目のセルと2番目のセルの重複検査
   の2行によって、h1=0となります。a(0)もa(1)も内容はであるからです。
   すると、
         If h1 = 1 Then
           For k = 1 To 3  '3番目のセル
             a(2) = k
             h2 = 1
             For l = 0 To 1 '3番目のセルと1,2番目のセルの重複検査
               If a(l) = a(2) Then
                 h2 = 0
                 Exit For
               End If
             Next
             If h2 = 1 Then  'DataGridViewへの表示と総数カウント
               DataGridView1.Rows.Add()  '1行追加
               For l = 0 To 2
                 DataGridView1(l, s).Value = a(l).ToString  '順列の表示
               Next
               s = s + 1  '総数カウント
             End If
           Next
         End If
  の部分は実行されません。そして、2次元(jのループ)の2巡目に入り、a(1) = j から

セルの内容 
セル番号 

  となります。そして、今回は
         h1 = 1
         If a(0) = a(1) Then h1 = 0  '1番目のセルと2番目のセルの重複検査
  a(0)の内容は、a(1)の内容はで異なっていますので、
  If文は実行されず、h1は書き換えられず1のままですから、
         If h1 = 1 Then
           For k = 1 To 3  '3番目のセル
             a(2) = k
             h2 = 1
             For l = 0 To 1 '3番目のセルと1,2番目のセルの重複検査
               If a(l) = a(2) Then
                 h2 = 0
                 Exit For
               End If
             Next
             If h2 = 1 Then  'DataGridViewへの表示と総数カウント
               DataGridView1.Rows.Add()  '1行追加
               For l = 0 To 2
                 DataGridView1(l, s).Value = a(l).ToString  '順列の表示
               Next
               s = s + 1  '総数カウント
             End If
           Next
         End If
  が実行されます。
           For k = 1 To 3  '3番目のセル
  で3次元目のループ=セル番号の世界=kのループ に入ります。
  a(2) = k によって、

セルの内容 
セル番号 

  となります。
             For l = 0 To 1 '3番目のセルと1,2番目のセルの重複検査
               If a(l) = a(2) Then
                 h2 = 0
                 Exit For
               End If
             Next
  の1巡目のループにおいて、が比較され内容が同じなので、
                     if(a[l]==a[2]){
                       h2=0;
                       break;
                     }
  によって、h2は0となり、for文も強制的に終了となります。
  3次元目の2回目のループのa[2]=k;によって、

セルの内容 
セル番号 

  となります。そして、
               If a(l) = a(2) Then
                 h2 = 0
                 Exit For
               End If
 の1巡目のループによって、が比較されますが、今度は内容が違うのでIf文はスルーされます。
 ところが、2巡目のループによってが比較され内容が同じなので、If文が実行されてしまいh2は0となってしまいます。すると、
             If h2 = 1 Then  'DataGridViewへの表示と総数カウント
               DataGridView1.Rows.Add()  '1行追加
               For l = 0 To 2
                 DataGridView1(l, s).Value = a(l).ToString  '順列の表示
               Next
               s = s + 1  '総数カウント
             End If
  は実行されず、3次元目ループの3巡目に入り、a(2) = k によって、

セルの内容 
セル番号 

  となります。3巡目においては、
             For l = 0 To 1 '3番目のセルと1,2番目のセルの重複検査
               If a(l) = a(2) Then
                 h2 = 0
                 Exit For
               End If
             Next
  は1回目においてが、2回目においてが比較されますが、いずれも内容が違うのでIf文は一度も実行されずに終わりますので、
  h2は1のままで、
             If h2 = 1 Then  'DataGridViewへの表示と総数カウント
               DataGridView1.Rows.Add()  '1行追加
               For l = 0 To 2
                 DataGridView1(l, s).Value = a(l).ToString  '順列の表示
               Next
               s = s + 1  '総数カウント
             End If
  が実行され、1個目の順列がデータグリッドビューに表示され、s = s + 1 によって、順列の個数が1とカウントされます。
  変数sの役割は、順列総数のカウントだったわけです。

  かなり、長くなったので以降のトレースは次話で。




第3話へ 第5話へ

006

VC++講義第1部へ
vb講義へ
VB講義基礎へ
初心者のための世界で一番わかりやすいVisual C++入門基礎講座

数学研究室に戻る