3

ここでの私の課題は、再帰を使用して文を翻訳できる豚のラテン語翻訳者を作成することでした。ルールは次のとおりです。

  1. 英単語に母音がなければ、pigLatinWord は英単語 + "ay" になります。(10 個の母音があります: 'a'、'e'、'i'、'o'、および 'u' と、それに対応する大文字です。'y' は、この割り当ての目的では母音とは見なされません。つまり、 my が myay になる、Why が whyay になるなど)
  2. そうでなく、englishWord が母音で始まる場合、 pigLatinWord は、englishWord + "yay" になります。
  3. それ以外の場合 (englishWord に母音があり、母音で始まらない場合)、 pigLatinWord は end + start + "ay" であり、end と 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()

まず、Vowel の比較を単純化できます。1 つの方法は、正規表現を使用することです。別の方法は、セットを使用することです。

次のようなものがあるとします。

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

次に、母音チェックを長い if ステートメントから次のようなものに変更できます。

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

第 2 に、練習のために意図的に再帰的に 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;
}

これら 2 つの変更により、コードのほぼ半分が読みやすくなると思います。

于 2012-12-10T02:19:08.500 に答える
0

正規表現を使用して単語を一致させてみてください。正規表現 [a-zA-Z]+ は、文字の同時シーケンスに一致します。Javaで正規表現を使用する方法については、演習として残しますが、それほど難しくありません。

基本的に、文字列を取り、次の一致を見つけます。単語の最後の文字の位置を元の文字列に格納します。その単語を処理してから、次の一致を見つけます。次に、前の一致の最後の文字と現在の一致の最初の文字の間の部分文字列を取得し、何も処理せずにそのまま出力します。

例: 「Hello, world!」という文字列があるとします。

  • 最初の一致は、位置 0 から始まり、位置 4 (両端を含む) で終わる "Hello" になります。
  • それを処理して「エロヘイ」を出力
  • 7 位から 11 位で終わる "world" となる次の一致を検索します。
  • 前の一致の最後の文字と現在の一致の最初の文字の間の部分文字列を出力します。これは、位置 5 から位置 6 までを意味し、文字列 ", " が得られます。
  • 現在の一致を処理して出力します。これは「orldway」を出力します
  • 次の一致を見つけてみてください。一致するものは現在見つかりません
  • 何も処理せずに残りの文字列を出力します。これは、位置 12 からストリングの終わりまでを意味します。これにより、部分文字列「!」が得られます。

このようにして、プロセスは「Hello, world!」に変換されます。「エロヘイ、オルドウェイ!」

お役に立てれば

于 2012-12-10T01:29:02.747 に答える