✨ Lv. 1 - [1차] 다트 게임
문제 링크 : https://school.programmers.co.kr/learn/courses/30/lessons/17682
카카오톡 게임별의 하반기 신규 서비스로 다트 게임을 출시하기로 했다. 다트 게임은 다트판에 다트를 세 차례 던져 그 점수의 합계로 실력을 겨루는 게임으로, 모두가 간단히 즐길 수 있다.
갓 입사한 무지는 코딩 실력을 인정받아 게임의 핵심 부분인 점수 계산 로직을 맡게 되었다. 다트 게임의 점수 계산 로직은 아래와 같다.
0~10의 정수와 문자 S, D, T, *, #로 구성된 문자열이 입력될 시 총점수를 반환하는 함수를 작성하라.
"점수|보너스|[옵션]"으로 이루어진 문자열 3세트.
예) 1S2D*3T
3번의 기회에서 얻은 점수 합계에 해당하는 정수값을 출력한다.
예) 37
조건이 많습니다. 우선 조건을 하나씩 간단하게 정리해보겠습니다.
- 한 번의 다트 게임은
점수 | 보너스 | 옵션
으로 이루짐.- 숫자는
0 - 10
의 값을 가짐.- 보너스는 항상 존재하며,
S, D, T
로 각각 1제곱, 2제곱, 3제곱을 의미.- 옵션은
*, #
이며, 존재하지 않을수도, 중복으로 존재할 수도 있음.*
은 이전 점수와 현재 점수에x 2
.#
는 현재 점수에x -1
.- 다트 게임 점수의 총합을 구하여라.
이를 바탕으로 아래와 같은 순서로 코드를 작성하였습니다.
- 각 게임의 점수를 담을
result
배열 선언- 점수를 담을
current
변수 선언dartResult
를 순회하며 아래를 반복
- 숫자면current
에 더하기
-*
인 경우,result
의 가장 뒤에 있는 2개의 값에 2를 곱하기
-#
인 경우,result
의 가장 뒤에 있는 값에 -1 곱하기
-S, D, T
인 경우,current
의 1, 2, 3제곱을result
에push
,current
초기화
이를 바탕으로 작성한 코드는 아래와 같습니다.
function solution(dartResult) {
let result = [];
let current = '';
[...dartResult].forEach((v) => {
if('0' <= v && v <= '9') current += v;
else if(v === '*') {
if(result.length >= 2) result[result.length - 2] *= 2;
result[result.length - 1] *= 2;
}
else if(v === '#') {
result[result.length - 1] *= -1;
}
else {
if(v === 'S') result.push(Number(current));
if(v === 'D') result.push(Math.pow(Number(current), 2));
if(v === 'T') result.push(Math.pow(Number(current), 3));
current = '';
}
});
return result.reduce((s, v) => s + v);
}
코드의 가독성을 높이고, 보다 명확하게 하기 위해서 정규표현식과 객체를 활용하여 다른 방식으로 풀이가 가능합니다. 우선 매번 비교하여 보너스와 옵션에 따라 코드를 작성하지 않기 위하여 객체 형태로 이를 작성합니다.
이후, 정규표현식을 이용하여 점수 | 보너스 | 옵션
형태를 기준으로 match
를 활용하여 배열 형태로 저장합니다.
/\d\d?.?\D/g
\d
: 숫자를 나타냄. 최대 10까지 올 수 있으므로, 2번 사용.?
: 존재하지 않을수도 있음. 한 자리인 경우도 있으므로\d
뒤에 사용..?
: 임의의 한 문자를 의미하며,.
는 해당 문자열이 뒤에 오는 문자로 끝남을 의미.\D
: 숫자가 아닌 문자를 의미.g
: global, 대상 문자열 내의 모든 패턴을 검색함을 의미.
이후, 배열을 순회하며 각 경우를 정규표현식을 활용하여 숫자와 보너스, 옵션으로 나누어 계산합니다.
/(^\d{1,})(S|D|T)(\*|#)?/
(\d{1, })
: 숫자를 나타냄.{1,}
은\d
가 1개 이상 위치함을 의미.(S|D|T)
:S, D, T
중 하나가 위치함을 의미.(\*|#)?
:*, #
둘 중 하나가 위치함을 의미하며, 존재하지 않을 수도 있음.()
: 하나의 그룹을 표현함.
이를 이용하면 index 0
에는 매치된 문자열이, 그 뒤로는 각 그룹에 매치된 문자열이 저장됩니다. 이를 이용하여 문제를 풀이할 수 있습니다. 위 내용을 활용한 코드는 아래와 같습니다.
function solution(dartResult) {
const bonus = { 'S': 1, 'D': 2, 'T': 3 };
const option = { '*': 2, '#': -1, undefined: 1 };
let games = dartResult.match(/\d\d?.?\D/g);
games.forEach((v, i) => {
let current = v.match(/(^\d{1,})(S|D|T)(\*|#)?/);
let score = Math.pow(current[1], bonus[current[2]]) * option[current[3]];
if(i >= 1 && current[3] === '*') games[i - 1] *= option['*'];
games[i] = score;
})
return games.reduce((s, v) => s + v);
}