프로그래머스 - 배스트앨범

1. 문제

문제 링크


2. 풀이

2-1. 조건

  1. 장르 별로 가장 많이 재생된 노래를 두 개씩 모은다.
  2. 속한 노래가 많이 재생된 장르를 먼저 수록한다.
  3. 장르 내에서 많이 재생된 노래를 먼저 수록한다.
  4. 장르 내에서 재생 횟수가 같은 노래 중에서는 고유 번호가 낮은 노래를 먼저 수록한다.

2-2. 풀이

차근차근 구현해 나가봅시다.
일단 음악들을 장르별로 묶어서 플레이 시간과 어떤 음악들이 있는지 저장합니다.

const agg = genres.reduce((m, genre, index) => {
    m[genre] = m[genre] || { playtime: 0, music: [] };
    m[genre].playtime += plays[index]; // 플레이 시간 누적
    m[genre].music.push([index, plays[index]]); // 어떤 음악이 있는지 기록(인덱스와 플레이 시간)
    return m;
}, {});

// 가공 후의 agg의 모습
agg = {
    rock: {
        playtime: 200
        music: [[0, 100], [2, 100]]
    },
    pop: {
        playtime: 500,
        music: [[1, 100], [3, 200], [4, 300]]
    }
}

그 다음 agg를 playtime을 기준으로 내림차순 정렬을 합니다. (2번 조건 충족)

const sort = Object.values(agg).sort((a, b) => b.playtime - a.playtime)

// 정렬 후 sort의 모습
sort = [{ playtime: 500, music: [[1, 100], [3, 200], [4, 300]] }, { playtime: 200, music: [[0, 100], [2, 100]] }

이젠 music을 플레이 시간 기준으로 내림차순 정렬해서 장르별로 두 개씩만 뽑아내면 되겠네요.
플레이 시간이 같아도 고유 번호가 낮은 음악이 먼저 선택되는 건 보장되니 굳이 정렬 안해도 됩니다.
(1번 조건, 3번 조건, 4번 조건 충족)

const album = sort.reduce((m, genre) => {
     // 플레이 시간 기준으로 내림차순 정렬
     genre.music.sort((a, b) => b[1] - a[1]);
     // 두 개씩 모으기
     return m = m.concat(genre.music.slice(0, 2).map(v => v[0]));
}, []);

총 정리를 하면
1. 음악들을 장르별로 묶어서 플레이 시간과 어떤 음악들이 있는지 저장합니다.
2. 저장한 집합을 playtime을 기준으로 내림차순 정렬을 합니다.
3. 정렬한 집합에서 music을 플레이 시간 기준으로 내림차순 정렬해서 두 개씩 뽑아냅니다.

3. 전체 코드

function solution(genres, plays) {
           // 1. 음악들을 장르별로 묶어서 플레이 시간과 어떤 음악들이 있는지 저장합니다.
    return Object.values(genres.reduce((m, genre, index) => {
            m[genre] = m[genre] || { playtime: 0, music: [] };
            m[genre].playtime += plays[index];
            m[genre].music.push([index, plays[index]]);
            return m;
        }, {}))
        // 2. 저장한 집합을 playtime을 기준으로 내림차순 정렬을 합니다.
        .sort((a, b) => b.playtime - a.playtime)
        // 3. 정렬한 집합에서 music을 플레이 시간 기준으로 내림차순 정렬해서 두 개씩 뽑아냅니다.
        .reduce((m, genre) => {
            genre.music.sort((a, b) => b[1] - a[1]);
            return m = m.concat(genre.music.slice(0, 2).map(v => v[0]));
        }, []);
}

좋은 웹페이지 즐겨찾기