3

我在这里的任务是使用递归创建一个猪拉丁语翻译器,它可以翻译句子。规则如下:

  1. 如果englishWord 中没有元音,那么pigLatinWord 就是englishWord + "ay"。(有十个元音:'a'、'e'、'i'、'o' 和 'u',以及它们的大写对应物。就本作业而言,'y' 不被视为元音,即my 变成 myay,why 变成 whyay 等)
  2. 否则,如果englishWord 以元音开头,那么pigLatinWord 就是englishWord + "yay"。
  3. 否则(如果englishWord 中有元音但不以元音开头),则pigLatinWord 为end + start + "ay",其中end 和start 定义如下:-

让 start 是所有englishWord 直到(但不包括)它的第一个元音。让 end 成为从第一个元音开始的所有英语单词。但是,如果englishWord 大写,则结束大写并“取消大写”开始。

到目前为止,这是我的代码(对不起,奇怪的格式,我的评论搞砸了):

    /*Recursively Translate a String (without punctuation or numerical characters) to Pig Latin*/


//prep the string for translation and submit it to be translated
public static String translate(String finished) {
    finished.trim();        //Trim the String of whitespace at the front and end
    finished += " ";        //Because of the recursive method I use, the string must have a
                            //space at the end
    finished = translateSentence(finished); //recursively translate the string
    finished.trim();    //trim the whitespace added earlier
    return finished;    //Return the string
}


//recursively submits each word in the string to the translator, then 
//returns the translated sentence
private static String translateSentence(String finished) {

if (finished.length() == 0) {   //the base condition is met when each word in the string
   return finished; //has been sent to the translator (string is empty)
    }
    else {
    return (translateWord(finished.substring(0, finished.indexOf(' ') )) + " "
        + translateSentence(finished.substring(finished.indexOf(' ') + 1)));        
    }
}
/*If the base condition is not met, the method returns the first word of the string
 * (translated) and a space, then submits the rest of the 
 * string back to the method.  The first word is defined as the beginning 
 * of the string up until the first space. The rest of the string
 * starts one character after the space.   */



//Checks the submitted word for vowels and vowel placement, and translates accordingly

    private static String translateWord(String stringA) {
    if (stringA.indexOf('a') == -1
    && stringA.indexOf('e') == -1           //Checks for presence of any vowels
    && stringA.indexOf('i') == -1       //if no vowels are found
    && stringA.indexOf('o') == -1       //the word + ay is returned
    && stringA.indexOf('u') == -1
    && stringA.indexOf('A') == -1
    && stringA.indexOf('E') == -1
    && stringA.indexOf('I') == -1
    && stringA.indexOf('O') == -1
    && stringA.indexOf('U') == -1) {
        return stringA + "ay";
    }       
    if (stringA.charAt(0) == 'a'
    ||  stringA.charAt(0) == 'e' //checks if there is a vowel at the start
    ||  stringA.charAt(0) == 'i'//of the string. if there is a vowel
    ||  stringA.charAt(0) == 'o'    //it returns the word + yay
    ||  stringA.charAt(0) == 'u'
    ||  stringA.charAt(0) == 'A'
    ||  stringA.charAt(0) == 'E'
    ||  stringA.charAt(0) == 'I'
    ||  stringA.charAt(0) == 'O'
    ||  stringA.charAt(0) == 'U') {
        return stringA + "yay";
    }       
/* if the word has a vowel that isn't at the start, the part of the string


* before the first vowel is moved to the end of the vowel, and "ay" is added.


* However, if the first character in the word is capitalized, the first vowel becomes


* uppercase and the former first character in the word becomes lowercase */
    else {
        if (Character.isUpperCase(stringA.charAt(0))) {
            return Character.toUpperCase(stringA.charAt(firstVowel(stringA, 0))) 
            + stringA.substring(firstVowel(stringA, 0) + 1, stringA.length())
            + Character.toLowerCase(stringA.charAt(0))
            + stringA.substring(1, firstVowel(stringA, 0)) + "ay";
        }
        else {
        return stringA.substring(firstVowel(stringA, 0), stringA.length()) 
        + stringA.substring(0, firstVowel(stringA, 0)) + "ay";
        }
    }
}



