티스토리 뷰

반응형

 

프로그래머스 - 다트게임

 

이 문제를 마지막으로 프로그래머스 1단계 문제는 모두 풀었다. 이제 카카오 문제 제외하고는 대부분 1단계 문제는 금방 푸는 것 같다. 정말 간단한 거는 10초도 안 걸리고 오래 걸려도 5분 안에는 푼다. 이제 2단계를 다 풀어야 하는데 다음 주면 리액트 주차 시작이라 여유가 있지 않을 것 같다ㅠ

 

1단계 중 카카오 문제는 난이도가 다른 1단계에 비해 있는 편이라 항상 푸는데  오래걸렸는데 이 문제는 생각보다 금방 풀리긴 했다. 하지만 정규표현식을 활용하지 않아 좀 까다롭고 이 때문에 코드의 가독성이 좋지 않다는 생각이 들었다. 

 

답안 제출 후 다른 분들의 풀이를 보니 역시 예상했던대로 정규식 표현을 사용해 푼 답안이 가장 좋아요를 많이 받았다. 

저번처럼 정규식 표현에 익숙해지려고 노력한다해놓고 오늘도 피해버렸다.. ;;  오늘 또 한 번 파고들면 좀 나아지겠지 싶다.

 


 

풀이 과정

2번 과정이 조금 까다로웠다. 

1. 인풋값들을 점수로 환산한다. 
2. "#" of "*"  일 때 각 점수 연산해준다.
3. 최종적으로 연산이 완료된 score에서 숫자만 뽑아 값을 합산해준다.

 

 

1.  인풋 값들을 점수로 환산하기 

score이라는 빈 배열을 선언해주고, 각 조건에 맞게 계산해 각 게임의 점수와 "#", "*"로만 반환되도록 했다. 

 

dartResult : "1S*2T*3S"

score : [ 1, '*', 8, '*', 3 ]

 

또 10S와 같이 점수가 10점인 경우도 있기 때문에 아래와 같은 조건을 추가시켰다.

    if (dart[i] === "0" && dart[i - 1] === "1") dart[i] = 10;

 

 

 let dart = dartResult.split("");
  let score = [];

  for (let i = 0; i < dart.length; i++) {
    if (dart[i] === "0" && dart[i - 1] === "1") dart[i] = 10;
    if (dart[i] === "S") score.push(Math.pow(dart[i - 1], 1));
    if (dart[i] === "D") score.push(Math.pow(dart[i - 1], 2));
    if (dart[i] === "T") score.push(Math.pow(dart[i - 1], 3));
    if (dart[i] === "*" || dart[i] === "#") score.push(dart[i]);
  }

 

 

 

2.  "#" of "*"  일 때 각 점수 연산해주기

 

아래 score의 상태에서 "#" of "*"  일 때 각 점수 연산해준다. 

score : [ 1, '*', 8, '*', 3 ]

 

2-1. score [i] = "#"일 때는 해당 값만 -1을 곱해주면 되므로 score[i-1] 에 -1을 곱해준다. 

 

2-2. score[i] = "*" 일 때는 두 가지 경우가 존재한다. i = 3일 경우 "*"를 보면  1, 8에 각각 x2를 해줘야 하는 상황이다. 

원래는 아래처럼 조건을 줬었는데 이 경우에는 index = i-2까지는 index = 1인 경우이므로 socre [1] = "*"에 해당되고 그렇게 되면 score [0] = 1에 x2는 되지 않는 상황이 발생한다. 

  score = score.map((val, index) =>
          index < i && index >= i - 2 && !isNaN(val) ? val * 2 : val
        );

 

 

