5

I'm getting an error here with a simple if else chain, and I can't figure out what is going on. I started learning ruby the other day, I already know some java, and was just trying to re-write programs to learn ruby faster. I am trying to tally vowels and consonants. Anyways here is my code...

#!/usr/bin/ruby/
alphabet = 'abcdefghijklmnopqrstuvwxyz'

array = alphabet.chars.to_a
vowel = 0
cons = 0
puts array.at(1)
for i in 0...26 
    if array.at(i) == "a"
        vowel++   
    elsif array.at(i) == 'e'
        vowel++
        elsif array.at(i) == 'i'
        vowel++
    elsif array.at(i) == 'o'
        vowel++
    elsif array.at(i) == 'u'
        vowel++
    else
        cons++
    end#end if else chain
end#end for loop

puts 'Vowel: ' + vowel.to_s
puts 'Consonants: ' + cons.to_s

Here is the error I am getting:

C:/Users/Kelan/Documents/Programming/Ruby Files/Little Programs/Alphabet.rb:11: syntax error, unexpected keyword_elsif elsif array.at(i) == 'e' ^

C:/Users/Kelan/Documents/Programming/Ruby Files/Little Programs/Alphabet.rb:13: syntax error, unexpected keyword_elsif elsif array.at(i) == 'i' ^

C:/Users/Kelan/Documents/Programming/Ruby Files/Little Programs/Alphabet.rb:15: syntax error, unexpected keyword_elsif elsif array.at(i) == 'o' ^

C:/Users/Kelan/Documents/Programming/Ruby Files/Little Programs/Alphabet.rb:17: syntax error, unexpected keyword_elsif elsif array.at(i) == 'u' ^

C:/Users/Kelan/Documents/Programming/Ruby Files/Little Programs/Alphabet.rb:19: syntax error, unexpected keyword_else

C:/Users/Kelan/Documents/Programming/Ruby Files/Little Programs/Alphabet.rb:21: syntax error, unexpected keyword_end

C:/Users/Kelan/Documents/Programming/Ruby Files/Little Programs/Alphabet.rb:25: syntax error, unexpected $end, expecting keyword_end puts 'Consonants: ' + cons.to_s ^

[Finished in 0.203 seconds]

I'm sure it's just something silly, but I've been looking forever online for help and I have heard of your great community, so I thought I would try here,

Kelan

2

5 Answers 5

15

There is no ++ operator in Ruby. You should have used += 1 You may also want to learn about case statement:

alphabet = 'abcdefghijklmnopqrstuvwxyz'

26.times do |i|
    case alphabet[i]
        when 'a' then vowel += 1
        when 'e' then vowel += 1
        when 'i' then vowel += 1
        when 'o' then vowel += 1
        when 'u' then vowel += 1
        else cons += 1
    end#end case
end#end times

puts 'Vowel: ' + vowel.to_s
puts 'Consonants: ' + cons.to_s

Or, even better, use method count from class String, like this:

alphabet = 'abcdefghijklmnopqrstuvwxyz'
vowels = 'aeiou'
vowel_count = alphabet.count vowels
cons_count = alphabet.length - vowel_count
puts "Vowels: #{vowel_count}"
puts "Consonants: #{cons_count}"
Sign up to request clarification or add additional context in comments.

3 Comments

While trying to learn Ruby, I had the same issue and it was solved by changing "i++" into "i += 1". Thanks a lot!
You can also overload the case whens: when 'a', 'e', 'i', 'o', 'u' then vowel += 1
Thanks!! I got this too!! How can I know the error is in ++, I've been debugging it for hours!! Ruby compiler shouldn't point the error on elsif!! I've never use elsif and tot there is something wrong with my usage!!
5

Your problem is you're using the Java/PHP/C style increment operator. Ruby isn't down with that. You have to use foo += 1 instead.

How about I show you a more Ruby way of doing this though?

# use a range to define your alphabet
alphabet = ('a'..'z').entries  #=> ['a', 'b', 'c', ...]

# define vowels as members of an array. it's more flexible, which
# is great for things that change (what if you decide to use 'y'?)
vowels = %w{ a e i o u }  #=> ['a', 'e', 'i', 'o', 'u']

# keep counts all together in a hash, which I personally find cleaner
counts = { :vowels => 0, :consonants => 0 }

# even the `for` loops in ruby use the iterators, so you actually
# get better performance out of using the more user-friendly `.each`
alphabet.each do |letter|
  if vowels.include? letter
    counts[:vowels] += 1
  else 
    counts[:consonants] += 1
  end
end

puts "There were #{counts[:vowels]} vowels and #{counts[:consonants]} consonants."

2 Comments

I don't really understand what is going on with this :P (specifically the %w, and the counts parts) You are using Hashes though, right? I should probably look those up. Thank you so much for the help
%w is a way of defining an array quickly in ruby (see stackoverflow.com/questions/1274675/ruby-what-does-warray-mean), and the counts hash is iterated through during each alphabet letter, and depending on if the current letter in the loop is a vowel or a consonant, the appropriate hash key value is increased by 1 (counts[:vowels] += 1 during the first iteration (for 'A') for example). After the script finishes, count[:vowels] will be 5, and count[:consonants] will be 21.
3

I think rather than vowel++ and con++, you need to use vowel+=1 and con+=1.

Ruby does not have C-style pre/post incrementors.

1 Comment

That made all the difference!! Thanks!
2

Here is yet another way to write the demo:

puts("%d vowels & %d consonants" % ('a'..'z').inject([0,0]) do |m, e|
    m[/[aeiou]/.match(e) ? 0:1] += 1; m 
  end)

1 Comment

And this is exactly what you might do if you were writing a shell script. It's much better to write code where the intent is clear, though, rather than have to leave an inline comment to explain what is happening.
2
  • There is an easy way of constructing the set of alphabets, using Range.
  • Since you are using ruby, you should use internal iterators instead of the external ones. You will rarely see a for loop in a good program in ruby.
  • case construction is handy in this case. You can put multiple matching patterns into one, separated by comma.
  • There is no ++ or -- operators in ruby. Use += 1.
  • Use "#{ }" notation. It's much better and faster than using +. In fact, you can omit to_s if you use it.

I would go like this:

vowel = 0
cons = 0
('a'..'z').each do |c|
  case c
  when 'a', 'e', 'i', 'o', 'u'; vowel += 1
  else                          cons += 1
  end
end

puts "Vowel: #{vowel}"
puts "Consonants: #{cons}"

If I wanted a shorter one, I might go with this:

partition = ('a'..'z').group_by{|c| c =~ /[aeiou]/}
puts "Vowel: #{partition[0].length}"
puts "Consonants: #{partition[nil].length}"

1 Comment

I didn't know about the #{} notation, but I tried it out, and I love it!! So much easier. THANKS :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.