Hi there, I've been trying to solve an issue at work or a project.
How do I create multiple unique combinations of a single string? It's supposed to be for a string of 4 digits. e.g. 1234.
Okay, I have managed to solve the part of generating combinations for 4 different digits and 3 same digits (e.g. 1234, 1112).
The problem I have right now is, when I key in 1122 into the textbox and click generate, I will end up getting combinations that are wrong (1112, 2221, 1111, 2222).
The whole idea is to generate combinations that will still retain the same digits from the input.
Can anyone help me with this problem? I've copied my codes below.
private char [ ] chDigits = new char [ 4 ];
private string [ ] permutated4DNumbers;
// Split the 4D number into an array of characters.
chDigits = bet4D.ToCharArray ( 0, bet4D.Length );
permutated4DNumbers = new string [ 24 ];
Random rand = new Random ( );
// A simple variable used for calculating the total number of possible combinations.
int j = 1;
// An index variable for looping through the permutated4DNumbers [] array.
int i = 0;
// This loop will be used to determine the total number of permutations possible.
while (i < 24)
{
// Generate the possible combinations using a random index for each character of the 4D number.
string str4DCombination = chDigits [ rand.Next ( 0, 4 ) ].ToString ( ) + chDigits [ rand.Next ( 0, 4 ) ].ToString ( ) + chDigits [ rand.Next ( 0, 4 ) ].ToString ( ) + chDigits [ rand.Next ( 0, 4 ) ].ToString ( );
bool isInArray = false;
if ( permutated4DNumbers.Length > 0 )
{
foreach ( string betnumber in permutated4DNumbers )
{
// Check if this combination, str4DCombination, generated a few lines above, is already in the array.
if ( betnumber == str4DCombination )
{
isInArray = true;
break;
}
}
}
if ( !isInArray )
{
// if str4DCombination is not in the array and it contains all the numbers from the original 4D number, then add it into the array.
if ( str4DCombination.Contains ( chDigits [ 0 ].ToString ( ) ) && str4DCombination.Contains ( chDigits [ 1 ].ToString ( ) ) && str4DCombination.Contains ( chDigits [ 2 ].ToString ( ) ) && str4DCombination.Contains ( chDigits [ 3 ].ToString ( ) ) )
{
permutated4DNumbers [ i ] = str4DCombination;
j++;
}
}
i++;
}
Loading
AlanPosted Mar 14, 2008, 6:10 AM
We'll need to add a bit more code to deal with that. Here's the full program for convenience:
using System;
using System.Collections.Generic;
class Program perms = new List();
{
static void Main()
{
Console.Clear();
string input;
do
{
Console.Write("Please enter a 4 character string : ");
input = Console.ReadLine();
}
while (input.Length != 4);
List
char[] ca = new char[4];
// generate all 24 permutations
for (int i = 0; i < 4; i++)
{
ca[0] = input[i];
for (int j = 0 ; j < 4; j++)
{
if (j == i) continue;
ca[1] = input[j];
for (int k = 0; k < 4; k++)
{
if (k == i || k == j) continue;
ca[2] = input[k];
for (int l = 0; l < 4; l++)
{
if (l == i || l == j || l == k) continue;
ca[3] = input[l];
perms.Add(new string(ca));
}
}
}
}
// sort them so that duplicates are adjacent to each other
perms.Sort();
// remove duplicates
string current = perms[perms.Count -1];
for (int i = perms.Count - 2; i >= 0; i--)
{
if (perms[i] == current)
{
perms.RemoveAt(i);
}
else
{
current = perms[i];
}
}
// print out unique permutations
Console.WriteLine("\nThe {0} unique permutation(s) is/are :\n", perms.Count);
foreach (string perm in perms)
{
Console.WriteLine(perm);
}
// count how many characters there are of each type
List
List
int index;
chars.Add(input[0]);
totals.Add(1);
for (int i = 1; i < 4; i++)
{
index = chars.IndexOf(input[i]);
if (index == -1)
{
chars.Add(input[i]);
totals.Add(1);
}
else
{
totals[index]++;
}
}
// work out prize winning category
string[] prizeCats = {"4 Different","2 Same", "2 Pairs", "3 Same", "4 Same"};
int prizeCatId = 0; // 4 different
switch(totals.Count)
{
case 3: // 2 same
prizeCatId = 1;
break;
case 2: // 2 pairs or 3 same
prizeCatId = (totals[0] == 2) ? 2 : 3;
break;
case 1: // 4 same
prizeCatId = 4;
break;
}
// print out analysis
Console.WriteLine("\nThe character analysis is :\n");
for(int i = 0; i < chars.Count ; i++)
{
Console.WriteLine("{0} occurs {1} time(s)", chars[i], totals[i]);
}
Console.WriteLine("\nThe prize category is '{0}'", prizeCats[prizeCatId]);
Console.ReadKey(); // pause to view console before exit
}
}
Phillip TanPosted Mar 13, 2008, 11:08 PM
Another problem I encountered while working on my program is that I have trouble identifying between each combinations, identifying whether they fall into either of this categories:
Four Different Digits - 1234
2 Same Digits - 1123 or 1231
2 Pairs - 1212, or 1122
3 Same Digits - 1112, or 1211
I have a database in the backend that has a table called tblPrizeCategory:
tblPrizeCategory
PrizeCategoryID (int)
PrizeCategoryDesc (varchar)
All the different combinations of numbers will be stored in another table called, tblMemberBet:
tblMemberBet
bet4D (varchar[4]) - This is where the combinations are stored.
PrizeCategoryID - This is the field that categorizes the combinations.
This table has many other fields, but I'm leaving them out because they have no concern with the present issue.
How can I determine the PrizeCategory Type just before I make the insert into the database? I need this to work in other to calculate the bet winning & losing prize amount.
AlanPosted Mar 13, 2008, 7:41 AM
Sure I can.
What we're doing there is generating all possible combinations of the four characters in the string (input) ignoring for the moment that some of them might be the same.
So, we define a character array (ca) to hold each permutation which can then be converted to a string and added to the 'perms' list.
The first element in the array can be any one of the four characters.
The second element can be any one of the three remaining characters.
The third element can be any one of the two remaining characters.
The fourth (and final) element must then be the remaining character, making 4 x 3 x 2 x 1 = 24 permutations in all.
So we define 4 nested for loops each of which range over all 4 characters in the string but, if we've already used a character in a previous loop, we pass on to the next character in the loop (using the 'continue' keyword).
The characters in the string can, of course, be obtained using the indexer i.e. input[0] is the first character and so on.
Incidentally, looking at the code again we could in fact eliminate the step where we mark the duplicates for deletion and just delete them immediately provided we look backwards through the permutations. We can't do this going forwards because when we delete an element, the indices of the following elements all move down one which upsets the logic:
using System;
using System.Collections.Generic;
class Program perms = new List();
{
static void Main()
{
Console.Clear();
string input;
do
{
Console.Write("Please enter a 4 character string : ");
input = Console.ReadLine();
}
while (input.Length != 4);
List
char[] ca = new char[4];
// generate all 24 permutations
for (int i = 0; i < 4; i++)
{
ca[0] = input[i];
for (int j = 0 ; j < 4; j++)
{
if (j == i) continue;
ca[1] = input[j];
for (int k = 0; k < 4; k++)
{
if (k == i || k == j) continue;
ca[2] = input[k];
for (int l = 0; l < 4; l++)
{
if (l == i || l == j || l == k) continue;
ca[3] = input[l];
perms.Add(new string(ca));
}
}
}
}
// sort them so that duplicates are adjacent to each other
perms.Sort();
// remove duplicates
string current = perms[perms.Count -1];
for (int i = perms.Count - 2; i >= 0; i--)
{
if (perms[i] == current)
{
perms.RemoveAt(i);
}
else
{
current = perms[i];
}
}
// print out unique permutations
Console.WriteLine("\nThe {0} unique permutation(s) is/are :\n",
perms.Count);
foreach (string perm in perms)
{
Console.WriteLine(perm);
}
}
}
There are more sophisticated ways of generating combinations and permutations of a given number of characters using recursion. However, when you only have a small number of characters, the above approach is easier to understand and reasonably efficient.
Phillip TanPosted Mar 13, 2008, 2:10 AM
Thank you so much, this solution works! Thumbs Up!
Do you mind explaining what this set of code does:
for
( int i = 0; i < 4; i++ ){
ca [ 0 ] = input [ i ];
for ( int j = 0; j < 4; j++ )
{
if ( j == i )
continue;
ca [ 1 ] = input [ j ];
for ( int k = 0; k < 4; k++ )
{
if ( k == i || k == j )
continue;
ca [ 2 ] = input [ k ];
for ( int l = 0; l < 4; l++ )
{
if ( l == i || l == j || l == k )
continue;
ca [ 3 ] = input [ l ];
perms.Add ( new string ( ca ) );
}
}
}
}
AlanPosted Mar 12, 2008, 4:50 PM
Try this:
using System;
using System.Collections.Generic;
class Program perms = new List();
{
static void Main()
{
Console.Clear();
string input;
do
{
Console.Write("Please enter a 4 character string : ");
input = Console.ReadLine();
}
while (input.Length != 4);
List
char[] ca = new char[4];
// generate all 24 permuations
for (int i = 0; i < 4; i++)
{
ca[0] = input[i];
for (int j = 0 ; j < 4; j++)
{
if (j == i) continue;
ca[1] = input[j];
for (int k = 0; k < 4; k++)
{
if (k == i || k == j) continue;
ca[2] = input[k];
for (int l = 0; l < 4; l++)
{
if (l == i || l == j || l == k) continue;
ca[3] = input[l];
perms.Add(new string(ca));
}
}
}
}
// sort them so that duplicates are adjacent to each other
perms.Sort();
// mark duplicates as null
string current = perms[0];
for (int i = 1; i < perms.Count; i++)
{
if (perms[i] == current)
{
perms[i] = null;
}
else
{
current = perms[i];
}
}
// remove duplicates
for (int i = perms.Count - 1; i >= 0; i--)
{
if (perms[i] == null) perms.RemoveAt(i);
}
// print out unique permutations
Console.WriteLine("\nThe {0} unique permutation(s) is/are :\n", perms.Count);
foreach (string perm in perms)
{
Console.WriteLine(perm);
}
}
}