はじめに
今回は課題としてアラビア数字からローマ数字に変換するという課題が出たので、その課題を解いてみる事にする
解答
プログラム
- 正直全く良い方法分からない、、、、、
num = ARGV[0]
def divide_num(num)
ans_list,count = [],0
while num > 0
tmp = num % 10
ans_list.push(tmp * (10 ** count))
num = num / 10
count = count + 1
end
return ans_list.reverse
end
ans_list,count = divide_num(num.to_i),0
def num_to_roman_hundred(num)
if num == 900
print "CM"
elsif num <= 800 && num >= 500
num = num - 500
if num != 0
print "D" + "C" * (num / 100)
else
print "D"
end
elsif num == 400
print "CD"
elsif num <= 300 && num >= 100
num = num - 100
if num != 0
print "C" + "C" * (num / 100)
else
print "C"
end
end
end
def num_to_roman_ten(num)
if num == 90
print "XC"
elsif num <= 80 && num >= 50
num = num - 50
if num != 0
print "L" + "X" * (num / 10)
else
print "L"
end
elsif num == 40
print "XL"
elsif num <= 30 && num >= 10
num = num - 10
if num != 0
print "X" + "X" * (num / 10)
else
print "X"
end
end
end
def num_to_roman(num)
roman_first = ['I','II','III','IV','V','VI','VII','VIII','IX','X']
if num >= 1000
tmp = num / 1000
x = "M" * tmp
print x
elsif num <= 900 && num >= 100
num_to_roman_hundred(num)
elsif num <= 90 && num >= 10
num_to_roman_ten(num)
elsif num <= 10 && num >= 1
print roman_first[num-1]
end
end
for i in ans_list do
num_to_roman(i)
end
print "\n"
自分で書いてて思います。頭悪い実装です(笑)
(深夜にやっていて頭回ってないという言い訳をしときます(笑))
個別の関数毎の説明
-
divide_num 関数の中で受けとった数字を分解
-
num_to_roman_hundred, num_to_roman_ten はそれぞれの桁数に合わせてローマ数字に変換を行う
-
num_to_roman で全ての数字をローマ数字に変換
-
追記
- コードの改良を行った – 11/21
- 改良版を下の方に載せときます
答え合わせ
では作成したプログラムが正しいかどうかの答え合わせをしましょう!!
-
以下のようなプログラム(a.sh)を作成します
for i in $(seq 1 3999);do ruby a.rb $i # a.rb はソースコードの名前なので何でもいいです done
-
bash a.sh > tmp.txt
-
エクセルから 3999 までのローマ数字を作成(1 分以内で可能)し、tmp2.txt として保存
-
diff tmp.txt tmp2.txt
何も出力されなければ成功!!
逆に出力されたら失敗してます。。。
追記(コード改良版)
- num_to_roman_hundred と num_to_roman_ten の関数を統合してnum_to_roman_each 関数に変更した(new_roman_numeral.rb)
これで少しはコード少くなったかな?
(元のアルゴリズムが良くないからそんなに短くなってないけど、、、、)
num = ARGV[0]
def divide_num(num)
ans_list,count = [],0
while num > 0
tmp = num % 10
ans_list.push(tmp * (10 ** count))
num = num / 10
count = count + 1
end
return ans_list.reverse
end
ans_list,count = divide_num(num.to_i),0
def num_to_roman_each(num, f_str, s_str, t_str, fo_str)
f_num = num.to_s[0].to_i
if f_num == 9
print f_str
elsif f_num <= 8 && f_num >= 5
if (f_num - 5) != 0
print s_str + t_str * (f_num - 5)
else
print s_str
end
elsif f_num == 4
print fo_str
elsif f_num <= 3 && f_num >= 1
if (f_num - 1) != 0
print t_str + t_str * (f_num - 1)
else
print t_str
end
end
end
def num_to_roman(num)
roman_first = ['I','II','III','IV','V','VI','VII','VIII','IX','X']
if num >= 1000
tmp = num / 1000
x = "M" * tmp
print x
elsif num <= 900 && num >= 100
num_to_roman_each(num, "CM", "D", "C", "CD")
elsif num <= 90 && num > 10
num_to_roman_each(num, "XC", "L", "X", "XL")
elsif num <= 10 && num >= 1
print roman_first[num-1]
end
end
for i in ans_list do
num_to_roman(i)
end
print "\n"
GitHub
以下の URL に全てのプログラムと txt file を置いておきます。
- source ~/Downloads/git/grad_members_20f/members/taiseiyo/memos/roman.org