C# - Требуется алгоритм для комбинаций Power Set / Sub-Set, но только для фиксированного числа элементов

В порядке,

Это расширение этой проблемы - Супер набор в списке:

Получение всех возможных комбинаций из списка номеров

Это помогает, но возвращает все подмножества: http://rosettacode.org/wiki/Power_set

Но мне нужно получить только те подмножества, которые имеют фиксированное число. Т.е. мой список представляет собой набор чисел:

1 2 3 4 5 6

Мне нужны только разные комбинации для точных 4 чисел, т.е. 1,2,3,4 1,2,3,5 1,2,3,6 1,3,4,5 1,3,4,6 1, 4,5,6 2,3,4,5 2,3,4,6 2,4,5,6 3,4,5,6

Я использую числа в качестве примера, но в своем решении я имею дело с другими типами объектов.

Я на 100% уверен, что это очень легко решить для тех, кто знает....

заранее спасибо

2 ответа

Решение

Вы можете расширить решение, на которое вы ссылаетесь, отфильтровав длину результатов

public IEnumerable<IEnumerable<T>> GetPowerSetOfLength<T>(List<T> list, int length)
{
    return from m in Enumerable.Range(0, 1 << list.Count)
              //because doing a count will iterate through the enumerable 
              //better to just convert it to a list up front 
              let setResult = ( from i in Enumerable.Range(0, list.Count)
                                where (m & (1 << i)) != 0
                                select list[i]).ToList()
              where setResult.Count==length
              select setResult;
}

Вот ссылка на скриптовую точку, которая использует этот код, если вы хотите проверить его

Предполагая, что вы всегда хотите ровно 4, это относительно простой алгоритм написания с использованием вложенных циклов for.

var set = new[] {1, 2, 3, 4, 5, 6};

for (int firstIndex = 0; firstIndex < set.Length; firstIndex++)
{
    for (int secondIndex = firstIndex+1; secondIndex < set.Length; secondIndex++)
    {
        for (int thirdIndex = secondIndex+1; thirdIndex < set.Length; thirdIndex++)
        {
            for (int fourthIndex = thirdIndex+1; fourthIndex < set.Length; fourthIndex++)
            {
                Console.WriteLine(string.Format($"{set[firstIndex]}, {set[secondIndex]}, {set[thirdIndex]}, {set[fourthIndex]}"));
            }
        }
    }
}

Если вам нужно, чтобы он был динамическим и поддерживал разные размеры списка (т.е. это не всегда 4), то, вероятно, легче преобразовать в рекурсивный вызов, который повторяется N раз.

Другие вопросы по тегам