99 Bottles of Beer (Ruby)
From LiteratePrograms
99 Bottles of Beer is a very long song that goes like:
99 bottles of beer on the wall, 99 bottles of beer. Take one down and pass it around, 98 bottles of beer on the wall.
98 bottles of beer on the wall, 98 bottles of beer. Take one down and pass it around, 97 bottles of beer on the wall.
97 bottles of beer on the wall, 97 bottles of beer. Take one down and pass it around, 96 bottles of beer on the wall.
The lyrics are repeated until the final 3 verses:
2 bottles of beer on the wall, 2 bottles of beer. Take one down and pass it around, 1 bottle of beer on the wall.
1 bottle of beer on the wall, 1 bottle of beer. Take one down and pass it around, no more bottles of beer on the wall.
No more bottles of beer on the wall, no more bottles of beer. Go to the store and buy some more, 99 bottles of beer on the wall.
This song conforms with grammar and shifts to singular "bottle" instead of "bottles". This implementation thus has to reflect that.
Contents |
Final Verses
First, let's implement the final 3 verses, because they're special, and to get a feel for ruby's print methods
Using puts
We could just use puts, which is the equivalent of System.out.println; it prints out a string and prints a newline.
<<end lyrics puts>>= puts "2 bottles of beer on the wall, 2 bottles of beer." puts "Take one down and pass it around, 1 bottles of beer on the wall." puts "" puts "1 bottle of beer on the wall, 1 bottle of beer." puts "Take one down and pass it around, no more bottles of beer on the wall." puts "" puts "No more bottles of beer on the wall, no more bottles of beer." puts "Go to the store and buy some more, 99 bottles of beer on the wall."
Using here documents
Or, better yet, we could print the lyrics in a here document:
<<end lyrics here document>>= puts <<END_LYRICS 2 bottles of beer on the wall, 2 bottles of beer. Take one down and pass it around, 1 bottle of beer on the wall. 1 bottle of beer on the wall, 1 bottle of beer. Take one down and pass it around, no more bottles of beer on the wall. No more bottles of beer on the wall, no more bottles of beer. Go to the store and buy some more, 99 bottles of beer on the wall. END_LYRICS
The advantage of this is that the lyrics are unmodified; code is only around the lines.
Lyrics Implementation
These are the implementations of the other lyrics, that loop down from 99 to 3 bottles on the wall.
Using downto
Ruby is fully OOP, meaning that even numbers have methods. And one of those methods happens to match this program's needs: downto. It counts down from the number object that is called to the number object given (inclusive):
<<downto function call>>= 99.downto(3) do |number| downto block end
Here the downto method will call the block with variable "number" as integers from 99 to 3, inclusive. The block will then print out the lyrics:
<<downto block>>= puts <<LYRICS #{number} bottles of beer on the wall, #{number} bottles of beer. Take one down and pass it around, #{number - 1} bottles of beer on the wall. LYRICS
Again, a here document is used. In Ruby's here documents, #{} can evaluate an expression.
The full program
<<99beers.rb>>= downto function call end lyrics here document