티스토리 뷰

반응형

 

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

 

문제는 위 링크에서 볼 수 있다. 문제에 대한 해설보다는 기억하고 싶은 개념, 사고, 문법을 기록하는 글이다. 

답안은 맨 아래에 표기해 두었다.

 

 


 

답안 풀이

이번 문제는 처음부터 끝까지 접근하고 푸는 방식을 적는 게 도움이 될 것 같아서 풀이를 해보려 한다. 

이 풀이 말고 프로그래머스에서 best에 있는 풀이법도 가져왔는데,

그건 정말 신박해서 기억하고 싶었다. 그에 대한 풀이는 여기서 확인하면 된다. 

 


 

참고로 주어진 테스트 케이스에는

조건 3. 장르 내에서 재생 횟수가 같은 노래 중에서는 고유 번호가 낮은 노래를 먼저 수록합니다.

를 확인할 수 없어서 테스트 케이스에 값을 하나 더 추가했다. 따라서 원하는 출력 값은 [4, 1, 3, 5]가 되겠다. 

const genres = ["classic", "pop", "classic", "classic", "pop", "classic"];
const plays = [500, 600, 150, 800, 2500, 800];

output = [ 4, 1, 3, 5 ]

 


 

 reduce() 메서드로 객체화하여 풀이

지난 문제들과 객체화하는 방식은 같지만, 이차 배열을 만들어 좀 더 복잡하다. 문제를 보면 알 수 있듯 필요한 변수들과 풀이 순서들을 나열해보겠다. 

 

const chart = 

1. 장르별로 나누고 재생 수 합하기 : playCount

2. 고유번호 i 인 노래를 각 장르에 맞는 list에 담는다. 이때 고유번호 index 도 같이 list배열 안에 넣어준다. 

 

원하는 output 

chart:  {
  classic: {
    playCount: 2750,
    list: [ [ 0, 500 ], [ 2, 150 ], [ 3, 800 ], [ 5, 800 ], [ 6, 500 ] ]
  },
  pop: { playCount: 3100, list: [ [ 1, 600 ], [ 4, 2500 ] ] }
}

code : 

 const chart = genres.reduce((obj, genre, i) => {
    if (!obj[genre]) {
      obj[genre] = { playCount: plays[i], list: [] };
    } else {
      obj[genre].playCount += plays[i];
    }

    obj[genre].list.push([i, plays[i]]);

    return obj;
  }, {});

 

 

sort() 메서드로 playCount 정렬하기

const sorted =

3. 합산된 playCount를 내림차순으로 정렬한다. ( 조건 1. 속한 노래가 많이 재생된 장르를 먼저 수록합니다.)

 

원하는 output : playCount 값이 큰 순서대로 나열된다. 

sorted : [
  { playCount: 3100, list: [ [ 1, 600 ], [ 4, 2500 ] ] },
  {
    playCount: 2750,
    list:  [ [ 0, 500 ], [ 2, 150 ], [ 3, 800 ], [ 5, 800 ], [ 6, 500 ] ]
  }
]

code  :

  const sorted = Object.values(chart).sort((a, b) => {
    // 내림차순 정렬
    return b.playCount - a.playCount;
  });

 

 

sort() 메서드로 list 정렬하기 

const answer = 

4. 재생된 장르가 많은 순으로 정렬된 sorted를 그 안에서 재생된 노래를 내림차순으로 정렬한다. (조건 2. 장르 내에서 많이 재생된 노래를 먼저 수록합니다)

 

원하는 output : list 값이 큰 순서대로 나열된다. 

첫번째 순회 : genre(pop)=  { playCount: 3100, list: [ [ 4, 2500 ], [ 1, 600 ] ] }
두번째 순회 : genre(classic) =  {
  playCount: 2750,
  list: [ [ 3, 800 ], [ 5, 800 ], [ 0, 500 ], [ 6, 500 ], [ 2, 150 ] ]
}

 

 

code :

  const answer = sorted.reduce((acc, genre) => {
    genre.list.sort((a, b) => {
      return b[1] - a[1];
    });
  }, []);

  return answer;

 

 

 

answer에 해당 index push()하기

5. 장르 내에서 정렬된 리스트의 첫 번째 index와 두 번째 index를 answer에 push 한다.

(조건 3. 장르 별로 가장 많이 재생된 노래를 두 개씩 모아 베스트 앨범을 출시하려 합니다. & 장르에 속한 곡이 하나라면, 하나의 곡만 선택합니다.)

 

 

원하는 output :  내림차순으로 정렬된 sorted의 list들을 각각의 genre에서 index가 0, 1 인 값을 차례로 answer에 push 해준다. 이때 장르에 속한 곡이 두 개 이상일 때만 두 번째 값을 넣어주는 조건문을 쓴다. 

answer = [ 4, 1, 3, 5 ]

 

code : 

  const answer = sorted.reduce((acc, genre) => {
    genre.list.sort((a, b) => {
      return b[1] - a[1];
    });
    
    // 5.에 해당하는 부분
    acc.push(genre.list[0][0]);
    // 장르에 속한 곡이 2개부터 두 번 째 값을 넣어준다.
    if (genre.list.length > 1) {
      acc.push(genre.list[1][0]);
    }
    return acc;
  }, []);

 

 


 

답안

function solution(genres, plays) {
  // input 객체화 시키기
  const chart = genres.reduce((obj, genre, i) => {
    if (!obj[genre]) {
      obj[genre] = { playCount: plays[i], list: [] };
    } else {
      obj[genre].playCount += plays[i];
    }
    obj[genre].list.push([i, plays[i]]);
    
    return obj;
  }, {});

  // 객체 정렬
  const sorted = Object.values(chart).sort((a, b) => {
    // 내림차순 정렬
    return b.playCount - a.playCount;
  });

  // 정렬한 sorted를 사용한다.
  const answer = sorted.reduce((acc, genre) => {
    genre.list.sort((a, b) => {
      return b[1] - a[1];
    });
    acc.push(genre.list[0][0]);

    if (genre.list.length > 1) {
      acc.push(genre.list[1][0]);
    }
    return acc;
  }, []);

  return answer;
}

 

 


 

Comment

풀었던 해시 관련 문제 중 가장 난이도가 있는 문제였던 것 같다. 우선 reduce()를 사용해서 이차 배열을 만들 수 있다는 것을 배웠다. 

필요한 조건을 쓰면서 그 조건을 다 담으려고 노력해야겠다. 

 

 

 


 

반응형