문제 출처 : programmers.co.kr/learn/courses/30/lessons/17682
코딩테스트 연습 - [1차] 다트 게임
programmers.co.kr
1. 문제 이해
다트 게임은 총 3번의 기회로 구성
각 기회마다 얻을 수 있는 점수는 0점에서 10점
점수와 함께 싱글, 더블, 트리플 영역이 존재하고
각 영역 당첨 시 점수에서 1제곱, 2제곱, 3제곱 (점수^1 , 점수^2 , 점수^3 )으로 계산됨
스타상(*) 당첨 시 해당 점수와 바로 전에 얻은 점수를 각 2배 (맨 처음에 나올 경우 첫번째 스타상의 점수만 2배)
아차상(#) 당첨 시 해당 점수는 마이너스
스타상의 효과는 다른 스타상의 효과와 중첩 가능 -> 중첩된 스타상 점수 4배
스타상과 아차상의 효과 중첩 가능 -> 중첩된 아차상의 점수는 -2배
싱글, 더블, 트리플은 점수마다 하나씩 존재
스타상, 아차상은 점수마다 둘 중 하나만 존재할 수 있으며, 존재하지 않을 수도 있음
점수|보너스|옵션으로 이루어진 문자열 3세트가 입력될 시
총 점수를 반환
점수는 0에서 10사이
보너스는 S,D,T중 하나
옵션은 * 또는 # 또는 없음
2. 풀이 계획
뒤에서부터 풀어야할 것 같긴한데 잘 모르겠다.
3. 구현
4. 검토 및 개선
def solution(dartResult):
bonus = {'S' : 1, 'D' : 2, 'T' : 3}
option = {'*' : 2, '#' : -1}
# 각 계산값이 변할 수 있기 때문에 세 분기의 합을 따로 구하기
a = [0, 0, 0] # 맨 처음 배열 초기화
flag = -1 # 배열의 인덱스
for idx, dart in enumerate(dartResult) :
if dart.isdigit() : # isdigit() : 문자열이 숫자인지 판단
flag += 1
if dart == '0' :
continue
elif dartResult[idx + 1].isdigit() : # 점수 10일때 처리
a[flag] = int(dart) * 10
flag -= 1 # 다음 for문 돌 때도 숫자가 있으므로 flag 증가시켜주기때문에 미리 감소시켜줌
else :
a[flag] = int(dart)
elif dart in 'SDT' :
a[flag] **= bonus[dart]
else :
if dart == '*' and flag > 0:
a[flag-1] *= 2
a[flag] *= option[dart]
return sum(a)
출처 : ychae-leah.tistory.com/196?category=332760
c.f. 숫자가 10일때를 처리하기위해 다음과같은 방식을 사용할 수도 있다.
def solution(dartResult):
dartResult = dartResult.replace('10', 'k') # 주의 : replace는 새로운 배열을 반환하므로 저장해줘야한다.
dart = ['10' if i == 'k' else i for i in dartResult]
bonus = {'S' : 1, 'D' : 2, 'T' : 3}
option = {'*' : 2, '#' : -1}
i = -1
answer = [0, 0, 0]
for j in dart :
if j.isdigit() :
i += 1
answer[i] = int(j)
elif j in ('S', 'D', 'T') :
answer[i] **= bonus[j]
elif j in ('*', '#') :
if i > 0 and j == '*':
answer[i-1] *= 2
answer[i] *= option[j]
return sum(answer)
## 정규표현식 이용한 풀이 ##
# 틀린코드 (주의사항)
# 튜플을 변경하고 마지막에 계산하려고했음
import re
def solution(dartResult):
bonus = {'S' : 1, 'D' : 2, 'T' : 3}
option = {'*' : 2, '#' : -1, '' : 1}
p = re.compile('(\d+)([SDT])([*#]?)')
dart = p.findall(dartResult)
print(dart)
for i in range(len(dart)) :
if i > 0 and dart[i][2] == '*' :
dart[i-1][0] = str(int(dart[i-1][0]) * 2) # 튜플은 변경 못함
answer = 0
for d in dart :
answer += int(d[0]) ** bonus[d[1]] * bonus[d[2]]
return answer
# 정규표현식 이용한 풀이
import re
def solution(dartResult):
bonus = {'S' : 1, 'D' : 2, 'T' : 3}
option = {'*' : 2, '#' : -1, '' : 1}
p = re.compile('(\d+)([SDT])([*#]?)')
# 주의: \d는 [0-9]와 동일한 표현식이므로 [] 써줄필요 없음
# 주의: ()안넣어주면 튜플로 반환 안해줌
dart = p.findall(dartResult)
for i in range(len(dart)) :
if i > 0 and dart[i][2] == '*' :
dart[i-1] *= 2 # 이해되지 않았던 부분
dart[i] = int(dart[i][0]) ** bonus[dart[i][1]] * option[dart[i][2]]
return sum(dart)
위의 풀이에서 dart[i-1][2]가 이해되지않았다.
dart는 분명히 [('1', 'S', ''), ('2', 'D', '*'), ('3', 'T', '')] 이런 튜플의 배열일텐데
어떻게 곱하기 연산을 해서 int값이 나올 수 있나했더니
그 다음 줄에 i번째 튜플을 계산한뒤 아예 값으로 치환하기 때문이었다 ...!!!!!!
+) 정규 표현식
정규 표현식(Regular Expressions)은 복잡한 문자열을 처리할 때 사용하는 기법으로,
파이썬만의 고유 문법이 아니라 문자열을 처리하는 모든 곳에서 사용한다. (모든 언어 공통)
※ 정규 표현식은 줄여서 간단히 "정규식"이라고도 말한다.
정규 표현식이 필요한 이유
주민등록번호를 포함하고 있는 텍스트에 포함된 모든 주민등록번호의 뒷자리를 * 문자로 변경하는 코드
# 여러줄로 된 문자열 사용 ('''문자열''' 또는 """문자열""")
data = """
park 800905-1049118
kim 700905-1059119
"""
result = []
for line in data.split("\n"):
word_result = []
for word in line.split(" "): # 전체 텍스트를 공백 문자로 나눈다.
if len(word) == 14 and word[:6].isdigit() and word[7:].isdigit(): # 나뉜 단어가 주민등록번호 형식이면
word = word[:6] + "-" + "*******" # 주민등록번호 뒷자리를 *로 변환한다.
word_result.append(word)
result.append(" ".join(word_result)) # 나뉜 단어를 다시 조립한다.
print("\n".join(result))
# 결과값:
# park 800905-*******
# kim 700905-*******
반면에 정규식을 사용하면 다음처럼 훨씬 간편하고 직관적인 코드를 작성할 수 있다.
만약 찾으려는 문자열 또는 바꾸어야 할 문자열의 규칙이 매우 복잡하다면 정규식의 효용은 더 커지게 된다.
import re
data = """
park 800905-1049118
kim 700905-1059119
"""
pat = re.compile("(\d{6})[-]\d{7}")
print(pat.sub("\g<1>-*******", data))
# 결과값:
# park 800905-*******
# kim 700905-*******
출처 : wikidocs.net/1642
정규표현식은 내용이 너무 많아서 다음 사이트를 참고하는 것이 좋겠다.
정규 표현식 시작하기 - wikidocs.net/4308
위키독스
온라인 책을 제작 공유하는 플랫폼 서비스
wikidocs.net
강력한 정규 표현식의 세계로 - wikidocs.net/4309
위키독스
온라인 책을 제작 공유하는 플랫폼 서비스
wikidocs.net
위의 블로그 내용을 잘 설명해준 동영상 - www.youtube.com/watch?v=dTDoTR0MXjU
'Problem Solving > 프로그래머스' 카테고리의 다른 글
Lv2. 멀쩡한 사각형 [X] (0) | 2020.11.11 |
---|---|
Lv1. 월간 코드 챌린지 시즌1- 내적 [O] (0) | 2020.11.11 |
Lv1. 2019 KAKAO BLIND RECRUITMENT실패율 [XO] (0) | 2020.11.05 |
Lv1. 2018 KAKAO BLIND RECRUITMENT[1차] 비밀지도 [O] (0) | 2020.11.03 |
Lv1. 예산 [O] (0) | 2020.11.03 |
댓글