프로그래머스 - [1차] 다트 게임 (Lv.1)

2 minute read

문제 링크

문제 접근

  • dartResult 로 주어진 문자열을 파싱만 잘하면 된다.
  • 총 3번의 시도를 하기 때문에 점수판은 길이가 3인 배열로 표현한다.
  • 문자열을 탐색하며 숫자 문자인 경우 string 자료형인 str 에 담는다.
  • 숫자 뒤에는 바로 S, D, T 의 보너스 문자가 반드시 나오므로 해당 문자가 나오면 str 에 담아둔 숫자 문자열을 정수로 변환한다.
  • 보너스 문제에 맞도록 추가 점수 연산을 한다.
  • 다음 문자를 확인해서 옵션에 해당하는 스타상(*), 아차상(#) 인 경우 추가 연산을 한다.
  • scores 인덱스를 증가시키괴 다음 위 과정을 반복한다.

구현(All Pass)

#include <string>
#include <cctype>
#include <iostream>
#include <vector>

using namespace std;

int solution(string dartResult) {
    int answer = 0;
    
    vector<int> scores(3,0);
    string str;
    int idx = 0;
    for(int i=0; i<dartResult.size(); i++){
        char ch = dartResult[i];
        if(isdigit(ch)){
            str.push_back(ch);
        }
        else if(ch=='S' || ch=='D' || ch=='T'){
            int num = stoi(str);
            str.clear();
            if(ch=='D') num = num*num;
            else if(ch=='T') num = num*num*num;
            scores[idx] = num;
            
            // 스타상, 아차상 확인
            if(i==dartResult.size()-1) continue;
            char nCh = dartResult[i+1];
            if(nCh=='*'){
                if(idx>0) scores[idx-1] = scores[idx-1] * 2;
                scores[idx] = scores[idx] * 2;
                i++;
            }
            else if(nCh=='#'){
                scores[idx] = scores[idx] * (-1);
                i++;
            }
            idx++;
        }
    }
    
    answer = scores[0] + scores[1] + scores[2];
    return answer;
}

추가 풀이

  • 다른 사람의 풀이를 보다가 좋은 방법이 있어서 직접 구현해보았다.
  • stringstream 을 활용하여 자료형 별로 입력을 받아 문자열 파싱을 쉽게 구현했다.

구현 - » 연산자를 활용했을 때 분석 (틀린 풀이)

#include <string>
#include <sstream>
#include <iostream>
#include <vector>

using namespace std;

int solution(string dartResult) {
    int answer = 0;
    stringstream ss(dartResult);
    
    vector<int> scores(3, 0);
    int num;
    char bonus, option;
    for(int i=0; i<3; i++){
        ss >> num >> bonus >> option;
        cout << num << " " << bonus << " " << option << endl;
        if(option != '*' && option != '#')
            ss.unget(); // 버퍼의 커서를 앞으로 옮긴다.
        
        // 보너스
        if(bonus=='D') num = num*num;
        else if(bonus=='T') num = num*num*num;
        scores[i] = num;
        
        // 옵션
        if(option=='*'){
            if(i>0) scores[i-1] = scores[i-1] * 2;
            scores[i] = scores[i]*2;
        }
        else if(option=='#'){
            scores[i] = scores[i] * (-1);
        }
    }
    
    answer = scores[0] + scores[1] + scores[2];
    return answer;
}

  • » 입력 연산자는 개행 문자를 만나면 더이상 입력을 받지 않는다.
  • 위 코드에서 stringstream 을 통해 » 연산자로 입력을 받는 경우 개행 문자를 만나면 입력을 받지 않게 되면서 option 변수에 아무런 문자도 들어오지 않게 된다. 따라서, option 변수에는 이전에 저장되어 있던 값이 그대로 사용되는 것이다.

구현 - get() 입력함수로 개행문자, 공백문자도 받아들이도록 함

#include <string>
#include <sstream>
#include <iostream>
#include <vector>

using namespace std;

int solution(string dartResult) {
    int answer = 0;
    stringstream ss(dartResult);
    
    vector<int> scores(3, 0);
    int num;
    char bonus, option;
    for(int i=0; i<3; i++){
        ss >> num;
        bonus = ss.get();
        option = ss.get();
        
        if(option != '*' && option != '#')
            ss.unget(); // 버퍼의 커서를 앞으로 옮긴다.
        
        // 보너스
        if(bonus=='D') num = num*num;
        else if(bonus=='T') num = num*num*num;
        scores[i] = num;
        
        // 옵션
        if(option=='*'){
            if(i>0) scores[i-1] = scores[i-1] * 2;
            scores[i] = scores[i]*2;
        }
        else if(option=='#'){
            scores[i] = scores[i] * (-1);
        }
    }
    
    answer = scores[0] + scores[1] + scores[2];
    return answer;
}

  • get() 함수는 공백문자, 개행문자를 포함하여 문자를 버퍼에서 읽어오고, 커서를 다음으로 옮긴다.
  • unget() 함수는 버퍼의 커서를 앞으로 한칸 옮긴다.

Leave a comment