C++

백준 2503번 숫자야구

Bubbles 2021. 12. 11. 01:31

https://www.acmicpc.net/problem/2503

 

2503번: 숫자 야구

첫째 줄에는 민혁이가 영수에게 몇 번이나 질문을 했는지를 나타내는 1 이상 100 이하의 자연수 N이 주어진다. 이어지는 N개의 줄에는 각 줄마다 민혁이가 질문한 세 자리 수와 영수가 답한 스트

www.acmicpc.net

맞은 것 같은데 자꾸 에러나서 확인해보니 조건 하나 빼먹었었다... 문제를 꼼꼼하게 보자...

- 각 자리 수 다 다르고 모든 자리에 0이 들어가면 안된다. 
- 숫자와 위치까지 맞추면 스트라이크, 숫자만 맞추면 볼
- 각 자리별로 비교해야 하므로 문자열로 만들어서 비교하자

 


< 코드 작성 전 정리 한 것 >

- 질문을 통해 답변받은 숫자들은 구조체 형태로 정리하고 구조체 배열에 각각 넣어두었다. num은 문자열 형태로 넣어두었다. (어차피 나중에 한 자리씩 비교해야 하니까)

num 123 356 327 489
strike 1 1 2 0
ball 1 0 0 1

- 각 숫자별로 비교할 때 중첩 for문 사용해서 탐색해야 한다. 단순 숫자만 같아서 ball인지, 위치까지 같아서 strike인지 개수 세야하기 때문

- 123~987까지만 탐색하면 된다. (이 때 987 이하이므로 =붙여줘야함) 세자리 숫자들을 모두 돌면서, 사전에 입력된 검사 결과들( ex 123이면 스트라이크 1 볼 1 이런식)과 비교해서 맞는 조건인지 확인.

- 모든 조건 만족시에만 정답에 넣을 것 (answer vector사용, 나중에 size만 출력해줬음)


우선 전체 코드... 

#include <iostream>
#include <string>
#include <vector>
using namespace std;
struct Number {
    string number;
    int strike;
    int ball;
};
vector <Number> numbers;
vector <string> answers;

bool checkNum(string num) {
    if (num[0] == '0' || num[1] == '0' || num[2] == '0') {
        return false;
    }
    else if (num[0] == num[1] || num[1] == num[2] || num[0] == num[2]) {
        return false;
    }
    else {
        return true;
    }
}

bool compareNum(string num, string comparenum, int strike, int ball) {
    int i, j, strike_count = 0, ball_count = 0;
    for (i=0; i<3; i++) {
        for (j=0; j<3; j++) {
            if (num[i] == comparenum[j]) {
                if (i == j) {
                    strike_count++; 
                }
                else {
                    ball_count++; 
                }
            }
        }
    }
    
    if (strike_count == strike && ball_count == ball) {
        return true;
    } 
    else {
        return false;
    }
}

int main() {
    int i, j, size, strike, ball;
    string num, temp;
    bool flag;
    cin>>size;
    for (i=0; i<size; i++) {
        Number number;
        cin>>num;
        cin>>strike;
        cin>>ball;
        number.number = num;
        number.strike = strike;
        number.ball = ball;
        numbers.push_back(number);
    }

    for (i=123; i<=987; i++) {
        flag = true;
        temp = to_string(i); 
        if (!checkNum(temp)) {
            continue;
        }
        else {
            for (j=0; j<size; j++) { 
                if (!compareNum(temp, numbers[j].number, numbers[j].strike, numbers[j].ball)) {
                   flag = false;
                   break;
                }
            }
        }
        if (flag == true) {
            answers.push_back(temp);
        }
    }
    cout<<answers.size();
}

 


각 코드 별 부연설명

1. checkNum

bool checkNum(string num) {
    if (num[0] == '0' || num[1] == '0' || num[2] == '0') {
        return false;
    }
    else if (num[0] == num[1] || num[1] == num[2] || num[0] == num[2]) {
        return false;
    }
    else {
        return true;
    }
}

123~987 숫자 중에서 0이 들어가거나, 각 자릿수 중 하나라도 겹치는 부분 있는 숫자는 탐색 대상에서 제거해야 한다. 그러기 위해 만든 함수. 

 

 

2. compareNum

매개변수로 검사할 숫자인 num과 이미 numbers구조체 벡터에 넣어둔 각 숫자들을 비교해서 strike개수와 ball개수가 맞는지 비교하는 함수이다.  

bool compareNum(string num, string comparenum, int strike, int ball) {
    int i, j, strike_count = 0, ball_count = 0; 
    for (i=0; i<3; i++) {
        for (j=0; j<3; j++) {
            if (num[i] == comparenum[j]) {
                if (i == j) {
                    strike_count++; //자리까지 같으면 strike조건에 만족하는 것
                }
                else {
                    ball_count++; // 숫자는 같으나 자리가 다르면 ball
                }
            }
        }
    }

    //최종적으로 ball개수랑 strike개수가 원래거랑 맞는지 확인
    if (strike_count == strike && ball_count == ball) {
        return true;
    } 
    else {
        return false;
    }
}

 

3. 메인함수 

int main() {
    int i, j, size, strike, ball;
    string num, temp;
    bool flag;
    
    cin>>size; // 검증된 숫자 개수 
    
    for (i=0; i<size; i++) {
        Number number;
        cin>>num;
        cin>>strike;
        cin>>ball;

        number.number = num;
        number.strike = strike;
        number.ball = ball;

        numbers.push_back(number); // 검사된 숫자들 넣어둠.
    }

    for (i=123; i<=987; i++) {
        flag = true;
        temp = to_string(i); // 각 숫자별 비교를 위해 문자열로 전환
        if (!checkNum(temp)) {
            continue; // 겹치는 숫자 있을경우 연산 필요 없이 다음 숫자로 넘김
        }
        else {
            for (j=0; j<size; j++) { // 검증 횟수만큼 숫자 검사
                if (!compareNum(temp, numbers[j].number, numbers[j].strike, numbers[j].ball)) {
                   flag = false;
                   break;
                }
            }
        }
        if (flag == true) {
            answers.push_back(temp);
        }
    }
    
    cout<<answers.size();
}

numbers가 질의응답 했던 숫자들 담아둔 구조체 배열이고, 응답의 모든 조건들을 다 검사해야 하고, 그 각각의 스트라이크 / 볼 횟수가 다 일치해야만 answers에 추가한다. 하나라도 false뜨면 안되므로 flag변수를 하나 넣어놨다.