Golf die Pseudoprimes!

9

Einleitung / Hintergrund

In einer kürzlichen Diskussion im Krypto-Chat wurde ich aufgefordert, mit dem Fermat-Primalitätstest und den Carmichael-Zahlen zu diskutieren / zu helfen . Dieser Test basiert auf der Prämisse, dass a^(p-1) mod p==1immer für Primzahlen gilt p, aber nicht immer für Verbundwerkstoffe. Jetzt ist eine Carmichael-Zahl im Wesentlichen der schlimmste Feind des Fermat-Tests: Eine Zahl, für die Sie sich entscheiden müssen, um anicht mit ihnen pzu koprimieren, um sie zu erhalten a^(p-1) mod p!=1. Wenn dies anicht Co-Prime ist, haben Sie im Wesentlichen einen nicht trivialen Faktor von gefundenpund wie wir alle wissen, kann Factoring ziemlich schwierig sein. Besonders wenn alle Faktoren ausreichend groß sind. Sie werden jetzt vielleicht feststellen, warum der Fermat-Test in der Praxis nicht so oft verwendet wird (nun, es gibt bessere Algorithmen), weil es Zahlen gibt, für die Sie als Verteidiger (in Bezug auf die Sicherheit) ähnlich viel Arbeit leisten müssten wie ein Angreifer (nämlich Faktor die Zahl).

Jetzt, da wir wissen, warum diese Zahlen etwas faszinierend sind, werden wir sie so schnell wie möglich generieren, sodass wir uns den generierenden Code einfach merken können, wenn wir jemals einen brauchen!

Carmichael-Nummern werden in OEIS auch als A002997 bezeichnet .
Es gibt bereits eine damit verbundene Herausforderung , aber die Einträge von dort sind hier nicht wettbewerbsfähig, da sie im Gegensatz zur Größe auf Geschwindigkeit optimiert sind. Das gleiche Argument gilt für die umgekehrte Richtung. Einträge hier machen wahrscheinlich Kompromisse gegen die Geschwindigkeit zugunsten der Größe.

Spezifikation

Eingang

Dies ist eine Herausforderung, so dass Sie eine positive oder nicht negative ganze Zahl nehmen nals Eingabe. nkann je nach Wunsch 0- oder 1-indiziert sein (bitte angeben).

Ausgabe

Ihre Ausgabe ist entweder die n-te Carmichael-Nummer oder die erste nCarmichael-Nummer, wie Sie es bevorzugen (bitte angeben).

Spezifikation

Eine ganze Zahl xist genau dann eine Carmichael-Zahl, wenn sie zusammengesetzt xist und für alle ganzen Zahlen ymit gcd(x,y)=1gilt y^(x-1) mod x==1.

Wer gewinnt?

Dies ist , also gewinnt der kürzeste Code im Byte!
Es gelten die Standardregeln für E / A und Lücken.

Testfälle

Die ersten Carmichael-Zahlen sind:

 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
SEJPM
quelle

Antworten:

6

Python 2 , 92 Bytes

f=lambda j,n=1:j and f(j-([(k/n)**~-n%n for k in range(n*n)if k/n*k%n==1]<[1]*~-n),n+1)or~-n

Probieren Sie es online aus!

1-indexiert und langsam wie Melasse.

Im Listenverständnis verwende ich Dennis 'Methode, um alle Ganzzahlen zu ngenerieren , die gleichzeitig kopiert werden ( ns Summen ), und berechne dann x**~-n%nfür alle. Nennen wir diese Liste L.

Um eine Carmichael-Nummer zu ermitteln, vergleiche ich diese Liste lexikografisch mit einer Liste, die aus n-1Einsen besteht. Warum funktioniert das?

Jedes Element von List eine positive ganze Zahl: (k/n)ist Koprime zu n, so (k/n)**~-nist es auch, so (k/n)**~-n%n > 0. Somit sind die einzig möglichen Werte davon Llexikographisch kleiner als [1]*(n-1) diejenigen, die vollständig aus weniger als n-1 Eins bestehen. ( LKann nicht mehr als n-1Werte enthalten, da nes nicht mehr als n-1Summen geben kann! Vergleiche wie [1,1,1,1,3] < [1,1,1,1]sind also out.)

Wenn Sie überprüfen, ob weniger als n-1Einträge vorhanden sind L, nwird sichergestellt, dass diese zusammengesetzt sind. ( n-1Totative zu haben ist eine äquivalente Bedingung zur Primalität.) Und dann ist die Bedingung, eine Carmichael-Zahl zu sein, genau, dass jedes Element Lgleich ist 1. Dieser lexikografische Vergleich erkennt also genau die Ls, an denen wir interessiert sind.

