そもそも、たのしいRubyに七千八百二十三とかを7823とかに変換するプログラムを作れというのが練習問題にあって、回答がネット上にありました。
def kan2num(string) digit4 = digit3 = digit2 = digit1 = "0" nstring = string.dup nstring.gsub!(/一/, "1") nstring.gsub!(/二/, "2") nstring.gsub!(/三/, "3") nstring.gsub!(/四/, "4") nstring.gsub!(/五/, "5") nstring.gsub!(/六/, "6") nstring.gsub!(/七/, "7") nstring.gsub!(/八/, "8") nstring.gsub!(/九/, "9") if nstring =~ /((\d)?千)?((\d)?百)?((\d)?十)?(\d)?$/ if $1 digit4 = $2 || "1" end if $3 digit3 = $4 || "1" end if $5 digit2 = $6 || "1" end digit1 = $7 || "0" end return (digit4+digit3+digit2+digit1).to_i end
いろいろ感じて、感じたことが正しいかどうかは別にして、一応書くと。
1.stringのまま扱っているのが2バイト文字はやはりいったんarrayにすべきではないかと思う
2.一二三四もarrayで持って、mapなりzapなりした方がいいと思う
3.正規表現で切り分けるのはかっこよすぎる
4.万億兆京までは対応すべき
5.recursiveにならないか
次にネットで見つけたのが次。
def kan2num(kan) i = nil sum = 0 kan.scan(/./).each do |e| if e == "〇" i = 0 elsif e == "一" i = 1 elsif e == "二" i = 2 elsif e == "三" i = 3 elsif e == "四" i = 4 elsif e == "五" i = 5 elsif e == "六" i = 6 elsif e == "七" i = 7 elsif e == "八" i = 8 elsif e == "九" i = 9 elsif e == "千" if i i = i*1000 else i = 1000 end sum += i i = nil elsif e == "百" if i i = i*100 else i = 100 end sum += i i = nil elsif e == "十" if i i = i*10 else i = 10 end sum += i i = nil end end return sum+=i end
えっと、というわけでたとえば文字列が
kanstring="七千八百二十三"
とすると、まず、
kanary(漢字のarryのつもり)=kanstring.split(//)
なのでkanary2num(kanary)という関数を作る。
京兆億万とすると、切り分けて
kanary1京kanary2兆kanary3億kanary4億kanary5
として、答えを
kanary1*10**16 +
kanary2*10**12 +
kanary3*10**8 +
kanary4*10**4 +
kanary5
とするのでどうか。
4桁部分はとりあえずkanary2num_s(スモールの意味)とするのでどうか。
全体的に命名法に難アリですね。kan2numがいいし、やはり最初は引数はstringかな。そこから呼び出すものをf_kan2numとかにするのはどうか。4桁漢字=>numの意味。
def f_kan2num(array) end def kan2num(string) end
ととりあえずスタブを置く。
次にテスト。
def test_kan2num assert_equal(7516, kan2num("七千五百十六")) assert_equal(1516, kan2num("千五百十六")) assert_equal(30, kan2num("三十")) assert_equal(10000, kan2num("万")) assert_equal(75160001, kan2num("七千五百十六万一")) end def test_f_kan2num assert_equal(0, kanary2num([])) assert_equal(30, kanary2num(["三","十"])) end
で、今。
require 'kconv' $KCODE='s' def f_kan2num(array) ary = array.dup i = 0 sum = 0 kan = ["〇","一","二","三","四","五","六","七","八","九"] ary = ary.map{|item| kan.index(item) ? kan.index(item) : item} ary.each do |element| case element when 0..9 then i = element when "千" then (i != 0) ? (i = i*1000) : (i = 1000) sum += i i = 0 when "百" (i != 0) ? (i = i*100) : (i = 100) sum += i i = 0 when "十" (i != 0) ? (i = i*10) : (i = 10) sum += i i = 0 end end sum += i return sum end def kan2num(string) kanary = string.split(//) sum = 0 if (index_kei = kanary.index("京")) kanary_temp = kanary[0...index_kei] num = f_kan2num(kanary_temp) (num != 0) ? num = num * 10**16 : num = 10**16 sum += num kanary = kanary[index_kei+1..-1] end if (index_chou = kanary.index("兆")) kanary_temp = kanary[0...index_chou] num = f_kan2num(kanary_temp) (num != 0) ? num = num * 10**12 : num = 10**12 sum += num kanary = kanary[index_chou+1..-1] end if (index_oku = kanary.index("億")) kanary_temp = kanary[0...index_oku] num = f_kan2num(kanary_temp) (num != 0) ? num = num * 10**8 : num = 10**8 sum += num kanary = kanary[index_oku+1..-1] end if (index_man = kanary.index("万")) kanary_temp = kanary[0...index_man] num = f_kan2num(kanary_temp) (num != 0) ? num = num * 10**4 : num = 10**4 sum += num kanary = kanary[index_man+1 .. -1] end num = f_kan2num(kanary) if kanary sum += num end if $0 == __FILE__ p kan2num(ARGV[0].chomp) end