문제
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
'Problem Solving > 프로그래머스' 카테고리의 다른 글
[프로그래머스|파이썬] [3차] n진수 게임 (2018 KAKAO BLIND RECRUITMENT/lv.2) (0) | 2023.05.22 |
---|---|
[프로그래머스|파이썬] k진수에서 소수 개수 구하기 (2022 KAKAO BLIND RECRUITMENT/lv.2) (0) | 2023.05.22 |
[프로그래머스|파이썬] 뒤에 있는 큰 수 찾기 (연습문제/lv.2) (0) | 2023.05.22 |
[프로그래머스|파이썬] 공원 산책 (연습문제/level 1) (0) | 2023.04.28 |
[프로그래머스|파이썬] 달리기 경주 (연습문제/level 1) (0) | 2023.04.27 |
[프로그래머스 | 파이썬 / 자바스크립트] 게임 맵 최단거리(깊이/너비 우선 탐색(DFS/BFS)/level 2) (0) | 2023.04.10 |