Calculating all possible combinations of a string, with a twist - c#

I'm trying to allow a user to enter text in a textbox, and have the program generate all possible combinations of it, except with a minimum of 3 characters and maximum of 6. I don't need useless words like 'as', 'a', 'i', 'to', etc cluttering up my array. I'll also be checking each combination against a dictionary to make sure it's a real word.
I have the dictionary complete (painstakingly generated, here's a link to it in return (WARNING: gigantic load time (for me)!)
Anyways, if the user enters 'ABCDEF' (in no particular order), how could I generate, for example:
'ABC'
'BAC'
'CAB'
...
'ABD'
'ABE'
'ABF'
etc... EVERY possible combination, no matter what order? I understand that there are a ridiculous amount of these combinations, but it only needs to be calculated once, so I'm not too worried about that.
I've found code samples to recursively find combinations (not permutations, I don't need those) of just the fixed-width string (ABCDEF, ABCDFE ... ACDBFE, etc). They don't do what I need, and I haven't the slightest clue about where to even start with this project.
This isn't homework, it started out as a personal project of mine that's grown to take over my life over such a simple problem... I can't believe I can't figure this out!

It sounds to me like you're describing the Power Set
Here's an implementation I had lying around my personal library:
// Helper method to count set bits in an integer
public static int CountBits(int n)
{
int count = 0;
while (n != 0)
{
count++;
n &= (n - 1);
}
return count;
}
public static IEnumerable<IEnumerable<T>> PowerSet<T>(
IEnumerable<T> src,
int minSetSize = 0,
int maxSetSize = int.MaxValue)
{
// we want fast random access to the source, so we'll
// need to ToArray() it
var cached = src.ToArray();
var setSize = Math.Pow(2, cached.Length);
for(int i=0; i < setSize; i++)
{
var subSetSize = CountBits(i);
if(subSetSize < minSetSize ||
subSetSize > maxSetSize)
{
continue;
}
T[] set = new T[subSetSize];
var temp = i;
var srcIdx = 0;
var dstIdx = 0;
while(temp > 0)
{
if((temp & 0x01) == 1)
{
set[dstIdx++] = cached[srcIdx];
}
temp >>= 1;
srcIdx++;
}
yield return set;
}
yield break;
}
And a quick test rig:
void Main()
{
var src = "ABCDEF";
var combos = PowerSet(src, 3, 6);
// hairy joins for great prettiness
Console.WriteLine(
string.Join(" , ",
combos.Select(subset =>
string.Concat("[",
string.Join(",", subset) , "]")))
);
}
Output:
[A,B,C] , [A,B,D] , [A,C,D] , [B,C,D] , [A,B,C,D] , [A,B,E] , [A,C,E] , [B,C,E] , [A,B,C,E] ,
[A,D,E] , [B,D,E] , [A,B,D,E] , [C,D,E] , [A,C,D,E] , [B,C,D,E] , [A,B,C,D,E] , [A,B,F] ,
[A,C,F] , [B,C,F] , [A,B,C,F] , [A,D,F] , [B,D,F] , [A,B,D,F] , [C,D,F] , [A,C,D,F] ,
[B,C,D,F] , [A,B,C,D,F] , [A,E,F] , [B,E,F] , [A,B,E,F] , [C,E,F] , [A,C,E,F] , [B,C,E,F] ,
[A,B,C,E,F] , [D,E,F] , [A,D,E,F] , [B,D,E,F] , [A,B,D,E,F] , [C,D,E,F] , [A,C,D,E,F] ,
[B,C,D,E,F] , [A,B,C,D,E,F]

The best way to do this is to use a for loop and convert each character from an int to a char and concatenate them together in a string.
For example:
for(int i = 0; i < 26; i++)
{
Console.WriteLine((char)i + 'A');
}

Supposed, you also want stuff like "AAB" the "cross product" of your set of letters should be it.
Generation can be as simple as a LINQ:
string myset = "ABCDE";
var All = (from char l1 in myset
from char l2 in myset
from char l3 in myset
select new string(new char[] { l1, l2, l3})).ToList();
Note: construction many strings and char Arrays is not fast. You may want to replace the new string and new char[] with a custom class like so:
select new MyCustomClass(l1, l2, l3).ToList();
If you don't want things like "AAB" (or "EEL") then I'd point you to wikipedia for "combinations".
To get from fixed-length to "any length from 3 to 6" join multiple sets, if the limits are dynamic then use a loop.

Related

How to get values from user using comma in c#?

