С# (математика, комбинторика) перебор всех подмножеств данного множества

У меня есть список чисел небольшой (длина <= 5 элементов). Мне нужно разбить его на под-списки (или массивы) которые будут содержать все варианты пар, троек, четвёрок чисел без повторений (порядок не имеет значения).

Пример для списка [a, b, c, d, e]:

  • Список одиночных чисел и есть исходный список [a, b, c, d, e] - 5 элементов
  • Список пар [ [a,b], [a,c], [a,d], [a,e], [b,c], [b,d], [b,e], [c,d], [c,e], [d,e] ] - 10 элементов
  • Список троек [ [a,b,c], [a,b,d], [a,b,e], [a,c,d], [a,c,e], [a,d,e], [b,c,d], [b,c,e], [b,d,e], [c,d,e] ] - 10 элементов
  • Список четвёрок [ [a,b,c,d], [a,b,c,e], [a,b,d,e], [a,c,d,e], [b,c,d,e] ] - 5 элементов
  • Список пятёрок (токо одна возможна) [ [a,b,c,d,e] ] - 1 элемент

Не могу понять как сделать универсальный перебор для любого размера и что бы не расписывать в кучу строк. Спасибо заранее)

UPD: прикрепил ответ с готовым цыклом


Ответы (1 шт):

Автор решения: KuzCode

Вот, что у меня получилось в результате:

char[] arr = new char[]{'a','b','c','d','e'};
var result = new List<List<char>>();

for (int mask = 0; mask < (1 << arr.Length); mask++)
{ //перебор масок
    result.Add(new List<char>());

    for (int j = 0; j < arr.Length; j++) //перебор индексов массива
    {
        if((mask & (1 << j)) != 0) //поиск индекса в маске
        {
            result.Last().Add(arr[j]); // добавление элемента
            Console.Write(arr[j] + " "); //вывод элемента
        }
    }

    Console.WriteLine(); //перевод строки для вывод следующего подмножества
}

Вывод:

a 
b 
a b 
c 
a c 
b c 
a b c 
d 
a d 
b d 
a b d 
c d 
a c d 
b c d 
a b c d 
e 
a e 
b e 
a b e 
c e 
a c e 
b c e 
a b c e 
d e 
a d e 
b d e 
a b d e 
c d e 
a c d e 
b c d e 
a b c d e 

Что бы не создавался массив с нулевой длинной можно изменить стартовое значение mask на 1.

→ Ссылка