【发布时间】:2019-07-03 23:35:40
【问题描述】:
为了个人启蒙,我正在摆弄 Swift 的 .reduce(),但我遇到了我无法理解的异常行为。
我花了很多意想不到的时间(至少 6 小时)进行研究和实验,但我很难过。
我有两个算法(我写了第二个。)它们似乎做完全相同的事情,即计算出现在具有重复模式的无限字符串中的字符数(在本例中为“a”) .两种算法在大约 50% 的时间里表现相同。一个使用 .reduce() 两次,另一个 - 工作的 - 使用 for 循环。
适用于所有情况的算法是:
let str = readLine()!
let length = Int(readLine()!)!
let fullRepetitions = length / str.characters.count
let lengthLastRep = length % str.characters.count
var count = fullRepetitions * str.characters.reduce(0) { $1 == "a" ? $0 + 1 : $0 }
for i in 0..<lengthLastRep {
if str[str.index(str.startIndex, offsetBy: i)] == "a" {
count += 1
}
}
print(count)
而不是,但应该,是:
let pattern = readLine()!
let length = Int(readLine()!)!
let fullyRepeatedPatterns = length / pattern.count
let lastPatternLength = pattern.count % length
var countOfAs = fullyRepeatedPatterns * pattern.reduce(0, { $1 == "a" ? $0 + 1 : $0 })
countOfAs += pattern
.prefix(upTo: pattern.index(pattern.startIndex, offsetBy: lastPatternLength - 1))
.reduce(0, { $1 == "a" ? $0 + 1 : $0 })
print(countOfAs)
至少从表面上看,它们看起来应该做的完全一样。但他们没有。
起初,我以为我在执行取模以获取最后一个模式的长度时发现了我的问题,然而,如果我将第二个算法更改为第一个,它不仅会停止执行边缘情况,但有一个严重的运行时错误。也就是说,改变这个:
let lastPatternLength = pattern.count % length
对此:
let lastPatternLength = length % pattern.count
导致具有更多 .reduce() 的第二个算法中断(运行时错误),所以我认为模数不会导致错误。
更有趣的是,错误并不一致。输入:
aab
882787
“aab”重复了 882787 次,看起来像是一个错误的错误......或者似乎是一个错误。不过……
let pattern = "aab"
let length = 882787
let fullyRepeatedPatterns = length / pattern.count
let lastPatternLength = pattern.count % length
var countOfAs = fullyRepeatedPatterns * pattern.reduce(0, { $1 == "a" ? $0 + 1 : $0 })
countOfAs += pattern
.prefix(upTo: pattern.index(pattern.startIndex, offsetBy: lastPatternLength - 1))
.reduce(0, { $1 == "a" ? $0 + 1 : $0 })
print("expected 588525 but got \(countOfAs)")
我提前知道正确答案,所以我可以说:
我预计是 588525,但得到了 588526。
但是输入时:
babbaabbabaababaaabbbbbbbababbbabbbababaabbbbaaaaabbaababaaabaabbabababaabaabbbababaabbabbbababbaabb
860622337747
27 点就关了!
最后,好像故意很讨厌,输入:
ababa
3
关闭 -1。
在很多情况下两种算法都有效,例如:
aba
10
但我不在乎那些。
有人可以解释一下我在这里缺少什么吗?
【问题讨论】: