[알고리즘] 프로그래머스 Lv2 방금그곡

Sieun Dorothy Lee·2023년 12월 15일
0

문제

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

풀이과정

  1. 총 재생 시간을 구한다
  2. 재생 시간동안 재생되는 노래의 음을 기록한다(total_melody)
  3. 네오가 들은 음이 total_melody에 있는지 구한다

풀이 과정은 단순하다
그러나 음의 종류에 #이 있어서 이 점이 좀 까다로웠다.

주의해야하는 부분은 모두 #과 관련이 있다.
1. total_melody 자체를 잘못 구하는 경우 -> 단순히 노래의 길이를 len(melody)로 구하게 되면, 노래의 길이가 아닌 문자열의 길이를 구하게 된다. 음에는 #이 붙은 것도 있다..!
2. total_melody에 m이 있기는 하나, 제일 뒤의 음이 사실 #이 더 붙은 경우 -> 예시 테스트 케이스의 세번째 케이스에서 볼 수 있다. -> 이때는 total_melody에서 m에 해당하는 부분 뒤에 #이 붙었는지 확인해줘야하는데, m이 total_melody 안에 여러 번 나오는 경우도 있다는 점에 주의해야 한다.

코드

def solution(m, musicinfos):
    answer_list = [] # 네오가 들은 음(m)이 곡에 포함된 경우, 여기에 시간과 곡 이름을 추가
    for info in musicinfos:
        start, end, name, melody = info.split(',') # 구분자가 , 이므로 , 로 split
        hh = int(end[0:2]) - int(start[0:2])
        mm = int(end[3:]) - int(start[3:])
        if mm < 0:
            hh -= 1
            mm = 60 + mm

        play_time = hh * 60 + mm # 총 재생시간을 분으로 바꿈

        melody_list = [] # melody 문자열의 길이일 뿐, 음의 개수는 아님 -> #이 붙은 음도 있으므로
        i = 0
        while i < (len(melody) - 1): # melody 순회하면서 뒤에 오는 문자가 #이면 #까지 포함해서 melody_list에 저장, 아니면 그 문자만 저장 -> melody에 포함된 음을 구분하는 용도
            if melody[i + 1].isalpha():
                melody_list.append(melody[i])
                i += 1
            else:
                melody_list.append(melody[i]+melody[i+1])
                i += 2
        if i == len(melody) - 1:
            melody_list.append(melody[i])

        total_melody = ''.join(melody_list * (play_time // len(melody_list)) + melody_list[0:(play_time % len(melody_list))]) 
        # 총 플레이 시간동안 재생된 음들을 //와 %를 사용하여 리스트 형태로 구하고 문자열로 만듬
        # print(total_melody)

        while total_melody.find(m) != -1: # total_melody에 네오가 들은 음(m)이 있으면
            idx = total_melody.find(m) # 인덱스를 구해서
            if idx + len(m) == len(total_melody): # 인덱스 + m의 길이가 total_melody의 전체 길이와 같으면 -> 끝에 오는 문자가 없다는 말
                answer_list.append((play_time, name)) # 정답이 될 수 있음
                break
            else: # 인덱스 + m의 길이가 total_melody의 전체 길이와 같지 않으면 -> 뒤에 #이 있을 수 있음 
                if total_melody[idx+len(m)] != '#': # #이 없으면 -> 정답이 될 수 있음
                    answer_list.append((play_time, name))
                    break
                else: # #이 있으면, m+'#'을 total_melody에서 제거하고 다시 m 있는지 확인
                    total_melody = total_melody.replace(m+'#', '')

    if answer_list:
        answer_list.sort(key=lambda x: -x[0]) 
        # 정답이 여러 개 있으면, 재생 시간이 제일 긴 음악이 정답이 되고, 재생 시간이 같으면 먼저 입력된 음악이 정답이 되므로 play_time 기준 내림차순 정렬
        # print(answer_list)
        return answer_list[0][1] # 곡 제목 return
    else:
        return '(None)'

다른 사람의 풀이

def shap_to_lower(s):
    s = s.replace('C#','c').replace('D#','d').replace('F#','f').replace('G#','g').replace('A#','a')
    return s

def solution(m,musicinfos):
    answer=[0,'(None)']   # time_len, title
    m = shap_to_lower(m)
    for info in musicinfos:
        split_info = info.split(',')
        time_length = (int(split_info[1][:2])-int(split_info[0][:2]))*60+int(split_info[1][-2:])-int(split_info[0][-2:])
        title = split_info[2]
        part_notes = shap_to_lower(split_info[-1])
        full_notes = part_notes*(time_length//len(part_notes))+part_notes[:time_length%len(part_notes)]
        if m in full_notes and time_length>answer[0]:
            answer=[time_length,title]
    return answer[-1]

#이 붙은 음을 소문자로 바꾸는 과정을 추가해서 깔끔하게 풀이한 코드를 발견했다!
문자열 문제는 replace를 잘 활용해야 한다는 점을 배운다.

profile
성장하는 중!

0개의 댓글