프로그래머스

[프로그래머스] 베스트앨범 Swift

띵지니어 2024. 8. 12. 14:51
반응형

https://school.programmers.co.kr/learn/courses/30/lessons/42579?language=swift

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

 

내 코드

import Foundation

struct Record {
    let name: String
    let count: Int
    let index: Int
}

func map(_ genres: [String], _ plays: [Int]) -> [Record] {
    
    var records: [Record] = []
    
    for i in 0..<genres.count {
        records.append(Record(name: genres[i], count: plays[i], index: i))
    }
    
    return records
}

func getGenrePlayCount(_ record: [Record], _ genre: Set<String>) -> [(String, Int)] {
    var genrePlayCount: [String: Int] = [:]

    for r in record {
        genrePlayCount[r.name, default: 0] += r.count
    }

    return genrePlayCount.sorted { $0.value > $1.value }
}


func solution(_ genres: [String], _ plays: [Int]) -> [Int] {
    
    let genre = Set(genres)
    let record = map(genres, plays)
    let specificGenre = getGenrePlayCount(record, genre)
    var result: [Int] = []
    
    for (genreName, _) in specificGenre {
        let filterList = record.filter { $0.name == genreName }.sorted { $0.count > $1.count }
        
        
        // prefix(2) 보다 시간 복잡도가 더 낮았다 (프로그래머스 환경 에서는)
        // 기존 조건문을 변경하고 싶어서 아래 처럼 변경
        // 기존 방식과 거의 유사하지만, `prefix(2)`의 사용을 피하며 코드 간결화
        for i in 0..<min(2, filterList.count) {
            result.append(filterList[i].index)
        }
    }
    return result
}

 

Review

처음 문제를 봤을 때 해야 할 것은  "장르별로 가장 많이 재생된 노래두개씩 모아 고유 번호가 들어 있는 하나의 리스트로 반환해주는 것"
이라고 생각 하였습니다.

저는 장르(name)와 재생 횟수(count) 고유번호(index)를 구분하기 위해 Record 객체를 만들어 주었습니다.

func map(_ genres: [String], _ plays: [Int]) -> [Record] {
    var records: [Record] = []
    
    for i in 0..<genres.count {
        records.append(Record(name: genres[i], count: plays[i], index: i))
    }
    
    return records
}

map 함수는 예제에서 제공한 데이터를 제가 원하는 Record 데이터로 변환해 주는 함수입니다.

예를 들어 위 예제에서 나온 genres로 만든다면 Record(name: "classic", count: 500, index: 0) 이런 데이터를 리스트에 넣어 준다고 생각하면 됩니다.

그렇게 만들어진 Record 배열은 getGenrePlayCount 라는 함수에 사용이 됩니다.

 

func getGenrePlayCount(_ record: [Record], _ genre: Set<String>) -> [(String, Int)] {
    var genrePlayCount: [String: Int] = [:]

    for r in record {
        genrePlayCount[r.name, default: 0] += r.count
    }

    return genrePlayCount.sorted { $0.value > $1.value }
}

getGenrePlayCount 함수는 Record 배열에서 장르와, 장르의 총 재생 횟수를 튜플로 만들어 주는 함수입니다.

딕셔너리를 튜플로 변환해 준 이유는 총 재생 횟수 순으로 정렬을 하기 위함입니다.

그러면 getGenrePlayCount 함수는 [("pop", 3100), ("classic", 1450)] 이런 형태로 리턴 이 됩니다.

func solution(_ genres: [String], _ plays: [Int]) -> [Int] {
    
    let genre = Set(genres)
    let record = map(genres, plays)
    let specificGenre = getGenrePlayCount(record, genre)
    var result: [Int] = []
    
    for (genreName, _) in specificGenre {
        let filterList = record.filter { $0.name == genreName }.sorted { $0.count > $1.count }
        
        for i in 0..<min(2, filterList.count) {
            result.append(filterList[i].index)
        }
    }
    return result
}

 

따라서 마지막 solution 함수에서

1. getGenrePlayCount 함수를 호출하여 받은 결과 값으로 장르 이름만 가져와서
2. Record 배열에서 genreName 과 같은 거를 거르고 각각 재생 횟수별로 정렬합니다.
3. 마지막으로 최대 2개를 result 배열에 노래의 고유번호를 넣어주는 방법으로 구현을 하였습니다. ( 1개 일 때는 1개만 )

반응형