お題
アラビア数字(arabic numerals)を受け取って,ローマ数字(roman numerals)を返すmethodを書きなさい1.
ローマ数字で使われる文字
arabic numerals | roman numerals |
---|---|
1 | I |
5 | V |
10 | X |
50 | L |
100 | C |
500 | D |
1000 | M |
例
arabic numerals | roman numerals |
---|---|
1 | I |
2 | II |
4 | IV |
5 | V |
6 | VI |
9 | IX |
10 | X |
11 | XI |
14 | XIV |
15 | XV |
19 | XIX |
38 | XXXVIII |
42 | XLII |
49 | XLIX |
51 | LI |
97 | XCVII |
99 | XCIX |
439 | CDXXXIX |
483 | CDLXXXIII |
499 | CDXCIX |
732 | DCCXXXII |
961 | CMLXI |
999 | CMXCIX |
1999 |
コード
require 'colorize'
class Number
def initialize(arabic_numeral)
@arabic_numeral = arabic_numeral.to_i # string to int
@num_thousands = @arabic_numeral / 1000
@num_hundreds = (@arabic_numeral - @num_thousands*1000) / 100
@num_tens = (@arabic_numeral - @num_thousands*1000 - @num_hundreds*100) / 10
@num_ones = @arabic_numeral % 10
@roman_numeral = ""
end
def convert_roman
if @arabic_numeral > 3999 or @arabic_numeral == 0
puts "arabic_numeral :: #{@arabic_numeral.to_s}"
puts "can't convert".red
exit 0
end
self.to_roman(@num_thousands, 6)
self.to_roman(@num_hundreds, 4)
self.to_roman(@num_tens, 2)
self.to_roman(@num_ones, 0)
end
def to_roman(num, digit)
element = ['I','V','X','L','C','D','M']
case num
when 0..3 then
@roman_numeral = @roman_numeral + element[digit] * num
when 4 then
@roman_numeral = @roman_numeral + element[digit] + element[digit+1]
when 5..8 then
@roman_numeral = @roman_numeral + element[digit+1] + element[digit]*(num-5)
when 9 then
@roman_numeral = @roman_numeral + element[digit] + element[digit+2]
end
end
def puts_numeral
puts "arabic_numeral :: #{@arabic_numeral.to_s}"
puts "roman_numeral :: #{@roman_numeral}".green
end
end
def gets_num
num = ARGV[0]
if num == nil
puts "What\'s the number?".green
num = gets.chomp
end
return num
end
num = gets_num
numeral = Number.new(num)
#numeral.initialize(num)
numeral.convert_roman
numeral.puts_numeral
解説
初期化の部分
def initialize(arabic_numeral)
@arabic_numeral = arabic_numeral.to_i # string to int
@num_thousands = @arabic_numeral / 1000
@num_hundreds = (@arabic_numeral - @num_thousands*1000) / 100
@num_tens = (@arabic_numeral - @num_thousands*1000 - @num_hundreds*100) / 10
@num_ones = @arabic_numeral % 10
@roman_numeral = ""
end
まずは必要な変数の初期化です.
- "@"をつけないとクラス内で使えないので忘れないようにしましょう.
- それぞれの桁の数値をわける関数もあるようですが中身がよくわからないので,計算で求めました.
アラビア数字からローマ数字へ
def to_roman(num, digit)
element = ['I','V','X','L','C','D','M']
case num
when 0..3 then
@roman_numeral = @roman_numeral + element[digit] * num
when 4 then
@roman_numeral = @roman_numeral + element[digit] + element[digit+1]
when 5..8 then
@roman_numeral = @roman_numeral + element[digit+1] + element[digit]*(num-5)
when 9 then
@roman_numeral = @roman_numeral + element[digit] + element[digit+2]
end
end
アラビア数字からローマ数字への変換の部分です.
- digit で桁数を指定して,num を元に場合分けを行います.
- roman_numeral に文字を追加する形で実装してます.
一つの桁に対して3種類の文字を使う可能性があります.
- 例えば 1~9 の場合だと 'I','V','X' の3つ必要になります.
- 使う文字の組み合わせはコードのように 4 通りあるのでそれぞれ分けましょう
- 10 以上の数値の場合については各桁ごとに分けてつなげます
実際の変換部分
def convert_roman
if @arabic_numeral > 3999 or @arabic_numeral == 0
puts "arabic_numeral :: #{@arabic_numeral.to_s}"
puts "can't convert".red
exit 0
end
self.to_roman(@num_thousands, 6)
self.to_roman(@num_hundreds, 4)
self.to_roman(@num_tens, 2)
self.to_roman(@num_ones, 0)
end
アラビア数字からローマ数字へ実際に変換する部分です.
まず,今回の実装では 1 ~ 3999 の数値しか変換が行なえません.そのためそれ以外が入力されている場合はエラーがでるようにしました.
- 数字以外が入力された場合は0になるので今回の処理で弾けるようですね
- せっかくなのでエラーといえば赤という感じで色もつけました.成功した場合は緑になります.
参照文献
- source ~/Documents/my_ruby/grad_members_20f/members/toshi0707/c6_roman_numerals.org
-
"初めてのプログラミング", Chris Pine (著), 西山 伸 (翻訳),オライリー・ジャパン (2006/7/24). ↩