Problema nº 25 del Proyecto Euler pregunta:
¿Cuál es el primer término de la secuencia de Fibonacci que contiene 1000 dígitos?
La forma de resolverlo por fuerza bruta es simplemente decirle al ordenador que genere números de Fibonacci hasta que encuentre el primero que tenga 1000 dígitos. Yo quería buscar una solución más matemática que no requiriera tantos cálculos.
Inicialmente, esperaba que al graficar los números de Fibonacci (mapeando el número en sí al número de dígitos) obtendría una gráfica logarítmica. Sólo tracé los primeros y la secuencia parecía más bien una progresión lineal (espero que ese sea el término matemático correcto; me refiero a algo similar a y=x funciones).
También me he dado cuenta de que, aproximadamente, cada cinco números el número de cifras se incrementa en 1 - excepto los números de cuatro cifras (sólo hay cuatro) y los de una cifra (si cuentas el primer 1, hay seis).
1,1,2,3,5,8 13,21,34,55,89 144,233,377,610,987 1597,2584,4181,6765 10946,...
Así, el primer número con siete dígitos sería n=5⋅(7−1) que resultó ser correcta. Sin embargo, a partir del décimo dígito, el comportamiento de la secuencia cambia (o mejor dicho, se hace evidente que no es lineal). El primer número con 10 dígitos no es 5⋅(10−1) pero 5⋅(10−1)−1 .
Si se traza la secuencia para números aún más grandes (de nuevo, números asignados a su número de dígitos), se obtiene una curva logarítmica muy ligera. Por ejemplo, el primer número con 1000 dígitos es 5⋅(1000−43) ( WolframAlpha ).
Mi pregunta es,
¿Cómo se puede abstraer el comportamiento de la secuencia de Fibonacci de manera que el problema se pueda resolver de forma más elegante, en lugar de utilizar el algoritmo de fuerza bruta?
Editar: En cuanto a la eficiencia
La pregunta, la hice principalmente para satisfacer mi curiosidad. Hacer esto por fuerza bruta es probablemente la mejor manera en una aplicación del mundo real (los ordenadores pueden hacerlo rápido y el código es más claro). Pero (de nuevo, sólo por entretenimiento) la solución más eficiente puede seguir siendo utilizar una fórmula matemática para encontrar el índice del número que se busca; he aquí por qué:
- Los condicionales son caros. Hacer menos de ellos siempre es bueno, y el enfoque de fuerza bruta requiere que usted haga una comprobación en cada número que genera.
- Algunos lenguajes (como C++ y D) permiten hacer trucos como generar parte de la secuencia de Fibonacci en tiempo de compilación (ver meta-programación). Esto significa menos trabajo en tiempo de ejecución, aunque hay que admitir que esto también podría aplicarse al enfoque de fuerza bruta.
No hacer comprobaciones sobre los números, así como generar muchos de ellos en tiempo de compilación, puede hacer que el algoritmo sea significativamente más rápido (pero sólo en un sentido teórico; la mayoría de los ordenadores de hoy en día son lo suficientemente rápidos como para que ningún humano note la diferencia a menos que haga los cálculos un par de veces por segundo).
Además, el proceso de contar los dígitos de un número -requerido por el enfoque de fuerza bruta- es en sí mismo bastante caro, tanto si se utiliza el ⌈log10n⌉ o el algoritmo n\mod10 algoritmo.