2012-02-01 12 views
5

Eventuali duplicati:
Generating all Possible CombinationsN-enumerables in una istruzione LINQ?

io non sono sicuro di come formulare la domanda; ma stavo lavorando a uno stupido puzzle logico che ero in grado di risolvere usando una dichiarazione LINQ. Il codice in questione si presentava così:

(from myA in Enumerable.Range(1, 40) 
from myB in Enumerable.Range(1, 40) 
from myC in Enumerable.Range(1, 40) 
from myD in Enumerable.Range(1, 40) 
where myA + myB + myC + myD == 40 
    && myA <= myB 
    && myB <= myC 
    && myC <= myD 
select new[] {myA, myB, myC, myD}) 

quindi è praticamente generare tutte le combinazioni di A, B, C D che soddisfano i criteri nella clausola WHERE.

Quello che sto cercando di fare ora è generalizzare, così posso fare esattamente la stessa cosa con N valori invece di solo quattro. Ad esempio, con 3 valori - il codice equivalente sarebbe:

(from myA in Enumerable.Range(1, 40) 
from myB in Enumerable.Range(1, 40) 
from myC in Enumerable.Range(1, 40) 
where myA + myB + myC == 40 
    && myA <= myB 
    && myB <= myC 
select new[] {myA, myB, myC}) 

Naturalmente, non voglio modificare il codice - Voglio una funzione che posso chiamare e di fornire un numero intero e farlo tornare il corretto oggetto.

Ho fatto alcuni tentativi sbagliati; ma davvero non riesco a vedere come fare una cosa del genere. Qualcuno può indicarmi la giusta direzione?

+4

Eric Lippert [bloggato su questo] (http://blogs.msdn.com/b/ericlippert/archive/2010/06/28/computing-a-cartesian- product-with-linq.aspx) per quanto riguarda i prodotti informatici di molte sequenze. Potrebbe aiutare. –

+0

@AnthonyPegram - È perfetto. Esattamente quello che sto cercando. Se vuoi pubblicarlo come risposta, lo accetterei. –

+0

Non è la * mia * risposta. ;) Se desideri dare credito a chi è dovuto il credito, [prova qui] (http://stackoverflow.com/a/3098381/414076) –

risposta

0

Non ho letto i collegamenti e non sono sicuro che questo sia l'approccio corretto, ma perché non immaginiamo di camminare su un albero di profondità n con ogni nodo che ha 40 (o 20 come nell'esempio) bambini? Si sarà simile a questa, allora:

class Program { 
    static void Main(string[] args) { 
     Walk(3).Where(l => l.Sum() == 20 && 
      l.Skip(1).Where((num, i) => num < l[i]).Count() == 0) 
     .ToList().ForEach(l => Console.WriteLine(string.Join(" ", l))); 
     Console.ReadLine(); 
    } 

    static IEnumerable<List<int>> Walk(int depth) { 
     return depth == 0 ? 
      new[] { new List<int>()} : 
      Enumerable.Range(1,20).SelectMany(i => 
       Walk(depth - 1).Select(l => l.Concat(new[] {i}).ToList())); 
    } 
}