이숭간 공부기록

[프로그래머스] 파이썬 _ 베스트앨범 본문

알고리즘/프로그래머스

[프로그래머스] 파이썬 _ 베스트앨범

이숭간 2021. 6. 16. 02:54
728x90

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

 

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

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

programmers.co.kr

 

문제유형 : 해시, 구현

 

문제풀이 : 

 

1. 장르를 키로하고 튜플로 (노래번호,  노래재생횟수)를 값으로 하는 딕셔너리를 만든다.

{'classic': [(0, 500), (2, 150), (3, 500)], 'pop': [(1, 600), (4, 2500)]}

2. 장르의 총 재생횟수가 높은순으로 소팅한다. -> 재생횟수가 같으면 노래인덱스가 낮은순에서 높은순으로 소팅한다.

# 단, 딕셔너리를 소팅한 sorted함수의 결과는 원하는 순서로 정렬된 list임
    dic = sorted(dic.items(), key=lambda x: sum(x[1][:]), reverse=True)

3. 재생횟수가 높은순에서 2위까지만 답에 넣어주는데 이때 각 장르의 값들중에ㅅ

 

기억할것 : 

  • Sorted 에서 lambda로 정렬기준 정하기 다시정리
    • sorted(data.items(), key = lambda x:x[1][0], reverse = False)
      
      // sorted(1st pmt, 2nd pmt, 역순여부)
      
      // data.items() : dict_items([('pop', [600, 2500]), ('classic', [500, 150, 500])])
      
      
      출처 : https://eslife.tistory.com/915
    • 첫번째 인수에 있는 iteratable파라미터가 하나씩 2번째 수식에 대입되어 들어간다!!
    • 첫번째 인수가 data.items()이면 각 원소가 키, 값이 튜플로 이루어져 있는 형식임
    • 이때 key = lambda x:x[0] -> key로 소팅하겠다.
    • key = lambda x: x[1] -> 값으로 소팅하겠다.
    • 값이 리스트인경우? key = lambda x:sum(x[1][:]) -> 해당 리스트의 전체합을 기준으로 소팅하겠다 
  •  풀다가 만난 오류 : TypeError: 'set' object is not subscriptable
    • set은 순서가 없는 중복불가능한 컬렉션 자료형으로 다른 collection자료형처럼 item검사, 길이, 루프가 가능하다.
    • 하지만 순서가 없기때문에 위치를 저장하지 않는다 -> indexing이 불가능하다 (slice불가능!)

정답코드1:

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))
        print(dic1)
        if g not in dic2:
            dic2[g] = p
        else:
            dic2[g] += p
        print(dic2)
    for (k, v) in sorted(dic2.items(), key=lambda x:x[1], reverse=True):
        print(k,v)
        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 = []
    n = len(plays)
    dic = dict()
    dic2 = dict()
    genre = list(set(genres))
    for i in range(len(genre)):
        dic[genre[i]] = []

    for i in range(n):
        dic[genres[i]].append(plays[i])
        if plays[i] not in dic2:
            dic2[plays[i]] = [i]
        else:
            dic2[plays[i]].append(i)


    # 단, 딕셔너리를 소팅한 sorted함수의 결과는 원하는 순서로 정렬된 list임
    dic = sorted(dic.items(), key=lambda x: sum(x[1][:]), reverse=True)

    for i in dic:
        if len(i[1]) == 1:
            answer.append(dic2[i[1][0]])
            continue
        else:
            i[1].sort(reverse=True)  # 각 장르에서 재생순서가 높은순으로 소팅
            array = i[1][:2]
            # 값이 똑같으면
            if array[0] == array[1]:
                temp = dic2[array[0]][:2]
                answer.append(temp)
            else:
                for i in array:
                    answer.append(dic2[i])
    r = []
    # 장르별 리스트를 원소로 갖는배열 answer
    for i in answer:
        for j in i:
            r.append(j)
    return r

k = solution(["classic", "pop", "classic", "classic", "pop"], [500, 600, 150, 500, 2500]	)
print(k)

 

정답코드3(210707):

from collections import defaultdict
def solution(genres, plays):
    answer = []
    n = len(plays)
    dic = defaultdict(list)
    
    for i in range(n):
        dic[genres[i]].append((plays[i], i))
    
    print(dic)
    
    genre_dic = dict()
    for i in dic.items():
        sum = 0
        genre = i[0]
        stream_list = i[1]
        for j in stream_list:
            sum += j[0]    
        genre_dic[genre] = sum
    
    for genre in sorted(genre_dic.items(), key=lambda x: x[1], reverse=True):
        stream_list = dic[genre[0]]
        for k in sorted(stream_list, key=lambda x:x[0], reverse=True)[:2]:
            answer.append(k[1])
            
        
            
    print(answer)
        
    return answer