RosettaCodeData/Task/Number-names/Crystal/number-names.cr
2026-04-30 12:34:36 -04:00

41 lines
1.3 KiB
Crystal

struct Int
THOU_PREFIXES = %w(undec dec non oct sept sext quint quadr tr b m)
.map(&.+("illion")) + ["thousand", ""]
TENS = ["", ""] + %w(twen thir for fif six seven eigh nine).map &.+("ty")
ONES = [""] + %w(one two three four five six seven eight nine ten) +
%w(eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen)
def to_words
raise "Number to big to express in words" unless self.abs <= Int128::MAX
return "zero" if self == 0
String.build do |s|
n = self
if n < 0
s << "negative "
n = n.abs
end
ths = Array(Int128).new(THOU_PREFIXES.size, 0)
(0...ths.size).reverse_each do |idx|
n, ths[idx] = n.divmod(1000)
end
ths.zip(THOU_PREFIXES).each do |th, pref|
next if th == 0
hundreds, rest = th.divmod 100
s << ONES[hundreds] << " hundred " if hundreds > 0
if rest < 20
s << ONES[rest] << " " if rest > 0
else
tens, ones = rest.divmod 10
s << TENS[tens]
s << "-" << ONES[ones] if ones > 0
s << " "
end
s << pref << " " if pref != ""
end
s.chomp! 32u8
end
end
end
[0, 4, 6, 11, 75, -164, 1234, 9_876_543_209, Int128::MAX, 101010101010101].each do |n|
print " ", n, ": ", n.to_words, "\n"
end