Regex (ECMAScript), 276 205 201 193 189 Bytes
Der Vergleich der Multiplizitäten (Exponenten) verschiedener Primfaktoren ist ein interessantes Problem für die Lösung mit ECMAScript Regex - das Fehlen von Rückreferenzen, die durch Iterationen einer Schleife bestehen, macht es zu einer Herausforderung, alles zu zählen. Selbst wenn das Zählen des fraglichen numerischen Merkmals möglich ist, führt ein indirekterer Ansatz oft zu einem besseren Golf.
Wie bei meinen anderen regulären ECMA-Posts gebe ich eine Spoiler-Warnung ausgeben: Ich empfehle dringend, zu lernen, wie man unäre mathematische Probleme in ECMAScript-Regex löst. Es war eine faszinierende Reise für mich, und ich möchte sie keinem verderben, der sie möglicherweise selbst ausprobieren möchte, insbesondere denen, die sich für Zahlentheorie interessieren. In diesem früheren Beitrag finden Sie eine Liste der nacheinander mit Spoiler-Tags gekennzeichneten empfohlenen Probleme, die nacheinander gelöst werden müssen.
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 ECMAScript regex zu lösen, wie in dem oben verlinkten Beitrag beschrieben.
Die Hauptnutzlast eines Regex, den ich zuvor entwickelt habe, erwies sich als sehr zutreffend für diese Herausforderung. Das ist der reguläre Ausdruck, der die Primzahlen der höchsten Multiplizität findet . Meine erste Lösung dafür war sehr lang, und ich spielte sie später schrittweise ab, indem ich sie zuerst für die Verwendung von Molecular Lookahead umschrieb und dann mit einer fortschrittlichen Technik auf einfaches ECMAScript portierte , um das Fehlen von Molecular Lookahead zu umgehen , und anschließend Golf es viel kleiner als die ursprüngliche einfache ECMAScript-Lösung.
Der Teil dieses regulären Ausdrucks, der für dieses Problem gilt, ist der erste Schritt, bei dem Q ermittelt wird, der kleinste Faktor von N, der alle seine Primfaktoren teilt. Sobald wir diese Zahl haben, müssen wir nur noch N durch Q teilen, bis wir nicht mehr können. Wenn das Ergebnis 1 ist, sind alle Primzahlen gleich vielfach.
Nachdem ich eine Antwort unter Verwendung meines zuvor entwickelten Algorithmus zur Ermittlung von Q eingereicht hatte, stellte ich fest, dass diese auf eine völlig andere Weise berechnet werden kann: Ermitteln Sie den größten quadratfreien Faktor von N (unter Verwendung desselben Algorithmus wie bei meinem Carmichael-Zahlen-Regex) ). Wie sich herausstellt, ist dies überhaupt keine Schwierigkeit * im Hinblick auf das Fehlen eines molekularen Lookaheads und eines Lookbehinds mit variabler Länge (es ist nicht erforderlich, die zuvor verwendete fortschrittliche Technik einzuarbeiten), und es ist 64 Byte kürzer! Darüber hinaus entfällt die Komplexität, quadratfreies N und Prim N als unterschiedliche Sonderfälle zu behandeln, wodurch weitere 7 Byte aus dieser Lösung entfernt werden.
(Es verbleiben noch andere Probleme, die die fortgeschrittene Technik erfordern, die früher hier zum Herabsetzen der Berechnung von Q verwendet wurde, aber derzeit wird keine von ihnen durch meine PPCG-Posts dargestellt.)
Ich habe den Multiplizitätstest vor den Konsekutiv-Primzahlen-Test gestellt, weil letzterer viel langsamer ist; Wenn Sie Tests durchführen, die schneller fehlschlagen können, wird der reguläre Ausdruck für gleichmäßig verteilte Eingaben schneller. Es ist auch besser, Golf an erster Stelle zu setzen, weil es mehr Rückreferenzen verwendet (die mehr kosten würden, wenn sie zweistellig wären).
Ich konnte 4 Bytes aus dieser Regex (193 → 189) mit einem von Grimy gefundenen Trick löschen , der die Division weiter verkürzen kann, falls der Quotient garantiert größer oder gleich dem Divisor ist.
^(?=(|(x+)\2*(?=\2$))((?=(xx+?)\4*$)(?=(x+)(\5+$))\6(?!\4*$))*x$)(?=.*$\2|((?=((x*)(?=\2\9+$)x)(\8*$))\10)*x$)(?!(((x+)(?=\13+$)(x+))(?!\12+$)(x+))\11*(?=\11$)(?!(\15\14?)?((xx+)\18+|x?)$))
Probieren Sie es online!
# For the purposes of these comments, the input number = N.
^
# Assert that all of N's prime factors are of equal multiplicity
# Step 1: Find Q, the largest square-free factor of N (which will also be the smallest
# factor of N that has all the same prime factors as N) and put it in \2.
# If N is square-free, \2 will be unset.
(?=
# Search through all factors of N, from largest to smallest, searching for one that
# satisfies the desired property. The first factor tried will be N itself, for which
# \2 will be unset.
(|(x+)\2*(?=\2$)) # for factors < N: \2 = factor of N; tail = \2
# Assert that tail is square-free (its prime factors all have single multiplicity)
(
(?=(xx+?)\4*$) # \4 = smallest prime factor of tail
(?=(x+)(\5+$)) # \5 = tail / \4 (implicitly); \6 = tool to make tail = \5
\6 # tail = \5
(?!\4*$) # Assert that tail is no longer divisible by \4, i.e. that that
# prime factor was of exactly single multiplicity.
)*x$
)
# Step 2: Require that either \2 is unset, or that the result of repeatedly
# dividing tail by \2 is 1.
(?=
.*$\2
|
(
# In the following division calculation, we can skip the test for divisibility
# by \2-1 because it's guaranteed that \2 <= \8. As a result, we did not need to
# capture \2-1 above, and can use a better-golfed form of the division.
(?=
( # \8 = tail / \2
(x*) # \9 = \8-1
(?=\2\9+$)
x
)
(\8*$) # \10 = tool to make tail = \8
)
\10 # tail = \8
)*
x$ # Require that the end result is 1
)
# Assert that there exists no trio of prime numbers such that N is divisible by the
# smallest and largest prime but not the middle prime.
(?!
( # \11 = a factor of N
( # \12 = a non-factor of N between \11 and \13
(x+)(?=\13+$) # \13 = a factor of N smaller than \11
(x+) # \14 = tool (with \15) to make tail = \13
)
(?!\12+$)
(x+) # \15 = tool to make tail = \12
)
\11*(?=\11$) # tail = \11
# Assert that \11, \12, and \13 are all prime
(?!
(\15\14?)? # tail = either \11, \12, or \13
((xx+)\18+|x?)$
)
)
* Mit molekularem Lookahead ist es immer noch sauberer, ohne dass N quadratfrei ist. Dies lässt 6 Bytes fallen und ergibt eine 195 187 183-Byte- Lösung:
^(?=(?*(x+))\1*(?=\1$)((?=(xx+?)\3*$)(?=(x+)(\4+$))\5(?!\3*$))*x$)(?=((?=((x*)(?=\1\8+$)x)(\7*$))\9)*x$)(?!(((x+)(?=\12+$)(x+))(?!\11+$)(x+))\10*(?=\10$)(?!(\14\13?)?((xx+)\17+|x?)$))
# For the purposes of these comments, the input number = N.
^
# Assert that all of N's prime factors are of equal multiplicity
# Step 1: Find Q, the largest square-free factor of N (which will also be the smallest
# factor of N that has all the same prime factors as N) and put it in \1.
(?=
(?*(x+)) # \1 = proposed factor of N
\1*(?=\1$) # Assert that \1 is a factor of N; tail = \1
# Assert that tail is square-free (its prime factors all have single multiplicity)
(
(?=(xx+?)\3*$) # \3 = smallest prime factor of tail
(?=(x+)(\4+$)) # \4 = tail / \3 (implicitly); \5 = tool to make tail = \4
\5 # tail = \4
(?!\3*$) # Assert that tail is no longer divisible by \3, i.e. that that
# prime factor was of exactly single multiplicity.
)*x$
)
# Step 2: Require that the result of repeatedly dividing tail by \1 is 1.
(?=
(
# In the following division calculation, we can skip the test for divisibility
# by \1-1 because it's guaranteed that \2 <= \8. As a result, we did not need to
# capture \1-1 above, and can use a better-golfed form of the division.
(?=
( # \7 = tail / \1
(x*) # \8 = \7-1
(?=\1\8+$)
x
)
(\7*$) # \9 = tool to make tail = \7
)
\9 # tail = \7
)*
x$ # Require that the end result is 1
)
# Assert that there exists no trio of prime numbers such that N is divisible by the
# smallest and largest prime but not the middle prime.
(?!
( # \10 = a factor of N
( # \11 = a non-factor of N between \10 and \12
(x+)(?=\12+$) # \12 = a factor of N smaller than \10
(x+) # \13 = tool (with \14) to make tail = \12
)
(?!\11+$)
(x+) # \14 = tool to make tail = \11
)
\10*(?=\10$) # tail = \10
# Assert that \10, \11, and \12 are all prime
(?!
(\14\13?)? # tail = either \10, \11, or \12
((xx+)\17+|x?)$
)
)
Hier wird es auf Lookbehind mit variabler Länge portiert:
Regex (ECMAScript 2018), 198 195 194 186 182 Bytes
^(?=(x+)(?=\1*$)(?<=^x((?<!^\5*)\3(?<=(^\4+)(x+))(?<=^\5*(x+?x)))*))((?=((x*)(?=\1\8+$)x)(\7*$))\9)*x$(?<!(?!(\14\16?)?((xx+)\12+|x?)$)(?<=^\13+)((x+)(?<!^\15+)((x+)(?<=^\17+)(x+))))
Probieren Sie es online!
# For the purposes of these comments, the input number = N.
^
# Assert that all of N's prime factors are of equal multiplicity
# Step 1: Find Q, the largest square-free factor of N (which will also be the smallest
# factor of N that has all the same prime factors as N) and put it in \1.
(?=
(x+)(?=\1*$) # \1 = factor of N; head = \1
(?<= # This is evaluated right-to-left, so please read bottom to top.
^x
(
(?<!^\5*) # Assert that head is no longer divisible by \6, i.e. that
# that prime factor was of exactly single multiplicity.
\3 # head = \4
(?<=(^\4+)(x+)) # \4 = head / \5 (implicitly); \3 = tool to make head = \4
(?<=^\5*(x+?x)) # \5 = smallest prime factor of head
)*
)
)
# Step 2: Require that the result of repeatedly dividing tail by \1 is 1.
(
# In the following division calculation, we can skip the test for divisibility
# by \1-1 because it's guaranteed that \2 <= \8. As a result, we did not need to
# capture \1-1 above, and can use a better-golfed form of the division.
(?=
( # \7 = tail / \1
(x*) # \8 = \7-1
(?=\1\8+$)
x
)
(\7*$) # \9 = tool to make tail = \7
)
\9 # tail = \7
)*
x$ # Require that the end result is 1
# Assert that there exists no trio of prime numbers such that N is divisible by the
# smallest and largest prime but not the middle prime.
# This is evaluated right-to-left, so please read bottom to top, but switch back to
# reading top to bottom at the negative lookahead.
(?<!
# Assert that \13, \15, and \17 are all prime.
(?!
(\14\16?)? # tail = either \13, \15, or \17
((xx+)\12+|x?)$
)
(?<=^\13+)
( # tail = \13
(x+) # \14 = tool to make tail = \15
(?<!^\15+)
(
(x+) # \16 = tool (with \14) to make tail = \17
(?<=^\17+)(x+) # \17 = a factor of N smaller than \13
) # \15 = a non-factor of N between \13 and \17
) # \13 = a factor of N
)