상세 컨텐츠

본문 제목

[파이썬] 로마숫자를 10진수 정수로 변환하기

프로그래밍

by ∫2tdt=t²+c 2012. 10. 23. 21:26

본문


이 역시 정수를 로마숫자로 변환하는것([파이썬] 정수를 로마숫자로 변환하기)과 함께 수업시간에 과제로 나온것인데, 미적인 코-드를 향한 욕망 때문에 금방 끝낼수 있는걸 몇시간째 붙들고 있는중ㅋ.


로마숫자 체계는 다음과 같습니다.



I  1
 V  5
 X  10
 L  50
 C  100
 D  500
 M  1000
 F  5000

그냥 여기서 끝나면 참 좋으려만, 조합할 때 다음과 같은 규칙이 있어서 어렵습니다.


XI 는 11이지만, IX는 9

LX는 60이지만, XL은 40.


즉 앞에있는 숫자가 뒤의 있는 숫자보다 작을 경우에는 뒤에있는 숫자에서 앞에있는 숫자를 빼준 값이 되는것.

나머지 경우는 그대로 숫자를 합하면 됩니다.


첫번째 코-드


1
2
3
4
5
6
7
8
9
10
11
12
13
def  roman2int(roman):
    def getdv(r):
        p = 'IVXLCDMF'.find(r)
        return 0 if p < 0 else 10**(p // 2) * (1 (4*(p % 2)))
 
    i = 0
    v = map(getdv, roman)
    s = 0
    while i < len(v):
        if i 1 == len(v) or v[i] >= v[i+1]: s += v[i]
        else: s -= v[i]
        = 1
    return s

접근법은 각 자리를 그 자리가 의미하는 숫자로 변환해주고, 반복문을 돌면서 앞의 숫자가 뒤의 숫자보다 작은경우는 뺄셈을 해주는것.

getdv함수는 약간 변태같이 짜졌는데, {'I'=1, 'V'=5, 'X'=10 ...} 이렇게 사전으로 만들었다가... 너무 길어지고 타이핑하기 귀찮아서 규칙을 찾아서 수식으로 바꿔어버렸습니다.


근데 뭔가 반복문을 좀더 아름답게 바꿔볼수 있을거같아서 다시 삽질.



1
2
3
4
5
6
7
def  roman2int2(roman):
    def getdv(r):
        p = 'IVXLCDMF'.find(r)
        return 0 if p < 0 else 10**(p // 2) * (1 (4*(p % 2)))
 
    v = map(getdv, roman)
    return reduce(lambda s, x: s + x[0] if x[0]>=x[1] else s - x[0], zip(v, v[1:] + [0]), 0)

zip함수와 reduce함수를 이용해 반복문을 없애버렸다!!!! 더더더더더ㅋ 훨씬 보기 좋아졌습니다 ㅎ (는 개뿔 변태스러워졌네요.)


관련글 더보기

댓글 영역