
Recientemente he aprendido que existe una sucesión muy "parecida" a la famosísimasucesión de Fibonacci: se trata de lasucesión de Lucas.
Lasucesión de Fibonacci se obtiene comenzando con 0 y 1, y para los siguientes números, simplemente se suman los dos anteriores:
0, 1, 1, 2, 3, 5, 8, 13, 21...
Lasucesión de Lucas se obtiene comenzando con 2 y 1, y al igual que con la sucesión de Fibonacci, se suman las dos posiciones anteriores para cada nueva posición.
2, 1, 3, 4, 7, 11, 18, 29, 47...
Si lo implementamos en Python, tendremos dos funciones muy similares:
"""Sucesión de Lucas. :param n: La posición del número a calcular. :return: Una lista con las n primeras posiciones de Lucas."""lucas=lambdan: \[]ifn<0else \[2]ifn==0else \[2,1]ifn==1else \(l_lucas:=lucas(n-1))+[l_lucas[-1]+l_lucas[-2]]"""Sucesión de Fibonacci. :param n: La posición del número a calcular. :return: Una lista con las n primeras posiciones de Fibonacci."""fibo=lambdan: \[]ifn<0else \[0]ifn==0else \[0,1]ifn==1else \(l_fibo:=fibo(n-1))+[l_fibo[-1]+l_fibo[-2]]
Para obtener las listas con las sucesiones empleamos lambdas, la expresiónif, y el nuevooperador de asignación, de manera que solo tengamos que calcular la lista anterior una sola vez.
En el enlace anterior puedes aprender sobre este operador, solo tienes que bajar casi hasta el final.
Como ya sabemos, la forma de trabajar con lambdas es emplear la recursividad cada vez que queramos algo parecido a un bucle. La recursividad solo funciona si tenemos un caso base (las dos posiciones inicialesn == 0 yn == 1), y un caso normal (el resto de posiciones paran > 1).
Añadimos un caso base "extra" (n < 0), por si se da el caso de algún usuario "travieso".
La forma de generar ambas sucesiones es muy similar. Para ambas tenemos dos valores iniciales, que deben ser devueltos si intentamos obtener las dos primeras posiciones: es decir, la 0 y la 1.
A partir de ahí, simplemente concatenamos la lista anterior con la suma de las posiciones última y penúltima de dicha lista.
De hecho... son demasiado parecidas... ¿no podríamos crear una función única, que tomase como parámetro las dos primeras posiciones de la sucesión a generar? Ya de paso, ¿podemos crear una función a la que se le pasen lasn primeras posiciones de la lista inicial de una sucesión para generar los números de Lucas, de Fibonacci, y deTribonacci?
Veamos, la funciónsucc()
solo hay que devolver, dada una lista iniciall_init y su número de posicioneslen_l_init...
- paran < 0, la lista vacía,
[]
- paran < i, la listal_init hastan + 1 (porque los índices en Python comienzan en 0):
l_init[:n + 1]
- para el resto de casos
n >= len_l_init
,- se calcula la lista para
succ(n - 1)
, y se calcula el nuevo elemento, que es el resultado de sumar laslen_l_init últimas posiciones.
- se calcula la lista para
Pues ya lo tenemos. Como el código ya es más
complicado que un par de líneas, crearemos una función "de verdad".
defsucc(l_init,n):""" Sucesión genérica. :param l: La lista inicial de valores. :param n: La posición del número a calcular. :return: Una lista con las n primeras posiciones de Lucas, Fibonacci o Tribonacci."""len_l_init=len(l_init)toret=[]matchn:case_ifn<0:toret=[]case_ifn<len_l_init:toret=l_init[:n+1]case_:# Sucesión hasta la posición anteriortoret=succ(l_init,n-1)# Calcula la nueva posicióntoret+=[sum(toret[-len_l_init:])]returntoret
¡Python mola!
Estamos empleando la nueva estructura depattern matching, que, para que nos entendamos, hablando mal y rápido es comoswitch en C, pero mucho más potente. Aquí solo empleamos una fracción de sus capacidades, concretamente le añadimos condiciones a las etiquetas de los primeros dos casos. Sustituimos el nombre de lo que sería la nueva variable por _ porque en realidad, no nos interesa, ya lo tenemos enn.
Utilicemos el código:
defmain():foriinrange(-1,10):print(f"Succ Fibo -{succ([0,1],i)=}")print()foriinrange(-1,10):print(f"Succ Lucas -{succ([2,1],i)=}")if__name__=="__main__":main()
Y efectivamente, el resultado es:
ucc Fibo - succ([0, 1], i)=[]Succ Fibo - succ([0, 1], i)=[0]Succ Fibo - succ([0, 1], i)=[0, 1]Succ Fibo - succ([0, 1], i)=[0, 1, 1]Succ Fibo - succ([0, 1], i)=[0, 1, 1, 2]Succ Fibo - succ([0, 1], i)=[0, 1, 1, 2, 3]Succ Fibo - succ([0, 1], i)=[0, 1, 1, 2, 3, 5]Succ Fibo - succ([0, 1], i)=[0, 1, 1, 2, 3, 5, 8]Succ Fibo - succ([0, 1], i)=[0, 1, 1, 2, 3, 5, 8, 13]Succ Fibo - succ([0, 1], i)=[0, 1, 1, 2, 3, 5, 8, 13, 21]Succ Fibo - succ([0, 1], i)=[0, 1, 1, 2, 3, 5, 8, 13, 21, 34]Succ Lucas - succ([2, 1], i)=[]Succ Lucas - succ([2, 1], i)=[2]Succ Lucas - succ([2, 1], i)=[2, 1]Succ Lucas - succ([2, 1], i)=[2, 1, 3]Succ Lucas - succ([2, 1], i)=[2, 1, 3, 4]Succ Lucas - succ([2, 1], i)=[2, 1, 3, 4, 7]Succ Lucas - succ([2, 1], i)=[2, 1, 3, 4, 7, 11]Succ Lucas - succ([2, 1], i)=[2, 1, 3, 4, 7, 11, 18]Succ Lucas - succ([2, 1], i)=[2, 1, 3, 4, 7, 11, 18, 29]Succ Lucas - succ([2, 1], i)=[2, 1, 3, 4, 7, 11, 18, 29, 47]Succ Lucas - succ([2, 1], i)=[2, 1, 3, 4, 7, 11, 18, 29, 47, 76]
Top comments(0)
For further actions, you may consider blocking this person and/orreporting abuse