2012-02-16 3 views
3

私は、次のような情報与えられたすべての組み合わせを見つける方法をどのように把握しようとしています:C#の高度な順列のシナリオ

私はJSONデータセットで始まる:

私は把握しようとしている何
var choices = { 1: {'Q': 100, 'R': 150, 'W' : 250, 'T', 30}, 
       2: {'Q': 90, 'R': 130, 'W' : 225, 'T', 28}, 
       3: {'Q': 80, 'R': 110, 'W' : 210, 'T', 25}, 
       4: {'Q': 70, 'R': 90, 'W' : 180, 'T', 22}, 
       5: {'Q': 60, 'R': 70, 'W' : 150, 'T', 18}, 
       6: {'Q': 50, 'R': 50, 'W' : 110, 'T', 15}, 
       7: {'Q': 40, 'R': 30, 'W' : 80, 'T', 11}, 
       8: {'Q': 30, 'R': 25, 'W' : 50, 'T', 8}, 
       9: {'Q': 20, 'R': 10, 'W' : 25, 'T', 5}, 
       10: {'Q': 10, 'R': 5, 'W' : 15, 'T', 3} 
       }; 

どのように私はこのデータセットを取ることができ、各行の 'Q'、 'R'、 'W'、または 'T'のいずれかの要素を選択すると、すべての可能な組み合わせを生成します。

は、だから、私は最終的な結果は、このようなものになることを願っています

var allChoices = { 0: {1: {'Q': 100}, 
         2: {'R': 130}, 
         3: {'W' : 210}, 
         4: {'W' : 180}, 
         5: {'T', 18}, 
         6: {'R': 50,}, 
         7: {'Q': 40,}, 
         8: {'T', 8}, 
         9: {'R': 10}, 
         10: {'W' : 15}, 
        }, 
       1: {...}, 
       ... 
       1048576: {...} 

       }; 

私はそれを視覚化するのが最も簡単だと思うので、私はJSONを使用したが、誰もが、私はC#でこれを達成するに取り掛かることができる方法を知っていますか?

これが十分明確でない場合は、私はこの質問をどのくらい正確に尋ねるのか苦労しています。

+0

Woa!あなたは無限を分割しませんでした!一度それを見るのはニース。 – Almo

+0

これを私に教えてください。 Q、R、W、Tの文字セットと数字のセット{100,130,210、...}があります。可能なすべての組み合わせで文字を数値に関連付ける必要があります。 – Ani

+0

@ananthonlineまさに。だから最後には、最初のスロットに "Q"があるすべてのラインの合計を私に教えてくれるようなものを言うことができます。私は、各選択肢に4つの可能性がある10の選択肢について、可能な値の合計をすべて見つけようとしています。それは理にかなっていますか。だから最初の例は私が知りたい最初の結果行は合計が761で、最初の位置はQでした。 –

答えて

2

深さの最初の再帰を使用して行う方法です。私のマシンでは約3秒かかります。また、これは、4の代わりに5つの列があり、必要に応じて追加のペアを追加した場合は、PAIRCOUNTを5に変更して任意のサイズのペアリングを行うことができます。

void Main() 
    { 
     var OriginValues = new List<KeyValuePair<char, int>>(); 
     OriginValues.Add(new KeyValuePair<char, int>('Q', 100)); 
     OriginValues.Add(new KeyValuePair<char, int>('R', 150)); 
     OriginValues.Add(new KeyValuePair<char, int>('W', 250)); 
     OriginValues.Add(new KeyValuePair<char, int>('T', 30)); 

     OriginValues.Add(new KeyValuePair<char, int>('Q', 90)); 
     OriginValues.Add(new KeyValuePair<char, int>('R', 130)); 
     OriginValues.Add(new KeyValuePair<char, int>('W', 225)); 
     OriginValues.Add(new KeyValuePair<char, int>('T', 28)); 

     OriginValues.Add(new KeyValuePair<char, int>('Q', 80)); 
     OriginValues.Add(new KeyValuePair<char, int>('R', 110)); 
     OriginValues.Add(new KeyValuePair<char, int>('W', 210)); 
     OriginValues.Add(new KeyValuePair<char, int>('T', 25)); 

     ///... and the other 7 

     var AllPermutation = new List<List<KeyValuePair<char, int>>>(); 
     Recurse(OriginValues, ref AllPermutation); 

     //all results will be in AllPermutation now 

    } 

    const int PAIRCOUNT = 4; 
    void Recurse(List<KeyValuePair<char, int>> OriginValues, ref List<List<KeyValuePair<char, int>>> result, List<KeyValuePair<char, int>> itemset = null) 
    { 
     itemset = itemset ?? new List<KeyValuePair<char, int>>(); 
     var temp = new List<KeyValuePair<char, int>>(itemset); 
     if (itemset.Count == OriginValues.Count/PAIRCOUNT) 
     { 
      result.Add(temp); 
      return; 
     } 
     for (int x = 0; x < PAIRCOUNT; x++) 
     { 
      temp.Add(OriginValues[itemset.Count * PAIRCOUNT + x]); 
      Recurse(OriginValues, ref result, temp); 
      temp = new List<KeyValuePair<char, int>>(itemset); 
     } 

    } 
