• ベストアンサー

VBAで順列を表現する方法

VBAによる順列の表記の仕方を教えてほしいです。 例えばn個の数値から2つの要素を並べる順列nP2の場合、1番目に選んだ数値が2番目の順列の選択候補から外れ、1番目と2番目の数値を順列として表示するようなVBAを組みたいです。 つまり同じ数字を2回以上使わないnPm(m≧2)という順列を作成したいのです。 どのようなプログラムを組めばよいか教えてください。

  • HUNK
  • お礼率30% (22/73)

質問者が選んだベストアンサー

  • ベストアンサー
  • lark_0925
  • ベストアンサー率63% (37/58)
回答No.2

新規ブックにて、試してみてください。 標準モジュール(Module1)に '==================================================================== Sub main()   Dim 抜き取り数 As Long   Dim ans() As Variant   Dim retcode As Long   Dim rw As Long   Dim cnt As Long   cells.clear   With Range("a1:g1")    .Formula = "=column()"    .Value = .Value    抜き取り数 = Int(Rnd() * .Count) + 1    MsgBox "a1:g1の値から、 7P" & _        抜き取り数 & _        " の順列リストを作成します"   End With   ReDim ans(1 To 抜き取り数)   rw = 3   cnt = init_permut(Range("a1:g1"), 抜き取り数)   retcode = get_permut(ans())   Do While retcode = 0    Range(Cells(rw, 1), Cells(rw, UBound(ans()))).Value = ans()    rw = rw + 1    retcode = get_permut(ans())   Loop      Call term_permut   MsgBox "以上、 " & cnt & " 個のリストを作成しました"    End Sub 別の標準モジュール(Module2)に 順列リスト作成プログラムパック Option Explicit   Private p_svn As Long '抜き取り数保存   Private p_myarray() '順列対象値の配列   Private p_idx() As Long '配列の各位置のボインタ '========================================================================================= Function init_permut(ByVal rng As Range, ByVal seln As Long) As Double '順列リストを作成の初期化処理 'input rng 順列リスト作成する標本セル範囲 ' seln 抜き取り数 'output init_permut---順列数  On Error Resume Next   Dim g0 As Long   Dim crng As Range   p_svn = seln   Erase p_myarray()   Erase p_idx()   g0 = 1   ReDim p_myarray(1 To rng.Count)   For Each crng In rng    p_myarray(g0) = crng.Value    g0 = g0 + 1    Next   ReDim p_idx(1 To seln)   For g0 = 1 To UBound(p_idx())    p_idx(g0) = 1    Next   init_permut = WorksheetFunction.Permut(rng.Count, seln) End Function '======================================================================================== Function get_permut(ans(), Optional ByVal n_cnt As Long = 1) As Long 'init_permutの指定に基づく順列リストを取得する 'output ans() 順列リストを配列で出力する '        予め必要な配列領域は呼び出し側で用意すること '        尚、指定配列の添え字ベースは1とする '    get_permut 0 正常に順列リストを取得 1 順列リストはなし  Dim g0 As Long  Dim g1 As Long  Dim retcode As Long  get_permut = 1  For g0 = p_idx(n_cnt) To UBound(p_myarray())    retcode = 0    For g1 = LBound(p_idx()) To n_cnt - 1      If p_idx(g1) = g0 Then       retcode = 1       Exit For       End If      Next g1    If retcode = 0 Then      ans(n_cnt) = p_myarray(g0)      p_idx(n_cnt) = g0      If n_cnt < UBound(p_idx()) Then       get_permut = get_permut(ans(), n_cnt + 1)      Else       p_idx(n_cnt) = g0 + 1       get_permut = 0       End If      End If    If get_permut = 0 Then Exit For    Next g0  If get_permut = 1 Then    p_idx(n_cnt) = 1    End If End Function '====================================================================================== Sub term_permut() '順列リストを作成の終了処理 '(ファイルだって、Openすれば、クローズするよね)   Erase p_myarray()   Erase p_idx() End Sub これでmainを実行してみてください。 例題コードは、アクティブシートのA1:G1に入力された 1~7の数字を乱数によって、選定された抜き取り数で 順列リストを3行目から表示します。 順列リスト作成プログラムパックは、私は、普段はクラスモジュールで 運用していますが、今回は標準モジュールにしました。 試してみてください

その他の回答 (1)

  • hige_082
  • ベストアンサー率50% (379/747)
回答No.1

過去に似たような質問があります http://okwave.jp/qa1634838.html http://okwave.jp/qa1126322.html http://okwave.jp/qa1128457.html 参考にしてください