using System;
namespace reverse
{
class Program
{
static void Main(string[] args)
{
int[] a = new int [10];
for (int i= 0; i<a.Length; i++)
{
a[i] = int.Parse(Console.ReadLine());
}
}
}
}
here I can get values from a user by pressing enter key after each time i give the value but I want to give value as a whole with comma. Thanks!
I would suggest to gradually step towards functional programming.
Why?
Weel, with words from Eric Lippert from "Functional programming for beginners"
I will talk about the “why” a little bit, but basically it boils down to
a great many bugs are caused by bad mutations.
By taking a page
from functional style and designing programs so that variables and
data structures change as little as possible, we can eliminate a
large source of bugs.
Structuring programs into small functions
whose outputs each depend solely on inputs
makes for programs that
are easy to unit test.
the ability to pass functions as data
allows us to create new and interesting control flows and patterns,
like LINQ.
Rewriting your code
Use Linq in a single and simple line:
int [] res =
Console.ReadLine () // read the input
.Split (',') // transform it into an array
.Take (10) // consider only the first 10 strings
.Select (int.Parse) // transform them into int
.ToArray (); // and finally get an array
You can add a check after the Split and before Take:
.Where (d => {int t; return int.TryParse (d, out t);}).Take
Try this one and read comments to get more info :
static void Main()
{
string input = Console.ReadLine(); // grab user input in one whole line
string[] splitted = input.Split(','); // split user input by comma sign ( , )
int[] a = new int[splitted.Length]; // create a new array that matches user input values length
for(int i = 0; i < splitted.Length; i++) // iterate through all user input values
{
int temp = -1; // create temporary field to hold result
int.TryParse(splitted[i], out temp); // check if user inpu value can be parsed into int
a[i] = temp; // assign parsed int value
}
}
This method will ensure that program will execute even if user wont input numerics. For example if user input will be :
1 , 2,3,45,8,9898
The output will be :
{ 1, 2, 3, 45, 8, 9898 }
But if the input will be :
1,adsadsa,13,4,6,dsd
The output will be :
{ 1, 0, 13, 4, 6, 0 }

Calculate variations on a string

