본문 바로가기

알고리즘

[2019 KAKAO BLIND RECRUITMENT] 블록 게임(C++)

https://tech.kakao.com/2018/09/21/kakao-blind-recruitment-for2019-round-1/

 

2019 카카오 신입 공채 1차 코딩 테스트 문제 해설

작년에 이어 올해도 블라인드 전형으로 카카오 개발 신입 공채가 시작되었습니다! 그 첫 번째 관문으로 1차 온라인 코딩 테스트가 지난 9월 15일(토) 오후 2시부터 7시까지 5시간 동안 치러졌는데요. 지원자분들 만큼이나 준비위원들도 테스트가 문제없이, 공정하게 치러질 수 있도록 많은 준비를 했고 두근 거리는 마음으로 끝까지 온라인 테스트를 모니터링했답니다. 문제는 작년과 비슷하게 구현 문제 위주로 쉬운 난이도에서 어려운 […]

tech.kakao.com

 

오랜만에 한 번만에 끝낸 문제!

접근법 공유해드립니다.

 


 

코드를 바로 작성하기 전에 문제를 파악하고 어떻게 풀어야 할까를 먼저 생각해봐야 한다. 이 문제는 절대 시뮬레이션 문제가 아니다!

 


 

우선, 문제를 살펴보자!

하나의 모형은 4개의 블럭으로 구성되어 있다. 4개로 이루어진 블록들중에서도, 없앨 수 있는 블록은 5가지가 존재한다.

5가지 모형에 대해서 표현해보겠다.

 

 

 

1. ___|

 

2. |___

 

3. ㅗ

 

4. |_

 

5. _|

 

 

이 5가지가 미래에(?) 없애질 가능성이 있는 놈들이다. 

 

 

 

우선 모든 블록 조합들을 파악하기 위해서, vector<pair<int,int>> v[201]의 자료구조에 모든 블록조합을 넣는다. 1 ~ 200까지 자연수로 이루어졌으므로, 201을 설정했다.

 

 

 

 

이제 이 자료구조를 모두 탐색하며, 미래에 없애질 놈들을 찾아서 새로운 자료구조에 넣어야 한다.

1번 모형(___|) 에 대해서 생각해보면, 가장 꼭대기에 있는 애가 0번째 원소가 될 것이고, 아래부터 차례로 1,2,3번을 구성할 것이다. 이 순서는, board 자료구조를 읽는 방식에 의해서 설정된 것이다.

 

 

 

 

 

1,2,3번 블록들은 행 인덱스가 동일해야 하고, 각 열은 1씩 차이로 구성되어야 한다. 0번과 1번 블록은 열 인덱스가 같아야 하고 행은 1차이가 나야 한다.

 

 

이 것을 코드로 구현하면 다음과 같다. 이런 식으로 2, 3, 4, 5번 모형에 대해서도 구현해야 하면 된다.

 

1
2
3
4
5
6
        // |___ : Type 1
        if (b_v[i][1].first == b_v[i][2].first && b_v[i][2].first == b_v[i][3].first
            && b_v[i][1].second + 1 == b_v[i][2].second && b_v[i][2].second + 1 && b_v[i][3].second
            && b_v[i][0].first + 1 == b_v[i][1].first && b_v[i][0].second == b_v[i][1].second) {
 
        }
http://colorscripter.com/info#e" target="_blank" style="color:#4f4f4ftext-decoration:none">Colored by Color Scripter
 

 

 


 

자, 이제 미래에 없어질 후보들이 진짜 없어질지에 대해서 확인해야 한다. 블록이 없어지기 위해서는 검은 블록을 이용해 꽉 찬 직사각형을 만들어야 한다.

 

 

검은 블록이 해당 블록으로 안전하게(?) 내려올 수 있어야 없어질 수 있다. 따라서, 안전하게 내려올 수 있는지를 확인해줘야 한다.

 

 

확인하는 것은 반복문을 통해서 쉽게 확인할 수 있다.

 

 

삭제될 수 있는 블록들의 인덱스를 저장해두고 후보들에서 일괄적으로 삭제하고, 배열에서도 0으로 표시해야 한다.

다시 후보들중에서 사라질 수 있는 것들을 탐색해야 한다.

 

 

이 과정을 반복하면 쉽게 문제를 해결할 수 있다.

 

 


 

추가적으로, 코드 구현에는 문제가 없지만 Segmentation Error가 발생할 수 있다. 나도 같은 에러를 겪었는데, 이유는 블록들을 구성하는 숫자가 1~N(N<=200)까지 연속적으로 발생한다고 착각을 했기 때문이다. 이 부분을 염두하고 코드를 수정한다면, 쉽게 통과할 수 있을 것이다.

 

 


코드구현(C++)

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
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
#include <string>
#include <vector>
#include <iostream>
#include <algorithm>
#include <set>
 
using namespace std;
 
