문제
정말 오랜만에 알고리즘 문제 풀이! 지금까지 나름 꾸준히 풀긴 했는데 기록으로 남기질 않은 것 같아서 다시 정리해본다.
본 문제는 다트게임이라는 문제로, 문제에서 제시되는 상황을 정리하면 아래와 같다.
- 총 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까지 포함이 되어있기 때문에 별도로 예외처리를 했다. ㅜㅜ
'Algorithm & 자료구조 > 알고리즘 w.JavaScript' 카테고리의 다른 글
[알고리즘 JS] 숫자 짝꿍 (프로그래머스 Lv.1) (1) | 2023.01.02 |
---|---|
[알고리즘 JS] 로또의 최고 순위와 최저 순위 (프로그래머스 Lv.1) (0) | 2022.11.16 |
[알고리즘 JS] 쇠막대기 (Stack) (0) | 2022.09.24 |
[알고리즘 JS] 크레인 인형뽑기 게임 (프로그래머스 Lv.1) (2) | 2022.09.22 |
[알고리즘 JS] 프로그래머스 LV.1 소수 찾기 (0) | 2022.07.18 |