https://programmers.co.kr/learn/courses/30/lessons/17683#
이 문제가 꽤 시간이 오래걸렸다. 간단한 문제였지만, 빨리 풀려는 마음에, 한 지문을 내마음대로 이해해버렸다. 아래 과정에서 설명하도록 하겠다.
문제를 풀기 위해서는, 재생된 시간을 맞춰서 멜로디를 늘려주거나 줄여주면 된다.
예를 들어서,
ABCDEFG | [12:00,12:14,HELLO,CDEFGAB, 13:00,13:05,WORLD,ABCDEF] |
CDEFGAB의 경우에는, CDEFGABCDEFGAB의 형태로 작성해주면 된다. 이렇게 해야 ABCDEFG를 찾을 수 있다.
나누기와 나머지 연산을 사용해서 재생된 시간만큼의 문자열을 만들어 주면 된다.
만들어진 문자열에서 find 함수를 통해서 네오가 기억하는 멜로디를 검색해주면 된다.
하지만 문제에서 말했듯이, ABC#의 경우에는 ABC가 아니다. 간편한 연산을 위해서 C#를 소문자 c의 형태로 변경할 것이다. 이렇게 처리하면, C인지 C#인지 찾지 않아도 한 번만에 처리가 가능하다.
네오가 기억한 멜로디와 악보에 사용되는 음은 C, C#, D, D#, E, F, F#, G, G#, A, A#, B 12개이다.
위의 문장에서, 한 음이라고 한 것에 주목해야 한다. 한 음이라는 것은 1분을 소요하게 된다.
문제가 오래걸렸던 이유는, C#의 경우에 C, #을 각각 1음을 체크를 했었다. 문제를 제대로 읽었다면 쉽게 풀 수 있었을 것이다.
또한 추가적으로 살펴봐야 할 것은 아래의, 작동이다. 재생시간에 맞춰서 멜로디를 만들기 위해 나누기와 나머지 연산이 아니고, 아래의 형태를 가지게 했는데, 문제가 발생했다. 다음 코드는 종료되지 않는다.
#include <iostream>
#include <string>
using namespace std;
int main(void) {
string str = "test";
int val = 5;
while (true) {
cout << val - str.size() << endl;
if (val - str.size() >= 0) {
val -= str.size();
}
else {
cout << val << endl;
break;
}
}
return 0;
}
이 코드를 실행해보면, val - str.size()의 값이 오버플로우 형태를 가진다. 하지만 if(val - str.size() >= 0) 이후에서 val은 또 정상적인 값을 가진다.
원래 알고있는대로라면, 자동 형 변환은 자료형이 큰쪽으로 맞춰져야 한다.
val - (int)str.size()를 사용하면 정상적으로 작동한다. 또한, val -= str.size()의 형태는 자료형이 큰쪽으로 자동 형변환이 이루어진다.
반면에, val - str.size()에선 str.size()의 자료형에 맞춰진다. 찾아보니, int(val)와 unsigned int(size())의 rank가 같기 때문에, 무부호형인 unsigned int로 맞춰진다고 한다.
val -= str.size()는 val의 int 자료형으로 강제적으로 형변환을 하고 있으니, int형으로 자료형이 맞춰지는게 맞다. 코드를 작성할 때, size()는 자주 사용되기 때문에 참고할만한 사항이다.
해설코드(C++).
#include <string>
#include <vector>
#include <string.h>
#include <iostream>
using namespace std;
int strtoTime(string str) {
int result = 0;
result += 600 * (str[0] - '0');
result += 60 * (str[1] - '0');
result += 10 * (str[3] - '0');
result += 1 * (str[4] - '0');
return result;
}
string solution(string m, vector<string> musicinfos) {
string answer = "'(None)'";
int ans_time = -1;
for (int i = 0; i < musicinfos.size(); i++) {
char* tok = strtok((char*)musicinfos[i].c_str(), ",");
int idx = 1;
int start_time = 0;
int end_time = 0;
string song;
string rem;
string melody;
while (tok != NULL) {
if (idx == 1)
start_time = strtoTime(tok);
else if (idx == 2)
end_time = strtoTime(tok);
else if (idx == 3) {
song = tok;
//cout << song << endl;
}
else if (idx == 4) {
rem = tok;
int time = end_time - start_time;
while (true) {
if (time - (int)rem.length() >= 0) {
time -= (int)rem.length();
if (time == 0)
break;
}
else {
if (time < 0)
time += (int)rem.length();
melody.append(rem.substr(0, time));
break;
}
}
//cout << melody << endl;
size_t found = melody.find(m);
while (found != string::npos) {
if ((int)found + (int)m.length() < (int)melody.length()) {
cout << melody[found] << endl;
if (melody[(int)found + (int)m.length()] == '#');
else {
if (answer.compare("'(None)'") == 0) {
answer = song;
ans_time = end_time - start_time;
}
else {
if (ans_time < end_time - start_time)
{
answer = song;
ans_time = end_time - start_time;
}
}
break;
}
}
found = melody.find(m, (int)found + 1);
}
}
tok = strtok(NULL, ",");
idx++;
}
}
return answer;
}
'알고리즘' 카테고리의 다른 글
[2018 KAKAO BLIND RECRUITMENT] [3차] 자동완성 (0) | 2020.01.24 |
---|---|
[2018 KAKAO BLIND RECRUITMENT] [3차] 압축 (0) | 2020.01.24 |
[2018 KAKAO BLIND RECRUITMENT] 캐시(C++) (0) | 2020.01.23 |
[2018 KAKAO BLIND RECRUITMENT] 다트 게임(C++) (0) | 2020.01.23 |
[2018 KAKAO BLIND RECRUITMENT] 셔틀버스(C++) (0) | 2020.01.23 |