Swift中的重构解决方案 [英] Refactored Solution In Swift

查看:97
本文介绍了Swift中的重构解决方案的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在通过做HackerRank测试用例来学习编码考试,在大多数情况下我都做得不错,但是我挂在一些简单的用例上,当我看不见时,大家都帮了我解决方案.我正在解决这个问题:

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 I can't see the solution. I'm working on this problem:

https://www.hackerrank.com/challenges/ctci-ransom-note

绑架者写了一张赎金通知书,但担心它会追溯到他身上.他找到了一本杂志,想知道他是否可以从中删掉整个单词,并用它们来创建赎金记录的无法追踪的副本.他笔记中的单词区分大小写,并且他必须使用杂志上可用的整个单词,这意味着他不能使用子字符串或串联来创建他需要的单词.

A kidnapper wrote a ransom note but is worried it will be traced back to him. He found a magazine and wants to know if he can cut out whole words from it and use them to create an untraceable replica of his ransom note. The words in his note are case-sensitive and he must use whole words available in the magazine, meaning he cannot use substrings or concatenation to create the words he needs.

给出杂志上的字眼和赎金记录中的字眼,如果他可以使用杂志中的整个字眼准确地复制他的赎金记录,则打印是";否则,打印编号

Given the words in the magazine and the words in the ransom note, print Yes if he can replicate his ransom note exactly using whole words from the magazine; otherwise, print No.

输入格式

第一行包含两个空格分隔的整数,分别描述(杂志中的单词数)和(赎金票据中的单词数)的值. 第二行包含用空格分隔的字符串,表示杂志中存在的单词. 第三行包含用空格分隔的字符串,表示赎金票据中出现的单词.

The first line contains two space-separated integers describing the respective values of (the number of words in the magazine) and (the number of words in the ransom note). The second line contains space-separated strings denoting the words present in the magazine. The third line contains space-separated strings denoting the words present in the ransom note.

每个单词都由英文字母组成(即to和to). 笔记和杂志中的单词区分大小写. 输出格式

Each word consists of English alphabetic letters (i.e., to and to ). The words in the note and magazine are case-sensitive. Output Format

如果可以使用杂志为他的赎金票据创建无法追踪的副本,则打印是";否则,打印编号

Print Yes if he can use the magazine to create an untraceable replica of his ransom note; otherwise, print No.

样本输入

6 4
give me one grand today night
give one grand today

样本输出

Yes
Explanation

杂志上有写出无法追踪的赎金票据所需的所有四个单词,因此我们将是"作为答案.

All four words needed to write an untraceable replica of the ransom note are present in the magazine, so we print Yes as our answer.

这是我的解决方案:

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: " ") }
    }

    // Get list of elements that intersect in each array
    let filtered = Set(a).intersection(Set(b))
    // Map set to set of Boolean where true means set a has enough words to satisfy set b's needs
    let checkB = filtered.map{ word in reduceSet(b, word: word) <= reduceSet(a, word: word) }

    // If mapped set does not contain false, answer is Yes, else No
    return !checkB.contains(false) ? "Yes" : "No"
}
func reduceSet(_ a: [String], word: String) -> Int {
    return (a.reduce(0){ $0 + ($1 == word ? 1 : 0)})
}

print(main())

在使用此解决方案的20个测试用例中,我总是会超时.因此,该解决方案似乎可以解决所有测试用例,但不能在其所需的时间限制内解决.这些都是很好的做法,但是当您陷入这样的困境时,实在令人沮丧.

I always time out on three of the 20 test-cases with this solution. So the solution seems to solve all the test cases, but not within their required time constraints. These are great practice, but it's so extremely frustrating when you get stuck like this.

我应该注意,我使用SetsSet(a).intersection(Set(b))是因为当我尝试映射Strings的数组时,一半的测试用例超时了.

I should note that I use Sets and the Set(a).intersection(Set(b)) because when I tried mapping an array of Strings, half the test-cases timed out.

任何更清洁或更有效的解决方案将不胜感激!谢谢!

Any cleaner, or more efficient solutions will be greatly appreciated! Thank you!

推荐答案

我很轻松地对您的代码进行了一些改进.我发表评论来解释这些变化:

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())

删除评论:

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. :)

这篇关于Swift中的重构解决方案的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