소소한 개발이야기

[Programmers 문제풀이 JAVA] 다트 게임 본문

Programmers

[Programmers 문제풀이 JAVA] 다트 게임

plplim 2019. 6. 24. 20:13

 

📄 다트 게임

🔗 문제 풀러가기


문제는 문자열과 스택의 개념을 이용하여 해결하였습니다. 문제의 조건이 생각보다 많아서 잘 정리하며 문제 풀이를 해야합니다. 먼저 문제의 조건을 살펴보겠습니다.

문제 조건

  1. 다트 게임은 총 3번의 기회로 구성된다.
  2. 각 기회마다 얻을 수 있는 점수는 0점에서 10점까지이다.
  3. 각 점수마다 보너스가 주어진다(S, D, T)
  4. 옵션 스타상과 아차상이 주어지며 각 옵션은 중첩이 가능하다.
    • 스타상 : 해당 점수와 이전 점수를 각 2배로 만든다.(첫 번째 기회에도 나올 수 있다.)
    • 아차상 : 해당 점수는 마이너스가 된다.
  5. 보너스는 각 점수마다 존재하지만 옵션은 존재하지 않을 수 있다.
  6. 옵션은 둘 중 하나만 존재할 수 있다.
  7. 입력은 점수 | 보너스 | [옵션] 으로 주어진다.

문제 풀이

먼저 입력에서 무조건 점수 | 보너스 는 주어지기 때문에 점수에 대한 확인은 하지 않고 보너스(S, D, T)와 옵션을 기준으로 나눌 수 있습니다.

  1. 보너스 조건 확인(S, D, T)
  2. 보너스를 적용 시킬 점수 확인
  3. 옵션이 존재 할 경우 스택에 있는 점수들에 적용

문제에서 주어진 입력에서 보너스를 만났을 경우 앞에 수를 확인하고 해당 보너스에 맞는 점수를 연산해주면 됩니다. 하지만 여기서 주의해야 할 점은 수가 0 또는 10일 때 입니다. 보너스 숫자 앞의 수가 0일 경우 0인지 10인지 확인한 뒤 연산을 해줘야 합니다. 이렇게 연산 된 점수를 스택에 넣습니다. 이 후 옵션이 등장했을 때 옵션에 맞는 연산을 스택에 있는 점수들에 적용시키면 문제를 해결 할 수 있습니다.

예외 처리

문제에서 예외처리 해야 할 사항은 다음과 같습니다.

  1. 연산해야 할 점수가 0또는 10일 경우
  2. 첫 번째 점수에 0점이 나왔을 경우
  3. 첫 번째 기회에 스타상이 나온경우

첫 번째 예외 처리의 경우 주어진 보너스의 index - 1의 문자가 0일 경우 index - 2의 문자가 1인지 확인하면 해결할 수 있습니다.

두 번째 예외 처리의 경우 첫 번째 점수가 0일 경우 10인지 확인하지 않아도 되기 때문에 배열의 인덱스를 벗어나는지 확인하면 해결할 수 있습니다.

세 번째 예외 처리의 경우 점수 스택의 사이즈가 2이상일 경우만 이전 점수에 스타상을 적용시키면 해결할 수 있습니다.

 

글보단 소스코드를 보면 쉽게 이해할 수 있습니다.


🌱 Solution 함수

다트게임 결과를 입력받고 각 점수들을 계산한 뒤 결괏값을 반환하는 함수입니다.

// 전역 변수
private HashMap<Character, Integer> bonusCase;
private String dartBoard;
private NumberStack dartScoresStack;

private static final int NUMBER_TEN= 10;
private static final int NUMBER_ZERO= 0;

public int solution(String dartResult) {
    dartScoresStack = new NumberStackImpl();
    dartBoard = dartResult;

    bonusCase = new HashMap<>();
    bonusCase.put('S', 1);
    bonusCase.put('D', 2);
    bonusCase.put('T', 3);

    for (int i = 0; i < dartResult.length(); i++) {
        solve(dartResult.charAt(i), i);
    }

    return dartScoresStack.totalSum();
}

🌱 solve 함수

다트 게임 결과를 입력받아 보너스와 옵션을 구분해 스택에 저장 및 연산을 호출하는 함수입니다.

private void solve(char ch, int currentIndexOfDartResult) {
    if (ch == 'S' || ch == 'D' || ch == 'T') {
        dartScoresStack.push(calcBonus(ch, currentIndexOfDartResult));
    } else if (ch == '*' || ch == '#') {
        dartScoresStack.calcOption(ch);
    }
}

🌱 calcBonus 함수

보너스 연산을 하는 함수입니다.

private int calcBonus(char ch, int currentIndexOfDartResult) {
    return (int) Math.pow(getNumber(currentIndexOfDartResult), bonusCase.get(ch));
}

🌱 getNumber 함수

보너스 앞의 점수를 반환하는 함수입니다.

private int getNumber(int currentIndexOfDartResult) {
    if (dartBoard.charAt(currentIndexOfDartResult - 1) == '0') {
        if (isPossibleIndex(currentIndexOfDartResult - 2) && isNumberTen(currentIndexOfDartResult - 2)) {
            return NUMBER_TEN;
        }
        return NUMBER_ZERO;
    }
    return dartBoard.charAt(currentIndexOfDartResult - 1) - '0';
}

🌱 isPossibleIndex 및 isNumberTen 함수

isPossibleIndex : 첫 번째 점수가 0일 수 있기 때문에 조건을 확인하는 함수
isNumberTen : 0을 만났을 때 10인지 확인하는 함수

private boolean isPossibleIndex(int index) {
    return index >= 0;
}

private boolean isNumberTen(int index) {
    return dartBoard.charAt(index) == '1';
}

🌱 NumberStack 클래스

연산 결과를 저장하는 스택 클래스 입니다.
연산 결과는 총 3개만 저장되므로 Stack의 사이즈는 3으로 초기화합니다.

interface NumberStack {
    void push(int score);
    int totalSum();
    void calcOption(char option);
}

class NumberStackImpl implements NumberStack {

    private int[] scores = new int[3];
    private int index = 0;

    public NumberStackImpl() {
    }

    @Override
    public void push(int score) {
        scores[index++] = score;
    }

    @Override
    public int totalSum() {
        int sum = 0;
        for (int i = 0; i < index; i++) {
            sum += scores[i];
        }
        return sum;
    }

    @Override
    public void calcOption(char option) {
        if (option == '*') {
            calcStar();
        } else {
            calcAhcha();
        }
    }

    private void calcStar() {
        scores[index - 1] *= 2;
        if (index >= 2) scores[index -2] *= 2;
    }

    private void calcAhcha() {
        scores[index - 1] *= (-1);
    }
}

💡 Github에 더 많은 문제 풀이가 있습니다.

Programmers 문제 풀이

BaekJoon Online Judge 문제 풀이

Comments