Home > Software engineering >  I could not get the intended output from the written code
I could not get the intended output from the written code

Time:09-21

I have to write a method called consonant_cancel that takes in a sentence and returns a new sentence where every word begins with it's first vowel. The intended output is for given test functions are puts consonant_cancel("down the rabbit hole") #=> "own e abbit ole" puts consonant_cancel("writing code is challenging") #=> "iting ode is allenging"
but I am getting "own e abbit it ole e" "iting ing ode e is allenging enging ing" with this code

def consonant_cancel(sentence)
  arr = []
  vowels = 'aeiou'
  words = sentence.split
  words.each do |word|
      word.each_char.with_index do |char, i|
        if vowels.include?(char)
           arr << word[i..-1]
        end
      end
  end
 return arr.join(' ')
end

puts consonant_cancel("down the rabbit hole") #=> "own e abbit ole"
puts consonant_cancel("writing code is challenging") #=> "iting ode is allenging"

Can you guys help me to debug it.

CodePudding user response:

If we adding in a puts to see what's happening in your loop:

def consonant_cancel(sentence)
    arr = []
    vowels = 'aeiou'
    words = sentence.split
    words.each do |word|
        word.each_char.with_index do |char, i|
            if vowels.include?(char)
                puts char
                arr << word[i..-1]
            end
        end
    end
    return arr.join(' ')
end

Then running consonant_cancel "hello world" we see:

irb(main):044:0> consonant_cancel "hello world"
e
o
o
=> "ello o orld"
irb(main):045:0>

You'll see the same issue with any word with multiple consonants, because of the way you're looping over the characters in a word and checking for consonants.

An easier way to accomplish this would be with regular expressions.

words.split.map { |w| w.sub(/^[^aeiou]*/i, "") }.join(' ')

CodePudding user response:

word.each_char.with_index

This loop iterates all chars (and vowels) of the word. break it after the first vowel found, so it does not repeat the side-effects for subsequent vowels of this word.


As an alternative, here's another regex-based solution

def consonant_cancel(sentence)
  sentence.scan(/\b[^aeiou]*(. ?)\b/i).join(" ")
end

CodePudding user response:

You can use String#gsub with a regular expression. There is no need to break the string into pieces for processing and subsequent recombining.

def consonant_cancel(str)
  str.gsub(/(?<![a-z])[a-z&&[^aeiou]] /i,'')
end
consonant_cancel("down the rabbit hole")
  #=> "own e abbit ole"
consonant_cancel("writing code is challenging")
  #=> "iting ode is allenging"

See the section "Character Classes" in the doc for Regexp for an explanation of the && operator.

We can write the regular expression in free-spacing mode1 to make it self-documenting.

/
(?<!              # Begin a negative lookbehind
  [a-z]           # Match a lowercase letter
)                 # End negative lookbehind
[a-z&&[^aeiou]]   # Match one or more lowercase letters other than vowels
/ix               # Invoke case-indifference and free-spacing modes 

The negative lookahead ensures that no string of letters immediately preceded by a letter is matched. The line

[a-z&&[^aeiou]] 

can alternatively be written

[b-df-hj-np-tv-z] 

1. See the section "Free-Spacing Mode and Comments" in the doc for Regexp.

CodePudding user response:

You don't have to write such a big coding. You could write the following code to accomplish what you have wanted.

Input

a="down the rabbit hole"

Code

p a.split
   .map { |x| x.sub(/[^aeiou]/, "") }
   .join(" ")

Output

"own he abbit ole"
  •  Tags:  
  • ruby
  • Related