0

Here is a Scala stream to calculate the Fibonacci sequence :

    import scala.math.BigInt

    object fib extends App {

      val fibs: Stream[BigInt] = BigInt(0) #:: BigInt(1) #:: fibs.zip(
        fibs.tail).map(n => {
          n._1 + n._2
        })
    }
  fibs take 5 foreach println
  fibs take 6 foreach println

src : http://www.scala-lang.org/api/current/index.html#scala.collection.immutable.Stream

Instead of taking the first n numbers in the sequence how to sum the first n numbers using a stream , and return this sum ?

I could introduce a var sum like this :

object fib extends App {

    var sum = 3;
  val fibs: Stream[BigInt] = BigInt(0) #:: BigInt(1) #:: fibs.zip(fibs.tail).map(n => {

      sum = n._1.toInt + n._2.toInt
      n._1 + n._2

    })

  fibs take 5 foreach println

}

And then somehow check this summed value. But this is not a good solution.

Update : I'm attempting to provide the summed value and return values that compute this sum, not sum the actual stream.

So takeSum(7) will return '0,1,1,2,3'

Assumption is that the n value sum will contain a subset of the fib sequence

blue-sky
  • 51,962
  • 152
  • 427
  • 752

3 Answers3

4

You can just use the sum-method on Stream. It will work with all types that have an implicit Numeric[T] implementation available (such as Int, Long, Double, BigInt and so on).

fibs.take(5).sum
marstran
  • 26,413
  • 5
  • 61
  • 67
  • I'm attempting to provide the summed value and return values that compute this sum, not sum the actual stream. I've updated question, apologies for ambiguity – blue-sky Sep 09 '16 at 09:51
0
def takeSum(n:Int) = fib.scanLeft(List[BigInt]()){(b,a)=> a::b}
                        .find(_.sum==n)
                        .get
                        .reverse
 takeSum(7)  //> res0: List[BigInt] = List(0, 1, 1, 2, 3)

The scanLeft builds prefixes of the stream (with the prefix in reverse order), then it's just a matter of finding the one with the right sum. If your assumption is that the n value will be the sum of a subset of the fib sequence is not valid, it will not terminate! You could change it to >= if that's important

The Archetypal Paul
  • 41,321
  • 20
  • 104
  • 134
0

Sounds like you want something along the lines of...

fibs.takeWhile(f => fibs.takeWhile(_ <= f).sum <= n)

...where n is the target sum.

Not a terribly efficient implementation but I think it gets the job done.

Or, alternatively.

fibs.take( fibs.tail.scan(0:BigInt)(_+_).indexWhere(_>n) )

A little more verbose but a little less repetition of effort.

jwvh
  • 50,871
  • 7
  • 38
  • 64