Search code examples
c#algorithmlanguage-agnosticpermutation

Clean algorithm to generate all sets of the kind (0) to (0,1,2,3,4,5,6,7,8,9)


Basically, I'd like a set of sets that contains from (0..9), then (0, 1..9), (1, 2..9)..(8,9), and so on and so forth up until (0,1,2,3,4,5,6,7,8,9). I know this can be accomplished by nesting for loops in the manner below, but I'm wondering if there's a neater way of doing it?

Preferably something that could be accomplished within C#, but I'm interested in any algorithm.

for (int i = 0; i < max; i++) {
    yield {i};
    for (int j = i + 1; j < max; j++) {
        yield {i, j};
        for (int k = j + 1; k < max; k++) {
            yield {i, j, k};
            for (int l = k + 1; l < max; l++) {
                yield {i, j, k, l};
                for (int m = l + 1; m < max; m++) {
                    yield {i, j, k, l, m};
                    // And so on and so forth
                }
            }
        }
    }
}

Solution

  • I wrote this a while ago. It uses a Stack. It's generic, so it can be used for other sequences as well.

    static IEnumerable<T[]> CombinationsAnyLength<T>(params T[] values)
    {
        Stack<int> stack = new Stack<int>(values.Length);
        int i = 0;
        while (stack.Count > 0 || i < values.Length) {
            if (i < values.Length) {
                stack.Push(i++);
                int c = stack.Count;
                T[] result = new T[c];
                foreach (var index in stack) result[--c] = values[index];
                yield return result;
            } else {
                i = stack.Pop() + 1;
                if (stack.Count > 0) i = stack.Pop() + 1;
            }
        }
    }
    
    CombinationsAnyLength(1, 2, 3, 4) outputs:
    

    1 12 123 1234 124 13 134 14 2 23 234 24 3 34 4