sucesion serie programacion ejercicios conejos biografia algoritmo scala sequence list-comprehension fibonacci

serie - Genera una secuencia de número de Fibonacci en Scala



sucesion de fibonacci conejos (7)

Hay muchas formas de definir la secuencia de Fibonacci, pero mi favorito es este:

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

Esto crea una secuencia que se evalúa perezosamente cuando desea un número de Fibonacci específico.

EDITAR: Primero, como señaló Luigi Plinge, el "flojo" al principio era innecesario. En segundo lugar, ve a ver su respuesta, prácticamente hizo lo mismo con más elegancia.

Esta pregunta ya tiene una respuesta aquí:

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 }

Entonces, lo anterior es mi código para generar una secuencia de Fibonacci usando Scala a un valor n . Me pregunto si hay una manera más elegante de hacer esto en Scala.


No es tan elegante como Streams, no es flojo, sino que es de naturaleza recursiva y maneja BigInt (lo cual es fácil de hacer con Luigis scanLeft también, pero no con Zip de Tal, tal vez solo para mí).

@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: Lista [BigInt] = Lista (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)


Aquí hay otra aproximación que usa * Stream * s en una tupla intermedia:

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)


Encuentro que esta implementación es más legible:

def fibonacci: Stream[Int] = { def loop(a: Int, b: Int): Stream[Int] = (a + b) #:: loop(b, b + a) loop(0, 1) }


def fib:Stream[Int] ={ def go(f0: Int, f1:Int): Stream[Int] = { Stream.cons(f0,go(f1,f0+f1)) } go(0,1) }


Mi versión favorita es:

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

Con los valores predeterminados puede simplemente llamar a fibs() y obtener la Stream infinita.

También creo que es muy legible a pesar de ser un trazador de líneas.

Si solo quiere la primera n entonces puede usar take como fibs() take n , y si lo necesita como una lista fibs() take n toList .


Esto es un poco más elegante:

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

Con Streams "tomas" varios valores, que luego puedes convertir en una lista:

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

Actualización: He escrito una publicación de blog que detalla más acerca de cómo funciona esta solución y por qué terminas con una secuencia de Fibonacci.