| By James McCaffrey | Article Rating: |
|
| June 21, 2006 02:00 PM EDT | Reads: |
19,406 |
The Choose() Method
The last method in my class is
one that returns the total number of combination elements for specified
values of set size n and subset size k as you can see in Listing 4.
In mathematics this function is often called Choose() so I use it here too. Recall from the beginning of this article that Choose(5,3) returns the number of combination elements of 5 strings taken 3 at time. I declare the function as Shared because it's not really tied to a particular instance of a StringCombination element; so when I call the function I'll call it as StringCombination.Choose(5,3) rather than instantiating a StringCombination object (say c, for example) and calling as c.Choose(5,3). First, I check my input parameters to make sure their values aren't zero or negative. This is arbitrary to some extent and you may want to modify your definition of Chosse(n,k) if n or k or both are zero.
Now, the mathematical definition of Choose(n,k) is n! / (n! * (n-k)!) where n! is "n factorial." You might recall from a math course that 3! = 3 * 2 * 1 = 6, and 4! = 4 * 3 * 2 * 1 = 24, and so on. Implementing a Choose method from the math definition is a very bad approach because the value of n! gets very, very large, very quickly. For example, the value of 64! is 64 * 63 * 62 * . . . * 1 = 126,886,932,100,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000, 000,000,000,000,000,000,000 - approximately.
With the Visual Basic.NET-type Integer, the longest factorial that can be stored without overflow is only 12!
Anyway, the point is that if you use factorial calculations, your intermediate results will likely overflow even for small values of n and k. A better algorithm is to use an alternative definition of Choose():
Choose(n,k) = (n * (n-1) * (n-2) * . . . * (n-k+1)) / (1 * 2 * . . . * k).
For example, Choose(5,3) = (5 * 4 * 3) / (1 * 2 * 3) = 60/6 = 10. The idea is to compute partial products and divide as you go rather than compute two huge numbers and divide them. A second optimization for the Choose() implementation comes from the fact that, as it turns out:
Choose(n,k) = Choose(n, n-k).
For example, Choose(20,17) = Choose(20,3).
This isn't an obvious relation but if you work out a few examples on paper you'll see why it's true. Calculating Choose(20,17) involves 16 partial products and divisions, but calculating the equivalent Chose(20,3) requires only two partial products and divisions. Putting these ideas leads to the implementation of Choose() above. I use the variable diff to hold the difference between n and k, and I use the variable newk to hold the smaller of k and n-k.
I'll leave it to you to walk through a couple of examples to see the other details of exactly how the algorithm works.
Using the StringCombination Class
With the
StringCombination class implemented as described and saved as
StringCombinationsLib, you can easily create and manipulate string
combinations. For example, you can create a new Visual Studio Console
Application program. Then add a project reference to the
StringCombinationsLib and an Imports StringCombinationsLib statement.
With that done you can write code like:
Dim items As String() = New String() {"alpha", "beta", "delta", "gamma"}
Console.WriteLine("Number of 4 items taken 2 at a time is " &
StringCombination.Choose(4, 2))
Dim c1 As StringCombination = New StringCombination(items, 2)
Console.WriteLine("The initial element is " & c1.ToString())
Dim c2 = c1.Successor()
Console.WriteLine("The next element is " & c2.ToString())
And to print all string combination elements you can write code like this:
Dim items As String() = New String() {"alpha", "beta", "delta", "gamma"}
Dim c As StringCombination = New StringCombination(items, 2)
While Not c Is Nothing
Console.WriteLine(c.ToString())
c = c.Successor
End While
Notice that at the end of the While loop, the string combination object c will have value Nothing, so you'll have to re-instantiate it if you want to use it further.
Discussion, References, and Conclusion
String
combinations have a wide range of use in development, testing, and
management. For example, suppose you're a tester and you have to feed
three string arguments to a function under test. If you have a pool of
five possible strings, you can use the code in this article to generate
the 10 possible test case input sets programmatically.
Or suppose you're a program/project manager and you have to look at hardware/software configuration combinations of an operating system (Windows 98, Windows 2000, Windows XP), RAM (128MB, 256MB), and so on. You can programmatically generate configuration scenarios rather than try to grind them out manually.
The number of situations where you can use string combinations is absolutely enormous once you start looking for them.
The code I've presented here is designed for maximum flexibility and ease of modification rather for than efficiency. Consider the overall class design, for example. Notice that each instance of a StringCombination class has the exact same orig array that holds the original strings. You might want to consider modifying the design by making the orig array Shared like so:
Private Shared orig As String() = Nothing
With this approach, there's only one orig array that's shared by all instances of the StringCombination class. If you are a C# programmer, Shared is the Visual Basic.NET equivalent of a static class field. Unfortunately, if you use this design you can only have a particular flavor of StringCombination objects in scope at any given time. In other words, if you create a string object with five animal strings then in the same program scope create a second string object with four color strings, the shared orig array will conflict. It turns out that this is actually a very nasty but very interesting design problem - perhaps the topic of another article.
To summarize, string combinations are subsets of a set of strings where order doesn't matter. String combinations have a wide range of use in many areas of the software development process. The code presented in this article lets you programmatically create and manipulate string combinations and determine the total number of combination elements for a given set size n and subset size k.
References
You can find out more about
combinations from many online and printed resources. An article that
describes the use of mathematical combinations in software testing and
gives C# source code is at http://msdn.microsoft.com/msdnmag/issues/04/07/TestRun/.
An article that describes the very tricky algorithm of how to generate a particular combination element without having to iterate from the first element is at http://msdn.microsoft.com/library/default.asp?url=/ library/en-us/dv_vstechart/html/mth_lexicograp.asp.
An article that describes mathematical permutations, a close cousin to combinations, is at http://msdn.microsoft.com/library/default.asp?url=/ library/en-us/dnnetsec/html/permutations.asp.
And an extensive discussion of both combinations and permutations is presented in Chapter 10 of my book .NET Test Automation Recipes: A Problem-Solution Approach, Apress, 2006: www.apress.com/book/bookDisplay.html?bID=10119.
Published June 21, 2006 Reads 19,406
Copyright © 2006 SYS-CON Media, Inc. — All Rights Reserved.
Syndicated stories and blog feeds, all rights reserved by the author.
More Stories By James McCaffrey
Dr. James McCaffrey works for Volt Information Sciences, Inc., where he manages technical training for software engineers working at Microsoft's Redmond, WA campus. He has worked on several Microsoft products, including Internet Explorer and MSN Search. James can be reached at jmccaffrey@volt.com or v-jammc@microsoft.com.
![]() |
SYS-CON Brazil News Desk 06/21/06 02:22:36 PM EDT | |||
Sooner or later you'll probably find it useful to be able to create and manipulate combinations programmatically. By far the most useful kinds of combinations are string combinations. A string combination of order (n, k) is a subset of k strings chosen from a set of n strings, where order doesn't matter. |
||||
- Kindle 2 vs Nook
- Confessions of a Ulitzer Addict
- IBM Hardware Chief, Intel VC Exec Arrested in Insider Trading Scam
- Tactical Cloud Computing Panel at 1st Annual GovIT Expo
- Ulitzer.com Named Exclusive "New Media" Sponsor of Cloud Computing Conference & Expo
- Infrastructure-as-a-Service Will Mature in 2010: Microsoft's David Chou
- Windows 7 – Microsoft’s First Step to the Cloud
- Cloud Expo and the End of Tech Recession
- Jill Tummler Singer, Deputy CIO of CIA, Keynotes at GovIT Expo
- Reality Check at the Cloud Computing Expo
- Visual Studio 2010 Is Cloud Friendly
- Fired SCO CEO Fires Back
- Kindle 2 vs Nook
- The Difference Between Web Hosting and Cloud Computing
- Ajax in RichFaces 3.3, JSF 2 and RichFaces 4
- Confessions of a Ulitzer Addict
- Wave on Ulitzer: Confessions of a Google Wave Fanboy
- IBM Hardware Chief, Intel VC Exec Arrested in Insider Trading Scam
- Cloud Computing Best Practices
- Tactical Cloud Computing Panel at 1st Annual GovIT Expo
- Ulitzer.com Named Exclusive "New Media" Sponsor of Cloud Computing Conference & Expo
- Infrastructure-as-a-Service Will Mature in 2010: Microsoft's David Chou
- Eval JavaScript in a Global Context
- Windows 7 – Microsoft’s First Step to the Cloud
- Google Maps and ASP.NET
- Crystal Reports XI & How It Has Changed
- Converting VB6 to VB.NET, Part I
- Creating Controls for.NET Compact Framework in Visual Studio 2005
- Where Are RIA Technologies Headed in 2008?
- How to Write High-Performance C# Code
- AJAX World RIA Conference & Expo Kicks Off in New York City
- Implementing Tab Navigation with ASP.NET 2.0
- i-Technology Photo Exclusive: Bill Gates & Steve Jobs In "Nerds"
- .NET Archives: Getting Reacquainted with the Father of C#
- i-Technology Viewpoint: "SOA Sucks"
- Programmatically Posting Data to ASP .NET Web Applications





























