-->

[프로그래머스] 해시 - 베스트앨범 (파이썬)

반응형

프로그래머스 해시 - 베스트앨범, 문제 확인

프로그래머스 해시 마지막 문제이다. 문제 설명은 아래와 같다.

 


장르별로 가장 많이 재생된 노래 두개를 뽑으려 함

노래는 고유번호로 구분되며 수록 기준은 아래와 같음

 

1) 속한 노래가 많이 재생된 장르 먼저 수록

2) 장르 내에서 많이 재생된 노래 먼저 수록

3) 장르 내에서 재생횟수가 같은 노래 중에서는 고유번호가 낮은 노래를 먼저 수록

 

genres : 노래의 장르를 나타내는 문자열 배열 (genres[i]가 노래 장르, i가 고유번호)

plays: 노래별 재생 횟수를 나타내는 정수 배열 (plays[i]는 고유번호가 i인 노래가 재생된 횟수)

 

장르에 속한 곡이 하나라면, 하나의 곡만 선택함

뽑을 노래 두개의 고유번호를 순서대로 리턴하도록 solution 함수를 작성

 

 

설명만 봐서는 살짝 헷갈리므로 예시를 봐보자. 클래식 장르는 500+150+800 = 1450회 재생되었고 팝 장르는 600+2500=3100회 재생되었기 때문에 팝 장르의 노래를 먼저 수록해야 한다. 여기서 팝 장르에 속한 노래의 고유번호는 1,4이고 1,4 중에서는 4가 더 재생이 많이 되었으므로 [4,1] 순서가 된다. 그다음 클래식 장르의 노래 2곡을 수록해야 하므로 재생된 순서대로 [3,0]이 된다. 따라서 리턴값은 [4,1,3,0] 이다.

 

[classic, pop, classic, 

classic, pop]

[500, 600, 150,

800, 2500]

[4, 1, 3, 0]

 

 

프로그래머스 해시 - 베스트앨범, 문제 풀이 (파이썬)

이번엔 여태까지의 해시 문제에서 파이썬 내장함수인 zip에 대해 새로 알게됐으므로 zip을 사용하도록 하겠다!ㅎㅎ 참고로 아래와 같이 zip에도 enuerate를 씌울 수 있다.

 

def solution(genres, plays):
    answer = []
    for i, (g,p) in enumerate(zip(genres, plays)):
        print(i,g,p)
    return answer

 

 

문제를 푸는데 중요한 예외처리는 1) 속한 곡이 한개인 경우 2)재생수가 많은 곡 2개의 재생수가 동일할 경우이다. 해당 예외처리에 대한 테스트케이스로 아래 두케이스를 추가해서 테스트를 진행했다.

 


1)

["classic", "pop", "classic", "classic", "pop"]

[500, 600, 800, 800, 2500]

[4, 1, 2, 3]

 

2)

["classic", "pop", "classic", "classic", "pop", "jpop"]
[500, 600, 150, 800, 2500, 3000]
[4, 1, 5]

 

 

 

예외처리도 전부 해주었는데 계속 아래처럼 채점결과가 33.3%가 나왔다. 도대체 뭐지 하면서 좀 삽질을 했는데 알고보니 나도모르게 top2의 곡을 뽑아야 한다는 것에 사로잡혀서 장르자체도 재생수가 높은순으로 top2를 뽑아놓는 방식으로 했다ㅋㅋ;

 

 

 

해당 부분만 고쳐주니 채점을 통과할 수 있었다.

 

 

 

{"장르"=(재생수,고유번호)} 형태의 딕셔너리를 처음에 구한 후 여기서 다시 {"장르"=총재생수}인 딕셔너리를 구해 총재생수가 놓은 순서대로 장르를 나열한 top_gen 리스트를 얻었다. 그리고 총재생수가 높은 장르 순서대로 반복문을 돌면서 재생수 순으로 각 장르의 곡을 내림차순으로 정렬한 song 리스트를 얻는다.

 

그리고 이 song 리스트에서 속한 노래가 2개가 안되는 경우와 재생수가 일치하는 곡의 경우 고유번호가 작은것을 먼저 추가하는 예외만 처리해주는 방식으로 코드를 작성했다.

 

from collections import defaultdict
def solution(genres, plays):
    answer = []; top_gen = []
    total_dict = defaultdict(list); count_dict = defaultdict(list)

    #key=장르, value=(재생수,고유번호) ->total_dict
    for i, (g,p) in enumerate(zip(genres, plays)): total_dict[g].append((p,i)) 
    
    #key=장르, value=총재생수 ->count_dict
    for k,v in total_dict.items(): 
        sum = 0
        for v in total_dict[k]: sum+=int(v[0])
        count_dict[k]=sum
   
    #총재생수대로 내림차순 정렬 후 재생수가 많은 순대로 장르를 정렬함 ->top_gen
    sort_dict=sorted(count_dict.items(), key=lambda x: x[1], reverse=True)
    for i,v in enumerate(sort_dict):
        if i<2: top_gen.append(v[0])
   
    #총재생수가 높은 장르순으로 반복문을 돌게됨
    for v in top_gen:
        song=total_dict[v]
        #재생수대로 내림차순 정렬
        song.sort()
	#속한 노래가 2개가 안된다면 제일 재생수가 큰 노래의 고유번호를 answer에 추가하고 끝
        if len(song) < 2: 
            answer.append(song[-1][1])
            continue
        #재생수가 제일큰 노래 2개의 재생수가 같다면 고유번호가 작은것을 먼저 answer에 추가    
        if(song[-1][0] == song[-2][0] and song[-1][1] > song[-2][1]): 
            answer.append(song[-2][1])
            answer.append(song[-1][1])
        else: 
            answer.append(song[-1][1])
            answer.append(song[-2][1])

    return answer

 

 

해시 문제가 끝났으니 다음 programmers 포스팅에서는 스택/큐를 풀어보도록 한다.

 

 

댓글

Designed by JB FACTORY