본문 바로가기
알고리즘 문제/프로그래머스_Lv2 도장깨기

[프로그래머스] 방금그곡 (Python)

by 스코필 2024. 1. 23.

문제 링크

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

 

프로그래머스

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

programmers.co.kr

 

문제설명

음악의 멜로디는 특정 시간만큼 반복하는데, 네오가 기억한 멜로디를 담은 문자열 m과 일치한다면

음악의 제목을 반환하고, 없다면 (None)을 리턴하는 문제이다.

  • 방금그곡 서비스에서는 음악 제목, 재생이 시작되고 끝난 시각, 악보를 제공한다.
  • 네오가 기억한 멜로디와 악보에 사용되는 음은 C, C#, D, D#, E, F, F#, G, G#, A, A#, B 12개이다.
  • 각 음은 1분에 1개씩 재생된다. 음악은 반드시 처음부터 재생되며 음악 길이보다 재생된 시간이 길 때는 음악이 끊김 없이 처음부터 반복해서 재생된다. 음악 길이보다 재생된 시간이 짧을 때는 처음부터 재생 시간만큼만 재생된다.
  • 음악이 00:00를 넘겨서까지 재생되는 일은 없다.
  • 조건이 일치하는 음악이 여러 개일 때에는 라디오에서 재생된 시간이 제일 긴 음악 제목을 반환한다. 재생된 시간도 같을 경우 먼저 입력된 음악 제목을 반환한다.
  • 조건이 일치하는 음악이 없을 때에는 "(None)"을 반환한다.

입력 형식

입력으로 네오가 기억한 멜로디를 담은 문자열 m과 방송된 곡의 정보를 담고 있는 musicinfos가 주어진다.

  • m은 음 1개 이상 1439개 이하로 구성되어 있다.
  • musicinfos는 100개 이하의 곡 정보를 담고 있는 배열로, 각각의 곡 정보는 음악이 시작한 시각, 끝난 시각, 음악 제목, 악보 정보가 ' , '로 구분된 문자열이다.
    • 음악의 시작 시각과 끝난 시각은 24시간 HH:MM 형식이다.
    • 음악 제목은 ' , ' 이외의 출력 가능한 문자로 표현된 길이 1 이상 64 이하의 문자열이다.
    • 악보 정보는 음 1개 이상 1439개 이하로 구성되어 있다.

출력 형식

조건과 일치하는 음악 제목을 출력한다.

 

풀이

input 3번 처럼, m = ABC이고 음악 악보가 C#DEFGAB일 경우,

음악 악보가 반복 재생하면 C#DEFGABC#D... 이 되기 때문에 악보를 비교했을 때,

일치하는 경우가 발생할 수 있으므로 악보에서 올림표(#)를 확실하게 구별해야 한다.

단순 반복문을 돌아, 올림표를 구분할 수도 있지만

악보의 올림표들을 객체로 만들어 특정 문자로 선언하고, 변환하는 것이

코드 길이를 더 줄일 수 있어 아래와 같이 코드를 작성하였다.

 

✅ Code - 성공

def solution(m, musicinfos):
    answer = ['(None)', 0]
    
    change_lst = {'A#' : '1', 'C#' : '2', 'D#': '3', 'F#': '4', 'G#': '5'}
    
    # 올림표 변환해주는 함수
    def change(music):          
        for s in change_lst:
            if s in music:
                music = music.replace(s, change_lst[s])
        return music
    
    m = change(m)
    
    for musicinfo in musicinfos:
        musicinfo = musicinfo.split(',')
        time1, time2, title, sheets = musicinfo[0].split(':'), musicinfo[1].split(':'), musicinfo[2], musicinfo[3]
        hour, minute = int(time2[0]) - int(time1[0]), int(time2[1]) - int(time1[1])
        t_gap = hour * 60 + minute
        
        sheets = change(sheets)
        
        sheet_cont = ''
        for i in range(t_gap):
            sheet_cont += sheets[i % len(sheets)]
        
        if m in sheet_cont and len(sheet_cont) > answer[1]:
            answer[0], answer[1] = title, len(sheet_cont)
            
    return answer[0]

 

※ 참고

악보의 음이 올림표가 아닐 때, 뒤에 '0'을 붙여 올림표와 기본 음을 구별

def solution(m, musicinfos):
    answer = ['(None)', 0]

    m_split = ''
    for i in range(len(m) - 1):
        if m[i].isalpha():
            if m[i + 1] == '#':
                m_split += m[i] + m[i + 1]
            else:
                m_split += m[i] + '0'
    if m[-1].isalpha():
        m_split += m[-1] + '0'

    for musicinfo in musicinfos:
        musicinfo = musicinfo.split(',')
        time1, time2, title, sheets = musicinfo[0].split(':'), musicinfo[1].split(':'), musicinfo[2], musicinfo[3]
        hour, minute = int(time2[0]) - int(time1[0]), int(time2[1]) - int(time1[1])
        t_gap = hour * 60 + minute

        sheet = []
        for i in range(len(sheets) - 1):
            if sheets[i].isalpha():
                if sheets[i + 1] == '#':
                    sheet.append(sheets[i] + sheets[i + 1])
                else:
                    sheet.append(sheets[i] + '0')
        if sheets[-1].isalpha():
            sheet.append(sheets[-1] + '0')

        sheet_cont = ''
        for i in range(t_gap):
            sheet_cont += sheet[i % len(sheet)]

        if m_split in sheet_cont and len(sheet_cont) > answer[1]:
            answer[0], answer[1] = title, len(sheet_cont)

    return answer[0]