Combinations have many use cases in the daily life of a programmer: for
testing a given function, for generating the all possible input sets of a
particular problem instance, etc. Writing them down in lexicographic order is
something we all do time to time. For instance, 2-combination of a set
can simply be written as follows.

We also have a shortcut to get the total number of combinations for a particular
instance. That is,

which applies to our above example 4-choose-2 as follows:
.

You might also have noticed the pattern we used to generate the combinations in
lexicographic order. The algorithm finds the rightmost index element that can be
incremented, increments it, and then changes the elements to the right to each
be 1 plus the element on their left. This procedure repeats until there are no
more rooms left to increment. (You might want to check out Applied
Combinatorics by Alan Tucker for further details of the algorithm.)

One advantage of generating combinations in lexicographic order using the above
algorithm is that given the ‘th combination, one can easily generate
‘th combination. Which leads us to the fact that one can continue
generating combinations given the combination at a particular position.

The Problem

In the case of a single consumer, one can iterate over a set of combinations
step by step. However, what if there are multiple consumers? In this case, a
single producer can present a central combination queue, where it pushes new
combinations on demand, and then the consumers can poll the queue as they
desire. That being said, in this setup the producer can become the bottleneck.
That is, what if consumers poll the queue at a speed faster than the producer’s
push rate? Houston, we have a problem.

Previously we have seen that given the ‘th combination, we can compute the
‘th one. In addition, we also know how to calculate the total number of
combinations, that is, . With this in mind, we can split the
all possible combinations set into two separate parts:

Going from to is trivial, we can keep a counter for the
generated combinations up to . But what about ? How can we
compute the ‘th combination without having a prior information about
‘th one. In other words, can we calculate , given just and
?

Enumerating Combinations

Lucky for us, there exists a vast literature for combinatorial number
system, where people
come up with a way to enumerate combinations. Long story short, combinatorial
number system presents a mapping between natural numbers (taken to include 0)
and the combinations. In a combinatorial number system of degree , each
natural number map to a one and only one r-combination
with the following equality.

For instance, let and . Here corresponds to the
2-combination in combinatorial number system of degree 2 with the
following equality.

The r-combination of a given number can be computed using the following
greedy algorithm: take maximal with , then
take maximal with ,
and so forth.

So far so good. Let’s do the magic. Suppose that we want to enumerate the
combinations of 5-choose-2. That is, we want the following mapping.

We know that , hence we have 10 combinations enumerated
from 0 to 9. Let’s try to find the 3rd combination in this sequence from
scratch.

First, we set to the index of the combination we are interested in:

Second, we set to the dual index of in system:
.

Now let’s find the 2-combination of : ,
that is, the 2-combination corresponding to is .

Next we subtract the found 2-combination from the mask , where 4’s
comes from : .

Yay! 3rd combination of system is ! Hrm… Was that
a coincidence? Let’s give it another try with 8th combination this time.

First, we set to the index of the combination we are interested in:

Second, we set to the dual index of in system:
.

Now let’s find the 2-combination of : ,
that is, the 2-combination corresponding to is .

Next we subtract the found 2-combination from the mask :
.

8th combination turns out to be . Eureka!

Conclusion

We have shown that using -combinations one can compute the ‘th
combination among the lexicographically ordered set of combinations of
-choose-, where . Using this method we
can partition the space of all combinations into multiple subsets and generate
each of them individually. For this purpose, I put together a Java library:
combination. Here is a sample snippet.