카카오톡에 뜬 네 번째 별! 심심할 땐? 카카오톡 게임별~
카카오톡 게임별의 하반기 신규 서비스로 다트 게임을 출시하기로 했다. 다트 게임은 다트판에 다트를 세 차례 던져 그 점수의 합계로 실력을 겨루는 게임으로, 모두가 간단히 즐길 수 있다.
갓 입사한 무지는 코딩 실력을 인정받아 게임의 핵심 부분인 점수 계산 로직을 맡게 되었다. 다트 게임의 점수 계산 로직은 아래와 같다.
0~10의 정수와 문자 S, D, T, *, #로 구성된 문자열이 입력될 시 총점수를 반환하는 함수를 작성하라.
"점수|보너스|[옵션]"으로 이루어진 문자열 3세트.
예) 1S2D*3T
3번의 기회에서 얻은 점수 합계에 해당하는 정수값을 출력한다.
예) 37
function solution(dartResult) {
const state = { star:'*', oops:'#', Single:'S', Double:'D', Triple:'T'};
let score = 0, scores = [], scoreIdx = 0;
for(let i = 0; i < dartResult.length; ++i){
// 이전 숫자가 1이면 10으로 판단해서 변수에 대입한다.
if(!isNaN(dartResult[i])){
score = +dartResult[i-1] === 1 ? 10 : +dartResult[i];
} else{
switch(dartResult[i]){
case state.Single:
scores.push(score);
break;
case state.Double:
scores.push(Math.pow(score, 2));
break;
case state.Triple:
scores.push(Math.pow(score, 3));
break;
case state.star: // 스타상은 이전과 현재 숫자를 곱해준다.
if(0 <= scores.length - 2){
scores[scores.length - 2] *= 2;
}
scores[scores.length - 1] *= 2;
break;
case state.oops: // 아차상은 현재를 마이너스로 바꿔준다.
scores[scores.length - 1] *= -1;
break;
}
}
}
return scores.reduce((acc,cur)=> acc += cur);
}
우선 레벨1 난이도라고 하기엔 조금 어려웠던 것 같다! 역시 카카오 문제는 클라스가 다르다! 처음 드는 생각은 정규표현식을 이용해서 라운드를 묶어서 분할 하는 방법이 있을 것 같은데, 잘 되지 않았다. 그래서 그냥 상태를 만들고 매번 요소가 숫자인지, 아니면 상태 값에 해당되는지 체크해서 작성했다.
function solution(dartResult) {
const bonus = {'S': 1, 'D': 2, 'T': 3};
let darts = dartResult.match(/\d.?\D/g);
for (let i = 0; i < darts.length; i++) {
let split = darts[i].match(/(\d{1,})([SDT])([*#])?/),
score = Math.pow(split[1], bonus[split[2]]);
if (split[3] !== undefined) {
if (split[3] === '*') {
score *= 2;
if (i > 0) darts[i - 1] *= 2;
} else score *= -1;
}
darts[i] = score;
}
return darts.reduce((a, b) => a + b);
}
오.. 신기해서 따라 테스트 해봤는데 정규표현식/\d.?\D/g
으로 라운드 별로 배열로 나눠졌다!
너무 깔끔한 방법인데 아쉬운 것은 내가 푼 직관적인 방법 보다는 속도가 약간 느렸다! 정규표현식을 이용하면 전체적인 탐색을 다양하게 하기 때문인 것으로 판단된다.
/(\d{1,})([SDT])([*#])?/
는 괄호로 첫 번째, 두 번째, 세 번째로 그룹을 나누어서 판별하고 배열로 만들어진다. 값이 없으면 undefined가 되므로 예외를 처리한 것이다.
참고 자료 및 사이트 (감사합니다)