2

私のコードには、動的な数のリストを含む INPUTS というリストがあります。それらを A、B、C、.. N と呼びましょう。これらのリストには、動的な数のイベントが含まれています。

イベントの組み合わせごとに関数を呼び出したいと思います。例を示します。

INPUTS: A(0,1,2), B(0,1), C(0,1,2,3)

組み合わせごとに関数を何度も呼び出す必要があります (入力カウントは動的です。この例では 3 つのパラメーターですが、多かれ少なかれ可能性があります)

function(A[0],B[0],C[0]) 
function(A[0],B[1],C[0]) 
function(A[0],B[0],C[1])
function(A[0],B[1],C[1])
function(A[0],B[0],C[2]) 
function(A[0],B[1],C[2])
function(A[0],B[0],C[3])
function(A[0],B[1],C[3])

function(A[1],B[0],C[0]) 
function(A[1],B[1],C[0]) 
function(A[1],B[0],C[1])
function(A[1],B[1],C[1])
function(A[1],B[0],C[2]) 
function(A[1],B[1],C[2])
function(A[1],B[0],C[3])
function(A[1],B[1],C[3])

function(A[2],B[0],C[0]) 
function(A[2],B[1],C[0]) 
function(A[2],B[0],C[1])
function(A[2],B[1],C[1])
function(A[2],B[0],C[2]) 
function(A[2],B[1],C[2])
function(A[2],B[0],C[3])
function(A[2],B[1],C[3])

これが私がこれまで考えてきたことです。これまでの私のアプローチは、組み合わせのリストを作成することです。要素の組み合わせ自体は、入力配列 A、B、および C への「インデックス」のリストです。例:

マイリスト iCOMBINATIONS には、次の iCOMBO リストが含まれています

(0,0,0) 
(0,1,0) 
(0,0,1)
(0,1,1)
(0,0,2) 
(0,1,2)
(0,0,3)
(0,1,3)

(1,0,0) 
(1,1,0)  
(1,0,1) 
(1,1,1)
(1,0,2) 
(1,1,2)
(1,0,3) 
(1,1,3)

(2,0,0)
(2,1,0)  
(2,0,1) 
(2,1,1)
(2,0,2) 
(2,1,2)
(2,0,3) 
(2,1,3)

次に、これを行います:

foreach( iCOMBO in iCOMBINATIONS)
{
      foreach ( P in INPUTS )
      {
           COMBO.Clear()
           foreach ( i in iCOMBO )
           {
                 COMBO.Add( P[ iCOMBO[i] ] )
           }
           function( COMBO ) --- (instead of passing the events separately)
      }
}

しかし、任意の数の INPUTS とそのイベントに対してリスト iCOMBINATIONS を作成する方法を見つける必要があります。何か案は?

実際にこれよりも優れたアルゴリズムはありますか? 私を助ける擬似コードは素晴らしいでしょう。

C# (または VB)

ありがとうございました

4

6 に答える 6

1

配列を使用して、各リストのインデックスを保持できます。例:

List<List<int>> lists = new List<List<int>> {
  new List<int> { 0,1,2 },
  new List<int> { 0,1 },
  new List<int> { 0,1,2,3 }
};

int[] cnt = new int[lists.Count];
int index;
do {
  Console.WriteLine(String.Join(",", cnt.Select((c,i) => lists[i][c].ToString()).ToArray()));
  index = cnt.Length - 1;
  do {
    cnt[index] = (cnt[index] + 1) % lists[index].Count;
  } while(cnt[index--] == 0 && index != -1);
} while (index != -1 || cnt[0] != 0);
于 2010-04-12T06:39:54.643 に答える
0

A、B、Cを行列に入れてください!M = [A、B、C]

recursive_caller(d,params):
    if d == len(M):
        function(params)
        return

    for i in M[d]:
        params[d]=i
        recursive_caller(d+1,params)
于 2010-04-12T06:46:01.663 に答える
0

これが順列問題です。これを見てください:

http://www.interact-sw.co.uk/iangblog/2004/09/16/permuterate

于 2010-04-12T06:18:03.037 に答える
0

少し前に同様の問題がありました(組み合わせの生成) 。 http://www.merriampark.com/comb.htmのコードを使用しました。Java ですが、C# に変換するのに問題はありませんでした。

于 2010-04-12T06:21:20.453 に答える
0

あなたが本当に望んでいるのは、順列でも組み合わせでもないようです。いくつかのセットのデカルト積(ここを参照)を調べたいとします。この反復には、個々のセットの組み合わせによる反復が含まれる場合があります。

ただし、これは組み合わせの問題とは異なります。各セットから 1 つの要素を選択する方法を探しているからです。これを行う方法の数は、セットのサイズです。組み合わせの問題は、通常、n 個のセットからk 個のオブジェクトを選択することを伴います。ここで、k =1 またはnは自明です。

ここでは、C# で反復子を生成するいくつかの方法について説明しました。(Jon Skeetによるものを含む)。

.NET を使用している場合は、CodePlexのKwCombinatoricsなど、開発された組み合わせモジュールにも興味があるかもしれません。

編集して、LINQ を使用して救助します。

private void cartesian1()
{
    textAppend("Cartesian 1");
    var setA = new[] { "whole wheat", "white", "rye" };
    var setB = new[] { "cold cut", "veggie", "turkey", "roast beef" };
    var setC = new[] { "everything", "just mayo" };

    var query =
        from bread in setA
        from meat in setB
        from toppings in setC
        let sandwich = String.Format("{1} on {0} with {2}",
            bread, meat, toppings)
        select sandwich;

    foreach( string sandwich in query )
    {
        textAppend(sandwich);
    }
}
于 2010-04-12T07:46:05.563 に答える