2017-05-23 5 views
0

事前定義されたint []から10個の整数のすべての可能な組み合わせを生成できる必要があります。リスト。各組み合わせは、の長さ5である必要があります。データソース[10]が必要な組み合わせの長さ[5]より大きい組み合わせを生成する

例:

{1, 2, 3, 4, 5}, 
{2, 3, 4, 5, 6}, 
{3, 4, 5, 6, 7}, etc. 

私はこれまで、次のいる:

int[] cardFaces = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; 
List<int[]> combos = new List<int[]>(); 

// For every value in the cardFaces array, get the value and the index. 

foreach (var item in cardFaces.Select((value, i) => new { i, value })) 
    { 
    int value = item.value; 
    int index = item.i;  
    int value1 = 0; 
    int value2 = 0; 
    int value3 = 0; 
    int value4 = 0; 
    int value5 = 0; 

    // Need some nested loop code here, which will create combinations 
    // from the cardFaces[] with a length of 5. 

    int[] combo = {value1, value2, value3, value4, value5}; 

    combos.Add(combo); 

    } 

これは、任意の繰り返しを含むべきではありません。私はこれにかなり新しいので、私は必要な組み合わせを得るためにループに取り組む方法を考えるのに苦労しています。

+0

私は(HTTPS [組み合わせ、パート1を生産]だと思います。com/2014/10/13/producing-combination-part-one /)が役立つ可能性があります – stuartd

答えて

1

もっと一般的な実装です。選択する項目のリストと選択する項目の数が表示されます(k)。あなたの場合、k = 5

このように動作します。ソースリストの最初のk要素を指すkの「ポインタ」を初期化します。これが最初の組み合わせです。視覚我々は持っている:

source: [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ] 
pointers:^^^^^

、次の組み合わせを取得し、ポインタの最後をインクリメントするには:

source: [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ] 
pointers:^^^^ ^

そのポインタは、その後、我々は、前に行って、今、リストの末尾過去1である場合それをインクリメントして、最後のポインタをそのポインタの後ろに1つ移動します。したがって、現在の組み合わせが次のようになっているとしましょう:

source: [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ] 
pointers:^^^^    ^

最後のポインタを増やすと、最後を超えてしまいます。代わりに、我々は最後から次のポインタを見て、それをインクリメントし、それの後に私たちの最後のポインタ1を置くので:

source: [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ] 
pointers:^^^ ^^ 

をその後、我々は戻っていつものように最後のポインタをインクリメントする行く:

source: [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ] 
pointers:^^^ ^ ^

source: [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ] 
pointers:^^^ ^ ^

そして、そうです。最後のポインタが最後に来るたびに、最後のポインタの次のポインタを移動します。終わりになると(実際には前に1つ)、を次のに戻します。基本的に最後のポインタが終わりに達すると、前方に移動できるポインタが見つかるまで、ポインタのリストを順方向に移動します。一度見つけたら、それに続くすべてのポインタを設定します。たとえば、

source: [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ] 
pointers:^    ^^^^

ポインタをループして、最初のものを除いて移動できないことに気付くでしょう。だから我々は、次のスポットへの1、その後、その直後、右であることを他のすべてをリセットすることを移動します。

source: [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ] 
pointers: ^^^^^

最初のポインタが最後からk個の要素よりも小さい場合には、我々は最後の組み合わせにいると、私たちは立ち止まることができる。

このようなコードで

、:// ericlippert:

public static IEnumerable<IEnumerable<T>> GetOrderedPermutations<T>(IList<T> source, int k) 
{ 
    if(k == 0) yield return Enumerable.Empty<T>(); 
    if(k == source.Count) yield return source; 
    if(k > source.Count) yield break; 
    var pointers = Enumerable.Range(0, k).ToArray(); 

    while(pointers[0] <= source.Count - k) 
    { 
     yield return pointers.Select(p => source[p]); 

     pointers[k - 1]++; 

     int i = k - 2; 
     while(pointers[k - 1] >= source.Count && i >= 0) 
     { 
      pointers[i]++; 

      for(int j = i + 1; j < k; ++j) 
      { 
       pointers[j] = pointers[j - 1] + 1; 
      } 

      --i; 
     } 
    } 
}