99 Bottles of Beer (Ruby)

From LiteratePrograms

Jump to: navigation, search
Other implementations: Alice ML | Erlang | Haskell | Inform 7 | Java | OCaml | Perl | Python | Ruby

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
Views