![[JavaScript] [1차] 다트 게임 - 2018 카카오 블라인드 코딩 테스트 [JavaScript] [1차] 다트 게임 - 2018 카카오 블라인드 코딩 테스트](http://t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png)
문제
카카오톡 게임별의 하반기 신규 서비스로 다트 게임을 출시하기로 했다.
다트 게임은 다트판에 다트를 세 차례 던져 그 점수의 합계로 실력을 겨루는 게임으로, 모두가 간단히 즐길 수 있다.
갓 입사한 무지는 코딩 실력을 인정받아 게임의 핵심 부분인 점수 계산 로직을 맡게 되었다.
다트 게임의 점수 계산 로직은 아래와 같다.
- 다트 게임은 총 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)은 점수마다 하나씩 존재한다.
- 스타상(*), 아차상(#)은 점수마다 둘 중 하나만 존재할 수 있으며, 존재하지 않을 수도 있다.
0~10의 정수와 문자 S, D, T, *, #로 구성된 문자열이 입력될 시 총점수를 반환하는 함수를 작성하라.
예시
입력 형식은 점수|보너스|[옵션]으로 이루어진 문자열 3세트이다.
dartResult | return | 풀이 방식 |
1S2D*3T | 37 | 1^1 * 2 + 2^2 * 2 + 3^3 |
1D2S#10S | 9 | 1^2 * + 2^1 * (-1) + 10^1 |
나의 풀이
function pow(score, option) {
switch(option) {
case "S":
return score ** 1;
case "D":
return score ** 2;
case "T":
return score ** 3;
}
}
function bonus(score, option) {
switch(option) {
case "*":
return score * 2;
case "#":
return score * -1;
}
}
function solution(dartResult) {
const reg = /\d{1,2}/g;
const idx = [...dartResult.matchAll(reg)].map((v) => v.index);
const scores = [dartResult.slice(idx[0], idx[1]), dartResult.slice(idx[1], idx[2]), dartResult.slice(idx[2])];
const result = scores.map((v, i) => {
const num = v.match(/\d{1,2}/)[0];
const option = v.replace(num, "");
let score = 0;
if (option.length > 1) {
score = bonus(pow(num, option[0]), option[1]);
} else {
score = pow(num, option);
}
if (scores[i+1]) {
return scores[i+1].includes("*") ? score * 2 : score
}
return score;
});
return result.reduce((a, c) => a + c, 0);
}
다른 풀이
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);
}
풀이 방법
나의 풀이 방법
1.정규식('/\d{1,2}/g')을 사용해서 문자열 안의 숫자를 모두 찾고 그 숫자의 index 값을 배열로 저장했다.
// 1~2자리 숫자를 찾는 정규식
const reg = /\d{1,2}/g;
// 정규식을 이용해서 문자열 안의 숫자의 시작 index 찾기
const idx = [...dartResult.matchAll(reg)].map((v) => v.index);
2. 위에서 찾은 숫자들의 index값과 slice() 함수를 사용해서 scores안에 배열로 넣어줬다.
const scores = [dartResult.slice(idx[0], idx[1]), dartResult.slice(idx[1], idx[2]), dartResult.slice(idx[2])];
// scores = ["1S", "2D*", "3T"]
3. scores의 문자열 배열을 map() 함수를 사용해서 각 문자열의 점수와 옵션을 분리시켰다.
const result = scores.map((v, i) => {
// 정규식을 사용해서 숫자 분리
// "1S" -> "1"
const num = v.match(/\d{1,2}/)[0];
// replace() 함수로 숫자를 없애줌
// "1S" -> "S"
const option = v.replace(num, "");
...
})
4. 첫 번째 옵션을 처리할 pow 함수와 두 번째 옵션을 처리할 bonus 함수를 작성했다.
function pow(score, option) {
switch(option) {
case "S":
return score ** 1;
case "D":
return score ** 2;
case "T":
return score ** 3;
}
}
function bonus(score, option) {
switch(option) {
case "*":
return score * 2;
case "#":
return score * -1;
}
}
5. 옵션이 2개 이상인 문자열은 bonus() 함수로 계산하고 1개인 경우 pow() 함수로 작성한 값을 score에 넣어줬다.
// 계산된 점수를 반환할 변수
let score = 0;
if (option.length > 1) {
score = bonus(pow(num, option[0]), option[1]);
} else {
score = pow(num, option);
}
6. 만약 다음 index가 존재하고 그 문자열에 "*"가 포함된다면 score에 2를 곱한 점수를 반환했다.
* 문제의 규칙 4번
if (scores[i+1]) {
return scores[i+1].includes("*") ? score * 2 : score
}
return score;
7. 이렇게 나온 점수들을 reduce() 함수로 계산된 값을 반환해줬다.
return result.reduce((a, c) => a + c, 0);
다른 풀이 방법
정규식을 써서 풀었지만 다른 사람의 코드를 보고 그저 놀라웠다.
나름 곰곰히 생각해서 숫자와 문자열의 조합을 어떻게 끊을까 고민을 많이한 결과가 1, 2번이었다.
하지만 위 코드에서는 정규식만을 사용해서 스코어의 조합을 잘라냈다.
let darts = dartResult.match(/\d.?\D/g);
// ["1S", "2D*", "3T"]
그리고 정규식을 사용해서 계산을 진행했다.
let split = darts[i].match(/(^\d{1,})(S|D|T)(\*|#)?/),
score = Math.pow(split[1], bonus[split[2]]) * options[split[3]];
정규식을 사용하면 간단한 코드로 원하는 계산을 수행할 수 있다는 사실을 다시 한번 깨닫게 된 문제였다.
'🧬알고리즘 > Programmers' 카테고리의 다른 글
[JavaScript] 모의고사 (0) | 2024.08.23 |
---|---|
[JavaScript] K번째 수 (0) | 2024.08.23 |
[JavaScript] [1차] 비밀지도 - 2018 카카오 블라인드 코딩 테스트 (0) | 2024.08.22 |
[JavaScript] x만큼의 간격이 있는 n개의 숫자 (0) | 2024.08.21 |
[JavaScript] 행렬의 덧셈 (0) | 2024.08.21 |
댓글