Introduction

In my previous article, 'A C# Permutation Iterator', I presented a compact way to permutate over a sequence. In this article, I will expand my iterator to include combinations.

Using the Code

This iterator works recursively. The recursion terminal condition is when we elect to choose 0 elements, in which case the sequence is returned as is. In the recursive case, it is a bit more complex than the permutation iterator. The algorithm works by holding the first element, and making a recursive call on the rest of the sequence. This is done iteratively (n) times where (n) is the length of the sequence. However, each progressive iteration calls the recursion with an ever decreasing sequence length. As an example, here is a depiction of the process when choosing 2 elements from a sequence of 5 (the result of each iteration is the first 2 elements):

Sequence yielded

Comments

Result (the first 2 elements)

12345

The initial sequence and first result

12

13452

Inner rotation (starting at the 2nd element)

13

14523

Inner rotation

14

15234

Inner rotation

15

23451

Outer rotation

23

24531

Inner rotation - Note that the last element is now excluded from the rotation

24

25341

Inner rotation

25

34512

Outer rotation

34

35412

Inner rotation - Note how the last two elements are now excluded from the rotation

Points of Interest

There are many implementations of combination and permutation iterators to be found on the internet, however I particularly like this one due to the fact that it is light on memory, and doesn't create any unnecessary objects. The corollary of this, is that the sequence is modified while the iterator is running; if this is not desired, the iteration should be run on a copy of the original sequence.

Of course there are many ways to iterate over combinations, I am just posting one of them, which I like for its brevity, simplicity and efficiency (one might argue over the efficiency of RotateLeft - but it can be further optimized, especially if you work with a more advanced data structure than an array list).

I think @PIEBALDconsult has a valid point here, because you describe the algorithm as being "light on memory" without telling us what its memory (or time) complexity is.

Of course, the time complexity is more likely to be an issue for a user of this algorithm: as you rightly say, the RotateLeft is not a good approach.

In your permutations article space complexity wasn't an issue, since its infeasible to generate all permutations except for very small values of N. (Space complexity was O(N), time complexity was poor due to the RotateRight. Note: despite their names IList only guarantees an indexable data structure and List is implemented as an indexable array. LinkedList therefore doesn't implement IList for obvious reasons. )

An indication of time and space complexity, preferably in "Big O notation", would be a useful addition to the article.

I'm currently working on an almost equally simple implementation of O(N) (N - is the size of the output, not the input in this case) time complexity using LinkedList. The LinkedList can be employed to provide such time complexity for permutations as well.

I am not sure if I should update my 2 articles or if I should post a new once, since the implementation is quite different.

If you post an article here you will be seen as an expert. Therefore you should post the very best code you can.
There are people who will download your code and use it in production environments thinking it's safe to do so.

Isn't that the point here? So far all I have seen from you is a lot of complaining and an arrogant attitude, like if you have done all of this at least once in the last year, surely all competent programmers have also. Fact is, serious searching among the forums I find get with a google for combinations and permutations yields a lot of recursive implementations and barely a single example of any other choice. If you have an elegant answer to combos and permutes using IEnumables or something other than recursion, put up or shut up as the old saying goes. There are a lot of new and upcoming programmers out there that would benefit much more by that offering that what you have offered so far.