본문 바로가기
Problem Solving/프로그래머스

[프로그래머스|파이썬] 베스트앨범 (해시/level 3)

by 청량리 물냉면 2023. 4. 29.
반응형
문제

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

 

프로그래머스

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

programmers.co.kr

 

 

🐍파이썬
def solution(genres, plays):
    answer = []
    dic = {g:[] for g in set(genres)}
    for index, (genre, play) in enumerate(zip(genres, plays)):
        dic[genre].append([index, play])
    genre_sort = sorted(dic.keys(), key=lambda x:sum(map(lambda y:y[1], dic[x])), reverse=True)
    for g in genre_sort:
        temp = [i[0] for i in sorted(dic[g], key=lambda x:(x[1], -x[0]), reverse=True)]
        answer += temp[:min(2, len(temp))]
    return answer

 

👉 코드 설명

line 3️⃣ 

dic = {g:[] for g in set(genres)}

장르별로 재생횟수와 인덱스(고유번호)를 담을 수 있는 딕셔너리를 생성한다. 장르의 중복제거를 위해 set을 사용했다.

 

line 4️⃣ ~ 5️⃣ 

for idx, (genre, play) in enumerate(zip(genres, plays)):
    dic[genre].append([idx, play])   #장르별 인덱스(고유번호)와 재생횟수
dic = {'classic': [[0, 500], [2, 150], [3, 800]], 'pop': [[1, 600], [4, 2500]]}

 

line 6️⃣ 

gen_sort = sorted(dic.keys(), key=lambda x:sum(map(lambda y:y[1], dic[x])), reverse=True)
# gen_sort = ['pop', 'classic']

재생횟수 합산으로 dic.key 정렬. 합산 결과대로 key(ex. classic, pop...)가 정렬된다.

정렬의 기본값은 오름차순이므로 합산 결과가 큰 순서부터 정렬하기 위해 내림차순 정렬한다. (reverse=True)

dic = {'classic': [[0, 500], [2, 150], [3, 800]], 'pop': [[1, 600], [4, 2500]]}

lambda x
= 'pop', 'classic'
lambda y
- pop 👉 [1, 600], [4, 2500]
- classic 👉 [0, 500], [2, 150], [3, 800]
sum(map(lambda y:y[1], dic[x]))​

dic[x], 즉 dic['pop'], dic['classic']의 1번 인덱스(play)의 합을 리턴

 

line 7️⃣ ~ 🔟

    for g in genre_sort:
        temp = [i[0] for i in sorted(dic[g], key=lambda x:(x[1], -x[0]), reverse=True)]
        # temp = [4, 1] [3, 0, 2]
        answer += temp[:min(2, len(temp))]
    return answer

👉 가장 많이 재생된 장르부터 내부 요소를 재생횟수 기준으로 내림차순, 동일차순일 경우 인덱스별 오름차순을 진행한다. 이때도 위와 마찬가지로 기본 정렬이 오름차순이므로, 많이 재생된 순서부터 정렬하기 위해 reverse=True를 사용한다.

👉 이렇게 정렬된 리스트의 인덱스 번호만 추출(리스트 컴프리헨션의 i[0])한 뒤 각 장르의 곡이 2곡 이상이면 2개까지, 2곡 미만이면 그 길이까지 answer에 담는다.

👉 최종적으로 인덱스가 담긴 answer을 리턴하면 풀이 종료.

 

더보기

혼자 아이디어를 떠올릴 수 없어서 인터넷에서 풀이를 참고해 풀었다.

해시와 lambda를 이용한 정렬에 익숙해질 수 있는 기회였다.

 

 

다른 풀이 방법

def solution(genres, plays):
    answer = []

    dic1 = {}	#장르별 인덱스, 플레이 횟수
    dic2 = {}	#장르별 플레이 횟수

    for i, (g, p) in enumerate(zip(genres, plays)):
        if g not in dic1:
            dic1[g] = [(i, p)]
        else:
            dic1[g].append((i, p))

        if g not in dic2:
            dic2[g] = p
        else:
            dic2[g] += p           
    #print(dic2.items())
    #dict_items([('classic', 1450), ('pop', 3100)])
    
    #플레이 횟수 기준으로 dic2 정렬(장르별 많이 들은 장르 내림차순 정렬)
    for (k, v) in sorted(dic2.items(), key=lambda x:x[1], reverse=True):
    	#각 장르별 플레이 횟수 기준으로 dic1[장르] 정렬
        for (i, p) in sorted(dic1[k], key=lambda x:x[1], reverse=True)[:2]:
            answer.append(i)

    return answer

def solution(genres, plays):
    answer = []
    dic = {}
    album_list = []
    for i in range(len(genres)):
        dic[genres[i]] = dic.get(genres[i], 0) + plays[i]
        album_list.append(album(genres[i], plays[i], i))

    dic = sorted(dic.items(), key=lambda dic:dic[1], reverse=True)
    album_list = sorted(album_list, reverse=True)

    while len(dic) > 0:
        play_genre = dic.pop(0)
        print(play_genre)
        cnt = 0;
        for ab in album_list:
            if play_genre[0] == ab.genre:
                answer.append(ab.track)
                cnt += 1
            if cnt == 2:
                break
    return answer

class album:
    def __init__(self, genre, play, track):
        self.genre = genre
        self.play = play
        self.track = track

    def __lt__(self, other):
        return self.play < other.play
    def __le__(self, other):
        return self.play <= other.play
    def __gt__(self, other):
        return self.play > other.play
    def __ge__(self, other):
        return self.play >= other.play
    def __eq__(self, other):
        return self.play == other.play
    def __ne__(self, other):
        return self.play != other.play
반응형