문제 설명
라디오를 자주 듣는 네오는 라디오에서 방금 나왔던 음악이 무슨 음악인지 궁금해질 때가 많다. 그럴 때 네오는 다음 포털의 '방금 그 곡' 서비스를 이용하곤 한다. 방금 그 곡에서는 TV, 라디오 등에서 나온 음악에 관해 제목 등의 정보를 제공하는 서비스이다.
네오는 자신이 기억한 멜로디를 가지고 방금그곡을 이용해 음악을 찾는다. 그런데 라디오 방송에서는 한 음악을 반복해서 재생할 때도 있어서 네오가 기억하고 있는 멜로디는 음악 끝부분과 처음 부분이 이어서 재생된 멜로디일 수도 있다. 반대로, 한 음악을 중간에 끊을 경우 원본 음악에는 네오가 기억한 멜로디가 들어있다 해도 그 곡이 네오가 들은 곡이 아닐 수도 있다. 그렇기 때문에 네오는 기억한 멜로디를 재생 시간과 제공된 악보를 직접 보면서 비교하려고 한다. 다음과 같은 가정을 할 때 네오가 찾으려는 음악의 제목을 구하여라.
- 방금 그 곡 서비스에서는 음악 제목, 재생이 시작되고 끝난 시각, 악보를 제공한다.
- 네오가 기억한 멜로디와 악보에 사용되는 음은 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개 이하로 구성되어 있다.
출력 형식
조건과 일치하는 음악 제목을 출력한다.
입출력 예시
m | musicinfos | answer |
"ABCDEFG" | ["12:00,12:14,HELLO,CDEFGAB", "13:00,13:05,WORLD,ABCDEF"] | "HELLO" |
"CC#BCC#BCC#BCC#B" | ["03:00,03:30,FOO,CC#B", "04:00,04:08,BAR,CC#BCC#BCC#B"] | "FOO" |
"ABC" | ["12:00,12:14,HELLO,C#DEFGAB", "13:00,13:05,WORLD,ABCDEF"] | "WORLD" |
설명
첫 번째 예시에서 HELLO는 길이가 7분이지만 12:00부터 12:14까지 재생되었으므로 실제로 CDEFGABCDEFGAB로 재생되었고, 이 중에 기억한 멜로디인 ABCDEFG가 들어있다.
세 번째 예시에서 HELLO는 C#DEFGABC#DEFGAB로, WORLD는 ABCDE로 재생되었다. HELLO 안에 있는 ABC#은 기억한 멜로디인 ABC와 일치하지 않고, WORLD 안에 있는 ABC가 기억한 멜로디와 일치한다.
나의 풀이
[Python(파이썬)]
def sharp_check(melody): # '#'정리 하기
m_temp = []
if '#' in melody:
for k in range(len(melody)):
if melody[k] == '#':
m_temp[-1] += '#'
else:
m_temp.append(melody[k])
return m_temp
else:
return list(melody)
def solution(m, musicinfos):
info, play_time, include_m_idx, include_m_time = [], [], [], []
m = sharp_check(m) # 기억하는 멜로디 # 정리
for i in range(len(musicinfos)):
time = []
musicinfos[i] = (musicinfos[i].split(',')) # 음악 정보 문자열을 ',' 기준으로 잘라 리스트로 만들기
# 음악 재생시간 구하기
time.append(musicinfos[i][0].split(':'))
time.append(musicinfos[i][1].split(':'))
play_time.append((int(time[1][0])*60+int(time[1][1])) - (int(time[0][0])*60+int(time[0][1])))
# info 음악의 # 정리
m_temp = sharp_check(musicinfos[i][3])
a, b = divmod(play_time[i], len(m_temp))
info.append(m_temp * a + m_temp[:b]) # 재생시간만큼의 멜로디
# 기억하는 멜로디의 음악 제목 찾기
for j in range(len(info)):
for l in range(len(info[j])):
if info[j][l] == m[0]:
idx = 0
for check in range(len(m)):
if l+idx < len(info[j]) and m[check] == info[j][l+idx]:
if check == len(m)-1:
include_m_idx.append(j)
idx += 1
else:
break
if len(include_m_idx) == 1: # 멜로디를 포함하는 음악이 1개
return musicinfos[include_m_idx[0]][2]
elif not include_m_idx: # 멜로디를 포함하는 음악이 X
return '(None)'
else: # 멜로디를 포함하는 음악이 여러개
for i in include_m_idx:
include_m_time.append(play_time[i])
return musicinfos[include_m_idx[include_m_time.index(max(include_m_time))]][2]
학습한 내용
풀이 과정
1. #이 포함된 음악 정리
2. musicinfos의 노래 정리하기
2-1. 음악 재생 시간 구하기
2-2. 악보 정보를 재생 시간 길이만큼 만들기(# 생각하기)
3. 기억한 멜로디의 음악 찾기
4. 조건이 일치하는 음악이 여러 개일 때
1. #이 포함된 음악 정리
예제 3번에서
"ABC" | ["12:00,12:14,HELLO,C#DEFGAB", "13:00,13:05,WORLD,ABCDEF"] |
첫번째 음악 C#DEFGABC#DEFGAB, 두번째 음악 ABCDE 일때 'ABC'를 찾으면 #을 분리해주지 않았을 때
C#DEFGABC#DEFGAB에서 A, B, C#인데 A, B, C,#라고 생각하면 ABC가 포함되어 있다고 계산되어 답이 HELLO로 나올 수 있다.
따라서 C#을 하나의 음처럼 생각할 수 있도록 구현해야 한다.
def sharp_check(melody): # '#'정리 하기
m_temp = []
if '#' in melody:
for k in range(len(melody)):
if melody[k] == '#':
m_temp[-1] += '#'
else:
m_temp.append(melody[k])
return m_temp
else:
return list(melody)
1) 멜로디에 '#'이 포함되어 있는지 검사 -> 있다면 2번으로 없다면 바로 list로 변환하여 반환
2) for문을 이용해 melody[k] == '#' 인지 check
2-1) '#'이라면 m_temp[-1]에 '#' 더해주기 ex) B, C, #, D 을 B, C#, D로
2-2) '#'이 아니라면 m_temp에 음을 append
#을 제거하는 다른 사람 방식
def convert_sharp(music):
music = music.replace('C#', 'c')
music = music.replace('D#', 'd')
music = music.replace('F#', 'f')
music = music.replace('G#', 'g')
music = music.replace('A#', 'a')
return music
- 네오가 기억한 멜로디와 악보에 사용되는 음은 C, C#, D, D#, E, F, F#, G, G#, A, A#, B 12개이다.
위처럼 12개라고 정해져 있기 때문에 #이 포함된 음들을 소문자로 대체해서 사용하면 for문을 사용하지 않고 더 간단히 구현할 수 있다는 걸 알았다.
2. musicinfos의 노래 정리하기
먼저 음악 정보 문자열을 ',' 기준으로 잘라 리스트로 만든다.
musicinfos[i] = (musicinfos[i].split(','))
ex) "12:00,12:14, HELLO, C#DEFGAB" -> ['12:00', '12:14', 'HELLO', 'C#DEFGAB']
2-1. 음악 재생 시간 구하기
# 음악 재생시간 구하기
time.append(musicinfos[i][0].split(':'))
time.append(musicinfos[i][1].split(':'))
play_time.append((int(time[1][0])*60+int(time[1][1])) - (int(time[0][0])*60+int(time[0][1])))
ex) 12:00,12:14 -> [[12, 00], [12, 14]] -> 12 * 60 + 14 - 12 * 60 - 0 -> 14
2-2. 악보 정보를 재생 시간 길이만큼 만들기(# 생각하기)
문제에서 주어진 내용
각 음은 1분에 1개씩 재생된다. 음악은 반드시 처음부터 재생되며 음악 길이보다 재생된 시간이 길 때는 음악이 끊김 없이 처음부터 반복해서 재생된다. 음악 길이보다 재생된 시간이 짧을 때는 처음부터 재생 시간만큼만 재생된다.
m_temp = sharp_check(musicinfos[i][3]) # 1. #이 포함된 음악 정리 함수 호출
a, b = divmod(play_time[i], len(m_temp))
info.append(m_temp * a + m_temp[:b]) # 재생시간만큼의 멜로디
ex) ["12:00,12:14, HELLO, C#DEFGAB", "13:00,13:05, WORLD, ABCDEF"]
- "12:00,12:14, HELLO, C#DEFGAB" -> 음악 길이보다 재생된 시간이 길 때는 음악이 끊김 없이 처음부터 반복해서 재생
1) C#DEFGAB ('#' 정리 함수 sharp_check 호출) -> ['C#', 'D', 'E', 'F', 'G', 'A', 'B']
2) 14초와 len(m_temp)를 이용해 몫 나머지 구하기 -> divmod(14, 7) -> (2, 0)
3) m_temp * 2 + m_temp[ : 0] -> ['C#', 'D', 'E', 'F', 'G', 'A', 'B', 'C#', 'D', 'E', 'F', 'G', 'A', 'B']
- "13:00,13:05, WORLD, ABCDEF" -> 음악 길이보다 재생된 시간이 짧을 때는 처음부터 재생 시간만큼만 재생
1) ABCDEF(sharp_check 함수 호출) -> ['A', 'B', 'C' , 'D', 'E', 'F']
2) 5초와 len(m_temp)를 이용해 몫 나머지 구하기 -> divmod(5, 6) -> (0, 5)
3) m_temp * 0+ m_temp[ : 5] -> ['A', 'B', 'C' , 'D', 'E']
3. 기억한 멜로디의 음악 찾기
# 기억하는 멜로디의 음악 제목 찾기
for j in range(len(info)):
for l in range(len(info[j])):
if info[j][l] == m[0]:
idx = 0
for check in range(len(m)):
if l+idx < len(info[j]) and m[check] == info[j][l+idx]:
if check == len(m)-1:
include_m_idx.append(j)
idx += 1
else:
break
4. 조건이 일치하는 음악이 여러 개일 때
if len(include_m_idx) == 1: # 멜로디를 포함하는 음악이 1개
return musicinfos[include_m_idx[0]][2] # 해당 음악 return
elif not include_m_idx: # 멜로디를 포함하는 음악이 X
return '(None)'
else: # 멜로디를 포함하는 음악이 여러개
for i in include_m_idx:
include_m_time.append(play_time[i])
return musicinfos[include_m_idx[include_m_time.index(max(include_m_time))]][2]
# 음악 재생시간이 가장 긴 음악 return
문제 출처
코딩테스트 연습 - [3차] 방금그곡
방금그곡 라디오를 자주 듣는 네오는 라디오에서 방금 나왔던 음악이 무슨 음악인지 궁금해질 때가 많다. 그럴 때 네오는 다음 포털의 '방금그곡' 서비스를 이용하곤 한다. 방금그곡에서는 TV,
programmers.co.kr
카카오 신입 공채 3차 코딩 테스트 문제 해설
블라인드 채용으로 관심을 모은 카카오 신입 공채의 세 번째 테스트가 지난 10월 29일(일), 오후 2시부터 6시까지 네 시간에 걸쳐 오프라인으로 치러졌습니다. 두 차례의 온라인 테스트를 통과한
tech.kakao.com
'[Python] Programmers > Level2' 카테고리의 다른 글
[프로그래머스/Level2] 괄호 회전하기(월간 코드 챌린지 시즌2) (0) | 2021.09.30 |
---|---|
[프로그래머스/Level2] 최댓값과 최솟값 (0) | 2021.09.19 |
[프로그래머스/Level2] 이진 변환 반복하기 (월간 코드 챌린지 시즌1) (0) | 2021.09.16 |
[프로그래머스/Level2] 올바른 괄호 (0) | 2021.09.16 |
[프로그래머스/Level2] 입실 퇴실 (위클리 챌린지 7주차) (0) | 2021.09.14 |
댓글