레이블이 카카오인 게시물을 표시합니다. 모든 게시물 표시
레이블이 카카오인 게시물을 표시합니다. 모든 게시물 표시

2017년 9월 17일 일요일

카카오 1차 온라인 코딩 테스트

2018 1ST KAKAO BLIND RECRUITMENT


결과적으로 말하자면 4문제 밖에 못풀었다..
문제는 쉬운편이였다.
나는 쉬운 알고리즘 문제가 나올줄 알았는데 거의 다 구현문제였다.

많은 사람들이 5문제이상, 만점도 많이 받은거 같은데 충분히 그럴 시험이었다 ㅠㅠ
나는 1,2,5,6번을 풀고 3,4,7번을 못풀었다.

3번은 알고리즘을 찾아서 구현해야되서 귀찮아서 넘겼고 4번은 이해가 안되서 바로 넘겼다.
7번 문제를 풀기 시작했는데 남은 2시간내에 풀지 못했다 ㅠㅠ
풀이법은 맞는데 어느순간 스파게티소스가 되서 틀린테케를 잡지를 못했다.
날짜,시간,분,초 단위를 decoder, incoder하는 함수를 만들었으면 깔끔하고 금방풀지 않았을 까 
생각해본다.

사실 푼 문제들도 코드들이 더러운 편이다.
앞으로는 깔끔하게 코드를 작성하는 법과 문제이해를 빠르게 하는 연습을 해야겠다.

1번 문제
#include <string>
#include <vector>
#include <cstring>
using namespace std;
int map[16][16];
vector<string> solution(int N, vector<int> arr1, vector<int> arr2) {
    memset(map, 0sizeof map);
    for (int n = 0;n<N;n++) {
        for (int m = 1 << (N - 1), cnt = 0; m>0;m /= 2, cnt++) {
            int get1 = arr1[n] / m;
            int get2 = arr2[n] / m;
            if (get1 == 1 || get2 == 1) map[n][cnt] |= 1;
            arr1[n] -= get1*m;
            arr2[n] -= get2*m;
        }
    }
 
    vector<string> answer;
    for (int n = 0;n<N;n++) {
        string tmp("");
        for (int m = 0;m<N;m++) {
            if (map[n][m] == 1) tmp = tmp + '#';
            else tmp = tmp + ' ';
        }
        answer.push_back(tmp);
    }
    return answer;
}
cs


2번 문제
#include <string>
#include <cstring>
#include <cmath>
#include <iostream>
using namespace std;
int idx;
int Score[4], Bonus[4], Option[4];
void getScore(int time, int &idx, string dartResult) {
    if (dartResult[idx + 1== '0') Score[time] = 10, idx++;
    else Score[time] = dartResult[idx] - '0';
    idx++;
 
    if (dartResult[idx] == 'S') Bonus[time] = 1;
    else if (dartResult[idx] == 'D') Bonus[time] = 2;
    else Bonus[time] = 3;
    idx++;
 
    if (idx == dartResult.size() || !(dartResult[idx] == '*' || dartResult[idx] == '#')) Option[time] = -1;
    else {
        if (dartResult[idx] == '*') Option[time] = 1;
        else if(dartResult[idx] == '#' )Option[time] = 2;
        idx++;
    }
    if (Bonus[time] == 1) Score[time] = Score[time];
    else if (Bonus[time] == 2) Score[time] = (int)pow(Score[time], 2);
    else Score[time] = (int)pow(Score[time], 3);
}
int solution(string dartResult) {
    memset(Score, 0sizeof Score);
    memset(Bonus, 0sizeof Bonus);
    memset(Option, 0sizeof Option);
    idx = 0;
    for (int n = 1;n <= 3;n++) {
        getScore(n, idx, dartResult);
    }
    int answer = 0;
    for (int n = 1;n <= 3;n++) {
        for (int m = n;m <= n + 1;m++) {
            if (Option[m] == 1) Score[n] *= 2;
        }
        if (Option[n] == 2) Score[n] *= -1;
        answer += Score[n];
    }
    return answer;
}
cs

5번 문제
#include <cstdio>
#include <string>
#include <cmath>
#include <algorithm>
#include <vector>
#include <queue>
#include <stack>
#include <iostream>
#include <set>
#include <map>
using namespace std;
multiset<string>::iterator i;
bool NNot(const char &c) {
    if ((c >= 'A' && c <= 'Z'|| (c >= 'a' && c <= 'z')) return false;
    return true;
}
bool BBigger(const char &c) {
    if (c >= 'A' && c <= 'Z'return true;
    return false;
}
int solution(string str1, string str2) {
    multiset<string> set_save1, set_save2;
    map<stringint> save1, save2;
    int N = str1.size(), M = str2.size();
    vector<string> str;
    int up = 0, down = 0;
    for (int n = 1;n < N;n++) {
        if (NNot(str1[n - 1]) || NNot(str1[n])) continue;
        string s = "";
        if (BBigger(str1[n - 1])) s = s + str1[n - 1];
        else s = s + (char)(str1[n - 1- 'a' + 'A');
        if(BBigger(str1[n])) s = s + str1[n];
        else s = s + (char)(str1[n] - 'a' + 'A');
        str.push_back(s);
        set_save1.insert(s);
        if (save1.find(s) == save1.end()) save1[s] = 1;
        else {
            int tmp = save1[s];
            save1[s] = tmp + 1;
        }
    }
    
    for (int m = 1;m < M;m++) {
        if (NNot(str2[m - 1]) || NNot(str2[m])) continue;
        string s = "";
        if (BBigger(str2[m - 1])) s = s + str2[m - 1];
        else s = s + (char)(str2[m - 1- 'a' + 'A');
        if (BBigger(str2[m])) s = s + str2[m];
        else s = s + (char)(str2[m] - 'a' + 'A');
        str.push_back(s);
        if (save2.find(s) == save2.end()) save2[s] = 1;
        else {
            int tmp = save2[s];
            save2[s] = tmp + 1;
        }
        set_save2.insert(s);
        if (set_save1.find(s) != set_save1.end()) {
            auto iter = lower_bound(set_save1.begin(), set_save1.end(), s);
            set_save1.erase(iter);
            up++;
        }
    }
    sort(str.begin(), str.end());
    str.erase(unique(str.begin(), str.end()), str.end());
    for (auto &n : str) {
        if (save1.find(n) != save1.end() && save2.find(n) != save2.end()) {
            down += max(save1[n], save2[n]);
        }
        else if (save1.find(n) != save1.end()) down += save1[n];
        else if (save2.find(n) != save2.end()) down += save2[n];
    }
    if (up == 0 && down == 0return 65536;
    double ans = (double)up / (double)down;
    ans *= 65536;
 
    return (int)ans;
}
cs

6번 문제
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <vector>
#include <queue>
#include <stack>
#include <string>
using namespace std;
int N, M;
bool Erase[31][31];
char map[31][31];
int dy[4][3= { { -1,-1 ,0 },{-1,-1,0},{0,1,1},{0,1,1} };
int dx[4][3= { { -1,0,-1 },{0,1,1},{-1,-1,0},{1,1,0} };
void solve(int y, int x) {
    if (map[y][x] == ' 'return;
    for (int i = 0;i < 4;i++) {
        int cnt = 0;
        for (int j = 0;j < 3;j++) {
            int ny = y + dy[i][j], nx = x + dx[i][j];
            if (ny < 0 || ny >= N || nx < 0 || nx >= M) continue;
            if (map[y][x] == map[ny][nx]) cnt++;
        }
        if (cnt == 3) {
            Erase[y][x] = true;
            for (int j = 0;j < 3;j++) {
                int ny = y + dy[i][j], nx = x + dx[i][j];
                Erase[ny][nx] = true;
            }
        }
    }
}
void goErase() {
    for (int m = 0;m < M;m++) {
        for (int n = N - 1;n >= 0;n--) {
            int x = m, y = n;
            if (map[y][x] != ' ')
            {
                y++;
                while (y < N && map[y][x] == ' ') {
                    swap(map[y][x], map[y - 1][x]), y++;
                }
            }
        }
    }
}
int solution(int a, int b, vector<string> board) {
    N = a, M = b;
    int answer = 0;
    for (int n = 0;n < N;n++) {
        for (int m = 0;m < M;m++)
            map[n][m] = board[n][m];
    }
    while (1) {
        memset(Erase, falsesizeof Erase);
        for (int n = 0;n < N;n++) {
            for (int m = 0;m < M;m++) {
                solve(n, m);
            }
        }
        int cnt = 0;
        for (int n = 0;n < N;n++) {
            for (int m = 0;m < M;m++) {
                if (Erase[n][m]) cnt++, map[n][m] = ' ';
            }
        }
        if (cnt == 0break;
        answer += cnt;
        goErase();
    }
    return answer;
}
cs

2017년 9월 3일 일요일

카카오 모의 테스트

2018 1ST KAKAO BLIND DEMO TEST

https://programmers.co.kr/competitions/35/welcome-kakao


1, 2, 3번은 너무 간단하니 생략한다.

<4번 문제>
1 또는 0으로 채워져있는 배열이 주어진다.
이 배열에서 찾을 수 있는 가장 큰 정사각형을 구하는 문제이다.

$O(NM\cdot logT)$으로 풀린다.
구간 합을 구한후에 각 정점위치에서 이분탐색으로 가장 큰 정사각형을 구해주었다.

여기서 약간의 최적화를 해야 효율성 검사에서 시간초과가 나지않는데
이미 지금까지 구한 최대 정사각형보다 큰 범위를 탐색해주게 하면 된다.
<더빠른 방법 있으면 댓글로 달아주세요!!!!>
#include<vector>
#include <algorithm>
#include <cstdio>
#include <cstring>
using namespace std;
int sum[1001][1001];
int solution(vector<vector<int>> board){
    memset(sum,0,sizeof sum);
    int N = board.size(), M =board[0].size();
    for(int n=0;n<board.size();++n){
        for(int m=0;m<board[n].size();++m){
            sum[n][m] += board[n][m];
            if(n-1>=0)
                sum[n][m] += sum[n-1][m];
            if(m-1>=0)
                sum[n][m] += sum[n][m-1];
            if (n - 1 >= 0 && m - 1 >= 0)
                sum[n][m] -= sum[n - 1][m - 1];
        }
    }
    int ans = 0;
    for (int n = 0;n < N;n++) {
        for (int m = 0;m < M;m++) {
            int l = 1, r = min(N - n, M - m);
            if(r <= ans) continue;
            while (l <= r) {
                int mid = (l + r) >> 1;
                if (sum[n + mid - 1][m + mid - 1- sum[n + mid - 1][m - 1- sum[n - 1][m + mid - 1+ sum[n - 1][m - 1== mid*mid)
                    l = mid + 1;
                else r = mid - 1;
            }
            ans = max(ans, r);
        }
    }
    return ans*ans;
}
cs

<5번 문제>
N행 4열로 구성된 땅이있다.
한행씩 내려오는데 같은 행을 연속해서 밟을 수는 없다.
밟은 땅들의 값의 최대 합을 구하는 문제이다.

간단한 DP문제다.
#include <cstdio>
#include <algorithm>
#include <cstring>
#include<vector>
using namespace std;
int N;
int land[100001][4];
int dp[100001][4];
int solve(int y, int x) {
    if (y == N) return 0;
    int &ret = dp[y][x];
    if (ret != -1return ret;
    ret = 0;
    for (int n = 0;n < 4;n++) {
        if (x == n) continue;
        ret = max(ret, solve(y + 1, n) + land[y][n]);
    }
    return ret;
}
int solution(vector<vector<int> > l){
    memset(dp, -1 ,sizeof dp);
    N = l.size();
    for(int n=0;n<N;n++){
        for(int m=0;m<4;m++)
            land[n][m] = l[n][m];
    }
    int ans = 0;
    for(int n=0;n<4;n++){
        ans = max(ans, solve(0, n));
    }
    return ans;
}
cs

<6번 문제>
원형으로 구성된 스티커가있다. 
스티커를 뜯었을 때 점수를 얻을 수 있는데 뜯은 스티커의 양쪽 스티커는 뜯지 못한다.
최대 점수를 구하는 문제이다.

이것도 DP문제이다.
뜯었을 때의 경우와 뜯지 않았을 때의 경우로 나누고 
처음뜯었을때와 아닌 경우로 3차원 DP로 만들어 풀었다.
N이 1인 경우 예외처리를 해줘야 한다.
#include <vector>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
int N;
int arr[100001];
int dp[100001][2][2];
using namespace std;
int solve(int idx, int get, int flag) {
    if (flag && idx >= N - 1return 0;
    if (!flag && idx >= N) return 0;
    int &ret = dp[idx][get][flag];
    if (ret != -1)return ret;
    if (get) 
        ret = max(solve(idx + 20, flag), solve(idx + 21, flag)) + arr[idx];    
    else 
        ret = max(solve(idx + 11, flag),solve(idx + 10, flag));
    return ret;
}
int solution(vector<int> sticker){
    memset(dp,-1,sizeof dp);
    N = sticker.size();
    for(int n=0;n<N;n++) arr[n]= sticker[n];
    return N == 1 ? sticker[0] : max(solve(000), solve(011));
}
cs

<7번 문제>
문자열 T를 만드는데 주어지는 단어조각을 최소한만 이용해서 만드는 문제이다.

이것도 DP문제다.
(사실 4, 5, 6, 7 전부 DP였다.)
set을 이용해서 쉽게 풀리는데 주어지는 단어조각의 길이가 5임을 모르고 
$O(N^2)$으로 풀어서 계속 시간초과가 났다.

범위를 최대 +5개로 제한해서 $O(N\cdot 5)$로 풀 수 있다.
#include <iostream>
#include <cstring>
#include <string>
#include <algorithm>
#include <unordered_set>
using namespace std;
#define INF 987654321
int N, M;
int dp[20001];
unordered_set<string> visit;
string str[101], T;
int solve(int idx) {
    if (idx == M) return 0;
    int &ret = dp[idx];
    if (ret != -1return ret;
    ret = INF;
    for (int n = idx; n< min(idx + 5, M);n++) {
        if (visit.find(T.substr(idx, n - idx + 1)) != visit.end())
            ret = min(ret, solve(n + 1+ 1);
    }
    return ret;
}
int solution(vector<string> strs, string t){
    T = t;
    visit.clear();
    memset(dp, -1sizeof dp);
    N = strs.size();
    M = t.length();
    for(int n=0;n<N;n++) str[n] = strs[n];
    for (int n = 0;n < N;n++
        visit.insert(str[n]);
    int get = solve(0);
    if(get == INF) return -1;
    return get;
}
cs