I have a series of incorrectly encoded base36 values - these were encoded from integers using a string of letters, missing the "i" and "o". They now need to be converted back to integers using C#.
There are multiple permutations because of the rollover effect.
"0" can either equal 0 or 34;
"1" can either equal 1 or 35.
So, for instance, if I have a string "a110", it has six possible values.
I'm having a hard time trying to figure how to code for this.
All the examples I've looked at compute variations for a set of elements, for example
char[] = { a, b, c }
int[] = { 1, 2, 3 }
However, in my case, there are conditionals involved too, and it's making my head hurt. Can anyone help?
You can compute the list of all possible input strings. First, read the input into a list of ints. Now, you know that each of those (if it's a sufficiently low value) could be one of two things. So then you can create an enumerator that returns all of the possible inputs, via a recursive descent.
I managed to do it with the following code. It was actually a little simpler than I expected, since I only had two conditions, and two options. It uses recursion and steps through each character in the string. If that character is a 0 or 1, it then diverges, and continues building the string.
It actually generates a few duplicates, so I had to add a condition to only add it to the string list if it doesn't already exist. If someone else can point me to slightly better logic I'd appreciate it
public string st = "101"; // hardcoded for now
public char[] cs;
public List<string> variations;
static void Main()
{
cs = st.ToCharArray();
variations = new List<string>();
vary("",0);
}
static void vary(string m, int n)
{
for (int i = n; i < cs.Count(); i++)
{
if (cs[i] == '0' || cs[i] == '1')
{
// recurse
combo(m + (cs[i] == '0' ? "0" : "1"), i + 1);
combo(m + (cs[i] == '0' ? "Y" : "Z"), i + 1);
}
m += cs[i];
}
if(!variations.Contains(m))
variations.Add(m);
}
for the string "101" I get the following combinations
101
10Z
1Y1
1YZ
Z01
Z0Z
ZY1
ZYZ

How to display the items from a dictionary in a random order but no two adjacent items being the same

First of all, there is actually more restrictions than stated in the title. Plz readon.
say, i have a dictionary<char,int> where key acts as the item, and value means the number of occurrence in the output. (somewhat like weighting but without replacement)
e.g. ('a',2) ('b',3) ('c',1)
a possible output would be 'babcab'
I am thinking of the following way to implement it.
build a new list containing (accumulated weightings,char) as its entry.
randomly select an item from the list,
recalculate the accumulated weightings, also set the recent drawn item weighing as 0.
repeat.
to some extent there might be a situation like such: 'bacab' is generated, but can do no further (as only 'b' left, but the weighting is set to 0 as no immediate repetition allowed). in this case i discard all the results and start over from the very beginning.
Is there any other good approach?
Also, what if i skip the "set the corresponding weighting to 0" process, instead I reject any infeasible solution. e.g. already i got 'bab'. In the next rng selection i get 'b', then i redo the draw process, until i get something that is not 'b', and then continue. Does this perform better?
How about this recursive algorithm.
Create a list of all characters (candidate list), repeating them according to their weight.
Create an empty list of characters (your solution list)
Pick a random entry from the candidate list
If the selected item (character) is the same as the last in solution list then start scanning for another character in the candidate list (wrapping around if needed).
If no such character in step 4 can be found and candidate list is not empty then backtrack
Append the selected character to the solution list.
If the candidate list is empty print out the solution and 'backtrack', else go to step 3.
I'm not quite sure about the 'backtrack' step yet, but you should get the general idea.
Try this out, it should generate a (pseudo) random ordering of the elements in your enumerable. I'd recommend flattening from your dictionary to a list:
AKA Dictionary of
{b, 2}, {a, 3} becomes {b} {b} {a} {a} {a}
public static IEnumerable<T> RandomPermutation<T>(this IEnumerable<T> enumerable)
{
if (enumerable.Count() < 1)
throw new InvalidOperationException("Must have some elements yo");
Random random = new Random(DateTime.Now.Millisecond);
while (enumerable.Any())
{
int currentCount = enumerable.Count();
int randomIndex = random.Next(0, currentCount);
yield return enumerable.ElementAt(randomIndex);
if (randomIndex == 0)
enumerable = enumerable.Skip(1);
else if (randomIndex + 1 == currentCount)
enumerable = enumerable.Take(currentCount - 1);
else
{
T removeditem = enumerable.ElementAt(randomIndex);
enumerable = enumerable.Where(item => !item.Equals(removeditem));
}
}
}
If you need additional permutations, simply call it again for another random ordering. While this wont get you every permutation, you should find something useful. You can also use this as a base line to get a solution going.
This should be split into some seperate methods and could use some refactoring but the idea is to implement it in such a way that it does not depend on randomly moving things around till you get a valid result. That way you can't predict how long it would take
Concatenate all chars to a string and randomize that string
Loop through the randomized string and find any char that violates the rule
Remove that char from the string
Pick a random number. Use this number as "put the removed char at the nth valid position")
Loop around the remaining string to find the Nth valid postion to put the char back.
If there is no valid position left drop the char
Repeat from step 2 until no more violations are found
using System;
using System.Collections.Generic;
namespace RandomString
{
class Program
{
static void Main(string[] args)
{
Random rnd = new Random(DateTime.Now.Millisecond);
Dictionary<char, int> chars = new Dictionary<char, int> { { 'a', 2 }, { 'b', 3 }, { 'c', 1 } };
// Convert to a string with all chars
string basestring = "";
foreach (var pair in chars)
{
basestring += new String(pair.Key, pair.Value);
}
// Randomize the string
string randomstring = "";
while (basestring.Length > 0)
{
int randomIndex = rnd.Next(basestring.Length);
randomstring += basestring.Substring(randomIndex, 1);
basestring = basestring.Remove(randomIndex, 1);
}
// Now fix 'violations of the rule
// this can be optimized by not starting over each time but this is easier to read
bool done;
do
{
Console.WriteLine("Current string: " + randomstring);
done = true;
char lastchar = randomstring[0];
for (int i = 1; i < randomstring.Length; i++)
{
if (randomstring[i] == lastchar)
{
// uhoh violation of the rule. We pick a random position to move it to
// this means it gets placed at the nth location where it doesn't violate the rule
Console.WriteLine("Violation at position {0} ({1})", i, randomstring[i]);
done = false;
char tomove = randomstring[i];
randomstring = randomstring.Remove(i, 1);
int putinposition = rnd.Next(randomstring.Length);
Console.WriteLine("Moving to {0}th valid position", putinposition);
bool anyplacefound;
do
{
anyplacefound = false;
for (int replace = 0; replace < randomstring.Length; replace++)
{
if (replace == 0 || randomstring[replace - 1] != tomove)
{
// then no problem on the left side
if (randomstring[replace] != tomove)
{
// no problem right either. We can put it here
anyplacefound = true;
if (putinposition == 0)
{
randomstring = randomstring.Insert(replace, tomove.ToString());
break;
}
putinposition--;
}
}
}
} while (putinposition > 0 && anyplacefound);
break;
}
lastchar = randomstring[i];
}
} while (!done);
Console.WriteLine("Final string: " + randomstring);
Console.ReadKey();
}
}
}

