본문 바로가기

Algorithm & Data Structure

2018 KAKAO BLIND RECRUITMENT [1차] 다트게임 with python

요즘 취업에서는 '코딩 테스트는 중요하다' 라는 소리는 강조가 부족할 정도 입니다.
프로그래머스 1단계 문제들을 해설해보려고 합니다.
항상 머릿속에 이렇게 하면 되겠지 하고 떠오르는데, 코드로 작성하려니 헷갈리기도 하네요.
오늘 1단계로 가볍게 머리도 쓰면서 재밌게 풀었던 카카오 블라인드 1차 문제로 나왔던
다트게임을 풀어볼게요.
문제설명

출처 : 프로그래머스 1단계 [1차]다트게임 https://programmers.co.kr/learn/courses/30/lessons/17682

지문 이해
되게 복잡하네요.ㅎㅎ
문제를 풀기위해서는 먼저 문제를 이해하는게 중요합니다. 어떻게 풀것인가 이겠죠!!

1. 다트를 던질 기회는 3번이 있다.
2. 점수는 Single, Double, Triple로 나뉜다
3. 옵션은 [ *, # ] 이 있어서, [ * ]은 첫 번째기회에 오면 첫 번째 점수에 2배만, 두 번째 세 번째 오면 해당 점수와
   이전 얻은 점수에 각각 2배씩, [ # ]은 -1배를 해주면 된다.
4. 중첩이 허용되어서 [ * ]가 나왔는데 다음번에 [ * ] 또 나오면 이전 점수에 2배를 추가한다.
   ( 즉 옵션은 중첩이 가능하다는 소리 )

저는 이렇게 이해를 하고 시작했습니다.

 

이제 어떻게 풀것인가?

3개의 리스트에 문자열을 처리해서 인덱싱해서 풀까?

이전 점수에 영향을 줘야 하니깐 스택을 쓸까?

정규식으로 풀 수도 있으려나요?

 

이제는 방향을 정해야 합니다. 저는 문자열 처리를 해서 풀어보려고 했습니다.

 

문제풀이 해설
def solution(dartResult):
    answer = []
    # 점수리스트
    score = ['S', 'D', 'T']

    # 점수가 10점이 들어올경우 A로 바꿈
    dartResult = dartResult.replace('10', 'A')

    # 리스트컴프리헨션을 이용하여 문자열을 차례대로 탐색하여 A면 '10'으로 반환
    # 아니면 그대로 반환 (문자열을 리스트로 변환)
    dart = ['10' if i == 'A' else i for i in dartResult]

    # 이전에 얻은점수를 조회하기 위해 index로 사용
    i = -1
    print('dart : ',  dart)

    # 문자열 리스트 완전탐색
    for j in dart:
        # 점수리스트에 있는 문자인지 검사 ( 만약 SDT중 하나면 )
        if j in score:
            # 가장 최근에 얻은 점수에 S의 index는 0, D의 index는 1, T의 index는 2
            # S면 1제곱, D면 2제곱, T면 3제곱
            answer[i] = answer[i] ** (score.index(j) + 1)
        # 만약 *문자열이면
        elif j == '*':
            # 해당 점수에 2배
            answer[i] = answer[i] * 2
            # 만약 첫번째 점수가 아니라면 이전 점수에 2배
            if i != 0:
                answer[i - 1] = answer[i - 1] * 2
        # 만약 #문자열 이라면
        elif j == '#':
            # 해당 점수에 -1배
            answer[i] = answer[i] * (-1)
        else:
            # 문자열이 점수라면 리스트에 추가 (맨처음에 나오는 점수는 바로 추가)
            answer.append(int(j))
            # 다음 인덱스로 넘어가기위해 +1 (처음 점수가 들어가고 나면 index는 0부터 시작
            i += 1
    print(answer)
    return sum(answer)

 

모범풀이 해설

문제를 풀고 다른 분들은 어떻게 풀었는지 확인 해봤습니다.

정규표현식으로 아주 쉽게 푼 코드가 있어서 추가적으로 해설을 달아보았습니다.

import re
def solution3(d):
    # 점수와 옵션은 딕셔너리로 변환
    bonus = {'S' : 1, 'D': 2, 'T': 3}
    option = {'': 1, '*': 2, '#': -1}
    answer = []

    # (\d+) : 정수 (10이상도 찾아줌)
    # ([SDT]) : 'SDT' 인 문자
    # ([*#]?) : '*#' 문자를 찾는데, ? -> 없으면 '' 반환
    # 정규표현식을 이용하여 튜플로 묶어서 리스트로 변환
    p = re.compile('(\d+)([SDT])([*#]?)')
    dart = p.findall(d) # 입력값이 d = '1S2D*10T' 일때
    print(dart)         # [('1', 'S', ''), ('2', 'D', '*'), ('10', 'T', '')] 으로 리스트가 생성됨
    # 3개의 리스트 완전탐색
    for i in dart:
       # 2 index의 옵션이 [ * ]이고 다트를 던진횟수가 1번이상이면
        if i[2] == '*' and len(answer) > 0:
            # 이전에 얻은 점수에 2배
            answer[-1] *= 2
        # 다트점수 + 보너스점수 + 옵션 연산
        answer.append(int(i[0]) ** bonus[i[1]] * option[i[2]])
    return sum(answer)

문제를 풀고 나서 다른 분들이 푸신 코드를 보면서 문제를 푸는 방법은 무궁무진하구나라고 느끼게 되었네요.

알고리즘을 열심히 공부해야겠습니다.

궁금한 사항 있으시면 추가 댓글 주시면 답글 드리겠습니다.