[1차] 다트 게임
문제 분석
자세한 내용은 위의 링크를 참조.
- 문자열
dartResult
가 주어진다.
S, D, T
중 1개씩 총 3개를 포함한다.S
: 점수의 1승D
: 점수의 2승T
: 점수의 3승
0~10
까지 점수 중 1개씩 총 3개를 포함한다.
- ,
#
중 1개씩 총 3개를 랜덤으로 포함한다. - : 해당 점수 2배, 이전 점수 2배
#
: 점수를 음수로 변경
- 얻은 점수를 리턴하라.
ex)
dartResult = "1S2D*3T"
1. 첫 번째 점수 :
점수
: 1, 보너스
: S, 옵션
: 없음2. 두 번째 점수 :
점수
: 2, 보너스
: D, 옵션
: *3. 세 번째 점수 :
점수
: 3, 보너스
: T, 옵션
: 없음dartResult = "1S*2T*3S"
1. 첫 번째 점수 :
점수
: 1, 보너스
: S, 옵션
:2. 두 번째 점수 : 점수
: 2, 보너스
: T, 옵션
:3. 세 번째 점수 : 점수
: 3, 보너스
: S, 옵션
: 없음입출력 예제
풀이 과정
코딩 테스트에서 흔히 볼 수 있는 첫 번째 문제 유형이다.
보통 첫 번째 유형으로 문자열 가공 문제가 많이 제출되는 것 같다.
문자열 가공 로직이 중요하다.
어떻게 문자열을 요리할 것인가? 그것이 나의 접근 방식이다.
🎯 문자열 가공
해당 문제는 항상 등장하는
보너스
및 점수
를 기준으로 문자열을 나눌 수 있을 것 같다.옵션
은 등장할 수도, 안 할 수도 있다. 그래서 옵션
을 기준으로는 나눌 수 없다.보너스
와 점수
중 어느 문자를 기준으로 문자열을 나눌 것인가?점수
의 length
는 1
아니면 2
다. (0점 ~ 10점)보너스
는 항상 S
, D
, T
중 하나일 것이다.length
기준이 S, D, T
보다 번거롭다.보너스
를 기준으로 문자열을 나눈 뒤, 점수
를 계산하고 옵션
을 계산한다.문자열을 담을 배열을 선언한다.
총 3번의 기회이므로 사이즈는
3
점수
, 보너스
, 옵션
총 3가지의 배열 선언int[] point = new int[3]; // 점수를 담을 배열 String[] bonus = new String[3]; // 보너스를 담을 배열 String[] option = new String[3]; // 옵션을 담을 배열
🎯 S, D, T 로 문자열을 나누기
주어질
dartResult
이 어떤 문자열(값)을 가지고 있을지 모르지만,점수
, 보너스
는 확실히 있다.그 중에서도
보너스(S, D, T)
를 기준으로 문자열을 자르자.int index = 0; // 배열 인덱스 String inputPoint = ""; // 추가할 점수 for (int i = 0; i < dartResult.length(); i++) { char check = dartResult.charAt(i); // 하나씩 잘라서, if (check == 'S' || check == 'D' || check == 'T') { // S, D, T 중 하나라면 point[index] = Integer.parseInt(inputPoint.replaceAll("[#*]", "")); // point에 점수 추가! bonus[index++] = String.valueOf(check); // 보너스에 S, D, T 중 하나 추가! , 배열 인덱스 증가 inputPoint = ""; // 추가할 점수 문자열 초기화 continue; // 아래 로직 스킵 } inputPoint += check; // S, D, T 가 아니라면 점수다. }
charAt()
으로 잘라낸 문자가 만약 S, D, T
중 하나라면 각 배열에 추가해준다.그게 아니라면
String inputPoint
에 더해주게 되는데S, D, T
가 아니라면 점수
거나 옵션
일테고 inputPoint
에 값이 할당된다.예시로
"1S2D*3T"
가 주어진다면,처음
S
가 등장하는 시점에 String inputPoint
는 "1"
이 될 것이다.다시
if
문 로직으로 돌아가서,점수만 체크하기 위해
inputPoint.replaceAll()
로 옵션들을 제거해준뒤int point[]
배열에 추가해준다.String bonus[]
배열도 마찬가지로 추가해준다. (.charAt()
자체가 S, D, T
중 하나)String inputPoint
의 문자열을 초기화해준뒤 continue
를 실행해 다음 로직을 스킵해준다.🎯 가지고 있는 배열로 먼저 계산
점수와 보너스를 얻었기 때문에 먼저 계산해보자.
첫 번째 점수 =
point[0] * bonus[0]
두 번째 점수 =
point[1] * bonus[1]
세 번째 점수 =
point[2] * bonus[2]
만약,
bonus[] == 'S'
라면 point[] * 1
(point[]
의 1승)bonus[] == 'D'
라면 point[] * point[]
(point[]
의 2승)bonus[] == 'T'
라면 point[] * point[] * point[]
(point[]
의 3승)for (int i = 0; i < point.length; i++) { if (bonus[i].equals("D")) { point[i] = point[i] * point[i]; } if (bonus[i].equals("T")) { point[i] = point[i] * point[i] * point[i]; } }
S
1승은 할 필요 없다.D, T
만 계산해주자.🎯 옵션을 체크해보자
보너스는 항상 등장,
length
는 1
이다. (S
, D
, T
)점수도 항상 등장,
length
1
or 2
다. (0
~ 10
)옵션은 등장할 수도, 안 할수도..
1S1D1T
가 주어질 수도, 10S*10D*10T*
가 주어질 수도 있다.특정 위치에 고정적으로 옵션이 등장하지 않으므로
문자열의
최소 렝스와 최대 렝스
를 따지면 계산이 조금 번거로워진다.첫 번째 옵션과 마지막 옵션을 기준으로 체크하고 그 외에 위치는 두 번째 옵션으로 본다.
for (int i = 0; i < dartResult.length(); i++) { char check = dartResult.charAt(i); // 하나씩 문자로 잘라서 if (check == '*' || check == '#') { // 옵션이라면, if (i < 3) option[0] = String.valueOf(check); // 첫번째 옵션 등장 규칙 else if (i == dartResult.length() - 1) option[2] = String.valueOf(check); // 마지막 옵션 등장 규칙 else option[1] = String.valueOf(check); // 그 외 등장은 항상 두 번째 옵션 } }
옵션이 아예 없는 최소
length
든,10점이면서
옵션
이 전부 등장하는 최대 length
든(ex.
1S1D1T
, 10S*10D*10T*
)첫 번째 옵션 등장 위치는 항상
3미만
이다.세 번째 옵션 등장 위치는 항상
마지막 렝스
다.두 번째 옵션 등장 위치는 위의 둘이 아니면 맞다.
🎯 옵션을 계산하자
옵션
이 비어있다면 스킵,그게 아니라면 주어진 문제에 따라 계산해주자.
#
은 점수를 음수로 바꿔주는 것.- 은 해당 점수를 2배로, 그 앞의 점수도 2배로.
for (int i = 0; i < option.length; i++) { if (option[i] == null) continue; if (option[i].equals("#")) { point[i] -= point[i] * 2; } if (option[i].equals("*")) { point[i] += point[i]; int preIndex = i - 1; if (preIndex >= 0) point[preIndex] += point[preIndex]; } }
나의 생각
문자열 가공 문제는 항상 여러 로직들을 순차적으로 실행시키는 문제들이 많은 것 같다.
얼만큼 자료 구조에 잘 담고 있으며 너가 생각하는 로직이 얼마나 단순하고 어떤 효율이 보여주는가? 를 묻는 느낌이 강하다.
문자열 가공 문제는 꼬여있는 문제들을 하나씩 천천히 풀다보면 정답을 얻을 수 있는 것 같다.
코드
import java.util.*; class Solution { public int solution(String dartResult) { int answer = 0; int[] point = new int[3]; String[] bonus = new String[3]; String[] option = new String[3]; int index = 0; String inputPoint = ""; for (int i = 0; i < dartResult.length(); i++) { char check = dartResult.charAt(i); if (check == 'S' || check == 'D' || check == 'T') { point[index] = Integer.parseInt(inputPoint.replaceAll("[#*]", "")); bonus[index++] = String.valueOf(check); inputPoint = ""; continue; } inputPoint += check; } for (int i = 0; i < point.length; i++) { if (bonus[i].equals("D")) { point[i] = point[i] * point[i]; } if (bonus[i].equals("T")) { point[i] = point[i] * point[i] * point[i]; } } for (int i = 0; i < dartResult.length(); i++) { char check = dartResult.charAt(i); if (check == '*' || check == '#') { if (i < 3) option[0] = String.valueOf(check); else if (i == dartResult.length() - 1) option[2] = String.valueOf(check); else option[1] = String.valueOf(check); } } /////////////////////////////////////// // for (int i : point) { // System.out.print(i + " "); // } /////////////////////////////////////// // for (String s : option) { // System.out.println(s); // } /////////////////////////////////////// for (int i = 0; i < option.length; i++) { if (option[i] == null) continue; if (option[i].equals("#")) { point[i] -= point[i] * 2; } if (option[i].equals("*")) { point[i] += point[i]; int preIndex = i - 1; if (preIndex >= 0) point[preIndex] += point[preIndex]; } } /////////////////////////////////////// // System.out.println(); // for (int i : point) { // System.out.print(i + " "); // } /////////////////////////////////////// return Arrays.stream(point).sum(); } }