새소식

⌨️ Algorithms/프로그래머스

[Python] 프로그래머스 Lv3_베스트앨범

2023. 1. 9. 23:14

  • -

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

 

프로그래머스

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

programmers.co.kr

 

  • 장르 별로 가장 많이 재생된 노래를 두 개씩 모아 베스트 앨범을 출시하려 함
  • 노래는 고유 번호로 구분하며, 노래를 수록하는 기준은 다음과 같음
    • 속한 노래가 많이 재생된 장르를 먼저 수록
    • 장르 내에서 많이 재생된 노래를 먼저 수록
    • 장르 내에서 재생 횟수가 같은 노래 중에서는 고유 번호가 낮은 노래를 먼저 수록
  • genres: 노래의 장르를 나타내는 문자열 배열
  • plays: 노래별 재생 횟수를 나타내는 정수 배열
  • 베스트 앨범에 들어갈 노래의 고유 번호를 순서대로 return

제한사항

  • genres[i]는 고유번호가 i인 노래의 장르
  • plays[i]는 고유번호가 i인 노래가 재생된 횟수
  • genres와 plays의 길이는 같으며, 이는 1 이상 10,000 이하
  • 장르 종류는 100개 미만
  • 장르에 속한 곡이 하나라면, 하나의 곡만 선택
  • 모든 장르는 재생된 횟수가 다름

 

"""
입출력 예시)

genres = ["classic", "pop", "classic", "classic", "pop"], plays = [500, 600, 150, 800, 2500] -> [4, 1, 3, 0]
"""
# genres = ["classic", "pop", "classic", "classic", "pop"], plays = [500, 600, 150, 800, 2500] -> [4, 1, 3, 0]

# classic 장르는 1,450회 재생되었으며, classic 노래는 아래와 같음
#     - 고유 번호 3: 800회 재생
#     - 고유 번호 0: 500회 재생
#     - 고유 번호 2: 150회 재생

# pop 장르는 3,100회 재생되었으며, pop 노래는 아래와 같음
#     - 고유 번호 4: 2,500회 재생
#     - 고유 번호 1: 600회 재생

# -> pop 장르의 [4, 1]번 노래를 먼저, classic 장르의 [3, 0]번 노래를 그다음에 수록
# (장르 별로 가장 많이 재생된 노래를 최대 두 개까지 모아 베스트 앨범을 출시하므로 pop 장르의 2번 노래는 수록되지 x)

# => [4, 1, 3, 0]

 

 

## 의사코드 ##

# 노래의 고유 번호 -> index

# 해시 -> dict()
# 장르별 노래의 고유 번호와 재생 횟수를 담을 genre_dict = defaultdict(list)
# 장르별 총 재생 횟수를 담을 total_play = defaultdict(lambda:0)

# for i, (g, p) in enumerate(zip(genres, plays)):
# 먼저, 장르를 dict의 key로, value는 [(노래의 고유 번호(i), plays[i])]로 설정
    # genre_dict[g].append((i, p))
# 장르별로 총 재생 횟수를 구함
    # total_play[g] += p

# 장르별 총 재생 횟수가 높은 순으로 장르를 정렬
# 장르 내에서 재생 횟수가 높은 노래를 2개까지 선택해서 answer에 append
#   (장르에 속한 곡이 1개인 경우 -> 곡 1개만 선택)
#   (재생 횟수가 같은 노래들이 있으면 고유 번호(index)가 낮은 노래부터 선택)

 

 

 

통과한 코드

 

from collections import defaultdict
def solution(genres, plays):
    answer = []
    genre_dict = defaultdict(list) # 장르별 노래의 고유 번호와 재생 횟수를 담은 딕셔너리
    total_play = defaultdict(lambda:0) # 장르별 총 재생 횟수를 담은 딕셔너리
    
    for i, (g, p) in enumerate(zip(genres, plays)):
        genre_dict[g].append((i, p)) # {genre1: [(노래의 고유 번호(i), plays[i]), ...], genre2: [(노래의 고유 번호(i), plays[i]), ...], ...}
        total_play[g] += p # {genre1: 총 재생 횟수, genre2: 총 재생 횟수, ...}

    # 장르별 총 재생 횟수가 높은 순으로 장르를 정렬    
    for k, v in sorted(total_play.items(), key=lambda x:x[1], reverse=True):
        # 정렬된 장르의 순서대로 장르 내에서 재생 횟수가 높은 노래를 2개까지 선택
        for i, p in sorted(genre_dict[k], key=lambda x:x[1], reverse=True)[:2]:
            answer.append(i)

    return answer

-> defaultdict를 활용해서 장르별 정보를 담을 딕셔너리와 장르별 총 재생 횟수를 담을 딕셔너리를 따로 생성

 

 

  • 장르 내에서 재생 횟수가 같은 노래 중에서 고유 번호가 낮은 노래가 먼저 수록
# 장르 내에서 재생 횟수가 같은 노래 중에서 고유 번호가 낮은 노래가 먼저 수록되는지 테스트
from collections import defaultdict 
genres = ["classic", "pop", "classic", "classic", "pop", "classic"]
plays = [500, 600, 150, 800, 2500, 500]

genre_dict = defaultdict(list)
total_play = defaultdict(lambda:0)

for i, (g, p) in enumerate(zip(genres, plays)):
    genre_dict[g].append((i, p))
    total_play[g] += p

print(sorted(genre_dict['classic'], key=lambda x: x[1], reverse=True))

"""
[(3, 800), (0, 500), (5, 500), (2, 150)]
"""

-> 장르 내에서 재생 횟수가 같은 노래 중에서 고유 번호가 낮은 노래부터 정렬됨

 

 

 

 

참고)

 

https://velog.io/@sem/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-LEVEL3-%EB%B2%A0%EC%8A%A4%ED%8A%B8%EC%95%A8%EB%B2%94-Python

 

[프로그래머스] LEVEL3 베스트앨범 (Python)

프로그래머스 알고리즘 풀이

velog.io

 

 

Contents

포스팅 주소를 복사했습니다

이 글이 도움이 되었다면 공감 부탁드립니다!