codekata6. 로마자

rahula·2021년 6월 28일
0

algorithm

목록 보기
6/9

로마자에서 숫자로 바꾸기 1~3999 사이의 로마자 s를 인자로 주면 그에 해당하는 숫자를 반환해주세요.

문제 파악

요구사항 : 로마자를 숫자로 반환해서 줘라.

제한 사항 : IV, IX 등등 로마자의 계산체계

인풋 : 로마자를 표현한 string값

아웃풋 : 숫자값

본질 : 딕셔너리의 key로 값을 가져오는 성질. 그리고 제한사항에 대한 조건문.

생각하는 과정

  1. 리스트의 각 문자를 숫자값으로 바꾼다?

  2. IX같은 경우는 어떻게 할거야? 반복문에서 바로 하기엔 무리가 있다.

  3. 자릿수는 어떻게 할거야? X이전에 오는 I는 X보다 크잖아.

  4. 리스트로 만들자! IX, I, X, 이렇게 의미가 확실히 구분되는 문자들끼리. 아니, 자릿수끼리.

첫번째 방법

by 예랑님.
1. 딕셔너리 정의 : 로마자의 특이한 부분들과, 모든 로마자를 각각 딕셔너리로 만든다.
2. 반복문 : rome_1의 각 문자에 대해서
3. 반복문 안의 반복문 : 해당 문자가 인풋값에 있는 경우에 대해서
4. 딕셔너리 접근 : 여기서 딕셔너리의 키는 곧 로마문자이고 value는 곧 그 문자가 뜻하는 값이므로, 이렇게. (딕셔너리의 items메서드도 알게 됐다. enumerate의 딕셔너리 버전.)
5. += : result에 차곡차곡 그 값을 더한다.
6. replace : 해당 문자를 빈 str값으로 바꾼다. 즉, 없앤다.

  1. 반복문의 순서가 중요하다. 만약 rome_2부터 반복문을 실행한다면 rome_2의 문자들을 찾아볼 수 없음.
  2. 일반적인 문자들에 대해서도 반복문 실행. 앞의 반복문과 비슷하다.
  3. return : 결과값을 반환한다.
def roman_to_num(s):
  result = 0
  rome_1 = {
    ‘IV’: 4, ‘IX’: 9,
    ‘XL’: 40, ‘XC’: 90,
    ‘CD’: 400, ‘CM’: 900,
  }
  rome_2 = {
    ‘I’: 1, ‘V’: 5, ‘X’: 10,
    ‘L’: 50, ‘C’: 100, ‘D’: 500, ‘M’: 1000,
  }
  for rome in rome_1:
    while rome in s:
      result += rome_1[rome]
      s = s.replace(rome, ‘’, 1)
  for rome in rome_2:
    while rome in s:
      result += rome_2[rome]
      s = s.replace(rome, ‘’, 1)
  print(‘result:, result)
  return result

두번째 방법

by (최)준영님.

첫번째 방법과 접근방식이 살짝 다르다. 로마자의 특이한 문자들의 패턴을 읽은 것 같다.

  1. 딕셔너리 정의 : 일반적인 문자들에 대해서만
  2. 반복문 실행 : range(인풋값 길이 -1)에 대해서
  3. 조건문 : 여기서 패턴이 나온다. 해당 문자가 다음 index의 문자보다 작을 경우, 즉 첫번째 방법에서 정의한 rome_1의 문자들의 경우에는 결과값에서 해당 문자의 값을 뺀다.
    아닐경우, 해당 문자의 값을 계속 더해나간다.
  4. 마지막 index의 값을 더한다. (i+1번째로 접근하는 부분이 index error을 야기하기 때문)
  5. return : 결과값 반환
def roman_to_num(s):
  all_roman = {
    "I":1,
    "V":5,
    "X":10,
    "L":50,
    "C":100,
    "D":500,
    "M":1000
  }
  result= 0
  for i in range(len(s) - 1):
    current_one = all_roman[s[i]]
    print(current_one)
    next_one = all_roman[s[i+1]]
    if current_one < next_one:
      result -= current_one
    else:
      result += current_one
  result += all_roman[s[-1]]
  print(result)
  return result

roman_to_num("XXVII")

세번째 방법

by 동명님.

두번째와 접근방식이 비슷하다. 그러나 reversed와 집합을 쓴 점이 다르다.

def roman_to_num(s):
    romans = {
        "I":1,
        "V":5,
        "X":10,
        "L":50,
        "C":100,
        "D":500,
        "M":1000
    }
    seen = set()
    result = 0
    for c in reversed(s):
        if c not in seen:
            seen.add(c)
            if c == "V" or c =="X":
                romans["I"] = -1
            elif c == "L" or c == "C":
                romans["X"] = -10
            elif c == "D" or c == "M":
                romans["C"] = -100
        result += romans[c]
    return result

roman_to_num("XXVII")

생각과 질문

  1. 문제 파악이 문제 해결의 50%를 차지하는 것 같다. 난 로마자 자체를 이상하게 이해해서, 접근방식도 이상해질 수 밖에 없었다.
profile
백엔드 지망 대학생

0개의 댓글