課題
アラビア数字(arabic numerals)を受け取って,ローマ数字(roman numerals)を返すmethodを書きなさい.
作成
ひとまず動くものを作ってみた.4桁の整数が入力されるものとして各桁を分割し,それぞれに対して4か9かそれ以外かという分岐を施した.
roman_numerals.rb
class Integer
def arab_to_roman
number = self
m = number / 1000
number = number % 1000
c = number / 100
number = number % 100
x = number / 10
number = number % 10
i = number
roman = 'M' * m
if c == 9
roman += 'CM'
elsif c == 4
roman += 'CD'
else
roman += 'D' * (c / 5)
c = c % 5
roman += 'C' * c
end
if x == 9
roman += 'XC'
elsif x == 4
roman += 'XL'
else
roman += 'L' * (x / 5)
x = x % 5
roman += 'X' * x
end
if i == 9
roman += 'IX'
elsif i == 4
roman += 'IV'
else
roman += 'V' * (i / 5)
i = i % 5
roman += 'I' * i
end
puts roman
end
end
[4, 15, 32, 44, 99, 439, 499, 961, 2254, 3782].each do |i|
i.arab_to_roman
end
結果は,
IV
XV
XXXII
XLIV
XCIX
CDXXXIX
CDXCIX
CMLXI
MMCCLIV
MMMDCCLXXXII
動くけども冗長なコードになってダサい.
改造しよう.ifをcaseを用いて短縮することを考える.
roman_numerals.rb
class Integer
def arab_to_roman
number = self
m = number / 1000
number = number % 1000
c = number / 100
number = number % 100
x = number / 10
number = number % 10
i = number
roman = 'M' * m
case c
when 9 then roman += 'CM' #900
when 4 then roman += 'CD' #400
else
roman += 'D' * (c / 5)
c = c % 5
roman += 'C' * c
end
case x
when 9 then roman += 'XC' #90
when 4 then roman += 'XL' #40
else
roman += 'L' * (x / 5)
x = x % 5
roman += 'X' * x
end
case i
when 9 then roman += 'IX' #9
when 4 then roman += 'IV' #4
else
roman += 'V' * (i / 5)
i = i % 5
roman += 'I' * i
end
puts roman
end
end
[4, 15, 32, 44, 99, 439, 499, 961, 2254, 3782].each do |i|
i.arab_to_roman
end
さらにcaseの動作は三回ともほぼ同じなので別のメソッドを作っておいて使用する.
roman_numerals.rb
class Integer
def arab_to_roman
number = self
m = number / 1000
number %= 1000
c = number / 100
number %= 100
x = number / 10
number %= 10
i = number
roman = 'M' * m
roman = proc(roman, ["C","D","M"], c)
roman = proc(roman, ["X","L","C"], x)
roman = proc(roman, ["I","V","X"], i)
puts roman
end
def proc(roman, sym, n)
case n
when 9 then roman += (sym[0]+sym[2])
when 4 then roman += (sym[0]+sym[1])
else
roman += (sym[1] * (n / 5))
n = n % 5
roman += (sym[0] * n)
end
return roman
end
end
[4, 15, 32, 44, 99, 439, 499, 961, 2254, 3782].each do |i|
i.arab_to_roman
end
だいぶマシにはなった.まだ短くできるのかもしれないけども,僕はここまでしかできません.
まとめ
アラビア数字をローマ数字に変換するコードを作成した.
参考
- source ~/prog/github/grad_members_20f/members/miyanagi/post/roman.org