Como cualquier usuario que no está ligado a la informática en el sentido más estricto de la palabra; pero, con un inmenso interés por todo lo que atañe a la Ciencia y Tecnología —sobre todo lo referido a la computación— siempre estoy buscando algo que aprender en mis ratos libres.
En la mayoría de los casos tiene que que ver con este mundo de las Tecnologías Libres y últimamente en lo particular con los lenguajes de programación. El primer escollo era elegir un lenguaje determinado para comenzar, y cuando no tienes claro el ¿por qué? o ¿para qué? lo vas a estudiar, la elección puede no ser tan sencilla. Obviamente en mi caso no fue tan difícil después de todo, luego de un tiempo de análisis escogí Python.
En un comienzo había empezado a estudiar C viendo una serie de videos tutoriales enfocados en el libro C Premier Plus impartidos por Richard Couture en LinuxCabal —dicen que si dominas C, el lenguaje Python es más fácil de aprender, no creo que sea tanto así. Al tiempo, desistí de C para enfocarme solo en Python.
Igualmente no importa lo complejo que pueda ser un lenguaje en particular, si estás motivado en estudiarlo los resultados pueden ser muy alentadores. Particularmente cambié a Python debido a las siguientes razones:
- Se ha vuelto un lenguaje muy pero muy popular, con una inmensa comunidad.
- Extensa documentación para usuarios avanzados y principiantes, tanto en inglés como en español —muy importante para alguien que no estudió informática—.
- Código extensible, potente y muy legible.
- Otras razones que tienen que ver con el aprendizaje de Django y otros Frameworks de Python dedicados al desarrollo web.
- La curva de aprendizaje de Python es más corta.
- Con C en algún momento me iba a estrellar.
Estoy contento con Python. ¿Qué sigue?
En este punto ya estoy algo familiarizado con el lenguaje, aunque sea muy poco lo estudiado, ahora me encuentro en la búsqueda de excusas para escribir algunas líneas de código y es aquí donde renace otra obsesión que siempre he tenido: «La sucesión de Fibonacci».
Esto no es nada nuevo, hay infinidad de artículos sobre ello —incluso en los libros de Python—, yo no estoy inventando nada aquí. Simplemente quiero compartir con la comunidad desde mi escasa experiencia como obtener los números de la sucesión de Fibonacci utilizando Python. Pero para ello primero debemos conocer un poco acerca de Fibonacci.
Sucesión de Fibonacci
Según Wikipedia:
En matemáticas, la sucesión de Fibonacci (a veces llamada erróneamente serie de Fibonacci) es la siguiente sucesión infinita de números naturales: 0,1,1,2,3,5,8,13,21,34,55,89,144,233,377,610,987,1597
La sucesión comienza con los números 0 y 1, y a partir de estos, «cada término es la suma de los dos anteriores», es la relación de recurrencia que la define.
A los elementos de esta sucesión se les llama números de Fibonacci. Esta sucesión fue descrita en Europa por Leonardo de Pisa, matemático italiano del siglo XIII también conocido como Fibonacci.
Tiene numerosas aplicaciones en ciencias de la computación, matemáticas y teoría de juegos. También aparece en configuraciones biológicas, como por ejemplo en las ramas de los árboles, en la disposición de las hojas en el tallo, en las flores de alcachofas y girasoles, en las inflorescencias del brécol romanesco y en la configuración de las piñas de las coníferas.
Utilizando Python
Una vez entendido los conceptos básicos ya podemos entrar en materia de programación. He visto un centenar de scripts en Python sobre este tema, algunos utilizando 4 o 5 líneas, otros más de 10. Con estructuras de ciclo: for, while, o simplemente utilizando variables como: «ultimo =, penúltimo =» etc.
Todos los códigos realizados en Python llegan al resultado satisfactoriamente, sin embargo, la optimización no es la misma en todos los casos. Personalmente me encuentro en un dilema; al no tener un dominio aceptable de Python mi razonamiento para escribir el código se reduce a un procedimiento muy vertical, típico de un principiante como yo —nada de bucles o ciclos y otros artilugios—.
Esto iba a dar como resultado un script largo y aburrido que horrorizaría a más de un «pythoniano», por lo que decidí utilizar un código existente y modificarlo mínimamente. El código en cuestión forma parte de la página oficial de Python.
Pero antes vamos a instalar Python en el caso de que no esté presente en nuestro sistema:
Nota: Utiliza el comando apropiado para tu distribución.
Debian GNU/Linux y derivadas:
sudo apt install python3
Alternativamente podemos instalar el entorno de desarrollo de Python:
sudo apt install idle3
Manos a la obra
El código mostrado en el sitio de Python se ve de esta forma:
def fib(n): a, b = 0,1 while a < n: print(a, end=' ') a, b = b, a+b print() fib(1000)
Como resultado, la sucesión de Fibonacci:
0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987
Que se puede interpretar aquí:
En la primera línea se define una función fib con un parámetro n el cual va a tomar un valor dado. Luego se definen dos variables locales cuyos valores son 0 y 1; como se explicó más arriba se debe partir de estos valores como predeterminados para que sea una sucesión de Fibonacci, las variables también se podrían haber asignado de la siguiente forma —más usual en un novato—:
def fib(n): a = 0 b = 1
A partir de aquí se utiliza una condición, en este caso utilizando el bucle while. Python evalúa la condición y, si es verdadero (True), ejecuta las instrucciones contenidas —identadas— en el cuerpo del bucle. Este proceso se repite tantas veces como la condición sea cierta. Cuando la condición dé como resultado falso (False) —es decir que no se cumple— el cuerpo del bucle terminará de ejecutarse y continuará con el resto de las instrucciones.
while a < n: print(a, end=' ') a, b = b, a+b
Va a imprimir los valores arrojados por la variable a en repetidas veces mientras la condición sea a < n, es decir verdadero (True), cuando verifique que a = n la condición pasará a falso (False) terminando la ejecución del programa. Los valores de a y b son obtenidos utilizando la asignación paralela, aún no me acostumbro a esta instrucción. La línea que imprime los valores de la sucesión de Fibonacci es print(a, end=’ ‘).
Y para finalizar, en la primera línea vimos que la función def fib(n) cuyo parámetro n tomará un valor asignado: 1000 en este caso, pero puede ser cualquier valor que nosotros le asignemos, este es representado en la última línea de código. Aquí es dónde se llama a la función que creamos:
fib(1000)
Este código tal cual se presenta no me resultaba atractivo, si bien consigue el propósito era algo extraño para mi. Supongamos que yo quisiera 18 términos de la sucesión en vez de 17 como está propuesto el script, obviamente el siguiente valor a …987 es superior a 1000 —por eso terminó ahí—, vasta sumar 987 con el anterior para tener una vaga idea del próximo término; pero, ¿si quiero más términos? 25, 30. Estaría adivinando todo el tiempo hasta dar con el número de términos que deseo.
Para 18 términos el valor que sigue es 1597, así que cualquier valor comprendido entre 1598 y 2584 dará ese número:
fib(2015)
El resultado:
0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597
Este método lo que te permite es elegir un límite máximo de la sucesión, por ejemplo si quieres que tu número final no sea mayor que 10000 entonces utilizas fib(10001). Aunque el valor arrojado será 6765, sin embargo no se puede especificar el número de términos, por ahora.
Modificando el código
Algo que no quería estar haciendo todo el tiempo era modificar el script para designar un límite máximo en la línea fib(1000), aquí es dónde podría decirse que empiezo a interactuar con Python a mi manera, la cual no es precisamente la más acertada, probablemente.
Simplemente agregué una línea para que el programa me preguntara el límite máximo de la sucesión, eso es todo:
def fib(n): a, b = 0,1 while a < n: print(a, end=' ') a, b = b, a + b m = int(input("Ingresa límite máximo de la sucesión: ")) fib(m)
La línea int(input()) me pide una entrada (input), véase que está precedido por int es decir que el valor a ingresar será un entero, el cual es asignado a la variable m —puede ser cualquier nombre de variable—.
Por último una vez más llegamos a la instrucción dónde se llama a la función, fib(m), en este caso contiene como argumento m y no 1000, es decir la variable que asignamos anteriormente, y cuyo valor va a ser capturado finalmente por la primera línea del código def fib(n):.
Utilizando número de términos
Lo que a mi más me interesaba como comenté en un principio, era designar el número de términos que deseaba calcular para obtener la sucesión de Fibonacci. Ahora ya no sabemos cual va a ser el último valor en la sucesión, por ejemplo para 30 términos. Pero me da el control de decidir al menos cuantos números de la sucesión quiero imprimir, además de ser más útil en el caso de crear una tabla.
a, b = 0,1 for i in range(30): print(a, end=' ') a, b = b, a + b
Una vez más alteré el código original, esta vez utilizando la sentencia for en lugar de while. Ambas generan un bucle, sin embargo a diferencia de while, for no hace una operación booleana para determinar si es verdadero o falso, simplemente inicia un ciclo ejecutando las líneas de códigos contenidas dentro del bucle for tantas veces como sea especificado —iteración—, aquí utilicé un rango de 30 mediante la función range().
for i in range(30):
El resultado:
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
Buscando flexibilidad
Aquí también introduje una entrada (input) para no estar modificando el código todo el tiempo:
def fib(n): a, b = 0,1 for i in range(n): print(a, end=' ') a, b = b, a + b m = int(input("Ingrese número de términos para la sucesión? ")) fib(m)
También lo podría hacer así:
n = int(input("Ingrese número de términos para la sucesión? ")) a, b = 0,1 for i in range(n): print(a, end=' ') a, b = b, a + b
Combinar ambos códigos:
sucesion = input("Ingrese (S) para límite máximo de la sucesión \ [por omisión número de términos]? ") if sucesion == 'S': def fib(n): a, b = 0,1 while a < n: print(a, end=' ') a, b = b, a + b m = int(input("Límite máximo~> ")) fib(m) else: n = int(input("Número de términos~> ")) a, b = 0,1 for i in range(n): print(a, end=' ') a, b = b, a + b
En la primera línea se me pregunta en que me quiero basar para el cálculo de la sucesión de Fibonacci, el dato introducido es asignado a la variable sucesion. En la segunda línea agrego la sentencia if la cuál hace una comparación y en base a ello toma una decisión.
En este caso compara el dato almacenado en la variable sucesion con S, si la condición se cumple, es verdadero (True), ejecuta el bloque de código identado en if. Si no se cumple ejecuta el siguiente bloque de código identado correspondiente a else, el cual hace referencia al cálculo basado en el número de términos para obtener los números de Fibonacci.
Depurando mi código
sucesion = input("Ingrese: (S) límite máximo, (N) número de \ términos? ") if sucesion == 'S': def fib(n): a, b = 0,1 while a < n: print(a, end=' ') a, b = b, a + b m = int(input("Límite máximo~> ")) fib(m) elif sucesion == 'N': a, b = 0,1 n = int(input("Número de términos~> ")) for i in range(n): print(i, a) a, b = b, a + b else: print("Debe ingresar S o N")
Por último he minimizado las opciones de entrada a dos posibilidades «S» o «N» utilizando la sentencia elif (else if) para evaluar una segunda condición, y como último recurso en caso de que ambas condiciones den como resultado falso continúa con la sentencia else. Es decir que si no ingreso S o N, cualquier otro carácter imprimirá Debe ingresar S o N. También modifiqué print(i, a), el cual imprime la cantidad de términos y los valores de la sucesión de Fibonacci verticalmente.
Conclusiones
Utilicé un ejemplo muy común basado en Implementación Iterativa cuyas modificaciones fueron muy pocas en realidad, estoy más que seguro que el código se puede optimizar mucho mejor.
Sin embargo para comenzar ha resultado muy entretenido para mi desde el punto de vista de un principiante. Hay muchos ejemplos que pueden ser punto de partida para practicar en el Python Shell (IDLE) y la sucesión de Fibonacci.
Sucesión de Fibonacci en la naturaleza:
Consigna:
Escribe tu código para obtener la sucesión de Fibonacci en tu lenguaje preferido o modifica el descrito por mi y compártelo con nosotros, procura utilizar correctamente las identaciones o sangrías —en los lenguajes que lo requieran— para que otros puedan copiar/pegar.
Fuente:
http://www.ecured.cu/Fibonacci
https://es.wikipedia.org/wiki/Sucesi%C3%B3n_de_Fibonacci
http://edupython.blogspot.com.ar/2013/07/los-numeros-de-fibonacci.html
https://cuestionesmatematicas.wordpress.com/2015/02/22/
http://visionesdelamatrix.blogspot.com.ar/2015/06/la-espiral-de-fibonacci-de-verdad-todo.html
Aqui una implementacion en Cor
bah se me olvido encerrar el condigo dentro de un PRE
por favor, algun admin pudiera editarlo?
No se ve muy bonito porque no tengo idea la razón salen 2 cuadros … pero ya esta puesto
Mi código en Python de la función fibonacci usando recursividad:
def fib(n):
if 0 == n or n == 1:
return n
return fib(n - 1) + fib(n - 2)
La versión de recursividad ya se queda algo alta para los usuarios que nunca han tenido que programar y el concepto de recursividad les puede traer un verdadero dolor de cabeza no obstante… de las que he visto esa es mi solución favorita, es cierto que gastas un tanto mas de memoria pero optimizas el tiempo de respuesta 😉
No es muy buena, esa función para fibonacci, esta que he hecho es más eficiente:
def fibonacci(n,a=0,b=1):
while n!=0:
return fibonacci(n-1,b,a+b)
return a
La etiqueta pre no está funcionando en los comentarios.
si… en realidad tuve que usar la etiqueta Code para que se viera así y poder definir el identado (tan importante en Python)
La etiqueta pre no se activa en comentarios, a menos que en el archivo function.php le digamos a la plantilla que si lo haga.
Todavía se puede reducir un poco más:
def fib(n):
if 0 <= n <= 1: return n
return fib(n - 1) + fib(n - 2)
Recursiva en CoffeeScript:
fib = (n) -> if n<=0 or n<=1 then n else fib(n-1) + fib(n - 2)