<프로그래머스, 다트 게임>

Minwoong Kim·2022년 10월 2일
0

2022-Sep-22, today getting out of my comfort zone.

문제 설명

출처: '프로그래머스',
본 내용은 학습 목표로 작성되었으며, 추후 문제가 될 시 즉시 삭제 조치 하겠습니다.

어느 회사의 신규 서비스로 다트 게임을 출시하기로 했다.

  1. 다트 게임은 총 3번의 기회로 구성되며, 각 기회마다 얻을 수 있는 점수는 0점에서 10점까지이다.

  2. 점수와 함께 Single(S), Double(D), Triple(T) 영역이 존재하고 각 영역 당첨 시 점수에서 1제곱, 2제곱, 3제곱 (점수1 , 점수2 , 점수3 )으로 계산된다.

  3. 옵션으로 '' , '#'이 존재하며 '*' 당첨 시 해당 점수와 바로 전에 얻은 점수를 각 2배로 만든다.

  4. '#' 당첨 시 해당 점수는 마이너스된다.

  5. ''은 첫 번째 기회에서도 나올 수 있다. 이 경우 첫 번째 '*'의 점수만 2배가 된다.

  6. '*'의 효과는 다른 ''의 효과와 중첩될 수 있다. 이 경우 중첩된 '*' 점수는 4배가 된다.

  7. '*'의 효과는 '#'의 효과와 중첩될 수 있다. 이 경우 중첩된 '#'의 점수는 -2배가 된다.

  8. Single(S), Double(D), Triple(T)은 점수마다 하나씩 존재한다.

  9. '*', '#'은 점수마다 둘 중 하나만 존재할 수 있으며, 존재하지 않을 수도 있다.

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

접근 방식

  1. 먼저 정규식을 사용하여, [점수+영역+보너스] 형태로 문자열을 인식, Split한다.

  2. for문과 if문 그리고 Switch문을 사용하여 각 형태의 점수를 숫자화, Case 분류하여 점수 계산하고 숫자인 형태로 미리 만들어둔 ScoreArray에 Push 한다.

  3. 이때, 특수 문자 '*', '#'가 있을 시 추가적 연산을 할 수 있도록 한다.

  4. 마지막으로 완성된 ScoreArray의 모든 요소의 합을 구하여 return 한다.

Comfort zone

Step 1

let regExpScore1 = /[SDT][#*]|[SDT]/gi;
let regExpScore2 =  /[0-9]{1,2}/gi;
let DartScore = dartResult.match(regExpScore2);
let DartSection = dartResult.match(regExpScore1);
let ScoreArray = [];

점수를 나타내는 숫자와 영역을 나타내는 S/D/T, 보너스 점수*, #을 각각 다른 배열에 Split하여 할당하였다.(DartScore/DartSection)

어차피 각 배열의 길이는 동일하기 때문에, 문제의 조건에 의한 보너스 점수(*) 연산 수행 시 바로 전의 점수까지 2배를 해줘야 하는데, 이 연산 수행이 더 쉽게 구현될 수 있을 것이라 생각했기 때문이다.


Step 2

for(let i=0; i<3; i++){
 if(DartSection[i].split('').length === 2){
  switch(DartSection[i].split('')[1]){
   case '*' :
   if(DartSection[i].split('')[0]==='S'){
    ScoreArray.push((Number(DartScore[i])**1)*2);
    ScoreArray[i-1]*=2;
    break;
                }
   else if(DartSection[i].split('')[0]==='D'){
    ScoreArray.push((Number(DartScore[i])**2)*2);
    ScoreArray[i-1]*=2;
    break;
                }
   else if(DartSection[i].split('')[0]==='T'){
    ScoreArray.push((Number(DartScore[i])**3)*2);
    ScoreArray[i-1]*=2;
    break;
                }
case '#' :
  if(DartSection[i].split('')[0]==='S'){
    ScoreArray.push((Number(DartScore[i])**1)*(-1));
                    break;
                }
  else if(DartSection[i].split('')[0]==='D'){
    ScoreArray.push((Number(DartScore[i])**2)*(-1));
                    break;
                }
  else if(DartSection[i].split('')[0]==='T'){
    ScoreArray.push((Number(DartScore[i])**3)*(-1));
                    break;
                }
        }

Step 1에서 정규식을 활용하여 filtering한 DartSection(D/T/S 및 *, #)을 ''기준으로 Split하여 그 length가 2 이거나 1 일 때의 경우로 나누었다. (문제에 의하면 보너스는 있을 수도, 없을 수도 있기 때문에)

만약, 보너스 점수가 존재하여 길이가 2라면 그때의 Case 분류를 Switch를 사용하여 나누었다.

S/D/T 여부에 따라 계산을 수행한다. 이때 점수는 문자 타입이므로 Number를 활용하여 숫자 타입으로 바꿔주었다.

완료된 값은 ScoreArray에 Push한다. 단, 보너스 점수가 *인 경우에 한해, 해당 과정의 바로 전에 연산되어 ScoreArray에 push된 값에 2배를 해주는 연산을 추가한다.

ScoreArray[i-1]*=2;

Step 3

 } else if(DartSection[i].split('').length === 1){
switch(DartSection[i].split('')[0]){
 case 'S' : 
 ScoreArray.push(Number(DartScore[i]**1)); break;
 case 'D' : 
 ScoreArray.push(Number(DartScore[i]**2)); break;
 case 'T' : 
 ScoreArray.push(Number(DartScore[i]**3)); break;
        }
    }
}
console.log(ScoreArray);
var answer = ScoreArray[0]+ScoreArray[1]+ScoreArray[2];

Step 2에 해당하지 않는 예외의 조건으로 보너스 점수가 존재하지 않을 때 연산할 내용이다. 단순 S/D/T여부에 따라 각각 맞는 연산을 수행하여 마찬가지로 ScoreArray에 Push한다.

마지막으로, 완성된 ScoreArray배열의 모든 요소의 합을 answer에 할당한다.

Getting out of comfort zone

왜 Object를 생각 못했을까? 오브젝트를 활용했으면 Switch로 Case 분류할 필요가 없는데..

처음의 풀이와 다르게 추가된 개념으로는 Object 사용과 Object 요소 접근법, Math.pow의 사용, 그리고 reduce이다.

Math.pow(base,square)

그냥 알아만 두자. 제곱할 숫자(base), 지수(square)를 입력하면 제곱 값이 나오는 메서드이다.

이번 풀이의 핵심은 Object의 사용이다. Single/Double/Triple 존을 각 key로 하는 object와 별모양과 우물정자 모양을 key로 하는 object를 만들어서 각 case에 맞게 접근만 해주면 된다.

처음 풀이와 마찬가지로, 숫자만을 나타내는 배열과 문자를 나타내는 배열 두 가지를 만들어 접근했다.(그래도 두 배열의 길이는 동일할 것이므로)

for문을 활용하여 문자를 나타내는 배열을 split했고, Section 및 bonus Object 배열의 임의의 key에 접근하여 Math.pow 메서드에 입력해주었다. bonus에 undefined을 추가하여 별 모양이나 우물 정자 모양이 포함되어 있지 않아도 동작할 수 있도록 한 점도 중요 포인트라 할 수 있겠다.

느낀점

무지성으로 for, if, else if, switch 쓰기 전에 내가 가진 지식으로 더 나은 방법이 있는지 계속 체크하는 습관을 가지자.

profile
Get out of my comfort zone

0개의 댓글