David Alan Black <dblack / candle.superlink.net> wrote: > On Wed, 20 Dec 2000, Stephen White wrote: > > > Hopefully this code dissection, rewriting and optimisation becomes a > > regular feature. Anyone else want to post the next amusing problem > > for us to work on? :) > > Just wait til the online cookbook is up and running :-) > > Meanwhile -- well, am I allowed to do the cowardly thing, and > pose this as a puzzle, without actually having done it yet? I did > do it in Perl, but am curious to see ideas for it in Ruby. > > Namely...... > > Input: 123456 > Output: "one-hundred twenty-three thousand four-hundred fifty-six" irb(main):001:0> load 'numreader.rb' true irb(main):002:0> NumReader::English.say(123456) "one hundred twenty-three thousand four hundred fifty-six" irb(main):003:0> NumReader::English.say(-42111000404 irb(main):004:1> ) "negative forty-two billion one hundred eleven million four hundred four" The problem is that originally I had a NumReader::French (module) and included that from NumReader::English (module), but I need to rethink how the constants would be set and overridden. #!/usr/local/bin/ruby module NumReader module English NEGATIVE = "negative" n = %w(zero one two three four five six seven eight nine ten eleven twelve thirteen) NUMBERS = n + (4 .. 9).collect {|num| n[num] + "teen"} TENS = [nil, nil] + %w(twenty thirty forty fifty sixty seventy eighty ninety) HUNDRED = "hundred" ORDERS_OF_3 = [""] + %w(thousand million billion trillion zillion quadrillion quintillion sextillion septillion octillion nonillion decillion undecillion duodecillion tredecillion quattuordecillion quindecillion sexdecillion septendecillion octodecillion novemdecillion vigintillion) def English.say(num) num = num.to_i if num < 0 num = -num negative = true else negative = false end return NUMBERS[0].dup if num.zero? answer = [] i = 0 while num > 0 x = num % 1000 if x.nonzero? f = less_than_1000(x) if i != 0 answer.push([f, ORDERS_OF_3[i]]) else answer.push(f) end end i += 1 num /= 1000 end answer.push(NEGATIVE) if negative answer.reverse.join(" ") end private def English.less_than_100(num) case num when 0 .. 19 NUMBERS[num] when 20 .. 99 units = num % 10 if units.nonzero? TENS[num / 10] + "-" + NUMBERS[units] else TENS[num / 10] end else raise ArgumentError, "number not between 0 and 99" end end def English.less_than_1000(num) hundreds = num / 100 if hundreds.nonzero? NUMBERS[hundreds] + " " + HUNDRED + ((num % 100).nonzero? ? " " + less_than_100(num % 100) : "") else less_than_100(num % 100) end end end end -- Brian Fundakowski Feldman \ FreeBSD: The Power to Serve! / green / FreeBSD.org `------------------------------'