따라서 아래와 같이로  score [i - 2] 값이 "*" or "#"인 경우( isNaN(score [i - 2])에 Index>= i - 3으로,  score [i - 2] 값이 숫자인 경우(! isNaN(score [i - 2])에는 Index>= i - 2으로 해주면 알맞은 답이 나온다. 

  for (let i = 0; i < score.length; i++) {
  	// "#" 일 때 해당 점수는 마이너스된다.
    if (score[i] === "#") {
      score[i - 1] = score[i - 1] * -1;
    }
	// "*" 일 때 해당 점수와 바로 전에 얻은 점수를 각 2배로 만든다.
    if (score[i] === "*") {
      //  score[i - 2] 값이 "*" or "#" 인 경우에는 index가 그 전의 값인 i -3보다 크고 
      // i 보다 작은 것들만 2배로 해줘야 한다.
      if (isNaN(score[i - 2])) {
        score = score.map((val, index) =>
          index < i && index >= i - 3 && !isNaN(val) ? val * 2 : val
        );
        
      } else {
        // score[i - 2] 값이 숫자라면 index가 i -2 보다 크고 i보다 작은 것들만 2배로 해줘야 한다.
        score = score.map((val, index) =>
          index < i && index >= i - 2 && !isNaN(val) ? val * 2 : val
        );
      }
    }
  }

 

 

 

 

3. 최종적으로 연산이 완료된 score에서 숫자만 뽑아 값을 합산해준다.

 

그렇게 되면 최종적으로 아래와 같이 연산이 완료된 score가 나온다. 

최종 score : [ 4, '*', 16, '*', 3 ]

filter()로 숫자만 반환하고 그 값들을 reduce()를 통해 합산해서 리턴해주면 알맞은 결괏값을 배출한다. 

  return score.filter((val) => !isNaN(val)).reduce((acc, cur) => acc + cur, 0);

 


 

제출 코드 

function solution(dartResult) {
  let dart = dartResult.split("");
  let score = [];

  for (let i = 0; i < dart.length; i++) {
    if (dart[i] === "0" && dart[i - 1] === "1") dart[i] = 10;
    if (dart[i] === "S") score.push(Math.pow(dart[i - 1], 1));
    if (dart[i] === "D") score.push(Math.pow(dart[i - 1], 2));
    if (dart[i] === "T") score.push(Math.pow(dart[i - 1], 3));
    if (dart[i] === "*") score.push("*");
    if (dart[i] === "#") score.push("#");
  }

  for (let i = 0; i < score.length; i++) {
    if (score[i] === "#") {
      score[i - 1] = score[i - 1] * -1;
    }

    if (score[i] === "*") {
      if (isNaN(score[i - 2])) {
        score = score.map((val, index) =>
          index < i && index >= i - 3 && !isNaN(val) ? val * 2 : val
        );
      } else {
        score = score.map((val, index) =>
          index < i && index >= i - 2 && !isNaN(val) ? val * 2 : val
        );
      }
    }
  }
  return score.filter((val) => !isNaN(val)).reduce((acc, cur) => acc + cur, 0);
}

 

 


 

정규식을 이용한 풀이

match() : 이 함수는 정규식에 맞는 부분을 찾아주는 것이다.
.. : 개행 문자를 제외한 모든 단일 문자와 대응된다. 
.? : 앞의 표현식이 0 또는 1회 등장하는 부분과 대응됩니다. {0,1}와 같은 의미이다.
\d {1,} 은 \d가 숫자, {1,}는 한 개부터 무한대까지 숫자가 연속 나오면 그것을 하나로 생각한다는 것이다.
~~{2} 하면 길이가 2인 것만 찾겠다는 의미이다.

 

function solution(dartResult) {
  const bonus = { S: 1, D: 2, T: 3 },
    options = { "*": 2, "#": -1, undefined: 1 };

  let darts = dartResult.match(/\d.?\D/g);
  console.log(darts);

  for (let i = 0; i < darts.length; i++) {
    let split = darts[i].match(/(^\d{1,})(S|D|T)(\*|#)?/),
      score = Math.pow(split[1], bonus[split[2]]) * options[split[3]];

    if (split[3] === "*" && darts[i - 1]) darts[i - 1] *= options["*"];

    darts[i] = score;
  }

  return darts.reduce((a, b) => a + b);
}

 

 

 

 

 

 



반응형