1
このうち

チェック:Combination Generator in Linq

別の解決策LINQなしでは、あなたが行あたりわずか4のものでこれをやっているだろうと仮定すると、最も簡単な方法は、それだけで強引にされ、ネストされたforeach文を実行します。

foreach (choice in allChoices) 
{ 
    foreach (choice in allChoices) 
    { 
     foreach (choice in allChoices) 
     { 
      foreach (choice in allChoices) 
      { 
       // combine and add to a collection 
      } 
     } 
    } 
} 

編集:のforeachループ上に追加されたオブジェクトは、それが10桁ベース4数だ

+0

私はこれを考えましたが、彼は10のforeachを必要としませんでしたか?それぞれが4つの選択肢を通過しますか? – weston

+0

@ westonええ、それは私にこのようにすることを混乱させている、私は実際にそれを正しく設定する方法がわからない –

+0

私はあなたが必要と確信していない10。あなたがヒットしたい4 propeties場合は、コレクション全体を「foreach」し、順番に各プロパティにアクセスします。 4つのプロパティは、4つのforeachループを意味します。私はまだリンクされているLINQパーミュテーションのソリューションは機能的で再帰的で、手動でループするかどうかを宣言するので、最もクリーンなソリューションだと思います。 –

3

ループ。 (私はそれがより適切と呼ばれていると考えると10進直積)何を探してるんですか

class Program 
{ 
    static void Main(string[] args) 
    { 
     int baseN = 4; 
     int maxDigits = 10; 
     var max = Math.Pow(baseN, maxDigits); 
     for (int i = 0; i < max; i++) 
     { // each iteration of this loop is another unique permutation 
      var digits = new int[maxDigits]; 
      int value = i; 
      int place = digits.Length - 1; 
      while (value > 0) 
      { 
       int thisdigit = value % baseN; 
       value /= baseN; 
       digits[place--] = thisdigit; 
      } 

      int choice = 0; 
      foreach (var digit in digits) 
      { 
       choice ++; 
       //Console.Write(digit); 
       switch (digit) 
       { 
        case 0: break; //choose Q from choice 
        case 1: break; //choose R from choice 
        case 2: break; //choose W from choice 
        case 3: break; //choose T from choice 
       } 
      } 
      //Console.WriteLine(); 
      // add it to your list of all permutations here 
     } 
     Console.WriteLine("Done") 
     Console.ReadLine(); 
    } 
} 
+0

私はこれを直接コピーしています。それは永遠に続くと思われます、それは私が期待していたはずのものです。 –

+0

コンソールに1,048,576行を表示するのに時間がかかるかもしれませんが、停止するでしょう。 'maxDigits'で' 6'を実行してみてください。 – weston

+0

'Console.Write'呼び出しを削除しても、' maxDigits'に '10'が入っていても、まったく時間がかかりません。 – weston

3

は10個のアレイのデカルト積です。エリックリペットは、ここでのアレイのarbtirary数のためにこれを行うには良い(と、非常に高度な)記事を書いた:http://ericlippert.com/2010/06/28/computing-a-cartesian-product-with-linq/

それの結末は、私は次の関数は、あなたがやりたいだろうと思うことです:

static IEnumerable<IEnumerable<T>> CartesianProduct<T>(this IEnumerable<IEnumerable<T>> sequences) 
{ 
    IEnumerable<IEnumerable<T>> emptyProduct = new[] { Enumerable.Empty<T>() }; 
    return sequences.Aggregate(
    emptyProduct, 
    (accumulator, sequence) => 
     from accseq in accumulator 
     from item in sequence 
     select accseq.Concat(new[] {item})); 
} 

ケース内の入力は、10個の配列の配列です。出力は、各ステップで10項目のienumerableを返すienumerableになります。基本的には、その関数の出力を反復してすべての可能な順列を取得します。

関連する問題