Streamフィボナッチ数列の作成

1821 ワード

Streamストリームは、1つのヘッダー(現在の要素)と1つのテーブルの末尾(セットの残りの部分)を含む再帰的なデータ構造です.1つの関数と関数の再帰コールを使用してストリームを構築できます.
Stream.cons(head,tail)headはStreamのヘッダであり、tailは残りの要素である
例:整数値を指定し、連続的に増加する整数セットを作成します.
scala> def inc(i:Int):Stream[Int] = Stream.cons(i,inc(i+1))
scala> inc(1).take(5).toList
res0: List[Int] = List(1,2,3,4,5)

フィボナッチ数列の作成
scala> def fabonacciStream(last:Int,now:Int):Stream[Int] = Stream.cons(now,fabonacciStream(now,last+now))
scala> fabonacciStream(0,1).take(20).toList
res1: List(1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181, 6765)

構想:Streamではヘッダ要素しか取れませんが、フィボナッチには最末端の2つの要素が必要です.
再帰的な関数には最末端の2つの要素を入力し、Streamの末尾に計算して入れる必要があります.
fabonacciStream(0,1).take(5)の計算プロセス:
Stream.cons( 1, fabinacciStream( 1, 0+1 => 1))//List(1)
Stream.cons( 1, Stream.cons( 1, fabinacciStream( 1, 1+1 => 2)))//List(1,1)
Stream.cons( 1, Stream.cons( 1, Stream.cons( 2, fabinacciStream( 2, 1+2=>3))))//List(1,1,2)
Stream.cons( 1, Stream.cons( 1, Stream.cons( 2, Stream.cons(3, fabinacciStream( 3, 2+3 => 5)))))//List(1,1,2,3)
Stream.cons( 1, Stream.cons( 1, Stream.cons( 2, Stream.cons(3, Stream,cons( 5, fabinacciStream( 5, 3+5 =>8))))))//List(1,1,2,3,5)
もう一つの興味深いフィボナッチ数列の作成方法も見られます
scala>  lazy val fib: Stream[BigInt] = Stream.cons(1, Stream.cons(1, (fib zip fib.tail).map(p => p._1 + p._2)))

scalaのzip操作
zip:zip[B](that:GenIterable[B]):List[(A,B)]は別のリストとファスナー操作を行い、対応する位置の要素を1つのpairに構成し、返されるリスト長は2つのリストの中で短いものである
scala> val list = List(1,2,3,4,5)
scala> list zip list.tail
res2: List[(Int,Int)] = List((1,2),(2,3),(3,4),(4,5))

参考記事
ScalaにおけるStreamの応用シーンとその実現原理
ScalaのStream
Scalaの強力な集合データ操作例