나의 풀이
어떻게 풀어야 할까 고민을 많이 했다.
엄청어렵기보단 문자열을 어떻게 잘 다루는지 알아보는 문제 같았다.
해야할 것
1. 어떤 장르가 가장 재생이 많이 되었는지 알아야한다.
2. 해당 장르에서 많이 들은 순으로 노래를 정렬해야한다.
3. 장르당 최대 2곡까지만 저장하고 나머지는 버린다.
4. 해당 장르 노래의 고유 번호를 retrun 해야한다.
1. 속한 노래가 많이 재생된 장르를 내림차순으로 배열안에 정렬하기
// 1. 속한 노래가 많이 재생된 장르를 내림차순으로 배열안에 정렬
const rank = genres.reduce((acc,cur,index) => {
acc[cur] = (acc[cur] || 0) + plays[index]
return acc
},{})
const rankInArr = Object.entries(rank).sort(([_,a],[__,b]) => b- a).map(([genre, play]) => genre)
결론부터 말하면 이 예제로 console.log(rankInArr)를 하면 ['pop', 'classic'] 가 출력된다. pop 장르의 재생수가 제일 높다.
genres 배열을 reduce를 통해 객체로 만들어준다.
이 객체는 각 장르별로 총 몇번 재생되었는지가 저장된다.
이 객체를 가지고 배열을 만든 뒤 sort를 통해 value를 기준으로 정렬한뒤 map으로 key값만 남은 배열로 만든다.
2. 각 장르 별로 재생횟수 상위 2개 노래만 저장
// 2. 각 장르 별로 재생횟수 상위 2개 노래만 저장
const topTwoMusic = genres.reduce((acc,cur,index) => {
acc[cur] = acc[cur] ? ([[plays[index],index], ...acc[cur]].sort(([a,aIdx], [b,bIdx]) => {
if( b-a !== 0) {
return b-a
}else{
return aIdx - bIdx;
}
}).slice(0,2) ) : [[plays[index],index]]
return acc
},{})
1) 먼저 reduce를 통해서 객체를 만들것이다.
key에는 장르가 들어가고 value에는 이중 배열 형태의 [[ 플레이 횟수, 고유번호], [플레이 횟수, 고유번호]] 값이 들어간다.
이렇게 만드는 과정 사이에 sort와 slice도 함께 들어가 있다.
sort는 플레이 횟수에 따라 정렬하기 위해서이고 slice는 top2곡만 남기기 위해서이다.
이 코드를 구현하면서 sort를 통해 두 가지 기준으로 정렬하는 방법을 배웠다.
.sort(([a,aIdx], [b,bIdx]) => {
if( b-a !== 0) {
return b-a
}else{
return aIdx - bIdx;
}
})
b랑 a가 같지 않을 때(노래 재생 횟수가 같지않을 때)만 a,b를 비교해서 내림차순으로 정렬
b랑 a가 같을 때는 aIdx - bIdx 기준으로 정렬한다.
다시말해 노래 재생 횟수가 같지 않을 때는 재생 횟수로 정렬하고
재생 횟수가 같을 때는 고유번호를 기준으로 정렬한다.
topTwoMusic을 console.log() 해본다면
3. 가장 재생이 많이된 노래를 가지고 있는 장르부터 최대 2곡씩 배열안에 넣기
// 3. 가장 재생이 많이된 노래를 가지고 있는 장르부터 최대 2곡씩 배열안에 넣기
rankInArr.forEach((value) => {
if(topTwoMusic[value].length === 2){
result.push(topTwoMusic[value][0][1])
result.push(topTwoMusic[value][1][1])
}else{
result.push(topTwoMusic[value][0][1])
}
})
해당 장르에 곡이 2곡이면 2곡 모두 고유번호를 push 1곡이면 1곡 고유번호만 push
전체 코드
풀이 1
function solution(genres, plays) {
const result = []
// 1. 속한 노래가 많이 재생된 장르를 내림차순으로 배열안에 정렬
const rank = genres.reduce((acc,cur,index) => {
acc[cur] = (acc[cur] || 0) + plays[index]
return acc
},{})
const rankInArr = Object.entries(rank).sort(([_,a],[__,b]) => b- a).map(([genre, play]) => genre)
// 2. 각 장르 별로 재생횟수 상위 2개 노래만 저장
const topMusic = genres.reduce((acc,cur,index) => {
acc[cur] = acc[cur] ? ([[plays[index],index], ...acc[cur]].sort(([a,aIdx], [b,bIdx]) => {
if( b-a !== 0) {
return b-a
}else{
return aIdx - bIdx;
}
}).slice(0,2) ) : [[plays[index],index]]
return acc
},{})
// 3. 가장 재생이 많이된 노래를 가지고 있는 장르부터 최대 2곡씩 배열안에 넣기
rankInArr.forEach((value) => {
if(topMusic[value].length === 2){
result.push(topMusic[value][0][1])
result.push(topMusic[value][1][1])
}else{
result.push(topMusic[value][0][1])
}
})
return result
}
풀이 2
function solution(genres, plays) {
// 장르 순위구하기 (내림차순)
const genreRanking = calculateGenreRanking(genres, plays)
// 각 장르별 탑2 선정 고유번호로 간직
const topTwoPlayWithGenres = getTopTwoPlayWithGenres(genres, plays)
return genreRanking.reduce((acc,genre) => {
acc.push(...topTwoPlayWithGenres[genre])
return acc
},[])
}
function calculateGenreRanking(genres, plays) {
const genreDict= genres.reduce((acc,genre,index) => {
acc[genre] = (acc[genre] || 0) + plays[index]
return acc
},{})
const genreRanking = Object.entries(genreDict)
genreRanking.sort(([_,a],[__,b]) => b - a)
const genreRankingResult = genreRanking.map(([genre,play]) => genre)
return genreRankingResult
}
function getTopTwoPlayWithGenres(genres, plays) {
const genrePlays = genres.reduce((acc,genre,index) => {
acc[genre] ? acc[genre].push([plays[index], index]) : acc[genre] = [[plays[index], index]]
return acc
},{})
// 이미 처음 만들때 부터 인덱스가 낮은 순서대로 정렬되어있어서 노래재생 횟수가 같은 노래중에서 고유번호 낮게 정렬은 신경 안 써도 된다.
for (let genre in genrePlays) {
genrePlays[genre] = genrePlays[genre].sort(([playA, _],[playB, __]) => playB - playA)
.slice(0,2)
.map(([play,uniqueNumber]) => uniqueNumber)
}
return genrePlays
}
'알고리즘 > 프로그래머스 - JS' 카테고리의 다른 글
[프로그래머스 - JS] level.1 개인정보 수집 유효기간 (0) | 2023.05.30 |
---|---|
[프로그래머스] level.2 가장 큰수 😱 (0) | 2023.05.26 |
[프로그래머스] level.1 바탕화면 정리 (0) | 2023.05.23 |
[프로그래머스] level.1 대충 만든 자판 (0) | 2023.05.23 |
[프로그래머스] level.2 다리를 지나는 트럭 (1) | 2023.05.22 |