Language Ruby
(Using continuations, singleton classes)
Date: | 09/15/06 |
Author: | Victor Borja |
URL: | n/a |
Comments: | 9 |
Info: | http://www.ruby-lang.org |
Score: | (3.41 in 316 votes) |
# 99 Bottles of beer, in Ruby # By Victor Borja, Sep 14, 2006 # This one shows my favorite Ruby features: # continuations, open classes, singleton classes, blocks and being funny! class Integer # The bottles def drink; self - 1; end end class << song = nil attr_accessor :wall def bottles (@bottles.zero? ? "no more" : @bottles).to_s << " bottle" << ("s" unless @bottles == 1).to_s end def of(bottles) @bottles = bottles (class << self; self; end).module_eval do define_method(:buy) { bottles } end self end def sing(&step) puts "#{bottles.capitalize} of beer on the wall, #{bottles} of beer." if @bottles.zero? print "Go to the store buy some more, " step = method :buy else print "Take one down and pass it around, " end @bottles = step[@bottles] puts "#{bottles} of beer on the wall." puts "" or wall.call unless step.kind_of? Method end end callcc { |song.wall| song.of(99) }.sing { |beer| beer.drink }
Download Source | Write Comment
Alternative Versions
Version | Author | Date | Comments | Rate |
---|---|---|---|---|
object-oriented version | Mike Gertz | 04/20/05 | 2 | |
minimal version | Anonymous | 05/18/05 | 3 | |
shows inheritance, iterators, yield, etc | Kian Wright | 06/10/05 | 0 | |
alternative version | Greg T. | 05/18/05 | 10 | |
In words | Daniel Straight | 07/10/06 | 1 | |
wall-based OO version | Kevin Baird | 07/07/05 | 2 | |
monkeypatch and anonymous procs | J. B. Rainsberger | 04/04/07 | 0 | |
Readably re-opening Integer, teetotaller | Eric Budd | 01/06/08 | 0 |
Download Source | Write Comment
Add Comment
Please provide a value for the fields Name,
Comment and Security Code.
This is a gravatar-friendly website.
E-mail addresses will never be shown.
Enter your e-mail address to use your gravatar.
Please don't post large portions of code here! Use the form to submit new examples or updates instead!
Comments
Pepe said on 01/19/07 20:33:48
Yeah men, keep doing the good work. How Deep is this men, it moves me to tears.
rafa said on 01/25/07 18:49:34
I really like this over the other versions, I think it shows more the ruby way.
The part I liked the more was the last line, especially "}.sing {", that makes use of a not commonly known behavior of ruby continuations. When the continuation is called the first time, the #sing message is sent to the value resulting from the body of callcc, however subsequent calls to the continuation (by means of wall.call) always send the #sing message to the nil object. I proved this by changing "song = nil" to "song = Object.new", now I understand why Victor used nil as the song, a very cleaver choice !.
Hesenrre said on 01/26/07 02:05:15
Jejejejeje, like your coding friend :D, ruby rules!!!!
Namagem said on 12/31/08 16:33:56
It's absolutely possible to make a slightly less polished version in only 4 lines.
I actually think I'll submit it.
similar to python one said on 02/19/09 16:23:05
A friend said the python version looked cleaner. So I wrote that one in Ruby.
(1..99).to_a.reverse.each do |bottle|
if bottle > 1
puts "#{bottle} bottles of beer on the wall, #{bottle} bottles of beer."
suffix = bottle > 2 ? "#{bottle -1} bottles of beer on the wall" : "1 bottle of beer on the wall"
elsif bottle == 1
puts "1 bottle of beer on the wall, 1 bottle of beer."
suffix = "no more beer on the wall!"
end
puts "Take one down, pass it around #{suffix}"
puts "--"
end
jeff said on 03/24/09 05:53:56
As noted by the first comment, this entry stands out not for being the shortest, but because it shows some neat language features, and how they are combined in the last line, that looks almost like a DSL. I think many rubyists would agree, in that ruby makes programming so easy, that the focus is more in expression and artistic value.
Nice codes.
Billy said on 12/16/09 02:33:42
I really like this one!
num_bot = proc { |n| "#{n} bottle#{n == 1 ? '' : 's'}" }
99.downto(2) do |num|
puts "#{num_bot[num]} of beer on the wall, #{num_bot[num]} of beer!"
puts "Take one down, pass it around, #{num_bot[num-1]} of beer on the wall!"
end
puts "#{num_bot[1]} of beer on the wall, #{num_bot[1]} of beer!"
puts "Take one down, pass it around, no more bottles of beer on the wall!"
regeya said on 04/12/10 21:54:54
#Not very ruby-ish, but it works
bob = proc { |num| "#{num == 0 ? "no more" : num} bottle#{"s" if num != 1} of beer" }
bob_on_wall = proc { |num| "#{bob[num]} on the wall" }
99.downto(1) {|f| print "#{bob_on_wall[f]}, #{bob[f]}!\nTake one down, pass it around, #{bob_on_wall[f-1]}!\n\n" }
puts <<END
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
D. Rose said on 04/27/10 19:06:58
# 99 Bottles of Beer in 258 chars for ruby 1.9 and exactly the SAME as http://99-bottles-of-beer.net/lyrics.html
# I prefer clear ruby code thought
def b i,w=nil;"#{i==0&&"no more"||i} bottle#{"s"if i!=1} of beer#{" on the wall"if w}"end
99.downto(1){|i|puts"#{b i,1}, #{b i}.\nTake one down, pass it around, #{b i-1,1}.\n\n"}
puts b(0,1).capitalize+", #{b 0}.\nGo to the store and buy some more, #{b 99,1}."