【问题标题】:How do I get fibonacci numbers using sliding Stream in scala?如何在scala中使用滑动流获得斐波那契数?
【发布时间】:2013-12-23 03:29:01
【问题描述】:

Stream 文档中有一个很好的例子,它可以获取斐波那契数。

val fibs:Stream[Int] = 0 #:: 1 #:: fibs.zip(fibs.tail).map { n => n._1 + n._2 }

我想通过滑动来实现,所以我尝试了以下操作。

val test = 0 #:: 1 #:: Stream.empty
test.sliding(2).map(_.sum).toStream

最后一行正确获取 Stream(1, ?) 但是当我按如下方式将其连接到上面时,当我尝试获得第三个成员。

val fibs2:Stream[Int] = 0 #:: 1 #:: fibs2.sliding(2).map(_.sum).toStream

如果我如下给出 3 个数字,它会计算前两个数字的总和。但这不是斐波那契数。

val fibs3:Stream[Int] = 0 #:: 0 #:: 1 #:: fibs3.sliding(2).map(_.sum).toStream

任何想法或帮助将不胜感激。

更新

  • 我怀疑错误的原因是滑动方法返回Iterator,它需要知道使用hasNext方法是否有next值
  • 如果给定第一个播种机,则滑动方法应计算前 n 个数字的总和,这些数字称为 tribonacci (n=3)、tetranacci (n=4) 等。

【问题讨论】:

    标签: scala stream fibonacci sliding


    【解决方案1】:

    问题似乎是GroupedIterator(由sliding 返回)过于急切。创建每个滑动窗口时,它会强制当前窗口之后的下一个元素。

    这是一个简单的例子:

    import scala.util.Try
    
    def bad[T]: Stream[T] = throw new RuntimeException("Don't peek!")
    
    // Should be able to view group of first 2 elements without error,
    // but sliding and grouped both read the 3rd element
    def testA: Stream[Int] = 1 #:: 2 #:: bad
    
    Try { testA.sliding(2).next }
    // res0: scala.util.Try[scala.collection.immutable.Stream[Int]] = Failure(java.lang.RuntimeException: Don't peek!)
    
    Try { testA.grouped(2).next }
    // res1: scala.util.Try[scala.collection.immutable.Stream[Int]] = Failure(java.lang.RuntimeException: Don't peek!)
    
    // Adding an extra element before the bad entry gives
    // sufficient padding for a sliding window of 2
    def testB: Stream[Int] = 1 #:: 2 #:: 3 #:: bad
    
    Try { testB.sliding(2).next }
    // res2: scala.util.Try[scala.collection.immutable.Stream[Int]] = Success(Stream(1, ?))
    
    Try { testB.grouped(2).next }
    // res3: scala.util.Try[scala.collection.immutable.Stream[Int]] = Success(Stream(1, ?))
    

    您可以使用scanLeft,而不是sliding

    val fibs: Stream[Int] = 0 #:: fibs.scanLeft(1)(_+_)
    

    scan 函数有点像fold,但会产生所有中间结果。所以你得到的是这样的:

    • 0
    • 1 = 1
    • 0 + 1 = 1
    • 1 + 1 = 2
    • 1 + 2 = 3
    • 2 + 3 = 5
    • ...

    【讨论】:

    • 谢谢,这是获取斐波那契数的另一种方法。我应该学习和练习 scenLeft。
    【解决方案2】:

    道文的清晰解释表明滑动方法无法解决问题。 我发现了另一种计算Fibonacci numbers of higher order的方法。

    /* make a Stream of Stream of integer 
    input - Stream(0, 1)
    output - Stream(0, 1), Stream(1, 1), Stream(1, 2), Stream(2, 3), ... 
    */
    def appendSum(initial:Stream[Int]):Stream[Stream[Int]] = 
      Stream.iterate(initial)(s => s.tail :+ s.sum)
    
    /* fibonacci number of higher order is original Stream + new Stream's last member */
    def nbonacci(n:Int) = { 
        val inits = Stream.continually(0).take(n-1) :+ 1
        inits.append(appendSum(inits).tail.map(_.last)) 
    }
    
    /* print out first 20 members of fibonacci, tribonacci, tetrabonacci numbers */
    (2 to 4).foreach(n => {println(s"$n -----"); nbonacci(n).take(20).foreach(println(_))})
    

    如果滑动返回 Stream,它会更干净,也许更快。

    【讨论】:

      猜你喜欢
      • 2016-08-02
      • 1970-01-01
      • 2012-01-29
      • 1970-01-01
      • 1970-01-01
      • 2015-08-26
      • 1970-01-01
      • 2017-11-18
      • 2015-06-05
      相关资源
      最近更新 更多