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

Munang·2021년 9월 22일
0

알고리즘

목록 보기
25/26
post-custom-banner

1. 문제 해설

문제 해설은 어렵지 않았다. 하지만,, 생각보다 조건이 까다로웠고 그 조건을 매끄럽게 해결하는 것이 어려웠다. 실제로 다른 블로그의 답을 보고서도 이.. 예외케이스가 어떻게 이 2줄로 해결되지..? 라고 몇 시간이나 생각을 계속 했다.


문제는 이렇다. musicinfos를 인자로 받으면 ,를 기준으로 하나씩
음악 재생 시작 시간, 종료 시간, 곡명, 곡의 악보 이다.
여기서 구해야 할 것은 라디오에서 재생된 시간이 제일 긴 음악 제목을 반환하는 것이다.

2. 어려웠던 점

2-1. 예외사항

일단 라디오에서 재생된 시간이 제일 긴 음악 제목을 반환하는 것 자체가 예외사항이 나에게는 조금 까다로웠다.

  • 재생된 시간도 같을 경우 먼저 입력된 음악 제목을 반환
  • 음악 끝부분과 처음 부분이 이어서 재생된 멜로디일 수도 있다.

첫 번째 예외사항은 괜찮았는데, 두 번째 예외사항에서 고려해야 할게 많았다.

# 악보 내에서 연속된 비교가 이뤄져야 함
# 연속된 비교가 이뤄진 후에도 더 긴 연주를 하는 경우에만 제외를 시켜야함 
for i in cpr_list(=list(m)):
        if i in music_play_list_temp and cpr_list.index(i)>=temp:
                result.append(i)
                temp = cpr_list.index(i)
                
        if len(result)==len(sheet):
            result = []
            for i in music_play_list:
                if i in sheet:
                    music_play_list.remove(i)
                    result.append(i)

그래서 이렇게 처리를 했는데, 여기서도 고려해야 할게 너무 많았다.
예를 들어 다음과 같은 케이스의 경우에는 FOO가 나와야 하는데 계속 BAR가 나왔다.
"CCB", ["03:00,03:10,FOO,CCB#CCB", "04:00,04:08,BAR,ABC"]
이런 경우의 케이스도 처리하려면 예외 처리를 수도 없이 해야 했고
내 풀이가 애초에 잘못된 접근이라고 생각이 들었다. 그래서 다른 사람들의 풀이를 참고해봤다.

3. 풀이

3-1. 모범 풀이

이 블로그에서 참고했다.

def change(melody):
    if 'A#' in melody: melody = melody.replace('A#', 'a')
    if 'C#' in melody: melody = melody.replace('C#', 'c')
    if 'D#' in melody: melody = melody.replace('D#', 'd')
    if 'F#' in melody: melody = melody.replace('F#', 'f')
    if 'G#' in melody: melody = melody.replace('G#', 'g')
    return melody

def solution(m, musicinfos):
    m = change(m)
    answer = ('(None)', None)
    for info in musicinfos:
        start, end, title, melody = info.split(',')
        start_h, start_m, end_h, end_m = map(int, start.split(':') + end.split(':'))
        time = 60*(end_h-start_h) + (end_m-start_m)
        melody = change(melody)
        melody_played = (melody*time)[:time]
        if m in melody_played:
            if (answer[1] == None) or (time > answer[1]):
                answer = (title, time)
    return answer[0]

먼저 #이 포함된 케이스를 모두 lower처리 했다. 이게 더 편하기 때문인 것으로 보인다.
풀이의 전체적인 로직은 동일한데 이 부분만 달랐다.
나는 이 2줄을 이렇게 구현하고도 실패했는데, 이 모든 예외가 2줄에 해결된다는게 놀라웠다.

## 내가 구현한 부분
# 악보 내에서 연속된 비교가 이뤄져야 함
# 연속된 비교가 이뤄진 후에도 더 긴 연주를 하는 경우에만 제외를 시켜야함 
for i in cpr_list(=list(m)):
        if i in music_play_list_temp and cpr_list.index(i)>=temp:
                result.append(i)
                temp = cpr_list.index(i)
                
        if len(result)==len(sheet):
            result = []
            for i in music_play_list:
                if i in sheet:
                    music_play_list.remove(i)
                    result.append(i)
## 모범 답안
melody = change(melody)
melody_played = (melody*time)[:time]

(melody*time)[:time] 이 부분 만으로 어떻게 연속적인 비교가 가능할지 의문이었다. 곡에 재생 시간을 곱하고 다시 재생시간 만큼 자르면 뭐하러 자르는 것인지? 의문이었다.

그래서 직접 디버깅을 해보기로 했다. 디버깅을 해보고 나서 알게되었다.
문자열 자체 만으로 비교가 가능 하다는 것을... 나는 문자열 자체만으로 비교가 안되는 줄 알았는데... 되는 것이었다...

그리고 악보의 처음과 끝 이슈는 나는 #을 제대로 처리해주지 못해 발생한 것이었다. #이 붙은 문자를 아예 다른 문자로 치환해주면 해당 이슈가 발생하지 않는다....
그런 것이었다..

3-2. 내 풀이

import re
# 악보 내에서 연속된 비교가 이뤄져야 함
# 연속된 비교가 이뤄진 후에도 더 긴 연주를 하는 경우에만 제외를 시켜야함 

def change(melody):
    if 'A#' in melody: melody = melody.replace('A#', 'a')
    if 'C#' in melody: melody = melody.replace('C#', 'c')
    if 'D#' in melody: melody = melody.replace('D#', 'd')
    if 'F#' in melody: melody = melody.replace('F#', 'f')
    if 'G#' in melody: melody = melody.replace('G#', 'g')
    return melody

def solution(m, musicinfos):
    m = change(m)
    answer = ('(None)', None)
    for musicinfo in musicinfos:
        music_start, music_end, title, sheet = musicinfo.split(",")
        music_play_time = (int(music_end.split(":")[0]) - int(music_start.split(":")[0]))*60 + (int(music_end.split(":")[1]) - int(music_start.split(":")[1]))
        sheet = change(sheet)
        music_play_list = ''.join([sheet[i%len(sheet)] for i in range(music_play_time)])
        
        if m in music_play_list:
            if (answer[1] == None) or music_play_time > answer[1]:
                answer = (title, music_play_time)
        
    return answer[0]
    ```
post-custom-banner

0개의 댓글