Introduction

Combination is the way of picking a different unique smaller set from a bigger set, without regard to the ordering (positions) of the elements (in the smaller set). This article teaches you how to find combinations. First, I will show you the technique to find combinations. Next, I will go on to explain how to use my source code. The source includes a recursive template version and a non-recursive template version. At the end of the article, I will show you how to find permutations of a smaller set from a bigger set, using both next_combination() and next_permutation().

Before all these, let me first introduce to you the technique of finding combinations.

The Technique

The Notations Used in this Article

n: n is the larger sequence from which the r sequence is picked.

r: r is the smaller sequence picked from the n sequence.

c: c is the formula for the total number of possible combinations of r, picked from n distinct objects: n! / (r! (n-r)!).

The ! postfix means factorial.

Explanation

Let me explain using a very simple example: finding all combinations of 2 from a set of 6 letters {A, B, C, D, E, F}. The first combination is AB and the last is EF.

The total number of possible combinations is: n!/(r!(n-r)!)=6!/(2!(6-2)!)=15 combinations.

I'm thinking if you would have noticed by now, the number of times a letter appears. The formula for the number of times a letter appears in all possible combinations is n!/(r!(n-r)!) * r / n == c * r / n. Using the above example, it would be 15 * 4 / 6 = 10 times. All the letters {A, B, C, D, E, F} appear 10 times as shown. You can count them yourself to prove it.

Source Code Section

Please note that all the combination functions are now enclosed in the stdcomb namespace.

The Recursive Way

I have made a recursive function, char_combination() which, as its name implies, takes in character arrays and processes them. The source code and examples of using char_combination() are in char_comb_ex.cpp. I'll stop to mention that function. For now, our focus is on recursive_combination(), a template function, which I wrote using char_combination() as a guideline.

The parameters prefixed with 'n' are associated with the n sequence, while the r-prefixed one are r sequence related. As an end user, you need not bother about those parameters. What you need to know is func. func is a function defined by you. If the combination function finds combinations recursively, there must exist a way the user can process each combination. The solution is a function pointer which takes in two parameters of type RanIt (stands for Random Iterator). You are the one who defines this function. In this way, encapsulation is achieved. You need not know how recursive_combination() internally works, you just need to know that it calls func whenever there is a different combination, and you just need to define the func() function to process the combination. It must be noted that func() should not write to the two iterators passed to it.

The typical way of filling out the parameters is n_column and r_column is always 0, loop is the number of elements in the r sequence minus that of the n sequence, and func is the function pointer to your function (nbegin and nend, and rbegin and rend are self-explanatory; they are the first iterators and the one past the last iterators of the respective sequences).

Just for your information, the maximum depth of the recursion done is r+1. In the last recursion (r+1 recursion), each new combination is formed.

An example of using recursive_combination() with raw character arrays is shown below:

Certain Conditions Must Be Satisfied In Order For next_combination() to Work

All the objects in the n sequence must be distinct.

For next_combination(), the r sequence must be initialized to the first r-th elements of the n sequence in the first call. For example, to find combinations of r=4 out of n=6 {1,2,3,4,5,6}, the r sequence must be initialised to {1,2,3,4} before the first call.

As for prev_combination(), the r sequence must be initialised to the last r-th elements of the n sequence in the first call. For example, to find combinations of r=4 out of n=6 {1,2,3,4,5,6}, the r sequence must be initialsed to {3,4,5,6} before the first call.

The n sequence must not change throughout the process of finding all the combinations, else results are wrong (makes sense, right?).

next_combination() and prev_combination() operate on data types with the == operator defined. That is to mean if you want to use next_combination() on sequences of objects instead of sequences of POD (Plain Old Data), the class from which these objects are instantiated must have an overloaded == operator defined, or you can use the predicate versions.

When the above conditions are not satisfied, results are undetermined even if next_combination() and prev_combination() may return true.

Return Value

When next_combination() returns false, no more next combinations can be found, and the r sequence remains unaltered. Same for prev_combination().

Some Information About next_combination() and prev_combination()

The n and r sequences need not be sorted to use next_combination() or prev_combination().

next_combination() and prev_combination() do not use any static variables, so it is alright to find combinations of another sequence of a different data type, even when the current finding of combinations of the current sequence have not reached the last combination. In other words, no reset is needed for next_combination() and prev_combination().

Examples of how to use these two functions are in next_comb_ex.cpp and prev_comb_ex.cpp.

So What Can We Do With next_combination()?

With next_combination() and next_permutation() from STL algorithms, we can find permutations!!

The formula for the total number of permutations of the r sequence, picked from the n sequence, is: n!/(n-r)!

