Pig-Latin method translation

 ̄綄美尐妖づ 提交于 2019-12-07 21:00:31

问题


Trying to write Method in ruby that will translate a string in pig-latin , the rule : Rule 1: If a word begins with a vowel sound, add an "ay" sound to the end of the word.

Rule 2: If a word begins with a consonant sound, move it to the end of the word, and then add an "ay" sound to the end of the word and also when the word begins with 2 consonants , move both to the end of the word and add an "ay"

As a newbie , my prob is the second rule , when the word begin with only one consonant it work , but for more than one , I have trouble to make it work ,Can somebody look at the code and let me know how i can code that differently and probably what is my mistake , probably the code need refactoring. Thanks , so far i come up with this code :

def translate (str)
  str1="aeiou"
  str2=(/\A[aeiou]/)
  vowel = str1.scan(/\w/)
  alpha =('a'..'z').to_a
  con = (alpha - vowel).join
  word = str.scan(/\w/)  
  if  #first rule 
    str =~ str2
    str + "ay" 
  elsif # second rule 
    str != str2 
    s = str.slice!(/^./)
    str + s + "ay"
  elsif 
    word[0.1]=~(/\A[con]/)
    s = str.slice!(/^../)
    str + s + "ay"
  else
    word[0..2]=~(/\A[con]/) 
    s = str.slice!(/^.../)
    str + s + "ay" 
  end
end

translate("apple") should == "appleay"

translate("cherry") should == "errychay"

translate("three") should == "eethray"


回答1:


okay this is an epic pig latin translator that I'm sure could use a bit of refactoring, but passes the tests

def translate(sent)
    sent = sent.downcase
    vowels = ['a', 'e', 'i', 'o', 'u']
    words = sent.split(' ')
    result = []

words.each_with_index do |word, i|
    translation = ''
    qu = false
    if vowels.include? word[0]
        translation = word + 'ay'
        result.push(translation)
    else
        word = word.split('')
        count = 0
        word.each_with_index do |char, index|
            if vowels.include? char
                # handle words that start with 'qu'
                if char == 'u' and translation[-1] == 'q'
                    qu = true
                    translation = words[i][count + 1..words[i].length] + translation + 'uay'
                    result.push(translation)
                    next
                end
                break
            else
                # handle words with 'qu' in middle
                if char == 'q' and word[i+1] == 'u'
                    qu = true
                    translation = words[i][count + 2..words[i].length] + 'quay'
                    result.push(translation)
                    next
                else
                    translation += char
                end
                count += 1
            end
        end
        # translation of consonant words without qu
        if not qu
            translation = words[i][count..words[i].length] + translation + 'ay'
            result.push(translation)
        end
    end

end
result.join(' ')
end

So this will give the following:

puts translate('apple')                # "appleay"
puts translate("quiet")                # "ietquay"
puts translate("square")               # "aresquay"
puts translate("the quick brown fox")  # "ethay ickquay ownbray oxfay"



回答2:


No need for all those fancy regexes. Keep it simple.

def translate str
  alpha = ('a'..'z').to_a
  vowels = %w[a e i o u]
  consonants = alpha - vowels

  if vowels.include?(str[0])
    str + 'ay'
  elsif consonants.include?(str[0]) && consonants.include?(str[1])
    str[2..-1] + str[0..1] + 'ay'
  elsif consonants.include?(str[0])
    str[1..-1] + str[0] + 'ay'
  else
    str # return unchanged
  end
end

translate 'apple' # => "appleay"
translate 'cherry' # => "errychay"
translate 'dog' # => "ogday"



回答3:


This will handle multiple words, punctuation, and words like 'queer' = 'eerquay' and 'school' = 'oolschay'.

def translate (sent)
    vowels = %w{a e i o u}
    sent.gsub(/(\A|\s)\w+/) do |str|
            str.strip!
        while not vowels.include? str[0] or (str[0] == 'u' and str[-1] == 'q')
            str += str[0]
            str = str[1..-1]
        end
        str  = ' ' + str + 'ay'
    end.strip
end



回答4:


def translate(sentence)
  sentence.split(" ").map do |word|
    word = word.gsub("qu", " ")
    word.gsub!(/^([^aeiou]*)(.*)/,'\2\1ay')
    word = word.gsub(" ", "qu")
  end
end

That was fun! I don't like the hack for qu, but I couldn't find a nice way to do that.




回答5:


So for this pig latin clearly I skipped and\an\in and singular things like a\I etc. I know that wasn't the main question but you can just leave out that logic if it's not for your use case. Also this goes for triple consonants if you want to keep it with one or two consonants then change the expression from {1,3} to {1,2}

All pig latin is similar so just alter for your use case. This is a good opportunity to use MatchData objects. Also vowel?(first_letter=word[0].downcase) is a style choice made to be more literate so I don't have to remember that word[0] is the first letter.

My answer is originally based off of Sergio Tulentsev's answer in this thread.


  def to_pig_latin(sentence)
    sentence.gsub('.','').split(' ').collect do |word|
      translate word
    end.compact.join(' ')
  end

  def translate(word)
    if word.length > 1
      if word == 'and' || word == 'an' || word == 'in'
        word
      elsif capture = consonant_expression.match(word)
        capture.post_match.to_s + capture.to_s + 'ay'
      elsif vowel?(first_letter=word[0].downcase)
        word + 'ay'
      elsif vowel?(last_letter=word[-1].downcase)
        move_last_letter(word) + 'ay'
      end
    else
      word
    end
  end

  # Move last letter to beginning of word
  def move_last_letter(word)
    word[-1] +  word[0..-2]
  end

  private
  def consonant_expression
    # at the beginning of a String
    # capture anything not a vowel (consonants)
    # capture 1, 2 or 3 occurences
    # ignore case and whitespace
    /^ [^aeiou] {1,3}/ix
  end

  def vowel?(letter)
    vowels.include?(letter)
  end

  def vowels
    %w[a e i o u]
  end

