This question already has answers here:
Best way to reverse a string
(51 answers)
Closed 9 years ago.
Below is the fastest code I could create for reversing a String
public static void ReverseFast(string x)
{
string text = x;
StringBuilder reverse = new StringBuilder();
for (int i = text.Length - 1; i >= 0; i--)
{
reverse.Append(text[i]);
}
Console.WriteLine(reverse);
}
I want to address every bottleneck in this equation to make it as fast as possible. The only one I can find so far is the Array Bounds check which I only partially understand. Is there anyway to disable this as I understand it if you use .Length the compiler decides not to check the bounds but if you are decrementing as I am in the for loop it still does the boundary check? Can someone convert this to use pointers for me which would avoid the boundary check, I would like to test the speed difference for strings in the range of 100k+ characters.
Based on the comments and posts below this is what I have come up with so far.
public static void ReverseFast(string x)
{
StringBuilder reverse = new StringBuilder(x.Length);
for (int i = x.Length - 1; i >= 0; i--)
{
reverse.Append(x[i]);
}
Console.WriteLine(reverse);
}
This above solution is way faster than the suggested duplicate question answer. This question is really addressing reversal in the range of 5000 * 26 characters +. I would still like to test this out using pointers to really see if there is no bottleneck especially with such large amount of characters.
var arr = x.ToCharArray();
Array.Reverse(arr);
return new string(arr);
Note, however, that this will reverse any unicode modifier characters (accents, etc).
Benchmark:
Array.Reverse: 179ms
StringBuilder: 475ms
With:
static void Main()
{
string text = new string('x', 100000);
GC.Collect();
GC.WaitForPendingFinalizers();
var watch = Stopwatch.StartNew();
const int LOOP = 1000;
for (int i = 0; i < LOOP; i++)
{
var arr = text.ToCharArray();
Array.Reverse(arr);
string y = new string(arr);
}
watch.Stop();
Console.WriteLine("Array.Reverse: {0}ms", watch.ElapsedMilliseconds);
GC.Collect();
GC.WaitForPendingFinalizers();
watch = Stopwatch.StartNew();
for (int i = 0; i < LOOP; i++)
{
var reverse = new StringBuilder(text.Length);
for (int j = text.Length - 1; j >= 0; j--)
{
reverse.Append(text[j]);
}
string y = reverse.ToString();
}
watch.Stop();
Console.WriteLine("StringBuilder: {0}ms", watch.ElapsedMilliseconds);
}
If we try a string of length 500 and loop 500000 times:
Array.Reverse: 480ms
StringBuilder: 1176ms
I also tried adding unsafe into that, i.e.
fixed (char* c = text)
{
for (int j = text.Length - 1; j >= 0; j--)
{
reverse.Append(c[j]);
}
}
this made no difference whatsoever.
And I added in JeffRSon's answer too; I get:
Array.Reverse: 459ms
StringBuilder: 1092ms
Pointer: 513ms
(for the 500 length x 5000 iterations test)
Here's a pointer based solution:
unsafe String Reverse(String s)
{
char[] sarr = new char[s.Length];
int idx = s.Length;
fixed (char* c = s)
{
char* c1 = c;
while (idx != 0)
{
sarr[--idx] = *c1++;
}
}
return new String(sarr);
}
Getting rid of the array index (sarr[--idx]) the following might be faster:
unsafe String Reverse(String s)
{
char[] sarr = new char[s.Length];
fixed (char* c = s)
fixed (char* d = sarr)
{
char* c1 = c;
char* d1 = d + s.Length;
while (d1 > d)
{
*--d1 = *c1++;
}
}
return new String(sarr);
}
Set the capacity when you create the StringBuilder, that way it doesn't have to grow during the loop and allocate more memory. Assigning the parameter to a local variable is an unnecessary step, as the parameter is already a local variable.
public static void ReverseFast(string text) {
StringBuilder reverse = new StringBuilder(text.Length);
for (int i = text.Length - 1; i >= 0; i--) {
reverse.Append(text[i]);
}
}
That is just the basic steps to remove any unneccesary work. If you really have a performance problem with the code, you would need to analyse what the generated code does, and possibly create different versions that do different things depending on the current framework and hardware.
Related
Question Background
I read this question that is about how to reverse a string as fast as possible. I found that one of the answers was comparing different methods. In one of them, they just run a loop swapping elements from position i with the one at position string.Length-1-i but they use the known tricky swap via XOR. I was wondering how faster is reversing the string using the swap via XOR in comparison with the same method using the classic swap via a temporal variable. Surprisingly I'm getting almost a 50% improvement over the XOR one.
The Question
Is the compiler doing something magic behind the scenes, why I'm I getting this result?
The modified code with the Benchmarks
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ContestLibrary
{
public class Problem
{
delegate string StringDelegate(string s);
static void Benchmark(string description, StringDelegate d, int times, string text)
{
Stopwatch sw = new Stopwatch();
sw.Start();
for (int j = 0; j < times; j++)
{
d(text);
}
sw.Stop();
Console.WriteLine("{0} Ticks {1} : called {2} times.", sw.ElapsedTicks, description, times);
}
public static string ReverseXor(string s)
{
char[] charArray = s.ToCharArray();
int len = s.Length - 1;
for (int i = 0; i < len; i++, len--)
{
charArray[i] ^= charArray[len];
charArray[len] ^= charArray[i];
charArray[i] ^= charArray[len];
}
return new string(charArray);
}
public static string ReverseClassic(string s)
{
char[] charArray = s.ToCharArray();
int len = s.Length-1;
for (int i = 0; i < len; i++, len--)
{
char temp = charArray[len];
charArray[len] = charArray[i];
charArray[i] = temp;
}
return new string(charArray);
}
public static string StringOfLength(int length)
{
Random random = new Random();
StringBuilder sb = new StringBuilder();
for (int i = 0; i < length; i++)
{
sb.Append(Convert.ToChar(Convert.ToInt32(Math.Floor(26 * random.NextDouble() + 65))));
}
return sb.ToString();
}
static void Main(string[] args)
{
int[] lengths = new int[] {1,10,100,1000, 10000, 100000};
foreach (int l in lengths)
{
int iterations = 10000;
string text = StringOfLength(l);
Benchmark(String.Format("Classic (Length: {0})", l), ReverseClassic, iterations, text);
Benchmark(String.Format("Xor (Length: {0})", l), ReverseXor, iterations, text);
Console.WriteLine();
}
Console.Read();
}
}
}
The reason is very simple, lets check how many operations in IL code each function has.
But first, lets see the real difference in time of both functions. You said that the XOR function is almost 50% slower than the other, when I run the code in Debug mode I have that results, but you must run the code in Release mode to fully allow the optimizer do its job :). In release mode the XOR functions is almost 3x slower.
The pictures have the IL code of the part inside the for loop, that is the only piece that changes.
The first picture is the function with the temp variable
The second picture is the function with the XOR
As you can see the difference in the number of instructions is huge, 14 against 34. The 3x difference in time come from some operations like conv.u2 that are a little expensive.
I agree with Harold. XOR swap is not faster than using a temporary variable.
I think that the myth of XOR swap dates back to the days where allocating memory for new variables was a time consuming job.
Initially I thought there is a chance that this might have something to do with the type, and maybe using XOR swap in int arrays would give a better results than on char arrays, so I've built upon your benchmark one for int arrays just to text - turns out the same results (more or less) for int XOR swap is just slower than using a temporary variable.
Update:
As Damien_The_Unbeliever wrote in his comment to your question, The answer given by R. Martinho Fernandes in the question you've linked to is actually the only answer in the first page that correctly reverse a string, even with languages other then English.
In fact, Based on that answer and one of it's comments I've written an extension method to correctly reverse a string.
In my native language (Hebrew) we have all kinds of dots and symbols to specify vowels, and the simple reverse of an array (or IEnumerable) is doing it wrong, just like in the French example.
It's significantly slower than the regular swap based implementation (And about 10 times slower than the XOR based swap), but I hardly think that's going to be an issue, since reversing a string is not something you do very often, and reversing many strings in a tight loop even less.
Tested based on your benchmark method, reversing 10,000 string of length 10,000 with this method took approximately 13.5 seconds.
If anyone would ever write a program that actually needs to do so many reverses for such long strings, I would be very surprised.
So here is my international safe string reverse implementation, I hope someone would benefit from it:
public static string Reverse(this string source)
{
if (string.IsNullOrEmpty(source))
{
return source;
}
var info = new StringInfo(source);
var sb = new StringBuilder();
for (int i = info.LengthInTextElements - 1; i > -1; i--)
{
sb.Append(info.SubstringByTextElements(i, 1));
}
return sb.ToString();
}
You can test below code with Array.Reverse, It will more efficient than other approaches which you are mentioned, Array.Reverse is coded natively and it is very simple to maintain and understand.
public static string ReverseArray(string text)
{
if (text == null) return null;
char[] array = text.ToCharArray();
Array.Reverse(array);
return new String(array);
}
Below is a complete code to demonstrate,
delegate string StringDelegate(string s);
static void Benchmark(string description, StringDelegate d, int times, string text)
{
Stopwatch sw = new Stopwatch();
sw.Start();
for (int j = 0; j < times; j++)
{
d(text);
}
sw.Stop();
Console.WriteLine("{0} Ticks {1} : called {2} times.", sw.ElapsedTicks, description, times);
}
public static string ReverseArray(string text)
{
if (text == null) return null;
// this was posted by petebob as well
char[] array = text.ToCharArray();
Array.Reverse(array);
return new String(array);
}
public static string ReverseXor(string s)
{
char[] charArray = s.ToCharArray();
int len = s.Length - 1;
for (int i = 0; i < len; i++, len--)
{
charArray[i] ^= charArray[len];
charArray[len] ^= charArray[i];
charArray[i] ^= charArray[len];
}
return new string(charArray);
}
public static string ReverseClassic(string s)
{
char[] charArray = s.ToCharArray();
int len = s.Length-1;
for (int i = 0; i < len; i++, len--)
{
char temp = charArray[len];
charArray[len] = charArray[i];
charArray[i] = temp;
}
return new string(charArray);
}
public static string StringOfLength(int length)
{
Random random = new Random();
StringBuilder sb = new StringBuilder();
for (int i = 0; i < length; i++)
{
sb.Append(Convert.ToChar(Convert.ToInt32(Math.Floor(26 * random.NextDouble() + 65))));
}
return sb.ToString();
}
static void Main(string[] args)
{
int[] lengths = new int[] { 1, 10, 100, 1000, 10000, 100000 };
foreach (int l in lengths)
{
int iterations = 10000;
string text = StringOfLength(l);
Benchmark(String.Format("Classic (Length: {0})", l), ReverseClassic, iterations, text);
Benchmark(String.Format("Array (Length: {0})", l), ReverseArray, iterations, text);
Benchmark(String.Format("Xor (Length: {0})", l), ReverseXor, iterations, text);
Console.WriteLine();
}
Console.Read();
}
Note: I have corrected your code for reversing the string, it was not correctly reverse the string as your post
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 6 years ago.
Improve this question
I have the following code:
static void Main(string[] args)
{
int[] array = FillArray(); //Imagine FillArray() Fills the array with numbers from 0 to 100
string numbers = "";
for(int i = 0;i<array.Count();i++)
{
numbers += i.ToString();
}
}
What Im trying to do is to make this code more performant, maybe instead of using a For use a built in C# Method, extension method that makes this without having to repeat this For 100 times.
Edit: It is a broad Question, Of course you will have your own answer in regards of your knowledge we could say that all the answers that beat the timer of this Algorithm is sufficient answer for the question in itself.
Imagine to iterate with this algorithm 1.000.000.000 times, then we can compare with concrete numbers about different solutions.
Use StringBuilder if you want to concatenate string many many times.
Also use array.Length instead.
static void Main(string[] args)
{
int[] array = FillArray(); //Imagine FillArray() Fills the array with numbers from 0 to 100
var sb = new StringBuilder();
var len = array.Length;
for(int i = 0; i < len; i++)
{
sb.Append(i.ToString());
}
var numbers = sb.ToString();
}
To become really fast you need to get rid of (nearly) all allocations. Most people are not aware that i.ToString() allocates a new string instance which is not needed anymore after it has been appended to the StringBuilder instance.
Your initial version did concat the "temp" string with every i.ToString() which results in a string which gradually becomes larger and larger and hence slower to allocate every time a new slightly larger string. That is not an issue for a few strings but if you concat this way thousands or millions of strings it looks like this method will never terminate.
A much better approach is to use StringBuilder which is basically a mutable string that can extend its existing buffer. That allows efficient appending of strings without creating new temporary strings because string instances are not mutable. Now you are already quite good you can do better by allocating a large enough char array for all expected integers. Then you do not i.ToString() but i.ToCharArray() into the final char buffer. That beats the StringBuilder approach by over a factor 2.
ArrayToStringSteakOverCooked 0.39s 0.40s 0.43s
ArrayToStringKeithNicolasAlternate2 0.43s 0.44s 0.46s
ArrayToStringAlois 0.17s 0.16s 0.16s
The numbers above were achieved with this code
int[] Integers = Enumerable.Range(-5, 5 * 1000 * 1000).ToArray();
void ArrayToStringAlois()
{
char[] buffer = new char[Integers.Length * 11]; // an integer can have 10 digits plus sign = 11 digits. This buffer is big enough for all possible numbers
int startIdx = 0;
for (int i = 0; i < Integers.Length; i++)
{
startIdx += ToCharArray(Integers[i], buffer, startIdx);
}
string lret = new string(buffer, 0, startIdx);
GC.KeepAlive(lret);
}
public static int ToCharArray(int value, char[] buffer, int bufferIndex)
{
if (value == 0)
{
buffer[bufferIndex] = '0';
return 1;
}
int len = 1;
int upperBound = 0;
if (value < 0)
{
buffer[bufferIndex] = '-';
len = 2;
upperBound = 1;
}
value = Math.Abs(value);
for (int rem = value / 10; rem > 0; rem /= 10)
{
len++;
}
for (int i = len - 1; i >= upperBound; i--)
{
buffer[bufferIndex + i] = (char)('0' + (value % 10));
value /= 10;
}
return len;
}
void ArrayToStringSteakOverCooked()
{
var numbers = new StringBuilder();
var length = Integers.Length;
for (int i = 0; i < length; i++)
{
numbers.Append(i.ToString());
}
var lret = numbers.ToString();
GC.KeepAlive(lret);
}
void ArrayToStringKeithNicolasAlternate2()
{
var lret = string.Concat(Integers);
GC.KeepAlive(lret);
}
Try string.Concat which is specially designed for this:
static void Main(string[] args) {
string numbers = string.Concat(FillArray());
...
}
There are multiple different ways that get better performance. In my testing StringBuilder possibly has the slight edge (timing is variable across multiple runs and the numbers are very close, over 10 iterations StringBuilder was always the fastest, the other two kept swapping around on which was faster)
static void Orginal(int[] array)
{
string numbers = "";
for (int i = 0; i < array.Count(); i++)
{
numbers += i.ToString();
}
}
static void Improved(int[] array)
{
var numbers = new StringBuilder();
for (int i = 0; i < array.Length; i++)
{
numbers.Append(i);
}
}
static void Alternate(int[] array)
{
var strings = array.Select(n => n.ToString()).ToArray();
var s = string.Join("", strings);
}
static void Alternate2(int[] array)
{
string.Concat(array);
}
static void Time(string name, Action<int[]> action, int[] array)
{
Stopwatch stopwatch = Stopwatch.StartNew();
action(array);
stopwatch.Stop();
Console.WriteLine("{0} - {1}", name, stopwatch.ElapsedMilliseconds);
}
static void Main(string[] args)
{
var array = Enumerable.Range(0, 100000).ToArray();
for (int i = 0; i < 10; i++)
{
Time("Original", Orginal, array);
Time("Improved", Improved, array);
Time("Alternate", Alternate, array);
Time("Alternate2", Alternate2, array);
}
}
I've been playing around / researching ways to randomize the order of chars in a string. I frankly just don't understand how to do it. I've searched through the C# documentation and a handful of websites. I found one particular way of randomizing the order of chars in a string but I don't understand how it works. I've also read that the Random class isn't truly random, which would explain why the results are so similar.
How exactly does the current method I'm using function (especially the OrderBy() method).
Is there a better way to do this?
Current code
string baseList = "abcdefghijklmnopqrstuvwxyz";
Random random = new Random();
string[] randLists = new string[baseList.Length];
for (int i = 0; i < baseList.Length; i++)
{
randLists[i] = new string(baseList.ToCharArray().OrderBy(s => (random.Next(2) % 2) == 0).ToArray());
Console.WriteLine(randLists[i]);
}
Console.Read();
This is my attempt at randomizing but it doesn't function at all:
*string bL = "abcdefghijklmnopqrstuvwxyz";
string[] rL = new string[bL.Length];
Random randomizer = new Random();
for (int i = 0; i < bL.Length; i++)
{
rL = new string(bL.ToCharArray().OrderBy(c => (randomizer.Next(0, 25)).ToString()));
}*
Thanks in advance for any assistance. I'll continue researching in the meantime.
Although the code that you found is short, it does not make a nicely distributed shuffle of the original string: the randomizer is likely to give you the same numbers in the process of generating a shuffle, increasing a probability that the corresponding characters would remain in the same order relative to each other as in your original string.
One solution to this problem is using Fisher–Yates shuffle. It is easy to implement (you need to stay away from common implementation errors, though).
Since string is immutable, you would need to shuffle an array of characters, and then make a string from it.
To add to the suggestion of the Fisher-Yates shuffle, here's a code sample, just ignore the test assertion, just trying to debug and make sure it's random enough.
[TestMethod]
public void RandomizeText()
{
string baseList = "abcdefghijklmnopqrstuvwxyz";
char[] result = baseList.ToCharArray();
Shuffle<char>(result);
var final = string.Join("", result);
final.Should().NotMatch(baseList);
}
public void Shuffle<T>(T[] array)
{
var random = new Random();
for (int x = 0; x < 100; x++)
{
for (int i = array.Length; i > 1; i--)
{
// Pick random element to swap.
int j = random.Next(i); // 0 <= j <= i-1
// Swap.
T tmp = array[j];
array[j] = array[i - 1];
array[i - 1] = tmp;
}
}
}
Another example...
static void Main(string[] args)
{
string baseList = "abcdefghijklmnopqrstuvwxyz";
Console.WriteLine(baseList);
string shuffled = Shuffle(baseList);
Console.WriteLine(shuffled);
Console.ReadLine();
}
static Random R = new Random();
static string Shuffle(string list)
{
int index;
List<char> chars = new List<char>(list);
StringBuilder sb = new StringBuilder();
while (chars.Count > 0)
{
index = R.Next(chars.Count);
sb.Append(chars[index]);
chars.RemoveAt(index);
}
return sb.ToString();
}
Instead of looping through each character to see if it's the one you want then adding the index your on to a list like so:
var foundIndexes = new List<int>();
for (int i = 0; i < myStr.Length; i++)
{
if (myStr[i] == 'a')
foundIndexes.Add(i);
}
You can use String.IndexOf, see example below:
string s = "abcabcabcabcabc";
var foundIndexes = new List<int>();
long t1 = DateTime.Now.Ticks;
for (int i = s.IndexOf('a'); i > -1; i = s.IndexOf('a', i + 1))
{
// for loop end when i=-1 ('a' not found)
foundIndexes.Add(i);
}
long t2 = DateTime.Now.Ticks - t1; // read this value to see the run time
I use the following extension method to yield all results:
public static IEnumerable<int> AllIndexesOf(this string str, string searchstring)
{
int minIndex = str.IndexOf(searchstring);
while (minIndex != -1)
{
yield return minIndex;
minIndex = str.IndexOf(searchstring, minIndex + searchstring.Length);
}
}
usage:
IEnumerable<int> result = "foobar".AllIndexesOf("o"); // [1,2]
Side note to a edge case: This is a string approach which works for one or more characters. In case of "fooo".AllIndexesOf("oo") the result is just 1 https://dotnetfiddle.net/CPC7D2
How about
string xx = "The quick brown fox jumps over the lazy dog";
char search = 'f';
var result = xx.Select((b, i) => b.Equals(search) ? i : -1).Where(i => i != -1);
The raw iteration is always better & most optimized.
Unless it's a bit complex task, you never really need to seek for a better optimized solution...
So I would suggest to continue with :
var foundIndexes = new List<int>();
for (int i = 0; i < myStr.Length; i++)
if (myStr[i] == 'a') foundIndexes.Add(i);
If the string is short, it may be more efficient to search the string once and count up the number of times the character appears, then allocate an array of that size and search the string a second time, recording the indexes in the array. This will skip any list re-allocations.
What it comes down to is how long the string is and how many times the character appears. If the string is long and the character appears few times, searching it once and appending indicies to a List<int> will be faster. If the character appears many times, then searching the string twice (once to count, and once to fill an array) may be faster. Exactly where the tipping point is depends on many factors that can't be deduced from your question.
If you need to search the string for multiple different characters and get a list of indexes for those characters separately, it may be faster to search through the string once and build a Dictionary<char, List<int>> (or a List<List<int>> using character offsets from \0 as the indicies into the outer array).
Ultimately, you should benchmark your application to find bottlenecks. Often the code that we think will perform slowly is actually very fast, and we spend most of our time blocking on I/O or user input.
public static List<int> GetSubstringLocations(string text, string searchsequence)
{
try
{
List<int> foundIndexes = new List<int> { };
int i = 0;
while (i < text.Length)
{
int cindex = text.IndexOf(searchsequence, i);
if (cindex >= 0)
{
foundIndexes.Add(cindex);
i = cindex;
}
i++;
}
return foundIndexes;
}
catch (Exception ex) { }
return new List<int> { };
}
public static String[] Split(this string s,char c = '\t')
{
if (s == null) return null;
var a = new List<int>();
int i = s.IndexOf(c);
if (i < 0) return new string[] { s };
a.Add(i);
for (i = i+1; i < s.Length; i++) if (s[i] == c) a.Add(i);
var result = new string[a.Count +1];
int startIndex = 0;
result[0] = s.Remove(a[0]);
for(i=0;i<a.Count-1;i++)
{
result[i + 1] = s.Substring(a[i] + 1, a[i + 1] - a[i] - 1);
}
result[a.Count] = s.Substring(a[a.Count - 1] + 1);
return result;
}
Here is the recursive code.
Can you guys give inputs on how I can implement this using iterative method?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace PermAndComb
{
class Program
{
static void Main(string[] args)
{
string s = "abcd";
Permutation(s);
Console.ReadKey();
}
public static void Permutation(string s)
{
int len = s.Length;
char [] inStr = s.ToCharArray();
StringBuilder outStr = new StringBuilder();
bool[] used = new bool[len];
doPermute(inStr, outStr,used, len, 0);
}
public static void doPermute(char[] instr, StringBuilder outStr,bool [] used, int len, int level)
{
if (level == len)
{
Console.WriteLine(outStr.ToString());
return;
}
for (int i = 0; i < len; i++)
{
if (used[i]) continue;
outStr.Append(instr[i]);
used[i] = true;
doPermute(instr, outStr, used, len, level + 1);
used[i] = false;
outStr.Length = outStr.Length - 1;
}
}
}
}
This article is rather heavy on the math, but might help out:
http://msdn.microsoft.com/en-us/magazine/cc163513.aspx
In summary, you use factoradics to enumerate the permutation in lexical order. And if that sounds like Greek to you, you're not alone.
Now, that's the correct way to do it (at least until a math PhD figures out something better). But I doubt it's what they're looking for in an interview. More likely, they're looking for an understanding that any recursive problem is also a stack problem that just uses the program's call stack rather than building it's own.
So you can convert any recursive code to iterative by taking a stack, pushing the initial value, then looping while the stack is not empty. Inside the loop you pop the next value, make the same calculation you would have made in your recursive function and push everywhere you would have made a recursive call.
the factoradics approach is less work than you'd be led to expect based on the article. I've had to use similar approach on many a Project Euler problem.
string str = "abcd";
Func<int, int> factorial = n =>
Enumerable.Range(1, n)
.Aggregate((i, j) => i * j);
Func<int, int, int[]> tofactoradic = (n, strLength) =>
Enumerable.Range(1, strLength)
.Reverse()
.Select(i => { var m = n; n /= i; return m % i; })
.ToArray();
Func<int[], string, string> Apply = (f, s) => {
var chars = s.ToList();
var result = "";
for (int i = 0; i < s.Length; i++) {
result += chars[f[i]];
chars.RemoveAt(f[i]);
}
return result;
};
int max = factorial(str.Length);
for (int i = 0; i < max; i++ ) {
var f = tofactoradic(i, str.Length);
Console.WriteLine(Apply(f, str));
}