문제 보기 · 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. 조각으로 나눈다: (1, D, 없음), (2, S, #), (10, S, 없음)
  2. 영역: 1² = 1, 2¹ = 2, 10¹ = 10
  3. 옵션: 두 번째의 #로 2 → −2
  4. 합: 1 − 2 + 10 = 9

10이 두 글자라는 점을 놓치면 조각이 어긋난다.

2단계 · 가장 단순한 방법과 그 속도

문자열이 아주 짧아서(조각 세 개) 속도는 문제가 되지 않는다. 어려운 곳은 두 군데다. 조각을 정확히 나누는 것, 그리고 *가 앞 점수까지 바꾼다는 규칙이다.

3단계 · 핵심 아이디어
  • 나누기: 정규 표현식 (\d+)([SDT])([*#]?)로 조각 세 개를 한 번에 꺼낸다. \d+가 10을 한 조각으로 잡는다.
  • 점수 기록: 계산한 점수를 리스트 scores에 차례로 넣는다. 그러면 “바로 앞 점수”는 늘 scores[-1]이다. *가 나오면 그 자리의 값을 두 배로 고치면 된다.
  • 겹침은 저절로 처리된다: *가 두 번 이어지면 앞 점수는 두 번 두 배가 되어 4배다. #로 음수가 된 점수에 나중 *가 오면 −2배다. 규칙대로 곱하기만 하면 따로 처리할 필요가 없다.
4단계 · 코드 흐름
  1. 영역별 거듭제곱 표 {"S": 1, "D": 2, "T": 3}을 만든다.
  2. 조각마다 점수 = 점수 ** 거듭제곱.
  3. 옵션이 *면 이번 점수를 두 배로 하고, 앞 점수가 있으면 그것도 두 배로 한다.
  4. 옵션이 #면 이번 점수를 음수로 한다.
  5. 이번 점수를 scores에 넣는다.
  6. 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. 프로그래머스 스쿨, “[1차] 다트 게임” (https://school.programmers.co.kr/learn/courses/30/lessons/17682), 2026-09-30 조회. ↩