using System;
using System.Text.RegularExpressions;
using System.Diagnostics;
public class Test
{
static Regex reg = new Regex(@"\{[^\{\}]*\}", RegexOptions.Compiled);
static Random
rand = new Random
((int)DateTime.
Now.
Ticks); static String[] parts;
public static void Main()
{
String text = "Oh! {{I'm|You're} here!|How are you{ doing{|, {buddy|pal|guy}}|}?}";
Console.WriteLine("Input Text: " + text);
Console.WriteLine("Testing SpinRE: " + SpinRE(text));
Console.WriteLine("Testing SpinRE: " + SpinRE(text));
Console.WriteLine("Testing SpinRE: " + SpinRE(text));
Console.WriteLine("Testing SpinRE: " + SpinRE(text));
Console.WriteLine("Testing SpinRE: " + SpinRE(text));
Console.WriteLine("Testing SpinRE: " + SpinRE(text));
Console.WriteLine("Testing SpinRE: " + SpinRE(text));
Console.WriteLine("Testing SpinRE: " + SpinRE(text));
Console.WriteLine("Testing SpinRE: " + SpinRE(text));
Console.WriteLine("Testing SpinRE: " + SpinRE(text));
Console.WriteLine("Testing SpinNoRE: " + SpinNoRE(text));
Console.WriteLine("Testing SpinNoRE: " + SpinNoRE(text));
Console.WriteLine("Testing SpinNoRE: " + SpinNoRE(text));
Console.WriteLine("Testing SpinNoRE: " + SpinNoRE(text));
Console.WriteLine("Testing SpinNoRE: " + SpinNoRE(text));
Console.WriteLine("Testing SpinNoRE: " + SpinNoRE(text));
Console.WriteLine("Testing SpinNoRE: " + SpinNoRE(text));
Console.WriteLine("Testing SpinNoRE: " + SpinNoRE(text));
Console.WriteLine("Testing SpinNoRE: " + SpinNoRE(text));
Console.WriteLine("Testing SpinNoRE: " + SpinNoRE(text));
Console.WriteLine("Testing SpinSergey: " + SpinSergey(text));
Console.WriteLine("Testing SpinSergey: " + SpinSergey(text));
Console.WriteLine("Testing SpinSergey: " + SpinSergey(text));
Console.WriteLine("Testing SpinSergey: " + SpinSergey(text));
Console.WriteLine("Testing SpinSergey: " + SpinSergey(text));
Console.WriteLine("Testing SpinSergey: " + SpinSergey(text));
Console.WriteLine("Testing SpinSergey: " + SpinSergey(text));
Console.WriteLine("Testing SpinSergey: " + SpinSergey(text));
Console.WriteLine("Testing SpinSergey: " + SpinSergey(text));
Console.WriteLine("Testing SpinSergey: " + SpinSergey(text));
Stopwatch s1 = new Stopwatch();
Stopwatch s2 = new Stopwatch();
Stopwatch s3 = new Stopwatch();
for (int i = 0; i < 100000; i++)
{
s1.Start(); SpinRE(text); s1.Stop();
s2.Start(); SpinNoRE(text); s2.Stop();
s3.Start(); SpinSergey(text); s3.Stop();
}
Console.WriteLine("\nTime elapsed over 100,000 runs of each in alternation:\n");
Console.WriteLine("SpinRE: " + String.Format("{0:00}.{1:000}", s1.Elapsed.Seconds, s1.Elapsed.Milliseconds) + "s");
Console.WriteLine("SpinNoRE: " + String.Format("{0:00}.{1:000}", s2.Elapsed.Seconds, s2.Elapsed.Milliseconds) + "s");
Console.WriteLine("SpinSergey: " + String.Format("{0:00}.{1:000}", s3.Elapsed.Seconds, s3.Elapsed.Milliseconds) + "s");
}
public static String SpinRE(String text)
{
while (true)
{
Match m = reg.Match(text);
if (!m.Success) break;
parts = m.Value.Substring(1, m.Value.Length-2).Split('|');
text
= text.
Substring(0, m.
Index) + parts
[rand.
Next(parts.
Length)] + text.
Substring(m.
Index + m.
Length); }
return text;
}
public static String SpinNoRE(String text)
{
int i; // stores index of current open brace.
int j; // stores index of current close brace.
int e; // stores index of earliest untouched open brace.
// helpers.
char[] curls = new char[] {'{', '}'};
// hack to prevent ArgumentOutOfRangeExceptions without having to check.
text += '~';
// index of "earliest untouched open brace" is unknown at start.
e = -1;
do
{
i = e;
e = -1;
// loop as long as an open brace is found.
while ((i = text.IndexOf('{', i+1)) != -1)
{
j = i;
// loop as long as a brace is found and it is not a close brace.
while ((j = text.IndexOfAny(curls, j+1)) != -1 && text[j] != '}')
{
// means nested spintax was found; make j (the inner open
// brace) the "new" i and continue search for close brace.
// nested spintax found; we're going to skip the current
// open brace in favor of this new one; but remember the
// index of the current open brace if it's the first such
// to be skipped; make j the "new" i; continue the search.
if (e == -1) e = i;
i = j;
}
// if close brace found, process spintax.
if (j != -1)
{
parts = text.Substring(i+1, (j-1)-(i+1-1)).Split('|');
text
= text.
Remove(i
, j
-(i
-1)).
Insert(i
, parts
[rand.
Next(parts.
Length)]); }
}
}
// loop as long as an earlier untouched open brace exists (decrement e
// before looping: the next loop begins its search at "i+1" == "e+1").
while (e-- != -1);
// undo aforementioned hack and return.
return text.Remove(text.Length-1);
}
// @SergeyS's code:
static int[] partIndices = new int[100];
static int[] depth = new int[100];
static char[] symbolsOfTextProcessed = new char[100000];
public static String SpinSergey(String text)
{
int cur = SpinEvenMoreFasterInner(text, 0, text.Length, 0);
return new String(symbolsOfTextProcessed, 0, cur);
}
public static int SpinEvenMoreFasterInner(String text, int start, int end, int symbolIndex)
{
int last = start;
for (int i = start; i < end; i++)
{
if (text[i] == '{')
{
int k = 1;
int j = i + 1;
int index = 0;
partIndices[0] = i;
depth[0] = 1;
for (; j < end && k > 0; j++)
{
if (text[j] == '{')
k++;
else if (text[j] == '}')
k--;
else if (text[j] == '|')
{
if (k == 1)
{
partIndices[++index] = j;
depth[index] = 1;
}
else
depth[index] = k;
}
}
if (k == 0)
{
partIndices[++index] = j - 1;
int part
= rand.
Next(index
); text.CopyTo(last, symbolsOfTextProcessed, symbolIndex, i - last);
symbolIndex += i - last;
if (depth[part] == 1)
{
text.CopyTo(partIndices[part] + 1, symbolsOfTextProcessed, symbolIndex, partIndices[part + 1] - partIndices[part] - 1);
symbolIndex += partIndices[part + 1] - partIndices[part] - 1;
}
else
{
symbolIndex = SpinEvenMoreFasterInner(text, partIndices[part] + 1, partIndices[part + 1], symbolIndex);
}
i = j - 1;
last = j;
}
}
}
text.CopyTo(last, symbolsOfTextProcessed, symbolIndex, end - last);
return symbolIndex + end - last;
}
}