PROGRAMMERS Python Lv1. 다트게임

1 분 소요

이번 문제는 다트게임이다.

정답 코드는 다음과 같다.

def solution(dartResult):
    answer = 0
    for idx in range(1, len(dartResult)):
        if dartResult[idx] == "S":
            if idx+1 != len(dartResult):
                if dartResult[idx+1] == "*":
                    answer += (int(dartResult[idx-1])^1) * 2
                elif dartResult[idx+1] == "#":
                    answer += (int(dartResult[idx-1])^1) * (-1)
                else:
                    answer += int(dartResult[idx-1])^1
            else:
                answer += int(dartResult[idx-1])^1
        elif dartResult[idx] == "D":
            if idx+1 != len(dartResult):
                if dartResult[idx+1] == "*":
                    answer += (int(dartResult[idx-1])^2) * 2
                elif dartResult[idx+1] == "#":
                    answer += (int(dartResult[idx-1])^2) * (-1)
                else:
                    answer += int(dartResult[idx-1])^2
            else:
                answer += int(dartResult[idx-1])^2
        elif dartResult[idx] == "T":
            if idx+1 != len(dartResult):
                if dartResult[idx+1] == "*":
                    answer += (int(dartResult[idx-1])^3) * 2
                elif dartResult[idx+1] == "#":
                    answer += (int(dartResult[idx-1])^3) * (-1)
                else:
                    answer += int(dartResult[idx-1])^3
            else:
                answer += int(dartResult[idx-1])^3
        else:
            pass
    return answer

처음에 나는 위의 코드처럼 문제에 접근했었다. 결과는 당연히 실패였고, 코드 실행 결과 중 단 하나만 맞췄다.
내가 생각했던 방식은 우선 주어진 리스트를 하나씩 읽어 들여서,
알파벳을 기준으로 구분 하려했다. 알파벳이 아닐 경우는 pass 시키고 각각의 알파벳일 때, 두 가지로 나눴다.
하나는 알파벳 뒤에 *나 #가 따라올 경우, 하나는 아무것도 없이 알파벳만 있을 경우이다.

그렇지만 여기서 내가 고려하지 못한 것은 10과 같이 2자리 점수일 경우이다. 또한 이 코드가 다른 테스트들에서 거의 제대로 작동하지 않았던 것도 문제였다.

그래서 정규표현식을 활용한 정답을 분석하고, 다시 한번 리뷰해보려고 한다.

정규 표현식 정답

import re

def solution(dartResult):
  bonus = {'S' : 1, 'D' : 2, 'T' : 3}
  option = {'' : 1, '*' : 2, '#' : -1}
  p = re.compile('(\d+)([SDT])([*#]?)')
  dart = p.findfall(dartResult)
  for i in range(len(dart)):
    if dart[i][2] == '*' and i > 0:
      dart[i-1] *= 2
    dart[i] = int(dart[i][0]) ** bonus[dart[i][1]] * option[dart[i][2]]

   answer = sum(dart)
   return answer

우선 정규표현식 사용을 위해 re를 import 시켜준다. 여기선 알파벳과 보너스 기호를 각각 dictionary로 만들어줬다.

p = re.compile('(\d+)([SDT])([*#]?)')

위 코드는 p에 re.compile의 결과를 돌려주는 것이다. \d는 숫자와 매치한다는 것이고 +는 한번 이상 매치한다는 의미이다. [SDT] 는 각각의 문자와 매칭한다는 것이고,
[*#]?는 ?가 붙어 있어 * 혹은 #이 포함될 수도 아닐 수도 있다는 것이다.

findfall은 정규식과 매치되는 모든 문자열(substring)을 리스트로 돌려준다.

예시 1번으로 주어진 것과 같이 1S2D*3T가 주어지면

dart = p.findfall(dartResult)는

[[“1”,”S”,””],[“2”,”D”,”*”],[“3”,”T”,””]] 과 같이 나타난다.

따라서, 2차원의 리스트로 되어 있으므로,

dart의 원소들을 숫자로 변환해준 후 sum함수를 통해 더해주면 된다.

이 코드는 사실 다시 내가 작성해서 풀기는 매우 어려울 것 같다고 느껴졌다.

그러나, spark를 배우고 있고, 정규표현식을 많이 사용해서

정규표현식에 대한 공부를 더 할 필요는 있을 것 같다.

댓글남기기