본문 바로가기

자료구조 & 알고리즘 & cs/CodingTest

[python] 2608 - 로마 숫자

2608번: 로마 숫자 (acmicpc.net)

 

2608번: 로마 숫자

첫째 줄과 둘째 줄에 하나씩 로마 숫자로 표현된 수가 주어진다. 입력된 각 수는 2000 보다 작거나 같고, 두 수의 합은 4000보다 작다.

www.acmicpc.net

 

뭐랄까.. 굉장히 어렵진 않지만

조건들도 많았고 구현하기 싫게 생긴 문제였다.

우선, 딕셔너리에 각 문자 값들을 구분해서 담아준 후

문자를 숫자로 변환하는 함수와

숫자를 문자로 변환하는 함수 두개를 만들어 주었다.

 

문자를 숫자로 변환하는 과정은 크게 까다롭지 않았으나

숫자를 문자로 변환할 때가 만족스럽지 않은 코드였다.

숫자의 자리수와 값을 토대로 if문을 사용하여 케이스를 나눠주었는데

두 숫자의 합에 대한 값이 4000 이하로 제한되어 있기 때문에

해결은 되었지만 더 깔끔한 코드가 없을까 고민을 많이 했다.

 

# 2608 로마 숫자
import sys
input = sys.stdin.readline

#참고 딕셔너리
l1 = {'I': 1, 'V': 5, 'X': 10, 'L': 50, 'C': 100, 'D': 500, 'M': 1000}
l2 = {'IV': 4, 'IX': 9, 'XL': 40, 'XC': 90, 'CD': 400, 'CM': 900}

#문자_숫자
def str_to_num(romaList):
    total=0
    i=0
    while romaList:
        
        if len(romaList)==1:
            total += l1[romaList[i]]
            break
        
        plus = romaList[i]+romaList[i+1]
        if plus in l2:
            total+=l2[plus]
            romaList=romaList[i+2:]
        else:
            total+=l1[romaList[i]]
            romaList=romaList[i+1:]
            
    return total

#숫자_문자
def num_to_str(num):
    roma=''
    i=0
    # 자리수와 숫자 체크 
    while num!=0:
        size=len(str(num))
        k=int(str(num)[i])
        
        if 4== size:
            roma+= 'M'*k
            num -= 1000*k
        elif size==3:
            if 9 == k:
                roma +='CM'
                num-=900
            elif 5<=k<9:
                roma += 'D'
                num-=500
            elif 4<=k<5:
                roma += 'CD'
                num-= 400
            else: 
                roma += 'C'
                num-=100
        elif size==2:
            if 9 == k:
                roma +='XC'
                num-=90
            elif 5<=k<9:
                roma += 'L'
                num-=50
            elif 4<=k<5:
                roma += 'XL'
                num-= 40
            else: 
                roma += 'X'
                num-=10
        else:
            if 9 == k:
                roma +='IX'
                num-=9
            elif 5<=k<9:
                roma += 'V'
                num-=5
            elif 4<=k<5:
                roma += 'IV'
                num-= 4
            else: 
                roma += 'I'
                num-=1
    return roma

# 입력
n1=input().strip()
n2=input().strip()

# 아라비아 출력
num1=str_to_num(n1)
num2= str_to_num(n2)
print(num1+num2)

# 로마 출력
romaNum=num_to_str(num1+num2)
print(romaNum)

 

 

스터디 후 다른 분이 작성한 깔끔한 코드가 있어 정리해보려고 한다.

def num_to_str(num):
    times = {'M': 3, 'CM': 1, 'D': 1, 'CD': 1, 'C': 3, 'XC': 1, 
      'L': 1, 'XL': 1, 'X': 3, 'IX': 1, 'V': 1, 'IV': 1, 'I': 3}    
    word = []
    for t in times:
        value = l1.get(t) 		# l1 = {'M': 1000, 'CM': 900, 'D': 500, 'CD': 400, 'C': 100, 'XC': 90, 'L': 50, 'XL': 40, 'X': 10, 'IX': 9, 'V': 5, 'IV': 4, 'I': 1}			
        limit = times[t]
        while limit and num >= value:
            num -= value
            times[t] -= 1
            word.append(t)
    return ''.join(word)

 

각 로마 숫자는 사용 횟수에 제한이 있으므로 제한 딕셔너리를 생성한 후 

while문을 돌면서 value 값을 비교하여

전체 로마 숫자 리스트에서 뺄 수 있는 큰 수부터 빼준다.

훨씬 깔끔한 코드였다!

 

 

* 모든 코드는 github에서 관리합니다.  seinShin (SEIN SHIN) (github.com)

 

seinShin - Overview

blog : https://bboddorong.tistory.com/. seinShin has 7 repositories available. Follow their code on GitHub.

github.com

 

728x90