본문 바로가기
Computer Science

4 Problem C : 숫자 야구2

by OKOK 2020. 1. 27.

Problem C : 숫자 야구2

 

제한시간: 1000 ms    메모리제한: 128 MB
Special Judge

 

 

 정현이는 다음과 같이 동작하는 숫자 야구 프로그램을 만들었다.

 

* 프로그램은 0~9까지 10개의 수를 사용하여 4자리 수의 정답을 생성한다. 0으로 시작할 수 있다.

* 10개의 수는 한번씩만 사용되므로 정답에 중복된 수는 없다.

* 프로그램에게 임의의 4자리 수를 물어보면 프로그램은 그 수를 정답과 비교한 결과를 알려준다.

* 프로그램은 자리가 일치한 숫자는 strike, 

  정답에 포함되나 자리가 틀린 수를 ball로 판단하여 strike와 ball의 수를 알려준다.

  따라서 정답을 맞췄을 경우 프로그램의 리턴값은 strike=4, ball=0 이다.  

 

사용자 코드가 아래와 같이 주어질 때, 주어진 소스를 분석하여 

프로그램에게 질의하는 query 함수를 최대한 적게(10번 이하) 호출하여
정답을 맞출 수 있도록 tryBest​함수를 완성하시오.

 

* 질의는 query 함수를 사용하며 정답은 tryBest함수의 input parameter int suppose[] 배열에 저장한다.

* struct Result 와 함수 Result query(int suppose[]) 는 수정할 수 없다.

* 그 외 추가적인 전역변수나 함수는 사용 가능하다.

* 질의 수가 2,520을 초과하거나 1124 같은 잘못된 숫자를 질의했을 경우 

   프로그램은 strike=-1, ball=-1을 리턴한다.

 

 

[참고]

사용자 소스파일을 분리컴파일 하여 문제를 푸는경우 

사용자는 아래 정의한 구조체를 사용자 소스 파일의 상단에 추가하여 코딩합니다.

 

