1. 문제 정의
총 3라운드의 다트게임이 진행 되는데, 형식은 다음과 같이 들어온다. ex) "1S*2T*3S"
숫자는 0~10까지 들어오고 S일경우 1제곱, D일경우 2제곱, T일경우 3제곱을 수에 곱해주고 *일경우에는 자신의 바로앞 점수 *2, 그리고 현재 점수 *2 를 하게 된다. #일 경우에는 현재 숫자 * -1 이다. *와 #은 있을수도 있고 없을 수도 있다.
2. 나의 시도
처음에 문제를 풀 때에는 뭔가 가독성있게 풀려고 생각을 했는데, 생각해보니 정규표현식을 잘 알지 못해서, 그냥 생 if else문으로 문제를 해결했다. (빠르게 해결하고 더 좋은 풀이를 찾는 것이 목적이었기 때문에 중복코드를 제거하는 메서드 조차 만들지 않았다.) 그리고 다른사람의 풀이를 살펴보고, 정규표현식을 쓰는 법을 학습하여 내 나름대로의 로직을 통해 구현하였다.
또한 *이 나올경우 이전에 숫자에 다시 *2 연산을 하기 위해 배열을 이용하여 각 라운드 별로 점수를 저장하는 방법도 있었지만, 나는 스택을 이용하는 풀이가 좋아보여서, 결과적으로는 정규표현식과 스택을 섞어서 나만의 로직을 만들었다.
3. code
풀이1
public class Solution {
public static int solution(String dartResult) {
/*
* 최종결과값
*/
int answer =0;
/*
* 문자열을 char로 쪼갬
*/
char[] chars = dartResult.toCharArray();
/*
* 라운드는 총 3회여서 선언
*/
int gameRound = 1;
/*
* char 인덱스
*/
int index = 0;
/*
* *가 나오면 바로앞의 숫자도 *2 해야해서 preNum 저장해놓음.
*/
int preNum = 0;
/*
* 현재 계산할 숫자
*/
int currNum = 0;
while (gameRound<4){
/*
* 숫자가 10일 경우 10과 index +2 해주기
* 아닐경우에는 해당숫자와 index +1
*/
if(chars[index] == '1' && chars[index+1] =='0'){
currNum = 10;
index+=2;
}else if( chars[index] >='0' && chars[index]<='9'){
currNum = Character.getNumericValue(chars[index]);
index++;
}
/*
* S일 경우 + * or #
*/
if(chars[index] == 'S' ){
index++;
if (index < chars.length && chars[index] == '*'){
currNum = currNum*2;
answer += currNum + preNum;
index++;
}else if (index < chars.length && chars[index] == '#'){
currNum = currNum * -1;
answer += currNum;
index++;
}else{
answer += currNum;
}
/*
* D일경우 * or #
*/
} else if (chars[index] == 'D') {
index++;
currNum = currNum * currNum;
if (index < chars.length && chars[index] == '*'){
currNum = currNum*2;
answer += currNum + preNum;
index++;
}else if (index < chars.length && chars[index] == '#'){
currNum = currNum * -1;
answer += currNum;
index++;
}else{
answer += currNum;
}
/*
* T일경우 * or #
*/
} else if (chars[index] == 'T') {
index++;
currNum = currNum * currNum * currNum;
if (index < chars.length && chars[index] == '*'){
currNum = currNum*2;
answer += currNum + preNum;
index++;
}else if (index < chars.length && chars[index] == '#'){
currNum = currNum * -1;
answer += currNum;
index++;
}else{
answer += currNum;
}
}
preNum = currNum;
gameRound++;
}
return answer;
}
}
풀이2
public class Solution2 {
public static int solution(String dartResult) {
/*
* 라운드별 정규표현식
*/
String reg = "([0-9]{1,2}[S|D|T][*|#]?)";
/*
* 정규표현식 패턴으로 pattern객체 만듬
*/
Pattern pattern = Pattern.compile(reg);
/*
* pattern객체의 matcher 메서드를 통해 문자열과 정규표현식이 일치하는지 확인해주는 matcher 생성
*/
Matcher matcher = pattern.matcher(dartResult);
/*
* 이전 점수를 저장할 스택
*/
Stack<Integer> prev = new Stack<>();
for (int i = 0; i < 3; i++) {
/*
* reg와 일치하는 문자열을 찾고 group()으로 가져온다. (1S2D*3T 일경우 1S만)
*/
matcher.find();
String group = matcher.group();
Pattern localPattern = Pattern.compile("([0-9]{1,2})([S|D|T])([*|#]?)");
Matcher localMatcher = localPattern.matcher(group);
localMatcher.find();
/*
* 그룹별로 나눠진 것을 계산
*/
int curr = (int) Math.pow(Integer.parseInt(localMatcher.group(1)), getPower(localMatcher.group(2)));
String multiply = localMatcher.group(3);
curr *= getMultiply(multiply);
if (!prev.isEmpty() && getMultiply(multiply) != -1) {
Integer pop = prev.pop();
pop *= getMultiply(multiply);
prev.push(pop);
}
prev.push(curr);
}
/*
* 정답
*/
int answer = 0;
while (!prev.isEmpty()){
answer+= prev.pop();
}
return answer;
}
private static int getPower(String power) {
if (power.equals("S")) return 1;
if (power.equals("D")) return 2;
if (power.equals("T")) return 3;
return 0;
}
private static int getMultiply(String group) {
if (group.length() > 0) {
if (group.equals("*")) {
return 2;
}
if (group.equals("#")) {
return -1;
}
}
return 1;
}
}
4. 깨달은 점
역시 문자열의 패턴을 찾는다던가 하는 방식은 if-else문 보다는 정규표현식을 이용하는 것이 좀 더 효율적인 것 같다. 이번기회에 Pattern 클래스와 Matcher 클래스를 조금이나마 사용해보고 이해하여 정규표현식을 사용해봤는데, 완전히 암기는 하기 어렵지만 그때그때마다 찾아서 필요한 정규표현식을 만들정도의 기반은 마련한 것 같다.
참조
https://school.programmers.co.kr/learn/courses/30/lessons/17682
'프로그래밍 > 알고리즘 문제풀이' 카테고리의 다른 글
[pg] 프로그래머스 요격시스템 (0) | 2023.08.09 |
---|---|
[pg] 프로그래머스 비밀지도 (0) | 2023.08.08 |
[pg] 프로그래머스 실패율 (0) | 2023.08.08 |
[pg] 프로그래머스 키패드 누르기 (0) | 2023.08.02 |
[pg] 프로그래머스 신규아이디 추천 (0) | 2023.08.01 |