Programmers Level.2 Question Review 📓
문제출처: https://programmers.co.kr/learn/courses/30/lessons/17683
/*
한 요소당 '시작시간, 끝나는시간, 음악제목, 악보정보' 순서로 들어온다.
음악길이 > 재생된 시간 = 재생시간만큼만 재생
음악길이 < 재생된 시간 = 처음부터 반복해서 재생
1. 재생된 시간(길이; playingTime)구하기
2. actualPlayingInfo라는 변수에 실제 재생되었던 멜로디를 playingTime의 길이만큼 채우기
3. actualPlayingInfo가 m을 가지고 있는지 확인해야함.
*/
function solution(m, musicinfos) {
let answer;
let allPassedMusic = [];
musicinfos.forEach(el => {
let passedMusic = []; //[playingTime, 음악이름]
let curStr = el.split(",");//, 단위로 쪼개진 배열로 받기. [ '12:00', '12:14', 'HELLO', 'CDEFGAB' ]
const playingTime = getPlayingTime(curStr[0], curStr[1]); //14
const actualPlayingInfo = fillMusicNote(new Array(playingTime), curStr[3]);
const hasM = checkMusicNote(actualPlayingInfo, m);
if (hasM) {
answer = curStr[2];
passedMusic.push(playingTime);
passedMusic.push(curStr[2]);
allPassedMusic.push(passedMusic);
}
})
if (!answer) {
answer = `(None)`;
} else if (allPassedMusic.length >= 2){//조건이 일치하는 음악이 여러 개일 때에는 라디오에서 재생된 시간이 제일 긴 음악 제목을 반환한다. 재생된 시간도 같을 경우 먼저 입력된 음악 제목을 반환한다.
let longestMusic;
let longestPlayingTime = 0;
allPassedMusic.forEach(el => {
if (el[0] > longestPlayingTime) { //조건에 부합하는 음악이 2개이상일 때
longestPlayingTime = el[0];//el = [playingTime, 음악이름]
longestMusic = el[1];
} else if (el[0] === longestPlayingTime){ //조건에 부합하는 음악의 재생 시간들까지 같다면, 먼저 입력된 음악이 longestMusic.
}
});
answer = longestMusic;
}
return answer;
}
function getPlayingTime (start, end){//'12:00', '12:14'
let min;
let hr = end.substring(0, 2) - start.substring(0, 2);
if (hr > 0){ //시 단위가 0보다 클 때, 시를 분으로 바꾸어 분과 합치는 작업 필요.
const endMin = (end.substring(0, 2))*60 + end.substring(3)*1; //📍📍📍
const startMin = (start.substring(0, 2))*60 + start.substring(3)*1; //📍📍📍
min = endMin - startMin;
} else {
min = end.substring(3) - start.substring(3);
}
return min;
}
function fillMusicNote (emptyArr, str){
let idx = 0;
let playingNote = str.split(""); //#이 있는 경우에 앞전 요소와 합치고 앞전 요소는 빼야함.
playingNote.forEach((el, idx) => {
if (el === '#') {
el = `${playingNote[idx - 1]}` + `${el}`;
playingNote.splice(idx - 1, 2, el);
}
})
for (let i = 0; i < emptyArr.length; i++){
let curLetter = playingNote[i];
if (!curLetter){//악보정보가 실제실행시간보다 짧을 때. 처음부터 다시 실행되어야 함.
if (idx >= playingNote.length) {idx = 0};
curLetter = playingNote[idx];
idx++;
}
emptyArr[i] = curLetter;
}
return emptyArr;
}
function checkMusicNote (musicNote, melody){
//boolean으로 결과 반환. musicNote는 array로 들어오고, melody는 string으로 들어온다.
let arrMelody = melody.split("");
arrMelody.forEach((el, idx) => {
if (el === '#') {
el = `${arrMelody[idx - 1]}` + `${el}`;
arrMelody.splice(idx - 1, 2, el);
}
});
let melLength = arrMelody.length;
for(let i = 0; i < musicNote.length; i++){
if(musicNote[i][0] === melody[0]){
//melody의 길이만큼 musicNote의 요소들을 합쳐서 string으로 비교하기
const tempStr = musicNote.slice(i, i + melLength).join("");
if (tempStr === melody) {
return true;
}
}
};
return false;
}
+ 추가로 만든 테스트 케이스:
solution("ABCDEFG", ["12:00,12:14,HELLO,CDEFGAB", "13:00,13:05,WORLD,ABCDEF"]) //"HELLO"
solution("CC#BCC#BCC#BCC#B", ["03:00,03:30,FOO,CC#B", "04:00,04:08,BAR,CC#BCC#BCC#B"]) //"FOO"
solution("ABC", ["12:00,12:14,HELLO,C#DEFGAB", "13:00,13:05,WORLD,ABCDEF"]) //"WORLD"
solution("ABC", ["12:00,12:14,HELLO,C#DEFGAB", "13:00,13:05,WORLD,BCDEF"]) //"(None)"
solution("ABC", ["12:00,12:14,DROPTHEBEAT,ABCDEF", "12:00,12:14,VIVA,ABCDEF", "12:00,12:14,HELLO,ABCDEF"]) //"DROPTHEBEAT"
solution("A#B", ["12:00,12:03,a,BA#BB#"])//"a"
solution("A#B", ["12:00,12:03,a,A#B","12:00,12:08,b,A#B"]) //"b"
solution("A#BC#DFFF", ["12:00,12:07,a,A#BC#DFFF", "12:00,12:06,b,A#BC#"]) //"a"
solution("AAAA", ["12:00,12:05,a,AAAA", "12:00,12:05,b,AAAA"]); //"a"
solution("AAAA", ["12:00,14:05,a,AAAA", "12:00,12:06,b,AAAA"]); //"b"
sort()
정렬을 하면 더욱 간단해진다. //수정 전
if (!answer) {
answer = `(None)`;
} else if (allPassedMusic.length >= 2){
let longestMusic;
let longestPlayingTime = 0;
allPassedMusic.forEach(el => {
if (el[0] > longestPlayingTime) { //조건에 부합하는 음악이 2개이상일 때
longestPlayingTime = el[0];//el = [playingTime, 음악이름]
longestMusic = el[1];
} else if (el[0] === longestPlayingTime){ //조건에 부합하는 음악의 재생 시간들까지 같다면, 먼저 입력된 음악이 longestMusic.
}
});
answer = longestMusic;
}
//----------------------------------------------------------------------------------------------------------
//수정 후
if (!answer) {
answer = `(None)`;
} else if (allPassedMusic.length >= 2){
allPassedMusic.sort((a, b) => b[0] - a[0]);
answer = allPassedMusic[0][1];
}
*1
을 하지 않은 상태에서는 substring의 결과가 String타입으로 반환되어 84 + 005
가 된다. 즉, 원하는 결과는 845
인데 84005
를 반환 받게 되는 것이다.end.substring(3)
에도 1
을 곱해줌으로써 숫자형으로 강제타입변환 후 덧셈을 진행한다. 항상 연산하는 값들의 타입을 생각할 것!! (중요⭐️⭐️⭐️)const endMin = (end.substring(0, 2))*60 + end.substring(3)*1; //📍📍📍
const startMin = (start.substring(0, 2))*60 + start.substring(3)*1; //📍📍📍
#
이 붙는 요소(예. C#
)들이 있어 단순히 split("")을 통해 문자열을 배열형태로 바꾸는 것 뿐만 아니라 앞전 알파벳과 #
기호를 합쳐주는 과정이 필요했다. 설계시에는 생각하지 못했던 부분이라 수정하는 데에 시간이 꽤나 소요되었다.