#
# Convert numbers to English words in Ruby
# ----------------------------------------
# Supports numbers from 0 to 999,999,999,999,999.
#
# Strategy:
# - Break the number into named groups: trillions, billions, millions,
# thousands, hundreds.
# - Convert each 0–999 group using a helper method.
# - Append group names ("trillion", "billion", etc.) when needed.
# - Build the final string using an array and join() for efficiency.
#
ONES = [
"zero", "one", "two", "three", "four",
"five", "six", "seven", "eight", "nine",
"ten", "eleven", "twelve", "thirteen", "fourteen",
"fifteen", "sixteen", "seventeen", "eighteen", "nineteen"
].freeze
TENS_WORDS = [
"", "", "twenty", "thirty", "forty",
"fifty", "sixty", "seventy", "eighty", "ninety"
].freeze
#
# append_word:
# Adds a word to the output array.
#
def append_word(out, word)
out << word unless word.empty?
end
#
# convert_hundreds:
# Converts numbers from 0 to 999 into words.
#
def convert_hundreds(n, out)
return if n.zero?
if n >= 100
append_word(out, ONES[n / 100])
append_word(out, "hundred")
n %= 100
append_word(out, "and") if n > 0
end
if n >= 20
append_word(out, TENS_WORDS[n / 10])
append_word(out, ONES[n % 10]) if n % 10 != 0
elsif n > 0
append_word(out, ONES[n])
end
end
#
# number_to_words:
# Converts any number from 0 to 999,999,999,999,999 into English words.
#
def number_to_words(num)
return "zero" if num.zero?
out = []
trillions = num / 1_000_000_000_000
billions = (num / 1_000_000_000) % 1000
millions = (num / 1_000_000) % 1000
thousands = (num / 1_000) % 1000
hundreds = num % 1000
if trillions > 0
convert_hundreds(trillions, out)
append_word(out, "trillion")
end
if billions > 0
convert_hundreds(billions, out)
append_word(out, "billion")
end
if millions > 0
convert_hundreds(millions, out)
append_word(out, "million")
end
if thousands > 0
convert_hundreds(thousands, out)
append_word(out, "thousand")
end
convert_hundreds(hundreds, out) if hundreds > 0
out.join(" ")
end
#
# main:
# Demonstrates usage with multiple test numbers.
#
tests = [
1_234,
12_345,
123_456,
1_234_567,
123_456_789,
12_345_678_901,
1_234_567_890_123,
999_999_999_999_999
]
tests.each do |n|
puts "#{n} -> #{number_to_words(n)}"
end
#
# run:
#
# 1234 -> one thousand two hundred and thirty four
# 12345 -> twelve thousand three hundred and forty five
# 123456 -> one hundred and twenty three thousand four hundred and fifty six
# 1234567 -> one million two hundred and thirty four thousand five hundred and sixty seven
# 123456789 -> one hundred and twenty three million four hundred and fifty six thousand seven hundred and eighty nine
# 12345678901 -> twelve billion three hundred and forty five million six hundred and seventy eight thousand nine hundred and one
# 1234567890123 -> one trillion two hundred and thirty four billion five hundred and sixty seven million eight hundred and ninety thousand one hundred and twenty three
# 999999999999999 -> nine hundred and ninety nine trillion nine hundred and ninety nine billion nine hundred and ninety nine million nine hundred and ninety nine thousand nine hundred and ninety nine
#