jeudi 17 avril 2014

Pig Latin c# avec Regex remplacer - débordement de pile


First off- This is a Homework problem. Just getting that out there. Trying to build a Pig Latin Translator in C#, we have to use Regex replace but I'm having some issues. Not allowed to use the Split method to obtain an array of words. We have to use the static method Replace of type Regex. White Space, punctuation linebreaks et should be preserved. Capitalized words should remain so. For those unfamiliar with the rules of Pig Latin-



  1. If the string begins with a vowel, add "way" to the string. (vowels are a,e,i,o,u) Examples: Pig-Latin for "orange" is "orangeway", Pig-Latin for “eating” is “eatingway”

  2. Otherwise, find the first occurrence of a vowel, move all the characters before the vowel to the end of the word, and add "ay". (in the middle of the word ‘y’ also counts as a vowel, but NOT at the beginning) Examples: Pig-Latin for "story" is "orystay" since the characters "st" occur before the first vowel; Pig-Latin for "crystal" is "ystalcray", but Pig-Latin for "yellow" is "ellowyay".

  3. If there are no vowels, add "ay".Examples: Pig-Latin for "mph" is "mphay", Pig-Latin for RPM is RPMay


I've got a ton of commented out code, so I'll remove that for reading ease. My test sentence is "Eat monkey poo." I'm getting "Ewayaayt moaynkeayy poayoay." I know Regex is 'greedy', but I can't figure out how to get it to stop with just the first vowel it finds. Using Textboxes as well.


namespace AssignmentPigLatin
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
OriginalTb.Text = "Eat monkey poo.";
}

private void translateButton_Click(object sender, RoutedEventArgs e)
{
string vowels = "[AEIOUaeiou]";
var regex = new Regex(vowels);
var translation = regex.Replace(OriginalTb.Text, TranslateToPigLatin);
PigLatinTb.Text = translation;
}

private void ClearButton_Click(object sender, RoutedEventArgs e)
{
OriginalTb.Text = "";
PigLatinTb.Text = "";
}

static string TranslateToPigLatin(Match match)
{

string word = match.ToString();
string firstLetters = word.Substring(0, match.Length);
string restLetters = word.Substring(firstLetters.Length - 1, word.Length-1);
string newWord;
if (match.Index == 0)
{

return word + "way";

}
else
{
return restLetters + firstLetters + "ay";
}
}
}
}



The question was interesting to answer. Don't forget to attribute me ;)


Add this method in your class AssignmentPigLatin


private string PigLatinTranslator(string s)
{
s = Regex.Replace(s, @"(\b[a|e|i|o|u]\w+)", "$1way", RegexOptions.IgnoreCase);
List<string> words = new List<string>();
foreach (Match v in Regex.Matches(s, @"\w+"))
{
string result;
if (!v.Value.EndsWith("way"))
{
result = Regex.Replace(v.Value, @"([^a|e|i|o|u]*)([a|e|i|o|u])(\w+)", "$2$3$1ay", RegexOptions.IgnoreCase);
words.Add(result);
}
else { words.Add(v.Value); }
}
s = string.Join(" ", words);
words.Clear();
foreach (Match v in Regex.Matches(s,@"\w+"))
{
string result = Regex.Replace(v.Value, @"\b([^a|e|i|o|u]+)\b", "$1ay", RegexOptions.IgnoreCase);
words.Add(result);
}
s = string.Join(" ", words);
return s;
}

Call it like this:


string test = "MPH Eat monkey poo."; // Added MPH, so that you can test my method works or not.
string result = PigLatinTranslator(test);
Console.WriteLine(result); // MPHay Eatway onkeymay oopay.



Easier and more clear solution is to use Regex.Replace with lambda.


static string TranslateToPigLatin(string input)
{
char[] vowels = new[] { 'A', 'E', 'I', 'O', 'U', 'a', 'e', 'i', 'o', 'u' };
char[] vowelsExtended = vowels.Concat(new[] { 'Y', 'y' }).ToArray();
string output = Regex.Replace(input, @"\w+", m =>
{
string word = m.Value;
if (vowels.Contains(word[0]))
return word + "way";
else
{
int indexOfVowel = word.IndexOfAny(vowelsExtended, 1);
if (indexOfVowel == -1)
return word + "ay";
else
return word.Substring(indexOfVowel) + word.Substring(0, indexOfVowel) + "ay";
}
});
return output;
}


