-2

I have a List<Object>. I have an int maxSize. I want a List<List<Object>> containing all combinations of objects of maxSize (this lists are maxSize, not the objects), or less.

I've seen solutions to problems that looks like my problem, except they aren't my problem and evidently my brain isn't smart enough to figure it out. I've also already spent 3 days on my overall problem trying to recurse myself to oblivion, so I'm just looking for solutions that just work at that point.

Requirements:

  • It has to return a List<List<Object>>, not anything else.
  • It has to take a List<Object> and int as arguments. If it needs more arguments for recursion or whatever, it's fine. The first two args are still a List<Object> and an int, not anything else.
  • Each List<Object> can only be of maxSize, or less. The "or less" requirement is optional, I can work without it.
  • Order does not matter. {1,2} equals {2,1}.
  • Duplicates are not allowed. If it contains {1,2}, it cannot contain {2,1}.
AmiralPatate
  • 125
  • 1
  • 7
  • 2
    Don't use html to format your code. It's very difficult to re-format it then. Use the inbuilt editor features, especially the `code`-button after you've selected the text to format.. – Tim Schmelter Mar 31 '16 at 09:04
  • What's stopping you from using the C# answer in [the top related question](http://stackoverflow.com/questions/127704/algorithm-to-return-all-combinations-of-k-elements-from-n?rq=1) in a loop of 1 to maxSize? – Martheen Mar 31 '16 at 09:10
  • Because it doesn't return a List of List, and since I don't understand half of what it does, I can't figure how to adapt it. – AmiralPatate Mar 31 '16 at 09:14
  • [ToList](https://msdn.microsoft.com/en-us/library/bb342261%28v=vs.100%29.aspx) – Martheen Mar 31 '16 at 09:27

1 Answers1

2

Here's a slight modification to my answer to this question:
Clean algorithm to generate all sets of the kind (0) to (0,1,2,3,4,5,6,7,8,9)

static IEnumerable<List<T>> Subsets<T>(List<T> objects, int maxLength) {
    if (objects == null || maxLength <= 0)
        yield break;
    var stack = new Stack<int>(maxLength);
    int i = 0;
    while (stack.Count > 0 || i < objects.Count) {
        if (i < objects.Count) {
            if (stack.Count == maxLength)
                i = stack.Pop() + 1;
            stack.Push(i++);
            yield return (from index in stack.Reverse()
                          select objects[index]).ToList();
        } else {
            i = stack.Pop() + 1;
            if (stack.Count > 0)
                i = stack.Pop() + 1;
        }
    }
}

Example of usage:

var numbers = new List<int>{1,2,3,4,5};
foreach (var subset in Subsets(numbers, 3)) {
    Console.WriteLine(string.Join("", subset));
}

If you need a List<List<int>>, just call ToList() on the result.

Community
  • 1
  • 1
Dennis_E
  • 8,751
  • 23
  • 29