私自身が表題の問題を解いた時のプログラムについて解説します。
問題の詳細は「英語でプリーズ!」(CodeIQ)を参照してください。
与えられた整数値を、英語に変換するプログラムを作成してください。
たとえば"123"なら"One Hundred Twenty Three"、"-50000"のような負の数は、"Negative Fifty Thousand"のように出力してください。
必要な英単語は以下になります。
Zero
One
Two
Three
Four
Five
Six
Seven
Eight
Nine
Ten
Eleven
Twelve
Thirteen
Fourteen
Fifteen
Sixteen
Seventeen
Eighteen
Nineteen
Twenty
Thirty
Forty
Fifty
Sixty
Seventy
Eighty
Ninety
Hundred
Thousand
Million
Billion
Negative
【入力】
標準入力から1行目には入力データ数N(1≦N≦100)が、2行目以降には整数値が与えられます。
2行目以降のN行分の整数値を英語に変換してください。
ただし、入力データは符号付き32bit整数の範囲で収まるものに限ります。
【出力】
標準出力に、変換後の英語を出力してください(入力データ毎に改行してください)。
アルファベットの大文字・小文字は問いません。
【入出力サンプル】
Input
7 123 4567 89012 0 -34 -5678901 1111111111
Output
One Hundred Twenty Three Four Thousand Five Hundred Sixty Seven Eighty Nine Thousand Twelve Zero Negative Thirty Four Negative Five Million Six Hundred Seventy Eight Thousand Nine Hundred One One Billion One Hundred Eleven Million One Hundred Eleven Thousand One Hundred Eleven
Rubyで解答しています。
#!/usr/bin/ruby Strs = { 1 => "One", 2 => "Two", 3 => "Three", 4 => "Four", 5 => "Five", 6 => "Six", 7 => "Seven", 8 => "Eight", 9 => "Nine", 10 => "Ten", 11 => "Eleven", 12 => "Twelve", 13 => "Thirteen", 14 => "Fourteen", 15 => "Fifteen", 16 => "Sixteen", 17 => "Seventeen", 18 => "Eighteen", 19 => "Nineteen", 20 => "Twenty", 30 => "Thirty", 40 => "Forty", 50 => "Fifty", 60 => "Sixty", 70 => "Seventy", 80 => "Eighty", 90 => "Ninety", } Figs = { 1 => "Thousand", 2 => "Million", 3 => "Billion", } def parse3(n) ret = [] h = n / 100 if h > 0 then ret << Strs[h] ret << "Hundred" end m = n % 100 if (0 < m) && (m <= 19) then ret << Strs[m] else l = m % 10 k = m - l ret << Strs[k] ret << Strs[l] if l != 0 end return ret end def solve(n) return ["Zero"] if n == 0 nxt = n.abs ret = [] c = 0 while nxt > 0 lst3 = nxt % 1000 if lst3 != 0 then arr = parse3(lst3) arr << Figs[c] if c > 0 ret = arr + ret end nxt /= 1000 c += 1 end ret.unshift("Negative") if n < 0 return ret.join(" ") end # main ln = 0 while line = gets line.strip! next if line.empty? puts solve(line.to_i) if ln > 0 ln += 1 end
3桁ごとに処理することに気づけば簡単です。
入力値を数値にしてsolve()に渡し、結果を印字します。
1行目は入力数なので跳ばします。
入力値が0の時は"Zero"で終わりなのでそれでリターンします。
nxtは1000で割った商を保持する変数で、初期値はnの絶対値にします。
retは結果の英単語の配列です。
cは何回1000で割ったかをカウントします。
下から3桁ずつ処理します。
1000で割った余りをlst3に保持し、parse3()に渡して英単語にします。
結果はarrに入ってきますので、後から処理した分が前に来るようにretに連結します。73行目の処理は割った回数が1回ならThousand、2ならMillion、3ならBillionをつけるという処理です。
入力値がマイナスならretの先頭にNegativeをつけます。
最後にこれらをスペースで連結した文字列にして返します。
3桁ぶんを英単語にします。
まず、100で割ってその商を〜 Hundredにします。0の時は無視します。
次に100で割った余りが1〜19ならOne〜Nineteenにします。
そうでなければ更に10で割って商と余りにし、商をTwenty〜Ninetyに、余りをOne〜Nineにします。
このようにして作った単語の配列を返します。
前に同じような問題をやった気がする上に、番号が1658と若かったので2回目かと思いましたが初めてだったみたいです。
前にやったのは逆パターン(英単語を数字に)だったかなぁ?