Matthias Reitinger wrote:
Michael Morin wrote:
I did something slightly different, which works on multiple levels, not
just two. For example, it can go all the way up to 999 without any
extra code.
[...]
Unfortunately your implemention fails with multiples of 100.
Being the lazy guy I just used the excellent [Ruby Lingustics Framework][1] to deduce English numerals. The following program produces the [full 99 Bottles of Beer lyrics][2] with numerals:
---
require 'Linguistics'
Linguistics::use(:en)
class Fixnum
def bottles
case self
when 0: "no more bottles"
when 1: "one bottle"
else "#{self.en.numwords} bottles"
end
end
end
99.downto(0) do |n|
puts "#{n.bottles.capitalize} of beer on the wall, #{n.bottles} of beer."
if n > 0
puts "Take one down and pass it around, #{(n-1).bottles} of beer on the wall."
puts
else
puts "Go to the store and buy some more, #{99.bottles} of beer on the wall."
end
end
---
Regards,
Matthias
[1]: dev(E)iate
[2]: 99 Bottles of Beer | The lyrics to the song 99 Bottles of Beer
So it does. Just drop the "and" from the strings and it's still technically correct. Things could be better if I had special cases for things like that, but I didn't want to complicate the code.
Nothing lazy about using libraries. Linguistics takes a different approach though. They have three different procs stored in an array for the number of digits in the number.
# A collection of functions for transforming digits into word
# phrases. Indexed by the number of digits being transformed; e.g.,
# <tt>NumberToWordsFunctions[2]</tt> is the function for transforming
# double-digit numbers.
NumberToWordsFunctions = [
proc {|*args| raise "No digits (#{args.inspect})"},
# Single-digits
proc {|zero,x|
(x.nonzero? ? to_units(x) : "#{zero} ")
},
# Double-digits
proc {|zero,x,y|
if x.nonzero?
to_tens( x, y )
elsif y.nonzero?
"#{zero} " + NumberToWordsFunctions[1].call( zero, y )
else
([zero] * 2).join(" ")
end
},
# Triple-digits
proc {|zero,x,y,z|
NumberToWordsFunctions[1].call(zero,x) +
NumberToWordsFunctions[2].call(zero,y,z)
}
]
That's quite clever. Each proc calls the previous proc. Mine relied on recursion and subtraction instead of separating the digits. Doing it this way gives you an easy way to implement the special cases.
···
--
Michael Morin
Guide to Ruby
Become an About.com Guide: beaguide.about.com
About.com is part of the New York Times Company