
자세한 내용은 위의 링크를 참조.
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]; // 옵션을 담을 배열
주어질 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();
}
}

