Reputation: 59
I am trying to create a function that will create all permutations of a string in an incremental fashion. I would like to start at:
AAAAA
...
AAAAB
...
ACCCC
...
...
ZZZZZ
I have looked around, and can't seem to find anything of that sort. I tried to create it, but it wasn't incrementally.
Any suggestions?
Upvotes: 2
Views: 2332
Reputation: 659956
The "permutation" you are describing is better known as the Cartesian product. If you have an arbitrary number of sequences that you need to form the Cartesian product of, see my answer to this question on the subject:
Generating all Possible Combinations
Upvotes: 4
Reputation: 89499
Here is the LINQPad friendly code and it uses lambda expression.
void Main()
{
var chars = Enumerable.Range(65, 26);
var strings = chars.SelectMany (a =>
{
return chars.SelectMany (b => chars.SelectMany (c =>
{
return chars.SelectMany (d =>
{
return chars.Select (e => {return new string(new char[] {(char)a, (char)b, (char)c, (char)d, (char)e});});
});
}));
});
strings.Dump();
}
Upvotes: 0
Reputation: 5808
A different variant where I had the idea of using modulo arithmetic. Note that I lowered the character to {A,B,C} to test it, since going up to Z for 5 letters is a lot of strings.
public IEnumerable<char[]> AlphaCombinations(int length = 5, char startChar = 'A', char endChar = 'C')
{
int numChars = endChar - startChar + 1;
var s = new String(startChar, length).ToCharArray();
for (int it = 1; it <= Math.Pow(numChars, length); ++it)
{
yield return s;
for (int ix = 0; ix < s.Length; ++ix)
if (ix == 0 || it % Math.Pow(numChars, ix) == 0)
s[s.Length - 1 - ix] = (char)(startChar + (s[s.Length - 1 - ix] - startChar + 1) % numChars);
}
}
...
foreach (var s in AlphaCombinations(5))
{
Console.WriteLine(s);
}
Upvotes: 1
Reputation: 22433
Normally I wouldn't help these brute force type results... but seeing how many useless result you will get out of the set I figured I'd just toss this in.
var query = from c0 in Enumerable.Range(0, 26)
from c1 in Enumerable.Range(0, 26)
from c2 in Enumerable.Range(0, 26)
from c3 in Enumerable.Range(0, 26)
from c4 in Enumerable.Range(0, 26)
select new string(
new [] {
(char)('A' + c0),
(char)('A' + c1),
(char)('A' + c2),
(char)('A' + c3),
(char)('A' + c4),
}
);
BTW... if you just want the next value you can do something like this...
public static string Increment(string input)
{
var array = input.ToCharArray();
if (array.Any(c => c < 'A' || c > 'Z'))
throw new InvalidOperationException();
for (var i = array.Length-1; i >= 0; i--)
{
array[i] = (char)(array[i] + 1);
if (array[i] > 'Z')
{
array[i] = 'A';
if (i == 0)
return 'A' + new string(array);
}
else
break;
}
return new string(array);
}
Upvotes: 2
Reputation: 34408
Bashed out quickly - I expect this could be done better:
public static IEnumerable<string> GenerateStrings(int length = 5)
{
var buffer = new char[length];
for (int i = 0; i < length; ++i)
{
buffer[i] = 'A';
}
for(;;)
{
yield return new string(buffer);
int cursor = length;
for(;;)
{
--cursor;
if (cursor < 0)
{
yield break;
}
char c = buffer[cursor];
++c;
if (c <= 'Z')
{
buffer[cursor] = c;
break;
}
else
{
buffer[cursor] = 'A';
}
}
}
}
Upvotes: 0