코테/lvl1

프로그래머스 1차다트 게임(lvl1) 풀어보기

디비드킴 2026. 10. 5. 16:42

문제링크

https://school.programmers.co.kr/learn/courses/30/lessons/17682

 

프로그래머스

SW개발자를 위한 평가, 교육의 Total Solution을 제공하는 개발자 성장을 위한 베이스캠프

programmers.co.kr


문제 핵심

  1. 다트 게임은 총 3번의 기회로 구성된다.
  2. 각 기회마다 얻을 수 있는 점수는 0점에서 10점까지이다.
  3. 점수와 함께 Single(S), Double(D), Triple(T) 영역이 존재하고 각 영역 당첨 시 점수에서 1제곱, 2제곱, 3제곱 (점수1 , 점수2 , 점수3 )으로 계산된다.
  4. 옵션으로 스타상(*) , 아차상(#)이 존재하며 스타상(*) 당첨 시 해당 점수와 바로 전에 얻은 점수를 각 2배로 만든다. 아차상(#) 당첨 시 해당 점수는 마이너스된다.
  5. 스타상(*)은 첫 번째 기회에서도 나올 수 있다. 이 경우 첫 번째 스타상(*)의 점수만 2배가 된다. (예제 4번 참고)
  6. 스타상(*)의 효과는 다른 스타상(*)의 효과와 중첩될 수 있다. 이 경우 중첩된 스타상(*) 점수는 4배가 된다. (예제 4번 참고)
  7. 스타상(*)의 효과는 아차상(#)의 효과와 중첩될 수 있다. 이 경우 중첩된 아차상(#)의 점수는 -2배가 된다. (예제 5번 참고)
  8. Single(S), Double(D), Triple(T)은 점수마다 하나씩 존재한다.
  9. 스타상(*), 아차상(#)은 점수마다 둘 중 하나만 존재할 수 있으며, 존재하지 않을 수도 있다.

0~10의 정수와 문자 S, D, T, *, #로 구성된 문자열이 입력될 시 총점수를 반환하는 함수를 작성하라.


알고리즘

1.숫자,제곱,옵션 리스트로 분리

2.리스트순회하며 문제 조건에 맞게 시행


코드

public static int solution(String dartResult) {
        int answer = 0;
        List<String[]> arr = new ArrayList<>();
        int nc = 0;

        for (int i = 0; i < dartResult.length(); i++) {
            char c = dartResult.charAt(i);
            String key;

            if (Character.isDigit(c)) {
                if (i + 1 < dartResult.length()
                        && Character.isDigit(dartResult.charAt(i + 1))) {

                    key = "" + c + dartResult.charAt(i + 1);
                    i++;
                } else {
                    key = String.valueOf(c);
                }

                arr.add(new String[] { key, "num" });
                nc++;

            } else if (c == 'S' || c == 'D' || c == 'T') {
                arr.add(new String[] { String.valueOf(c), "act" });

            } else {
                arr.add(new String[] { String.valueOf(c), "option" });
            }
        }
        System.out.println(
                arr.stream()
                        .map(Arrays::toString)
                        .toList());
        int nowN = 0;
        int[] nums = new int[nc];
        int index = 0;
        for (String[] item : arr) {
            String key = item[0];
            String value = item[1];

            if (value.equals("num")) {
                nowN = Integer.parseInt(key);

            } else if (value.equals("act")) {
                switch (key) {
                    case "S":
                        nowN = (int) Math.pow(nowN, 1);
                        break;

                    case "D":
                        nowN = (int) Math.pow(nowN, 2);
                        break;

                    case "T":
                        nowN = (int) Math.pow(nowN, 3);
                        break;
                }

                nums[index] = nowN;
                index += 1;

            } else {
                switch (key) {
                    case "*":
                        nums[index - 1] *= 2;

                        if (index - 2 >= 0) {
                            nums[index - 2] *= 2;
                        }
                        break;

                    case "#":
                        nums[index - 1] *= -1;
                        break;
                }
            }

            System.out.println("key: " + key + " / value: " + value);
        }
        System.out.println(Arrays.toString(nums));
        answer = Arrays.stream(nums).sum();
        System.out.println(answer);
        return answer;
    }

 


결과

 


gpt피드백

1. 알고리즘 평가

논리적으로 정확해.

특히 잘 처리한 부분은 10을 한 숫자로 묶은 것과 *에서 현재 점수뿐 아니라 직전 점수까지 수정한 부분이야.

알고리즘 개선점

가장 큰 개선점은 굳이 파싱 결과를 전부 저장했다가 다시 읽을 필요가 없다는 것이야.

2. 코드 평가

평가

현재 코드의 장점은 단계가 눈에 잘 보인다는 것이야.

개선점 1 — List<String[]> arr 제거

가장 큰 부분.

List<String[]> arr = new ArrayList<>();

문자열을 이미 한 번 읽었는데 정보를 저장하고 다시:

for (String[] item : arr)

로 읽고 있어.

한 번의 반복문에서 처리 가능해.


개선점 2 — nc 필요 없음

다트 게임은 항상 3번의 기회가 주어지니까:

int nc = 0;
...
nc++;
...
int[] nums = new int[nc];

까지 할 필요 없이:

int[] nums = new int[3];

이면 돼.


개선점 3 — Math.pow() 불필요

현재:

nowN = (int) Math.pow(nowN, 2);

Math.pow()는 double을 반환해서 다시 (int) 캐스팅하고 있어.

이 문제는 지수가 1, 2, 3밖에 없으니까:

case 'S':
    break;
case 'D':
    nowN *= nowN;
    break;
case 'T':
    nowN = nowN * nowN * nowN;
    break;

로 충분해.


개선점 4 — "num", "act", "option" 문자열 비교 제거

현재:

if (value.equals("num"))
else if (value.equals("act"))
else

이건 네가 중간 파싱 자료구조를 만들었기 때문에 필요한 코드야.

직접 char를 판별하면 필요 없어져.

Character.isDigit(c)

c == 'S' || c == 'D' || c == 'T'

c == '*' || c == '#'
 
 
 

후기

옵션많아서 귀찮은 문제였다