1~3999 사이의 로마자 s를 인자로 주면 그에 해당하는 숫자를 반환해주세요.
✔️ 로마자를 숫자로 읽는 방법은 로마자를 왼쪽부터 차례대로 더하면 됩니다.
- III = 3 👈 I는 숫자 1이기 때문에 3(1+1+1)
- XII = 12 👈 X는 숫자 10이기 때문에 12(10+1+1)
- XXVII = 27 👈 V는 숫자 5이기 때문에 27(10+10+5+1+1)
✔️ 그런데 4를 표현할 때는 IIII가 아니라 IV 입니다. 뒤의 숫자에서 앞의 숫자를 빼주면 됩니다. 9는 IX입니다.
✔️ I는 V와 X앞에 와서 4, 9 X는 L, C앞에 와서 40, 90 C는 D, M앞에 와서 400, 900입니다.
- IV = 4 👈 1+5가 아닌, 5-1이기 때문에 4
- IX = 9 👈 1+10가 아닌, 10-1이기 때문에 9
- XL = 40 👈 10+50이 아닌, 50-10이기 때문에 40
- XC = 90 👈 10+100이 아닌, 100-10이기 떄문에 90
- CD = 400 👈 100+500이 아닌, 500-100이기 때문에 400
- CM = 900 👈 100+1000이 아닌, 1000-100이기 때문에 900
def roman_to_num(s): if len(s) == 0: return 0 # 👈 s에 아무것도 전달되지 않으면 0 반환 roman_d = {'I':1, 'V': 5, 'X':10, 'L':50, 'C':100, 'D': 500, 'M':1000} total = 0 for i in range(len(s)): # 👈 s의 길이만큼 순회 if i == len(s)-1: # 👈 out of range 에러 발생하지 않도록! total += roman_d[s[i]] else: if roman_d[s[i]] >= roman_d[s[i+1]]: # 👈 s[i] >= s[i+1] 일때,, total += roman_d[s[i]] else: # 👈 s[i] < s[i+1] 일때,, total -= roman_d[s[i]] return total s = 'XXVII' res = roman_to_num(s) print(res)
✔️ 우선 주어진 표를 딕셔너리로 만들어두고, for문을 순회해 s[i]값을 딕셔너리에서 찾아 total에 더해줘야 한다.
✔️ 다만, for문 내부에서 s[i]와 s[i+1]를 비교하기 때문에 out of range 에러를 방지하기 위해서 현재 i가 마지막 요소라면 비교하지 않고 바로 더할 수 있게 처리했다.
✔️ total값을 구하는 핵심은 s[i]가 s[i+1] 보다 크거나 같을 때는 딕셔너리에서 value값을 total에 계속 더해주기만 하면 되고, s[i]가 s[i+1] 보다 작을 때만 현재 s[i]를 total값에서 빼주면 된다.
✔️ 빼주는 이유는 IV는 4인데, I가 1이고, V가 5이기 때문이다. 먼저 빼주고 더해주면 둘다 처리가 가능하다.
def roman_to_num(s): roman_d = {'I': 1, 'V': 5, 'X': 10, 'L': 50, 'C': 100, 'D': 500, 'M': 1000} res = 0 for i in range(len(s)): if i > 0 and roman_d[s[i]] > roman_d[s[i-1]]: res += roman_d[s[i]] - 2 * roman_d[s[i-1]] else: res += roman_d[s[i]] return res s = 'XXVII' res = roman_to_num(s) print(res)
✔️ 이 방법은 s[i]가 s[i-1] 보다 클 때, s[i-1] 값에 2를 곱한 뒤, s[i]에서 빼주는 방식이다.
✔️ 즉, IV를보면, 여기서 I는 s[i-1]이 되고, V는 s[i]가 되기 떄문에 s[i]가 s[i-1] 보다 큰 상황이 발생된다.
✔️ 이럴 때, s[i-1]을 2를 곱해서 빼는 이유는 s[i-1]이 이 전 순회때 s[i]였기 때문에 이미 더해져버렸기 떄문이다. 미리 한번 더한뒤, 나중에 빼는 방식이기 때문에 2를 곱해서 빼야한다.
눈으로만 풀려하면 해결하기 어렵다. 손으로 그리며 규칙을 찾자.