https://school.programmers.co.kr/learn/courses/30/lessons/42579
나의 풀이
슈도 코드
- 먼저 장르별로 담고 있는 음악과 총 재생수를 저장하기 위한 genreDic 딕셔너리를 정의한다.
genreDic = { classic : { music : [각 장르에 담긴 고유번호 배열], count : 각 장르의 재생수 합 }, pop : { ... }, ... }
- genres를 반복문으로 돌리면서 genreDic의 각 장르별 music 배열 데이터를 채운다.
- genreDic 객체의 각 장르별 music 배열을 반복문으로 돌리면서 plays 배열을 참고해 count 합계를 계산하고, genreDic의 count를 채운다.
- genreDic의 장르들을 count들로 sort해서 새 배열 genreArr을 정의한다.
- genreArr을 반복으로 돌리면서 genreDic에서 해당하는 장르의 music 배열을 가져오고, 해당 배열을 count와 id별로 sort한 뒤 두 번째 원소까지만 구해서 answer에 push한다.
풀이 코드
function solution(genres, plays) {
var answer = [];
const genreDic = {};
//genreDic의 각 장르별 music을 채운다.
genres.map((genre, idx) => {
if (!genreDic[genre]) {
genreDic[genre] = {
music: [idx],
count: 0,
};
} else {
genreDic[genre].music.push(idx);
}
});
//genreDic의 각 장르별 count를 채운다.
Object.entries(genreDic).map(([key, { music }]) => {
const count = music.reduce((acc, cur) => {
return acc + plays[cur];
}, 0);
genreDic[key].count = count;
});
//장르별 count로 정렬한 genreArr을 생성한다.
const genreArr = Object.keys(genreDic).sort(
(a, b) => +genreDic[b].count - +genreDic[a].count
);
//genreArr을 돌리면서 해당하는 장르의 곡들을 정렬, 2개씩 slice하고 answer에 push한다.
genreArr.map((genre) => {
const songs = genreDic[genre].music;
const arr = songs.sort((a, b) => {
return +plays[b] - +plays[a] || +a - +b;
});
answer.push(...arr.slice(0, 2));
});
return answer;
}
다른 사람의 풀이
내 풀이는 뭔가 많이 추려냈는데도 조금 지저분했는데, 제출한 뒤 다른 사람의 풀이를 보니 깔끔한 코드가 있어서 올려 본다.
슈도 코드
- 장르별 재생수 합을 갖게 될 dic 딕셔너리를 정의한다. 형식은 다음과 같다.
dic = { classic : 각 장르의 재생수 합, pop : 각 장르의 재생수 합, ... }
- genres를 반복문으로 돌리며 dic을 채운다.
- answer에 제출할 장르별 곡 수 정보를 담을 dupDic 딕셔너리를 정의한다.
- genres를 반복문으로 돌리며 곡별 정보를 담고 있는 새 배열을 정의한다. 각 배열이 담고 있는 객체 원소의 형식은 다음과 같다.
{ genre : 곡의 장르, count : 곡의 재생수, index : 곡의 고유번호(인덱스) }
- 4의 배열을 sort한다. 첫 번째로는 dic을 참고한 장르별 count 합으로 sort하고, 같은 장르일 시 각 곡의 count로 sort한다. 곡 count가 같을 시 고유번호로 sort한다.
- 5의 배열에서 각 장르별로 2곡씩 추린다. 추리는 과정에서 dupDic을 이용한다.
- 6에서 인덱스만 뽑아서 answer로 리턴한다.
풀이 코드
function solution(genres, plays) {
var dic = {};
genres.forEach((t,i)=> {
dic[t] = dic[t] ? dic[t] + plays[i] :plays[i];
});
var dupDic = {};
return genres
.map((t,i)=> ({genre : t, count:plays[i] , index:i}))
.sort((a,b)=>{
if(a.genre !== b.genre) return dic[b.genre] - dic[a.genre];
if(a.count !== b.count) return b.count - a.count;
return a.index - b.index;
})
.filter(t=> {
if(dupDic[t.genre] >= 2) return false;
dupDic[t.genre] = dupDic[t.genre] ? dupDic[t.genre]+ 1 : 1;
return true;
})
.map(t=> t.index);
}
참고한 코드는... 우선 메소드 체이닝을 이용해서 간결하게 만든 게 깔끔해서 좋았고...
조금 복잡한 내 딕셔너리와 다르게 각 장르별 재생수 합만 넣어서 dic을 만들어 둔 후 나머지는 genres, plays에서 각자 가져와서 휘릭휘릭 계산한 점도 간단해서 좋았다.
또 filter를 저렇게 저런 식으로... index값을 활용하지 않고도 선착 n개만 받는 형식을 구현할 수 있다니 처음 보는 패턴이어서 새로웠다. 나중에 활용할 일이 있을 것 같다.
'공부 > 알고리즘 문제풀이' 카테고리의 다른 글
[프로그래머스 코딩테스트 연습] 기능개발 JS (0) | 2023.06.12 |
---|---|
백준 2941 : 크로아티아 알파벳 js 풀이 (1) | 2023.06.11 |
백준 4344 : 평균은 넘겠지 js 풀이 (0) | 2023.06.11 |
백준 8958 : OX퀴즈 nodejs 풀이 (1) | 2023.06.11 |