Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
menu search
person
Welcome To Ask or Share your Answers For Others

Categories

I'm trying to solve the problem of translating to pig latin using PHP. I'm stuck, because Y can be both a vowel or a consonant depending on context. If Y is on the beginning of the word, is considered a consonant, if it is on the middle is considered a vowel.

For example "yellow style" becomes "ellowyay ylestay". With the rules being: "Words that start with a vowel (A, E, I, O, U) simply have "WAY" appended to the end of the word. Words that start with a consonant have all consonant letters up to the first vowel moved to the end of the word (as opposed to just the first consonant letter), and "AY" is appended. ('Y' is counted as a vowel in this context)"

My code is as following:

class Config{

public static $vowels = 'aeiou';
public static $vowelTermination = "way";
public static $consonants = 'b-df-hj-np-tv-z';
}

class Piglatin
{

public function convert($input)
{
    $return = "";
    $wordArray = explode(" ", $input);

    foreach($wordArray as $word){
        $return .= $this->translate($word);
        $return .= " ";
    }

    return rtrim($return);
}

public function translate($input)
{
    $translation = "";

    if(!empty($input)){

        if(is_numeric($input)){
            return $input;
        }

        if($this->startVowel($input)){
            $input = $input . Config::$vowelTermination;
            return $input;
        }

        if($this->startConsonant($input) && strlen($input)===1 ){
            return $input.'ay';
        }

        if($this->startConsonant($input)){
            $input = preg_replace('/^([b-df-hj-np-tv-xz]*)([aeiouy].*)$/', "$2$1ay", $input);
            return $input;
        }
    }

    return $translation;
}

public function startVowel($input)
{
    $regex = '/^['.Config::$vowels.']/i';

    if(preg_match($regex, $input)){
        return true;
    }
    return false;
}

public function startConsonant($input)
{
    $regex = '/^['.Config::$consonants.']/i';

    if(preg_match($regex, $input)){
        return true;
    }
    return false;
}
}

Which given the input "yellow style" produces "yelloway ylestay" which is close to the expected result, but not quite.

Any idea on how to solve this?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
215 views
Welcome To Ask or Share your Answers For Others

1 Answer

Seems to me you've got 3 separate conditions.
This regex uses a branch reset (parallel groups) with those conditions.
Each condition must be enforced and that's what this does.

Note that it does not count for boundary's, but I would use a whitespace boundary if you need one. (?<!S)(?: regex )(?!S)
Also, you could add other characters to the [a-z] class or [b-df-hj-np-tv-xz]
but not to the vowels class [aeiouy] or the [y] class.

Basically it is
Find (?i)(?|([aeiou][a-z]*)()|([b-df-hj-np-tv-xz]+)([aeiouy][a-z]*)|([y]+[b-df-hj-np-tv-xz]*)([aeiouy][a-z]*))
Replace $2$1ay

Expanded

 (?i)                              # Modifier - case independent
 (?|                               # Branch Reset
      ( [aeiou] [a-z]* )                # (1), Condition: starts with a vowel
      ( )                               # (2)
   |  
      ( [b-df-hj-np-tv-xz]+ )           # (1), Condition: starts with a non-Y consonant
      ( [aeiouy] [a-z]* )               # (2), and Y as vowel
   |  
      ( [y]+ [b-df-hj-np-tv-xz]* )      # (1), Condition: starts with a Y consonant
      ( [aeiouy] [a-z]* )               # (2), and Y as vowel
 )

Sample input yellow style atak yyerto yystay start
Sample output ellowyay ylestay atakay ertoyyay ayyystay artstay


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share

548k questions

547k answers

4 comments

86.3k users

...