As a companion article to my Permutation Generation, I now present Combination generation.
This snippet will do a lazy generation of the combinations of a set of objects. Each combination has a grouping size (number of items in each combination). If you need a different grouping size, you'll have to create a new instance.
As was done in the permutation class, you can request specific lexical combinations either by calling the method GetCombination or by using the index operator.
How to use:
First you'll need an array of object. Call the Combination constructor passing the array and the grouping size. Since this is a generic class, you'll have to provide the class type of the array (like all generics).
The test example will take an array of six strings, with a grouping size of 3, and:
- Display how many different combinations there are.
- Display all the combinations.
- Display the fourth lexical combination using a method call.
- Display the sixth lexical combination using indexing.
using System;
using System.Text;
using Whittle.Math;
namespace Whittle {
class Program {
static void Main(string[] args) {
int counter = 0;
String[] myItems = { "A", "B", "C", "D", "E", "F" };
Combination<string> myCombos = new Combination<string>(myItems, 3);
Console.WriteLine("For {0} items there are {1} combinations", myItems.Length, myCombos.NumberOfCombinations);
Console.WriteLine();
foreach (String[] perm in myCombos) {
Console.Write("{0} ", SeqFormat(perm));
counter = (counter + 1) % 6;
if (counter == 0) Console.WriteLine();
}
Console.WriteLine();
Console.WriteLine("The fourth lexical combination is {0}", SeqFormat(myCombos.GetCombination(4)));
Console.WriteLine();
Console.WriteLine("The sixth lexical combination is {0}", SeqFormat(myCombos[6]));
Console.ReadLine();
}
static String SeqFormat(String[] strings) {
StringBuilder sb = new StringBuilder();
sb.Append("[");
foreach (String s in strings) {
sb.Append(s);
}
sb.Append("]");
return sb.ToString();
}
}
}
How it works:
The wikipedia article explains it better than I ever could :)
Limitations:
Because this requires the use of factorials (even though they are generated in a unique way) it is possible to overflow the int variables used to generate the combinations. If you really need larger combinations, try changing all the int values to long, or BigInteger.
Acknowlegments:
As before, my sources are wikipedia and the 2006 MSDN Article "Test Run" by Dr. James McCaffrey.