[JS][프로그래머스LV2]방금그곡
Algorithm/Programmers

[JS][프로그래머스LV2]방금그곡

문제 번호

 

코딩테스트 연습 - [3차] 방금그곡

방금그곡 라디오를 자주 듣는 네오는 라디오에서 방금 나왔던 음악이 무슨 음악인지 궁금해질 때가 많다. 그럴 때 네오는 다음 포털의 '방금그곡' 서비스를 이용하곤 한다. 방금그곡에서는 TV,

programmers.co.kr

 

 

알고리즘 분류

 

 

문제 풀이

 알고리즘은 어렵지않다. 주어진 정보를 어떻게 가공하여서 잘 비교하나가 중요한 문제였다.

이번 문제에서 가장 중요한 내용은 멜로디로 주어지는 내용중에 'C#'과 같이 두 글자를 한 글자로 보아야 한다는 것이다. 입력 'm' 이 대문자로만 주어진다는 내용을 못봤는데 다른 블로그를 참고해보니 소문자로는 입력되지 않는것 같다. 그래서 'C#'과 같이 뒤에 '#'이 붙은 멜로디의 경우 '#'앞에 있는 알파벳을 소문자로 바꾸어서 사용하였다. (''C#의 경우 c로 치환).

    // 1.주어진 노래들을 객체로 만들어서 배열에 입력받는다.
    let song = [];
    for(let i=0; i<musicinfos.length; i++){
        let start, end, title, code;
        let temp = musicinfos[i].split(',');
        start = temp[0];
        end = temp[1];
        title = temp[2];
        code = temp[3].replace(/(C#)/g,'c')
                      .replace(/(D#)/g,'d')
                      .replace(/(F#)/g,'f')
                      .replace(/(G#)/g,'g')
                      .replace(/(A#)/g,'a');        
        song.push({'start':start, 'end':end, 'title':title, 'code':code});
    }

 

멜로디에 대한 부분만 잘 해결했다면 나머지는 쉽다. 그냥 문제에서 요구하는대로 구현만 하면 된다.

그나마 조금 신경써야할 부분이라면 노래의 끝과 시작시간을 이용하여 플레이타임을 구하고, 이걸 바탕으로 해당 노래의 멜로디가 중간에 끊기는지, 여러번 반복되는지 정도만 판별하면 된다.

    // 2.노래들의 playTime을 구한다.
    for(let i=0; i<song.length; i++){
        let time = song[i].start.split(':');
        time = time.concat(song[i].end.split(':'))        
        
        let playTime = 60*(time[2] - time[0]) + (time[3] - time[1]);
        song[i].playTime = playTime;
        // 라디오에서 나오는 노래가 중간에 끊길경우.
        if(playTime < song[i].code.length){            
            song[i].code = song[i].code.slice(0, playTime);
        }                
        else{
            song[i].code = song[i].code.repeat(playTime / song[i].code.length + 1);
        }
    }

처음에는 else 구문의 song[i].code를 구하는 부분에서 

song[i].code = song[i].code.repeat(playTime / song[i].code.length);

이라고 했었다가 실패를 보았다. 문제에서 주어지는 'm'은 같은 노래를 여러번 반복하는 경우도 포함한다. 같은 노래가 여러번 반복되는경우 song[i]의 code가 'm' 보다 짧다면 song[i]와 'm'이 같은 노래라도 찾지 못하는 경우가 생긴다.(나는 includes 메서드를 사용했기 때문이다.) 

 m = abcdab

 song[i].code = abcd

와 같은경우.

 그래서 song[i].code를 'playTime / song[i].code.length + 1' 만큼 반복시켜줘야한다. 그래야 가장 뒷부분에 ab 와 같이 짤린 부분까지 포함하여 찾을 수 있다.

'playTime / song[i].code.length' 일 경우 'abcd' 에서 'abcdab' 를 찾는다. (false)

'playTime / song[i].code.length + 1' 인 경우 'abcdabcd' 에서 'abcdab'를 찾는다. (true)

 

나는 조건에 맞는 노래들을 answer 배열에 모두 집어 넣은 후 문제에서 주어진 조건에 따라서 정렬했다.

    // 3. 노래 목록에 주어진 노래가 있는지 찾아본다.
    m = m.replace(/(C#)/g,'c')
         .replace(/(D#)/g,'d')
         .replace(/(F#)/g,'f')
         .replace(/(G#)/g,'g')
         .replace(/(A#)/g,'a');      
    for(let i=0; i<song.length; i++){
        if(song[i].code.includes(m))
            answer.push(song[i])
    }
    // 4. 노래 들을 조건에 맞게 정렬한다.
    answer.sort((a,b) => {
        let A = a.playTime;
        let B = b.playTime;
        if(A>B) return -1;
        else if(A<B) return 1;
        else return 0;
    });

 

마지막으로 찾는 노래가 없다면 '(None)'을 반환하고 아니면 answer[0]을 반환하자.

    if(answer.length === 0)
        return '(None)';
    return answer[0].title;

 

전체코드

function solution(m, musicinfos) {
    var answer = [];
    
    // 1.주어진 노래들을 객체로 만들어서 배열에 입력받는다.
    let song = [];
    for(let i=0; i<musicinfos.length; i++){
        let start, end, title, code;
        let temp = musicinfos[i].split(',');
        start = temp[0];
        end = temp[1];
        title = temp[2];
        code = temp[3].replace(/(C#)/g,'c')
                      .replace(/(D#)/g,'d')
                      .replace(/(F#)/g,'f')
                      .replace(/(G#)/g,'g')
                      .replace(/(A#)/g,'a');        
        song.push({'start':start, 'end':end, 'title':title, 'code':code});
    }
    
    // 2.노래들의 playTime을 구한다.
    for(let i=0; i<song.length; i++){
        let time = song[i].start.split(':');
        time = time.concat(song[i].end.split(':'))        
        
        let playTime = 60*(time[2] - time[0]) + (time[3] - time[1]);
        song[i].playTime = playTime;
        if(playTime < song[i].code.length){            
            song[i].code = song[i].code.slice(0, playTime);
        }                
        else{
            song[i].code = song[i].code.repeat(playTime / song[i].code.length + 1);
        }
    }        
    // 3. 노래 목록에 주어진 노래가 있는지 찾아본다.
    m = m.replace(/(C#)/g,'c')
         .replace(/(D#)/g,'d')
         .replace(/(F#)/g,'f')
         .replace(/(G#)/g,'g')
         .replace(/(A#)/g,'a');      
    for(let i=0; i<song.length; i++){
        if(song[i].code.includes(m))
            answer.push(song[i])
    }
    // 4. 노래 들을 조건에 맞게 정렬한다.
    answer.sort((a,b) => {
        let A = a.playTime;
        let B = b.playTime;
        if(A>B) return -1;
        else if(A<B) return 1;
        else return 0;
    });
    
    if(answer.length === 0)
        return '(None)';
    return answer[0].title;
}

특이사항