🔗 문제 링크
https://programmers.co.kr/learn/courses/30/lessons/17683
✏️ 풀이
function solution(m, musicinfos) {
const normalize = (melody) => {
return melody.replace(/([A-Z])#/g, (_, group) => group.toLowerCase());
};
const getMin = (time) => {
const [hour, minute] = time.split(':').map(Number);
return hour * 60 + minute;
};
const getDiff = (start, end) => {
return getMin(end) - getMin(start);
};
const music = musicinfos.map(info => {
const [start, end, title, melody] = info.split(',');
return {
time: getDiff(start, end),
title,
melody: normalize(melody)
};
});
const targetMelody = normalize(m);
let output = { title: '(None)' };
music.forEach(info => {
const { time, title, melody } = info;
let compMelody = melody.repeat(2);
let count = 2;
while (targetMelody.length + melody.length - 1 > compMelody.length) {
compMelody += melody;
count++;
}
const index = compMelody.indexOf(targetMelody);
if (index >= 0 && index + targetMelody.length <= time) {
if (output.title === '(None)' || output.time < time) {
output = info;
}
}
});
return output.title;
}
musicinfos를 순회하면서 각 음악에 대한 정보를 갖고 { time, title, melody } 객체로 변환하여 music에 배열의 형태로 저장한다. 이 때, time은 음악이 재생된 시간의 양으로 바꾸고, melody는 C#, D#, F#, G#, A# 같이 두 글자로 된 음을 c, d, f, g, a로 모두 한 글자로 바꿔준다. (normalize)
마찬가지로 찾고자 하는 멜로디인 m도 normalize 함수로 모든 음을 한 글자로 변환한다.
output의 초기값을 제목이 (None)인 음악의 정보로 설정한다. 그리고 나서 music을 순회한다.
targetMelody와 현재 순회중인 음악의 melody를 비교할 때, 최소한 (targetMelody의 길이 + melody의 길이 - 1)만큼 melody를 반복 재생해야 모든 경우의 수를 다 확인할 수 있다. 예를 들어 targetMelody가 ABCAB 이고, melody가 BCA라면, melody를 BCA|BCA|B 까지는 재생해야 가능한 모든 5자리 멜로디를 확인할 수 있다. 따라서 compMelody에 계속 melody를 반복해서 최소한 모든 경우를 다 탐색할 수 있는 길이까지 만들어야 한다.
이렇게 반복재생한 melody를 이어붙여 만든 compMelody에서 targetMelody의 위치를 찾는다. 위 단계에서 아무런 제한 없이 melody를 이어붙였지만, 음악은 각각의 재생 시간이 있고, 이 재생 시간을 넘어서는 길이만큼의 melody는 재생되지 않는다. 따라서, 지금 찾은 targetMelody가 실제로 재생이 가능한 시간대에 있었는지를 확인해야 한다.
일단 compMelody에 targetMelody가 없으면 -1을 반환하므로, index >= 0이어야 한다. 그리고 index에 targetMelody의 길이를 더한 만큼이 time(음악이 재생된 분 수) 이하라면 실제로 재생이 되었던 것이다. 만약 실제로 재생이 되었다면 현재 output을 확인하여 title이 (None)이거나, 재생시간이 현재 time보다 더 짧다면 output을 현재 info로 교체한다.
순회가 끝난 뒤에 output의 title을 반환하였다.
'연습장 > 프로그래머스 문제풀이' 카테고리의 다른 글
[프로그래머스 Level 2] 파일명 정렬 - JavaScript (0) | 2022.06.11 |
---|---|
[프로그래머스 Level 2] 압축 - JavaScript (0) | 2022.06.10 |
[프로그래머스 Level 3] 여행경로 - JavaScript (0) | 2022.06.10 |
[프로그래머스 Level 2] 프렌즈4블록 - JavaScript (0) | 2022.06.10 |
[프로그래머스 Level 3] 네트워크 - JavaScript (0) | 2022.06.09 |