Muszę stworzyć listę kombinacji liczb. Liczby są dość małe, więc mogę użyć byte
zamiast int
. Jednak wymaga wielu zagnieżdżonych pętli, aby uzyskać każdą możliwą kombinację. Zastanawiam się, czy istnieje skuteczniejszy sposób na zrobienie tego, o co mi chodzi. Dotychczasowy kod to:
var data = new List<byte[]>();
for (byte a = 0; a < 2; a++)
for (byte b = 0; b < 3; b++)
for (byte c = 0; c < 4; c++)
for (byte d = 0; d < 3; d++)
for (byte e = 0; e < 4; e++)
for (byte f = 0; f < 3; f++)
for (byte g = 0; g < 3; g++)
for (byte h = 0; h < 4; h++)
for (byte i = 0; i < 2; i++)
for (byte j = 0; j < 4; j++)
for (byte k = 0; k < 4; k++)
for (byte l = 0; l < 3; l++)
for (byte m = 0; m < 4; m++)
{
data.Add(new [] {a, b, c, d, e, f, g, h, i, j, k, l, m});
}
Rozważałem użycie czegoś takiego jak a, BitArray
ale nie jestem pewien, jak mógłbym to zastosować.
Wszelkie zalecenia będą mile widziane. A może to najszybszy sposób na zrobienie tego, co chcę?
EDYTUJ Kilka szybkich uwag (i przeprosiny, których nie umieściłem w oryginalnym poście):
- Liczby i ich kolejność (2, 3, 4, 3, 4, 3, 3 itd.) Są bardzo ważne, więc użycie rozwiązania takiego jak Generowanie permutacji za pomocą LINQ nie pomoże, ponieważ wartości maksymalne w każdej „kolumnie” są różne
- Nie jestem matematykiem, więc przepraszam, jeśli nie używam poprawnie terminów technicznych, takich jak „permutacje” i „kombinacje” :)
- I nie trzeba wypełnić wszystkie te kombinacje na raz - nie mogę po prostu chwycić jedną lub inny oparty na indeksie
- Używanie
byte
jest szybsze niż używanieint
, gwarantuję to. O wiele lepsze jest również wykorzystanie pamięci, aby mieć 67 mln + tablic bajtów zamiast int - Moim ostatecznym celem jest znalezienie szybszej alternatywy dla zagnieżdżonych pętli.
- Rozważałem użycie programowania równoległego, ale ze względu na iteracyjny charakter tego, co próbuję osiągnąć, nie mogłem znaleźć sposobu, aby to zrobić z sukcesem (nawet z
ConcurrentBag
) - jednak cieszę się, że się mylę :)
WNIOSEK
Caramiriel dostarczył dobrą mikro-optymalizację, która pozwala zaoszczędzić trochę czasu na pętli, więc oznaczyłem tę odpowiedź jako poprawną. Eric wspomniał również, że wstępne przydzielenie listy jest szybsze. Ale na tym etapie wydaje się, że zagnieżdżone pętle są w rzeczywistości najszybszym możliwym sposobem zrobienia tego (przygnębiające, wiem!).
Jeśli chcesz wypróbować dokładnie to, z czym próbowałem StopWatch
porównać, użyj 13 pętli zliczających do 4 w każdej pętli - to daje około 67 milionów linii na liście. Na moim komputerze (i5-3320M 2,6GHz) wykonanie zoptymalizowanej wersji zajmuje około 2,2 sekundy.