프로그래머스 방금그곡 JavaScript
2023년 5월 11일
문제 풀이
방송된 곡들의 정보를 담은 musicinfos
의 음악 중 멜로디 m
이 포함된 음악을 찾는 문제다. 구현 문제라 생각이 들어 필요한 기능을 함수로 하나씩 구현했다.
함수
normalizationMelody(pitchs)
: 악보나 멜로디의 음들을 배열로 정규화해서 반환하는 함수.
매개변수pitchs
는 String 타입이다.pitchs
를 문자 하나씩 조회할 때, 조회하는 문자가(temp
) #인 경우 배열에 맨 뒤에 문자를 pop 하고 #을 더한다. 그 뒤엔 배열에 문자(temp
)를 push 한다.caculateMusicTime(start, end)
: 음악의 시작 시각과 종료 시각을 받아 플레이 타임을 반환하는 함수.
매개변수start
,end
는 HH:MM 형식의 문자열이므로, split 한 후 계산을 위해 *=1을 통해 숫자 타입으로 변환시킨다.
종료 시각의 분이 시작 시간의 분보다 작은 경우 종료 시각의 시간을 1 빼고 분에 60을 더한다. 이후 종료 시각의 시간 - 시작 시각의 시간, 종료 시각의 분 시작 시각의 분 계산을 하고, 계산된 시간에 * 60 + 분 을 반환한다.(분 형태의 시간)getActualSoundPlay(sheetmusic, musicTime)
: 음악의 악보와 플레이 시간을 입력받아 실제 재생되는 음들을 반환하는 함수.
매개변수로 받은 악보sheetmusic
를normalizationMelody(pitchs)
를 통해 배열로 정규화한 뒤, 정규화된 악보를 플레이 시간 동안 반복한다.checkMusic(soundPlayed)
: 재생되는 음들 중에 찾는 멜로디가 포함되는지 확인하는 함수, 찾을 경우 true, 못 찾을 경우 false를 반환.
찾는 멜로디m
이 정규화된 배열m_normalization
길이만큼 매개변수인 재생되는 음soundPlayed
를 slice 하여 비교
메인
매개변수 musicinfos
를 하나씩 조회하면서 현재 음악의 플레이 시간, 제목, 실제 재생되는 음을(musicTime
, musicTitle
, musicSoundPlayed
) 구하고 실제 재생되는 음을 통해 현재 음악이 찾는 멜로디가 포함되어 있으면 {제목, 실행 시간, musicinfos
의 인덱스} 객체 형태로 answer
에 push 한다. 이는 조건이 일치하는 음악이 여러 개일 수도 있기 때문이다.
모든 음악을 조회한 뒤,answer
의 길이가 0이면 조건이 일치하는 음악이 없는 경우로 "(None)"을 리턴
길이가 1이면 조건이 일치하는 음악이 하나이므로 그 음악의 제목을 리턴
길이가 2 이상일 경우 플레이 시간이 제일 긴 순서대로, 플레이 시간이 같은 경우 먼저 입력된 순서대로 정렬한다. 맨 앞에 음악이 해당 조건에 부합하는 음악이므로 이 음악의 제목을 리턴
solution.js
function solution(m, musicinfos) {
const answer = [];
const normalizationPitch = (pitchs) => {
const arr = [];
for (let i = 0; i < pitchs.length; i++) {
const temp = pitchs[i] !== '#' ? pitchs[i] : arr.pop() + '#';
arr.push(temp);
}
return [...arr];
};
const m_normalization = normalizationPitch(m);
const caculateMusicTime = (start, end) => {
let [startH, startM] = start.split(':');
let [endH, endM] = end.split(':');
startH *= 1;
startM *= 1;
endH *= 1;
endM *= 1;
if (endM < startM) {
endM += 60;
endH -= 1;
}
const timeH = endH - startH;
const timeM = endM - startM;
return timeH * 60 + timeM;
};
const getActualSoundPlay = (sheetmusic, musicTime) => {
let idx = 0;
const arr = [];
const sheetmusic_normalization = normalizationPitch(sheetmusic);
const musicLength = sheetmusic_normalization.length;
for (let time = 0; time < musicTime; time++) {
if (idx === musicLength) {
idx = 0;
}
arr.push(sheetmusic_normalization[idx++]);
}
return [...arr];
};
const checkMusic = (soundPlayed) => {
const mValue = m_normalization.length;
const maxValue = musicSeetMusic.length - mValue + 1;
for (let i = 0; i < maxValue; i++) {
const temp = musicSeetMusic.slice(i, i + mValue).join('');
if (temp === m) {
return true;
}
}
return false;
}
musicinfos.forEach((item, idx) => {
const musicinfo = item.split(',');
const musicTime = caculateMusicTime(musicinfo[0], musicinfo[1]);
const musicTitle = musicinfo[2];
const musicSoundPlayed = getActualSoundPlay(musicinfo[3], musicTime);
if (checkMusic(musicSoundPlayed)) {
const passMusic = {
title: musicTitle,
runningTime: musicTime,
index: idx
};
answer.push(passMusic);
}
});
if (answer.length === 0) {
return "(None)";
}
else if (answer.length === 1) {
return answer[0].title;
}
else {
answer.sort((a, b) => {
if (a.runningTime > b.runningTime) {
return -1;
}
if (a.runningTime < b.runningTime) {
return 1;
}
if (a.index > b.index) {
return 1;
}
if (a.index < b.index) {
return -1;
}
});
return answer[0].title;
}
return answer;
}