Saltar al contenido
Regresar

Factorización Prima Rápida: Encuentra el Factor Primo Más Pequeño

Publicado:  a las  05:07 p.m.

Atrévete a desafiar el número más grande, el primo más escurridizo no se resistirá.

🔮 Enunciado del Problema

Necesitamos una función capaz de desentrañar la estructura de cualquier entero positivo, revelando su constitución en forma de factores primos. Pero la tarea no termina ahí: nuestro objetivo final es identificar y retornar el factor primo más diminuto presente en esta descomposición.

Aquí las especificaciones:

Parámetros:

Retorna:

Ejemplo:

>>> smallest_prime_factor_master(13195)
5
>>> smallest_prime_factor_master(600851475143)
71

NOTA: La eficiencia es primordial. El código debe estar altamente optimizado para asegurar una ejecución inferior a 0.1 segundos, incluso para números de gran magnitud.

🧩 Resolución Paso a Paso

La estrategia se basa en la generación dinámica de números primos y su aplicación sucesiva en la división del número original hasta su completa factorización. La búsqueda del divisor primo más pequeño se optimiza utilizando la propiedad de que un número no primo siempre tendrá un factor menor o igual a su raíz cuadrada.

from math import floor, sqrt

Importamos las funciones floor y sqrt del módulo math. sqrt se utiliza para calcular la raíz cuadrada de un número, mientras que floor se utiliza para redondear un número hacia abajo al entero más cercano. Esta optimización es crucial para limitar la cantidad de iteraciones necesarias al verificar si un número es primo. 🧠

def is_prime(num):
	if num == 2:
		return True
	if not num % 2 or num == 1:
		return False
	for n in range(3, floor(sqrt(num)) + 1, 2):
		if not num % n:
			return False
	return True

La función is_prime(num) verifica si un número dado num es primo. Primero, maneja los casos especiales de 2 (que es primo) y los números pares (mayores que 2) e 1 (que no son primos). Luego, itera solo sobre los números impares hasta la raíz cuadrada de num. Si encuentra un divisor, retorna False; de lo contrario, retorna True.

def generate_prime_numbers():
	n = 2
	while True:
		if is_prime(n):
			yield n
		n += 1

generate_prime_numbers() es un generador que produce números primos de forma infinita. Comienza con 2 y va incrementando n en cada iteración, utilizando is_prime(n) para determinar si n es primo. Si lo es, yield n retorna el valor y pausa la ejecución, manteniendo el estado para la siguiente llamada. Es importante notar que el uso de yield convierte la función en un generador, lo que permite generar números primos bajo demanda, evitando calcularlos todos de antemano y ahorrando memoria. 💫

def smallest_prime_factor_master(num):
	"level: master; points: 10; time: 0.1"
	factors = []
	while num != 1:
		for p in generate_prime_numbers():
			if not num % p:
				factors.append(p)
				num //= p
				break
	return min(factors)

Finalmente, smallest_prime_factor_master(num) implementa la lógica principal. Inicializa una lista factors. Luego, mientras num sea diferente de 1, itera sobre los primos generados por generate_prime_numbers(). Cuando encuentra un factor primo p, lo agrega a factors, divide num entre p y rompe el bucle interno con break. Al finalizar el bucle principal, retorna el mínimo valor de la lista factors.

Solución Completa:

from math import floor, sqrt

def is_prime(num):
	if num == 2:
		return True
	if not num % 2 or num == 1:
		return False
	for n in range(3, floor(sqrt(num)) + 1, 2):
		if not num % n:
			return False
	return True

def generate_prime_numbers():
	n = 2
	while True:
		if is_prime(n):
			yield n
		n += 1

def smallest_prime_factor_master(num):
	"level: master; points: 10; time: 0.1"
	factors = []
	while num != 1:
		for p in generate_prime_numbers():
			if not num % p:
				factors.append(p)
				num //= p
				break
	return min(factors)

🧠 Conceptos Clave

La clave para el rendimiento reside en el uso eficiente de generadores. Estos no calculan todos los primos de antemano, sino que los producen bajo demanda, ahorrando memoria y tiempo de cómputo. La división entera (//) es crucial para truncar el resultado a un entero, evitando errores de punto flotante que podrían surgir al trabajar con números grandes. La factorización prima se realiza de forma iterativa, dividiendo el número original hasta obtener 1. La función is_prime está optimizada aprovechando el hecho de que solo es necesario verificar divisibilidad hasta la raíz cuadrada del número. Finalmente, la complejidad algorítmica de la solución es O(sqrt(N)), donde N es el número de entrada, debido a la verificación de primalidad optimizada y a la división sucesiva del número.

💫 Reflexiones Finales

Una posible mejora sería implementar un cache de números primos ya calculados, lo que evitaría recalcularlos en iteraciones posteriores, especialmente útil si se llama la función múltiples veces con números similares. Otra optimización podría ser el uso de un algoritmo de generación de números primos más eficiente, como la Criba de Eratóstenes, aunque adaptada para funcionar como un generador.

¿Sabías que…? El Teorema Fundamental de la Aritmética establece que todo entero mayor que 1 puede ser expresado como un producto único de números primos, sin importar el orden de los factores. Este teorema es la base teórica de la factorización prima.

Espero que este recorrido por la factorización prima haya sido tan revelador como una expedición a las profundidades de los números. ¡Anímate a explorar más algoritmos y optimizaciones en el fascinante mundo de la programación! Si te ha gustado, déjame un comentario y comparte este artículo con tus colegas. ¡Sigue aprendiendo y programando! ✨



Publicación anterior
Números de Kaprekar: Descubre si un número es mágico (Python)
Siguiente publicación
Capicúas y Productos: Encuentra el Mayor con Python