fork download
  1. ZERO_TO_TWENTY = {
  2. 0 => nil,
  3. 1 => "one",
  4. 2 => "two",
  5. 3 => "three",
  6. 4 => "four",
  7. 5 => "five",
  8. 6 => "six",
  9. 7 => "seven",
  10. 8 => "eight",
  11. 9 => "nine",
  12. 10 => "ten",
  13. 11 => "eleven",
  14. 12 => "twelve",
  15. 13 => "thirteen",
  16. 14 => "fourteen",
  17. 15 => "fifteen",
  18. 16 => "sixteen",
  19. 17 => "seventeen",
  20. 18 => "eighteen",
  21. 19 => "nineteen"
  22. }.freeze
  23.  
  24. TENS = {
  25. 2 => "twenty",
  26. 3 => "thirty",
  27. 4 => "forty",
  28. 5 => "fifty",
  29. 6 => "sixty",
  30. 7 => "seventy",
  31. 8 => "eighty",
  32. 9 => "ninety"
  33. }.freeze
  34.  
  35. NUMBER_SCALE = [
  36. nil,
  37. "thousand",
  38. "million",
  39. "billion",
  40. "trillion"
  41. ].freeze
  42.  
  43. def in_english(number)
  44. number = number.to_i
  45. raise RangeError if number < 0 or number > 999_999_999_999
  46. return "zero" if number.zero?
  47.  
  48. chunks = []
  49. number, chunks[chunks.count] = number.divmod(1000) while number > 0
  50.  
  51. strings = chunks.map do |number|
  52. string = []
  53. hundreds, remainder = number.divmod(100)
  54. string << "#{ZERO_TO_TWENTY[hundreds]} hundred" if hundreds > 0
  55.  
  56. tens, units = remainder < 20 ? [nil, remainder] : remainder.divmod(10)
  57. string << [ TENS[tens], ZERO_TO_TWENTY[units] ].compact.join("-")
  58.  
  59. string.join(" ")
  60. end
  61.  
  62. strings.zip(NUMBER_SCALE).reverse.flatten.compact.join(" ")
  63. end
  64.  
  65. # =========
  66.  
  67. number = 1_123_456_089
  68. p in_english(number)
Success #stdin #stdout 0.02s 7464KB
stdin
Standard input is empty
stdout
"one billion one hundred twenty-three million four hundred fifty-six thousand eighty-nine"