Mr. Xcoder sparte ein Byte, indem er zur rekursiven Lambda-Form wechselte: jZählt jedes Mal herunter, wenn wir eine Carmichael-Zahl treffen, und nzählt jedes Mal hoch, wenn wir wiederkehren. Sobald also jNull erreicht ist, n-1entspricht dies der original_value_of_j'ten Carmichael-Zahl.

Lynn
quelle
5

Gelee ,  12  11 Bytes

-1 Byte dank Meilen & Mr. Xcoder (Verwendung des Carmichael-Funktionsatoms & eines Golfs davon)

%Æc’=ÆP
⁹Ç#

Eine monadische Verbindung, ndie eine Liste der ersten nCarmichael-Nummern aufnimmt und zurückgibt.

Probieren Sie es online aus!

Wie?

Ähnlich wie im vorherigen (unten), mit der Ausnahme, dass für die Carmichael-Funktion eine Funktion integriert ist, die die kleinste Potenz liefert, sodass der auf diese Potenz angehobene Eingang zu einem Modulo kongruent ist, das für alle ganzen Zahlen mit dieser ganzen Zahl übereinstimmt. Somit können wir die falsch-positiven (Primzahlen) in weniger Bytes ausschließen und haben schnelleren Code!

%Æc’⁼ÆP - isCarmichael: number, n (any integer)
 Æc     - Carmicael function of n
%       - n modulo that
   ’    - decremented (0 for Carmichael numbers and primes)
     ÆP - is n prime? (1 for primes 0 otherwise)
    ⁼   - equal?

⁹Ç# - Main link: number, n
  # - count up finding the first n values satisfying:
 Ç  - ...condition: call the last link as a monad
⁹   - ...starting with a value of: literal 256

Vorherige 12 Bytes :

Ṗ*%⁼Ṗ_ÆP
⁹Ç#

Probieren Sie es online aus! (Ja, es läuft ab n=3).

Wie?

Eine Zahl cist eine Carmichael-Zahl, wenn sie zusammengesetzt ist, und es ist wahr, dass jede ganze Zahl x, die auf angehoben cwird, mit xModulo kongruent ist c.

Wir müssen dies nur für positive überprüfen xbis zu x=csich selbst.

Beachten Sie auch, dass bei x=cder Prüfung geprüft wird, ob die xErhöhung auf die Potenz von xzu xModulo kongruent ist x, was wahr ist - wir müssen dies also nicht überprüfen (dies führt zu kürzerem Code).

Ṗ*%⁼Ṗ_ÆP - Link 1, isCarmichaelNumber: integer c (greater than 1)
Ṗ        - pop c (uses the implicit range(c)) = [1, 2, 3, ..., c-1]
 *       - raise to the power of c (vectorises) = [1^c, 2^c, 3^c, ..., (c-1)^c]
  %      - modulo by c (vectorises) = [1^c%c, 2^c%c, 3^c%c, ..., (c-1)^c%c]
    Ṗ    - pop c = [1, 2, 3, ..., c-1]
   ⁼     - equal? (non-vectorising) = 1 if so, 0 if not
      ÆP - isPrime?(c) = 1 if so, 0 if not
     _   - subtract = 1 if Carmichael 0 if not
         -     (Note the caveat that c must be an integer greater than 1, this is because
         -      popping 1 yields [] thus the equality check will hold; same for 0,-1,...)

⁹Ç# - Main link: number, n
  # - count up finding the first n values satisfying:
 Ç  - ...condition: call the last link as a monad
⁹   - ...starting with a value of: literal 256
Jonathan Allan
quelle
Auch 12 Bytes , berechnet aber die ersten 33 in weniger als einer Minute unter Verwendung des Carmichael-Atoms.
Meilen
11 Bytes mithilfe der integrierten Carmichael-Funktion.
Mr. Xcoder
@ Mr.Xcoder Ich wollte Meilen vorschlagen, die separat gebucht wurden, dann habe ich deine gesehen, dann deinen Kommentar gesehen und gelöscht. Der dv mag sein, weil jemand denkt, dass er zu ähnlich zu Meilen ist, kommentierte er eher als diesen, aber ich denke, auch das ist ein seltsamer Grund, da es keinen Grund gibt zu glauben, dass Sie nicht unabhängig voneinander dasselbe gefunden haben (ich weiß, dass ich) habe so etwas schon oft gemacht). Ich werde Ihre 11 posten, wenn Sie wollen, aber ich bin der Meinung, dass Sie oder Meilen etwas Kredit nehmen sollten.
Jonathan Allan
@ Meilen auch ... ^
Jonathan Allan
@ JonathanAllan Poste es einfach selbst. Erwähne Meilen 'und meinen Beitrag, und ich denke auch nicht, dass Meilen etwas ausmachen :-) (Übrigens habe ich nicht einmal Meilen' Kommentar gesehen: - / bevor ich meine Antwort
gepostet
2

