베스트앨범 (level3)

원용현·2022년 9월 23일
0

프로그래머스

목록 보기
24/49

링크

https://school.programmers.co.kr/learn/courses/30/lessons/42579

문제

스트리밍 사이트에서 장르 별로 가장 많이 재생된 노래를 두 개씩 모아 베스트 앨범을 출시하려 한다. 노래는 고유 번호로 구분하며, 노래를 수록하는 기준은 다음과 같다.

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

노래의 장르를 나타내는 문자열 배열 genres와 노래별 재생 횟수를 나타내는 정수 배열 plays가 주어질 때, 베스트 앨범에 들어갈 노래의 고유 번호를 순서대로 return 하도록 solution 함수를 완성하라.

예제로 이해

genres = ["classic", "pop", "classic", "classic", "pop"]
plays = [500, 600, 150, 800, 2500]
return = [4, 1, 3, 0]

classic 장르는 총 1450회 재생 되었으며 각각 다음과 같다.

고유 번호 3: 800회 재생
고유 번호 0: 500회 재생
고유 번호 2: 150회 재생

pop 장르는 총 3100회 재생 되었으며 각각 다음과 같다.

고유 번호 4: 2,500회 재생
고유 번호 1: 600회 재생

따라서 총 재생 횟수가 가장 많은 pop 장르부터 베스트 앨범에 들어가며, 그 중에서도 재생 횟수가 가장 많은 순서인 [4, 1] 순서로 입력된다.

다음으로 재생 횟수가 많은 classic 장르가 베스트 앨범에 들어가며, 그 중에서 재생 횟수가 가장 많은 [3, 0, 2] 순서로 들어가지만, 한 장르에 대해서 2개까지 입력되므로 [3, 0]이 입력된다.

따라서 반환되는 값은 [4, 1, 3, 0]이 된다.

코드

function solution(genres, plays) {
    let result = []
    let index = []
    let totalPlay = []
    
    let total = 0
    let onlyGenres = [...new Set(genres)]
    
    for(let i = 0; i < onlyGenres.length; i++) {
        genres.filter((word, idx) => {
            if(word === onlyGenres[i]) {
                index.push(idx)
            }
        })
        
        for(let j = 0; j < index.length; j++) {
            total += plays[index[j]]
        }
        
        totalPlay.push(total)
        total = 0
        index = []
    }
    
    let onlyGenresLength = onlyGenres.length
    
    for(let i = 0; i < onlyGenresLength; i++) {
        let word = onlyGenres[totalPlay.indexOf(Math.max(...totalPlay))]
        onlyGenres.splice(totalPlay.indexOf(Math.max(...totalPlay)), 1)
        totalPlay.splice(totalPlay.indexOf(Math.max(...totalPlay)), 1)
        
        genres.filter((el, idx) => {
            if(word === el) {
                index.push(plays[idx])
            }
        })
        
        result.push(plays.indexOf(Math.max(...index)))
        index.splice(index.indexOf(Math.max(...index)), 1)
        
        if(index.length !== 0) {
            if(plays.indexOf(Math.max(...index)) === result[result.length - 1]) {
               result.push(plays.indexOf(Math.max(...index), plays.indexOf(Math.max(...index)) + 1))
            } else {
                result.push(plays.indexOf(Math.max(...index)))
            }
        }

        index = []
    }
    return result
}

코드 풀이

먼저 장르가 담겨 있는 배열에서 중복을 제거하여 어떤 장르가 존재하는지 확인한다.

각각의 장르에 대해서 반복이 실시되며 filter 함수를 통해서 해당 장르가 있는 index의 집합을 새로 만들어 해당 장르를 만족하는 총 재생횟수를 찾아낸다.

장르들의 총 재생횟수를 찾아내면 재생횟수가 가장 많은 순서대로 반환할 배열에 넣는 작업을 실시한다.

반복문은 장르의 종류의 수 만큼 반복이 진행되며, 총재생 배열에서 가장 큰 수를 찾은 뒤에 그 값의 index 값으로 장르의 이름을 알아낸다. 해당 이름을 장르를 다시 filter로 걸러내는데, filter 함수에서 제공하는 index를 활용해서 해당 index에 자리잡고 있는 재생횟수를 새로운 배열에 담아준다.

만들어진 배열에는 원하는 장르에 대한 재생횟수에 대한 집합이 존재한다. 이 배열에서 최댓값을 찾아 해당 값이 존재하는 index의 위치를 반환할 배열에 넣어준다.

여기에서 주의할 점은 장르에 대해 재생횟수의 집합의 길이가 1일 경우에는 값을 1번만 넣도록 예외를 적용해야한다. 또, 같은 장르에 대해서 같은 재생횟수를 가지고 있을 경우에는 index값이 작은 순서대로 넣는 과정이 필요하다.

0개의 댓글