같은 Level 1이었던 비밀지도 편에서는 이렇게 오래걸리지는 않았지만, 다트 게임에서 시간을 오래 쓴 것 같다.
이유는, 조금 더 효율적인 방법이 있을 줄 알았다. 지속적으로 S, D, T에 대해 파악해야 하며, 한번에 들어오는 값에 의해서 숫자를 어떻게 분리할 것인지, option이 나왔을 때에 이전 점수에 대해 어떻게 처리할 것인지, 현재 값을 어떻게 - 시키는지 이런 잡다한 고민들 때문에 시작하기부터 애를 먹었다.
처음부터 비효율적이라고 생각하게 되면 시도조차 하지 않는 성격이기에 노가다성의 알고리즘 문제보다는, 효율적인 알고리즘을 생각해내는 것이 더 어울리는 것 같다. 이 문제가 무작정의 알고리즘 문제는 아니지만, 이해는 나름 쉽지만 구현하는데에 애를 먹기도 하고, 상수처럼 값을 집어넣어 하는 부분이 있다고 생각했기 때문에 그렇게 느꼈던 것 같다.
잡다한 소리는 집어치우고 코딩한 것을 보자.
import java.util.*;
class Solution {
public int solution(String dartResult) {
int answer = 0;
int count = 0;
int[] total = new int[3];
StringBuilder sb = new StringBuilder();
for(int i = 0; i < dartResult.length(); i++) {
char c = dartResult.charAt(i);
if(c == 'S') {
total[count] = Integer.parseInt(sb.toString());
count++;
sb.setLength(0);
} else if(c == 'D') {
int temp = Integer.parseInt(sb.toString());
total[count] = (int) Math.pow(temp, 2);
count++;
sb.setLength(0);
} else if(c == 'T') {
int temp = Integer.parseInt(sb.toString());
total[count] = (int) Math.pow(temp, 3);
count++;
sb.setLength(0);
} else if(c == '*') {
total[count - 1] *= 2;
if(count != 1) {
total[count - 2] *= 2;
}
} else if(c == '#') {
total[count - 1] -= 2 * total[count - 1];
} else {
sb.append(c);
}
}
for(int i = 0; i < 3; i++) {
answer += total[i];
}
return answer;
}
}
해법
먼저 경우의 수를 나누어 보자.
1. S, D, T를 만난 경우 - bonus를 만난 경우
2. *, #을 만난 경우 - option을 만난 경우
3. 그 외
3번의 경우를 먼저 설명하겠다.
3번은 숫자를 만난 경우라고 볼 수 있겠다. 한 자리 숫자만 들어오면 당연히 쉽겠지만, 10이라는 숫자가 포함되어 있을 수 있어 고민을 해야한다. 필자의 경우에는 숫자를 만날 경우에는 StringBuilder에 집어 넣었다.
} else {
sb.append(c);
}
이 부분에 포함된다. 이는 나중에 1번의 경우의 수를 만날 때 숫자로 변환시켜 그 값에다 bonus를 시켜줄 예정이다.
그러면 이제 1번의 경우로 넘어와서 코드를 보겠다.
if(c == 'S') {
total[count] = Integer.parseInt(sb.toString());
count++;
sb.setLength(0);
} else if(c == 'D') {
int temp = Integer.parseInt(sb.toString());
total[count] = (int) Math.pow(temp, 2);
count++;
sb.setLength(0);
} else if(c == 'T') {
int temp = Integer.parseInt(sb.toString());
total[count] = (int) Math.pow(temp, 3);
count++;
sb.setLength(0);
}
S의 경우에는 보너스가 적용되지 않아 바로 integer으로 변환시킨 값을 배열에 넣어주고, D / T의 경우는 해당 보너스 값에 맞게 끔 제곱시킨 뒤에 값을 넣어주었다. count++는 총 3번의 기회가 주어지기 때문에 total[count] 로 활용하여 몇 번째 점수인지 indexing해주는 역할을 한다. 또한 sb.setLength(0)는 StirngBuilder에 있던 숫자들을 초기화시켜준다는 의미로 보면 될 것 같다.
이제 2번이다.
} else if(c == '*') {
total[count - 1] *= 2;
if(count != 1) {
total[count - 2] *= 2;
}
} else if(c == '#') {
total[count - 1] -= 2 * total[count - 1];
}
total[count - 1]의 의미는, S, D, T를 만나게 되면 다음 게임을 가리키게 되는데 갑자기 option을 만나게 되었을 경우 그 이전 게임에 영향을 받게 되므로 -1을 해주었다. 또한 첫번째 게임의 경우에 *을 만나게 되면 그 이전 배열값을 가리키면 안되기 때문에 if로 걸러내야 한다.
#은 해당 게임에만 마이너스로 만들어주면 되므로 if가 없다.
이러한 절차로 인하여 total배열에 모든 값을 넣고 더하여 answer의 값으로 만든다.
'알고리즘 > 프로그래머스' 카테고리의 다른 글
[프로그래머스/JAVA] 프렌즈4블록 - 2018 KAKAO BLIND RECRUITMENT (0) | 2022.01.17 |
---|---|
[프로그래머스/JAVA] 뉴스 클러스터링 - 2018 KAKAO BLIND RECRUITMENT (0) | 2022.01.15 |
[프로그래머스/JAVA] 비밀지도 - 2018 KAKAO BLIND RECRUITMENT (0) | 2022.01.14 |
[프로그래머스/JAVA] N으로 표현 (0) | 2022.01.12 |
[프로그래머스 - 해시] Hash(해시)에 관하여, Hash에 관한 문제들 (0) | 2021.12.19 |