Intro
Considérons le processus consistant à prendre un entier positif n dans une base b et à remplacer chaque chiffre par sa représentation dans la base du chiffre à droite.
- Si le chiffre à droite est un 0, utilisez la base b .
- Si le chiffre à droite est un 1, utilisez unaire avec 0 comme marque de pointage.
- S'il n'y a pas de chiffre à droite (c'est-à-dire que vous êtes à la place), faites une boucle vers le chiffre le plus significatif.
À titre d'exemple, n = 160 et b = 10. L'exécution du processus ressemble à ceci:
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.
La même procédure exacte mais se déplaçant vers la gauche au lieu de la droite peut également être effectuée:
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.
Ainsi, nous avons fait deux nombres liés à 160 (pour b = 10): 16 et 10000000.
Nous définirons n comme un nombre astucieux s'il divise également au moins l'un des deux nombres générés dans ce processus en 2 parties ou plus.
Dans l'exemple n est astucieux car 160 divise 10000000 exactement 62500 fois.
203 n'est PAS astucieux car les chiffres résultants sont 2011 et 203 lui-même, qui 203 ne peuvent pas se répartir uniformément en 2 fois ou plus.
Défi
(Pour le reste du problème, nous ne considérerons que b = 10.)
Le défi est d'écrire un programme qui trouve le plus haut nombre astucieux qui est également premier.
Les 7 premiers nombres premiers astucieux (et tout ce que j'ai trouvé jusqu'à présent) sont:
2
5
3449
6287
7589
9397
93557 <-- highest so far (I've searched to 100,000,000+)
Je ne suis pas officiellement certain qu'il en existe d'autres, mais je m'attends à ce qu'ils existent. Si vous pouvez prouver qu'il y en a (ou qu'il n'y en a pas) en nombre fini, je vous donnerai +200 représentants de primes.
Le gagnant sera la personne qui peut fournir le plus haut astuce astucieux, à condition qu'il soit évident qu'ils ont été actifs dans la recherche et ne prennent pas intentionnellement la gloire des autres.
Règles
- Vous pouvez utiliser tous les outils de recherche de choix que vous souhaitez.
- Vous pouvez utiliser des testeurs principaux probabilistes.
- Vous pouvez réutiliser le code d' autres personnes avec attribution . Il s'agit d'un effort commun. Les tactiques acharnées ne seront pas tolérées.
- Votre programme doit rechercher activement le premier. Vous pouvez commencer votre recherche au plus haut astucieux astuce connu.
- Votre programme devrait être capable de calculer tous les nombres premiers astucieux connus dans les 4 heures suivant les instances d' Amazon EC2 t2.medium (soit quatre à la fois, soit une pendant quatre heures ou quelque chose entre les deux). Je ne vais pas vraiment le tester sur eux et vous n'avez certainement pas besoin de le faire. Ceci est juste une référence.
Voici mon code Python 3 que j'ai utilisé pour générer le tableau ci-dessus: (s'exécute dans une seconde ou deux)
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()
la source
Réponses:
Mathematica, trouve 93 557 en 0,3 s (pas d'autres nombres premiers astucieux en dessous de 2 * 10 10 )
Ceci est juste une recherche exhaustive naïve à travers tous les nombres premiers. Pour commencer, il vérifie environ 1 000 000 de nombres premiers toutes les 55 secondes (ce qui est appelé à ralentir à mesure que les nombres premiers augmentent).
J'utilise un tas de fonctions d'assistance:
Et puis cette boucle fait la recherche réelle:
Je continuerai à mettre à jour le message, si je trouve des nombres premiers ou que je peux penser à des optimisations.
Il vérifie actuellement tous les nombres premiers jusqu'à 100 000 000 en environ 5,5 minutes.
Edit: j'ai décidé de suivre l'exemple de l'OP et suis passé à une table de recherche pour la conversion de base. Cela a donné une accélération d'environ 30%.
Numéros astucieux en général
J'arrête maintenant ma recherche de nombres premiers astucieux, car il me faudrait plusieurs jours pour rattraper le retard de la réponse Perl. Au lieu de cela, j'ai commencé à chercher tous les numéros astucieux. Peut-être que leur distribution aide à trouver une preuve que le nombre de nombres premiers astucieux est fini ou infini.
Je définis les nombres rusés à droite ceux qui divisent le nombre connexe obtenu en interprétant le chiffre à droite comme la nouvelle base, et les nombres rusés à gauche en conséquence. Il sera probablement utile de les aborder individuellement pour une preuve.
Voici tous les numéros de gauche jusqu'à 2 210 000 000:
Et voici tous les numéros judicieux de cette gamme:
Notez qu'il existe un nombre infini de nombres de gauche et de droite, car il existe plusieurs façons de les générer à partir de ceux existants:
0
s à tout nombre rusé de gauche dont le chiffre le moins significatif est supérieur à son chiffre le plus significatif pour obtenir un autre nombre rusé de gauche.0
s à n'importe quel nombre de droite dont le chiffre le moins significatif est inférieur à son chiffre le plus significatif. Ceci (et la déclaration précédente) est dû au fait que le0
sera ajouté à la fois au numéro astucieux et à son numéro associé, multipliant efficacement les deux par 10.2
s ou5
s est astucieux.777
s est astucieux.28
joints par0
s, comme28028028
soit toujours gauche-astucieux.Autres choses à noter:
125
. Il pourrait être utile de les étudier pour trouver une autre règle de production.Je suppose que cette liste serait plus intéressante si j'omis ceux dont l'existence est impliquée par un plus petit nombre rusé, d'autant plus que ce ne sont jamais des nombres premiers selon les règles de construction découvertes jusqu'à présent. Voici donc tous les nombres astucieux qui ne peuvent pas être construits avec l'une des règles ci-dessus:
Notez également qu'il existe quelques nombres doublement astucieux (ceux qui apparaissent dans les deux listes et divisent donc les deux nombres liés):
Il en existe également une infinité.
Mais comme vous pouvez le voir, à l'exception deJ'ai trouvé le contre-exemple16
, ceux28
-68
ci ne sont tous composés que d'un seul chiffre (répété). Il serait également intéressant de prouver si des nombres plus importants peuvent être doublement astucieux sans avoir cette propriété, mais cela pourrait simplement disparaître comme corollaire d'une preuve pour des nombres individuellement astucieux.1944919449
.la source
100540625, 100540625
dans votre liste astucieuse?Perl (1e5 en 0,03s, 1e8 en 21s). Max 93557 à 1e11.
Très similaire à l'original. Les changements incluent:
Est-ce que le premier 1e8 s'amorce en 21 secondes sur ma machine rapide, 3,5 minutes pour 1e9, 34 minutes pour 1e10. Je suis un peu surpris qu'il soit plus rapide que le code Python pour les petites entrées. Nous pourrions paralléliser (le nouveau Pari / GP
parforprime
serait bien pour cela). Puisqu'il s'agit d'une recherche, nous pouvons paralléliser à la main, je suppose (forprimes
peut prendre deux arguments).forprimes
est fondamentalement comme Pari / GPforprime
- il effectue des tamis segmentés en interne et appelle le bloc avec chaque résultat. C'est pratique, mais pour ce problème, je ne pense pas que ce soit un domaine de performance.la source
C ++ 11, avec threads et GMP
Timing (sur un MacBook Air):
Exigences:
g++ crafty.cpp -o crafty --std=c++11 -ffast-math -lprimesieve -O3 -lgmpxx -lgmp -Wall -Wextra
Production:
la source
C, avec GMP, multithread (1e8 en 17s pour 1 fil)
Concept similaire au reste, avec probablement un peu d'optimisations ici et là.
Compiler:
gcc -I/usr/local/include -Ofast crafty.c -pthread -L/usr/local/lib -lgmp && ./a.out
Veuillez donner votre puissance CPU. Je n'ai pas d'ordinateur rapide.
1e8 en 17 secondes avec 1 fil sur mon macbook air.
la source
Python, trouve 93557 en 0,28s
Très similaire au code OP en ce qu'il utilise également
pyprimes
. Je l'ai écrit moi-même si xDIl affiche également le temps écoulé depuis le début où il trouve un nombre.
Production:
Le format est
number left right time
. A titre de comparaison, le code OP trouve 93557 environ0.37
.la source