• 締切済み

EXCELマクロ

下記は0~9が重複せずに3つ、順番も考慮してシートに出すものです。 いわゆる=PERMUT(10,3)、数学で言えば10P3を力技で求めるもの。 さて、3つ程度のループなら下記のようにifを書いても良いのですが これが多重になればなるほど、ifが増えるので面倒になります。 なにか賢いアルゴリズムあったらご教示ください。 (使用目的は頭の体操、例えばポーカーの役の1回目に出る確率とかです。  本計算とは関係ありませんが、理屈で考えたものを検証したい為です。) Sub test() r = 2 For a = 0 To 9 For b = 0 To 9 If b = a Then GoTo 10 For c = 0 To 9 If c = a Then GoTo 20 If c = b Then GoTo 20 Cells(r, 1) = a Cells(r, 2) = b Cells(r, 3) = c r = r + 1 20 Next 10 Next Next End Sub

みんなの回答

  • 30246kiku
  • ベストアンサー率73% (370/504)
回答No.2

以下の様な感じではどうでしょうか test1 を実行すると 0 ~ 9 の 3 つを使って・・・ test2 を実行すると A ~ J の 3 つを使って・・・ test3 を実行すると 混合のもので 3 つ使って・・・ 関数にした ReCode は再帰呼び出しで利用します。 呼び出す時には、 第一引数は、常に True 第二引数は、使う数字または文字とかの配列 第三引数は、何個使って 以下では Cells(1, 1) から書き出します。 ソコソコ動くと思いますが、不都合あれば修正してください。 ※ 処理性能はわかりません Dim iRow As Long Dim iCol As Long Private Sub ReCode(bTop As Boolean, vAry As Variant _     , iNst As Long, Optional vInAry As Variant)   Dim i As Long, j As Long   Dim vI As Variant, v As Variant   If (iNst <= 0) Then Exit Sub   If (bTop) Then     ReDim vI(1 To iNst)     Call ReCode(False, vAry, iNst, vI)   Else     vI = vInAry     j = UBound(vI) - iNst     For Each v In vAry       For i = 1 To j         If (vI(i) = v) Then Exit For       Next       If (i > j) Then         vI(j + 1) = v         If (iNst = 1) Then           Cells(iRow, iCol).Resize(, UBound(vI)) = vI ' Cell への書き出し           iRow = iRow + 1         Else           Call ReCode(False, vAry, iNst - 1, vI)         End If       End If     Next   End If End Sub Public Sub test1()   Dim vAry As Variant   Dim i As Long   ReDim vAry(9)   For i = 0 To 9     vAry(i) = i   Next   iRow = 1   iCol = 1   Call ReCode(True, vAry, 3) End Sub Public Sub test2()   Dim vAry As Variant   Dim i As Long   ReDim vAry(9)   For i = 0 To 9     vAry(i) = Chr(Asc("A") + i)   Next   iRow = 1   iCol = 1   Call ReCode(True, vAry, 3) End Sub Public Sub test3()   Dim vAry As Variant   Dim i As Long   ReDim vAry(9)   vAry(0) = "A"   vAry(1) = 1   vAry(2) = "B"   vAry(3) = 2   vAry(4) = "C"   vAry(5) = 3   vAry(6) = "D"   vAry(7) = 4   vAry(8) = "E"   vAry(9) = 5   iRow = 1   iCol = 1   Call ReCode(True, vAry, 3) End Sub

  • okormazd
  • ベストアンサー率50% (1224/2412)
回答No.1

nPr=n!/(n-r)! を使う。 factは再帰で階乗を求める関数、fact2はforループで階乗を求める関数。どちらでも好きなほうをどうぞ。 Sub npr() Dim n As Double, r As Double, npr As Double n = 10 r = 3 ' npr = fact(n) / fact(n - r) npr = fact2(n) / fact2(n - r) MsgBox npr End Sub Function fact(x As Double) As Double If x = 0 Then fact = 1 Else fact = x * fact(x - 1) End If End Function Function fact2(x As Double) As Double Dim v As Double, i As Double v = 1 For i = 1 To x v = v * i Next fact2 = v End Function

housyasei-usagi
質問者

お礼

回答ありがとうございます。 すいません、質問が悪かったようで、 欲しいのは1、2、3~9、8、7の720組の数字です。

関連するQ&A

専門家に質問してみよう