なんか想像以上に手こずったよ^ ^;
case式内が見苦しい..
もっと簡単なやり方あるんだろうな。Integer#dollarizeを定義してみた。
数字を英語のドル表記に変換。
#!/usr/bin/env ruby
class Integer
def dollarize
num_set = split_by_unit.map(&:__dollarize__)
join_with_unit(num_set)
end
def split_by_unit(unit=10**3)
q, r = divmod(unit)
if q < unit
[q, r]
else
q.split_by_unit(unit) << r
end
end
UNDER_TENS = Hash[[*0..9].zip %w(Zero One Two Three Four Five Six Seven Eight Nine)]
TEENS = Hash[[*10..19].zip %w(Ten Eleven Twelve Thirteen Fourteen Fifteen Sixteen Seventeen Eighteen Nineteen)]
TYS = Hash[[*20.step(90,10)].zip %w(Twenty Thirty Forty Fifty Sixty Seventy Eighty Ninety)]
DIGITS = Hash[[10,100,1000].zip %w(Ten Hundred Thousand)]
def __dollarize__
ten_flag = false
digitaize.map do |n, digit|
case
when n.zero? && !ten_flag
# do_nothing
when digit == 10
unless n == 1
TYS[n*digit]
else
ten_flag = true
nil
end
when digit == 1 && ten_flag
ten_flag = false
TEENS[10+n]
else
"#{UNDER_TENS[n]}#{DIGITS[digit]}"
end
end.join
end
def digitaize
ns = split_by_unit(10)
ns.map.with_index { |n, i| [n, 10**(ns.size-1-i)] }
end
private
def join_with_unit(num_set, seps = %w(Thousand Million))
return UNDER_TENS[0] if num_set == ['','']
num_set.reverse.inject do |mem, var|
sep = seps.shift
sep = nil if var.empty?
[var, mem].join(sep)
end
end
end
puts ARGF.map { |line| line.to_i.dollarize + 'Dollars' }