// *** user.cpp ***
2.#ifdef _WIN32
3.#define ACTIVE 1
4.#else
5.#define ACTIVE 0
6.#endif // __WIN32
7.#if ACTIVE
8.typedef struct Data {
9.    int strike;
10.    int ball;
11.} Data;
12. 
13.#endif // ACTIVE
14. 
15.extern Data query(int supose[]);
16. 
17.void tryBest(int suppose[]) {
18. 
19.}
20. 
21. 
22.// *** main_code ***
23. 
24.#define _CRT_SECURE_NO_WARNINGS
25.#include <stdio.h>
26.#include <stdlib.h>
27.#include <time.h>
28. 
29.#define MAX          4
30.#define MAX_COUNT 2520
31. 
32.static int baseballNumbers[MAX];
33.static int numbersCheck[10];
34. 
35.static int T;
36. 
37.extern void tryBest(int suppose[]); ////************
38. 
39.static int queryCallCount;
40. 
41.static const int queryLimit = 110;
42.static int scoreTable[MAX_COUNT + 5];
43. 
44.typedef struct Data {
45.    int strike;
46.    int ball;
47.} Data;
48. 
49.static bool isAble(int suppose[]) {
50.    int supposeCheck[10];
51. 
52.    for (int count = 0; count < 10; ++count)
53.        supposeCheck[count] = 0;
54.    for (int idx = 0; idx < MAX; ++idx) {
55.        if (suppose[idx] < 0 || suppose[idx] >= 10 || supposeCheck[suppose[idx]] > 0)
56.            return false;
57.        supposeCheck[suppose[idx]]++;
58.    }
59.    return true;
60.}
61. 
62.Data query(int suppose[]) {
63.    Data result;
64. 
65.    if (queryCallCount > MAX_COUNT) {
66.        result.strike = -1;
67.        result.ball = -1;
68.        return result;
69.    }
70. 
71.    queryCallCount++;
72. 
73.    if (!isAble(suppose)) {
74.        result.strike = -1;
75.        result.ball = -1;
76.        return result;
77.    }
78. 
79.    result.strike = 0;
80.    result.ball = 0;
81. 
82.    for (int idx = 0; idx < MAX; ++idx)
83.        if (suppose[idx] == baseballNumbers[idx])
84.            result.strike++;
85.        else if (numbersCheck[suppose[idx]] > 0)
86.            result.ball++;
87. 
88.    return result;
89.}
90. 
91.static void initialize() {
92.    for (int count = 0; count < 10; ++count)
93.        numbersCheck[count] = 0;
94.    for (int idx = 0; idx < MAX;) {
95.        int c = rand() % 10;
96.        if (numbersCheck[c] == 0) {
97.            baseballNumbers[idx] = c;
98.            numbersCheck[c]++;
99.            idx++;
100.        }
101.    }
102.    queryCallCount = 0;
103.}
104. 
105.static bool check(int suppose[]) {
106.    for (int idx = 0; idx < MAX; ++idx) {
107.        if (suppose[idx] != baseballNumbers[idx])
108.            return false;
109.    }
110.    return true;
111.}
112. 
113. 
114.void initScoreTable() {
115.    int i;
116.    for (i = 0; i <= 10; ++i)
117.        scoreTable[i] = 100;
118.    for (; i <= queryLimit; ++i)
119.        scoreTable[i] = 110 - i;
120.}
121. 
122. 
123.int main() {
124.    int total_score = 0;
125. 
126.//freopen("input.txt", "r", stdin);
127.    setbuf(stdout, NULL);
128. 
129.//scanf("%d", &T);
130.    T = 50;
131.    initScoreTable();
132.    srand((unsigned int)time(NULL));
133.    for (int testcase = 1; testcase <= T; ++testcase) {
134.        initialize();
135. 
136.        int suppose[MAX] = { 0 };
137.        tryBest(suppose);
138. 
139.        if (!check(suppose)) {
140.            queryCallCount = MAX_COUNT;
141.            total_score = 0;
142.            break;
143.        }
144.        printf("#%d %d : ", testcase, queryCallCount);
145.        for (int i = 0; i < 4; ++i)
146.            printf("%d", suppose[i]);
147.        puts("");
148.        if (queryCallCount > queryLimit)
149.            queryCallCount = queryLimit;
150.        total_score += scoreTable[queryCallCount];
151.    }
152.    printf("Total Score = %d\n", total_score / T);
153. 
154.    return 0;
155.}

 

// main.c
#include <stdio.h> 
#include <stdlib.h> 
#include <time.h> 

#define MAX          4 
#define MAX_COUNT 2520 
#define _CRT_SECURE_NO_WARNINGS 

static int baseballNumbers[MAX];
static int numbersCheck[10];

static int T;

extern void tryBest(int suppose[]); ////************ 

static int queryCallCount;

static const int queryLimit = 110;
static int scoreTable[MAX_COUNT + 5];

typedef struct Data {
	int strike;
	int ball;
} Data;

static bool isAble(int suppose[]) {
	int supposeCheck[10];

	for (int count = 0; count < 10; ++count) supposeCheck[count] = 0;
	for (int idx = 0; idx < MAX; ++idx) {
		if (suppose[idx] < 0 || suppose[idx] >= 10 || supposeCheck[suppose[idx]] > 0) return false;
		supposeCheck[suppose[idx]]++;
	}
	return true;
}

Data query(int suppose[]) {
	Data result;

	if (queryCallCount > MAX_COUNT) {
		result.strike = -1;
		result.ball = -1;
		return result;
	}

	queryCallCount++;

	if (!isAble(suppose)) {
		result.strike = -1;
		result.ball = -1;
		return result;
	}

	result.strike = 0;
	result.ball = 0;

	for (int idx = 0; idx < MAX; ++idx)
	if (suppose[idx] == baseballNumbers[idx])
		result.strike++;
	else if (numbersCheck[suppose[idx]] > 0)
		result.ball++;

	return result;
}

