tags:

views:

143

answers:

6

I'm brand-spanking new to Java and I made this little translator for PigLatin.

package stringmanipulation;

public class PigLatinConverter {
    public String Convert(String word){
        int position = 0;
        if (!IsVowel(word.charAt(0))) {
            for (int i= 0; i < word.length(); i++) {
                if (IsVowel(word.charAt(i))) {
                    position = i;
                    break;
                }
            }
            String first = word.substring(position, word.length());
            String second = word.substring(0, position) + "ay";

            return first + second;
        } else {
            return word + "way";
        }
    }

    public boolean IsVowel(char c){
        if (c == 'a')
            return true;
        else if(c == 'e')
            return true;
        else if(c == 'i')
            return true;
        else if(c == 'o')
            return true;
        else if(c == 'u')
            return true;
        else
            return false;        
    }
}

Are there any improvements I can make?

Are there any nifty Java tricks that are in the newest Java version I might not be aware of? I come from a C# background.

Thank you!

A: 

Not strictly an improvement as such, but Java convention dictates that methods should start with a lowercase letter.

Ryan Mentley
word?~~~~~~~~~~~
Sergio Tapia
Sergio seems to be a C# guy. Haters gonna hate.
mattbasta
I'm not hating, I really want to learn Java. :)
Sergio Tapia
A: 

I'm years removed from Java, but overall, your code looks fine. If you wanted to be nitpicky, here are some comments:

  • Add comments. It doesn't have to follow the Javadoc specification, but at least explicitly describe the accepted argument and the expected return value and perhaps give some hint as to how it works (behaving differently depending on whether the first character is a vowel)
  • You might want to catch IndexOutOfBoundsException, which I think might happen if you pass it a zero length string.
  • Method names should be lower case.
  • IsVowel can be rewritten return c == 'a' || c == 'e' and so on. Due to short-circuiting, the performance in terms of number of comparisons should be similar.
Steven Xu
+4  A: 

I'd rewrite isVowel(char ch) as follows:

return "aeiou".indexOf(ch) != -1;

And I'd write the following instead:

// String first = word.substring(position, word.length());
   String first = word.substring(position);

I'd also rename method names to follow coding convention.

And of course, being me, I'd also use regex instead of substring and for loop.

System.out.println("string".replaceAll("([^aeiou]+)(.*)", "$2$1ay"));
// ingstray

References

polygenelubricants
This is the sexyness I was looking for. I'll test it out. EDIT: I get an error: Required: CharSequence Found: Char
Sergio Tapia
@Sergio: sorry, use `indexOf(char)` instead.
polygenelubricants
Thank you. :) WOrks!
Sergio Tapia
+1 for the "being me, I'd also use regex" (and the rest of the answer of course). Made me laugh.
Pascal Thivent
+1  A: 

Disclaimer: I don't know Java.

Inverted logic is confusing please write your if statement as such:

    if (IsVowel(word.charAt(0))) {
        return word + "way";
    } else {
        for (int i= 0; i < word.length(); i++) {

        // ...

        return first + second;
    }

You can even drop the else.

IsVowel may need to be private. It can also be rewritten using a single || chain, or as a "".indexOf (or whatever it is in Java).

Your for logic can be simplified int a short while:

        while (position < word.length() && !IsVowel(word.charAt(position)) {
            ++position;
        }
strager
I agree with the inverted logic. That while statement seems a bit convoluted in my opinion.
Sergio Tapia
@Sergio Tapia, Java may have something like `.indexOf` which takes a callback as an argument (and you'd use `IsVowel` as the callback), which turns the loop into a call and a check.
strager
I *much* prefer "returning early"; more levels of indentation makes the code harder to read. Apparently, nested conditionals are also the main source of bugs.
tc.
@tc., While I agree, I find it's more personal style and not something which is that objective. (See: single-`return`-per-function advocates.)
strager
@strager, presumably those are the same people who think "goto" is always evil, whereas I think unnecessarily embedding flow control into your data is evil (and a pain for your compiler to optimize).
tc.
A: 

Is this homework? If so, tag it as such.

  • Unclear what expected behaviour is for "honest" or "ytterbium".
  • It doesn't respect capitals ("Foo" should turn into "Oofay", and AEIOU are also vowels).
  • It crashes if you pass in the empty string.
tc.
Not my homework.
Sergio Tapia
+1  A: 

Here's a complete rewrite that makes the code more readable if you know how to read regex:

String[] words =
    "nix scram stupid beast dough happy question another if".split(" ");

for (String word : words) {
    System.out.printf("%s -> %s%n", word,
        ("w" + word).replaceAll(
            "w(qu|[^aeiou]+|(?<=(w)))([a-z]*)",
            "$3-$1$2ay"
        )
    );
}

This prints (as seen on ideone.com):

nix -> ix-nay
scram -> am-scray
stupid -> upid-stay
beast -> east-bay
dough -> ough-day
happy -> appy-hay
question -> estion-quay
another -> another-way
if -> if-way

Note that question becomes estion-quay, which is the correct translation according to Wikipedia article. In fact, the above words and translations are taken from the article.

The way the regex work is as follows:

  • First, all words are prefixed with w just in case it's needed
  • Then, skipping that w, look for either qu or a non-empty sequence of consonants. If neither can be found, then the actual word starts with a vowel, so grab the w using capturing lookbehind
  • Then just rearrange the components to get the translation

That is:

"skip" dummy w
|
w(qu|[^aeiou]+|(?<=(w)))([a-z]*)   -->  $3-$1$2ay
 \                2\_/ /\______/
  \_________1_________/    3

References

polygenelubricants
I start to see ASCII art in your answers, an upside down truck in this one :) +1 for art.
Pascal Thivent