Refactored Solution In Swift

后端 未结 2 918
旧时难觅i
旧时难觅i 2021-01-24 13:29

I\'ve been studying for a coding exam by doing the HackerRank test cases, for the most part I\'ve been doing well, but I get hung up on some easy cases and you all help me when

相关标签:
2条回答
  • 2021-01-24 13:30

    Thanks to @Alexander - I was able to solve this issue using NSCountedSet instead of my custom reduce method. It's much cleaner and more efficient. Here is the solution:

    import Foundation
    
    func main() -> String {
        let v = readLine()!.components(separatedBy: " ").map{Int($0)!}
        var a = [String](); var b = [String]()
        if v[0] < v[1] { return "No"}
        for i in 0 ..< 2 {
            if i == 0 {
                a = (readLine()!).components(separatedBy: " ")
            } else { b = (readLine()!).components(separatedBy: " ") }
        }
        let countA = NSCountedSet(array: a)
        let countB = NSCountedSet(array: b)
        let intersect = Set(a).intersection(Set(b))
        let check = intersect.map{ countB.count(for: $0) <= countA.count(for: $0) }
        return !check.contains(false) ? "Yes" : "No"
    }
    print(main())
    

    Many thanks!

    0 讨论(0)
  • 2021-01-24 13:40

    I took the leisure of making some improvements on your code. I put comments to explain the changes:

    import Foundation
    
    func main() -> String {
        // Give more meaningful variable names
        let firstLine = readLine()!.components(separatedBy: " ").map{Int($0)!}
        let (magazineWordCount, ransomNoteWordCount) = (firstLine[0], firstLine[1])
    
        // a guard reads more like an assertion, stating the affirmative, as opposed to denying the negation.
        // it also 
        guard magazineWordCount > ransomNoteWordCount else { return "No" }
    
        // Don't use a for loop if it only does 2 iterations, which are themselves hardcoded in.
        // Just write the statements in order.
        let magazineWords = readLine()!.components(separatedBy: " ")
        let ransomNoteWords = readLine()!.components(separatedBy: " ") //You don't need ( ) around readLine()!
    
        let magazineWordCounts = NSCountedSet(array: magazineWords)
        let ransomNoteWordCounts = NSCountedSet(array: ransomNoteWords)
    
        // intersect is a verb. you're looking for the noun, "intersection"
        // let intersection = Set(a).intersection(Set(b))
        // let check = intersect.map{ countB.count(for: $0) <= countA.count(for: $0) }
    
        // You don't actually care for the intersection of the two sets.
        // You only need to worry about exactly the set of words that
        // exists in the ransom note. Just check them directly.
        let hasWordWithShortage = ransomNoteWordCounts.contains(where: { word in
           magazineWordCounts.count(for: word) < ransomNoteWordCounts.count(for: word)
        })
    
        // Don't negate the condition of a conditional expression. Just flip the order of the last 2 operands.
        return hasWordWithShortage ? "No" : "Yes"
    }
    print(main())
    

    with the comments removed:

    import Foundation
    
    func main() -> String {
        let firstLine = readLine()!.components(separatedBy: " ").map{Int($0)!}
        let (magazineWordCount, ransomNoteWordCount) = (firstLine[0], firstLine[1])
    
        guard magazineWordCount > ransomNoteWordCount else { return "No" }
    
        let magazineWords = readLine()!.components(separatedBy: " ")
        let ransomNoteWords = readLine()!.components(separatedBy: " ")
    
        let magazineWordCounts = NSCountedSet(array: magazineWords)
        let ransomNoteWordCounts = NSCountedSet(array: ransomNoteWords)
    
        let hasWordWithShortage = ransomNoteWordCounts.contains{ word in
           magazineWordCounts.count(for: word) < ransomNoteWordCounts.count(for: word)
        }
    
        return hasWordWithShortage ? "No" : "Yes"
    }
    print(main())
    

    It's simpler, and much easier to follow. :)

    0 讨论(0)
提交回复
热议问题