Algorithm & 자료구조/알고리즘 w.JavaScript

[알고리즘 JS] 다트 게임 (프로그래머스 Lv.1)

프라이D 2022. 11. 15. 23:04

문제

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

정말 오랜만에 알고리즘 문제 풀이! 지금까지 나름 꾸준히 풀긴 했는데 기록으로 남기질 않은 것 같아서 다시 정리해본다.

본 문제는 다트게임이라는 문제로, 문제에서 제시되는 상황을 정리하면 아래와 같다.

  • 총 3번의 게임 기회가 있다.
  • 각 라운드당 획득 점수는 1 ~ 10점 이다.
  • S, D, T 각각 1, 2, 3만큼 거듭제곱되는 영역이 있다.
  • *, # 같은 옵션이 하나씩만 붙을 수 있다. * 기호의 경우 이전에 획득한 점수, 현재 획득한 점수 *2배, #의 경우 현재 점수를 음수로 바꾼다.
  • 예를들어 1D#2S*3S 라는 문자열이 주어지면 각 게임의 점수를 다음과 같이 정리할 수 있다.
    • 1D# => 1점을 2회 거듭제곱하고 음수로 변경 => [ -1 ]
    • 2S* => 2점을 1회 거듭제곱하고, 이전 점수와 현재점수 2배 => -1 * 2 + 2 * 2 => [-2, 4]
    • 3S => 3점을 1회 거듭제곱 => [-2 , 4, 3 ] 
    • 따라서 총 획득 점수는 -2 + 4 + 3 = 5 가 된다.

풀이

function solution(str) {
  let games = [];
  let tmp = [str[0]];

  // 숫자를 기준으로 각 점수를 분리하여 games 배열에 push 한다.
  for (let i = 1; i < str.length; i++) {
    // 현재 i가 숫자일 경우 지금까지 쌓인 tmp 배열을 games 에 push 후 tmp 초기화
    if (!isNaN(str[i]) && isNaN(str[i - 1])) {
      games.push(tmp);
      tmp = [];
    }

    // 숫자가 10까지 있으므로, 이 경우 tmp 에 따로 들어가있을 1 과 0을 합쳐 10으로 만들어주자.
    if (!isNaN(tmp[1])) {
      let num = tmp[0] + tmp[1];
      tmp = [num];
    }

    tmp.push(str[i]);
  }
  // 마지막 요소는 포함이 되지 않았으므로 직접 추가해준다.
  games.push(tmp);

  // 거듭제곱 되는 횟수를 저장!
  const powers = {
    S: 1,
    D: 2,
    T: 3,
  };

  let scores = [];

  for (let game of games) {
    // 숫자를 기준으로 분리한 각 점수를 다시 점수, 거듭제곱 수, 옵션으로 분리
    let [num, pow, opt] = game;
    let score = num ** powers[pow];
    // 옵션이 존재한다면 * 인지 # 인지 확인!
    // * 일 경우 이전 요소, 현재 요소의 점수를 * 2 한다.
    if (opt && opt === '*') {
      // 이전에 계산된 점수가 없는 경우 현재 점수에만 * 2 룰이 적용된다.
      if (scores.length) scores.push(scores.pop() * 2);
      scores.push(score * 2);
      continue;
    }
    // # 일 경우 현재 점수를 음수로 만든다.
    else if (opt && opt === '#') {
      score = -score;
    }
    scores.push(score);
  }
  return scores.reduce((acc, cur) => acc + cur, 0);
}
  • 정규 표현식을 쓰면 더 짧은 코드로 처리가 가능할 것 같다. 처음에는 정규표현식이 필요 없을 것 같아서 반복문으로 풀었는데, 다시 보니 얻을 수 있는 숫자 점수의 조건에 10까지 포함이 되어있기 때문에 별도로 예외처리를 했다. ㅜㅜ