Click here to Skip to main content
Click here to Skip to main content

Combinatorial algorithms in C#

By , 19 Aug 2002
 

Introduction

In this article will be presented a small number of classes that can be used to perform some basic combinatorial operations on collection of objects. Here you won’t find a detailed explanation of how the code works, but mainly on how to use these utility classes. The source code is small (only 4 classes in 4 files) so if you want to see how the algorithms are implemented, have a look there.

The purpose of the utilities shown here is to present the programmer with an easy way of generating all the possible combinations, permutations and variations from a collection of objects. For example, suppose that you have balls numbered from 1 to 35 put in a black box, and want to pick up 5 of them. Then the possible combinations of 5 balls to be taken from a total number of 35 are approximately 325,000. The presented classes will generate every single one of them. This is usually very handy if you have a theory of how the black box works and test all the combinations against your theory in order to figure out what is the most likely combination of 5 numbers to be drawn.

Details

First write:

using Combinatorial;

Now declare your array of integers :

Array myIntArray = Array.CreateInstance(
    Type.GetType("System.Int32"), 35);
for (int j = 0; j < myIntArray.Length; j++)
    myIntArray.SetValue(j, j);

Then make a combinatorial object to manipulates the objects in this array (in this particular case the objects are of type System.Int32) like this :

Combinations combs = new Combinations(myIntArray, 5);

Now write a cycle to generate all the possible combinations of 5 integers from 35.

while(combs.MoveNext()) {

    Array thisComb = (Array)combs.Current;

    for (int i = 0; i < thisComb.Length; i++) {
        // Just access the value. This requres boxing.
        int nVal00 = (int)thisComb.GetValue(i);
        // Just access the value. This requres no boxing.
        Object nVal01 = thisComb.GetValue(i);		
}

The Combinations, Permutations and Variations classes all support the System.Collections.IEnumerate interface, so it is very easy to cycle through them. If you want to reset these objects just call the Reset() member function. After that, all the combinations generation will start anew.

The collection that is going to be used is passed as a parameter to the constructor of the combinatorial object. This means that you cannot reinitialize the object with a new collection when you have finished using the current one, but have to create an entirely new Combinations (or some of the others) object.

There are three possible constructors :

protected CombinatorialBase(Array arrayObjects, int nKlass );
protected CombinatorialBase(IList listObjects, int nKlass );
protected CombinatorialBase(IEnumerator enumeratorObjects, 
    int nKlass );

As you can see, you can pass any collection that supports either IList or IEnumerator interfaces. Or you can pass any array of objects. This means that you can use these classes on almost every collection met in the .NET framework. Because the combinatorial classes support the IEnumerate interface itself, you actually can create constructs like : combination of combinations or permutations of combinations of variations and all the stuff like this, that you can think of. However I strongly advice you not to do so (unless for a situation with small number of combinations) because the constructor cycles through all the objects that it have to manipulate ( the objects in the collection). If you pass another combination this process can take a lot of time.

Armed with all the constructors from above we can use code like this :

double[] doubles = new double[10];
for (int j = 0; j < doubles.Length; j++)
    doubles[j] = (double)j;

// Generate the  combinations of 5  numbers from a bunch of 10
Combinations combs = new Combinations(doubles, 5);

Or like this when using ArrayList :

ArrayList myArrayList = new ArrayList(15);
for (int j = 0; j < 10; j++)
    myArrayList.Add("str"+j.ToString());

// Generate all the permutations of 10 objects.
Permutations perms = new Permutations(myArrayList);

And even some unusual constructs like this one here :

string myString = "abcdefghij";

// Generate all the possible five char combinations from the 
// letters of this string.
Combination combs = new Combination(myString.GetEnumerator(), 5);

And now a little note for those of you who would say : Hey isn’t it true that we can generate all the permutation of 5 elements, by generating all the variations of those five elements of size (class) 5 ?

This means that :

Permutations combs = new Permutations(myArrayList);

and

Variations combs = new Variations(myArrayList, myArrayList.Count);

actually do the same thing.

So why we need a Permutation object, when we have a more general Variation object? The truth is, that mathematically they do the same. But because the algorithms for generation of Combinations and Permutation are so much easier to implement than those of Variations, these two objects are the basis of this library. The Variations object actually uses the combinations and permutations to generate all the possible variations. If you need only permutations, please always use the Permutation class.

One last thing to mention : This library generates only combinations, variations and permutations without repetition. If you need repetition you have to implement it yourself. I do not have a need for such functionality right now, so probably won’t write it very soon.

Conclusion

Some may ask why haven’t I implemented the IEnumerable interface (like in the String or Array classes), but chose the IEnumerate instead. The IEnumerable interface has just one method : GetEnumerator() that returns an enumerator. Each time you request an enumerator this interface should return to you a valid enumerator over the sequence. And one very important thing : If you have requested enumerator over the same sequence previously it must not become invalid, because it still may be in use. This is impossible with the current implementation of the Combinatorial classes and I don’t see a way to easily modify this. So I supply just IEnumerate for now.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

About the Author

gybrush
Web Developer
Bulgaria Bulgaria
Member
No Biography provided

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
QuestionNice Job!memberMember 39299965 Jul '12 - 20:42 
Thanks for the article!
QuestionA recursive program in C to generate nCkmemberManohar Bhat20 Jan '12 - 9:06 
#include<stdio.h>
#include<stdlib.h>
#include<conio.h>
 
int nCk(int n,int loopno,int ini,int *a,int k)
{
    if(k==0)
    return 1;
    static int count=0;
    int i;
    loopno--;
    if(loopno<0)
    {
        a[k-1]=ini;
        for(i=0;i<k;i++)
        {
            printf("%d,",a[i]);
        }
        printf("\n");
        count++;
        return 0;
    }
    for(i=ini;i<=n-loopno-1;i++)
    {
        a[k-1-loopno]=i+1;
        nCk(n,loopno,i+1,a,k);
    }
    if(ini==0)
    return count;
    else
    return 0;
}
 
void main()
{
    int n,k,*a,count;
    printf("Enter the value of n and k\n");
    scanf("%d %d",&n,&k);
    a=(int*)malloc(k*sizeof(int));
    count=nCk(n,k,0,a,k);
    printf("No of combinations=%d\n",count);
    getch();
}

GeneralNeed helpmemberVikas Misra(TCS)14 Oct '09 - 4:21 
Looks gr8 stuff. I am basically C# developer. In C# and in any other coding language too, many a times we came across a situation to find out number of possible cases based upon two set of values say
 
A variable A may have 2 possible values in code 1) Null 2) Not Null
And same for Variable B Now if we look for possible combination of A and B it will be only one i.e. AB but cases will be 4 i.e 2(possible cases of A)*2(Possible cases of B).
 