static void initialize() {
	for (int count = 0; count < 10; ++count) numbersCheck[count] = 0;
	for (int idx = 0; idx < MAX;) {
		int c = rand() % 10;
		if (numbersCheck[c] == 0)
		{
			baseballNumbers[idx] = c;
			numbersCheck[c]++;
			idx++;
		}
	}
	queryCallCount = 0;
}

static bool check(int suppose[]) {
	for (int idx = 0; idx < MAX; ++idx)
	{
		if (suppose[idx] != baseballNumbers[idx])
			return false;
	}
	return true;
}

void initScoreTable() {
	int i;
	for (i = 0; i <= 10; ++i) scoreTable[i] = 100;
	for (; i <= queryLimit; ++i) scoreTable[i] = 110 - i;
}


int main() {
	int total_score = 0;

	//freopen("sample_input.txt", "r", stdin); 
	setbuf(stdout, NULL);

	//scanf("%d", &T); 
	T = 1;
	initScoreTable();
	srand((unsigned int)time(NULL));
	for (int testcase = 1; testcase <= T; ++testcase) {
		initialize();

		int suppose[MAX];
		tryBest(suppose);

		if (!check(suppose)) {
			queryCallCount = MAX_COUNT;
			total_score = 0;
			break;
		}
		printf("#%d %d : ", testcase, queryCallCount);
		for (int i = 0; i < 4; ++i) printf("%d", suppose[i]);
		puts("");
		//if (queryCallCount > queryLimit)
		//	queryCallCount = queryLimit;
		total_score += queryCallCount;
	}
	printf("Total Score = %d\n", total_score);

	return 0;
}
// user.c
typedef struct Data {
	int strike;
	int ball;
} Data;

int chk[10000];

extern Data query(int supose[]);

void encode(int num, int arr[])
{
	for (int i = 3; i >= 0; i--) {
		arr[i] = num % 10;
		num /= 10;
	}
}

Data myquery(int a[], int b[])
{
	Data result = { 0, 0 };

	for (int i = 0; i < 4; i++) {
		for (int j = 0; j < 4; j++) {
			if (a[i] == b[j]) {
				if (i == j) result.strike++;
				else result.ball++;
			}
		}
	}
	return result;
}

int confirm(int num)
{
	int arr1[4], arr2[4], cnt = 0, ans;
	encode(num, arr1);
	Data result1 = query(arr1), result2; // query 불러서 확인함
	if (result1.strike == 4) return num; // 정답입니다
	for (int i = num + 1; i <= 9876; i++) { // 다음 숫자를 넘어봄
		if (chk[i]) continue;
		encode(i, arr2);
		result2 = myquery(arr1, arr2);
		if (result1.strike != result2.strike || result1.ball != result2.ball) chk[i] = 1; // 거른다
		else {
			cnt++;
			ans = i;
		}
	}
	if (cnt == 1) return ans;
	return -1;
}

void tryBest(int suppose[]) {
	int i, j, k;
	for (i = 123; i <= 9876; i++) { // 0123 ~ 9876  차례대로 검사
		chk[i] = 0;
		encode(i, suppose);
		for (j = 0; j < 3; j++) for (k = j + 1; k < 4; k++) {
			if (suppose[j] == suppose[k]) chk[i] = 1; // 같은 숫자가 있으면 chk 표시함
		}
	}
	for (i = 123; i <= 9876; i++) {
		if (chk[i]) continue; // 중복된 수는 거르고
		k = confirm(i);
		if (k >= 0) break;
	}
	encode(k, suppose);
}

'Computer Science' 카테고리의 다른 글

Problem A : Bit_ImageMap3  (0) 2020.01.30
Problem D : 어디 있니?( where are you?)  (0) 2020.01.28
4 Problem B : 타일 채우기  (0) 2020.01.13
4 Problem A : 책 복사하기  (0) 2020.01.13
Problem D : 쌓기나무  (0) 2020.01.10

댓글