문제 보기 · Level 1 · 2018 KAKAO BLIND RECRUITMENT (1차) · 정답률 61% · 푼 사람 33,344명 (2026-09-30 기준)1
문제
다트를 세 번 던진 결과가 "1S2D*3T" 같은 문자열로 주어진다. 한 번의 결과는 점수(0~10), 영역, 옵션 순이다. 영역 S·D·T는 점수를 1·2·3제곱한다. 옵션 *는 이번 점수와 바로 앞 점수를 두 배로, #는 이번 점수를 음수로 만든다. 옵션은 없을 수도 있다. 총점을 돌려준다.
*가 첫 번째에 나오면 첫 점수만 두 배다*끼리 겹치면 4배,*와#가 겹치면 −2배다
풀이
막히면 한 단계씩 펼친다.
필요한 개념
문자열 파싱과 정규 표현식: 문자열을 “점수·영역·옵션” 조각 세 개로 나누기. 개념 문서의 예시가 바로 이 모양이다.
1단계 · 작은 예로 손으로 풀기
"1D2S#10S"
- 조각으로 나눈다: (1, D, 없음), (2, S, #), (10, S, 없음)
- 영역: 1² = 1, 2¹ = 2, 10¹ = 10
- 옵션: 두 번째의
#로 2 → −2 - 합: 1 − 2 + 10 = 9
10이 두 글자라는 점을 놓치면 조각이 어긋난다.
2단계 · 가장 단순한 방법과 그 속도
문자열이 아주 짧아서(조각 세 개) 속도는 문제가 되지 않는다. 어려운 곳은 두 군데다. 조각을 정확히 나누는 것, 그리고 *가 앞 점수까지 바꾼다는 규칙이다.
3단계 · 핵심 아이디어
- 나누기: 정규 표현식
(\d+)([SDT])([*#]?)로 조각 세 개를 한 번에 꺼낸다.\d+가 10을 한 조각으로 잡는다. - 점수 기록: 계산한 점수를 리스트
scores에 차례로 넣는다. 그러면 “바로 앞 점수”는 늘scores[-1]이다.*가 나오면 그 자리의 값을 두 배로 고치면 된다. - 겹침은 저절로 처리된다:
*가 두 번 이어지면 앞 점수는 두 번 두 배가 되어 4배다.#로 음수가 된 점수에 나중*가 오면 −2배다. 규칙대로 곱하기만 하면 따로 처리할 필요가 없다.
4단계 · 코드 흐름
- 영역별 거듭제곱 표
{"S": 1, "D": 2, "T": 3}을 만든다. - 조각마다 점수 = 점수 ** 거듭제곱.
- 옵션이
*면 이번 점수를 두 배로 하고, 앞 점수가 있으면 그것도 두 배로 한다. - 옵션이
#면 이번 점수를 음수로 한다. - 이번 점수를
scores에 넣는다. scores의 합을 돌려준다.
5단계 · 파이썬 코드
import re
def solution(dartResult):
power = {"S": 1, "D": 2, "T": 3}
scores = []
for num, bonus, opt in re.findall(r"(\d+)([SDT])([*#]?)", dartResult):
s = int(num) ** power[bonus]
if opt == "*":
s *= 2
if scores: # 첫 번째 기회면 앞 점수가 없다
scores[-1] *= 2
elif opt == "#":
s = -s
scores.append(s)
return sum(scores)
re.findall이 돌려주는 것은('1', 'S', '')같은 글자 세 개짜리 묶음이다. 그래서for num, bonus, opt in ...으로 나눠 받는다. 옵션이 없으면 빈 문자열''이다.int(num) ** power[bonus]: 글자를 수로 바꾼 뒤 거듭제곱한다.scores[-1] *= 2: 리스트에 이미 넣은 앞 점수를 그 자리에서 고친다.
정규 표현식 없이 한 글자씩 읽는 방법은 개념 문서의 “방법 2”를 그대로 쓰면 된다.
6단계 · 실행 추적
"1S*2T*3S"
| 조각 | 이번 점수 | 옵션 처리 | scores |
|---|---|---|---|
| (1, S, *) | 1¹ = 1 | 두 배 → 2, 앞 점수 없음 | [2] |
| (2, T, *) | 2³ = 8 | 두 배 → 16, 앞 점수 2 → 4 | [4, 16] |
| (3, S, 없음) | 3¹ = 3 | [4, 16, 3] |
합은 23이다. 첫 점수 1은 두 번의 *를 받아 4배(= 4)가 되었다.
7단계 · 복잡도와 흔한 실수
문자열 길이 L만큼 읽으니 \(O(L)\)이다.
- 점수를 한 글자씩 읽어 10을 1과 0으로 나눈다.
*에서 앞 점수를 고치지 않거나, 첫 조각에서 없는 앞 점수를 고치려다 오류가 난다.- 조각을 다 모은 뒤 나중에 옵션을 적용하면서 곱할 대상을 헷갈린다. 조각을 읽을 때마다 바로 적용하면 단순하다.
검증: 문제의 예시 7개를 통과했고, 무작위 입력 3,000개에서 “한 글자씩 읽고, 조각마다 배수 리스트를 따로 곱하는” 다른 풀이와 결과가 같았다 — 06_pg17682_p1.py
-
프로그래머스 스쿨, “[1차] 다트 게임” (https://school.programmers.co.kr/learn/courses/30/lessons/17682), 2026-09-30 조회. ↩