出于个人启发,我摆弄了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
但是我不在乎那些。
有人可以解释一下我在这里缺少什么吗?
答案 0 :(得分:2)
第一:
let lastPatternLength = pattern.count % length
应该是
let lastPatternLength = length % pattern.count
与原始算法相同。例如:
pattern = "abab"
length = 11
length / pattern.count = 11 / 4 = 2
length % pattern.count = 11 % 4 = 3
表示该模式需要两个副本以及三个附加字符才能达到11的总长度。
这有时在测试中导致运行时错误是由于第二个错误:In
.prefix(upTo: pattern.index(pattern.startIndex, offsetBy: lastPatternLength - 1))
您不能从lastPatternLength
中减去一个,应该是
.prefix(upTo: pattern.index(pattern.startIndex, offsetBy: lastPatternLength))
因为prefix(upTo:)
返回的子序列最多为 个给定索引。您也可以将其简化为
.prefix(lastPatternLength)