아침 6시에 일어나 꽉 찬 지하철을 타고 학교에 왔더니 벌써 체력 소진... 피곤하다 ㅠㅠ
프로그래머스 <[1차] 다트 게임> 문제 보기
https://school.programmers.co.kr/learn/courses/30/lessons/17682
프로그래머스
코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.
programmers.co.kr
프로그래머스 <[1차] 다트 게임> 문제 풀이
import math
def solution(dartResult):
answer = 0
tempA = int(dartResult[0])
tempB = 0
for i in range(1, len(dartResult)):
if dartResult[i].isdigit():
if dartResult[i]=='0' and dartResult[i-1]=='1':
tempA *= 10
continue
answer += tempB
tempB = tempA
tempA = int(dartResult[i])
else:
if dartResult[i] == 'S':
continue
if dartResult[i] == 'D':
tempA = pow(tempA, 2)
if dartResult[i] == 'T':
tempA = pow(tempA, 3)
if dartResult[i] == '*':
tempA *= 2
tempB *= 2
if dartResult[i] == '#':
tempA *= -1
answer += tempB
answer += tempA
return answer
문제를 제대로 읽지 않은 탓에 ... 숫자 10을 생각않고 설계해버렸다가 직전에 알아차려 코드를 이상하게 바꿨다. 확장 가능성이 떨어지는 코드라 좋지 않지만 우선은 풀었다는 것에 의의를 두고 다른 코드를 공부하려 마음 먹었다.
우선 처음에는 스택으로 풀까 하다가 그냥 2개의 변수(tempA, tempB)를 사용하기로 했다. [S,D,T], [*,#] 를 체크해주는 건 문제와 다름없고, 다만 i번째의 dartResult가 숫자일 경우 10을 체크하기 위해서 if문을 추가해주었다.
다른 풀이
def solution(dartResult):
point = []
answer = []
dartResult = dartResult.replace('10','k')
point = ['10' if i == 'k' else i for i in dartResult]
print(point)
i = -1
sdt = ['S', 'D', 'T']
for j in point:
if j in sdt :
answer[i] = answer[i] ** (sdt.index(j)+1)
elif j == '*':
answer[i] = answer[i] * 2
if i != 0 :
answer[i - 1] = answer[i - 1] * 2
elif j == '#':
answer[i] = answer[i] * (-1)
else:
answer.append(int(j))
i += 1
return sum(answer)
dartResult에서 10을 찾아 k로 치환했다가 point에 다시 10으로 담아주는 과정을 거침으로써 두자리수인 10을 체크해준다는 점이 인상적인 코드였다. 또, sdt 리스트를 만들어놓고 해당되는 경우에 그 index를 이용해서 제곱수를 만들어주는 것도 인상적이었다.
다른 풀이
import re
def solution(dartResult):
bonus = {'S' : 1, 'D' : 2, 'T' : 3}
option = {'' : 1, '*' : 2, '#' : -1}
p = re.compile('(\d+)([SDT])([*#]?)')
dart = p.findall(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
정규표현식을 사용한 풀이다. 정규표현식은 평소에 잘 사용하지 않아서 어색했는데 다른 분의 블로그를 보며 좀 체득했다.
출처: https://jeonzzang.tistory.com/31
import re를 통해 정규표현식 라이브러리를 사용할 수 있도록 한다.
p = re.compile('(\d+)([SDT])([*#]?)')
\d는 숫자라는 의미고, 뒤에 붙은 +는 숫자가 하나 이상 온다는 뜻이다. 즉, 한자리 혹은 두자리 혹은 세자리 혹은 그 이상을 모두 체크할 수 있는 것이다.
SDT는 말 그대로 S, D, T 중 하나인 것이다.
*# 또한 말 그대로 * 혹은 # 중 하나인 것인데 뒤에 ?가 붙었기 때문에 없을 수도 있다는 뜻이다.
이 외의 기본 패턴은 다음과 같다.
- [abcd]: a or b or c or d
- [0-9]: 모든 숫자
- [a-z]: 모든 소문자
- [A-Z]: 모든 대문자
- [a-zA-Z0-9]: 모든 알파벳 문자 및 숫자
- [^0-9]: ^가 맨 앞에 사용 되는 경우 해당 문자 패턴이 아닌 것과 매칭
- \d: [0-9]와 동일
- \D: 숫자가 아닌 문자 [^0-9]와 동일
- \s: 공백 문자(띄어쓰기, 탭, 엔터 등)
- \S: 공백이 아닌 문자
- \w: 알파벳대소문자, 숫자 [0-9a-zA-Z]와 동일
- '+': 1번 이상의 패턴이 발생
- '*': 0번 이상의 패턴이 발생
- '?': 0 혹은 1번의 패턴이 발생
dart = p.findall(dartResult)
# dartResult = "1D2S#10S"
# dart = [('1', 'D', ''), ('2', 'S', '#'), ('10', 'S', '')]
findall은 dartResult 안에서 p로 미리 정해둔 정규식과 매치되는 모든 문자열을 리스트로 반환해주는 함수다. 예시를 참고하여 이해하면 쉽다. 이 외에도 제공되는 함수들은 아래와 같다.
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]]
이후 if문을 통해 스타상(*) 효과 중 하나인 바로 전에 얻은 점수를 2배로 만드는 과정을 거쳐준다. 그 후에 dart[i]를 문제 조건에 따라 계산한다.
마지막에 sum(dart)를 반환하면 끝!
정규표현식을 알고 나니 내 코드가 한없이 부끄러워졌다. 한두달 뒤쯤 다시 풀어보면 좋을 거 같다.
'알고리즘 공부 > 코딩테스트(프로그래머스)' 카테고리의 다른 글
[프로그래머스 Level 2] 배달 (Python 파이썬) 풀이 방법 (0) | 2023.01.18 |
---|---|
[프로그래머스 Level 2] 피로도 (Python 파이썬) 풀이 방법 (0) | 2023.01.10 |
[프로그래머스 Level 1] 이상한 문자 만들기 (Python 파이썬) 풀이 방법 (0) | 2023.01.07 |
[프로그래머스 Level 2] 이모티콘 할인행사 (Python 파이썬) 풀이 방법 (0) | 2023.01.06 |
[프로그래머스 Level 2] 귤 고르기 (Python 파이썬) 풀이 방법 (1) | 2023.01.05 |