And you can have these values for the combination of AB cases
 
1) A(Null) B(Not Null)
2) A(Null) B(Null)
3) A(Not Null) B(Null)
4) A(Not Null) B(Not Null)
 
You can take this as SET A has 2 possible values abd SET B has 2 possible values
And we have to make all possible combination of two selecting one value from each set.
 
Can u write a program or guide me to how to achieve this.
GeneralCombinatorics...membergourmettt17 Jul '08 - 21:15 
Hi!
 
I need a Method that performs something like this:
I have x searchparameter (A and B) and y fields (a,b,c (eg. FirstName, LastName, MiddleName)) that can be searched for:
My Querystring should look like indicated in the table:
 

     Where    (a)                (b)                (c)
              like     and       like       and     like
        --------------------------------------------------------------------
            (A&B)                                               |    or
                                 (A&B)                          |    or
                                                     (A&B)      |    or
            (A)                  (B)                            |    or
            (B)                  (A)                            |    or
            (A)                                      (B)        |    or
            (B)                                      (A)        |    or
                                 (A)                 (B)        |    or
                                 (B)                 (A)        |    or
 
I´m really stuck, any hint is much appreciated:
wirth@jos.zzn.com
 
Thank you all!
GeneralLicense IssuememberÖzgür Akdemirci21 Apr '08 - 2:40 
Since no license is attached, I have to ask this question.
Can I use your source code for a non-commercial, educational purpose project.
I want to use your library for a master's thesis to output the combination list of a given set of nodes.
Thanks in advance.
GeneralRe: License Issuemembergybrush21 Apr '08 - 10:03 
Yes, please be my guest. You can use it for any purpose that you want, commercial or educational. No need to mention anything - it is completely and utterly free and you can do whatever you want with it.
GeneralRepeated ItemsmemberAndre Falci2 May '07 - 7:14 
How can I have permitations with repeated values like:
 
mystring = "AB";
 
Possible Combinations:
 
AA - AB - BA - BB
 
Thank you in advance, best regards and congrats for the article.
 
