- PR -

C#で全ての組み合わせを取得する方法

1
投稿者投稿内容
dsk
会議室デビュー日: 2007/06/20
投稿数: 4
投稿日時: 2007-06-20 03:23
C#で全ての組み合わせを取得する方法

C#で全ての組み合わせを取得する方法を模索しています。
具体的には、以下のようなことをしようとしています。

Group ID
--------------
A 1
A 2
--------------
B 3
B 4
B 5
--------------
C 6
C 7
--------------

のようなデータが存在するとして、

グループ単位での組み合わせの全てを取得したいのです。
上記の場合、全ての組み合わせは、
Aグループが2パターン、Bグループが3パターン、Cグループが2パターン
なので、2×3×2 = 12パターンが存在することになります。

今回、パターンの数を取得したいのではなく、以下のように具体的な組み合わせの
全てを取得したいと考えています。

この例において、具体的な組み合わせは、以下のようになります。

Group A Group B Group C
------------------------------------------
1 3 6
1 3 7
1 4 6
1 4 7
1 5 6
1 5 7
2 3 6
2 3 7
2 4 6
2 4 7
2 5 6
2 5 7
------------------------------------------
(合計12パターン)

なお、グループ数(ここでは、A〜Cの3種類)も、グループに含まれるデータ数も可変です。

基本的なアルゴリズムに関する問題ですので、ここに投稿するのは場違いかもしれませんが、ほかに適当な場所が見つからなかったので、投稿させていただきました。

ご教授いただければ、幸いです。
turutosiya
常連さん
会議室デビュー日: 2003/06/10
投稿数: 49
お住まい・勤務地: 東京都
投稿日時: 2007-06-20 04:52
単純にループではだめなんでしょうか?
dsk
会議室デビュー日: 2007/06/20
投稿数: 4
投稿日時: 2007-06-20 05:40
グループ数(ここでは、A〜Cの3種類)も、グループに含まれるデータ数も可変なので、単にループするだけでは上手くいかないと考えています。こういう場合には、再帰的な処理をして、組み合わせを決定していくのかなと考えているのですが、具体的にどのようにすればいいのか、イメージが浮かばないのです。
unibon
ぬし
会議室デビュー日: 2002/08/22
投稿数: 1532
お住まい・勤務地: 美人谷        良回答(20pt)
投稿日時: 2007-06-20 09:44
引用:

dskさんの書き込み (2007-06-20 05:40) より:
こういう場合には、再帰的な処理をして、組み合わせを決定していくのかなと考えているのですが、具体的にどのようにすればいいのか、イメージが浮かばないのです。


やはり、おっしゃるように再帰が良いと思います。

「件名:お手本になるようなソースコード」
http://www.atmarkit.co.jp/bbs/phpBB/viewtopic.php?mode=viewtopic&topic=38296&forum=3&start=40
の6ページ目の私が書いたソースコード(Java ですが)の loop という名前のメソッドみたいな感じになると思います。("お手本"とは言い難いですが、たとえば私はこうやっていますよ、という例です。)

--
unibon {B73D0144-CD2A-11DA-8E06-0050DA15BC86}
KI
大ベテラン
会議室デビュー日: 2007/01/10
投稿数: 239
投稿日時: 2007-06-20 10:01
時間あったので作ってみました。
細かい検証はしてないですが、とりあえず動きました。
参考になりましたら。

コード:
    public static class Combinations<T>
    {
        public static List<T[]> GetCombinations(List<T[]> sourceList)
        {
            List<T[]> resultList = new List<T[]>();
            Stack<T> stack = new Stack<T>();
            GetCombinationsCore(stack, resultList, sourceList);

            return resultList;
        }

        private static void GetCombinationsCore(Stack<T> stack, List<T[]> resultList, List<T[]> sourceList)
        {
            int dimension = stack.Count;
            if (sourceList.Count <= dimension)
            {
                T[] array = stack.ToArray();
                Array.Reverse(array);
                resultList.Add(array);
                return;
            }
            else
            {
                foreach (T item in sourceList[dimension])
                {
                    stack.Push(item);
                    GetCombinationsCore(stack, resultList, sourceList);
                    stack.Pop();
                }
            }
        }
    }



使うほうはこんな感じ

コード:
    static void Main(string[] args)
    {
        List<string[]> sourceList = new List<string[]>(3);
        sourceList.Add(new string[] { "a", "b" });
        sourceList.Add(new string[] { "c", "d", "e" });
        sourceList.Add(new string[] { "f", "g", "h", "i" });
        List<string[]> resultList = Combinations<string>.GetCombinations(sourceList);

        foreach (string[] item in resultList)
        {
            Console.WriteLine(string.Join(",", item));
        }
    }

かるあ
ぬし
会議室デビュー日: 2003/11/16
投稿数: 1190
お住まい・勤務地: センガワ→ムサシノ
投稿日時: 2007-06-20 10:03
引用:

dskさんの書き込み (2007-06-20 05:40) より:
グループ数(ここでは、A〜Cの3種類)も、グループに含まれるデータ数も可変なので、単にループするだけでは上手くいかないと考えています。こういう場合には、再帰的な処理をして、組み合わせを決定していくのかなと考えているのですが、具体的にどのようにすればいいのか、イメージが浮かばないのです。



再起のほうがすっきりするかもしれませんが、
for でできないことはないと思います。

どっちにしても、
ソートして
GroupIDごとにコレクションに格納して
ループまたは再帰で走査
って感じになるかな?

# って KIさん はえーw
_________________
かるあ のメモ
http://karua.at.webry.info/

[ メッセージ編集済み 編集者: かるあ 編集日時 2007-06-20 10:04 ]
dsk
会議室デビュー日: 2007/06/20
投稿数: 4
投稿日時: 2007-06-20 12:50
unibonさん、KIさん、かるあさん、教えていただきましてありがとうございます。
KIさんのサンプルは後で実際に動作を確認して、勉強をさせていただきます。
自分が悩んでいることも一瞬で回答できる方々がいる。本当にすごいですね。
また、何か気づいた点がありましたら、投稿させていただきます。
dsk
会議室デビュー日: 2007/06/20
投稿数: 4
投稿日時: 2007-06-21 02:15
KIさんのサンプルを開発環境上で確認させていただきました。自分が実装しようとしていることに、まさしくぴったりなアルゴリズムでした。今後のためにも、しっかりと頭に入れて、勉強しておきたいと思います。

ListとStackを使って、このような再帰処理で実装できるのですね。
また、皆さんがご指摘のように単純なループでも実装できるとの
お話でしたので、自分なりに考えてみたいと思います。

本当にありがとうございました。
1

スキルアップ/キャリアアップ(JOB@IT)