Estoy aprendiendo Python en este momento y para darme razones para aplicar lo que estoy aprendiendo, estoy teniendo problemas con algunos de los problemas del Proyecto Euler.
Actualmente estoy en el número 3, que es determinar el factor primo más alto de dicho número.
He deducido que probablemente necesito tener dos algoritmos, uno para determinar la originalidad y el segundo, que implicaría encontrar factores del número.
Así que he estado leyendo sobre artículos de Wiki . Tratando de determinar cuál podría ser el mejor algoritmo para usar y cómo hacerlo.
Pero ha pasado un tiempo desde que hice una programación basada en matemáticas y estoy luchando por comenzar en alguna parte.
Estaba buscando usar el método de factorización de Fermat con la inclusión de Trial by Division, pero no quiero hacer algo demasiado complicado. No busco descifrar RSA. Solo quiero dos algoritmos adecuados para mi problema y ahí está mi pregunta.
¿Qué algoritmos usaría para probar la primalidad / factorización de un número que sea adecuado para el problema en cuestión?
Editar
Gracias a todos por sus respuestas y puntos de vista, han sido de gran ayuda. Voté todos los que fueron útiles, ya sea a través de consejos o de sus propias experiencias con Euler. El que marqué como correcto fue simplemente el más útil, ya que me dio un lugar adecuado para comenzar, que fue un empujón en la dirección correcta. Gracias de nuevo =)
fuente
Respuestas:
Mi enfoque para esos problemas suele ser este: construir el algoritmo más simple posible para resolverlo, que generalmente es un enfoque ingenuo de fuerza bruta, y luego probar / calcular matemáticamente si es demasiado lento o no. La mayoría de las veces es lo suficientemente bueno. Cuando no es así, tiene un punto de partida claro para trabajar y optimizar las cosas hasta que el algoritmo sea lo suficientemente eficiente.
Aquí hay un algoritmo simple para resolver el problema 3 en el Proyecto Euler (en C, pero traducirlo a Python debería ser trivial):
fuente
isPrime
es una exageración. Simplemente hacern/=2
whilen%2==0
y luego comenzari
con 3 y luego hacer un bucleif (n%i==0) n/=i; else i+=2;
es suficiente (bueno, se puede detener una vezi*i > n
).Vale la pena escribir un código que fabrique y fabrique (básicamente lo mismo) porque probablemente lo reutilizará en muchas otras preguntas de Euler. Podrá mejorar el código para preguntas posteriores y tal vez buscar pruebas de primitivas no exhaustivas si considera que ya no es lo suficientemente eficiente, por lo que sugiero que el enfoque más simple por ahora es:
fuente
En realidad, esta es un área de investigación activa en Matemáticas e Informática. El artículo de wikipedia ofrece una buena descripción general:
http://en.wikipedia.org/wiki/Integer_factorization
Elija cualquier algoritmo que le guste / encuentre interesante, y pruebe.
Probablemente tendrá que hacer una compensación: la mayoría de los algoritmos "buenos" requieren un poco de experiencia matemática para comprender realmente (aunque podría implementarlos sin comprenderlos por completo).
Si no sabe por dónde empezar, le recomiendo el tamiz cuadrático:
http://en.wikipedia.org/wiki/Quadratic_sieve
No requiere un loco conocimiento matemático, pero funciona bien.
fuente
Resolví algunos problemas de ProjectEuler hace algún tiempo en Ruby usando la división de prueba con números primos .
Descubrí que generar los números primos era mucho más crítico que el algoritmo de factorización real. Tan pronto como reemplacé mi enfoque ingenuo de generación de números primos por un tamiz, mis tiempos de ejecución se redujeron a una cantidad razonable.
fuente
Manteniéndolo muy simple ...
Encontrar los factores de X: comenzaría (n) en 2 y trabajaría hasta el número entero (piso, no redondo) de la raíz cuadrada de X. Si dividir X entre n produce Y e Y es un número entero, tanto n como Y son factores. Los valores más bajos de n producirán los valores más altos de Y.
Primalidad de Y: Nuevamente, repita (m) desde 2 hasta la raíz cuadrada de Y y vea si Y / m es un número entero. Si es así, Y no es primo. Regrese para encontrar otro factor.
Si m golpea la raíz de Y, tienes tu número primo. Deja de mirar. Y es la respuesta.
Si n golpea la raíz de X, no hay factores primos.
fuente
Como ya hay una solución completa, publicaré esta Haskell ...
Básicamente, no hay necesidad de probar la primalidad. Si divide los factores que encuentra (y se asegura de manejar los factores de repetición), entonces un factor no primo nunca puede ocurrir, porque un factor no primo es un producto de factores primos más pequeños.
Cargué y ejecuté esto con GHCi: es instantáneo, y ahora tengo un total de 4 (¡sí, cuatro!) Problemas de Euler resueltos.
fuente
También estoy formando mi conocimiento de Python y también he comenzado a responder los problemas del Proyecto Euler en mi repositorio de github: https://github.com/rentes/Euler .
Para el problema 3, he programado una solución simple que se basa en las siguientes premisas:
1) dado un número entero positivo n, comienzo a dividirlo entre 2, 3, ..., m, y si encuentro que m es un factor primo, lo agrego a una lista. No estoy agregando a la lista múltiplos de factores primos ya descubiertos. Por ejemplo, 4 es un múltiplo de 2, por lo que 4 no se agrega a esta lista.
2) Luego multiplico cada primo en la lista para ver si es igual a n. Si es igual, hemos encontrado todos los factores primos de n. Si no, continúe dividiendo n entre el siguiente número m, hasta que la multiplicación de todos los factores primos sea igual a n o m llegue a n.
Consulte https://github.com/rentes/Euler/blob/master/problem3.py para obtener más detalles. He agregado comentarios que lo ayudarán a comprender lo que programé. Es una solución simple, y estoy seguro de que no es la solución más rápida, pero funciona y es lo suficientemente simple de entender.
Atentamente
fuente