Created
January 21, 2010 00:29
-
-
Save Mikoangelo/282465 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
NUMBERS = { | |
:a => 1, | |
:one => 1, | |
:two => 2, | |
:three => 3, | |
:four => 4, | |
:five => 5, | |
:six => 6, | |
:seven => 7, | |
:eight => 8, | |
:nine => 9, | |
:ten => 10, | |
:eleven => 11, | |
:twelve => 12, | |
:thirteen => 13, | |
:fourteen => 14, | |
:fifteen => 15, | |
:sixteen => 16, | |
:seventeen => 17, | |
:eighteen => 18, | |
:nineteen => 19, | |
:twenty => 20, | |
:thirty => 30, | |
:forty => 40, | |
:fifty => 50, | |
:sixty => 60, | |
:seventy => 70, | |
:eighty => 80, | |
:ninety => 90, | |
:hundred => 100, | |
:thousand => 1000, | |
:million => 1000000, | |
:billion => 1000000000 | |
} | |
# Decimas are stuff like million, hundred, thousand. | |
# Also hundred thousand and hundred million. | |
DECIMAS = [3,6,9].map { |n| 10 ** n } | |
DECIMAS.concat [100] + DECIMAS.map { |n| n * 100 } | |
def DECIMAS.highest num | |
select{ |d| d <= num }.max | |
end | |
NUMBERS.each do |meth, val| | |
# Kernel.send :define_method instead of Kernel.define_method because it's | |
# private. Truth be told, the |after| should be |*after| (and after=after[0] | |
# afterwards) to avoid a warning about arity. The whole powernesting-of- | |
# single-argument-methods thing kinda ruins the concept, though ;) | |
Kernel.send :define_method, meth do |after = nil| | |
ret = if after | |
after, is_decima = after if Array === after # See the `ret = [ret, ...] ...` line | |
highest_decima = DECIMAS.highest after | |
# if highest_decima < val, we are just adding digits (i.e. a "two-digit" method name) | |
if highest_decima.nil? or highest_decima < val | |
val + after | |
else | |
# This comment is too small to hold my elegant explanation for this. | |
val * highest_decima + after - ((val < 10 or is_decima) ? highest_decima : 0) | |
end | |
else | |
val | |
end | |
# Here's a little hack. Since there's no way of differentiating `million` | |
# and `one million` (as in `twenty [one] million`), `million` returns the | |
# value in an array just to distinguish it. It doesn't break the use since | |
# decimas are never supposed to be used at the start of a number nesting | |
# (use `one` or `a`). The :is_decima isn't needed per se, but hey; | |
# shits'n'giggles! | |
ret = [ret, :is_decima] if DECIMAS.include? val | |
ret | |
end | |
end | |
nineteen billion eight hundred six million five hundred forty three thousand two hundred ten # => 19806543210 | |
a thousand three # => 1003 | |
twenty one thousand three # => 21003 | |
twenty(thousand(three)) # => 20003 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment