본문 바로가기
코딩테스트

[파이썬] 방금그곡 - 2018 KAKAO BLIND RECRUITMENT [CODING TEST #41]

by ALTERww 2022. 8. 4.
320x100

https://school.programmers.co.kr/learn/courses/30/lessons/17683#

 

 

  1. musicinfos 속 정보들을 토큰화하여 리스트에 저장
  2. '#'이 붙은 멜로디는 replace() 함수를 이용하여 소문자로 치환 ( 'C#' -> 'c'로 치환)
  3. 각 악보별로 재생 시간을 계산
  4. m과 fixed_melody의 길이에 따라 구분.
    1. len(m) < len(fixed_melody) 이면, 그냥 주어진 fixed_melody를 한 번 반복한 뒤 재생 시간만큼 슬라이싱.
      그리고 m이 그 안에 있는지 check
    2. 그 외의 경우에는, fixed_melody를 적어도 len(m)의 2배 이상만큼 반복시켜야 한다.
      아래 테스트 케이스의 경우, len(m) = 12이고 FOO의 멜로디 길이는 3이다.
      m은 비교적 짧은 melody가 여러번 반복되어 들려진 것일 수도 있기 때문에, 적어도 m의 2배 이상으로 반복시킨 뒤 m이 그 안에 있는지를 check해야 한다. 몫을 반환하는 '//' 연산자를 활용

 

5. 일치하는 음악이 여러 개이면, 우선순위에 따라 음악을 선정한다. 재생 시간을 튜플로 함께 저장하여 가장 긴 음악의 이름을 저장한다. 재생 시간도 같으면 먼저 들어온 음악을 리턴하는데, answer_list 순서가 들어온 순서라서 재생 시간이 같을 경우 continue하도록 하였음.

 

일치하는 음악들이 담긴 answer_list에서 최적의 답을 찾는 부분을 구현할 때 처음에는 이렇게 구현했었다. 

    # 없을 경우 (None) 출력       
    if len(answer_list) == 0:
        return '(None)'
    elif len(answer_list) == 1:
        return answer_list[0][0]
    
    # 2개 이상일 경우 우선순위에 따라 선정
    else: 
        max_time = 0
        max_index = 0
        for idx, answers in enumerate(answer_list): 
            if max_time < answers[1] : # 가장 긴 음악을 찾는다
                max_time = answers[1]
                max_index = idx
            elif max_time == answers[1]: # 재생 시간이 같으면 먼저 들어온 것이 우선이므로 continue
                continue
        return answer_list[max_index][0]

 

그런데 위처럼 enumerate를 굳이 쓰지 않고, answers[0]값만 계속 갱신하여 저장하면 되는 거라 아래처럼 좀 더 간결하게 수정했다.

 

최종 코드

def solution(m, musicinfos):
    answer = ''
    answer_list = []
    music_list = [] # music_list[][0 : start / 1 : end / 2 : name / 3 : melody]
    for music in musicinfos:
        music_list.append(music.split(","))
    
    # 각 INFO를 돌면서, 음표 C#D#F#G#A# 소문자로 처리하기. replace('C#','c')
    # end - start를 계산. len(m)보다 짧으면 그 길이만큼 재생.
    # len(m)보다 길면 악보를 두 배로 늘린다. 그리고 end - start까지 찾으면서 m이 나오는지 check.
    m = m.replace('C#','c').replace('D#','d').replace('F#','f').replace('G#','g').replace('A#','a').replace('E#','e')
    for music in music_list:
        fixed_melody = music[3].replace('C#','c').replace('D#','d').replace('F#','f').replace('G#','g').replace('A#','a').replace('E#','e')
        start_time = 60 * int(music[0].split(':')[0]) + int(music[0].split(':')[1]) 
        end_time = 60 * int(music[1].split(':')[0]) + int(music[1].split(':')[1]) 
        time = end_time - start_time
        if len(m) < len(fixed_melody): # m이 melody보다 짧을 때
            fixed_melody *= 2
            melody = fixed_melody[:time]
        else: # m이 melody보다 길 때
            fixed_melody *= len(m)//len(fixed_melody)  * 2 + 1
            melody = fixed_melody[:time]
            print(melody)
        
        # answer_list 중 우선순위는 재생 시간, 그리고 입력된 순서임. 
        # 입력된 순서는 answer_list에 append되는 순서랑 같음. end-start만 추가로 저장하자. tuple로!    
        if m in melody:
            answer_list.append((music[2],time))
            
    # 없을 경우 (None) 출력       
    if len(answer_list) == 0:
        return '(None)'
    elif len(answer_list) == 1:
        return answer_list[0][0]
    
    # 2개 이상일 경우 우선순위에 따라 선정
    else: 
        max_time = 0
        for answers in answer_list: 
            if max_time < answers[1] : # 가장 긴 음악을 찾는다
                max_time = answers[1]
                song_name = answers[0]
            elif max_time == answers[1]: # 재생 시간이 같으면 먼저 들어온 것이 우선이므로 continue
                continue
        return song_name

댓글