소소한 개발이야기
[Programmers 문제풀이 JAVA] 다트 게임 본문
📄 다트 게임
🔗 문제 풀러가기
문제는 문자열과 스택의 개념을 이용하여 해결하였습니다. 문제의 조건이 생각보다 많아서 잘 정리하며 문제 풀이를 해야합니다. 먼저 문제의 조건을 살펴보겠습니다.
문제 조건
- 다트 게임은 총 3번의 기회로 구성된다.
- 각 기회마다 얻을 수 있는 점수는 0점에서 10점까지이다.
- 각 점수마다 보너스가 주어진다(S, D, T)
- 옵션 스타상과 아차상이 주어지며 각 옵션은 중첩이 가능하다.
- 스타상 : 해당 점수와 이전 점수를 각 2배로 만든다.(첫 번째 기회에도 나올 수 있다.)
- 아차상 : 해당 점수는 마이너스가 된다.
- 보너스는 각 점수마다 존재하지만 옵션은 존재하지 않을 수 있다.
- 옵션은 둘 중 하나만 존재할 수 있다.
- 입력은 점수 | 보너스 | [옵션] 으로 주어진다.
문제 풀이
먼저 입력에서 무조건 점수 | 보너스 는 주어지기 때문에 점수에 대한 확인은 하지 않고 보너스(S, D, T)와 옵션을 기준으로 나눌 수 있습니다.
- 보너스 조건 확인(S, D, T)
- 보너스를 적용 시킬 점수 확인
- 옵션이 존재 할 경우 스택에 있는 점수들에 적용
문제에서 주어진 입력에서 보너스를 만났을 경우 앞에 수를 확인하고 해당 보너스에 맞는 점수를 연산해주면 됩니다. 하지만 여기서 주의해야 할 점은 수가 0 또는 10일 때 입니다. 보너스 숫자 앞의 수가 0일 경우 0인지 10인지 확인한 뒤 연산을 해줘야 합니다. 이렇게 연산 된 점수를 스택에 넣습니다. 이 후 옵션이 등장했을 때 옵션에 맞는 연산을 스택에 있는 점수들에 적용시키면 문제를 해결 할 수 있습니다.
예외 처리
문제에서 예외처리 해야 할 사항은 다음과 같습니다.
- 연산해야 할 점수가 0또는 10일 경우
- 첫 번째 점수에 0점이 나왔을 경우
- 첫 번째 기회에 스타상이 나온경우
첫 번째 예외 처리의 경우 주어진 보너스의 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' 카테고리의 다른 글
[Programmers 문제풀이 JAVA] Level 2 위장 (0) | 2019.06.06 |
---|---|
[Programmers 문제풀이 JAVA] Level 5 비밀지도 (2017 카카오 블라인드) (0) | 2019.06.06 |
[Programmers 문제풀이 JAVA] Level 2 가장 큰 수 (0) | 2019.06.05 |
[Programmers 문제풀이 JAVA] Level 2 전화번호 목록 (0) | 2019.06.02 |
[Programmers 문제풀이 JAVA] Level 2 더 맵게 (0) | 2019.05.30 |