본문 바로가기
Algorithm/etc

[파이썬] 프로그래머스 : [3차] 방금그곡 (Lv.2)

by 베짱이28호 2023. 6. 28.

[파이썬] 프로그래머스 : [3차] 방금그곡 (Lv.2)

 

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr


풀이

0. 방향성 생각

조건에 m이 1~1439이다 :  최소 1분은 노래가 재생되고, 00:00 부터 최대 23:59분까지 재생된다.

유의할 점은 C# 같은 샵 붙은 문자는 한 음이므로 다른 덩어리로 치환해서 푼다.

날짜, 시간 등의 문자열을 처리하는 경우에는 이전에 프로그래머스 LV1 카카오 기출에서도 있었는데

1월1일, 00시 00분 등을 기준으로 해서 며칠이 지났는지 이런식으로 풀면 예외처리 할 필요 없이 쉽게 풀 수 있다.

 

1. 문자열 치환

def solution(m, musicinfos):
    
    # m # 제거
    change = [('C#','U'),('D#','W'),('F#','X'),('G#','Y'),('A#','Z')]
    for a,b in change:
        m = m.replace(a,b)
    listen = m
    listen_time = len(listen)

    # info 악보 # 제거
    info = []
    for val in musicinfos:
        temp = val.split(',')
        for a,b in change:
            temp[-1] = temp[-1].replace(a,b)
        info.append(temp)

입력 데이터 m에 대해서 #이 포함된 문자열을 모두 치환해준다.

마찬가지로 musicinfo에서 이터레이션을 돌릴 때 split으로 시작시간, 끝시간,제목, 악보를 구분해주고

악보에 있는 문자열을 제거해준다.

 

1. 시간 추출, 악보 정보 변경, 정답 후보 추출

    answer = []
    for idx,(start,end,title,melody) in enumerate(info):
        # 플레이 타임
        t1 = 60*int(start[:2])+int(start[-2:])
        t2 = 60*int(end[:2])+int(end[-2:])
        play_time = t2-t1
        
        # 악보 정보 변경
        melody_len = len(melody)
        if play_time >= melody_len : # 플탐이 악보보다 길거나 같은 경우 멜로디 반복
            p,q = divmod(play_time,melody_len)
            melody = melody*p + melody[:q]
            melody_len = len(melody)
            info[idx][-1] = melody
                
        else: # 플탐이 작은경우
            melody = melody[:play_time]
            melody_len = len(melody)
            info[idx][-1] = melody
            
        # 조건 맞으면 추가
        for i in range(melody_len-listen_time+1):
            if melody[i:i+listen_time] == listen :
                answer.append([play_time,t1,title]) # 재생시간, 시작시간, 제목

start, end를 추출해서 분 단위로 변경한다. 또한 시간 차이를 구해서 플레이 타임을 구한다.

1) 현재 악보 길이보다 플레이 타임이 긴 경우 현재 노래가 반복해서 재생된 경우이다.

플레이 타임만큼 악보를 확장해준다.

2) 그렇지 않은 경우 노래 한 곡이 끝나기 전 그 일부분을 듣는 경우이다.

악보를 플레이 타임 길이만큼 잘라낸다.

 

for문을 통해 일치하는 부분이 있으면 정답 후보군에 넣는다.

문제의 주어진 조건에 '일치하는 음악이 여려 개일 때에는 재생시간이 제일 긴 음악, 선 입력된 음악을 반환한다'라 했으므로 answer에 플레이타임, 시작시간, 제목 세 개를 모두 넣는다

 

2. 정답 추출

    if not answer :
        return "(None)"
    else :
        answer.sort(key=lambda x:(x[0],-x[1])) # 재생시간 긴거 뒤로, 시작시간 작은거 뒤로
        return answer[-1][-1]

리스트가 비어있으면 "(None)"

아닌 경우는 정렬 기준에 맞춰서 맨 뒤에 정답이 오게한다.


전체코드

def solution(m, musicinfos):
    
    # m # 제거
    change = [('C#','U'),('D#','W'),('F#','X'),('G#','Y'),('A#','Z')]
    for a,b in change:
        m = m.replace(a,b)
    listen = m
    listen_time = len(listen)

    # info 악보 # 제거
    info = []
    for val in musicinfos:
        temp = val.split(',')
        for a,b in change:
            temp[-1] = temp[-1].replace(a,b)
        info.append(temp)

    answer = []
    for idx,(start,end,title,melody) in enumerate(info):
        # 플레이 타임
        t1 = 60*int(start[:2])+int(start[-2:])
        t2 = 60*int(end[:2])+int(end[-2:])
        play_time = t2-t1
        
        # 악보 정보 변경
        melody_len = len(melody)
        if play_time >= melody_len : # 플탐이 악보보다 길거나 같은 경우 멜로디 반복
            p,q = divmod(play_time,melody_len)
            melody = melody*p + melody[:q]
            melody_len = len(melody)
            info[idx][-1] = melody
                
        else: # 플탐이 작은경우
            melody = melody[:play_time]
            melody_len = len(melody)
            info[idx][-1] = melody
            
        # 조건 맞으면 추가
        for i in range(melody_len-listen_time+1):
            if melody[i:i+listen_time] == listen :
                answer.append([play_time,t1,title]) # 재생시간, 시작시간, 제목

    if not answer :
        return "(None)"
    else :
        answer.sort(key=lambda x:(x[0],-x[1])) # 재생시간 긴거 뒤로, 시작시간 작은거 뒤로
        return answer[-1][-1]

 

코멘트

문제는 안어려웠는데 D# 대신 #D 치환으로 해놔서 시간 플렉스 해버림.

시간처리 막히신 분들은 프로그래머스 레벨1 개인정보 수집 유효기간 풀어보시면 될듯.

댓글