電子書籍の厳選無料作品が豊富!

1,2,3,--,n-1,nからm個とる組み合わせのパターンを
セル(1,1)から(nCm、nCm)に表示させる処理をVBAで記述
したいのですが、どうすればいいのでしょうか。
よろしくお願いします。

A 回答 (4件)

再帰呼び出しのアルゴリズムは「自分自身を呼び出す」わけですから、普通の上から下へ


読んでいくフローとはひと味違って、考えにくいところがあります(実は私もしばらくや
ってなかったので今回少し手こずりました)。

各行の意味を書きます。


Const nStr As String = "あいうえおかきく" '←n個の文字列
Const m As Integer = 3 '←取り出す個数
Dim n As Integer '←ご質問文のn
Dim rStr As String '←m個取り出した文字列を結合したもの
Dim mRow As Integer '←エクセル表へ書き出す際の行番号
Dim Nest As Integer '←再帰呼び出しの深さ=rStrの何文字目に取り出すのか
'-----------------------
Sub combi()
n = Len(nStr) 'nStrの文字列長をnに代入
If m > n Then Exit Sub 'nよりmが大きければ終了
rStr = String(m, " ") 'rStrにm個の空白を代入
Cells.ClearContents '書き出す表をクリア
mRow = 0 '書き出す行番号0クリア
Nest = 0 '再帰呼び出し深さ0クリア
combiPr (0) 'サブルーチン combiPr を引数0で呼び出し
End Sub
'-----------------------
Sub combiPr(n1) 'サブルーチン開始 引数はその時点での開始位置(nStrの何文字目まで処理したか)
Dim mCol As Integer '←エクセル表へ書き出す際の列番号
For nn = n1 + 1 To n - m + Nest + 1 'nnを開始位置の次の文字から始めて残りの文字数の手前までFor~Nextを繰り返す
Nest = Nest + 1 '再帰呼び出しを1カウントアップ
Mid(rStr, Nest, 1) = Mid(nStr, nn, 1) 'rStrのNest番目にnStrのnn番目を代入
If Nest = m Then 'rStrに取り出したのがm文字目なら
mRow = mRow + 1 'エクセル表の次の行へ
For mCol = 1 To m 'rStrの1文字目からm文字目まで書き出す。
Cells(mRow, mCol).Value = Mid(rStr, mCol, 1)
Next
Else 'そうでなければ、つまり現在の開始位置(=nStrの何文字目まで処理したか)がm個まで達してなければ
Call combiPr(nn) '現在の到達位置(nStrの何文字目まで処理したか)にnnをセットしてcombiPrを呼び出す(再帰呼び出し)
End If
Nest = Nest - 1'再帰呼び出しを1後退
Next
End Sub


手順は原始的なものです。
あ~く まで書かれたカードを8枚ならべて3枚抜き出すことを考えればお解りになるで
しょうか。

あ を一枚抜き出し、
い を抜き出し2枚目に置きます。
う を抜き出し、3枚目とします。←これを く まで繰り返します。

次に、い を戻して う を新たな2枚目とします。
え を抜き出し、3枚目とします。←これを く まで繰り返します。

の繰り返し・・・・

を行っているわけです。

ポイントは、1枚目を抜き出すのは か までだという点です。
き まで抜き出したら(く までしかないので)3枚目のカードがなくなります。
同様に2枚目は き までしか抜き出してはいけません。
これが「For nn = n1 + 1 To n - m + Nest + 1」の「n - m + Nest + 1」の部分の意味です。

テキストベースのみの説明なので伝えにくいのですが、不明な点があったら補足説明しますの
で、またおたずねください。
    • good
    • 1
この回答へのお礼

こんなにもていねいな説明にとても感謝します。
おかげでおおよその意味はつかめました。あと数回読み直し納得がいくようにいたします。

お礼日時:2007/06/13 09:07

> この combiというプロシジャを起動すれば、8個から3個取り出す組み合わせが表示されるはずなんですよね。



そうです。

> しかし、何も表示されません。エラーは何もでませんが。
パラメータとか指摘する必要ありますか。

特にパラメータなど指定する必要はありません。
Excel2002/標準モジュールにて確認しましたが当方の環境では56通りの組合せが表示されます。

この回答への補足

ソフト動作をシュミレートしておおよそどのような
動きをしているのか、説明くださればありがたい。
変数の定義など

combi(0)で0を入れる意味は

補足日時:2007/06/08 14:28
    • good
    • 0
この回答へのお礼

やり直したらうまく表示されました。ご回答どうもありがとうございました。

お礼日時:2007/06/08 12:59

再帰(的)呼び出しのアルゴリズムになると思います。


以下のソースでいかがでしょうか。

Const nStr As String = "あいうえおかきく" '←n個の文字列
Const m As Integer = 3 '←取り出す個数
Dim n As Integer
Dim rStr As String
Dim mRow As Integer
Dim Nest As Integer
'-----------------------
Sub combi()
n = Len(nStr)
If m > n Then Exit Sub
rStr = String(m, " ")
Cells.ClearContents
mRow = 0
Nest = 0
combiPr (0)
End Sub
'-----------------------
Sub combiPr(n1)
Dim mCol As Integer
For nn = n1 + 1 To n - m + Nest + 1
Nest = Nest + 1
Mid(rStr, Nest, 1) = Mid(nStr, nn, 1)
If Nest = m Then
mRow = mRow + 1
For mCol = 1 To m
Cells(mRow, mCol).Value = Mid(rStr, mCol, 1)
Next
Else
Call combiPr(nn)
End If
Nest = Nest - 1
Next
End Sub

この回答への補足

この combiというプロシジャを起動すれば、8個から3個取り出す組み合わせが表示されるはずなんですよね。
しかし、何も表示されません。エラーは何もでませんが。
パラメータとか指摘する必要ありますか。

補足日時:2007/06/07 15:46
    • good
    • 0

問題は(nCm、nCm)でなく(nCm、m)でしょうね。

    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!