일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
- Android
- androidstudio
- bitmap
- BOJ
- Canvas
- CS
- Database
- DBeaver
- DP
- Ecilpse
- Eclipse
- firebase
- git
- github
- GooglePlayServices
- gradle
- IDE
- IntelliJ
- java
- json
- kotlin
- level2
- linux
- mariadb
- MYSQL
- Paint
- permission
- python
- Sorting
- sourcetree
will come true
[프로그래머스 / Level1] 다트 게임 (Java) 본문
문제
https://programmers.co.kr/learn/courses/30/lessons/17682?language=java
#문자열 처리(String Manipulation) #토큰화(Tokenizing) #의미 분석(Semantic Analysis)
🎯 다트게임 규칙
- 다트판에 다트를 세 차례 던져 그 점수의 합계로 실력을 겨룬다.
- 총 3번의 기회 제공
- 점수 : 0점~10점
- 보너스 : Single(S), Double(D), Triple(T) 영역에 따라 점수^제곱(1, 2, 3)
점수마다 하나씩 존재 - 옵션 : 스타상(*) - 해당 점수와 바로 전에 얻은 점수를 각 2배 (1번째에 나오면 해당 점수만 2배 / 중첩 = 4배),
아차상(#) - 해당 점수 마이너스 (스타상+아차상 중첩 = -2배)
점수마다 둘 중 하나만 존재, 또는 존재하지 않음. - 0~10의정수, 문자 S, T, D, *, # 로 구성된 문자열 3세트에서 총점수 산출
기존 코드 (성공)
class Solution {
public int solution(String dartResult) {
int totalScore = 0;
int[] scores = new int[3];
int turn = 0;
for(int i = 0; i < dartResult.length(); i++){
char ch = dartResult.charAt(i);
if(Character.isDigit(ch)){
if(scores[turn] != 0) {
scores[turn] = 10;
}else{
scores[turn] = ch - '0';
}
}else if(Character.isAlphabetic(ch)){
switch(ch){
case 'D':
scores[turn] = (int)(Math.pow(scores[turn], 2));
break;
case 'T':
scores[turn] = (int)(Math.pow(scores[turn], 3));
break;
}
if(i == dartResult.length() -1){
break;
} else if(Character.isDigit(dartResult.charAt(i+1))){
turn++;
}
}else{
switch(ch){
case '*':
scores[turn] *= 2;
if(turn != 0){ scores[turn-1] *= 2; }
break;
case '#':
scores[turn] *= -1;
break;
}
turn++;
}
}
for(int score : scores){
totalScore += score;
}
return totalScore;
}
}
[점수]
i) 점수가 1자리일 경우(0~9) scores[turn]의 값은 한번 저장된다.
ii) 점수가 2자리일 경우(10) scores[turn]에 값이 저장된 뒤 다음 반복에서도 if(Character.isDigit(ch))에 걸려서 값이 두번 저장되게 된다. (.charAt(int index)로 접근 시 점수가 두자리면 1, 0을 따로 가져오기 때문) 이때 값이 0으로 덮어씌워지는 걸 방지하기 위해 해당 요소에 이미 값이 저장되어 있을 경우 10을 저장한다.
[보너스]
점수|보너스는 필수이나, 옵션은 필수가 아니다. 그렇기 때문에 한 기회의 문자열이
i) S, T로 끝나는 경우, ii) *, #로 끝나는 경우 두 가지로 나뉜다. 각각의 경우에서 다음 기회로 넘어가는 turn++ 처리
[옵션]
스타상일 경우, 기본적으로 현재 점수를 2배로 하고, 지금이 첫번째 시도가 아닐 경우(turn != 0)에만 이전것까지 2배로
개선 코드 (성공)
class Solution {
public int solution(String dartResult) {
int totalScore = 0;
int[] scores = new int[3]; //3번의 기회 각 점수를 저장
int turn = 0;
for(int i = 0; i < dartResult.length(); i++){
char ch = dartResult.charAt(i);
if(Character.isDigit(ch)){
if(scores[turn] != 0) { //해당 기회에 점수가 두번 저장되는 경우는 10뿐.
scores[turn] = 10;
}else{
scores[turn] = ch - '0';
}
}else{
switch(ch){
case 'D':
scores[turn] = (int)(Math.pow(scores[turn], 2));
break;
case 'T':
scores[turn] = (int)(Math.pow(scores[turn], 3));
break;
case '*':
scores[turn] *= 2;
if(turn != 0) { scores[turn-1] *= 2; } //1번째 기회에서는 현재 점수만 2배
break;
case '#':
scores[turn] *= -1;
break;
}
if(i == dartResult.length() -1){ //마지막 문자일 경우 .charAt(i+1) 하면 index넘어감
break;
} else if(Character.isDigit(dartResult.charAt(i+1))){ //다음 문자가 숫자면 이번 기회는 끝인 것
turn++;
}
}
}
for(int score : scores){
totalScore += score;
}
return totalScore;
}
}
기존 코드에서는 1) 숫자일 경우, 2) 알파벳일 경우, 3)숫자도 알파벳도 아닌 경우 세 가지로 분류했었는데, 한 기회의 끝 문자가 보너스(S, T)이거나 옵션(*, #)일 수 있기 때문에 (2), (3) 부분에 모두 다음 기회로 넘어가는 turn++ 코드가 들어갔는데, 두 부분의 처리가 비슷하기 때문에 하나의 블록에서 처리하기로 함. = switch문에서 보너스/옵션 구분
i) 문자열의 마지막 요소일 경우 => 종료
ii) 다음 기회가 남아있을 경우 => 다음 턴으로
학습 내용
//뒤늦게 카카오 공식 문제 해설을 발견했고, 새로운 방법이 있다는 것을 알게되어 학습중
토큰화(Tokenizing)
StringTokenizer
의미 분석(Semantic Analysis)
정규식
- 2018 KAKAO BLIND RECRUITMENT 다트게임 문제,
https://programmers.co.kr/learn/courses/30/lessons/17682?language=java - 카카오 신입 공채 1차 코딩테스트 해설, https://tech.kakao.com/2017/09/27/kakao-blind-recruitment-round-1/
'Algorithm' 카테고리의 다른 글
[프로그래머스 / Level1] 부족한 금액 계산하기 (Java) (0) | 2021.11.01 |
---|---|
[프로그래머스 / Level1] 2016년 (Java) (0) | 2021.10.31 |
[프로그래머스 / Level1] 3진법 뒤집기 (Java) (0) | 2021.10.30 |
[프로그래머스 / Level1] 문자열 다루기 (Java) (0) | 2021.10.30 |
[프로그래머스 / Level1] 소수 찾기 (Java) (0) | 2021.10.30 |