2020 카카오 블라인드 신입 공채 1차 코딩 테스트 후기 및 문제 풀이
by 줌코딩
카카오 블라인드 신입 공채 코딩 테스트
- 방학 기간을 백준에 갈아넣은 뒤 처음 본 코딩 테스트이다.
- 물론 공채를 위한 대회이지만 2020년 졸업 예정자가 아니어도 참여 가능하다고 하기에 바로 지원해서 도전해보게 되었다.
2020 블라인드 코딩 테스트 후기
- 2019 문제들을 어제 풀어봤는데 대부분이 구현에 초점이 맞춰져있고 뒤에 난이도가 있는 문제들은 알고리즘을 이용해서 푸는 문제들이었다.(구현은 실수 없이 문제를 정확히 해석하는 것이 제일 중요한 듯하다.)
- 올해도 마찬가지로 앞 문제들은 구현에 초점을 맞추고 있었다.
- 4번 문제가 효율성을 따지는 문제로 시간 효율을 위해 특정 알고리즘이 필요한 듯했고 5번까지 문제를 접한 나에게는 4번을 제외한 문제들은 구현의 문제로 다가왔었다.
- 다행히 4번을 빠르게 손절함으로써 알고리즘 공부 4개월 차인 나는 4시간 반만에 4문제를 풀었다.
- 내가 푼 문제인 1, 2, 3, 5번 문제에 대한 내 나름의 풀이를 적어보려 한다.
문제 해설
프로그래밍1
- 이 문제는 s를 쪼개는 단위인 k를 1개부터 n/2개까지 보면서 k일 때의 압축된 글자의 수 cnt를 확인한다. 이를 위해 i번째(비교대상)와 j번째(그 뒤에 샘플)를 비교해나간다.
- 두개가 같다면 j를 i + k로 업데이트 해서 다시 비교해주고 same_n의 개수를 늘린다.
- 다르다면 그떄는 same_n의 개수를 확인해서 이에 맞게 cnt를 업데이트해준다.
- 그리고 모든 k의 cnt 중에서 제일 작은 값을 ans로 반환한다.
주의할점!
- 압축한 횟수를 나타낼때 10 이상이면 2자리 100이상이면 3자리 1000이상이면 4자리가 된다. 이에 맞춰서 추가하지 않았을 때 한 60퍼센트정도 맞은 거 같다..^^
#include <string>
#include <vector>
using namespace std;
int solution(string s) {
int n = s.length(), ans = n;
for(int k = 1; k <= n/2; k++){
int cnt = 0, i = 0;
//비교대상 i
while(i < n){
int same_n = 0, next = 0;
if(i + k > n){
cnt+= n - i; break;
}
//샘플 j
for(int j = i+k; j < n; j+=k){
//비교시작
int t;
for(t = 0; t < k; t++){
//다른게 하나라도 있으면 0으로
if(s[i+t] != s[j+t])break;
}
if(t == k) same_n ++;
else {
next = j; break;
}
}
if(same_n){
if(same_n + 1 <= 9)cnt += k + 1;
else if(same_n + 1 <= 99)cnt += k + 2;
else if(same_n + 1 <= 999)cnt += k + 3;
else cnt += k + 4;
}
else cnt+= k;
if(next == 0)break;
i = next;
}
if(cnt < ans) ans = cnt;
}
return ans;
}
프로그래밍 2
- 이 문제는 알고리즘을 다 주기 때문에 이에 따라 얼마나 잘 구현해내는 가에 대한 문제이다.
- 괄호 set의 범위가 주어지면 거기서 u와 v 경계 지점(i)을 구해주고 u의 맞고 안맞고를 확인해주기(result) 위해 correct 함수를 만들었다.
- 만약 correct 함수에서 begin과 end가 같을 때는 그냥 begin과 1을 반환해주었다.
- v의 범위가 s 범위 밖으로 벗어나는 것을 방지하기 위해 다음을 해줘야 한다.
if(x2 >= n || y2 >= n)s2 = "";
- 그냥 psudo code를 따라가고 디버깅하다보면 풀 수 있는 문제이다.
#include <string>
#include <vector>
#include <stack>
#define pii pair<int, int>
using namespace std;
string p;
int n;
pii correct(int begin, int end){
stack<int> s;
int result = 1;
int o = 0, x = 0;
for(int i = begin; i <= end; i++){
if(p[i] == ')') {
o++;
if(s.empty()) result = 0;
else s.pop();
}
else {
s.push(1); x++;
}
if(o == x) return pii(i, result);
}
return pii(begin, 1);
}
string _solution(int begin, int end){
string result = "";
if(begin == end) return "";
pii r = correct(begin, end);
int x1 = begin, y1 = r.first, x2 = r.first + 1, y2 = end;
string s2 = "";
if(x2 >= n || y2 >= n)s2 = "";
else s2 = _solution(x2, y2);
if(r.second)return p.substr(x1, y1 - x1 + 1) + s2;
result = "(" + s2 + ")";
for(int i = x1 + 1; i <= y1 - 1; i++){
if(p[i] == '(') result += ")";
else result += "(";
}
return result;
}
string solution(string _p) {
p = _p, n = p.length();
return _solution(0, n-1);
}
프로그래밍 3
- 이 문제는 일단 key를 사방향으로 돌린 결과를 keys에 저장하고 5중 for문을 돌리면 된다..ㅎㅎ
- key의 위치만 중요한 것이 아니라 각각의 맞물리는 지점이 둘다 튀어나온 것은 아닌지 확인해줘야 하기에 전체를 다 확인해주었다.
주의할점!
- key가 좌측 위로 가고 lock이 우측 하단에 있을 때 열릴 수도 있기 때문에 비교를 -m, -m부터 시작해야 한다.
#include <string>
#include <vector>
using namespace std;
bool solution(vector<vector<int>> key, vector<vector<int>> lock) {
int keys[4][21][21], m = key.size(), n = lock.size(), locks = 0;
for(int i = 0; i < m; i++){
for(int j = 0; j < m; j++){
keys[0][i][j] = key[i][j];
keys[1][i][j] = key[m - j - 1][i];
keys[2][i][j] = key[m - i - 1][m - j - 1];
keys[3][i][j] = key[j][m - i - 1];
}
}
for(int x = 0; x < n; x++){
for(int y = 0; y < n; y++){
if(lock[x][y] == 0) locks++;
}
}
if(locks == 0)return true;
for(int x = - m; x < n; x++){
for(int y = - m; y < n; y++){
for(int k = 0; k < 4; k++){
int cnt = 0, wrong = 0;
for(int i = 0; i < m; i++){
for(int j = 0; j < m; j++){
if(x + i < 0 || y + j < 0 || x + i >= n || y + j >= n) continue;
if(keys[k][i][j] == 1 && lock[x + i][y + j] == 0)cnt ++;
else if(keys[k][i][j] == 1 && lock[x + i][y + j] == 1){
wrong = 1;
break;
}
}
if(wrong)break;
}
if(cnt == locks && !wrong) return true;
}
}
}
return false;
}
프로그래밍 5
- 이 문제도 구현을 잘할 수 있는 가에 조금의 트릭이 추가된 문제이다.
- 해당 명령이 주어졌을 때 명령에 해당하는 값을 수행하기에 합당한지 확인하기 위해 3개의 함수를 만들었다.(기둥 추가, 보 추가, 제거)
- 기둥 추가, 보 추가의 조건을 잘 적용시키는 것이 뽀인트다.
- 그리고 삭제 시에는 해당 기둥 혹은 보를 제거한 후 모든 원소를 각각 뺐다가 다시 추가할 때 모두 조건을 성립하는지 확인했다. 성립시 삭제, 하나라도 문제 생기면 삭제 x.
주의할점!
- 같은 지점에 보와 기둥이 둘다 들어갈 수 있기 때문에 arr를 3차원으로 준비한다.
#include <string>
#include <vector>
using namespace std;
int arr[102][102][2], n;
//기둥 0
int insert_gidung(int x, int y){
if(arr[x][y][1]){
arr[x][y][0] = 1;
return 1;
}
if(x - 1 >= 0 && arr[x - 1][y][1]){
arr[x][y][0] = 1;
return 1;
}
if(y == 0){
arr[x][y][0] = 1;
return 1;
}
if(y - 1 >= 0 && arr[x][y-1][0]){
arr[x][y][0] = 1;
return 1;
}
return 0;
}
//보 1
int insert_bo(int x, int y){
if(y - 1 >= 0 && (arr[x][y - 1][0] || arr[x + 1][y - 1][0])){
arr[x][y][1] = 1;
return 1;
}
if(arr[x + 1][y][1] && x - 1 >= 0 && arr[x - 1][y][1]){
arr[x][y][1] = 1;
return 1;
}
return 0;
}
int erase(int x, int y, int what){
int result = 1;
arr[x][y][what] = 0;
for(int i = 0; i < n + 1; i++){
for(int j = 0; j < n + 1; j++){
for(int k = 0; k < 2; k++){
if(arr[i][j][k] == 1){
arr[i][j][k] = 0;
if(k == 0){
if(!insert_gidung(i, j))result = 0;
}
else {
if(!insert_bo(i, j))result = 0;
}
arr[i][j][k] = 1;
}
}
}
}
if(!result) arr[x][y][what] = 1;
return result;
}
//기둥은 바닥 위에 있거나 보의 한쪽 끝 부분 위에 있거나, 또는 다른 기둥 위에 있어야 합니다.
//보는 한쪽 끝 부분이 기둥 위에 있거나, 또는 양쪽 끝 부분이 다른 보와 동시에 연결되어 있어야 합니다.
//[[1,0,0,1],[1,1,1,1],[2,1,0,1],[2,2,1,1],[5,0,0,1],[5,1,0,1],[4,2,1,1],[3,2,1,1]]
vector<vector<int>> solution(int _n, vector<vector<int>> build_frame) {
n = _n;
vector<vector<int>> answer;
for(int i = 0; i < build_frame.size(); i++){
int what = build_frame[i][2];
int how = build_frame[i][3];
int x = build_frame[i][0];
int y = build_frame[i][1];
//기둥 지을때
if(how == 1 && what == 0)insert_gidung(x, y);
else if(how == 1 && what == 1)insert_bo(x, y);
else erase(x, y, what);
}
for(int i = 0; i < n + 1; i++){
for(int j = 0; j < n + 1; j++){
for(int k = 0; k < 2; k++){
if(arr[i][j][k] == 1){
vector<int> arr(3);
arr[0] = i, arr[1] = j, arr[2] = k;
answer.push_back(arr);
}
}
}
}
return answer;
}
알고리즘 대회 참가의 필요성
- 이번 대회를 나가면서 시간의 제약 없이 백준을 푸는 것과 대회에서 문제를 푸는 것은 큰 차이가 있음을 느꼈다.
- 각종 코딩 대회에 대한 정보를 정리해봤는데 대회 관련 정보가 궁금하다면 다음 사이트를 참고하기 바란다.
- 각종 코딩대회 정보 정리
이 포스팅은 쿠팡 파트너스 활동의 일환으로, 이에 따른 일정액의 수수료를 제공받습니다.
Subscribe via RSS