ECMAScript Regex, 86 89 Bytes

Warnung: Lesen Sie dies nicht, wenn Sie nicht möchten, dass unäre Regex-Magie für Sie verwöhnt wird. Wenn Sie versuchen möchten, diese Magie selbst herauszufinden, empfehle ich dringend, zunächst einige Probleme in ECMAScript-Regex zu lösen : In diesem früheren Beitrag finden Sie eine Liste der nacheinander mit Spoiler-Tags versehenen empfohlenen Probleme, die nacheinander gelöst werden können.

^(?!(x(x+))(?!\2*$)\1*(?=\1$)(?!(xx+)\3+$))((?=(xx+?)\5*$)(?=(x+)(\6+$))\7(?!\5*$)){2,}x$

Probieren Sie es online aus!

# Match Carmichael numbers in the domain ^x*$ using Korselt's criterion
# N = input number (initial value of tail)
^
(?!
    # Iterate through factors \1, with \2 = \1-1, for which \2 does not divide into N-1
    (x(x+))
    (?!\2*$)           # Assert N-1 is not divisible by \2
    \1*(?=\1$)         # Assert N is divisible by \1; tail = \1
    # If the factor \1, which already passed the aboved tests, is prime, then fail the
    # outside negative lookahead, because N is not a Carmichael number.
    (?!(xx+)\3+$)
)
# Assert that N has at least 2 unique prime factors, and that all of its prime factors
# are of exactly single multiplicity (i.e. that N is square-free).
(
    (?=(xx+?)\5*$)     # \5 = smallest prime factor of tail
    (?=(x+)(\6+$))     # \6 = tail / \5 (implicitly); \7 = tool to make tail = \6
    \7                 # tail = \6
    (?!\5*$)           # Assert that tail is no longer divisible by \5, i.e. that that
                       # prime factor was of exactly single multiplicity.
){2,}
x$

Die Hauptmagie dieses regulären Ausdrucks liegt in dem Teil, der behauptet, dass alle Primfaktoren von N von genau einer Multiplizität sind. Es ist der gleiche Trick wie bei meinen Match-Strings, deren Länge eine vierte Potenz ist, und bei der Suche nach den glattesten Zahlen-Regexen: wiederholte implizite Division durch den kleinsten Primfaktor.

Es ist auch möglich, direkt zu testen, dass N keine perfekten Quadratfaktoren hat (dh dass N quadratfrei ist). Dies verwendet eine Variante des Multiplikationsalgorithmus, der kurz in einem Absatz meines Regex-Beitrags mit zahlreichen Zahlen beschrieben wird , um zu testen, ob eine Zahl ein perfektes Quadrat ist. Das ist ein Spoiler . So lesen keine weiteren , wenn Sie nicht einige erweiterte einstellige regex Magie für Sie verwöhnen wollen . Wenn Sie versuchen möchten, diese Magie selbst herauszufinden, empfehle ich dringend, zunächst einige Probleme in der Liste der empfohlenen Probleme mit fortlaufenden Spoiler-Tags in diesem früheren Beitrag zu lösen und zu versuchen, die mathematischen Erkenntnisse unabhängig voneinander zu entwickeln.

Die Verwendung dieses Algorithmus für dieses Problem bietet jedoch keinen Vorteil. Dies führt zu einem langsameren regulären Ausdruck mit einer größeren Größe von 97 Bytes. Ohne den Primmultiplizitätstest (der in einer Schleife sowohl bestätigt, dass es mindestens 2 Primfaktoren gibt als auch dass es sich jeweils um eine einzelne Multiplizität handelt) müssen wir separat behaupten, dass N zusammengesetzt ist.

^(?!(x(x+))(?!\2*$)\1*(?=\1$)(?!(xx+)\3+$)|((xx+)\5*(?=\5$))?(x(x*))(?=(\6*)\7+$)\6*$\8)(xx+)\9+$

