🙌문제설명
카카오톡 게임별의 하반기 신규 서비스로 다트 게임을 출시하기로 했다. 다트 게임은 다트판에 다트를 세 차례 던져 그 점수의 합계로 실력을 겨루는 게임으로, 모두가 간단히 즐길 수 있다.
갓 입사한 무지는 코딩 실력을 인정받아 게임의 핵심 부분인 점수 계산 로직을 맡게 되었다. 다트 게임의 점수 계산 로직은 아래와 같다.
- 다트 게임은 총 3번의 기회로 구성된다.
- 각 기회마다 얻을 수 있는 점수는 0점에서 10점까지이다.
- 점수와 함께 Single(S), Double(D), Triple(T) 영역이 존재하고 각 영역 당첨 시 점수에서 1제곱, 2제곱, 3제곱 (점수^1 , 점수^2 , 점수^3 )으로 계산된다.
- 옵션으로 스타상(`*`) , 아차상(`#`)이 존재하며 스타상(`*`) 당첨 시 해당 점수와 바로 전에 얻은 점수를 각 2배로 만든다. 아차상(`#`) 당첨 시 해당 점수는 마이너스된다.
- 스타상(`*`)은 첫 번째 기회에서도 나올 수 있다. 이 경우 첫 번째 스타상(`*`)의 점수만 2배가 된다. (예제 4번 참고)
- 스타상(`*`)의 효과는 다른 스타상(`*`)의 효과와 중첩될 수 있다. 이 경우 중첩된 스타상(`*`) 점수는 4배가 된다. (예제 4번 참고)
- 스타상(`*`)의 효과는 아차상(`#`)의 효과와 중첩될 수 있다. 이 경우 중첩된 아차상(`#`)의 점수는 -2배가 된다. (예제 5번 참고)
- Single(S), Double(D), Triple(T)은 점수마다 하나씩 존재한다.
- 스타상(`*`), 아차상(#)은 점수마다 둘 중 하나만 존재할 수 있으며, 존재하지 않을 수도 있다.
☑️나의 풀이
문제가 꽤 복잡한데, 문제를 다음과 같이 정리를 해보았다.
점수계산
3번의 점수 0~10점
보너스 : S 1제곱 D 2제곱 T 3제곱
옵션 : *상 현재점수 *2, 직전점수 *2 (직전점수 없을 수 있고, 없으면 현재점수만)
옵션 : #상 (-현재점수)
isNaN를 통해 보너스를 기준으로 인식을 한다. 예를들어 1S* 일경우 S 바로 앞의 위치[i]를 파악한다.
‼️ 문제 발생 ‼️ 10S*일 경우, S 바로 앞의 위치[i]는 0이된다. 점수가 0점부터 10점까지 있기 때문에, i-1 값이 1이면,10으로 인식해야한다. 아닐경우 해당값 그대로 진행되도록 한다.
문자 인식의 경우가 많기 때문에 switch - case 문으로 생각했다.
정규표현식도 많이 사용할 것 같다고 생각했는데, 나는 별로 선호하지않아 고려하지 않았다.
`Math.pow(score, 2)` 코드로 제곱을 적용하고
옵션 스타상에서 직전점수가 있을때, 직점점수 *2 는 경우를 추가했다.
각 문자횟수마다 돌면서 push 로 값을 넣어주었고, reduce 메소드로 배열의 누적값을 계산하였다.
function solution(dartResult) {
var ans = 0;
let score = 0;
let cnt = []
for(let i=0; i<dartResult.length; i++){
let res = dartResult[i];
if (!isNaN(res)) {
score = dartResult[i-1] === '1' ? 10 : Number(res);
} else {
switch (res) {
case "S":
cnt.push(score);
break;
case "D":
cnt.push(Math.pow(score, 2));
break;
case "T":
cnt.push(Math.pow(score, 3));
break;
case "*":
cnt[cnt.length - 1] *= 2;
if (cnt.length > 1) {
cnt[cnt.length - 2] *= 2;
}
break;
case "#":
cnt[cnt.length - 1] *= -1;
break;
}
}
}
return cnt.reduce((acc, cur)=>acc + cur);
}
☑️다른 사람 코드
`let darts = dartResult.match(/\d.?\D/g);`
\d 는 점수 (0~10) > 이때 .?문법을 통해 임의의 하나의 문자가 있을수도 있고 없을수도 있는 옵셔널 > 10을 인식한다!
\D 는 숫자가 아닌 문자
\g 는 특수문자
function solution(dartResult) {
const bonus = { 'S': 1, 'D': 2, 'T': 3 },
options = { '*': 2, '#': -1, undefined: 1 };
let darts = dartResult.match(/\d.?\D/g);
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);
}
match 를 통해 정규표현식을 파악하고, * 가 있으면 현재 점수 뿐만 아니라, 이전점수까지 계산식 적용한다.
☑️배운 점
카카오 문제 LV.1 이라고 해서 풀었는데,, 정규표현식이라는 어려움을 맞닥드렸다...
Math.pow 를 통해서 제곱하는 방법!
case 로 분기하고, push 를 적절하게 해서, reduce 누적값을 반환한다.
카카오테크 블로그에서 후기를 보니 정답률이 73.47%, 난이도 하 이다.
코테는 잠깐 못푸는 시간이 있으면 실력에 확 나타나는 것 같다.
앞으로 좀더 열심히 해보자..