Regex (PCRE-Geschmack), 66 (65🐌) Bytes
Inspiriert davon, dass sowohl Martin Ender als auch Jaytea , zwei Regex-Genies, Regex-Lösungen für diesen Code-Golf geschrieben haben, habe ich meine eigenen von Grund auf neu geschrieben. Der berühmte reguläre Ausdruck für die Erstprüfung kommt in meiner Lösung nirgendwo vor.
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:
- Primzahlen abgleichen (falls Sie noch nicht mit Regex vertraut sind)
- Kombiniere Potenzen von 2 (falls du es noch nicht getan hast). Oder arbeiten Sie sich einfach durch Regex Golf , zu dem Prime und Powers gehören. Stellen Sie sicher, dass Sie sowohl die Classic- als auch die Teukon-Problemmenge ausführen.
Finden Sie den kürzesten Weg, um Potenzen von N abzugleichen, wobei N eine Konstante ist (dh in der Regex angegeben, nicht die Eingabe), die zusammengesetzt sein kann (aber nicht sein muss). Passen Sie zum Beispiel Potenzen von 6 an.
Finden Sie einen Weg, um N-te Potenzen abzugleichen, wobei N eine Konstante> = 2 ist. Passen Sie beispielsweise perfekte Quadrate an. (Zum Aufwärmen Primzahlen angleichen .)
Stimmen Sie mit den richtigen Multiplikationsanweisungen überein. Dreieckige Zahlen abgleichen.
Stimmen Sie mit Fibonacci-Zahlen überein (wenn Sie so verrückt sind wie ich) oder wenn Sie sich an etwas Kürzeres halten möchten, stimmen Sie mit den korrekten Exponentiationsaussagen überein (zum Aufwärmen geben Sie den Logarithmus in Basis 2 mit einer Potenz von 2 als Übereinstimmung zurück). Bonus, machen Sie dasselbe für eine beliebige Zahl, runden Sie sie, wie Sie möchten, oder für Fakultätszahlen (zum Aufwärmen passen Sie die Primorialzahlen an ).
Kombiniere viele Zahlen (wenn du so verrückt bist wie ich)
Berechnen Sie eine irrationale Zahl mit der gewünschten Genauigkeit (z. B. dividieren Sie die Eingabe durch die Quadratwurzel von 2 und geben Sie das gerundete Ergebnis als Übereinstimmung zurück).
(Die von mir geschriebene Regex-Engine kann hilfreich sein, da sie bei unären mathematischen Regexen sehr schnell ist und einen unären numerischen Modus enthält, mit dem Bereiche natürlicher Zahlen getestet werden können. Sie verfügt jedoch auch über einen Zeichenfolgenmodus, mit dem nicht-unäre oder unäre Regexe ausgewertet werden können Standardmäßig ist es ECMAScript-kompatibel, verfügt jedoch über optionale Erweiterungen (mit denen selektiv Teilmengen von PCRE oder sogar molekularer Lookahead hinzugefügt werden können, was keine andere Regex-Engine hat).
Lesen Sie andernfalls weiter und lesen Sie auch diesen GitHub Gist (Warnung, viele Spoiler), der den Weg des Drängens von ECMAScript-Regex auf natürliche Zahlenfunktionen mit zunehmendem Schwierigkeitsgrad aufzeichnet (beginnend mit Teukon's Puzzlesatz, nicht alle mathematisch), der dies ausgelöst hat Reise).
Wie bei den anderen regulären Ausdrücken für dieses Problem wird die Eingabe als zwei unäre Zahlen angegeben, die durch ein Komma getrennt sind und einen einschließenden Bereich darstellen. Es wird nur eine Nummer zurückgegeben. Der reguläre Ausdruck könnte so modifiziert werden, dass alle Zahlen, die den gleichen kleinsten und größten Primfaktor haben, als separate Übereinstimmungen \K
zurückgegeben werden. Dies erfordert jedoch einen Lookbehind mit variabler Länge und das Einfügen eines Lookahead oder das Zurückgeben des Ergebnisses als Erfassung anstelle einer Übereinstimmung.
Die hier angewandte Technik der wiederholten impliziten Division durch den kleinsten Primfaktor ist identisch mit derjenigen, die in den Match-Zeichenfolgen verwendet wird, deren Länge eine vierte Potenz der Antwort ist, die ich vor einiger Zeit veröffentlicht habe.
Ohne weiteres:
((.+).*),(?!.*(?=\1)(((?=(..+)(\5+$))\6)*)(?!\2)).*(?=\1)\K(?3)\2$
Sie können es hier ausprobieren.
Und die Freiraumversion mit Kommentaren:
# No ^ anchor needed, because this algorithm always returns a
# match for valid input (in which the first number is less than
# or equal to the second number), and even in /g mode only one
# match can be returned. You can add an anchor to make it reject
# invalid ranges.
((.+).*), # \1 = low end of range; \2 = conjectured number that is the
# smallest number in the set of the largest prime factor of each
# number in the range; note, it is only in subsequent tests that
# this is implicitly confined to being prime.
# We shall do the rest of our work inside the "high end of range"
# number.
(?! # Assert that there is no number in the range whose largest prime
# factor is smaller than \2.
.*(?=\1) # Cycle tail through all numbers in the range, starting with \1.
( # Subroutine (?3):
# Find the largest prime factor of tail, and leave it in tail.
# It will both be evaluated here as-is, and later as an atomic
# subroutine call. As used here, it is not wrapped in an atomic
# group. Thus after the return from group 3, backtracking back
# into it can increase the value of tail – but this won't mess
# with the final result, because only making tail smaller could
# change a non-match into a match.
( # Repeatedly divide tail by its smallest prime factor, leaving
# only the largest prime factor at the end.
(?=(..+)(\5+$)) # \6 = tool to make tail = \5 = largest nontrivial factor of
# current tail, which is implicitly the result of dividing it
# by its smallest prime factor.
\6 # tail = \5
)*
)
(?!\2) # matches iff tail < \ 2
)
# now, pick a number in the range whose largest prime factor is \2
.*(?=\1) # Cycle tail through all numbers in the range, starting with \1.
\K # Set us up to return tail as the match.
(?3) # tail = largest prime factor of tail
\2$ # Match iff tail == \2, then return the number whose largest
# prime factor is \2 as the match.
Der Algorithmus kann einfach nach ECMAScript portiert werden, indem der Unterprogrammaufruf durch eine Kopie des Unterprogramms ersetzt und die Übereinstimmung als Erfassungsgruppe zurückgegeben wird, anstatt \ K zu verwenden. Das Ergebnis ist 80 Byte lang:
((x+)x*),(?!.*(?=\1)((?=(xx+)(\4+$))\5)*(?!\2)).*(?=\1)(((?=(xx+)(\8+$))\9)*\2$)
Probieren Sie es online!
Beachten Sie, dass ((.+).*)
dies geändert werden kann ((.+)+)
, indem die Größe um 1 Byte (von 66 auf 65 Byte ) verringert wird, ohne dass die korrekte Funktionalität verloren geht. Der reguläre Ausdruck explodiert jedoch exponentiell in der Langsamkeit.
Probieren Sie es online! (79 Byte ECMAScript Exponential-Slow-Down-Version)