Program for changing a vowel to its index number in a string in Ruby

This is a program for changing a vowel to your index:

def vowel_2_index(string) return '' if string.nil? arr = string.enum_for(:scan,/[aeiou]/i).map {Regexp.last_match.begin(0) } s_arr = arr.map{|x| x+1 } arr.each_with_index{|x,y| string[x] = s_arr[y].to_s} string end 

Can someone tell me why he can’t get through Codewars - the best website in the world?

When I try to transfer a test file, for example:

 Test.assert_equals(vowel_2_index('Codewars is the best site in the world'),'C2d4w6rs 10s th15 b18st s23t25 27n th32 w35rld') 

something like:

 "C2d4w6rs 10s t15e18bes232527ite32i35 the world" 
+7
ruby
source share
3 answers

As you can see, when you start replacing vowels with your positions, it works when the position is a single digit (i.e. 1 or 5 ), but when the position becomes 2-digit ( 10 or more), all found indices begin to shift , and arr information is no longer true.

I would suggest using gsub , since you want to do a global search and replace, you almost did it right:

 str = 'Codewars is the best site in the world' str.gsub(/[aeiou]/) { |item| Regexp.last_match.begin(0) + 1 } # => "C2d4w6rs 10s th15 b18st s23t25 27n th32 w35rld" 
+3
source share

All of the following apply to:

 str = 'Codewars is the best site in the world' 

Regarding the problem you are facing, let me break it down:

 enum = str.enum_for(:scan,/[aeiou]/i) #=> #<Enumerator: "Codewars is the best site in the world":scan(/[aeiou]/i)> 

To see the elements of this enumerator passed to map in its block, we can convert it to an array:

 enum.to_a #=> ["o", "e", "a", "i", "e", "e", "i", "e", "i", "e", "o"] 

Continuation:

 arr = enum.map {Regexp.last_match.begin(0) } #=> [1, 3, 5, 9, 14, 17, 22, 24, 26, 31, 34] s_arr = arr.map{|x| x+1 } #=> [2, 4, 6, 10, 15, 18, 23, 25, 27, 32, 35] arr.each_with_index{|x,y| string[x] = s_arr[y].to_s} #=> [1, 3, 5, 9, 14, 17, 22, 24, 26, 31, 34] str #=> "C2d4w6rs 10s t15e18bes232527ite32i35 the world" 

The method should return:

  #=> "C2d4w6rs 10s th15 b18st s23t25 27n th32 w35rld" 

So you see that the discrepancy starts with 'h' at 'the' , which is at index 13 . The problem occurs when the 10 of arr element is passed to the block. At this stage

 str #=> "C2d4w6rs is the best site in the world" 

For block variables, the value is set:

 x,y = [10, 3] x #=> 10 y #=> 3 

therefore block calculation:

 str[10] = s_arr[3].to_s #=> = "10" 

and now:

 str #=> "C2d4w6rs 10s the best site in the world" 

As you can see, the indices of all the letters following 10 increased by one. This was not a problem before, because the first three characters were replaced with a single digit. The remaining elements arr and s_arr now disabled by one, and after the next replacement, the indices of the remaining ones will be disabled by two, etc.

  ********* 

I would use one of the following approaches.

 VOWELS = 'aeiouAEIOU' 

# one

 pos = '0' str.gsub(/./) { |c| pos.next!; VOWELS.include?(c) ? pos : c } #=> "C2d4w6rs 10s th15 b18st s23t25 27n th32 w35rld" 

# 2

 str.each_char.with_index(1).map { |c,i| VOWELS.include?(c) ? i.to_s : c }.join #=> "C2d4w6rs 10s th15 b18st s23t25 27n th32 w35rld" 

# 3

 str.size.times.map { |i| VOWELS.include?(str[i]) ? (i+1).to_s : str[i] }.join #=> "C2d4w6rs 10s th15 b18st s23t25 27n th32 w35rld" 

I have a slight preference for # 1, because it works with the string directly, unlike creating an array, and then attaches its elements back to the string. Moreover, I think he reads best.

+3
source share
 str = 'Codewars is the best site in the world' 

You can split the string into an array of characters and compare each value with regex.Am using with_index (1), because the array is based on zero.

 str.split(//).map.with_index(1){|k,v| /[aeiou]/=~k ? v : k}.join 

What are the results:

 #=> 'C2d4w6rs 10s th15 b18st s23t25 27n th32 w35rld' 
+1
source share

All Articles