Introducción
Considere el proceso de tomar un número entero positivo n en alguna base b y reemplazar cada dígito con su representación en la base del dígito a la derecha.
- Si el dígito a la derecha es a 0, use la base b .
- Si el dígito a la derecha es un 1, use unario con 0 como marcas de conteo.
- Si no hay un dígito a la derecha (es decir, está en el lugar de las unidades), recorra el dígito más significativo.
Como ejemplo, n = 160 yb = 10. La ejecución del proceso se ve así:
The first digit is 1, the digit to the right is 6, 1 in base 6 is 1.
The next digit is 6, the digit to the right is 0, 0 is not a base so use b, 6 in base b is 6.
The last digit is 0, the digit to the right (looping around) is 1, 0 in base 1 is the empty string (but that's ok).
Concatenating '1', '6', and '' together gives 16, which is read in the original base b = 10.
El mismo procedimiento exacto pero moviéndose a la izquierda en lugar de a la derecha también se puede hacer:
The first digit is 1, the digit to the left (looping around) is 0, 0 is not a base so use b, 1 in base b is 1.
The next digit is 6, the digit to the left is 1, 6 in base 1 is 000000.
The last digit is 0, the digit to the left is 6, 0 in base 6 is 0.
Concatenating '1', '000000', and '0' together gives 10000000, which is read in the original base b = 10.
Por lo tanto, hemos hecho dos números relacionados con 160 (para b = 10): 16 y 10000000.
Definiremos n como un número astuto si divide al menos uno de los dos números generados en este proceso en 2 o más partes
En el ejemplo, n es astuto porque 160 divide 10000000 exactamente 62500 veces.
203 NO es astuto porque los números resultantes son 2011 y 203 en sí, que 203 no pueden caber uniformemente en 2 o más veces.
Desafío
(Para el resto del problema solo consideraremos b = 10.)
El desafío es escribir un programa que encuentre el número astuto más alto que también sea primo.
Los primeros 7 primos astutos (y todo lo que he encontrado hasta ahora) son:
2
5
3449
6287
7589
9397
93557 <-- highest so far (I've searched to 100,000,000+)
Oficialmente no estoy seguro de si existen más, pero espero que existan. Si puedes demostrar que hay (o no) finitamente muchos, te daré +200 repeticiones.
El ganador será la persona que pueda proporcionar el mejor nivel de astucia, siempre que sea evidente que han estado activos en la búsqueda y que no están tomando la gloria intencionalmente de los demás.
Reglas
- Puede usar cualquier herramienta de búsqueda principal que desee.
- Puede utilizar probadores primarios probabilísticos.
- Puede reutilizar el código de otras personas con atribución . Este es un esfuerzo comunitario. Las tácticas feroces no serán toleradas.
- Su programa debe buscar activamente la prima. Puede comenzar su búsqueda en el primer astuto más alto conocido.
- Su programa debería poder calcular todos los primos astutos conocidos dentro de las 4 horas posteriores a las instancias de Amazon EC2 t2.medium (ya sea cuatro a la vez o una durante cuatro horas o algo intermedio). En realidad no lo probaré en ellos y ciertamente no es necesario. Esto es solo un punto de referencia.
Aquí está mi código Python 3 que usé para generar la tabla anterior: (se ejecuta en un segundo o dos)
import pyprimes
def toBase(base, digit):
a = [
['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'],
['', '0', '00', '000', '0000', '00000', '000000', '0000000', '00000000', '000000000' ],
['0', '1', '10', '11', '100', '101', '110', '111', '1000', '1001'],
['0', '1', '2', '10', '11', '12', '20', '21', '22', '100'],
['0', '1', '2', '3', '10', '11', '12', '13', '20', '21'],
['0', '1', '2', '3', '4', '10', '11', '12', '13', '14'],
['0', '1', '2', '3', '4', '5', '10', '11', '12', '13'],
['0', '1', '2', '3', '4', '5', '6', '10', '11', '12'],
['0', '1', '2', '3', '4', '5', '6', '7', '10', '11'],
['0', '1', '2', '3', '4', '5', '6', '7', '8', '10']
]
return a[base][digit]
def getCrafty(start=1, stop=100000):
for p in pyprimes.primes_above(start):
s = str(p)
left = right = ''
for i in range(len(s)):
digit = int(s[i])
left += toBase(int(s[i - 1]), digit)
right += toBase(int(s[0 if i + 1 == len(s) else i + 1]), digit)
left = int(left)
right = int(right)
if (left % p == 0 and left // p >= 2) or (right % p == 0 and right // p >= 2):
print(p, left, right)
if p >= stop:
break
print('DONE')
getCrafty()
fuente
Respuestas:
Mathematica, encuentra 93,557 en 0.3s (no más primos astutos por debajo de 2 * 10 10 )
Esta es solo una búsqueda ingenua y exhaustiva a través de todos los números primos. Para comenzar, verifica aproximadamente 1,000,000 de primos cada 55 segundos (lo que seguramente se hará más lento a medida que los primos se hacen más grandes).
Estoy usando un montón de funciones de ayuda:
Y luego este bucle realiza la búsqueda real:
Seguiré actualizando la publicación, si encuentro primos o puedo pensar en optimizaciones.
Actualmente verifica todos los números primos hasta 100,000,000 en aproximadamente 5.5 minutos.
Editar: decidí seguir el ejemplo del OP y cambié a una tabla de búsqueda para la conversión de base. Eso dio aproximadamente un 30% de aceleración.
Números astutos en general
Estoy deteniendo mi búsqueda de primos astutos ahora, ya que necesitaría varios días para ponerme al día con la respuesta de Perl. En cambio, comencé a buscar todos los números astutos. Tal vez su distribución ayude a encontrar una prueba de que el número de primos astutos es finito o infinito.
Defino derecha astuto números de aquellos que dividen el número relacionado obtenido mediante la interpretación del dígito a la derecha como la nueva base, y -izquierda astuto números en consecuencia. Probablemente ayudará a abordarlos individualmente como prueba.
Aquí están todos los números astutos a la izquierda hasta 2,210,000,000:
Y aquí están todos los números astutos correctos en ese rango:
Tenga en cuenta que hay un número infinito de números astutos a la izquierda y a la derecha, porque hay varias formas de generarlos a partir de los existentes:
0
s a cualquier número de izquierda-astucia cuyo dígito menos significativo sea mayor que su dígito más significativo para obtener otro número de izquierda-astuto.0
s a cualquier número ingenioso cuyo dígito menos significativo sea menor que su dígito más significativo. Esto (y la declaración anterior) se debe a0
que se agregará tanto al número astuto como a su número relacionado, multiplicándolos efectivamente por 10.2
so5
s es astuto.777
s es astuto.28
unidos0
, como,28028028
siempre es astuto.Otras cosas a tener en cuenta:
125
. Podría valer la pena investigarlos para encontrar otra regla de producción.Supongo que esta lista sería más interesante si omitiera aquellos cuya existencia está implicada por un número astuto más pequeño, especialmente porque estas reglas de construcción descubiertas hasta ahora nunca son números primos. Así que aquí están todos los primos astutos que no pueden construirse con una de las reglas anteriores:
Tenga en cuenta también que hay algunos números doblemente astutos (los que aparecen en ambas listas y, por lo tanto, dividen ambos números relacionados):
Existen infinitamente muchos de estos también.
Pero como se puede ver, a excepción deEncontré el contraejemplo16
,28
,68
todos éstos consisten únicamente de un solo dígito (repetido). También sería interesante probar si cualquier número mayor puede ser doblemente astuto sin tener esa propiedad, pero eso podría desaparecer como un corolario de una prueba de números ingeniosamente simples.1944919449
.fuente
100540625, 100540625
en tu lista de expertos?Perl (1e5 en 0.03s, 1e8 en 21s). Máx. 93557 a 1e11.
Muy similar al original. Los cambios incluyen:
Hace los primeros 1e8 primos en 21 segundos en mi máquina rápida, 3.5 minutos por 1e9, 34 minutos por 1e10. Estoy un poco sorprendido de que sea más rápido que el código Python para entradas pequeñas. Podríamos paralelizar (lo nuevo de Pari / GP
parforprime
sería bueno para esto). Como es una búsqueda, podemos paralelizar a mano, supongo (forprimes
puede tomar dos argumentos).forprimes
es básicamente como Pari / GP'sforprime
: hace tamices segmentados internamente y llama al bloque con cada resultado. Es conveniente, pero para este problema no creo que sea un área de rendimiento.fuente
C ++ 11, con hilos y GMP
Tiempo (en una MacBook Air):
Requisitos:
g++ crafty.cpp -o crafty --std=c++11 -ffast-math -lprimesieve -O3 -lgmpxx -lgmp -Wall -Wextra
Salida:
fuente
C, con GMP, multiproceso (1e8 en 17s para 1 hilo)
Similar en concepto al resto, con probablemente un poco de optimizaciones aquí y allá.
Compilar:
gcc -I/usr/local/include -Ofast crafty.c -pthread -L/usr/local/lib -lgmp && ./a.out
Por favor done su poder de CPU. No tengo una computadora rápida.
1e8 en 17 segundos con 1 hilo en mi MacBook Air.
fuente
Python, encuentra 93557 en 0.28s
Muy similar al código de OP en que también usa
pyprimes
. Yo mismo escribí esto aunque xDTambién imprime el tiempo desde el inicio que encuentra un número.
Salida:
El formato es
number left right time
. Como comparación, el código de OP encuentra 93557 alrededor0.37
.fuente