First off- This is a Homework problem. Just getting that out there. Trying to build a Pig Latin Translator in C#, we have to use Regex replace but I'm having some issues. Not allowed to use the Split method to obtain an array of words. We have to use the static method Replace of type Regex. White Space, punctuation linebreaks et should be preserved. Capitalized words should remain so. For those unfamiliar with the rules of Pig Latin-



  1. If the string begins with a vowel, add "way" to the string. (vowels are a,e,i,o,u) Examples: Pig-Latin for "orange" is "orangeway", Pig-Latin for “eating” is “eatingway”

  2. Otherwise, find the first occurrence of a vowel, move all the characters before the vowel to the end of the word, and add "ay". (in the middle of the word ‘y’ also counts as a vowel, but NOT at the beginning) Examples: Pig-Latin for "story" is "orystay" since the characters "st" occur before the first vowel; Pig-Latin for "crystal" is "ystalcray", but Pig-Latin for "yellow" is "ellowyay".

  3. If there are no vowels, add "ay".Examples: Pig-Latin for "mph" is "mphay", Pig-Latin for RPM is RPMay


I've got a ton of commented out code, so I'll remove that for reading ease. My test sentence is "Eat monkey poo." I'm getting "Ewayaayt moaynkeayy poayoay." I know Regex is 'greedy', but I can't figure out how to get it to stop with just the first vowel it finds. Using Textboxes as well.


namespace AssignmentPigLatin
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
OriginalTb.Text = "Eat monkey poo.";
}

private void translateButton_Click(object sender, RoutedEventArgs e)
{
string vowels = "[AEIOUaeiou]";
var regex = new Regex(vowels);
var translation = regex.Replace(OriginalTb.Text, TranslateToPigLatin);
PigLatinTb.Text = translation;
}

private void ClearButton_Click(object sender, RoutedEventArgs e)
{
OriginalTb.Text = "";
PigLatinTb.Text = "";
}

static string TranslateToPigLatin(Match match)
{

string word = match.ToString();
string firstLetters = word.Substring(0, match.Length);
string restLetters = word.Substring(firstLetters.Length - 1, word.Length-1);
string newWord;
if (match.Index == 0)
{

return word + "way";

}
else
{
return restLetters + firstLetters + "ay";
}
}
}
}


The question was interesting to answer. Don't forget to attribute me ;)


Add this method in your class AssignmentPigLatin


private string PigLatinTranslator(string s)
{
s = Regex.Replace(s, @"(\b[a|e|i|o|u]\w+)", "$1way", RegexOptions.IgnoreCase);
List<string> words = new List<string>();
foreach (Match v in Regex.Matches(s, @"\w+"))
{
string result;
if (!v.Value.EndsWith("way"))
{
result = Regex.Replace(v.Value, @"([^a|e|i|o|u]*)([a|e|i|o|u])(\w+)", "$2$3$1ay", RegexOptions.IgnoreCase);
words.Add(result);
}
else { words.Add(v.Value); }
}
s = string.Join(" ", words);
words.Clear();
foreach (Match v in Regex.Matches(s,@"\w+"))
{
string result = Regex.Replace(v.Value, @"\b([^a|e|i|o|u]+)\b", "$1ay", RegexOptions.IgnoreCase);
words.Add(result);
}
s = string.Join(" ", words);
return s;
}

Call it like this:


string test = "MPH Eat monkey poo."; // Added MPH, so that you can test my method works or not.
string result = PigLatinTranslator(test);
Console.WriteLine(result); // MPHay Eatway onkeymay oopay.


Easier and more clear solution is to use Regex.Replace with lambda.


static string TranslateToPigLatin(string input)
{
char[] vowels = new[] { 'A', 'E', 'I', 'O', 'U', 'a', 'e', 'i', 'o', 'u' };
char[] vowelsExtended = vowels.Concat(new[] { 'Y', 'y' }).ToArray();
string output = Regex.Replace(input, @"\w+", m =>
{
string word = m.Value;
if (vowels.Contains(word[0]))
return word + "way";
else
{
int indexOfVowel = word.IndexOfAny(vowelsExtended, 1);
if (indexOfVowel == -1)
return word + "ay";
else
return word.Substring(indexOfVowel) + word.Substring(0, indexOfVowel) + "ay";
}
});
return output;
}

0 commentaires:

Enregistrer un commentaire