Considere la función Remove(n, startIndex, count)
que elimina count
dígitos del número que n
comienza desde el dígito en la posición startIndex
. Ejemplos:
Remove(1234, 1, 1) = 234
Remove(123456, 2, 3) = 156
Remove(1507, 1, 2) = 07 = 7
Remove(1234, 1, 4) = 0
Llamaremos al número primo X frágil si todas las Remove
operaciones posibles lo hacen no primo. Por ejemplo, 80651 es un primo frágil porque todos los siguientes números no son primos:
651, 51, 1, 0, 8651, 851, 81, 8, 8051, 801, 80, 8061, 806, 8065
Objetivo
Escribe un programa que encuentre el primo frágil más grande. Editar: eliminó el límite de tiempo porque había una forma relativamente justa de eludirlo.
El puntaje es el número primo frágil encontrado por su programa. En caso de empate, gana la presentación anterior.
Reglas
- Puede usar cualquier idioma y cualquier biblioteca de terceros.
- Ejecutas el programa en tu propio hardware.
- Puede usar pruebas de primalidad probabilística.
- Todo está en la base 10.
Entradas principales
- 6629 dígitos por Qualtagh (Java)
- 5048 dígitos por Emil (Python 2)
- 2268 dígitos por Jakube (Python 2)
Editar: he añadido mi propia respuesta.
- 28164 dígitos por Suboptimus Prime, basado en el algoritmo de Qualtagh (C #)
code-challenge
primes
Suboptimus Prime
fuente
fuente
Respuestas:
Java -
314433226629 dígitos6 0{3314} 8969999
Esta solución se basa en la respuesta de FryAmTheEggman .
¿Qué pasa si cavamos más profundo?
Se convierte en una estructura de árbol:
Llamemos al número R compuesto derecho si R y todas sus terminaciones son compuestas.
Vamos a iterar sobre todos los números compuestos correctos en primer lugar: 1, 9, 01, 81, 91, 09, 49, 69, 99, 001, 801, 901, etc.
Los números que comienzan con cero no se comprueban por primalidad, pero son necesarios para construir más números.
Buscaremos un número objetivo N en la forma X00 ... 00R, donde X es uno de 4, 6, 8 o 9 y R es el compuesto correcto. X no puede ser primo. X no puede ser 0. Y X no puede ser 1 porque si R termina con 1 o 9, entonces N contendría 11 o 19.
Si XR contiene números primos después de la operación "eliminar", XYR también los contendría para cualquier Y. Por lo tanto, no deberíamos atravesar ramas a partir de R.
Sea X una constante, digamos 6.
Pseudocódigo:
Deberíamos limitar la cantidad de ceros porque puede llevar demasiado tiempo encontrar un número primo en forma X + ceros + R (o para siempre si todos son compuestos).
El código real es bastante detallado y se puede encontrar aquí .
La prueba de primalidad para números en rango int largo se realiza mediante la variante determinista de la prueba de Miller. Para los números de BigInteger, primero se realiza una división de prueba y luego la prueba BailliePSW. Es probabilístico pero bastante seguro. Y es más rápido que la prueba de Miller-Rabin (deberíamos hacer muchas iteraciones para números tan grandes en Miller-Rabin para obtener suficiente precisión).
Editar: el primer intento fue incorrecto. También debemos ignorar las ramas que comienzan con R si X0 ... 0R es primo. Entonces X0 ... 0YR no sería primo frágil. Entonces se agregó un cheque adicional. Esta solución parece ser correcta.
Edición 2: se agregó una optimización. Si (X + R) es divisible entre 3, entonces (X + ceros + R) también es divisible entre 3. Entonces (X + ceros + R) no puede ser primo en este caso y se pueden omitir tales R.
Edición 3: no fue necesario omitir los dígitos primos si no están en la última o primera posición. Entonces finales como 21 o 51 están bien. Pero no cambia mucho nada.
Conclusiones:
fuente
Python 2 -
1261221133717192268 dígitosHay aproximadamente len (n) ^ 2 números resultantes de Remove (n, startIndex, count). Traté de minimizar esos números. Si hay muchos dígitos uno al lado del otro, muchos de estos números resultantes pueden ignorarse, ya que aparecen varias veces.
Así que lo llevé al extremo, solo 9 segundos y un poco primo en el medio. También eché un vistazo a la prima frágil por debajo de 1 millón, y vi que hay una prima tan frágil. Buscar números con 2 9 al final funciona muy bien, no estoy seguro de por qué. 1 número, 3 o 4 9 al final da como resultado primos frágiles más pequeños.
Utiliza el módulo pyprimes . No estoy seguro, si es bueno. Utiliza la prueba miller_rabin, por lo que es probabilístico.
El programa encuentra este primo frágil de 126 dígitos en aproximadamente 1 minuto, y durante el resto del tiempo busca sin éxito.
editar:
Acabo de ver que eliminaste el límite de tiempo. Ejecutaré el programa durante la noche, tal vez aparezcan algunos primos frágiles realmente grandes.
editar 2:
Hice mi programa original más rápido, pero aún no hay solución con más de 126 dígitos. Entonces me subí al tren y busqué x 9s + 1 dígito + y 9s. La ventaja es que tiene que verificar los números O (n) para primalidad, si corrige y. Encuentra un 1221 bastante rápido.
editar 3:
Para el número de 2268 dígitos utilizo el mismo programa, solo dividí el trabajo en múltiples núcleos.
fuente
Python 2.7 - 429623069
99993799Sin optimizaciones de ningún tipo, hasta ahora. Simplemente usando algunas observaciones triviales sobre primos frágiles (gracias a Rainbolt en el chat):
Solo trato de hacer rodar la pelota :)
Esto técnicamente dura un poco más de 15 minutos, pero solo verifica un solo número en el tiempo extra.
is_prime
se toma de aquí (isaacg lo usó aquí ) y es probabilístico.Solo una nota, cuando comienzo esto con
n=429623069
me levanto482704669
. El dígito extra realmente parece matar esta estrategia ...fuente
Python 2,
828 dígitos5048 dígitosComo señaló @Jakube, la primera prima que envié no era realmente frágil debido a un error en mi código. Arreglar el error fue fácil pero también hizo que el algoritmo fuera significativamente más lento.
Me limité a un subconjunto de búsqueda fácil de los primos frágiles, es decir, aquellos que solo consisten en el dígito 9 y exactamente un dígito 7.
Usé la misma
is_prime
función (desde aquí ) que @FryAmTheEggman.Editar:
Hice dos cambios para acelerar el algoritmo:
Intento omitir tantas verificaciones de primalidad como sea posible y solo retrocedo cuando se encuentra una posible prima frágil para asegurarme de que sea realmente frágil. Hay una pequeña cantidad de verificaciones duplicadas, así que memoricé crudamente la función de verificación principal.
Para los números del formulario
b*'9' + '7' + c*'9'
, limité el tamaño deb
. Cuanto más bajo es el límite, menos números deben verificarse, pero aumentan las posibilidades de no encontrar ningún primo frágil grande. Elegí arbitrariamente 222 como límite.Con unos pocos miles de dígitos, una sola verificación principal ya puede demorar unos segundos mi programa. Entonces, probablemente no pueda hacerlo mucho mejor con este enfoque.
No dude en verificar la corrección de mi envío. Debido a la comprobación de primalidad probabilística, mi número teóricamente podría no ser primo, pero si lo es, debería ser frágil. O he hecho algo mal. :-)
fuente
C #,
1003928164 dígitosEditar: Hice otro programa basado en el algoritmo de Qualtagh con algunas modificaciones menores:
Vieja respuesta:
Hay algunos patrones notables para números primos frágiles:
donde X puede ser 1, 2, 4, 5, 7 u 8.
Para tales números solo tenemos que considerar (longitud - 1) posibles
Remove
operaciones. Las otrasRemove
operaciones producen números duplicados o obviamente compuestos. Traté de buscar todos esos números con hasta 800 dígitos y noté que aparecen 4 patrones con más frecuencia que el resto: 8007001, 8004001, 9997999 y 6004009. Dado que Emil y Jakube están usando el patrón 999X999, decidí usar 8004001 solo Para agregar algo de variedad.He agregado las siguientes optimizaciones al algoritmo:
fuente
Haskell -
12201277 dígitos corregidos para verdaderos realesMejor uno - 1277 dígitos
Código Haskell
fuente