카카오 코딩테스트 | 방금그곡
오늘 하루종일 붙잡고 있었던 문제.. 풀어내긴 했지만 진이 다 빠져서 설명 포기^^!
삽질
재생 시간을 잘못 구했다.
13:30 - 14:40 처럼 끝난 시각의 분이 시작 시각의 분보다 큰 경우만 생각했다. 13:50 - 14:00 처럼 끝난 시각의 분이 더 작은 경우도 고려해야 한다.
나름 노력한 점
주어진 input을 의미 있는 자료구조로 만들기 위해 Map을 사용했다. 값을 한번에 뽑아오는 게 편해서 Map을 썼는데 이 문제에서는 딱히 그런 작업을 할 일이 없어서 그냥 객체로 사용했어도 됐을 것 같다. 근데 아직 미숙해서 코드가 너무 지저분하다. 자료구조 만들 때도 함수를 만들어서 썼어야 했는데 하다가 너무 짱나서 그냥 막 써버렸다. 😅
배운 점
이렇게 input을 받아 사용 가능한 데이터로 처리하는 걸 tokenize 라고 하는 걸 직접 느꼈다. 코코아 수업 때 들었던 개념인데 직접 해보니까 뜻이 와닿았다. 여기서 중요한 점이 있었는데, 각각의 token을 비교가 가능하도록 만들어줘야한다. 무슨 뜻이냐면 문제에서 C와 같은 것은 한글자, C#와 같이 #이 붙은 것은 두글자이다. 이것을 ['C', 'C#']
이렇게 배열로 만들던지, 아니면 #이 붙은 건 문제에서 안쓰이는 아예 다른 문자(예를 들면 소문자. 'Cc'
)로 치환하는 등 적절한 처리가 필요하다.
설계
코드
function solution(m, musicinfos) {
const getPlayTime = (start, end) => { // string type의 시간을 받아 재생 시간 리턴
const startTime = start.split(':').map(str => Number(str));
const endTime = end.split(':').map(str => Number(str));
if(startTime[1] <= endTime[1]) {
return (endTime[0] - startTime[0]) * 60 + endTime[1] - startTime[1];
}
if(startTime[1] > endTime[1]) {
endTime[1] += 60;
endTime[0] -= 1;
return (endTime[0] - startTime[0]) * 60 + endTime[1] - startTime[1];
}
}
const getUnitArr = (musicSheet) => {
const splitMusicSheet = musicSheet.split('');
for(let i = 1; i < splitMusicSheet.length; i++) {
if(splitMusicSheet[i] === '#') {
splitMusicSheet[i - 1] = splitMusicSheet[i - 1].toLowerCase();
}
}
return splitMusicSheet.filter(scale => scale !== '#')
}
// string type의 악보 받아 한 곡이 몇 분인지 리턴
const getMusicPlayTime = (musicSheet) => {
const unitArr = getUnitArr(musicSheet);
const musicPlayTime = unitArr.length;
return musicPlayTime
}
// 재생 시간에 맞게 노래 자르거나 이어붙이기 - 리턴값을 m과 비교할 것임
const getEntireMusicSheet = (playTime, musicPlayTime, unitArr) => {
let entireMusicSheetArr = [];
const repeat = Math.floor(playTime / musicPlayTime);
const remain = playTime % musicPlayTime;
if(playTime < musicPlayTime) {
return unitArr.slice(0, playTime + 1).join('');
}
if(playTime >= musicPlayTime) {
for(let i = 1; i <= repeat; i++) {
entireMusicSheetArr.push(...unitArr);
}
entireMusicSheetArr.push(...unitArr.slice(0, remain));
}
return entireMusicSheetArr.join('');
}
const hasM = (entireMusicSheet, m) => {
return (entireMusicSheet.includes(m) === true) ? true : false
}
// --------------------------------------- 실행부 ---------------------------------------
const tokenizedM = getUnitArr(m).join('');
const splitInfos = musicinfos.map(info => info.split(','));
console.log(splitInfos)
let data = [];
for(let i = 0; i < splitInfos.length; i++) {
const infoMap = new Map();
const playTime = getPlayTime(splitInfos[i][0], splitInfos[i][1]);
const musicPlayTime = getMusicPlayTime(splitInfos[i][3]);
const unitArr = getUnitArr(splitInfos[i][3]);
const entireMusicSheet = getEntireMusicSheet(playTime, musicPlayTime, unitArr)
infoMap.set('순서', i);
infoMap.set('제목', splitInfos[i][2]);
infoMap.set('재생된시간', playTime);
infoMap.set('재생된전체악보', entireMusicSheet);
infoMap.set('m포함?', hasM(entireMusicSheet, tokenizedM));
data.push(infoMap);
}
const musicsContainM = data.filter(musicInfo => musicInfo.get('m포함?') === true)
if(musicsContainM.length === 0) return '(None)';
if(musicsContainM.length === 1) return musicsContainM[0].get('제목');
let comparedItem = musicsContainM[0]
for(let i = 1; i < musicsContainM.length; i++) {
const currItem = musicsContainM[i]
if(comparedItem.get('재생된시간') < currItem.get('재생된시간')) {comparedItem = currItem}
if(comparedItem.get('재생된시간') >= currItem.get('재생된시간')) continue;
}
return comparedItem.get('제목');
}
Author And Source
이 문제에 관하여(카카오 코딩테스트 | 방금그곡), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@dyongdi/카카오-코딩테스트-방금그곡저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)