int solution(vector<vector<int>> board) {
    int answer = 0;
    vector<vector<int>> copy(board);
    vector<pair<intint>> b_v[201];
    set<pair<intint>> s;
    int length = 0;
    for (int i = 0; i < copy.size(); i++) {
        for (int j = 0; j < copy[i].size(); j++) {
            if (copy[i][j] != 0) {
                b_v[copy[i][j]].push_back(make_pair(i, j));
                length = max(length, copy[i][j]);
            }
        }
    }
 
    // Find
    for (int i = 1; i <= length; i++) {
        if (b_v[i].size() == 0)
            continue;
        // |___ : Type 1
        if (b_v[i][1].first == b_v[i][2].first && b_v[i][2].first == b_v[i][3].first
            && b_v[i][1].second + 1 == b_v[i][2].second && b_v[i][2].second + 1 && b_v[i][3].second
            && b_v[i][0].first + 1 == b_v[i][1].first && b_v[i][0].second == b_v[i][1].second) {
            s.insert(make_pair(i, 1));
        }
        // ___| : Type 2
        else if (b_v[i][1].first == b_v[i][2].first && b_v[i][2].first == b_v[i][3].first
            && b_v[i][1].second + 1 == b_v[i][2].second && b_v[i][2].second + 1 && b_v[i][3].second
            && b_v[i][0].first + 1 == b_v[i][3].first && b_v[i][0].second == b_v[i][3].second) {
            s.insert(make_pair(i, 2));
        }
        // ㅗ : Type 3
        else if (b_v[i][1].first == b_v[i][2].first && b_v[i][2].first == b_v[i][3].first
            && b_v[i][1].second + 1 == b_v[i][2].second && b_v[i][2].second + 1 && b_v[i][3].second
            && b_v[i][0].first + 1 == b_v[i][2].first && b_v[i][0].second == b_v[i][2].second) {
            s.insert(make_pair(i, 3));
        }
        // |_ : Type 4
        else if (b_v[i][0].first + 1 == b_v[i][1].first && b_v[i][1].first + 1 == b_v[i][2].first
            && b_v[i][0].second == b_v[i][1].second && b_v[i][1].second == b_v[i][2].second
            && b_v[i][3].first == b_v[i][2].first && b_v[i][2].second + 1 == b_v[i][3].second) {
            s.insert(make_pair(i, 4));
        }
        // _| : Type 5
        else if (b_v[i][0].first + 1 == b_v[i][1].first && b_v[i][1].first + 1 == b_v[i][3].first
            && b_v[i][0].second == b_v[i][1].second && b_v[i][1].second == b_v[i][3].second
            && b_v[i][2].first == b_v[i][3].first && b_v[i][2].second + 1 == b_v[i][3].second) {
            s.insert(make_pair(i, 5));
        }
    }
 
    // While Check
    while (s.size() != 0) {
        vector<pair<intint>> d_v;
        for (set<pair<intint>>::iterator it = s.begin(); it != s.end(); it++) {
            int idx = (*it).first;
            int type = (*it).second;
            // |___ : Type 1
            if (type == 1) {
                int row = b_v[idx][2].first - 1;
                int col1 = b_v[idx][2].second;
                int col2 = b_v[idx][3].second;
                while (row >= 0) {
                    if (copy[row][col1] == 0 && copy[row][col2] == 0) {
                        row--;
                        if (row == -1) {
                            d_v.push_back(make_pair(idx, type));
                            break;
                        }
                    }
                    else
                        break;
                }
            }
            // ___| : Type 2
            else if (type == 2) {
                int row = b_v[idx][1].first - 1;
                int col1 = b_v[idx][1].second;
                int col2 = b_v[idx][2].second;
                while (row >= 0) {
                    if (copy[row][col1] == 0 && copy[row][col2] == 0) {
                        row--;
                        if (row == -1) {
                            d_v.push_back(make_pair(idx, type));
                            break;
                        }
                    }
                    else
                        break;
                }
            }
            // ㅗ : Type 3
            else if (type == 3) {
                int row = b_v[idx][1].first - 1;
                int col1 = b_v[idx][1].second;
                int col2 = b_v[idx][3].second;
                while (row >= 0) {
                    if (copy[row][col1] == 0 && copy[row][col2] == 0) {
                        row--;
                        if (row == -1) {
                            d_v.push_back(make_pair(idx, type));
                            break;
                        }
                    }
                    else
                        break;
                }
            }
            // |_ : Type 4
            else if (type == 4) {
                int row = b_v[idx][3].first - 1;
                int col1 = b_v[idx][3].second;
                while (row >= 0) {
                    if (copy[row][col1] == 0) {
                        row--;
                        if (row == -1) {
                            d_v.push_back(make_pair(idx, type));
                            break;
                        }
                    }
                    else
                        break;
                }
            }
            // _| : Type 5
            else {
                int row = b_v[idx][2].first - 1;
                int col1 = b_v[idx][2].second;
                while (row >= 0) {
                    if (copy[row][col1] == 0) {
                        row--;
                        if (row == -1) {
                            d_v.push_back(make_pair(idx, type));
                            break;
                        }
                    }
                    else
                        break;
                }
            }
        }
 
        // Deleting
        if (d_v.size() == 0)
            break;
        else {
            answer += d_v.size();
            for (int i = 0; i < d_v.size(); i++) {
                for (int j = 0; j < 4; j++)
                    copy[b_v[d_v[i].first][j].first][b_v[d_v[i].first][j].second] = 0;
                s.erase(d_v.at(i));
            }
        }
    }
 
    return answer;
}
http://colorscripter.com/info#e" target="_blank" style="color:#4f4f4ftext-decoration:none">Colored by Color Scripter