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

Amokrane Chentir
  • 29,907
  • 37
  • 114
  • 158
Kelan Poten-Coyle
  • 285
  • 1
  • 4
  • 10
  • +1 because the answers are interesting. Someday you'll understand all them. ;) – Sony Santos May 11 '11 at 00:41
  • This is a duplicate of [New to Ruby - `while` loop issues in IRB](http://StackOverflow.Com/q/5679808/), [problem with `if` and `else` code … in ruby](http://StackOverflow.Com/q/5859170/) and probably many others as well. – Jörg W Mittag May 11 '11 at 09:12

5 Answers5

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}"
maro
  • 1,506
  • 13
  • 21
  • While trying to learn Ruby, I had the same issue and it was solved by changing "i++" into "i += 1". Thanks a lot! – Bogdan Păun Nov 02 '11 at 22:35
  • 3
    You can also overload the case whens: `when 'a', 'e', 'i', 'o', 'u' then vowel += 1` – Alex V Jul 18 '15 at 08:32
  • 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!! – Zennichimaro Mar 07 '16 at 16:46
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."
coreyward
  • 77,547
  • 20
  • 137
  • 166
  • 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 – Kelan Poten-Coyle May 11 '11 at 00:23
  • 1
    `%w` is a way of defining an array quickly in ruby (see http://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`. – William May 11 '11 at 00:43
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.

buruzaemon
  • 3,847
  • 1
  • 23
  • 44
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)
DigitalRoss
  • 143,651
  • 25
  • 248
  • 329
  • 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. – coreyward May 11 '11 at 00:52
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}"
sawa
  • 165,429
  • 45
  • 277
  • 381