「みんな教えて! 選手権!!」開催のお知らせ

Excelですべての組合せ(重複組合せ)を出力するには?

次の条件のような場合、Excelですべての組合せ(重複組合せ)をVBAで出力するにはどうしたらいいのでしょうか?

10種類のお菓子の中から、好きなものを3個選んでセットにするとします。
同じものを複数選ぶのはありですが「菓子A、菓子B、菓子C」と「菓子B、菓子C、菓子A」は選んだ順が違うだけで同じ組合せなので、どちらか片方だけにします。

この場合、すべての組合せの数は Excelの関数で求めることができるようで COMBIN(10+3-1,3) = 220 通りあることまではわかりましたが、このすべての組合せの一覧をどのようにして出力したらいいのかがわかりません。

いろいろ検索した結果、順列という方法は見つかりましたが、重複組合せでの方法は見つけることができませんでした。
また、Accessを使っても似たようなことができるのでしょうか? 直積?

できれば、3個固定ではなく5個の場合も出来るとうれしいです。
よろしくお願いします。

A 回答 (4件)

>同じものを複数選ぶのはありですが「菓子A、菓子B、菓子C」と「菓子B、菓子C、菓


つまり「菓子A、菓子A、菓子A」も「菓子A、菓子A、菓子B」もあり ですね。
№2さんのコードをお借りして
Sub Test()
  Dim myStr As Variant
  Dim rowX As Long
  Dim i As Long, j As Long, k As Long
  Const MaxNum = 10

  myStr = Split("A B C D E F G H I J")
  rowX = 1
  For i = 0 To MaxNum - 1
    For j = i To MaxNum - 1
      For k = j To MaxNum - 1
        Cells(rowX, 1).Value = myStr(i)
        Cells(rowX, 2).Value = myStr(j)
        Cells(rowX, 3).Value = myStr(k)
        rowX = rowX + 1
      Next k
    Next j
  Next i
End Sub
    • good
    • 1
この回答へのお礼

悩んでいた問題が解決し、とても助かりました。ありがとうございました。

お礼日時:2010/01/07 00:17

#2さんの回答は(普通の)組合せの場合のコードですので、


重複組合せの場合は、次のようにコードの一部を変えるだけ可能です。

'3個の場合
For i = 1 To MaxNum - 2
For j = i + 1 To MaxNum - 1
For k = j + 1 To MaxNum

For i = 1 To MaxNum
For j = i To MaxNum
For k = j To MaxNum


'5個の場合
For i = 1 To MaxNum - 4
For j = i + 1 To MaxNum - 3
For k = j + 1 To MaxNum - 2
For l = k + 1 To MaxNum - 1
For m = l + 1 To MaxNum

For i = 1 To MaxNum
For j = i To MaxNum
For k = j To MaxNum
For l = k To MaxNum
For m = l To MaxNum
    • good
    • 0
この回答へのお礼

悩んでいた問題が解決し、とても助かりました。ありがとうございました。

お礼日時:2010/01/07 00:18

なぜCOMBIN(10+3-1,3)なのでしょうか?


COMBIN(10,3)で良いと思うのですが・・・




Sub test()

Const MaxNum = 10
Dim s(10) As String
s(1) = "菓子A"
s(2) = "菓子B"
s(3) = "菓子C"
s(4) = "菓子D"
s(5) = "菓子E"
s(6) = "菓子F"
s(7) = "菓子G"
s(8) = "菓子H"
s(9) = "菓子I"
s(10) = "菓子J"

Dim i, j, k, l, m

Dim rowX As Long
rowX = 1

'3個の場合
For i = 1 To MaxNum - 2
For j = i + 1 To MaxNum - 1
For k = j + 1 To MaxNum
Cells(rowX, 1).Value = s(i)
Cells(rowX, 2).Value = s(j)
Cells(rowX, 3).Value = s(k)
rowX = rowX + 1
Next k
Next j
Next i

rowX = rowX + 1

'5個の場合
For i = 1 To MaxNum - 4
For j = i + 1 To MaxNum - 3
For k = j + 1 To MaxNum - 2
For l = k + 1 To MaxNum - 1
For m = l + 1 To MaxNum
Cells(rowX, 1).Value = s(i)
Cells(rowX, 2).Value = s(j)
Cells(rowX, 3).Value = s(k)
Cells(rowX, 4).Value = s(l)
Cells(rowX, 5).Value = s(m)
rowX = rowX + 1
Next m
Next l
Next k
Next j
Next i


End Sub
    • good
    • 2
この回答へのお礼

今回初めて知ったのですが、数学では「組合せ」と「重複組合せ」というのがあるようで、組合せが COMBIN(10,3) 重複組合せが COMBIN(10+3-1,3) なんだそうです。
組合せでの方法も知りたかったのでとても助かりました。ありがとうございました。

お礼日時:2010/01/07 00:16

面白そうなので、アクセスでやってみました。


選んだものを何かの規則で順番に並べ、グループ化してみました。

テーブル t1 を作成し
フィールド f1 に A,B,C...と十個のデータをセットする。

ソートに関しては、
http://www.geocities.co.jp/SilkRoad/4511/vb/strs …
をお借りして、そのまま、モジュールに貼り付けました。

モジュールにファンクションを一つ作り、クエリからソートされた文字列を表示できるようにしました。

Public strA(2) As String

Function Reorg(a, b, c) As String
Dim i As Long
strA(0) = a
strA(1) = b
strA(2) = c
StrSort strA, 0, 2
Reorg = ""
For i = 0 To 2
Reorg = Reorg & strA(i)
Next i
End Function

クエリを作成し、t1を3回表示させ(t1,t1_1,T1_2)
文字をソートして並べたものでグループ化して、
それぞれのf1の先頭を表示させる

SELECT First(t1.f1) AS f1の先頭2, First(t1_1.f1) AS f1の先頭1, First(t1_2.f1) AS f1の先頭, reorg([t1].[f1],[t1_1].[f1],[t1_2].[f1]) AS 式1
FROM t1, t1 AS t1_1, t1 AS t1_2
GROUP BY reorg([t1].[f1],[t1_1].[f1],[t1_2].[f1])
ORDER BY First(t1.f1), First(t1_1.f1), First(t1_2.f1);

効率的なやり方かどうかはわかりませんが、ちょっと改造すれば5個でもできます。
    • good
    • 0
この回答へのお礼

クエリを実行したところ、220件のデータが表示されました。
なぜそうなるかはまだ理解できていませんが、とても参考になりました。
ありがとうございました。

お礼日時:2010/01/07 00:14

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

このQ&Aを見た人はこんなQ&Aも見ています


おすすめ情報