関連するQ&A

  • 完全順列の総数について

    1、2、3…、nのn個の数字の完全順列は、1番目が2の場合がa通りあれば、1番目が3、4…、nの場合もそれぞれa通りあるのでしょうか? 参考書の問題ではすべてそうなのですが、nがどんな数字でもそうなるのか疑問に思いました。 よろしくお願いします。

  • 完全順列の問題

    完全順列についての漸化式D ( n ) = ( n - 1 ) { D ( n - 2 ) + D ( n - 1 ) }がありますが、その証明方法がわかりません。(1)一番目がkでk番目が位置の場合(2)一番目がkで、k番目が1以外の場合 の二つに場合分けして解く方法は理解しました。 今回質問したいのは、「n枚の完全順列の個数をanとします。 (1)ここへn+1枚目の札をn+1番目に追加します。 n+1番目の札を1~n番目の札のどれか1枚と交換すれば、 n+1枚とも順番が一致しなくなります。よって、an個ある完全順列からn+1番目へはそれぞれn個ずつの完全順列が作れます。 (2)また、n個のうちk番目だけが揃ってしまっているものからも、 k番目の数とn+1番目の札を入れ替えれば、これも完全順列の1つとなります。n個のうちk番目だけが揃っている札の並べ方をbnとすると、 1~nまでのn個のbnから、それぞれ1通りずつの完全順列(の1部)が作れます。 以上のことより、次の漸化式が作れます。 an+1=nan+nbn   ……(i) k番目以外はn-1個の完全順列となっているため、 bn=an-1 (n≧2)が成り立ちます。これを(i)II代入して上の漸化式が求まります。」 という解説が理解できないということです。具体的な疑問点は、(1)、(2)のせれぞれの操作は各々理解しているものの、なぜこれを足し合わせればすべて網羅したことになるのかということです。他に数えもれがありそうのように思えます。そもそもなぜこのようなやり方なのでしょうか。 ご教授のほどよろしくお願いします。

  • 円順列

    1~nの数字を書いたカードがそれぞれm枚ずつ、計nm枚ある。 これを1列に並べる順列の数F(n,m)は、F(n,m)=(nm)!/(m!)^n では、このm枚を円環状に並べる円順列の数G(n,m)はどうなるでしょうか? m=1なら、 G(n,1)=F(n,1)/n=(n-1)! m=p (pは素数)なら、 G(n,p)=(F(n,p)-F(n,1))/(np)+F(n,1)/n =((np)!/(p!)^n-n!)/(np)+(n-1)! mが任意の自然数のとき、G(n,m)をnとmの式、または漸化式で表すことは可能でしょうか? ちなみに、n,mが小さい数値のときのG(n,m)の値は次のようになっています。 G(2,2)=2 G(2,3)=4 G(2,4)=10 G(2,5)=26 G(2,6)=80 G(2,7)=246 G(2,8)=810 G(2,9)=2704 G(2,10)=9252 G(3,2)=16 G(3,3)=188 G(3,4)=2896 G(3,5)=50452 G(4,2)=318 G(4,3)=30804 G(5,2)=11352

  • 順列「n個からr個取り出す」の意味

    順列の定義では「いくつかあるものの中から2つ以上取り出して1列に並べたときの並べ方のこと」だそうですが、「取り出す」というのはどういうことなのでしょうか? 異なるn 個のものからr 個とった順列の総数の公式は nPr=n(n-1)…(n-1+1) という公式ですが、では単純に、ABCDを左から右に並べ方の総数は何通りあるか、という公式はどのような式になるのでしょうか?また実際の並べ方は樹形図になると思いますが、樹形図の書き方についてもご指導いただけたら幸いです。 (当方、数字は苦手なのでできるだけ優しく教えていただけると助かります)

  • 順列の問題

    順列の問題で 6個の数字0,1,2,3,4,5の中から、異なる数字を使って3桁の数を作る。 問.小さい方から順に並べると、43番目の数は何か。 という問題があり、わからなかったので解説を読んだところ 3桁の数のうち、百の位の数字が1または2であるものは 2×5P2=2×5・4=40(個) 百の位の数が3である3桁の数を小さい順に並べると 301,302,304,305... よって求める数は304 というふうにありましたが、良く意味が理解できません; どなたか分かる方、どのようにして解けばよいのか教えていただけませんか? ※・は×(かける)の意味です。

  • 名刺順列の個数

    1~nまでの数を1列に並べるときに、i番目にiという数字が来ない順列を名刺順列とか完全順列とか言います。 このような順列の個数をA(n)とすると、 A(n)=n! * Σ_{k=0}^{n} (-1)^k / k! であるそうです。この導出の仕方を教えて下さい。 ちなみに、A(n)に関する漸化式 A(n)=(n-1)*{A(n-1)+A(n-2)}, A(1)=0, A(2)=1は既に理解していますので、この漸化式の解き方でもいいです。 (この漸化式は1世代前の青チャートで見ました^^;) この式を用いると、全世界の人が名刺を1枚ずつ持ち寄ってシャッフルしたとき、自分のところに自分の名刺が戻ってくる人が1人もいない確率が1/e=36.8%もあることがわかり、なかなか神秘的なのですが。

  • 順列の列挙の方法

    順列の列挙の方法といっても辞書式順序のやつではありません。別の制約です。 グレイコードというのをご存知でしょうか。例えばビット列のグレイコードは次のようになります。 0:000 1:001 2:011 3:010 4:110 5:111 6:101 7:100 これがどんな制約を満たしているかと言うと、 1、となりのビット列に変換するには1ビット反転すれば良い。 2、すべてのビット列がちょうど1回現れる。 この2つです。グレイコードの正確な定義はさておき、とりあえず今はこれと言うことにします。 この順序でビット列を列挙する関数をC言語で書くと次のような感じになります。 f(int n) { if(n==-1)return; f(n-1); 第nビットを反転; 出力; f(n-1); } さて順列の話ですが、次のような制約を満たす順序で順列を列挙するアルゴリズムは どんな感じになるのでしょうか。 1、となりの順列に変換するには1回スワップ(2つの要素を入れ換える)すれば良い。 2、すべての順列がちょうど1回現れる。 この条件を満たすような順列の列はたくさんあると思いますが、 できるだけ法則性のあるやつ、というかプログラムに書きやすいやつを お願いします。 ビット列のアルゴリズムをちょこっと変えれば出来るかなーと思っていたのですが 数学的センスが無いせいか、苦戦しています。数学的センスのある方、ぜひご教示ねがいます。

  • エクセルで順列の列挙

    例えば 1 と 2 という2個の数字(文字)がある場合,  A列 B列   1   2   2   1 1 2 3 という3個の数字(文字)がある場合,  A列 B列 C列   1   2   3   1   3   2   2   1   3   2   3   1   3   1   2   3   2   1 1 2 3 4 という4個の数字(文字)がある場合,  A列 B列 C列 D列   1   2   3   4   1   2   4   3    ~ 省略 ~   4   3   2   1 という具合に n 個の数字(文字)がある場合,過不足無く列挙させるマクロ(VBA)を教えてください。 Excelの仕様上65,536行までしかないので,「8個の場合」とかいう限定された個数でもかまいません。 また,123,132,213,…,321 という具合に数値として1列に並べる方法でもかまいません。 また昇り順でなくてもかまいません。 よろしくおねがいします。

  • 最適円順列を求めるアルゴリズムについて教えてください

    ExcelのVBAでプログラムを作っているのですが、ある問題で   つまづいてしまいました。     問題は、30個のデータ(#1~#30とします)を円順列で   並べます。 (#1=10とか#18=24などの数値が入ります)   その場合の組み合わせは29!通りありますよね   そして、この組み合わせそれぞれである計算をさせます。   (ベクトル計算のようなものです)   その答えのもっとも最適な結果(今回の場合最小)が出る   組み合わせを見つけ出したいのです。   最適結果を導き出すアルゴリズムをご指導下さいお願いします。             

  • 順列文字の生成処理

    次のような左端の番号に対応した右側の文字列を作りたいのです。 これらの4個の文字列は、重複無しの順列になります。 下表では文字列が4個ですが、実際には7個程度まで生成したいのです。7個の場合は合計1*2*3*4*5*6*7=5040個になります。 言語はFORTRANですがCでも、あるいは手順説明でも良いです。文字列でなくともn桁数字あるいは配列でも良いです。c++のクラス処理も候補かも知れませんが、FORTRANで書くには荷が重いです。再帰処理は何とかなるかも知れませんが、できれば無しを希望します。 4個程度ならデータとして書けば済みますが、6,7個となるとそうは行きませんので、プログラムで生成したいのです。処理時間は問題になりません。 N個の処理を使ってn+1個の処理の形式で大分頭を悩ませましたが、ギブアップ気味です(まだ1日程度ですが)。虫の良いお願いですが奇特な諸兄のお知恵を拝借したく存じます。 1: 1234 2: 2134 3: 1324 4: 3124 5: 2314 6: 3214 7: 1243 8: 2143 9: 1423 10: 4123 11: 2413 12: 4213 13: 1342 . . 18: 4312 19: 2341 . . 24: 4321

専門家に質問してみよう