1

So I have a Pig Latin Translator that supports multiple words. But whenever I enter some words (For this we'll just use "banana apple shears chocolate Theodore train" for example.) It will spit out the translated words correctly but it makes repeats! Here is my code:

namespace Pig_Latin_Translator
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
    List<string> vowels = new List<string>();
    List<string> specials = new List<string>();

    private void TranslateButton_Click(object sender, EventArgs e)
    {
        String[] parts = TranslateBox.Text.Split();
        foreach (string s in specials)
        {
            if (TranslateBox.Text.Contains(s) || TranslateBox.Text == "\"")
            {
                TranslateOutput.Text = "";
                MessageBox.Show("No Special Characters!", "Warning!", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                break;
            }
            else
            {
                 foreach (String part in parts)
                {
                    foreach (String v in vowels)
                    {
                        if (part.Substring(0, 1) == v)
                        {
                            TranslateOutput.Text = TranslateOutput.Text + " " + part + "ay";
                            break;
                        }
                        else
                        {
                            if (part.Substring(0, 2) == "sh" || part.Substring(0, 2) == "ch" || part.Substring(0, 2) == "th" || part.Substring(0, 2) == "tr")
                            {
                                string SwitchP = part.Substring(2) + part.Substring(0, 2);
                                TranslateOutput.Text = TranslateOutput.Text + " " + SwitchP + "ay";
                                break;
                            }
                            else
                            {
                                string Switch = part.Substring(1) + part.Substring(0, 1);
                                TranslateOutput.Text = TranslateOutput.Text + " " + Switch + "ay";
                                break;
                            }
                        }
                    }
                }
            }
        }
    }
    private void Form1_Load(object sender, EventArgs e)
    {
        vowels.Add("a");
        vowels.Add("e");
        vowels.Add("i");
        vowels.Add("o");
        vowels.Add("u");

        specials.Add("`");
        specials.Add("1");
        specials.Add("2");
        specials.Add("3");
        specials.Add("4");
        specials.Add("5");
        specials.Add("6");
        specials.Add("7");
        specials.Add("8");
        specials.Add("9");
        specials.Add("0");
        specials.Add("-");
        specials.Add("=");
        specials.Add("[");
        specials.Add("]");
        specials.Add(@"\");
        specials.Add(";");
        specials.Add("'");
        specials.Add(",");
        specials.Add(".");
        specials.Add("/");

        specials.Add("~");
        specials.Add("!");
        specials.Add("@");
        specials.Add("#");
        specials.Add("$");
        specials.Add("%");
        specials.Add("^");
        specials.Add("&");
        specials.Add("*");
        specials.Add("(");
        specials.Add(")");
        specials.Add("_");
        specials.Add("+");
        specials.Add("{");
        specials.Add("}");
        specials.Add("|");
        specials.Add(":");
        specials.Add("\"");
        specials.Add("<");
        specials.Add(">");
        specials.Add("?");
    }

    private void AboutButton_Click(object sender, EventArgs e)
    {
        MessageBox.Show("Pig Latin is a fake language. It works by taking the first letter (Or two if it's a pair like 'th' or 'ch') and bringing it to the end, unless the first letter is a vowel. Then add 'ay' to the end. So 'bus' becomes 'usbay', 'thank' becomes 'ankthay' and 'apple' becomes 'appleay'.", "About:", MessageBoxButtons.OK, MessageBoxIcon.Information);
    }
}

}

Which outputs if you typed in "banana apple shears chocolate Theodore train":

"ananabay appleay earsshay ocolatechay heodoreTay aintray" repeating over 10 times.

BTW: Sorry if you can't answer because I know there is LOTS of code. But it doesn't matter because the thing still is useful. It's just that it shouldn't happen and get on my nerves. And I know there is still many glitches and MUCH more to do but I want to get this resolved first.

Xephyr
  • 122
  • 1
  • 2
  • 9

3 Answers3

1

You are iterating through your words once for each special character. Your foreach to go through your words and translate is inside of your foreach to check to see if the textbox contains any special characters.

In otherwords, you are going to do your translation once per special character.

You'll want to move your foreach (String part in parts) out of your foreach (string s in specials)

Alexei Levenkov
  • 98,904
  • 14
  • 127
  • 179
Trent Sartain
  • 446
  • 2
  • 10
  • If you are not sure if you have answer - post it as comments. Otherwise please avoid fluff text like: "hope you like it" or "try this out". – Alexei Levenkov Dec 20 '15 at 02:30
1

You have a bit of a logic problem in your loops.

Your outer loop:

foreach( string s in specials ) {

...is looping through all 42 characters in your special characters list.

Your inner loop

foreach( String part in parts ) {

...is then executed 42 times. So for your six word example you're actually doing your pig latin conversion 252 times.

If you extract the inner loop from the outer, your results are better. Like this:

foreach( string s in specials ) {
    if( TranslateBox.Text.Contains( s ) || TranslateBox.Text == "\"" ) {
        TranslateOutput.Text = "";
        MessageBox.Show( "No Special Characters!", "Warning!", MessageBoxButtons.OK, MessageBoxIcon.Warning );
        return;
    }
}

String[] parts = TranslateBox.Text.Split();
foreach( String part in parts ) {
    foreach( String v in vowels ) {
        if( part.Substring( 0, 1 ) == v ) {
            TranslateOutput.Text = TranslateOutput.Text + " " + part + "ay";
            break;
        }
        else {
            if( part.Substring( 0, 2 ) == "sh" || part.Substring( 0, 2 ) == "ch" || part.Substring( 0, 2 ) == "th" || part.Substring( 0, 2 ) == "tr" ) {
                string SwitchP = part.Substring( 2 ) + part.Substring( 0, 2 );
                TranslateOutput.Text = TranslateOutput.Text + " " + SwitchP + "ay";
                break;
            }
            else {
                string Switch = part.Substring( 1 ) + part.Substring( 0, 1 );
                TranslateOutput.Text = TranslateOutput.Text + " " + Switch + "ay";
                break;
            }
        }
    }
}

A somewhat more concise implementation would be:

private void TranslateButton_Click( object sender, EventArgs e )
{
    char[] specials = "`1234567890-=[]\";',./~!@#$%^&*()_+{}|:\\<>?".ToArray();
    char[] vowels = "aeiou".ToArray();

    TranslateOutput.Text = String.Empty;

    if( TranslateBox.Text.IndexOfAny( specials ) > -1 ) {
        MessageBox.Show( "No Special Characters!", "Warning!", MessageBoxButtons.OK, MessageBoxIcon.Warning );
        return;
    }

    String[] parts = TranslateBox.Text.Split();
    foreach( String part in parts ) {
        int firstVowel = part.IndexOfAny( vowels );
        if( firstVowel > 0 ) {
            TranslateOutput.Text += part.Substring( firstVowel ) + part.Substring( 0, firstVowel ) + "ay ";
        }
        else {
            TranslateOutput.Text += part + "ay ";
        }
    }

    TranslateOutput.Text = TranslateOutput.Text.TrimEnd();
}

In this example, I create two character arrays for the specials and the vowels. I can then leverage the framework's IndexOfAny method to search for any of the characters in the array and return the index of the first occurrence. That will find the first special, if any, in the first loop and the first vowel in the second loop. Once I have that character index from the word I can parse the word into pig Latin. Note that I'm checking for zero as the vowel index since, in pig Latin a leading vowel stays where it is and the "ay" is just appended to the end of the word.

Bob Mc
  • 1,980
  • 1
  • 28
  • 38
1

You are nesting your code in two loops that it shouldn't be nested in

foreach (string s in specials)

and

foreach (String v in vowels)

Your break statements are getting you out of trouble for one, but not the other.

You can avoid these loops entirely is you use the .Any(...) predicate.

Here's what your code could look like:

private void TranslateButton_Click(object sender, EventArgs e)
{
    TranslateOutput.Text = "";
    if (specials.Any(s => TranslateBox.Text.Contains(s)))
    {
        MessageBox.Show("No Special Characters!", "Warning!", MessageBoxButtons.OK, MessageBoxIcon.Warning);
    }
    else
    {
        String[] parts = TranslateBox.Text.Split();
        foreach (var part in parts)
        {
            var index = 1;
            if (vowels.Any(v => part.Substring(0, 1).ToLower() == v))
            {
                index = 0;
            }
            else if (new [] { "sh", "ch", "th", "tr", }.Contains(part.Substring(0, 2).ToLower()))
            {
                index = 2;
            }
            TranslateOutput.Text += " " + part.Substring(index) + part.Substring(0, index);
        }
    }
    TranslateOutput.Text = TranslateOutput.Text.TrimEnd();
}

This brings it down to the one foreach loop that you actually need.

You can also get your code to initalize vowels and specials down to this:

vowels.AddRange("aeiou".Select(x => x.ToString()));
specials.AddRange(@"`1234567890-=[]\;',./~!@#$%^&*()_+{}|:""<>?".Select(x => x.ToString()));
Enigmativity
  • 113,464
  • 11
  • 89
  • 172