Also just for the heck of it I'll include my dump from a pry session so you all can see how to use MatchData. MINSWAN. It's stuff like this that makes ruby great.


pry > def consonant_expression
pry *   /^ [^aeiou] {1,3}/ix
pry * end    
=> :consonant_expression
pry > consonant_expression.match('Stream')
=> #<MatchData "Str">
pry > capture = _
=> #<MatchData "Str">
pry > ls capture
MatchData#methods:
  ==  begin     end   hash     length  offset      pre_match     regexp  string  to_s     
  []  captures  eql?  inspect  names   post_match  pretty_print  size    to_a    values_at
pry >
pry > capture.post_match
=> "eam"
pry > capture
=> #<MatchData "Str">
pry > capture.to_s
=> "Str"
pry > capture.post_match.to_s
=> "eam"
pry > capture.post_match.to_s + capture.to_s + 'ay'
=> "eamStray"
pry >



回答6:


If I understood your question correctly, you can just directly check if a character is a vowel or consonant and then use array ranges to get the part of the string you want.

vowels = ['a', 'e', 'i', 'o', 'u']
consonants = ('a'..'z').to_a - vowels
return str + "ay" if vowels.include?(str[0])
if consonants.include?(str[0])
   return str[2..-1] + str[0..1] + "ay" if consonants.include?(str[1])
   return str[1..-1] + str[0] + "ay"
end
str



回答7:


Here's a solution that handles the "qu" phoneme as well as other irregular characters. Had a little trouble putting the individual words back into a string with the proper spacing. Would appreciate any feedback!

def translate(str)
vowels = ["a", "e", "i", "o", "u"]
new_word = ""
str.split.each do |word|
    vowel_idx = 0

    if vowels.include? word[0]
        vowel_idx = 0
    elsif word.include? "qu"
        until word[vowel_idx-2]+word[vowel_idx-1] == "qu"
            vowel_idx += 1
        end
    else
        until vowels.include? word[vowel_idx]
        vowel_idx += 1
        end
    end

    idx_right = vowel_idx
    while idx_right < word.length
        new_word += word[idx_right]
        idx_right += 1
    end

    idx_left = 0
    while idx_left < vowel_idx
        new_word += word[idx_left]
        idx_left += 1
    end
    new_word += "ay "
end

new_word.chomp(" ")
end



回答8:


I done gone did one too

    def translate(string)
  vowels = %w{a e i o u}
  phrase = string.split(" ")
  phrase.map! do |word|
    letters = word.split("")
    find_vowel = letters.index do |letter|
      vowels.include?(letter)
    end
    #turn "square" into "aresquay"
    if letters[find_vowel] == "u"
      find_vowel += 1
    end
    letters.rotate!(find_vowel)
    letters.push("ay")
    letters.join

   end

return phrase.join(" ")
end



回答9:


def piglatinize(word)
    vowels = %w{a e i o u}
    word.each_char do |chr|
    index = word.index(chr)
    if index != 0 && vowels.include?(chr.downcase)
      consonants = word.slice!(0..index-1)
      return word + consonants + "ay"
    elsif index == 0 && vowels.include?(chr.downcase)
      return word + "ay"
    end
  end
end

def to_pig_latin(sentence)
  sentence.split(" ").collect { |word| piglatinize(word) }.join(" ")
end



回答10:


This seems to handle all that I've thrown at it including the 'qu' phoneme rule...

def translate str
  letters = ('a'..'z').to_a

  vowels = %w[a e i o u]

  consonants = letters - vowels

  str2 = str.gsub(/\w+/) do|word|
      if vowels.include?(word.downcase[0])
        word+'ay'
      elsif (word.include? 'qu')
        idx = word.index(/[aeio]/)
        word = word[idx, word.length-idx] + word[0,idx]+ 'ay'
      else
        idx = word.index(/[aeiou]/)
        word = word[idx, word.length-idx] + word[0,idx]+'ay'
      end
  end
end

I'm grabbing the words with the 'qu' phoneme and then checking all the other vowels [excluding u].

Then I split the word by the index of the first vowel (or vowel without 'u' for the 'qu' cases) and dropping the word part before that index to the back of the word. And adding 'ay' ftw.




回答11:


Many of the examples here are fairly long. Here's some relatively short code I came up with. It handles all cases including the "qu" problem! Feedback always appreciated (I'm pretty new to coding).

$vowels = "aeiou"

#First, I define a method that handle's a word starting with a consonant
def consonant(s)
  n = 0
     while n < s.length
        if $vowels.include?(s[n]) && s[n-1..n] != "qu"
           return "#{s[n..-1]}#{s[0..n-1]}ay"
        else
           n += 1
        end
     end
  end
#Then, I write the main translate method that decides how to approach the word. 
def translate(s)
    s.split.map{ |s| $vowels.include?(s[0]) ? "#{s}ay" : consonant(s) }.join(" ")
end


来源:https://stackoverflow.com/questions/13498688/pig-latin-method-translation

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!