[프로그래머스] 베스트 앨범 (Swift)
https://school.programmers.co.kr/learn/courses/30/lessons/42579
해시 Hash
N개의 노래에 대해 장르 배열 1개, 재생수 배열 1개가 주어지고
장르별로 2곡을 뽑아 하나의 앨범을 만들어야 함. > 앨범 트랙리스트 (배열 인덱스 = 노래의 고유번호)를 반환하는 문제
앨범에 수록 되는 노래 순서 중요
곡 선정 과정 1) 총합 재생수가 높은 장르의 곡 먼저 수록, 2) 재생수가 많은 곡 먼저 수록, 3) 재생수가 같을 경우 고유번호가 작은 순으로 수록
접근방법
Swift dictionary, tuple 사용, 정렬된 건 array에 담아서 사용
우선 [장르: 재생수 합] 딕셔너리를 만들고, [장르: [(노래 고유번호, 노래 재생수)]] 딕셔너리를 만들어서 풀이했다.
이후 map을 써서 장르를 재생수 순으로 정렬한 배열을 만들고 (genRank)
genRank로 반복문을 돌면서 장르별 두곡씩 수록하는 과정을 거쳤다.
이때 만들어둔 두번째 딕셔너리에서 해당 장르에 수록된 곡 배열을 1)재생수 순, 2) 번호순으로 정렬해서 고유번호만 뽑아낸다. (*해당 장르에 곡 수가 2개 이상인 경우만)
장르의 곡 수가 1개면 그대로 앨범에 수록한다. (정렬X - core dumped 남)
오답노트
- 배열의 원소가 한 개일 수 있는 경우에서 정렬을 하면 안됨(아마 커스텀 정렬함수를 사용해서 오류가 났던 것 같다. 빌트인이었으면 예외처리 해뒀겠지만)
- 그리고..Array append 할 때 여러개 원소를 한번에 추가할 경우 contentsOf로 전달해야함
소스코드
import Foundation
func solution(_ genres:[String], _ plays:[Int]) -> [Int] {
var answer:[Int] = []
var dict1:[String:Int] = [:]
// 장르:재생수합
var dict2 = [String:[(song: Int, plays: Int)]]()
// 장르:노래 고유번호
for (i, gen) in genres.enumerated() {
if dict1[gen] == nil {
dict1[gen] = plays[i]
} else {
dict1[gen]! += plays[i]
}
if dict2[gen] == nil {
dict2[gen] = [(song: i, plays: plays[i])]
} else {
dict2[gen]!.append((song: i, plays: plays[i]))
}
}
let genRank:[String] = dict1.sorted { $0.1 > $1.1 }.map{ $0.0 }
for gen in genRank {
var songs:[(song: Int, plays: Int)] = dict2[gen]!
if songs.count >= 2 {
var songs2 = songs.sorted {
if $0.1 == $1.1 {
return $0.0 < $1.0
} else {
return $0.1 > $1.1
}
}.map{$0.0}
answer.append(contentsOf:songs2[0...1])
} else {
answer.append(songs[0].song)
}
}
return answer
}