Andre
GeneralUsed this to solve brainteasermemberigitur11 Apr '07 - 14:30 
Firstly, shouldn't indeces be indices?
 
Secondly, I'm part of a daily brainteaser mailing list. Sometimes I try to solve the puzzles by brute force, rather than struggling for hours on paper.
 
I used your classes to solve this riddle:
Cheri, Kelsey, Ramik, and Taylor had 16 coins all together
consisting of 4 pennies, 4 dimes, and 8 nickels. They each
had the same number of coins, but not an equal amount of
money. (For those who do not know, a dime=10c, a nickel=5c and a penny=1c)
 
Clues:
1. Taylor had the least amount of money, but just 1 cent
less than Kelsey.
2. Ramik had no pennies, but had the most money.
3. Cheri and Kelsey are the only ones who had at least one
of each coin.
 
How much money did each person have?

GeneralAnother examplemembergeblack31 Jul '06 - 8:37 
Another combinatory example can be found at
http://msdn.microsoft.com/msdnmag/issues/04/07/TestRun/[^]
GeneralTime Savermemberydrabu21 Jun '06 - 17:34 
Thanks for this code. I was halfway when it occured to me to look on code project and I came across this article. I took the liberty of alter it to suit my application. Hope you don't mind. And many thanks saved me a few hours! It works well.
 
Yasir Drabu
http://www.yasirdrabu.name
QuestionNeed help in combinationmemberobaid_8419 Dec '05 - 20:05 
plz tell me how to implement combination for the following :-
suppose i have a string "abcdef"
how to make unique sets of 4,5 characters using combination logic eg "abcd","aedc" -4 chars set or "abcde","abdef" -5 chars set.
 
plz mail me obaid_84@hotmail.com
 
Thanks & Regards
Obaid :->
GeneralCard Game HelpmemberTMcGee29 Jun '05 - 4:33 
I would like to use this library to help me evaluate a Gin Rummy Hand.
 
For instance if I have the following cards Ah, 2h, 3h, 7c, 7s, 7d, 8s, 9s, Jd, Kh. Then I want to get the following combinations {Ah,2h,3h}, {7c,7s,7d}, {7s,8s,9s}.
 
I can then determine which combinations give me the best hand. Any help would be greatly appreciated.
 

 
Thanks,
 
McGee
GeneralRe: Card Game HelpmemberDaniel Persson25 Jun '06 - 21:15 
If i get this right. I think you can do it this way:
Generate ALL three-card hands.
Build some kind of weighting function that can set a specific value to a hand, the greater number the better hand.
Now sort all of your hands using this wighting-function.
Pick the first one in the list.
Now try to pick the seccond one also, if two cards match, discard the seccond hand. Try the same with the third hand instead. Do this until two cards do not match. Now you have three cards left = one hand, run these cards through your weighting function. Sum all the three weighting values and get a result for your hand.
 
Now try exactly the same thing but instead of starting with the first hand you start with the seccond hand and walk your way down...
 
Not very efficient, but you can brake the search early if you consider that the list of hands is sorted. I think you'll pretty easy come up with a way to check for this.
QuestionTotal permutations?memberChris Sells17 Aug '03 - 13:40 
I’m struggling with generating permutations of n numbers that add up to 100 in increments of 5, e.g. if n = 3, than 0,0,100 and 0,95,5 and 0,90,10 are the first few permutations. Can I use your code to generate my totals?
 
Chris Sells
http://www.sellsbrothers.com/
AnswerRe: Total permutations?memberPete Burgess18 Oct '05 - 3:11 
Can you generate permutations of the numbers 1-20, check which perms add up to 20 and then return those numbers *5?
 
PeteB
I wouldn't say "he's not the sharpest knife",
I'd say "he's a spoon."

GeneralNice articlememberleppie22 Aug '02 - 9:22 
Got a need for it, but didnt even know it was here Smile | :)
 
MYrc : A .NET IRC client with C# Plugin Capabilities. See
http://sourceforge.net/projects/myrc
for more info. Big Grin | :-D
GeneralarraymemberGoran Mitrovic20 Aug '02 - 12:28 
It's not really related to your article/classes, but, why are you creating an array with Array.CreateInstance()?!
 
Are you aware that any array can be cast to object[], if that was the reason you did that?
 

 
- Goran.

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Permalink | Advertise | Privacy | Mobile
Web04 | 2.6.130523.1 | Last Updated 20 Aug 2002
Article Copyright 2002 by gybrush
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid