본문 바로가기

programming/알고리즘 풀이

[programmers] [3차] 17683번 - 방금그곡 (구현, 2018 KAKAO BLIND RECRUITMENT)

반응형

1. 문제 및 예제 

 

 문자열과 구현이 합쳐진 문제 같았다. 꼼꼼했다면 더 쉽게 풀 수 있었을 것 같았는데, 놓친부분이 있어 시간이 오래 걸린 문제다.


 

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr


2. 풀이

 

 해당 문제는 문자열이 반복되기 때문에 두개를 표현하는 문자열 C#, D#, F#, G#, A#를 하나의 특정한 값으로 교체 하였다. 나같은 경우 그냥 "C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B" 순서대로 1부터 9까지 그리고 뒤의 두개의 음을 A와 B로 즉, 고유한 값으로 변환하였다.

 

 이런 전처리가 끝났다면 별로 어렵지 않은 문제다. 단계별로 나누면 다음과 같다.

 

1. info의 각 원소대로 for문을 돌린다.

 1.1 한 문자열을 ',' 기준으로 나눈다.

 1.2 시작 시간과 끝 시간을 사용하여 재생 시간을 구한다.

 1.3 음들을 다시 한 문자당 하나의 음을 의미하도록 전처리를 진행한다.

 1.4 재생 시간 만큼 문자열을 반복하여 재생 문자열을 생성한다.

 1.5 배열에 재생시간, 노래이름, 재생 문자열을 저장한다.

2. 배열에서 문자열 m이 포함 된 재생 문자열이 있다면,

 2.1 만약 정답이 존재한다면, 재생시간을 비교하여 정답에 저장한다.

 2.2 만약 정이 존재하지 않다면, 바로 정답에 저장한다.

 

- 문자열 분리 함수

 

vector<string> get_string_arr(string str) {
    string tmp = "";
    vector<string> ans;

    for (auto it : str) {
        if (it == ',') {

            ans.push_back(tmp);
            tmp = "";
        }
        else
            tmp += it;
    }

    ans.push_back(tmp);

    return ans;
}

 

- 재생 시간을 계산 하는 함수

 

int get_minute(string start, string end) {

    int start_h = stoi(start.substr(0, 2));
    int start_m = stoi(start.substr(3, 2));

    int end_h = stoi(end.substr(0, 2));
    int end_m = stoi(end.substr(3, 2));

    int sum_start = start_h * 60 + start_m;
    int sum_end = end_h * 60 + end_m;

    return sum_end - sum_start;
}

 

- 다음은 문자열을 전처리하는 함수이다.

 

string get_hash_num(string str) {
    string hash[12] = { "C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B" };
    string tmp;
    int index;

    if (str[1] == '#') {
        tmp = str.substr(0, 2);
        index = 2;
    }
    else {
        tmp = str.substr(0, 1);
        index = 1;
    }
    string hash_arr = "";

    while (index < str.size()) {
        if (str[index] == '#') {
            tmp += str[index];
        }
        else {
            for (int j = 0; j < 12; j++) {
                if (hash[j] == tmp) {
                    if (j == 10) {
                        hash_arr += 'A';
                    }
                    else if (j == 11) {
                        hash_arr += 'B';
                    }
                    else
                        hash_arr += to_string(j);
                    break;
                }
            }
            tmp = str[index];
        }
        index++;
    }

    for (int j = 0; j < 12; j++) {
        if (hash[j] == tmp) {
            if (j == 10) {
                hash_arr += 'A';
            }
            else if (j == 11) {
                hash_arr += 'B';
            }
            else
                hash_arr += to_string(j);
            break;
        }
    }
    return hash_arr;
}

 

- 다음은 전체 코드이다.

 

#include <string>
#include <vector>
#include <iostream>

using namespace std;

vector<string> get_string_arr(string str) {
    string tmp = "";
    vector<string> ans;

    for (auto it : str) {
        if (it == ',') {

            ans.push_back(tmp);
            tmp = "";
        }
        else
            tmp += it;
    }

    ans.push_back(tmp);

    return ans;
}

int get_minute(string start, string end) {

    int start_h = stoi(start.substr(0, 2));
    int start_m = stoi(start.substr(3, 2));

    int end_h = stoi(end.substr(0, 2));
    int end_m = stoi(end.substr(3, 2));

    int sum_start = start_h * 60 + start_m;
    int sum_end = end_h * 60 + end_m;

    return sum_end - sum_start;
}

string get_hash_num(string str) {
    string hash[12] = { "C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B" };
    string tmp;
    int index;

    if (str[1] == '#') {
        tmp = str.substr(0, 2);
        index = 2;
    }
    else {
        tmp = str.substr(0, 1);
        index = 1;
    }
    string hash_arr = "";

    while (index < str.size()) {
        if (str[index] == '#') {
            tmp += str[index];
        }
        else {
            for (int j = 0; j < 12; j++) {
                if (hash[j] == tmp) {
                    if (j == 10) {
                        hash_arr += 'A';
                    }
                    else if (j == 11) {
                        hash_arr += 'B';
                    }
                    else
                        hash_arr += to_string(j);
                    break;
                }
            }
            tmp = str[index];
        }
        index++;
    }

    for (int j = 0; j < 12; j++) {
        if (hash[j] == tmp) {
            if (j == 10) {
                hash_arr += 'A';
            }
            else if (j == 11) {
                hash_arr += 'B';
            }
            else
                hash_arr += to_string(j);
            break;
        }
    }
    return hash_arr;
}

string solution(string m, vector<string> musicinfos) {
    string answer = "(None)";
    vector<pair<int, pair<string, string>>> dic;

    for (auto it : musicinfos) {
        vector<string> infos = get_string_arr(it);
        int play_time = get_minute(infos[0], infos[1]);
        string music_arr = "";
        string info = get_hash_num(infos[3]);

        for (int i = 0; i < (play_time / info.size()); i++) {
            music_arr += info;
        }
        music_arr += info.substr(0, (play_time % info.size()));
        dic.push_back(make_pair(play_time, make_pair(infos[2], music_arr)));
    }

    string hash_m = get_hash_num(m);
    int time = 0;

    for (auto it : dic) {
        if (it.second.second.find(hash_m) != string::npos && time < it.second.second.size()) {
            answer = it.second.first;
            time = it.second.second.size();
        }
    }

    if (answer.empty())
        answer = "(None)";

    return answer;
}

 

3. 결어

 

 문자열 전처리를 부분이 어려웠지만, 나름 적당한 난이도의 구현 문제라고 생각한다. 중요한점은 이런 문제를 40분 안에 다 풀어야 한다는 것... 구현 문제를 더 풀어봐야할 것 같다.

반응형