Probieren Sie es online aus!


 ^
 (?!
     # Iterate through factors \1, with \2 = \1-1, for which \2 does not divide into N-1
     (x(x+))
     (?!\2*$)           # Assert N-1 is not divisible by \2
     \1*(?=\1$)         # Assert N is divisible by \1; tail = \1
     # If the factor \1, which already passed the aboved tests, is prime, then fail the
     # outside negative lookahead, because N is not a Carmichael number.
     (?!(xx+)\3+$)
 |
 # Assert that N is square-free, i.e. has no divisor >1 that is a perfect square.
     ((xx+)\5*(?=\5$))?  # cycle tail through all of the divisors of N, including N itself
     # Match iff tail is a perfect square
     (x(x*))             # \6 = potential square root; \7 = \6 - 1
     (?=
         (\6*)\7+$       # iff \6 * \6 == our number, then the first match here must result in \8 == 0
     )
     \6*$\8              # test for divisibility by \6 and for \8 == 0 simultaneously
 )
 (xx+)\9+$               # Assert that N is composite
 

Deadcode
quelle
2
(Genau genommen ist dies eine decision-problemAntwort, aber die Herausforderung ist eine sequenceHerausforderung.) Vermutlich gibt es in einer leistungsstärkeren Regex-Variante einen direkteren Test für quadratische Teiler?
Neil
@Neil Du hast recht, ich kann es spielen, indem ich direkt auf quadratische Teiler teste. In ECMA sind keine zusätzlichen Funktionen erforderlich. Aber das wird es viel langsamer machen (und ich werde es auch unter einem Spoiler-Tag verstecken wollen). Ich denke, ich möchte beide Versionen einschließen.
Deadcode
Ja, es ist sehr ärgerlich, Fragen zu Regexen zu finden, die ich bereits geschrieben habe und die nicht die richtige Art von Herausforderung sind. Soll ich meine Antwort löschen?
Deadcode
@Neil Hier geht's. Ich habe den Algorithmus mit Ihrer Idee implementiert. Dies ist wahrscheinlich der Grund, warum ich nicht daran gedacht habe, es alleine zu verfolgen. Dies führt tatsächlich zu einer längeren Regex, da ein Is-Composite-Test erforderlich ist.
Deadcode
(Nach den Site-Regeln sollten Sie Ihre Antwort löschen, ja.) Meine Idee war, dass Sie mit zusätzlichen Funktionen von beispielsweise Retina-Regexen bis zu ^(?!(x(x+))(?!\2*$)\1*(?=\1$)(?!(xx+)\3+$)|((^x|xx\5){2,})\4*$)(xx+)\6+$72 Byte Golf spielen können .
Neil
1

Netzhaut , 94 Bytes

\d*$
x
"$+"}/^(?!(x(x+))(?!\2*$)\1*(?=\1$)(?!(xx+)\3+$)|((^x|xx\5){2,})\4*$)(xx+)\6+$/^+`$
x
x

Probieren Sie es online aus! 1-indiziert. Nicht schnell, daher tritt n>5bei TIO eine Auszeit auf. Erläuterung:

\d*$
x

Erhöhen Sie den aktuellen Wert. Beim ersten Durchgang wird dies ebenfalls naus dem Ausgabepuffer gelöscht ( $+kann aber trotzdem darauf zugreifen).

/^(?!(x(x+))(?!\2*$)\1*(?=\1$)(?!(xx+)\3+$)|((^x|xx\5){2,})\4*$)(xx+)\6+$/

Testen Sie, ob der aktuelle Wert eine Carmichael-Zahl ist. Dies verwendet den alternativen Algorithmus von @ Deadcode, da die Quadraterkennung beim Schreiben mit .NET / Perl / PCRE-Regex kürzer ist.

^+`

Wiederholen, bis der aktuelle Wert eine Carmichael-Zahl ist.

$
x

Erhöhen Sie den aktuellen Wert.

"$+"}

Wiederholen Sie das anfängliche Inkrement und die darüber liegenden Schleifenzeiten n.

x

Konvertieren Sie das Ergebnis in eine Dezimalzahl.

Neil
quelle
0

Haskell , 95 Bytes

s=filter
c n=s(\x->let l=s((1==).gcd x)f;f=[1..x-1]in l/=f&&all(\y->y^(x-1)`mod`x==1)l)[1..]!!n

Probieren Sie es online aus!

Degolfed:

-- function to filter out Carmichael numbers
filterFunction x = 
    let coprimes = filter ((1 ==) . gcd x) lesserNumbers
        lesserNumbers = [1 .. x - 1]
    in
        -- the number x is Carmichael if it is not prime
        lesserNumbers /= coprimes && 
            -- and all of its coprimes satisfy the equation
            all (\y -> y ^ (x - 1) `mod` x == 1) coprimes

-- get n'th Carmichael number (zero-based)
c n = filter filterFunction [1..] !! n
Max Yekhlakov
quelle