오랜만에 블로그 글을 작성하네요.
백준 문제 풀이를 작성하려고 만든 블로그인데 정작 백준 문제 푼 것은 못올리고 있는 상태입니다.. 앞으로 분발해야될 것 같네요.
오늘은 지난 5월에 진행된 2020 카카오 인턴십에 대한 후기를 작성할 겁니다.
사실 카카오 인턴을 쓰게 된 이유는 코딩테스트 문제를 풀어보려고 지원했는데, 포트폴리오도 내지 않은 서류를 운좋게 통과하여 면접까지 볼 수 있게 되었다. 직무는 산업기능요원 근무하는 동안 Windows 위주로 경력이 있었지만, 카카오에서 C#이 아닌 C++을 주로 사용해서 그냥 제가 지원하고 싶었던 서버 직무로 적었습니다.
코딩 테스트
코딩 테스트에서는 총 5문제가 나왔고, 저는 1,2,3,4번 총 네 문제를 풀었습니다. 5번 문제는 시간이 앞의 네 문제를 푸니 시간이 30분도 남지 않아서, 4문제에 대해서만 답을 올립니다. 카카오 공식 해설은 아래에서 확인할 수 있습니다.
https://tech.kakao.com/2020/07/01/2020-internship-test/
1번 문제는 구현 문제였는데, 구현을 난잡하게 하다보니 조금 늦게 풀었네요. 왼손은 1,4,7,*을 1,2,3,4로, 오른손은 3,6,9,#을 1,2,3,4로, 양손다 2,5,8,0을 5,6,7,8로 매핑한 후 계산하는 방식으로 했습니다.
#include <bits/stdc++.h>
using namespace std;
string solution(vector<int> numbers, string hand) {
string answer = "";
int left = 4, right = 4;
for(int num : numbers)
{
if(num%3==1)
{
answer+="L";
left = (num/3)+1;
}
else if(num && num%3==0)
{
answer+="R";
right = num/3;
}
else
{
int tl=0,tr=0;
int now=8;
if(num%3==2) now=(num/3)+5;
if(left>4) tl=std::abs(now-left);
else tl=std::abs(now-left-4)+1;
if(right>4) tr=std::abs(now-right);
else tr=std::abs(now-right-4)+1;
if(tl<tr)
{
answer+="L";
left=now;
}
else if(tl>tr || hand=="right")
{
answer+="R";
right=now;
}
else
{
answer+="L";
left=now;
}
}
}
return answer;
}
2번 문제는 카카오에서 좋아하는 문자열 문제입니다. C++로는 파싱이 힘들 것 같아서 파이썬을 사용하였습니다. 일단 정규표현식으로 사칙연산과 숫자를 분리하여 연산자 우선순위에 따라 각각 계산해주는 방식을 사용하였습니다.
import re
def solution(expression):
answer = 0
oper = ["+-*","+*-","-*+","-+*","*+-","*-+"]
for i in range(6):
check = re.findall("[+*-]+", expression)
numbers = re.findall("[0-9]+", expression)
for j in range(3):
k=0
while k<len(check):
if check[k]==oper[i][j]:
numbers[k]=str(eval(numbers[k]+check[k]+numbers[k+1]))
del check[k]
del numbers[k+1]
else:
k+=1
answer = max(answer,abs(int(numbers[0])))
return answer
3번 문제는 투 포인터에 대한 문제였습니다. 시작과 끝은 지정한 뒤에 모든 보석의 갯수를 다 포함하는지 일일이 세주는 방식으로 진행했습니다. 다만 그냥 map을 사용하니 효율성에서 일부 감점이 있어서 unordered_map을 사용하였습니다.
#include <bits/stdc++.h>
using namespace std;
bool check(unordered_map<string,int>& mp)
{
for(auto it=mp.begin();it!=mp.end();it++)
{
if(it->second==0) return false;
}
return true;
}
vector<int> solution(vector<string> gems) {
vector<int> answer;
unordered_map<string,int> kinds;
for(string gem:gems)
{
auto iter = kinds.find(gem);
if(iter == kinds.end()) kinds[gem]=0;
}
int n=gems.size();
int start=0,end=0;
int min=n-1,mins=1;
while(start<n && end<n)
{
while(start<n && !check(kinds))
{
kinds[gems[start]]++;
start++;
}
if(start>=n) break;
while(end<n && check(kinds))
{
kinds[gems[end]]--;
end++;
}
if(end>=n) break;
if(min>start-end)
{
min=start-end;
mins=end;
}
}
answer.push_back(mins);
answer.push_back(mins+min);
return answer;
}
4번 문제는 다익스트라 문제의 변형입니다. 우선순위 큐에 가장 적은 비용이 우선순위가 높게 설정을 한 뒤에 상하좌우로 이동 가능하면 우선순위 큐에 push하도록 설정하였습니다. 이때 visit는 상하좌우 방향을 모두 체크해야되기 때문에 bitmask로 visit 배열을 저장하는 방식으로 구현했습니다. 그리고 갈아엎기가 애매해서 pair로 4개의 변수를 저장해버렸는데 만약 다시 짜게되면 이 부분은 수정할 것 같습니다.
#include <bits/stdc++.h>
using namespace std;
int solution(vector<vector<int>> board) {
int answer = 0;
int n=board.size();
vector<vector<int>> visit;
for(int i=0;i<n;i++)
{
vector<int> temp;
for(int j=0;j<n;j++) temp.push_back(0);
visit.push_back(temp);
}
priority_queue<pair<int,pair<int,pair<int,int>>>, std::vector<pair<int,pair<int,pair<int,int>>>>, std::greater<pair<int,pair<int,pair<int,int>>>>> pq;
pq.push({0,{-1,{0,0}}});
visit[0][0]=1;
while(pq.size())
{
int cost=pq.top().first;
int dir=pq.top().second.first;
int nx=pq.top().second.second.first;
int ny=pq.top().second.second.second;
pq.pop();
visit[nx][ny]=visit[nx][ny]|(1<<dir);
if(nx==n-1 && ny==n-1)
{
answer=cost;
break;
}
int dx[]={1,-1,0,0};
int dy[]={0,0,1,-1};
for(int i=0;i<4;i++)
{
if(nx+dx[i]>=0 && nx+dx[i]<n && ny+dy[i]>=0 && ny+dy[i]<n && !(visit[nx+dx[i]][ny+dy[i]]&1<<i) && !board[nx+dx[i]][ny+dy[i]])
{
if(dir==i || dir==-1) pq.push({cost+100,{i,{nx+dx[i],ny+dy[i]}}});
else pq.push({cost+600,{i,{nx+dx[i],ny+dy[i]}}});
}
}
}
return answer;
}
그렇게 총 4시간 동안 4문제를 풀었고, 서류+코딩테스트 전형을 통과하게 되었습니다. 5문제 다 풀어도 떨어진 사람이 있었다는데, 아마 서류에서 산업기능요원 경력을 좋게 봐준게 아닐까 싶습니다.
면접
그 뒤에 면접을 보게 되었습니다. 5/27 ~ 6/2까지가 면접이었는데 두번째 날인 5/28(목)이 걸렸습니다. 면접 준비로는 산업기능요원 복무하면서 진행했던 프로젝트 정리 및 자기소개서에 적어둔 세 과목인 운영체제, 데이터베이스, 네트워크를 면접 일자가 발표된 월요일부터 조금씩 봤었습니다.
면접 당일날 구글 Meet을 사용하여 면접을 봤었고 저는 면접관 두 분이 들어오셨습니다. 면접 순서는 코딩 테스트 리뷰, 기술 면접, 프로젝트 설명, 인성 면접 순서로 봤습니다.
코딩 테스트 리뷰하면서는 단순히 어떻게 짰는지만 물어보는게 아니라 이 부분은 왜 이렇게 짰는지, 실제 개발에서는 어떻게 바꾸는게 좋을지도 물어봤고, 당연히 2번은 왜 파이썬으로 짰는지도 물어봤습니다..ㅎㅎ
기술 면접의 경우 C# 자신있다고 하니 C# 특징을 설명해보라 했었고, 간단한 자료구조, 알고리즘, 운영체제, 데이터베이스, 네트워크 질문들이 나왔습니다. 마지막으로 해당 팀에서 쓰는 기술에 대하여 물어봤는데 아쉽게도 해당 기술을 써보지 못해서 솔직하게 대답하였습니다.
인성 면접의 경우 개발을 좋아하냐고 물어봤던 질문이 인상적이었습니다.
불합격
그렇게 늦게 결과가 나왔지만 아쉽게도 탈락이었습니다. 기술 면접에서도 대답 못한 부분들이 있었고, 해당 팀의 기술도 대답하지 못했고, 무엇보다 아직 3학년이었기에 학교를 더 다녀야되는 부분이 제일 컸던 것 같습니다. 아쉽게도 이번 도전은 이렇게 멈췄지만 앞으로 다른 회사들을 지원할 때 방향성을 잡을 수 있었던 면접인 것 같습니다. 이번 면접에서 부족했던 점을 보완하여 다음번에 또 지원을 해볼 생각입니다.