Générer une séquence de nombre de Fibonacci dans Scala [dupliquer]

Cette question a déjà une réponse ici:


  def fibSeq(n: Int): List[Int] = {
    var ret = scala.collection.mutable.ListBuffer[Int](1, 2)
    while (ret(ret.length - 1) < n) {
      val temp = ret(ret.length - 1) + ret(ret.length - 2)
      if (temp >= n) {
        return ret.toList
      }
      ret += temp
    }
    ret.toList
  }

donc le code ci-dessus est mon code pour générer une séquence de Fibonacci en utilisant Scala à une valeur n. Je me demande s'il y a une façon plus élégante de faire cela à Scala?

19
demandé sur nobody 2012-03-26 02:03:05

7 réponses

Il y a plusieurs façons de définir la séquence de Fibonacci, mais mon préféré est celui-ci:

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

cela crée un flux qui est évalué de façon paresseuse quand vous voulez un nombre spécifique de Fibonacci.

modifier: Tout d'abord, comme L'a souligné Luigi Plinge, le "paresseux" au début n'était pas nécessaire. Deuxièmement, allez voir sa réponse, il a fait à peu près la même chose que plus élégamment.

24
répondu Tal Pressman 2012-03-26 06:07:42

C'est un peu plus élégante:

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

avec Streams vous "prenez" un certain nombre de valeurs, que vous pouvez alors transformer en une liste:

scala> fibs take 10 toList
res42: List[Int] = List(0, 1, 1, 2, 3, 5, 8, 13, 21, 34)

mise à Jour: j'ai écrit un blog ce qui explique plus en détail le fonctionnement de cette solution, et pourquoi vous vous retrouvez avec une séquence de Fibonacci!

69
répondu Luigi Plinge 2016-05-03 13:10:25

pas aussi élégant que Streams, pas paresseux, mais taillecursive et handles BigInt (ce qui est facile à faire avec Luigis scanLeft aussi, mais pas avec tal's zip - peut-être juste pour moi).

@tailrec 
def fib (cnt: Int, low: BigInt=0, high: BigInt=1, sofar: List[BigInt]=Nil): List[BigInt] = {
  if (cnt == 0) (low :: sofar).reverse else fib (cnt - 1, high, low + high, low :: sofar) }

scala> fib (75)

res135: List [BigInt] = List(0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181, 6765, 10946, 17711, 28657, 46368, 75025, 121393, 196418, 317811, 514229, 832040, 1346269, 2178309, 3524578, 5702887, 9227465, 14930352, 24157817, 39088169, 63245986, 102334155, 165580141, 267914296, 433494437, 701408733, 1134903170, 1836311903, 2971215073, 4807526976, 7778742049, 12586269025, 20365011074, 32951280099, 53316291173, 86267571272, 139583862445, 225851433717, 365435296162, 591286729879, 956722026041, 1548008755920, 2504730781961, 4052739537881, 6557470319842, 10610209857723, 17167680177565, 27777890035288, 44945570212853, 72723460248141, 117669030460994, 190392490709135, 308061521170129, 498454011879264, 806515533049393, 1304969544928657, 2111485077978050)

5
répondu user unknown 2012-03-26 09:39:31

ma version préférée est:

def fibs(a: Int = 0, b: Int = 1): Stream[Int] = Stream.cons(a, fibs(b, a+b))

Avec les valeurs par défaut, vous pouvez simplement appeler fibs() et obtenir l'infini Stream.

je pense aussi que c'est très lisible, en dépit d'être une doublure.

Si vous voulez juste le premier n alors vous pouvez utiliser takefibs() take n et si vous en avez besoin que d'une liste fibs() take n toList.

2
répondu dvdnglnd 2016-03-24 18:03:12

Voici encore une autre approche en utilisant * Stream*s sur un intermédiaire n-uplets:

scala> val fibs = Stream.iterate( (0,1) ) { case (a,b)=>(b,a+b)  }.map(_._1) 
fibs: scala.collection.immutable.Stream[Int] = Stream(0, ?)

scala> fibs take 10 toList
res68: List[Int] = List(0, 1, 1, 2, 3, 5, 8, 13, 21, 34)
1
répondu dimitrisli 2014-03-23 05:22:56

je trouve cette implémentation plus lisible:

def fibonacci: Stream[Int] = {
    def loop(a: Int, b: Int): Stream[Int] = (a + b) #:: loop(b, b + a)
    loop(0, 1)
}
0
répondu Cristian 2015-07-26 19:39:25
def fib:Stream[Int] ={
  def go(f0: Int, f1:Int): Stream[Int] = {
    Stream.cons(f0,go(f1,f0+f1))
  }
  go(0,1)
}
0
répondu Saddam Abu Ghaida 2016-03-19 16:08:47