Description de la tâche
Dans la théorie des nombres, la fonction de Carmichael λ prend un nombre entier positif n et retourne le plus petit entier positif k de telle sorte que la k puissance -ième de chaque entier coprime à n est égal à 1 modulo n .
Étant donné un entier positif n , votre solution doit calculer λ (n) . Le code le plus court en octets gagne.
Votre programme devrait théoriquement fonctionner pour des entrées arbitrairement grandes, mais n'a pas besoin d'être efficace.
Conseils
La séquence de tous les λ (n) est OEIS A002322 .
Une implémentation de Python non-golfée ressemblerait à
from fractions import gcd
def carmichael(n):
coprimes = [x for x in range(1, n) if gcd(x, n) == 1]
k = 1
while not all(pow(x, k, n) == 1 for x in coprimes):
k += 1
return k
(En Python, pow(A, B, C)
calcule efficacement pow(A, B) % C
.)
Cas de test
Input Output
1 1
2 1
3 2
10 4
35 12
101 100
530 52
3010 84
6511 3056
10000 500
Réponses:
Mathematica, 16 octets
Bien...
la source
Python,
767367 octetsEssayez-le en ligne!
Un autre octet peut être sauvegardé en retournant True au lieu de 1 .
Mise en œuvre alternative
En utilisant la même approche, il y a aussi l'implémentation suivante de @feersum qui n'utilise pas les compréhensions de liste.
Notez que cette implémentation nécessite O (n λ (n) ) temps. L'efficacité pourrait être considérablement améliorée tout en réduisant le score à 66 octets , mais la fonction renverrait True pour l'entrée 2 .
Contexte
Définitions et notation
Toutes les variables employées désigneront des entiers; n , k et α désigneront des entiers positifs ; et p désignera un nombre premier positif .
a | b si b est divisible par a , c'est-à-dire s'il y a q tel que b = qa .
a ≡ b ( mod m) si a et b ont le même résidu modulo m , c'est-à-dire si m | a - b .
λ (n) est le plus petit k tel que a k ≡ 1 ( mod n) - c'est-à-dire tel que n | a k - 1 - pour tous les a qui sont coprimes à n .
f (n) est le plus petit k tel que a 2k + 1 ≡ a k + 1 ( mod n) - c'est-à-dire tel que n | a k + 1 (a k - 1) - pour tous a .
λ (n) ≤ f (n)
Fixez n et laissez a être coprime à n .
Par la définition de f , n | a f (n) +1 (a f (n) - 1) . Depuis un et n n'ont pas un facteur premier commun, non plus un f (n) 1 et n , ce qui implique que n | a f (n) - 1 .
Puisque λ (n) est le plus petit entier k tel que n | a k - 1 pour tous les entiers a qui ont la priorité pour n , il en résulte que λ (n) ≤ f (n) .
λ (n) = f (n)
Puisque nous avons déjà établi l'inégalité λ (n) ≤ f (n) , il suffit de vérifier que k = λ (n) vérifie la condition qui définit f , c'est-à-dire que n | a λ (n) +1 (a λ (n) - 1) pour tout a . Pour cela, nous allons établir que p α | a λ (n) +1 (a λ (n) - 1) chaque fois que p α | n .
λ (k) | λ (n) chaque fois que k | n ( source ), donc (a λ (k) - 1) (a λ (n) -λ (k) + a λ (n) -2λ (k) + ⋯ + a λ (k) + 1) = a λ (n) - 1 et donc un λ (k) - 1 | a λ (n) - 1 | a λ (n) +1 (a λ (n) - 1) .
Si a et p α sont coprimes, par la définition de λ et celle ci-dessus, p α | a λ (p α ) - 1 | Un λ (n) +1 (un λ (n) - 1) suit, comme vous le souhaitez.
Si a = 0 , alors un λ (n) 1 (a λ (n) - 1) = 0 , ce qui est divisible par tous les nombres entiers.
Enfin, nous devons considérer le cas où a et p α ont un facteur premier commun. Puisque p est premier, cela implique que p | a . Le théorème de Carmichael établit que λ (p α ) = (p - 1) p α - 1 si p> 2 ou α <3 et que λ (p α ) = p α - 2 sinon. Dans tous les cas, λ (p α ) ≥ p α - 2 ≥ 2 α - 2 > α - 2 .
Par conséquent, λ (n) + 1 ≥ λ (p α ) + 1> α - 1 , donc λ (n) + 1 ≥ α et p α | p λ (n) +1 | a λ (n) +1 | a λ (n) +1 (a λ (n) - 1) . Ceci complète la preuve.
Comment ça marche
Alors que les définitions de f (n) et λ (n) considèrent toutes les valeurs possibles de a , il suffit de tester celles qui se trouvent dans [0, ..., n - 1] .
Lorsque f (n, k) est appelé, il calcule un k + 1 (a k - 1)% n pour toutes les valeurs de a dans cette plage, qui est 0 si et seulement si n | a k + 1 (a k - 1) .
Si tous les résidus calculés sont zéro, k = λ (n) et
any
renvoie False , donc f (n, k) renvoie 1 .D'autre part, alors que k <λ (n) ,
1-any(...)
retournera 0 , f est appelé de manière récursive avec une valeur incrémentée de k . Le premier-~
incrémente la valeur de retour de f (n, k + 1) , nous ajoutons donc 1 à f (n, λ (n)) = 1 une fois pour chaque entier de [1, ..., λ (n) - 1 ] . Le résultat final est donc λ (n) .la source
f=lambda n,k=1,a=1:a/n or(a**k*~-a**k%n<1)*f(n,k,a+2-n%2)or-~f(n,k+1)
(Ajoutez un octet en arrière si vous ne l'aimez pas prendre n ** λ (n) fois).Mathematica sans intégré,
5857 octetsMerci à Martin Ender d’avoir trouvé une erreur, puis de me sauver les octets nécessaires pour la réparer!
Merci aux miles d'avoir économisé 1 octet! (qui me semblait être 2)
Les fonctions intégrées conviennent parfaitement ... mais pour ceux qui veulent l'implémenter sans utiliser de force brute, voici une formule pour la fonction Carmichael:
Si p est un nombre premier, la fonction de Carmichael λ (p ^ r) est égale à (p ^ r) = (p-1) * p ^ (r-1) - sauf lorsque p = 2 et r≥3, auquel cas c'est la moitié, à savoir 2 ^ (r-2).
Et si la factorisation de la puissance première de n est égale à p1 ^ r1 * p2 ^ r2 * ..., alors λ (n) est égal au plus petit commun multiple de {λ (p1 ^ r1), λ (p2 ^ r2), .. .}.
Le temps d'exécution est un instant de plus que la factorisation du nombre entier en premier lieu.
la source
EulerPhi
pour obtenirLCM@@(EulerPhi[#^#2]/If[#==2<#2,2,1]&@@@FactorInteger@#)&
57 octets.Modèles considérés comme nuisibles , 246 octets
Une fonction non nommée (pas qu'il y ait des fonctions nommées).
C'est un de mes esolang oublié qui est interprété par un compilateur C ++ instanciant des modèles. Avec la profondeur de gabarit maximale par défaut de
g++
, cela peut faire λ (35), mais pas λ (101) (l'évaluation paresseuse aggrave la situation).la source
Haskell,
5756 octetsla source
Gelée, 2 octets
Merci pour la fonction intégrée, @Lynn
la source
Pyth -
191817 octetsUn octet enregistré grâce à @TheBikingViking.
Straight up force brute.
Essayez-le en ligne ici .
la source
f!smt
est un octet plus court.Rubis,
5956 octetsla source
J,
2827 octetsLa fonction de Carmichael est λ ( n ) et la fonction totale est ( n ).
Utilise la définition où λ ( p k ) = φ ( p k ) / 2 si p = 2 et k > 2 sinon φ ( p k ). Ensuite, pour générale n = p 1 k 1 p 2 k 2 ⋯ p i k i , λ ( n ) = PPCM [λ ( p 1 k 1 ) λ ( p 2 k 2 ) ⋯ λ ( p i k i )] .
Usage
Commandes supplémentaires utilisées pour formater plusieurs entrées / sorties.
Explication
la source
En fait,
3028251926 octetsLa fonction Carmichael,
λ(n)
oùn = p_0**k_0 * p_1**k_1 * ... * p_a**k_a
, est définie comme le plus petit commun multiple (LCM) deλ(p_i**k_i)
pour les premiers pouvoirs maximauxp_i**k_i
qui se divisent enn
. Étant donné que pour chaque puissance principale, à l'exception de la puissance principale2
, la fonction Carmichael est équivalente à la fonction de Eulerλ(n) == φ(n)
, nous utilisonsφ(n)
plutôt. Pour le cas particulier2**k
oùk ≥ 3
, nous vérifions simplement si2**3 = 8
divise enn
début de programme et divise par 2 si c'est le cas.Malheureusement, à l'heure actuelle, aucun LCM n'est intégré, j'ai donc créé un LCM à force brute. Les suggestions de golf sont les bienvenues. Essayez-le en ligne!
Ungolfing
la source
totient
et des commandesgcd
intégrées. En réalité, ce serait plus court si cela avait été faitlcm
directement, mais cela ne me dérangeait pas trop et cela ne supprimerait que 4 octets au maximum, de toute façon.JavaScript (ES6),
143135 octetsEdit: sauvegardé 8 octets grâce à Neil
Une implémentation utilisant la programmation fonctionnelle.
Ungolfed et commenté
Démo
Bien que cela fonctionne pour
6511
et10000
, je ne les inclurai pas ici car cela a tendance à être un peu lent.la source
0..n-1
gammes assez facilement:[...Array(n).keys()]
. Cela nécessite non pas un mais deux cas spéciaux, mais je suis toujours en avance:n=>(a=[...Array(n).keys()]).find(k=>k&&!c.some(c=>a.slice(0,k).reduce(y=>y*c%n,1)-1),c=a.filter(x=>(g=(x,y)=>x?g(y%x,x):y)(x,n)==1))||1
Ruby,
101869190 octetsUn port Ruby de ma réponse actuelle . Les suggestions de golf sont les bienvenues.
Edit: -4 octets pour supprimer,
a
mais +9 octets pour corriger un bogue1
renvoyénil
. -1 octet grâce à Cyoce.Ungolfing
la source
a=
. Malheureusement, vous reveneznil
pour n = 1 :(.(n.prime_division<<[2,1])
Corrige cela. Je ne sais pas s'il existe un moyen plus golfeur.(n%8<1?n/2:n).prime_division...
enregistre 2 autres octets.a
est un vestige d'une tentative de golf antérieure. Merci pour le rappel sura
et pour la tête sur1
..reduce :lcm
place de.reduce(:lcm)
.JavaScript (ES 2016) 149
Implémentation de référence Python portée sur JS. Certains éléments de Pyhton sophistiqués manquent dans js, comme
gcd
etpow
, et la compréhension du tableau n’est pas standard dans ES 6. Cela fonctionne dans Firefox.Moins joué au golf
la source
p=(a,b,c)=>b?a*p(a,b-1,c)%c:1;
Java,
209207202194192 octetsCode (96 octets):
fonctions supplémentaires (96 octets):
Test et non-golfé
Remarques
a
être unint
est plus courte que si je devais utiliser unboolean
pour effectuer mes tests.valueOf
toute nouvelleBigInteger
que de créer une fonction distincte (il y a 5, plus laONE
constante est un billet de faveur).gcd
est calculé encore et encore pour les mêmes valeurs.Se rase
if(...)a=...;
->a=...?...:1;
a==1
->a<2
BigInteger
en jouant au golfgcd
etmodPow
pourint
.modPow
-> récursif==1
-><2
(semble fonctionner pour tous les cas de test, ne sait pas pour les autres nombres.)la source
p
assez astucieuse. Au début, j’ai aussi essayé d’utiliser des entiers, mais comme je l’ai mentionné dans ma réponse, j’avais des problèmes de précision et c’est pourquoi je suis passé àBigInteger
(c’est- à -direMath.pow(3, 100)%101
retourné60.0
au lieu de1
). Votre implémentation est immunisée contre cela car elle effectue le mod dans chaque itération. Cependant, il souffre toujours d'un bug. Pour les grandsm
p
peut encore retourner des résultats erronés. De plus, en raison de la récursivité, uneStackOverflowError
entrée importante avec la taille de pile par défaut peut facilement se produire.int
types. Je pourrais utiliser des longs au lieu de ints, ce serait 8 octets supplémentaires. Mais à mon avis, tous les cas de test sont valides, donc je le laisse comme ça.StackOverflowError
peut arriver, mais c'est ainsi que fonctionne récursif. Il existe des méthodes pour limiter à 32 piles, mais elles utilisent beaucoup plus d'octets. Cette implémentation est fragile, oui, vous avez tout à fait raison. Mais c'est assez fort pour les cas de test.Java8
3819 +287295253248241 =325333272267260 octetsImportations, 19 octets
Explication
C'est une mise en œuvre simple. Les co-nombres premiers sont calculés dans le
Set p
et la puissance de chacun est utilisée pour vérifier si elle est égale à 1 modulo n.J'ai dû utiliser à
BigInteger
cause de problèmes de précision.Usage
Ungolfed
Toutes les suggestions pour jouer au golf sont les bienvenues :-)
Mise à jour
B()
k()
méthode et dep
(co-nombres premiers).la source
k(int)
dans la boucle car c'est un one-line et peut être fait. De plus, la constante O peut également être insérée dans lac
méthode. Je suppose que vous gagnerez des octets en le faisant!while(n>1&&!p.stream().allMatch(x->B((int)x).modPow(B(k), B(n)).equals(O)))
supprime les octets et corrige les problèmes que j'ai mentionnés si vous remettiez l'ensemble et la constante dans la méthode. En outre, vous utilisezO
deux fois, remplacer parB(1)
pour raser les octets.Java,
165 163 158 152143 octetsUn autre port de ma mise en œuvre C .
Essayez sur Ideone
la source
C ++,
208 200 149 144 140134 octetsUn port de mon mise en œuvre C .
Essayez sur Ideone
la source
Raquette 218 octets
Version non-golfée:
Essai:
Sortie:
la source
C,
278 276 272 265 256 243 140 134125 octetsCela utilise un algorithme d'exponentiation modulaire lente, calcule le GCD trop souvent et ne perd plus de mémoire!
Ungolfed:
Essayez sur Ideone
la source
Axiome 129 octets
moins golfé
résultats
la source