본문 바로가기
알고리즘 스터디/프로그래머스 스킬체크 레벨 1(끝)

[프로그래머스 스킬체크 레벨 1] [1차] 다트 게임 풀이 및 설명 - 자바스크립트[JavaScript]

by 레일라오리덕 2021. 7. 22.
728x90

https://programmers.co.kr/learn/courses/30/lessons/17682

 

코딩테스트 연습 - [1차] 다트 게임

 

programmers.co.kr

 

문제

 

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

  1. 다트 게임은 총 3번의 기회로 구성된다.
  2. 각 기회마다 얻을 수 있는 점수는 0점에서 10점까지이다.
  3. 점수와 함께 Single(S), Double(D), Triple(T) 영역이 존재하고 각 영역 당첨 시 점수에서 1제곱, 2제곱, 3제곱 (점수1 , 점수2 , 점수3 )으로 계산된다.
  4. 옵션으로 스타상(*) , 아차상(#)이 존재하며 스타상(*) 당첨 시 해당 점수와 바로 전에 얻은 점수를 각 2배로 만든다. 아차상(#) 당첨 시 해당 점수는 마이너스된다.
  5. 스타상(*)은 첫 번째 기회에서도 나올 수 있다. 이 경우 첫 번째 스타상(*)의 점수만 2배가 된다. (예제 4번 참고)
  6. 스타상(*)의 효과는 다른 스타상(*)의 효과와 중첩될 수 있다. 이 경우 중첩된 스타상(*) 점수는 4배가 된다. (예제 4번 참고)
  7. 스타상(*)의 효과는 아차상(#)의 효과와 중첩될 수 있다. 이 경우 중첩된 아차상(#)의 점수는 -2배가 된다. (예제 5번 참고)
  8. Single(S), Double(D), Triple(T)은 점수마다 하나씩 존재한다.
  9. 스타상(*), 아차상(#)은 점수마다 둘 중 하나만 존재할 수 있으며, 존재하지 않을 수도 있다.

0~10의 정수와 문자 S, D, T, *, #로 구성된 문자열이 입력될 시 총점수를 반환하는 함수를 작성하라.

 

제한 사항

  • 스테이지의 개수 N은 1 이상 500 이하의 자연수이다.
  • stages의 길이는 1 이상 200,000 이하이다.
  • stages에는 1 이상 N + 1 이하의 자연수가 담겨있다.
    • 각 자연수는 사용자가 현재 도전 중인 스테이지의 번호를 나타낸다.
    • 단, N + 1 은 마지막 스테이지(N 번째 스테이지) 까지 클리어 한 사용자를 나타낸다.
  • 만약 실패율이 같은 스테이지가 있다면 작은 번호의 스테이지가 먼저 오도록 하면 된다.
  • 스테이지에 도달한 유저가 없는 경우 해당 스테이지의 실패율은 0 으로 정의한다.

결괏값 예시

 

예제 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) {
    var answer = 0;
    return answer;
}

 

풀이 [JavaScript]

 

728x90

이번 문제는 개인적으로 제가 짠 코드가 마음에 들진 않습니다 하하;

우선, 이 문제를 풀면서 가장 중요한 포인트는, 1부터 10까지의 수라는 점입니다.

10을 split하면 1과 0이 되기 때문에 문제를 다 풀고 결과가 제대로 나오지 않아 굉장히 당황스러웠습니다.

split을 하기 전에, 들어온 값에서 10이 있다면, 특정 다른 값으로 바꿔주는 것이 좋습니다.

저는 11진법 기준으로 10을 A로 replace해주었는데요. split을 진행하고 나서 map함수를 사용하여 A라는 값을 10으로 바꿔주었습니다.

 

첫번째 for문에서는 S, D, T인 경우, 그 앞에는 1, 2, 3제곱을 해야하는 숫자가 있을 것이므로, 앞의 값을 적절히 제곱하여 새로운 배열인 answer에 넣어주었고요, *이나 #인 경우에는 그냥 answer에 푸쉬해서 넣어주었습니다.

 

그리고 answer값을 돌면서, *과 #에 알맞게 값을 곱해주었습니다.

먼저, *인 경우면서, *이 가장 첫번째 다트 값에 적용되는 경우에는, 이전 값이 없기 때문에, 단순히 별 앞에 있는 해당 값에 2를 곱해주었습니다.

여기서 중요한 점은 일반 for문에서는 var i=0으로 숫자로 지정해주지만, for-each문에서 i는 string이기때문에, 인덱스 1의 값을 찾을 때에, '1'로 비교하는 것을 조심해야한다.

 

하지만, *이지만, 첫번째 다트 값이 아닌 경우에는, 이전의 다트 값도 2배를 해주어야하기 때문에 별 바로 앞의 숫자에 2를 곱해주고 또 조건식을 만들었습니다.

[8, 4, *] 이런식으로 *바로 앞의 앞의 값이 바로 숫자인 경우에는 j-2의 값에 2를 곱해주면 되지만, [8, #, 4, *] 이런 식으로 별 앞의 앞의 값이 문자이면 그 앞의 값이 숫자이기 때문에, j-3의 값에 2를 곱해줍니다.

이를 판별하기 위해, j-2의 값이 isNaN(is Not A Number), 숫자가 아니라면, j-3의 값을 2배를 곱해주고, isNaN이 아니라면(문자라면) j-2의 값을 2배 해주면 됩니다.

 

그리고 #인 경우엔, 바로 앞의 숫자만 -1을 곱해주면 됩니다.

 

그리고, 이렇게 완성된 배열인 answer를 돌면서, !isNaN, 즉, 숫자라면 그 값을 reduce함수의 accumulator에 더해주어 값을 리턴하도록 합니다.

function solution(dartResult) {
    dartResult = dartResult.replace(/10/g,'A');
    var splited = dartResult.split('').map(v=> v ==='A' ? '10': v);
    var answer = [];
    for(var i in splited){
        if(splited[i] === 'S'){
            answer.push(Math.pow(splited[i-1], 1));
        }else if(splited[i] === 'D'){
            answer.push(Math.pow(splited[i-1], 2));
        }else if(splited[i] === 'T'){
            answer.push(Math.pow(splited[i-1], 3));
        }else if(splited[i] === '*'){
            answer.push('*');
        }else if(splited[i] === '#'){
            answer.push('#');
        }
    }
    for(var j in answer){
        if(answer[j] ===  '*' && j === '1'){
            answer[j-1] = answer[j-1]*2;
        }else if(answer[j] ===  '*' && j !== '1'){
            answer[j-1] = answer[j-1]*2;
            if(isNaN(answer[j-2])){
                answer[j-3] = answer[j-3] * 2;
            }else{
                answer[j-2] = answer[j-2] * 2;
            }
        }else if(answer[j] === '#'){
            answer[j-1] = answer[j-1] * -1;
        }
    }
    return answer.reduce((a, v) => !isNaN(v) ? a+v : a );
}

map함수 정리

https://leylaoriduck.tistory.com/manage/posts/

 

TISTORY

나를 표현하는 블로그를 만들어보세요.

www.tistory.com

reduce함수 정리

https://leylaoriduck.tistory.com/448?category=878030 

 

reduce() 함수 - 자바스크립트 배열 숫자 더하기, 누산기 함수 - 자바스크립트[JavaScript]

reduce() 함수 : 배열 내의 element들을 돌면서 각 element들을 합한 결과를 누산해서 반환하는 함수 reduce(a, v, i) => a(accumulator), v(value), i(index) -> 생략 가능 reduce() 각 element를 더할 때 var ar..

leylaoriduck.tistory.com

split함수 정리

https://leylaoriduck.tistory.com/447?category=878030 

 

split() 함수, join() 함수 - 자바스크립트 문자열 자르기, 배열 내 문자열/숫자 붙이기 - 자바스크립

split() 함수 : 특정 문자를 기준으로 문자열을 잘라내서 배열로 리턴하는 함수 join() 함수: 배열 내 element들을 ','를 기본 구분자를 두어 문자열로 합쳐서 리턴하는 함수 split()으로 문자열 자르기 (

leylaoriduck.tistory.com

채점 결과 [JavaScript]

 

728x90

댓글