We can call next_combination() first, then next_permutation() iteratively; that way, we will find all the permutations. A typical way of using them is as follows:

However, I must mention that there exists a limitation for the above code. The n and r sequences must be sorted in ascending order in order for it to work. This is because next_permutation() will return false when it encounters a sequence in descending order. The solution to this problem for unsorted sequences is as follows:

However, this method requires you to calculate the number of permutations beforehand.

So How Do I Prove They Are Distinct Permutations?

There is a set container class in STL we can use. All the objects in the set container are always in sorted order, and there are no duplicate objects. For our purpose, we will use this insert() member function:

pair <iterator, bool> insert(const value_type& _Val);

The insert() member function returns a pair, whose bool component returns true if an insertion is made, and false if the set already contains an element whose key had an equivalent value in the ordering, and whose iterator component returns the address where a new element is inserted or where the element is already located.

proof.cpp is written for this purpose, using the STL set container to prove that the permutations generated are unique. You can play around with this, but you should first calculate the number of permutations which would be generated. Too many permutations may take ages to complete (partly due to the working of the set container), or worse, you may run out of memory!

Comments and Discussions

I would like to generate all possible combinations using a sequence of vectors, where each vector contains all items that are allowed to stand at a certain place of the combination. For example, from the following input:

{ A } { A, B, C } { C } { D } { E, F }

I would like to get the following 5-item combinations:

AACDE<br />
AACDF<br />
ABCDE<br />
ABCDF<br />
ACCDE<br />
ACCDF

I use std::vector<std::vector<ITEM>> to represent the input, where ITEM is a class representing A, B, C, D, E or F. The result should also come as std::vector<std::vector<ITEM>>.

It looks like I might achieve the above result using your algorithm, but does it support variable counts/sets of allowed items at individual positions?

Here is the modified code below. Right now, the code can only handle 2 input vectors. If you need me to write code which can handle any number of input vectors (which is non-trivial to write), please let me know.

When running next_comb_ex.cpp in VS2005 (VC++ 8), I get a crash debug assertion when
the code gets runs next_combination in combination.h. It's bombing out at this line:

--tmp_r_begin;as the code tries to (via the prefix) go 1 BEFORE the first element of the iterator.

Given the context of this line ie.

BidIt tmp_r_begin=r_begin;<br />
--tmp_r_begin;

why would this be correct coding ie. why would we go backwards from first iterator element?

For the PoD plain array version no crash, but I do note the same thing at the code line:--temp_r_being
we are setting the address to one BEFORE the first element of the array. Isn't this dangerous (well not dangerous I guess - it's only a pointer) as we don't actually know what could be stored there?

For the code below, tmp_r_begin is equivalent to vector::rend(). I have to do that because I have to use != instead of >= to be compliant with the STL and its iterators. I did not de-reference anything at tmp_r_begin, so I thought that should be fine. Looks like that is not true for VC8.

<br/>
BidIt tmp_r_begin=r_begin;<br/>
--tmp_r_begin;<br/>

It worked for the POD array but not the container you are using, that is because the assertion is thrown out by the container iterator's -- operator.

thanks a lot for this excellent article! it seems, that it is the only(!) one in the net, which covers Permutations from a set of n elements, from which a sequence of r elements are picked.

one question: I´m using this code in a MSc. thesis and want to cite some reference for it, in order to explain, where the code is coming from. In a forum-posting, I found a reference to Donald Knuths "The Art of Computer Programming", but I dont have it at hand, so can you give me some references/hints?

in the prev_combination algorithm, is it possible to store each element in the combination to some variable (say P), convert that value to (P)/(P-1), and multiply them altogether? example: suppose the elements in my combination are {2, 3}. what i want to happen there is take the value (2)/(2-1)=2 and (3)/(3-1)=1.5 and multiply them (thus, the output i want to see is 2*1.5 = 3). or if my combination has the elements {3, 5}, then the algorithm should give me "(3)/(3-1)=1.5 times (5)/(5-1)=1.25 = 1.875"..

by the way, i'm no programming expert. i just need this code because i have to evaluate around 16 million combinations of certain numbers and look for the product similar to those examples i gave in the previous paragraph. i'd appreciate the quick response. thanks in advance!

I cannot send you a copy of the code because you will need the updated article to teach you how to use the code. Anyway, the updated article will emphasize on the explanation of algorithms more than on how to use my code.

keep in mind this is assuming that each character can only be used once in the combination

if you allow the characters to be used multiple times in the combination then i have the correct formula for that its (characters) ^ (length)
or the number of characters you can use to power of the length of the combination

for a length of 2 and 6 characters it is really 36
here is the table for that