320x100
https://school.programmers.co.kr/learn/courses/30/lessons/17683#
- musicinfos 속 정보들을 토큰화하여 리스트에 저장
- '#'이 붙은 멜로디는 replace() 함수를 이용하여 소문자로 치환 ( 'C#' -> 'c'로 치환)
- 각 악보별로 재생 시간을 계산
- m과 fixed_melody의 길이에 따라 구분.
- len(m) < len(fixed_melody) 이면, 그냥 주어진 fixed_melody를 한 번 반복한 뒤 재생 시간만큼 슬라이싱.
그리고 m이 그 안에 있는지 check - 그 외의 경우에는, fixed_melody를 적어도 len(m)의 2배 이상만큼 반복시켜야 한다.
아래 테스트 케이스의 경우, len(m) = 12이고 FOO의 멜로디 길이는 3이다.
m은 비교적 짧은 melody가 여러번 반복되어 들려진 것일 수도 있기 때문에, 적어도 m의 2배 이상으로 반복시킨 뒤 m이 그 안에 있는지를 check해야 한다. 몫을 반환하는 '//' 연산자를 활용
- len(m) < len(fixed_melody) 이면, 그냥 주어진 fixed_melody를 한 번 반복한 뒤 재생 시간만큼 슬라이싱.
5. 일치하는 음악이 여러 개이면, 우선순위에 따라 음악을 선정한다. 재생 시간을 튜플로 함께 저장하여 가장 긴 음악의 이름을 저장한다. 재생 시간도 같으면 먼저 들어온 음악을 리턴하는데, answer_list 순서가 들어온 순서라서 재생 시간이 같을 경우 continue하도록 하였음.
일치하는 음악들이 담긴 answer_list에서 최적의 답을 찾는 부분을 구현할 때 처음에는 이렇게 구현했었다.
# 없을 경우 (None) 출력
if len(answer_list) == 0:
return '(None)'
elif len(answer_list) == 1:
return answer_list[0][0]
# 2개 이상일 경우 우선순위에 따라 선정
else:
max_time = 0
max_index = 0
for idx, answers in enumerate(answer_list):
if max_time < answers[1] : # 가장 긴 음악을 찾는다
max_time = answers[1]
max_index = idx
elif max_time == answers[1]: # 재생 시간이 같으면 먼저 들어온 것이 우선이므로 continue
continue
return answer_list[max_index][0]
그런데 위처럼 enumerate를 굳이 쓰지 않고, answers[0]값만 계속 갱신하여 저장하면 되는 거라 아래처럼 좀 더 간결하게 수정했다.
최종 코드
def solution(m, musicinfos):
answer = ''
answer_list = []
music_list = [] # music_list[][0 : start / 1 : end / 2 : name / 3 : melody]
for music in musicinfos:
music_list.append(music.split(","))
# 각 INFO를 돌면서, 음표 C#D#F#G#A# 소문자로 처리하기. replace('C#','c')
# end - start를 계산. len(m)보다 짧으면 그 길이만큼 재생.
# len(m)보다 길면 악보를 두 배로 늘린다. 그리고 end - start까지 찾으면서 m이 나오는지 check.
m = m.replace('C#','c').replace('D#','d').replace('F#','f').replace('G#','g').replace('A#','a').replace('E#','e')
for music in music_list:
fixed_melody = music[3].replace('C#','c').replace('D#','d').replace('F#','f').replace('G#','g').replace('A#','a').replace('E#','e')
start_time = 60 * int(music[0].split(':')[0]) + int(music[0].split(':')[1])
end_time = 60 * int(music[1].split(':')[0]) + int(music[1].split(':')[1])
time = end_time - start_time
if len(m) < len(fixed_melody): # m이 melody보다 짧을 때
fixed_melody *= 2
melody = fixed_melody[:time]
else: # m이 melody보다 길 때
fixed_melody *= len(m)//len(fixed_melody) * 2 + 1
melody = fixed_melody[:time]
print(melody)
# answer_list 중 우선순위는 재생 시간, 그리고 입력된 순서임.
# 입력된 순서는 answer_list에 append되는 순서랑 같음. end-start만 추가로 저장하자. tuple로!
if m in melody:
answer_list.append((music[2],time))
# 없을 경우 (None) 출력
if len(answer_list) == 0:
return '(None)'
elif len(answer_list) == 1:
return answer_list[0][0]
# 2개 이상일 경우 우선순위에 따라 선정
else:
max_time = 0
for answers in answer_list:
if max_time < answers[1] : # 가장 긴 음악을 찾는다
max_time = answers[1]
song_name = answers[0]
elif max_time == answers[1]: # 재생 시간이 같으면 먼저 들어온 것이 우선이므로 continue
continue
return song_name
'코딩테스트' 카테고리의 다른 글
[파이썬] 파일명 정렬 - 2018 KAKAO BLIND RECRUITMENT [CODING TEST #43] (0) | 2022.08.06 |
---|---|
[파이썬] 괄호 회전하기 - 월간 코드 챌린지 시즌2 [CODING TEST #42] (0) | 2022.08.06 |
[파이썬] 가운데 글자 가져오기 [CODING TEST #40] (0) | 2022.08.04 |
[파이썬] 압축 - 2018 KAKAO BLIND RECRUITMENT [CODING TEST #39] (0) | 2022.08.03 |
[파이썬] 예상 대진표 - 2017 팁스타운 [CODING TEST #38] (0) | 2022.08.03 |
댓글