Roman to Int 〜leetcode〜


〜問題文〜

Roman numerals are represented by seven different symbols: I, V, X, L, C, D and M.

Symbol       Value
I             1
V             5
X             10
L             50
C             100
D             500
M             1000


For example, 2 is written as II in Roman numeral, just two one's added together. 12 is written as XII, which is simply X + II. The number 27 is written as XXVII, which is XX + V + II.

Roman numerals are usually written largest to smallest from left to right. However, the numeral for four is not IIII. Instead, the number four is written as IV. Because the one is before the five we subtract it making four. The same principle applies to the number nine, which is written as IX. There are six instances where subtraction is used:

I can be placed before V (5) and X (10) to make 4 and 9. 
X can be placed before L (50) and C (100) to make 40 and 90. 
C can be placed before D (500) and M (1000) to make 400 and 900.
Given a roman numeral, convert it to an integer.



Example

Input: roman = "III"
Output: 3
Example 2:

Input: roman = "IV"
Output: 4
Example 3:

Input: roman = "IX"
Output: 9
Example 4:

Input: roman = "LVIII"
Output: 58
Explanation: L = 50, V= 5, III = 3.
Example 5:

Input: roman = "MCMXCIV"
Output: 1994
Explanation: M = 1000, CM = 900, XC = 90 and IV = 4.


Constraints:

1 <= s.length <= 15
s contains only the characters ('I', 'V', 'X', 'L', 'C', 'D', 'M').
It is guaranteed that s is a valid roman numeral in the range [1, 3999].

引用元: https://leetcode.com/problems/roman-to-integer/

簡単に要約すると、「任意のローマ数字を入れたら数字になるようにコーディングしなさい。」だそうです。

↓回答例

def roman_to_int(s)
  hash = {
    'I'=> 1,
    'V'=> 5,
    'X'=> 10,
    'L'=> 50,
    'C'=> 100,
    'D'=> 500,
    'M'=> 1000
  }

  total = 0
  i = 0
  while i < s.length
    if i + 1 < s.length && hash[s[i]] < hash[s[i+1]]
      total += hash[s[i+1]] - hash[s[i]]
      i += 1
    else
      total += hash[s[i]]
    end

    i += 1
  end

  return total
end

回答引用元(一部改変):
https://leetcode.com/problems/roman-to-integer/discuss/704290/ruby-solution-44ms-using-each_char

以下、上記回答の分解分析

1. ハッシュでの定義

hash = {
    'I' =>    1,
    'V' =>    5,
    'X' =>    10,
    'L' =>     50,
    'C' =>     100,
    'D' =>     500,
    'M' =>     1000 
    }

やはりハッシュはアローでつなぐと見やすいですね(個人的に)。

2. 変数の定義

 i = 0

each処理をする前に、入力されたローマ数字の前後関係を定義しておく。

3. ① while文 + ② if文

① while文

while i < s.length

  〜省略〜

end

記入されたローマ数字の文字数(s.length)が回数( i )よりも少ない間は、処理が継続する。
(例)Input: s = "IV"  =>  s.length = 2

② if文

    if i + 1 < s.length && hash[s[i]] < hash[s[i+1]]

      total += hash[s[i+1]] - hash[s[i]]
      i += 1

    else

      total += hash[s[i]]

    end

【条件】
「記入されたローマ数字の文字数(s.length)が回数( i )よりも少ない」
 かつ
「前のローマ数字 が 後のローマ数字よりも小さい」

ならば、以下の処理を行う。

【処理】
後のローマ数字の値 - 前のローマ数字の値

return total

値を返却。