1~3999 사이의 로마자 s를 인자로 주면 그에 해당하는 숫자를 반환해주세요.
로마 숫자를 숫자로 표기하면 다음과 같습니다.
Symbol Value
I 1
V 5
X 10
L 50
C 100
D 500
M 1000
로마자를 숫자로 읽는 방법은 로마자를 왼쪽부터 차례대로 더하면 됩니다.
III = 3
XII = 12
XXVII = 27
입니다.
그런데 4를 표현할 때는 IIII가 아니라 IV 입니다.
뒤의 숫자에서 앞의 숫자를 빼주면 됩니다.
9는 IX입니다.
I는 V와 X앞에 와서 4, 9
X는 L, C앞에 와서 40, 90
C는 D, M앞에 와서 400, 900
def roman_to_num(string):
roman = {'I':1, 'V': 5, 'X':10, 'L':50, 'C':100, 'D': 500, 'M':1000}
total = 0
for i in range(len(string)):
current_rom = string[i]
if i == (len(string)-1):
total += roman[current_rom]
else:
if roman[string[i]]>=roman[string[i+1]]:
total += roman[current_rom]
else:
total -= roman[current_rom]
return(total)
앞뒤 대소비교를 해야해서 그럼 앞의 값이랑 뒤의 값이랑 더하거나 빼서 기존의 sum과 더해줘야하나? 계속 복잡하게 생각하다가 코드카타 짝꿍 정민님에게 어떻게 푸셨냐고 여쭤보니 그냥 앞>뒤면 수가 +이고 앞<뒤면 수가 -가 된다고 생각해서 푸셨다고 하셨다.(예를들어 XIV라면 10+(-1)+5)
이렇게 따로 떨어뜨려 생각하니 훨씬 생각하기 간단해져서 금방 풀 수 있었다. 감사합니다😀
#solution1
# def roman_to_num(s):
# """
# :type s: str
# :rtype: int
# """
# L = []
# sum = 0
# d = {'I':1, 'V':5, 'X':10, 'L':50, 'C':100, 'D':500, 'M':1000}
# for i in s[::-1]:
# if L:
# if i=='I' and L[-1] in ['V','X']:
# sum -= 1
# L.pop()
# elif i=='X' and L[-1] in ['L','C']:
# sum -= 10
# L.pop()
# elif i=='C' and L[-1] in ['D','M']:
# sum -= 100
# L.pop()
# else:
# sum += d[i]
# L.append(i)
# else:
# sum +=d[i]
# L.append(i)
# return sum
#solution2
numbers = {
"I" : 1,
"IV" : 4,
"V" : 5,
"IX" : 9,
"X" : 10,
"XL" : 40,
"L" : 50,
"XC" : 90,
"C" : 100,
"CD" : 400,
"D" : 500,
"CM" : 900,
"M" : 1000,
}
def roman_to_num(s):
if not s:
return 0
if numbers.get(s[:2]):
return numbers.get(s[:2]) + roman_to_num(s[2:])
return numbers.get(s[:1]) + roman_to_num(s[1:])
model solution2에서는 예외인 부분들까지 딕셔너리에 포함시켜 만들었다. 나도 처음에 이렇게 딕셔너리를 만들어볼까 고민했었는데 그 뒤로 어떻게 풀어나갈지 몰라서 포기했었다.
여기서는 로마자 2자와 딕셔너리의 key중에 맞는게 있다면 숫자로 변환하고 일치하는게 없다면 1글자만을 확인해서 숫자로 변환해준다. 그리고 숫자로 변환한 것 이외의 나머지 로마자들은 또 원래의 함수에 넣어서(재귀함수) 더이상 비교할 값이 없을때까지 동일 과정을 반복하여 더해준다.