Even Fibonacci numbers
Problem 2
Each new term in the Fibonacci sequence is generated by adding the prevIoUs two terms. By starting with 1 and 2,the first 10 terms will be:1,2,3,5,8,13,21,34,55,89,…
By considering the terms in the Fibonacci sequence whose values do not exceed four million,find the sum of the even-valued terms.
根据WWDC高级Swift视频实现了一个memoized斐波那契函数:
func memoize<T:Hashable,U>( body: ((T)->U,T) -> U) -> (T)->U { var memo = [T:U]() var result: ((T)->U)! result = { x in if let q = memo[x] { return q } let r = body(result,x) memo[x] = r return r } return result } let fibonacci = memoize { (fibonacci:Int->Double,n:Int) in n < 2 ? Double(n) : fibonacci(n-1) + fibonacci(n-2) }
并实现了一个符合Sequence协议的类
class FibonacciSequence: SequenceType { func generate() -> GeneratorOf<Double> { var n = 0 return GeneratorOf<Double> { fibonacci(n++) } } subscript(n: Int) -> Double { return fibonacci(n) } }
var fib = FibonacciSequence().generate() var n:Double = 0 var sum:Double = 0 while n < Double(4_000_000) { if n % 2 == 0 { sum += n } n = fib.next()! } println(sum)
第二个更实用的解决方案,使用ExSwift的takeWhile功能
let f = FibonacciSequence() println((1...40).map { f[$0] } .filter { $0 % 2 == 0 } .takeWhile { $0 < 4_000_000 } .reduce(0,combine: +))
我想改进这个解决方案,因为乞讨的1 … 40范围无缘无故地计算了太多的术语.理想情况下,我希望能够拥有某种无限范围,但同时只计算满足条件的所需条款
有什么建议 ?
解决方法
func filter<S : SequenceType>(source: S,includeElement: (S.Generator.Element) -> Bool) -> [S.Generator.Element]
但由于返回值是一个数组,如果你愿意,这不适合
使用“无限”序列.但随着
lazy(FibonacciSequence()).filter ( { $0 % 2 == 0 })
你得到了一个偶数斐波纳契数的“无限”序列.你不能
在该序列上调用ExSwift的.takeWhile()方法,因为
.takeWhile()仅为struct SequenceOf定义,而不是为
一般序列.但
TakeWhileSequence( lazy(FibonacciSequence()).filter ( { $0 % 2 == 0 }),{ $0 < 4_000_000 } )
工作并给出所有偶数斐波纳契数的序列小于
4000000.然后
let sum = reduce(TakeWhileSequence( lazy(FibonacciSequence()).filter ( { $0 % 2 == 0 }),{ $0 < 4_000_000 }),+)
给出预期结果并仅计算“必要”
斐波纳契数.
请注意,实际上不需要记住Fibonacci数字
这是因为它们是按顺序访问的.另外(作为@Matteo
已经注意到了),所有Fibonacci数都是整数.所以你可以
将序列更简单地定义为
struct FibonacciSequence : SequenceType { func generate() -> GeneratorOf<Int> { var current = 1 var next = 1 return GeneratorOf<Int>() { let result = current current = next next += result return result }; } }
而上述计算仍然有效.
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。