Hoy vamos a implementar la conjetura de Collatz en C. Aunque decir “implementar” la conjetura de Collatz no tiene sentido, así que mejor dicho vamos a tratar de probar la conjetura de Collatz.
Si en algún momento entramos a un ciclo infinito podríamos decir que la conjetura de Collatz es falsa, pero eso no ha pasado hasta el día de hoy.
Como sea, vamos a hacer una función que te indica las iteraciones que le llevan a un número llegar a 1 siguiendo la operación de 3N+1 si el mismo es impar, y dividiendo al número entre 2 si es par.
Además de indicar las iteraciones vamos a imprimir la secuencia de números.
Conjetura de Collatz en C
Entonces simplemente vamos a tener un número y haremos un ciclo que se va a ejecutar mientras el mismo sea distinto de 1. Dentro del ciclo vamos a comprobar si el número es par, y en caso de que así sea, lo vamos a dividir entre 2.
En caso de que el número no sea par, vamos a multiplicarlo por 3 y sumarle 1. La conjetura dice que no importa el número ya que siempre vamos a terminar en 1.
unsigned long long collatz(unsigned long long numero)
{
// https://parzibyte.me/blog
unsigned long long iteraciones = 0;
while (numero != 1)
{
if (numero % 2 == 0)
{
numero = numero / 2;
}
else
{
numero = (3 * numero) + 1;
}
// Si no quieres imprimir, simplemente elimina o comenta la siguiente línea
printf("%llu,", numero);
iteraciones++;
}
return iteraciones;
}
Nota: si por alguna razón el ciclo se repitiera infinitamente, estarías comprobando que la conjetura es falsa (yo he probado hasta con 9000000
y siempre llega a 1; otros han probado con números mucho más grandes y sigue cumpliéndose).
Por cierto, he usado el tipo de dato unsigned long long
para manejar números grandes. Si tú quieres o te confunde usar este tipo de dato puedes usar simplemente un int
, aunque debes tener cuidado con los desbordamientos.
Modo de uso
El modo de uso es el siguiente. Definimos el número del cual queremos la sucesión, invocamos a la función y obtenemos el resultado, que será el número de iteraciones que llevó para llegar a 1.
Recuerda que la función va a imprimir la sucesión de números cuando la invoques.
unsigned long long numero = 27;
unsigned long long iteraciones = collatz(numero);
printf("\nLas iteraciones para llegar a 1 desde %llu fueron: %llu\n", numero, iteraciones);
Al ejecutarlo con el número que ves, la salida es:
Y podemos hacer más pruebas. Por ejemplo, entre el 2 y el 9000000, ¿Cuál número da la mayor cantidad de iteraciones para llegar al 1? y no es 9000000, sino 8400511
como podemos comprobar a continuación:
int main()
{
unsigned long long numero;
unsigned long long maximoNumero = 0, maximasIteraciones = 0;
for (numero = 2; numero < 9000000; numero++)
{
unsigned long long iteraciones = collatz(numero);
if (iteraciones > maximasIteraciones)
{
maximasIteraciones = iteraciones;
maximoNumero = numero;
}
}
printf("Las mayores iteraciones fueron %llu para %llu\n", maximasIteraciones, maximoNumero);
}
La salida es la siguiente (si lo vas a probar, comenta la línea que imprime la sucesión):
Poniendo todo junto
El código completo junto con su implementación en el main
queda así:
#include <stdio.h>
unsigned long long collatz(unsigned long long numero)
{
// https://parzibyte.me/blog
unsigned long long iteraciones = 0;
while (numero != 1)
{
if (numero % 2 == 0)
{
numero = numero / 2;
}
else
{
numero = (3 * numero) + 1;
}
// Si no quieres imprimir, simplemente elimina o comenta la siguiente línea
printf("%llu,", numero);
iteraciones++;
}
return iteraciones;
}
int main()
{
unsigned long long numero = 27;
unsigned long long iteraciones = collatz(numero);
printf("\nLas iteraciones para llegar a 1 desde %llu fueron: %llu\n", numero, iteraciones);
return 0;
}
Por aquí te dejo más tutoriales de programación en C.