LoginSignup
5
0

More than 3 years have passed since last update.

roman_numerals

Posted at

ruby-2.7.1p83

お題

解答

# frozen_string_literal: true

require './assert_equal'

# ローマ数字は、基本的には左の記号から足していくことでアラビア数字と対応づけることができる。
# (ex. 3 -> III(1+1+1), 11 -> XI(10+1))
# ポーランド記法っぽく表現すると、分かりやすくて、3 -> + + I I I, 11 -> + X I
# しかし一部例外があって、上位の記号の近くでは、上の規則が成り立たない。
# (ex. 4 -> IV(not 1+5, but 5-1))
# ポーランド記法っぽく表現すると 4 -> - VI. これでも元の表記 IV とは逆になってしまっている。
# 最上位桁が一番大きい場合は表記通りに足し算をしていく。そうでない場合は第2位の桁と記号を入れ替えた上で引き算をする... というようなロジックが考えられるが、面倒くさい。
# そこで、左の記号から足していくというコンセプトをそのまま保つため、
# 上のような例外はあらかじめ内部で定義しておく。
class Roman
  def initialize(n)
    @roman = ''
    @n = n
    @arabic_roman = [
      [1, 'I'],
      [4, 'IV'],
      [5, 'V'],
      [9, 'IX'],
      [10, 'X'],
      [40, 'XL'],
      [50, 'L'],
      [90, 'XC'],
      [100, 'C'],
      [400, 'CD'],
      [500, 'D'],
      [900, 'CM'],
      [1000, 'M']
    ]
  end

  def roman
    @arabic_roman.reverse.each do |arabic, roman|
      quotient = @n / arabic
      @n -= quotient * arabic
      (1..quotient).each do |_|
    @roman += roman
      end
    end
    @roman
  end
end

def to_roman(n)
  return 'I' if n == 1
  return 'V' if n == 5
  return 'X' if n == 10
  return 'L' if n == 50
  return 'C' if n == 100
  return 'D' if n == 500
  return 'M' if n == 1000
end

if __FILE__ == $PROGRAM_NAME
  [
    ['I', 1],
    ['II', 2],
    ['III', 3],
    ['IV', 4],
    ['V', 5],
    ['VI', 6],
    ['IX', 9],
    ['X', 10],
    ['XI', 11],
    ['XIV', 14],
    ['XV', 15],
    ['XIX', 19],
    ['XXXVIII', 38],
    ['XLII', 42],
    ['XLIX', 49],
    ['LI', 51],
    ['XCVII', 97],
    ['XCIX', 99],
    ['CDXXXIX', 439],
    ['CDLXXXIII', 483],
    ['CDXCIX', 499],
    ['DCCXXXII', 732],
    ['CMLXI', 961],
    ['CMXCIX', 999],
    ['MCMXCIX', 1999]
  ].each do |expected, arg|
    assert_equal(expected, Roman.new(arg).roman)
  end

end

ちなみに、ruby では複数行のコメントを以下のように書けるのだが、

=begin
hoge
fuga
=end

rubocop により 全て # から始まる一行コメントに変換された。

test

全てのテストを pass した。

expected: I
result:   I
succeeded in assert_equal.
expected: II
result:   II
succeeded in assert_equal.
expected: III
result:   III
succeeded in assert_equal.
expected: IV
result:   IV
succeeded in assert_equal.
expected: V
result:   V
succeeded in assert_equal.
expected: VI
result:   VI
succeeded in assert_equal.
expected: IX
result:   IX
succeeded in assert_equal.
expected: X
result:   X
succeeded in assert_equal.
expected: XI
result:   XI
succeeded in assert_equal.
expected: XIV
result:   XIV
succeeded in assert_equal.
expected: XV
result:   XV
succeeded in assert_equal.
expected: XIX
result:   XIX
succeeded in assert_equal.
expected: XXXVIII
result:   XXXVIII
succeeded in assert_equal.
expected: XLII
result:   XLII
succeeded in assert_equal.
expected: XLIX
result:   XLIX
succeeded in assert_equal.
expected: LI
result:   LI
succeeded in assert_equal.
expected: XCVII
result:   XCVII
succeeded in assert_equal.
expected: XCIX
result:   XCIX
succeeded in assert_equal.
expected: CDXXXIX
result:   CDXXXIX
succeeded in assert_equal.
expected: CDLXXXIII
result:   CDLXXXIII
succeeded in assert_equal.
expected: CDXCIX
result:   CDXCIX
succeeded in assert_equal.
expected: DCCXXXII
result:   DCCXXXII
succeeded in assert_equal.
expected: CMLXI
result:   CMLXI
succeeded in assert_equal.
expected: CMXCIX
result:   CMXCIX
succeeded in assert_equal.
expected: MCMXCIX
result:   MCMXCIX
succeeded in assert_equal.

  • source ~/ghq/github.com/TeamNishitani/grad_members_20f/members/syasin-5d/roman_numerals.org
5
0
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
0