-
[프로그래머스] 베스트앨범 (Python)문제풀이/프로그래머스 2021. 6. 21. 16:04
https://programmers.co.kr/learn/courses/30/lessons/42579
def find_best_and_pop(d): best = list(d.keys())[0] for key in d: if d[key] > d[best]: best = key d.pop(best) return best def last(lst, idx): retbool = False ret = 0 if len(lst) >= idx + 2: if lst[idx][0] == lst[idx + 1][0]: ret = last(lst, idx + 1)[0] retbool = True else: return (idx, retbool) else: return (idx, retbool) return (ret, retbool) def solution(genres, plays): answer = [] genre = dict() total = dict() last_idx = 0 for idx in range(len(plays)): genre.setdefault(genres[idx], list()) genre[genres[idx]].append((plays[idx], idx)) total.setdefault(genres[idx], 0) total[genres[idx]] += plays[idx] for key in genre: genre[key].sort(reverse=True) for cnt in range(len(total)): best = find_best_and_pop(total) if len(genre[best]) == 1: answer.append(genre[best][0][1]) else: if last(genre[best], 0)[1] == True: last_idx = last(genre[best], 0)[0] answer.append(genre[best][last_idx][1]) answer.append(genre[best][last_idx - 1][1]) else: answer.append(genre[best][0][1]) last_idx = last(genre[best], 1)[0] answer.append(genre[best][last_idx][1]) return answer
저보다 훠어얼씬 짧게 푸신 분들도 많지만.. 직관적으로 이해하기 쉽게 풀어봤습니다.
먼저 solution함수가 우리가 만들어야 할 타겟 함수입니다.
파라미터인 genres와 plays는 각각 리스트로 주어지고, 각각의 인덱스(고유번호)에 따른 벨류는 장르이름과 재생횟수입니다.
i (고유 번호) i = 0 i = 1 i = 2 ... genres[i] (예시) 0번 노래의 장르 (pop) 1번 노래의 장르 (hiphop) 2번 노래의 장르 (pop) ... plays[i] (예시) 0번 노래 재생횟수 (20) 1번 노래 재생횟수 (40) 2번 노래 재생횟수 (20) ... [규칙]
answer에는 각 장르별로 재생횟수가 가장 많은 곡들의 고유 번호가 들어가야 합니다.
장르별 총 재생횟수가 가장 많은 장르부터 들어갑니다. (장르별 총 재생횟수는 모두 다릅니다.)
곡별 재생횟수가 많은 곡부터 최대 두 곡 들어갑니다. (해당 장르에 곡이 하나일 경우 하나만 들어갑니다.)
곡별 재생횟수가 같은 경우, 고유 번호가 작은 곡부터 들어갑니다.
[풀이]
genre와 total은 딕셔너리로 주어집니다.
genre의 키는 장르 이름으로 들어가며, 벨류는 (재생 횟수, 고유 번호)의 튜플의 리스트로 들어갑니다.
즉, genre = { 'pop' : [(20, 0), (20, 2)], 'hiphop' : [(40, 1)], ... }
여기에서 쓰인 setdefault(key, value) 메서드는 해당 key에 대한 value가 설정된적이 있으면 스킵, 없으면 해당 value로 초기화됩니다.
total의 키는 장르 이름, 벨류는 장르별 총 재생횟수로 들어갑니다.
즉, total = { 'pop' : 40, 'hiphop' : 40, ... }
이후 genre 딕셔너리의 각 벨류(리스트)를 역sort 시켜줍니다.
리스트에 튜플이 담겨 있을 경우, 튜플의 첫번째 원소를 기준으로 1차 정렬, 두번째 원소를 기준으로 2차 정렬이 이루어집니다.
즉, genre[romance] = [(80, 10), (20, 12), (20, 11), (5, 13)]
이후 total 딕셔너리에서 장르별 총 재생횟수가 가장 큰 key를 best에 저장하고, 그 item(키 + 벨류)을 pop해서 꺼내줍니다.
total 딕셔너리는 최종적으로 빈 딕셔너리 {} 가 됩니다.
각 best(키)마다 순서대로 해당하는 노래의 고유 번호를 answer에 넣어줍니다.
장르별 곡이 1곡일 때와 아닐 때(2곡 이상일 때)로 나눠주었습니다.
2곡 이상일 때에는 곡별 재생횟수가 가장 많은 곡(혹은 두번째로 많은 곡)이 두 개 이상일 경우와 아닐 경우를 나눠주었습니다.
최종적으로 곡별 재생횟수가 가장 많은 두 곡(겹칠시 고유번호가 가장 작은 두 곡)을 answer 리스트에 append하여 return해주었습니다..