본문 바로가기
알고리즘/BAEKJOON

BOJ 2503 : 숫자 야구

by 피로물든딸기 2021. 5. 13.
반응형

알고리즘 문제 전체 링크

 

www.acmicpc.net/problem/2503

 

이후 설명 및 입/출력은 링크 참고

 

 

숫자 야구의 원리는 삼성 B형 샘플 문제 : 숫자야구게임을 참고하자.

 

이 문제에서는 답이 되는 answerList 배열에서 답이 될 수 없는 숫자를 지워나가는 방식으로 해결한다.


먼저 답의 후보는 100 ~ 999 중, 0이 없고, 중복된 숫자가 없는 번호이다.

따라서 숫자에 0이 포함된 경우와 중복된 번호가 있는 경우에 answerList에 1(삭제)을 표시한다.

int main(void)
{
	scanf("%d", &N);

	int answerList[1000 + 5] = { 0 };

	for (int n = 100; n <= 999; n++)
	{
		if (isIncludeZero(n)) answerList[n] = 1;
		else if (isDuplicateNumber(n)) answerList[n] = 1;
	}

	...
    
}

 

0이 포함되었는지 여부는 나머지 연산을 이용한다.

1의 자리 수가 0이 아닌 경우, num을 10으로 나누고 다시 나머지 연산을 한다.

3번 반복해서 0이 나오지 않으면 0을 return한다.

int isIncludeZero(int num)
{
	for (int i = 0; i < 3; i++)
	{
		if (num % 10 == 0) return 1;
		num /= 10;
	}

	return 0;
}

 

중복된 번호를 찾는 것도 나머지 연산을 이용해 a, b, c 배열에 각 자리수를 담는다.

a, b, c 중 같은 것이 있으면 1을 return하고 그렇지 않으면 0을 return한다.

int isDuplicateNumber(int number)
{
	int a, b, c, num;

	num = number;

	a = num % 10;
	num /= 10;
	b = num % 10;
	num /= 10;
	c = num;

	if (a == b) return 1;
	if (b == c) return 1;
	if (c == a) return 1;

	return 0;
}

이제 야구게임을 할 숫자와 스트라이크 개수, 볼의 개수를 입력받는다.

100 ~ 999까지 answerList가 0인 경우에 대해서 검사를 하면 된다.

그리고 결과를 저장하기 위한 RESULT 구조체를 만든다.

이때, 숫자를 비교하여 strike와 ball의 개수를 쉽게 세기 위해 int형 정수를 int 배열로 바꾸는 함수가 필요하다.

나온 결과의 strike와 ball이 입력과 다르다면 answerList에 1을 표시해 답을 지운다.

typedef struct st
{
	int strike;
	int ball;
}RESULT;

...

int main(void)
{
	...
    
	for(int i = 0; i < N; i++)
	{
		int number, strike, ball;
		int numberArr[3], compare[3];

		scanf("%d %d %d", &number, &strike, &ball);

		intToArray(number, numberArr);
		for (int n = 100; n <= 999; n++)
		{
			if (answerList[n] == 1) continue;

			intToArray(n, compare);

			RESULT result = check(numberArr, compare);

			if (!(result.strike == strike && result.ball == ball))
				answerList[n] = 1;
		}
	}

	...
    
	return 0;
}

 

intToArray는 isDuplicateNumber에서 a, b, c가 아닌 arr 배열에 숫자를 담으면 된다.

void intToArray(int number, int arr[3])
{
	int num = number;

	arr[2] = num % 10;
	num /= 10;
	arr[1] = num % 10;
	num /= 10;
	arr[0] = num;
}

 

이제 두 배열을 비교해서 게임의 결과를 만들어주면 된다.

compTable에 compare의 숫자를 1로 표시하면 ball을 세는 것이 수월하다.

 

만약 compare가 123이라면 compTable[1] = compTable[2] = compTable[3] = 1이 된다.

그러면 각 numberList 배열에 대해 ball인지 아닌지는 compTable[numberList[i]]를 넣어보면 알 수 있다.

RESULT check(int numberList[3], int compare[3])
{
	RESULT result = { 0 };
	int compTable[10 + 2] = { 0 };

	compTable[compare[0]] = compTable[compare[1]] = compTable[compare[2]] = 1;

	for (int idx = 0; idx < 3; ++idx)
		if (numberList[idx] == compare[idx])
			result.strike++;
		else if (compTable[numberList[idx]] == 1)
			result.ball++;

	return result;
}

strike된 숫자는 ball에 포함되지 않으므로, strike check를 먼저한다.

 

마지막으로 지워지지 않은 답(answerList가 0인 경우)에 대해 개수를 세면 된다.

int sum = 0;
for (int n = 100; n <= 999; n++) sum += !answerList[n];

 

최종 코드는 아래와 같다.

#include <stdio.h>

int N;

typedef struct st
{
	int strike;
	int ball;
}RESULT;

int isIncludeZero(int num)
{
	for (int i = 0; i < 3; i++)
	{
		if (num % 10 == 0) return 1;
		num /= 10;
	}

	return 0;
}

int isDuplicateNumber(int number)
{
	int a, b, c, num;

	num = number;

	a = num % 10;
	num /= 10;
	b = num % 10;
	num /= 10;
	c = num;

	if (a == b) return 1;
	if (b == c) return 1;
	if (c == a) return 1;

	return 0;
}

void intToArray(int number, int arr[3])
{
	int num = number;

	arr[2] = num % 10;
	num /= 10;
	arr[1] = num % 10;
	num /= 10;
	arr[0] = num;
}

RESULT check(int numberList[3], int compare[3])
{
	RESULT result = { 0 };
	int compTable[10 + 2] = { 0 };

	compTable[compare[0]] = compTable[compare[1]] = compTable[compare[2]] = 1;

	for (int idx = 0; idx < 3; ++idx)
		if (numberList[idx] == compare[idx])
			result.strike++;
		else if (compTable[numberList[idx]] == 1)
			result.ball++;

	return result;
}

int main(void)
{
	scanf("%d", &N);

	int answerList[1000 + 5] = { 0 };

	for (int n = 100; n <= 999; n++)
	{
		if (isIncludeZero(n)) answerList[n] = 1;
		else if (isDuplicateNumber(n)) answerList[n] = 1;
	}

	for(int i = 0; i < N; i++)
	{
		int number, strike, ball;
		int numberArr[3], compare[3];

		scanf("%d %d %d", &number, &strike, &ball);

		intToArray(number, numberArr);
		for (int n = 100; n <= 999; n++)
		{
			if (answerList[n] == 1) continue;

			intToArray(n, compare);

			RESULT result = check(numberArr, compare);

			if (!(result.strike == strike && result.ball == ball))
				answerList[n] = 1;
		}
	}

	int sum = 0;
	for (int n = 100; n <= 999; n++) sum += !answerList[n];

	printf("%d\n", sum);

	return 0;
}
반응형

'알고리즘 > BAEKJOON' 카테고리의 다른 글

BOJ 1939 : 중량제한  (0) 2021.05.22
BOJ 5896 : 효율적으로 소 사기  (2) 2021.05.18
BOJ 2745 : 진법 변환  (0) 2021.05.08
BOJ 2609 : 최대공약수와 최소공배수  (0) 2021.05.05
BOJ 1913 : 달팽이  (0) 2021.04.30

댓글