Regex (saveur PCRE), 66 (65🐌) octets
Inspiré en voyant que Martin Ender et Jaytea , deux génies de regex, ont écrit des solutions de regex à ce code de golf, j'ai écrit le mien à partir de zéro. Le fameux regex Prime-Checking n'apparaît nulle part dans ma solution.
Ne lisez pas ceci si vous ne voulez pas que la magie unaire regex vous soit gâtée. Si vous voulez essayer vous-même de découvrir cette magie, je vous recommande vivement de commencer par résoudre certains problèmes dans la regex ECMAScript:
- Faites correspondre les nombres premiers (si vous n'êtes pas déjà habitué à le faire dans regex)
- Faites correspondre les pouvoirs de 2 (si vous ne l'avez pas déjà fait). Vous pouvez également vous frayer un chemin dans Regex Golf , qui comprend Prime et Powers. Assurez-vous de faire les ensembles de problèmes Classic et Teukon.
Trouvez le moyen le plus rapide de faire correspondre les puissances de N, où N est une constante (c'est-à-dire spécifiée dans la regex, pas dans l'entrée) qui peut être composite (mais ne doit pas nécessairement l'être). Par exemple, associez des puissances de 6.
Trouvez une façon de faire correspondre les Nièmes puissances, où N est une constante> = 2. Par exemple, faites correspondre les carrés parfaits. (Pour un échauffement, faites correspondre les principaux pouvoirs .)
Faites correspondre les déclarations de multiplication correctes. Correspondre à des nombres triangulaires.
Faites correspondre les chiffres de Fibonacci (si vous êtes aussi fou que moi), ou si vous voulez vous en tenir à quelque chose de plus court, faites correspondre les déclarations d'exonentiation correctes (pour un échauffement, renvoyez en tant que correspondance le logarithme en base 2 d'une puissance de 2 - bonus, faites la même chose pour n’importe quel nombre, en l’arrondissant comme vous le souhaitez) ou en nombres factoriels (pour un échauffement, faites correspondre les nombres premiers ).
Associez des nombres abondants (si vous êtes aussi fou que moi)
Calculer un nombre irrationnel à la précision demandée (par exemple, diviser l’entrée par la racine carrée de 2 et renvoyer le résultat arrondi sous la forme d’une correspondance)
(Le moteur de regex que j'ai écrit peut être utile, car il est très rapide avec les expressions rationnelles mathématiques unaires et inclut un mode numérique unaire qui permet de tester les plages de nombres naturels (mais également un mode chaînes permettant d'évaluer des expressions rationnelles non unaires Par défaut, il est compatible ECMAScript, mais comporte des extensions facultatives (qui peuvent ajouter de manière sélective des sous-ensembles de PCRE, ou même une apparence moléculaire, quelque chose qu'aucun autre moteur d'expression rationnelle n'a).)
Sinon, lisez la suite et lisez également ce GitHub Gist (avertissement, de nombreux spoilers) qui décrit le parcours consistant à pousser la regex ECMAScript à s’attaquer aux fonctions des nombres naturels de difficulté croissante (à commencer par les énigmes de teukon, qui ne sont pas toutes mathématiques, ce qui a déclenché cette périple).
Comme avec les autres solutions regex à ce problème, l'entrée est donnée sous forme de deux nombres dans unary bijective, séparés par une virgule, représentant une plage inclusive. Un seul numéro est renvoyé. L'expression rationnelle peut être modifiée pour renvoyer tous les nombres partageant le même plus petit facteur premier, sous forme de correspondances distinctes, mais cela nécessiterait une recherche de longueur variable et une mise \K
en attente ou un résultat renvoyé sous forme de capture au lieu d'une correspondance.
La technique utilisée ici de division implicite répétée par le plus petit facteur premier est identique à celle utilisée dans les chaînes de correspondance dont la longueur est une quatrième réponse puissante que j'ai postée il y a quelque temps.
Sans plus tarder:
((.+).*),(?!.*(?=\1)(((?=(..+)(\5+$))\6)*)(?!\2)).*(?=\1)\K(?3)\2$
Vous pouvez l'essayer ici.
Et la version à espace libre, avec des commentaires:
# 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.
L'algorithme peut être facilement porté sur ECMAScript en remplaçant l'appel de sous-routine par une copie du sous-routine et en renvoyant la correspondance en tant que groupe de capture au lieu d'utiliser \ K. Le résultat est 80 octets de longueur:
((x+)x*),(?!.*(?=\1)((?=(xx+)(\4+$))\5)*(?!\2)).*(?=\1)(((?=(xx+)(\8+$))\9)*\2$)
Essayez-le en ligne!
Notez que vous ((.+).*)
pouvez modifier cette option en ((.+)+)
supprimant la taille d'1 octet (de 66 à 65 octets ) sans perte de la fonctionnalité correcte - mais l'expression régulière explose de manière exponentielle par lenteur.
Essayez-le en ligne! (Version 79 octets ECMAScript à ralentissement exponentiel)