Posts 알고리즘 - Array 1(Exhaustive Search, Baby-gin Game)
Post
Cancel

알고리즘 - Array 1(Exhaustive Search, Baby-gin Game)

본격적인 내용에 앞서, 앞으로 공부는 이렇게 진행할 예정입니다.

사이트 https://swexpertacademy.com/main/learn/course/courseList.do 를 접속하면 위처럼 무료로 수강할 수 있는 강좌 목록들이 나옵니다.

초심부터 한다는 생각으로 Programming Intermediate 과정부터 차근차근 해 볼 예정입니다.

Programming Intermediate 과정은 프로그래밍을 위한 기본 내용들을 학습할 수 있습니다.

Array부터 시작해 Tree까지, 알고리즘을 구현하는 데 있어서 가장 기본이 되는 자료 구조들을 학습해볼 수 있습니다. 그리고 Self Stdy Book 에서 이것들을 활용한 간단한 알고리즘 예제들도 풀어볼 수 있습니다.

혼자 알고리즘을 공부하는 데는 이만한 사이트가 정말 없는 것 같습니다.. 최고입니다.


Exhaustive Search(완전 검색)

완전 검색은 모든 경우의 수를 나열해보고 확인하는 기법입니다. Brute-Force 또는 Generate-And-Test 기법이라고 부르기도 합니다.

당연히 경우의 수가 상대적으로 작을 때 유용할 것이고, 수행 속도는 느릴 수 있지만 해답을 찾지 못할 확률은 적습니다.

그래서 문제를 풀 때는 우선 완전 검색으로 접근해 해답을 도출하고, 성능 개선을 위해 다른 알고리즘을 사용하고 해답을 확인하는 것이 바람직하다고 합니다.

문제에 대한 적합한 알고리즘이 바로 생각난다면 그것으로 하고, 생각이 안 나면 완전 검색부터 이용한다는 의미로 받아들였습니다.

| Baby-gin Game

0에서 9 사이의 숫자 카드에서 임의로 카드 6장을 뽑을 때, 3장의 카드가 연속적인 번호를 가지는 경우를 run 이라 하고, 3장의 카드가 동일한 번호를 갖는 경우를 triplete 라고 합니다. 6장의 카드가 run, triplete 로 구성되어 있을 경우를 Baby-gin 이라 합니다.

[예] 667767은 두 개의 triplete이다. => 666,777, Baby-gin

[예] 054060은 1 개의 run과 한 개의 triplete이다. => 000,456, Baby-gin

[예] 101123은 1 개의 triplete가 존재하나(111), 023이 run이 아니므로 Baby-gin 이 아니다.

이 문제를 완전 검색 방법으로 접근해 보는 방식은 다음과 같습니다.

  • input으로 6개의 숫자를 입력받는다면 그것으로 만들 수 있는 모든 순열을 생각해 본다. 그런 다음 앞의 3자리와 뒤의 3자리를 잘라서 run과 triplete 여부를 테스트해 본다.

완전 검색 방식으로 코딩을 하는 것은 가장 단순하다고 볼 수 있습니다. 입력받은 6개의 숫자가 Baby-gin 인지 판별하는 코드를 순열로 경우의 수를 모두 판단하는 방식으로 작성해 봅니다.

[순열 알고리즘을 포함한 Baby-gin 판별 프로그램]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
#include <iostream>
#include <ctime>
using namespace std;

int num = 6;
int ginCount = 0; // count가 2이면 baby-gin이다.
int NumOfBabyGin = 0;

void swap(int* arr, int depth, int i) {
	int temp = arr[depth];
	arr[depth] = arr[i];
	arr[i] = temp;
}

void print(int* arr, int r) {
	for (int i = 0; i < r; i++) {
		cout << arr[i] << ' ';
	}
	cout << endl;
}

void isBabyGin(int* arr, int n) {

	// 1. 맨 앞의 3자리가 동일한 숫자일 경우 - triplete 1개
	if (arr[0] == arr[1] && arr[1] == arr[2]) {
		ginCount++;
	}
	// 2. 그 다음 3자리가 동일한 숫자일 경우 - triplete 1개
	if (arr[3] == arr[4] && arr[4] == arr[5]) {
		ginCount++;
	}
	// 3. 맨 앞의 3자리가 연속된 숫자일 경우 - run 1개
	if (arr[0] + 1 == arr[1] && arr[1] + 1 == arr[2]) {
		ginCount++;
	}
	// 4. 그 다음 3자리가 연속된 숫자일 경우 - run 1개
	if (arr[3] + 1 == arr[4] && arr[4] + 1 == arr[5]) {
		ginCount++;
	}

	if (ginCount == 2) {
		NumOfBabyGin++;
	}

	ginCount = 0;
}

void permutation(int* arr, int depth, int n, int r) {
	if (depth == r) {
		//print(arr, r);
		isBabyGin(arr, n);
		return;
	}

	for (int i = depth; i < n; i++) {
		swap(arr, depth, i);
		permutation(arr, depth + 1, n, r);
		swap(arr, depth, i);
	}
}


int main() {

	// 수 6개를 랜덤으로 지정하고자 할 때
	/*
	srand((unsigned int)time(0));
	int arr[6];	
	int RandomNum;
	for (int i = 0; i < num; i++) {
		RandomNum = rand() % 10;
		arr[i] = RandomNum;
	}
	*/

	int arr[6] = { 1,3,2,7,7,7 };

	// 순열 알고리즘으로 모든 경우의 수를 나타내고 baby-gin 판단하기
	permutation(arr, 0, num, num);

	cout << "뽑힌 6장의 카드 : ";
	for (int i = 0; i < num; i++)
		cout << arr[i] << ' ';
	cout << endl;

	if (NumOfBabyGin > 0) {
		cout << "해당 6개의 숫자는 Baby-gin 입니다. ";
	}
	else {
		cout << "해당 6개의 숫자는 Baby-gin이 아닙니다. ";
	}
}

입력받은 6개의 숫자가 Baby-gin인지 아닌지를 판별해 줍니다.

6개의 숫자로 만들 수 있는 모든 6자리 숫자들을 순열 알고리즘을 통해 만든 다음, 그것을 Baby-gin인지 아닌지 판단하는 단순한 과정입니다.

이렇게 6개의 숫자에 대한 모든 경우의 수를 가지고 찾았기 때문에 이를 두고 완전검색이라고 할 수 있습니다.

제목 1(sw 가이드)

알고리즘 - 그리디 알고리즘(Greedy Algorithm)