from collections import defaultdict
def solution(genres, plays):
answer = []
genre_li = []
dict_1 = defaultdict(int)
dict_2 = defaultdict(list)
dict_3 = defaultdict(list)
for i in range(len(genres)) :
dict_1[genres[i]] += plays[i]
dict_2[(genres[i], plays[i])].append(i)
dict_1 = sorted(dict_1.items(), reverse=True, key=lambda item: item[1])
for i in dict_1 :
genre_li.append(i[0])
k = list(dict_2.keys())
v = list(dict_2.values())
for i in range(len(k)) :
dict_3[k[i][0]].append({k[i][1] : v[i]})
for gen in genre_li :
hap = dict()
for i in dict_3[gen] :
hap.update(i)
hap = sorted(hap.items(), reverse = True)
answer.append(hap[0][1][0])
if len(hap[0][1]) >= 2 :
answer.append(hap[0][1][1])
elif len(hap) >= 2 :
answer.append(hap[1][1][0])
return answer
우와....... 5시간만에 드디어 ............. 드디어 ㅠㅠㅠㅠㅠ
고작 이거 하나를 하루죙일 푼 것 같ㄴㅔ 아 ..^^
일단 내 기준 제일 어려웠던 건 3번 조건이었다
어차피 재생 횟수 많은 순서대로 나열하려면 내림차순하면 되는데
재생 횟수 같으면 고유 번호 낮은 순대로 수록하라해서 음...ㅇㅓ..?
암튼 풀이 설명하기 전에 선언한 변수들부터 설명해보자면
< 예시 입출력 >
dict_1 : 장르별 총 재생 횟수를 내림차순 정렬한 딕셔너리
ex) {'classic' : 1450, 'pop' : 3100}
dict_2 : 같은 장르 내 재생 횟수가 동일한 노래를 고려한 딕셔너리
Key : (장르명, 재생 횟수)
Value : 각 노래의 인덱스
ex) {('classic', 500) : [0], ('pop', 600) : [1], ('classic', 150) : [2] ... }
-> plays 의 0번 인덱스 노래는 'classic' 장르에 속하며, 500회의 재생 횟수를 가짐.
plays 의 1번 인덱스 노래는 'pop' 장르에 속하며, 600회의 재생 횟수를 가짐.
...
dict_3 : 노래의 재생 횟수와 인덱스를 장르별로 구분한 딕셔너리
ex) {'classic': [{500: [0]}, {150: [2]}, {800: [3]}], 'pop': [{600: [1]}, {2500: [4]}]}
-> 'classic' 에 속하는 노래들 중 500회의 재생 횟수를 가진 노래의 인덱스는 0번
'classic' 에 속하는 노래들 중 150회의 재생 횟수를 가진 노래의 인덱스는 2번
'classic' 에 속하는 노래들 중 800회의 재생 횟수를 가진 노래의 인덱스는 3번
...
이런 식으로 구분해줬고, defaultdict() 를 사용해서 기본 타입을 정해줬다
그럼 이제 풀이를 설명해보겠ㄷㅏ... 근데 이제 본인도 헷갈리기 시작하는 ..ㅋ
for i in range(len(genres)) :
dict_1[genres[i]] += plays[i]
dict_2[(genres[i], plays[i])].append(i)
dict_1 = sorted(dict_1.items(), reverse=True, key=lambda item: item[1])
dict_1 은 defaultdict 의 인자를 int 로 줬기 때문에 초깃값이 0
그래서 genres 순회하면서 각 장르를 Key 로 지정해서 Value 에 갱신해줌
dict_2 에서 defaultdict 인자를 list 로 준 이유는 인덱스를 계속 덧붙여주려고 ..!!!
위에 써놓은 것처럼 Key 는 튜플 형태로 (장르명, 재생 횟수) 로 지정하고,
Value 는 append() 이용해서 인덱스를 계속 덧붙여나감.
k = list(dict_2.keys())
v = list(dict_2.values())
print("K : ", k, "\n")
print("V : ", v, "\n")
for i in range(len(k)) :
dict_3[k[i][0]].append({k[i][1] : v[i]})
print(dict_3)
그리고 dict_1 을 Value 기준으로 내림차순해서
재생 횟수가 높은 장르가 맨 앞에 올 수 있도록 해줌.
genre_li 는 총 재생 횟수 높은 순서대로 저장해준 장르 리스트인데,
이걸 따로 구해준 이유는 총 재생 횟수 높은 순서대로 수록해야 되기 때문 ..!!!
k = list(dict_2.keys())
v = list(dict_2.values())
print("K : ", k, "\n")
print("V : ", v, "\n")
for i in range(len(k)) :
dict_3[k[i][0]].append({k[i][1] : v[i]})
print(dict_3)
여기서부터는 나도 엄청 헷갈려하고 혼란스러워함 .. ^-^
차라리 출력문 보면서 이해하는 게 나을 듯
k : dict_2 의 Key 를 모아둔 리스트 => 튜플 형태 (장르명, 재생 횟수)
v : dict_2 의 Value 를 모아둔 리스트 => 노래의 인덱스
그리고 k 와 v 를 이용해서 dict_3 을 생성해줬다
dict_3 도 마찬가지로 defaultdict 인자로 list 를 지정해줬음.
dict_2 와 달리 튜플 형태가 아닌 장르 하나로 Key 를 지정해주고,
Value 에는 {재생횟수 : 인덱스} 딕셔너리가 존재하는 형태
그냥 딕셔너리 안에 또 다른 여러 개의 딕셔너리가 있다고 보면 됨 ..!!
for gen in genre_li :
hap = dict()
for i in dict_3[gen] :
hap.update(i)
print("장르 ", gen, "정렬 전 HAP : ", hap)
hap = sorted(hap.items(), reverse = True)
print("장르 ", gen, "정렬 후 HAP : ", hap, "\n")
print("HAP[0][1][0] : ", hap[0][1][0])
answer.append(hap[0][1][0])
if len(hap[0][1]) >= 2 :
# 같은 장르 안에서 재생 횟수가 동일한 노래가 2개 이상일 때
print("조건 1) HAP[0][1][1] : ", hap[0][1][1])
answer.append(hap[0][1][1])
elif len(hap) >= 2 :
# 같은 장르 안에서 재생 횟수가 여러 개일 때
print("조건 2) HAP[1][1][0] : ", hap[1][1][0])
answer.append(hap[1][1][0])
hap 은 뭐냐면 ..
현재 dict_3 은 장르별로 Value 에 여러 개의 딕셔너리가 존재하니까
하나로 합쳐주려고 update() 메서드 이용해서 합친 딕셔너리임.
update 는 딕셔너리끼리 병합해주는 메서드로,
예를 들어서 딕셔너리 a, b 가 있다고 가정할 때
a.update(b) 하면 둘이 합쳐져서 하나의 딕셔너리를 만들어냄.
암튼 hap 을 Key 기준으로 내림차순해서
장르 안에서 제일 높은 재생 횟수와 해당 노래의 인덱스를 알아냄.
그리고 어차피 장르별로 최대 2개까지만 노래를 수록할 수 있기 때문에
제일 처음 노래의 인덱스는 무조건 저장하고,
나머지 하나 노래는 2가지 경우로 나눠서 if-elif 문으로 작성해준거임.
if 조건문은 같은 장르 안에서 재생 횟수가 동일한 노래가 2개 이상일 때,
elif 조건문은 같은 장르 안에서 재생 횟수가 여러 개일 때
지금 입출력 예시는 같은 재생 횟수를 가진 노래가 없기 때문에
이해가 잘 안 갈수도 있으니까 아래 참고하시길 ,, 그럼 전 이만
'알고리즘' 카테고리의 다른 글
[프로그래머스 Lv3] - 숫자 게임 (Python) (1) | 2022.08.06 |
---|---|
[프로그래머스 Lv2] 괄호 회전하기 (Python) (0) | 2022.08.04 |
[프로그래머스 Lv2] 예상 대진표 (Python) (0) | 2022.07.27 |
[프로그래머스 Lv1] 소수 만들기 (Python) (0) | 2022.07.06 |
[프로그래머스 Lv1] 예산 (Python) (0) | 2022.07.02 |