Introduction / Contexte
Lors d'une récente discussion dans le chat crypto, j'ai été mis au défi de discuter / aider avec le test de primalité de Fermat et les nombres de Carmichael. Ce test est basé sur la prémisse qui a^(p-1) mod p==1
sera toujours valable pour les nombres premiers p
, mais pas toujours pour les composites. Maintenant, un nombre carmichael est essentiellement le pire ennemi du test de Fermat: un nombre pour lequel vous devez choisir a
de ne pas être co-amorcé avec p
pour obtenir a^(p-1) mod p!=1
. Maintenant, si ce a
n'est pas co-premier, vous avez essentiellement trouvé un facteur non trivial dep
et comme nous le savons tous, l'affacturage peut être assez difficile. Surtout si tous les facteurs sont suffisamment importants. Vous pouvez maintenant comprendre pourquoi le test de Fermat n'est pas utilisé dans la pratique aussi souvent (eh bien, il y a de meilleurs algorithmes), c'est parce qu'il y a des chiffres pour lesquels vous, en tant que défenseur (en termes de sécurité), devriez effectuer une quantité de travail similaire à un attaquant (à savoir factoriser le nombre).
Alors maintenant que nous savons pourquoi ces chiffres sont quelque peu fascinants, nous allons les générer le plus rapidement possible, afin que nous puissions simplement mémoriser le code de génération si nous en avons besoin!
Les numéros de Carmichael sont également connus sous le nom de A002997 sur OEIS .
Il existe déjà un défi connexe , mais les entrées à partir de là ne sont pas compétitives ici car elles sont optimisées pour la vitesse plutôt que pour la taille. Le même argument vaut pour la direction inverse, les entrées ici sont susceptibles de faire des compromis contre la vitesse en faveur de la taille.
spécification
Contribution
Il s'agit d'un défi de séquence standard , vous devez donc prendre un entier positif ou non négatif n
en entrée. n
peut être indexé 0 ou 1 selon vos préférences (veuillez l'indiquer).
Production
Votre sortie sera soit le n
-ième numéro de carmichael ou les premiers n
numéros de carmichael, comme vous préférez (veuillez l'indiquer).
spécification
Un entier x
est un nombre de Carmichael si et seulement si x
est composite et pour tous les entiers y
avec gcd(x,y)=1
, il le tient y^(x-1) mod x==1
.
Qui gagne?
C'est le code-golf , donc le code le plus court en octets gagne!
Les règles standard d'E / S et d'échappatoires s'appliquent.
Cas de test
Les premiers numéros de carmichael sont:
561,1105,1729,2465,2821,6601,8911,10585,15841,
29341,41041,46657,52633,62745,63973,75361,101101,
115921,126217,162401,172081,188461,252601,278545,
294409,314821,334153,340561,399001,410041,449065,
488881,512461
la source
Python 2 , 92 octets
Essayez-le en ligne!
1-indexé et lent comme la mélasse.
Dans la compréhension de la liste, j'utilise la méthode de Dennis pour générer tous les nombres entiers en coprime
n
( totaux de n ), puis je calculex**~-n%n
pour chacun d'eux. Appelons cette listeL
.Pour détecter un nombre de Carmichael, je compare lexicographiquement cette liste à une liste composée de
n-1
uns. Pourquoi ça marche?Chaque élément de
L
est un entier positif:(k/n)
est un coprime àn
, l'(k/n)**~-n
est aussi, donc(k/n)**~-n%n > 0
. Ainsi, les seules valeurs possibles deL
cela sont lexicographiquement inférieures à[1]*(n-1)
celles qui sont entièrement composées de moins den-1
un. (L
Ne peut pas contenir plus den-1
valeurs,n
ne peut pas avoir plus den-1
totatives! Donc , les comparaisons telles[1,1,1,1,3] < [1,1,1,1]
sont hors.)Vérifier qu'il y a moins de
n-1
entrées dansL
assure quen
c'est composite. (Avoir desn-1
totaux est une condition équivalente à la primauté.) Et puis, la condition pour être un nombre de Carmichael est exactement que chaque élément d'L
égaux1
. Cette comparaison lexicographique détecte donc exactement lesL
s qui nous intéressent.M. Xcoder a économisé un octet en passant à la forme lambda récursive:
j
décompte à chaque fois que nous atteignons un nombre Carmichael, etn
décompte à chaque fois que nous recursons. Donc, une foisj
atteint zéro,n-1
est égal auoriginal_value_of_j
nombre de Carmichael.la source
Gelée ,
1211 octets-1 octet grâce aux miles et à M. Xcoder (utilisation de l'atome de fonction Carmichael et de son golf)
Un lien monadique prenant
n
et retournant une liste des premiersn
numéros de Carmichael.Essayez-le en ligne!
Comment?
Tout comme le précédent (ci-dessous), sauf qu'il existe une fonction intégrée pour la fonction Carmichael - qui donne la plus petite puissance telle que l'entrée élevée à cette puissance est congruente à un modulo, cette puissance pour tous les entiers co-amorçant avec cet entier. Ainsi, nous pouvons exclure les faux positifs (nombres premiers) en moins d'octets et avoir un code plus rapide!
12 octets précédents :
Essayez-le en ligne! (Ouais, ça expire
n=3
).Comment?
Un nombre
c
,, est un nombre de Carmichael s'il est composite et il est vrai que tout entier,,x
élevé àc
est congru àx
moduloc
.Nous avons seulement besoin de vérifier cela pour le positif
x
àx=c
lui - même.Notez également que lors de
x=c
la vérification est de savoir six
élevé à la puissance dex
est congru àx
modulox
, ce qui est vrai - nous n'avons donc pas besoin de vérifier cela (cela rend le code plus court).la source
ECMAScript Regex,
8689 octetsAttention: ne lisez pas ceci si vous ne voulez pas que la magie des regex unaires soit gâtée pour vous. Si vous voulez essayer de découvrir cette magie vous-même, je vous recommande vivement de commencer par résoudre certains problèmes dans l'expression régulière ECMAScript: consultez ce post précédent pour une liste des problèmes recommandés marqués consécutivement par spoiler pour les résoudre un par un.
^(?!(x(x+))(?!\2*$)\1*(?=\1$)(?!(xx+)\3+$))((?=(xx+?)\5*$)(?=(x+)(\6+$))\7(?!\5*$)){2,}x$
Essayez-le en ligne!
La magie principale de cette expression rationnelle réside dans la partie qui affirme que tous les facteurs premiers de N sont de multiplicité exactement unique. C'est la même astuce que celle utilisée par mes chaînes Match dont la longueur est une quatrième puissance et Trouver les expressions rationnelles les plus lisses: division implicite répétée par le plus petit facteur premier.
Il est également possible de tester directement que N n'a pas de facteurs carrés parfaits (c'est-à-dire que N est sans carré). Cela utilise une variante de l'algorithme de multiplication brièvement décrit dans un paragraphe de mon post regex de nombres abondants pour tester si un nombre est un carré parfait. Ceci est un spoiler . Alors ne lisez pas plus loin si vous ne voulez pas que la magie regex unaire avancée soit gâtée pour vous . Si vous voulez essayer de découvrir cette magie vous-même, je vous recommande vivement de commencer par résoudre certains problèmes dans la liste des problèmes recommandés marqués consécutivement par spoiler dans ce post précédent , et d'essayer de trouver les idées mathématiques de manière indépendante.
L'utilisation de cet algorithme sur ce problème n'apporte cependant aucun avantage. Il en résulte une expression régulière plus lente, avec une plus grande taille de 97 octets. Sans le test de multiplicité premier (qui dans une boucle affirme à la fois qu'il existe au moins 2 facteurs premiers et qu'ils sont chacun de multiplicité unique), nous devons affirmer séparément que N est composite.
Essayez-le en ligne!
la source
decision-problem
réponse, mais le défi est unsequence
défi.) Vraisemblablement, dans une variante d'expression plus puissante, il y aurait un test plus direct pour les diviseurs carrés disponibles?^(?!(x(x+))(?!\2*$)\1*(?=\1$)(?!(xx+)\3+$)|((^x|xx\5){2,})\4*$)(xx+)\6+$
, ou peut-être même moins de 72 octets.J ,
725951 octetsEssayez-le en ligne!
la source
Rétine , 94 octets
Essayez-le en ligne! 1 indexé. Pas rapide, donc le temps sera écoulé
n>5
sur TIO. Explication:Incrémentez la valeur actuelle. Lors de la première passe, cela supprime également
n
le tampon de sortie (mais$+
peut toujours y accéder).Testez si la valeur actuelle est un nombre Carmichael. Cela utilise l'algorithme alternatif de @ Deadcode, car la détection carrée est plus courte lorsqu'elle est écrite à l'aide d'expressions régulières .NET / Perl / PCRE.
Répétez jusqu'à ce que la valeur actuelle soit un nombre Carmichael.
Incrémentez la valeur actuelle.
Répétez l'incrément initial et les
n
temps de boucle ci-dessus .Convertissez le résultat en décimal.
la source
Haskell , 95 octets
Essayez-le en ligne!
Dégolfé:
la source