Calculating Nth permutation step?

I have a char[26] of the letters a-z and via nested for statements I'm producing a list of sequences like:
aaa, aaz... aba, abb, abz, ... zzy, zzz.
Currently, the software is written to generate the list of all possible values from aaa-zzz and then maintains an index, and goes through each of them performing an operation on them.
The list is obviously large, it's not ridiculously large, but it's gotten to the point where the memory footprint is too large (there are also other areas being looked at, but this is one that I've got).
I'm trying to produce a formula where I can keep the index, but do away with the list of sequences and calculate the current sequence based on the current index (as the time between operations between sequences is long).
Eg:
char[] characters = {a, b, c... z};
int currentIndex = 29; // abd
public string CurrentSequence(int currentIndex)
{
int ndx1 = getIndex1(currentIndex); // = 0
int ndx2 = getIndex2(currentIndex); // = 1
int ndx3 = getIndex3(currentIndex); // = 3
return string.Format(
"{0}{1}{2}",
characters[ndx1],
characters[ndx2],
characters[ndx3]); // abd
}
I've tried working out a small example using a subset (abc) and trying to index into that using modulo division, but I'm having trouble thinking today and I'm stumped.
I'm not asking for an answer, just any kind of help. Maybe a kick in the right direction?
Hint: Think of how you would print a number in base 26 instead of base 10, and with letters instead of digits. What's the general algorithm for displaying a number in an arbitrary base?
Spoiler: (scroll right to view)
int ndx1 = currentIndex / 26 / 26 % 26;
int ndx2 = currentIndex / 26 % 26;
int ndx3 = currentIndex % 26;
Something like this ought to work, assuming 26 characters:
public string CurrentSequence(int currentIndex) {
return characters[currentIndex / (26 * 26)]
+ characters[(currentIndex / 26) % 26]
+ characters[currentIndex % 26];
}
Wow, two questions in one day that can be solved via Cartesian products. Amazing.
You can use Eric Lippert's LINQ snippet to generate all combinations of the index values. This approach results in a streaming set of values, so they don't require storage in memory. This approach nicely separates the logic of generating the codes from maintaining state or performing computation with the code.
Eric's code for all combinations:
static IEnumerable<IEnumerable<T>> CartesianProduct<T>(this IEnumerable<IEnumerable<T>> sequences)
{
IEnumerable<IEnumerable<T>> emptyProduct = new[] { Enumerable.Empty<T>() };
return sequences.Aggregate(
emptyProduct,
(accumulator, sequence) =>
from accseq in accumulator
from item in sequence
select accseq.Concat(new[] {item}));
}
You can now write:
public static IEnumerable<string> AllCodes()
{
char[] characters = {a, b, c... z};
IEnumerable<char[]> codeSets = new[] { characters, characters, characters };
foreach( var codeValues in codeSets.CartesianProduct() )
{
yield return
string.Format( "{0}{1}{2}", codeValues[0], codeValues[1], codeValues[2]);
}
}
The code above generates a streaming sequence of all code strings from aaa to zzz. You can now use this elsewhere where you perform your processing:
foreach( var code in AllCodes() )
{
// use the code value somehow...
}
There are multiple ways to solve your problem, but an option is to generate the sequence on the fly instead of storing it in a list:
IEnumerable<String> Sequence() {
for (var c1 = 'a'; c1 <= 'z'; ++c1)
for (var c2 = 'a'; c2 <= 'z'; ++c2)
for (var c3 = 'a'; c3 <= 'z'; ++c3)
yield return String.Format("{0}{1}{2}", c1, c2, c3);
}
You can then enumerate all the strings:
foreach (var s in Sequence())
Console.WriteLine(s);
This code doesn't use indices at all but it allows you to create a loop around the sequence of strings using simple code and without storing the strings.

Algorithm for dynamic combinations

My code has a list called INPUTS, that contains a dynamic number of lists, let's call them A, B, C, .. N. These lists contain a dynamic number of Events
I would like to call a function with each combination of Events. To illustrate with an example:
INPUTS: A(0,1,2), B(0,1), C(0,1,2,3)
I need to call my function this many times for each combination (the input count is dynamic, in this example it is three parameter, but it can be more or less)
function(A[0],B[0],C[0])
function(A[0],B[1],C[0])
function(A[0],B[0],C[1])
function(A[0],B[1],C[1])
function(A[0],B[0],C[2])
function(A[0],B[1],C[2])
function(A[0],B[0],C[3])
function(A[0],B[1],C[3])
function(A[1],B[0],C[0])
function(A[1],B[1],C[0])
function(A[1],B[0],C[1])
function(A[1],B[1],C[1])
function(A[1],B[0],C[2])
function(A[1],B[1],C[2])
function(A[1],B[0],C[3])
function(A[1],B[1],C[3])
function(A[2],B[0],C[0])
function(A[2],B[1],C[0])
function(A[2],B[0],C[1])
function(A[2],B[1],C[1])
function(A[2],B[0],C[2])
function(A[2],B[1],C[2])
function(A[2],B[0],C[3])
function(A[2],B[1],C[3])
This is what I have thought of so far:
My approach so far is to build a list of combinations. The element combination is itself a list of "index" to the input arrays A, B and C. For our example:
my list iCOMBINATIONS contains the following iCOMBO lists
(0,0,0)
(0,1,0)
(0,0,1)
(0,1,1)
(0,0,2)
(0,1,2)
(0,0,3)
(0,1,3)
(1,0,0)
(1,1,0)
(1,0,1)
(1,1,1)
(1,0,2)
(1,1,2)
(1,0,3)
(1,1,3)
(2,0,0)
(2,1,0)
(2,0,1)
(2,1,1)
(2,0,2)
(2,1,2)
(2,0,3)
(2,1,3)
Then I would do this:
foreach( iCOMBO in iCOMBINATIONS)
{
foreach ( P in INPUTS )
{
COMBO.Clear()
foreach ( i in iCOMBO )
{
COMBO.Add( P[ iCOMBO[i] ] )
}
function( COMBO ) --- (instead of passing the events separately)
}
}
But I need to find a way to build the list iCOMBINATIONS for any given number of INPUTS and their events. Any ideas?
Is there actually a better algorithm than this?
any pseudo code to help me with will be great.
C# (or VB)
Thank You
You can use an array to hold the indexes for each list. Example:
List<List<int>> lists = new List<List<int>> {
new List<int> { 0,1,2 },
new List<int> { 0,1 },
new List<int> { 0,1,2,3 }
};
int[] cnt = new int[lists.Count];
int index;
do {
Console.WriteLine(String.Join(",", cnt.Select((c,i) => lists[i][c].ToString()).ToArray()));
index = cnt.Length - 1;
do {
cnt[index] = (cnt[index] + 1) % lists[index].Count;
} while(cnt[index--] == 0 && index != -1);
} while (index != -1 || cnt[0] != 0);
This is permutation problem. You may take a look at this:
http://www.interact-sw.co.uk/iangblog/2004/09/16/permuterate
I had similar problem some time ago (generating combinations), I've used code from: http://www.merriampark.com/comb.htm . It's java, but I hadn't any problems to translate it into C#.
Put A,B,C in matrix!
M=[A,B,C]
recursive_caller(d,params):
if d == len(M):
function(params)
return
for i in M[d]:
params[d]=i
recursive_caller(d+1,params)
It would seem that what you really want, is neither a permutation, nor a combination, per se. You want to look at the cartesian product (see here) of several sets, the iteration over which may involve iterating through combinations of individual sets.
However, this is unlike a combination problem, because you are looking for the ways to choose 1 element from each set. The number of ways to do this is the size of the set. Combinations problems usually involve choose k-many things from a set of n-many things, where k=1 or n is trivial.
Several methods of producing iterators in C# have been discussed here. (Including one by Jon Skeet).
If you are using .NET, you may also be interested in developed combinatorics modules, such as KwCombinatorics at CodePlex.
edit Now, with LINQ to the rescue:
private void cartesian1()
{
textAppend("Cartesian 1");
var setA = new[] { "whole wheat", "white", "rye" };
var setB = new[] { "cold cut", "veggie", "turkey", "roast beef" };
var setC = new[] { "everything", "just mayo" };
var query =
from bread in setA
from meat in setB
from toppings in setC
let sandwich = String.Format("{1} on {0} with {2}",
bread, meat, toppings)
select sandwich;
foreach( string sandwich in query )
{
textAppend(sandwich);
}
}
A modified version of #Guffa's answer. I am by no means a creator of this code.
List<int> lists = new List<int> { 3, 2, 4 };
int[] cnt = new int[lists.Count];
int index;
do
{
Console.WriteLine(String.Join(",", cnt));
index = cnt.Length - 1;
do
{
cnt[index] = (cnt[index] + 1) % lists[index];
} while (cnt[index--] == 0 && index != -1);
} while (index != -1 || cnt[0] != 0);
Instead of using List<List<int>> - with possible values - use List<int> describing the amount of elements in collection. The output is the same an in original answer. The performance is better.

Categories

Resources