//Recursively determines the index number of the first vowel in a given word
//0 must always be submitted as int x
public static int firstVowel(String stringA, int x) {
    if (x > stringA.length() - 1) {     //if the index number becomes greater than the length
        return -1;      //of the string, -1 (no vowels) is returned
    }
    if (stringA.charAt(x) == 'a' 
        || stringA.charAt(x) == 'e'     //the base condition is met when the character
        || stringA.charAt(x) == 'i'     //at the current index number is a vowel
        || stringA.charAt(x) == 'o'     //and the index number is returned
        || stringA.charAt(x) == 'u' 
        || stringA.charAt(x) == 'A' 
        || stringA.charAt(x) == 'E' 
        || stringA.charAt(x) == 'I' 
        || stringA.charAt(x) == 'O' 
        || stringA.charAt(x) == 'U') {
        return x;
    }
    else {
        return firstVowel(stringA, x + 1);  //otherwise, the string and the index number
    }                                       // + 1 are submitted back to the method
}

这给了我想要的输出(“Why hello there”变成了“Whyay ellohay erethay”),但现在它不能处理标点符号。基本上我正在寻找的是任何提示或帮助让我的代码处理标点符号,或任何改进我的代码的方法(仍然使用递归)。

4

2 回答 2

2

@Cedric 给出了一个很好的建议,可以在执行处理时使用正则表达式。

在这里,我给出了一些其他的方向。

首先,我相信您可以更好地重用您的firstVowel方法。

translateWord可以大大简化为(我跳过您的大写处理以使其更易于理解):

private static String translateWord(String s) {
    int firstVowelIndex = firstVowel(s);
    if (firstVowel < 0) { // no Vowel
        return s + "ay";
    } else if (firstVowel == 0) {  // start with Vowel
        return s + "yay";
    } else {
        return s.substring(firstVowelIndex) + s.substring(0, firstVowelIndex) + "ay";
    }
}

你也有一些东西需要简化firstVowel()

首先可以简化元音的比较。一种方法是使用正则表达式。另一种方法是使用 Set:

假设你有这样的东西:

static Set<Character> vowels = new HashSet<Character>(
        Arrays.asList('a','e','i','o','u','A','E','I','O','U'));

然后你的元音检查可以从一个长的 if 语句更改为:

if (vowels.contains(c)) {...}

其次,您可能故意以递归方式编写 firstVowel() 以进行练习。但是,在我看来,如果以循环的形式编写该方法,则更容易阅读:

private static int firstVowel(String s) {
    int index = -1;
    for (int i = 0; i < s.length; ++i ) {
        if (isVowel(s.charAt(i)) {
            index = i;
            break;
        }
    }
    return index;
}

我相信这两个更改几乎可以以更具可读性的方式将您的代码减半。

于 2012-12-10T02:19:08.500 回答
0

尝试使用正则表达式来匹配您的单词。正则表达式 [a-zA-Z]+ 将匹配任何同时出现的字母序列。关于如何在 java 中使用正则表达式,我将把它作为练习留给你,但这并不难。

基本上拿你的字符串,找到下一个匹配项。存储单词的最后一个字符在原始字符串中的位置。处理该单词,然后找到下一个匹配项。现在取上一个匹配的最后一个字符和当前匹配的第一个字符之间的子串,直接输出,不做任何处理。

示例:假设我有字符串“Hello, world!”

  • 第一个匹配是“Hello”,从位置 0 开始,到位置 4(含)结束。
  • 处理并输出“Ellohay”
  • 找到下一个匹配“世界”,从位置 7 开始,到位置 11 结束
  • 输出上一个匹配的最后一个字符和当前匹配的第一个字符之间的子字符串。这意味着从位置 5 到位置 6,这给出了字符串 ", "
  • 处理当前匹配并输出它。这将输出“orldway”
  • 尝试找到下一个匹配项。现在找不到匹配项
  • 输出字符串的其余部分而不进行任何处理。这意味着从位置 12 到字符串的末尾。这给出了子字符串“!”

这样,该过程将转换“Hello, world!”。到“Ellohay,orldway!”

希望这可以帮助

于 2012-12-10T01:29:02.747 回答