카카오톡에 뜬 네 번째 별! 심심할 땐? 카카오톡 게임별~
카카오톡 게임별의 하반기 신규 서비스로 다트 게임을 출시하기로 했다. 다트 게임은 다트판에 다트를 세 차례 던져 그 점수의 합계로 실력을 겨루는 게임으로, 모두가 간단히 즐길 수 있다.
갓 입사한 무지는 코딩 실력을 인정받아 게임의 핵심 부분인 점수 계산 로직을 맡게 되었다. 다트 게임의 점수 계산 로직은 아래와 같다.
다트 게임은 총 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세트.
예) 1S2D*3T
점수는 0에서 10 사이의 정수이다.
보너스는 S, D, T 중 하나이다.
옵선은 *이나 # 중 하나이며, 없을 수도 있다.
출력 형식
3번의 기회에서 얻은 점수 합계에 해당하는 정수값을 출력한다.
예) 37
예제 dartResult answer 설명 1 1S2D*3T 37 11 * 2 + 22 * 2 + 33 2 1D2S#10S 9 12 + 21 * (-1) + 101 3 1D2S0T 3 12 + 21 + 03 4 1S*2T*3S 23 11 * 2 * 2 + 23 * 2 + 31 5 1D#2S*3S 5 12 * (-1) * 2 + 21 * 2 + 31 6 1T2D3D# -4 13 + 22 + 32 * (-1) 7 1D2S3T* 59 12 + 21 * 2 + 33 * 2
function solution(dartResult) {
let answer = 0;
let splitArr = dartResult.split("");
let doSDTArr = [];
let doStarArr = [];
if(dartResult.includes("10")){
let tenIdx = dartResult.indexOf("10");
splitArr = [...splitArr.slice(0,tenIdx),'10',...splitArr.slice(tenIdx+2,splitArr.length+1)]
}
//1. SDT처리
// console.log(splitArr);
splitArr.forEach((el,index)=>{
if(el === "S"){
return doSDTArr[index-1] = Number(splitArr[index-1])**1;
}else if(el === "D"){
return doSDTArr[index-1] = Number(splitArr[index-1])**2;
}else if(el === "T"){
return doSDTArr[index-1] = Number(splitArr[index-1])**3;
}else{
return doSDTArr[index] = el;
}
})
doSDTArr = doSDTArr.filter((el)=> el);
// console.log(doSDTArr);
//2. # 처리
let starArr = [];
let NotStarIdxArr = [];
doSDTArr.forEach((el,index)=>{
if(el ==="#"){
doStarArr[index] = 0;
return doStarArr[index-1] = Number(doSDTArr[index-1])*-1;
}else if(el !== "*"){
return doStarArr[index] = Number(el);
}else{
return doStarArr[index] = el;
}
})
//3. * 인덱스를 활용하여 앞으로 숫자 두개만 2곱하기 진행
console.log(doStarArr);
for(let i = 0; i < doStarArr.length; i++){
let count = 0;
for(let j = i; j >= 0; j--){
if(doStarArr[i] === "*"){
if(doStarArr[j] !== "*" && doStarArr[j] !== 0){
doStarArr[j] *= 2;
count +=1;
}
}
if (count >=2) break;
}
}
//총합
let filterStarArr = doStarArr.filter(el=>el!=="*");
console.log(filterStarArr);
answer = doStarArr.filter(el=>el!=="*").reduce((a,b)=>a+b);
return answer;
}
console.log(solution('1S*2T*3S')); //23
// console.log(solution('1S2D*3T')); //37
console.log(solution("1D#2S*3S")); //5
console.log(solution("1D2S3T*")); //59
// console.log(solution("1T2D3D#"));
console.log(solution("1D2S#10S")); //9
몇몇개의 테스트 케이스 통과가안된다
이 방식 자체가 잘못된듯 ㅎㅅㅎ...
배열을 계속 만들어 주며 그 안에서 필요한 조건에따라 숫자를 변경하는 방식으로 진행하려 하였다.
*의 조건이나 #의 조건에서 조금 엉킨것도 있을 것 같고
무엇보다 10에대한 처리가 제대로 되지않았었다 ㅎㅅㅎ...
function solution(dartResult) {
let answer = 0;
let splitArr = [];
let stack = [];
//스택은 위에서쌓고 빼면 제일위에것임
//따라서 concat(push는 배열순서바뀌니께)과 pop으로 조절할 수 가 있게된다.
dartResult.split("").forEach((el,index)=>{
if(!isNaN(dartResult[index-1]) && !isNaN(dartResult[index])){
console.log("find 10!");
splitArr.pop();
splitArr = splitArr.concat(('10'));
}else{
splitArr = splitArr.concat((el));
}
})
splitArr.forEach((el,index)=>{
if(!isNaN(el)){
stack = stack.concat(el);
}else if(["S","D","T"].includes(el)){
if(el === "S"){
let newEl = Number(stack.pop()**1);
stack = stack.concat(newEl);
}else if(el ==="D"){
let newEl = Number(stack.pop()**2);
stack = stack.concat(newEl);
}else if(el ==="T"){
let newEl = Number(stack.pop()**3);
stack = stack.concat(newEl);
}
}else if(["*"].includes(el)){
//앞의 숫자 2개까지 곱하기 2 한다고 하였으니!
// let newEl = Number(stack.pop()*2)
let newEl = stack.pop()*2;
let secondEl = stack.pop()*2;
if(secondEl){
stack = stack.concat(secondEl,newEl);
}else{
stack = stack.concat(newEl);
}
}else if(["#"].includes(el)){
let newEl = Number(stack.pop()*-1);
stack = stack.concat(newEl);
}
})
console.log(stack);
return stack.reduce((a,b)=>a+b);
}
console.log(solution('1S*2T*3S')); //23
console.log(solution("1D#2S*3S")); //5
console.log(solution("1D2S3T*")); //59
console.log(solution("1D2S#10S")); //9
생각을 조금 바꿔서 스택을 기본 구조로하고 10과함께 구분되어 있는 배열에 각 조건들을 뺏다가 넣어주는 방식으로 변경하였다.
진작 이렇게 할 걸... 자료구조에 대한 공부가 더욱 중요하다는 것을 깨닫게 되었다.
메서드에 혼동이 조금 있어 정리하자면
- push: 배열 길이 반환, 기존 배열 변환됨
- concat: 변경된 배열 반환, 기존배열 변환 없음
- pop: 제일 마지막 index의 값 반환, 기존배열 마지막 원소 제거