[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(); } }
![[Programmers] [1차] 다트 게임](/_next/image?url=https%3A%2F%2Fwww.notion.so%2Fimage%2Fattachment%253A630f03dd-3aba-4abf-858c-63f0537321c6%253Aalgorithm.jpg%3Ftable%3Dblock%26id%3D256a12d0-8f8e-802b-a7ca-dbba9990d269%26cache%3Dv2&w=3840&q=75)