본문 바로가기

코딩테스트

[프로그래머스] level1. 다트게임 (javascript)

반응형

문제

카카오톡 게임별의 하반기 신규 서비스로 다트 게임을 출시하기로 했다. 다트 게임은 다트판에 다트를 세 차례 던져 그 점수의 합계로 실력을 겨루는 게임으로, 모두가 간단히 즐길 수 있다.
갓 입사한 무지는 코딩 실력을 인정받아 게임의 핵심 부분인 점수 계산 로직을 맡게 되었다. 다트 게임의 점수 계산 로직은 아래와 같다.

다트 게임은 총 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, *, #로 구성된 문자열이 입력될 시 총점수를 반환하는 함수를 작성하라.

나의 풀이

function solution(dartResult) {
    var answer = 0;

    const arr = dartResult.replace(/(\D)/g," $1 ").split(" ").filter((el)=> el !=="")
    const arr2 = [];
    arr.map((cur,i)=> {
        if (cur == 'S'){
            arr2.push(+arr[i-1])
        } else if (cur == 'D'){
            arr2.push(arr[i-1]*arr[i-1])
        } else if (cur == 'T'){
            arr2.push(arr[i-1]*arr[i-1]*arr[i-1])
        } else if (cur == '*'){
            if (arr2.length == 1){
                arr2[arr2.length-1] = arr2[arr2.length-1]*2;    
            } else{
                arr2[arr2.length-1] = arr2[arr2.length-1]*2;
                arr2[arr2.length-2] = arr2[arr2.length-2]*2;    
            }
        } else if (cur == '#'){
            arr2[arr2.length-1] = -arr2[arr2.length-1]
        }
    })
    return arr2.reduce((acc,cur)=> acc = acc+cur);
}

 

정규 표현식으로 숫자 문자가 아닌 문자에 대응되는 \D를 통해 재배치를 해줬다.
그 후 각 문자에 따른 처리를 if문을 통해 해주었다.
마지막으로 reduce를 통해 이 결과들을 더 한 것으로 끝.

다른 이들의 풀이

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);
}

 

전반적으로 흐름은 같지만, 디테일이 많이 차이났다.
정규 표현식에서 ()를 통해 내가 나누고 싶은 경계선(분류)를 나눠주고 , 이를 배열 불러오듯 arr[1] 이런식으로 불러와서 사용한게 인상 깊다.

 

        let split = darts[i].match(/(^\d{1,})(S|D|T)(\*|#)?/),

 

[ '1D', '1', 'D', undefined, index: 0, input: '1D', groups: undefined ]
실제 돌려보면 위와 깉이 나오니, 이걸 이용해서

 

            score = Math.pow(split[1], bonus[split[2]]) * options[split[3]];

 

이런식으로 불러와서 계산하겠다는 뜻이다.

참조

match() : 이 함수는 정규식에 맞는 부분을 찾아주는것이다.
. : 개행 문자를 제외한 모든 단일 문자와 대응됩니다.
? : 앞의 표현식이 0 또는 1회 등장하는 부분과 대응됩니다. {0,1} 와 같은 의미입니다.

\d{1,} 은 \d가 숫자, {1,}는 한개 부터 무한대까지 숫자가 연속 나오면 그것을 하나로 생각한다는 것이다.

~~{2} 하면 길이가 2인 것만 찾겠다는 의미이다.

 

참조 : MDN

반응형