[Level 1] 신고 결과 받기 + Swift

sanghee·2022년 5월 6일
0

🙈코딩테스트

목록 보기
51/52
post-thumbnail

문제 링크

코딩테스트 연습 - 신고 결과 받기

문제

이용자의 ID가 담긴 문자열 배열 id_list, 
각 이용자가 신고한 이용자의 ID 정보가 담긴 문자열 배열 report, 
정지 기준이 되는 신고 횟수 k가 매개변수로 주어질 때, 
각 유저별로 처리 결과 메일을 받은 횟수를 배열에 담아 return 하도록 solution 함수를 완성해주세요.

입력

let id_list = ["muzi", "frodo", "apeach", "neo"]
let report = ["muzi frodo", "muzi frodo","apeach frodo","frodo neo","muzi neo","apeach muzi"]
let k = 2

출력

[2,1,1,0]

문제 풀이

Array extension

  • Playground에서는 generic하게 작성한 코드가 잘 돌아가나,
  • 프로그래머스에서 문제 실행시 where에서 에러가 발생하므로 Element 타입을 String으로 고정함
extension Array {

    func indexDictionary() -> [Element: Int] where Element: Hashable {
        var dict: [Element: Int] = [:]
        for (index, element) in self.enumerated() {
            dict[element] = index
        }
        return dict
    }

    mutating func appendIfNeeded(_ newElement: Element) where Element: Equatable {
        guard self.contains(newElement) == false else { return }
        self.append(newElement)
    }

}
// 실제 제출 코드
extension Array where Element == String {

    func indexDictionary() -> [Element: Int] {
        ...
    }

    mutating func appendIfNeeded(_ newElement: Element) {
        ...
    }

}

indexDictionary

  • 배열을 [인덱스: element]로 transform하는 함수
  • 이름에 해당하는 id값을 조회하기 위해 만듦
let id_list = ["muzi", "frodo", "apeach", "neo"]
let idDict: [String: Int] = id_list.indexDictionary() 
// ["muzi": 0, frodo: 1, "apeach": 2, "neo": 3]

appendIfNeeded

  • 배열에 있으면 추가하지 않고, 없으면 추가하는 함수
  • report가 중복되는 경우도 있기에 만듦
  • 아래의 경우, list에 reporter가 중복되는 경우는 발생하지 않게 됨
list.appendIfNeeded(reporter)

solution 함수

  1. reportDict를 구현함
  2. 1에서 구한 reportDict의 values의 길이가 k보다 클 때, countList에 1을 더함
func solution(_ id_list:[String], _ report:[String], _ k:Int) -> [Int] {
    let idDict: [String: Int] = id_list.indexDictionary()
    var countList: [Int] = Array(repeating: 0, count: id_list.count)
    var reportDict: [String: [String]] = [:] // [reported: [reporter]]

    for repo in report {
        let arr = repo.components(separatedBy: " ")
        guard let reporter = arr.first,
              let reported = arr.last else { continue }
        guard var list = reportDict[reported] else {
            reportDict[reported] = [reporter]
            continue
        }
        list.appendIfNeeded(reporter)
        reportDict[reported] = list
    }

    reportDict.values.forEach {
        guard $0.count >= k else { return }
        $0.forEach {
            guard let id = idDict[$0] else { return }
            countList[id] += 1
        }
    }

    return countList
}

전체 코드

extension Array {

    func indexDictionary() -> [Element: Int] where Element: Hashable {
        var dict: [Element: Int] = [:]
        for (index, element) in self.enumerated() {
            dict[element] = index
        }
        return dict
    }

    mutating func appendIfNeeded(_ newElement: Element) where Element: Equatable {
        guard self.contains(newElement) == false else { return }
        self.append(newElement)
    }

}

func solution(_ id_list:[String], _ report:[String], _ k:Int) -> [Int] {
    let idDict: [String: Int] = id_list.indexDictionary()
    var countList: [Int] = Array(repeating: 0, count: id_list.count)
    var reportDict: [String: [String]] = [:] // [reported: [reporter]]

    for repo in report {
        let arr = repo.components(separatedBy: " ")
        guard let reporter = arr.first,
              let reported = arr.last else { continue }
        guard var list = reportDict[reported] else {
            reportDict[reported] = [reporter]
            continue
        }
        list.appendIfNeeded(reporter)
        reportDict[reported] = list
    }

    reportDict.values.forEach {
        guard $0.count >= k else { return }
        $0.forEach {
            guard let id = idDict[$0] else { return }
            countList[id] += 1
        }
    }

    return countList
}
profile
👩‍💻

0개의 댓글