백준 2503번 숫자야구
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변수를 하나 넣어놨다.