Skip to content

Instantly share code, notes, and snippets.

@k00ka
Created May 8, 2012 21:37
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save k00ka/2639531 to your computer and use it in GitHub Desktop.
Save k00ka/2639531 to your computer and use it in GitHub Desktop.
Fixnum/Bignum to_en function - convert numbers to English. Useful for testing your Euler 17 solution (hint, hint)
# Fixnum and Bignum :to_en function
# For Ruby Hack Night, May 7, 2012
# By David Andrews, Ryatta Group
class Unit
UNITS = [ "thousand", "million", "billion", "trillion", "quadrillion", "quintillion", "sextillion", "septillion", "octillion", "nonillion", "decillion", "undecillion", "duodecillion", "tredecillion", "quattuordecillion", "quindecillion", "sexdecillion", "septendecillion", "octodecillion", "novemdecillion", "vigintillion" ]
HUNDRED = "hundred and"
def self.how_big(zeroes)
return HUNDRED if zeroes == 2
return "" if zeroes < 3 || zeroes % 3 > 0 # if it ain't hundred, or a power of three, there's no name for it
zeroes /= 3
throw "toobig!" if zeroes >= UNITS.length
"#{UNITS[zeroes-1]},"
end
end
class Bignum
def to_en # handles massively large (possibly negative) values
return "negative #{(-self).to_en}" if self < 0
as_chars = self.to_s.split("")
chunk = self.to_s.length % 3
chunk = 3 if chunk == 0
text = ""
while as_chars.length > 0 # eat "chunks" until there are none left
text << "#{as_chars.shift(chunk).join.to_i.hundreds_to_en} #{Unit.how_big(as_chars.length)} "
chunk = 3
end
text
end
end
class Fixnum
ONES = [ "zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten", "eleven", "twelve", "thirteen", "fourteen", "fifteen", "sixteen", "seventeen", "eighteen", "nineteen", "twenty" ]
TENS = [ "ten", "twenty", "thirty", "forty", "fifty", "sixty", "seventy", "eighty", "ninety" ]
def to_en
9999999999999999999.coerce(self).first.to_en # a cheap way of achieving DRY -> defer to Bignum's to_en
end
def hundreds_to_en # handles the range [0, 999]
case self.to_s.length
when 3 # a number in the hundreds
"#{ONES[self/100]} #{Unit.how_big(2)} #{(self % 100).hundreds_to_en}"
when 2 # tens
return ONES[self] if self < ONES.length # teens
return "#{TENS[self/10-1]}-#{ONES[self % 10]}" if self % 10 > 0 # a compound name, if not a power of 10
TENS[self/10-1]
when 1 # ones
ONES[self]
end
end
end
puts "Gimme some numbers and I'll print them in English"
ARGF.each do |line|
puts line.to_i.to_en
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment