Today
Yesterday
Total
  • [프로그래머스] 베스트앨범 (Python)
    문제풀이/프로그래머스 2021. 6. 21. 16:04

    목차

      https://programmers.co.kr/learn/courses/30/lessons/42579

       

      코딩테스트 연습 - 베스트앨범

      스트리밍 사이트에서 장르 별로 가장 많이 재생된 노래를 두 개씩 모아 베스트 앨범을 출시하려 합니다. 노래는 고유 번호로 구분하며, 노래를 수록하는 기준은 다음과 같습니다. 속한 노래가

      programmers.co.kr

       

      kotlin
      닫기
      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해주었습니다..

    sangilyoon.dev@gmail.com