Regex qui ne correspond que

339

Il y a des défis assez cool là - bas impliquant regex ( regex auto-correspondant , Regex validation regex )

C'est peut-être impossible, mais y a-t-il une expression régulière qui correspond SEULEMENT à elle-même?

NOTE, les délimiteurs doivent être inclus:

par exemple /thing/doit correspondre /thing/et non thing. La seule correspondance possible pour votre expression doit être l'expression elle-même. De nombreuses langues permettent l'implémentation d'une chaîne à la place d'une expression régulière. Par exemple dans Go

package main

import "fmt"
import "regexp"

func main() {

    var foo = regexp.MustCompile("bar")
    fmt.Println(foo.MatchString("foobar"))
}

mais dans l'intérêt du défi, laissez l'expression être délimitée (symbole de départ, expression, symbole de fin ex: /fancypantpattern/ou @[^2048]@), si vous souhaitez argumenter des guillemets comme délimiteur, qu'il en soit ainsi. Je pense que compte tenu de la difficulté apparente de ce problème, cela ne fera guère de différence.

Pour vous aider:

Un hack rapide que j'ai mis en place pour rubular.com (une page Web pour l'édition de ruby ​​regex):

var test = document.getElementById("test")
,regex = document.getElementById("regex")
,delimiter="/"
,options = document.getElementById("options")
,delay = function(){test.value = delimiter + regex.value + delimiter + options.value}
,update = function(e){
    // without delay value = not updated value
    window.setTimeout(delay,0);
}
regex.onkeydown = update;
options.onkeydown = update;

Même si, techniquement, il s'agit de «code golf», je serai très impressionné si quelqu'un peut trouver une réponse / prouver que c'est impossible.

Le lien est maintenant corrigé. Désolé à tous

Réponse gagnante jusqu'à présent: jimmy23013 avec 40 caractères

Dylan Madisetti
la source
3
Il est évident que toute expression rationnelle n'incluant que des littéraux fonctionnera: //, / a /, / xyz /, etc. Il serait peut-être bien de demander à la regex d'inclure une opération non littérale.
breadbox
9
les littéraux ne fonctionneront pas parce que vous devez faire correspondre les barres obliques inverses, par exemple / aaa / sera identique aaamais pas / aaa /
Dylan Madisetti
2
@DylanMadisetti Faut-il utiliser des //délimiteurs, ou pouvons-nous choisir d'autres délimiteurs (PCRE prend en charge à peu près tous les caractères, et vous pouvez notamment utiliser des parenthèses / accolades / crochets en guise de délimiteurs).
Martin Ender
3
Je pense que c’est un très bon problème mathématique / informatique et que la preuve n’est peut-être pas facile ... De nombreux théorèmes importants ont commencé comme une simple question, alors peut-être que dans 5 ans, il y aura un article de Wikipédia "Problème de Madisetti";)
Paweł Tokarz
3
Oui, exactement. Dans certaines langues (pensez à grep in bash), le délimiteur est essentiellement une chaîne vide. Donc, supposer que l'expression rationnelle nécessite des délimiteurs est déjà faux en premier lieu. En effet, puisque grep est l’une des premières implémentations de regexp, la définition canonique de regexp n’a pas de délimiteur. La manifestation la plus fausse de cette hypothèse est PHP, qui nécessite deux délimiteurs: "/et/"
slebetman le

Réponses:

590

PCRE flavour, 261 289 210 184 127 109 109 71 53 51 44 40 octets

Oui c'est possible!

<^<()(?R){2}>\z|\1\Q^<()(?R){2}>\z|\1\Q>

Essayez ici. (Mais il /est montré que c'est le délimiteur sur Regex101.)

Veuillez vous abstenir de faire des modifications inutiles (mises à jour) sur la page Regex101. Si votre édition n'implique pas réellement d'améliorer, d'essayer ou de tester cette expression rationnelle, vous pouvez la créer ou en créer de nouvelles à partir de leur page d'accueil .

La version fonctionne plus correctement sur Regex101 (44 octets):

/^\/()(?R){2}\/\z|\1\Q^\/()(?R){2}\/\z|\1\Q/

Essayez ici.

C'est beaucoup plus simple que la version originale et ça ressemble plus à un quine traditionnel. Il essaie de définir une chaîne sans l'utiliser et de l'utiliser à un endroit différent. Ainsi, il peut être placé très près d'une extrémité de la regex, afin de réduire le nombre de caractères nécessitant plus de caractères pour définir le motif correspondant et répétés plusieurs fois.

Explications:

  • \Q^\/()(?R){2}\/\z|\1\Qcorrespond à la chaîne ^\/()(?R){2}\/\z|\1\Q. Cela utilise une bizarrerie qu'il \Q...\En'est pas nécessaire de fermer, et les délimiteurs non échappés fonctionnent dans \Q. Certaines versions précédentes ne fonctionnaient donc que sur Regex101 et non localement. Mais heureusement, la dernière version a fonctionné, et j'ai utilisé plusieurs fois plus d'octets.
  • \1avant que le \Qgroupe capturé ne corresponde. Comme le groupe 1 n’existe pas dans cette option, il ne peut correspondre que dans les appels récursifs. Dans les appels récursifs, il correspond aux chaînes vides.
  • (?R){2}appelle la regex entière deux fois de manière récursive, ce qui correspond ^\/()(?R){2}\/\z|\1\Qà chaque fois.
  • () ne fait que capturer une chaîne vide dans le groupe 1, ce qui active l'autre option dans les appels récursifs.
  • ^\/()(?R){2}\/\zcorrespondances (?R){2}avec des délimiteurs ajoutés, du début à la fin. L' \/avant des appels récursifs a également permis de s'assurer que cette option elle-même ne correspond pas aux appels récursifs, car elle ne sera pas au début de la chaîne.

51 octets avec fermé \Q...\E:

/\QE\1|^\/(\\)Q(?R){2}z\/\E\1|^\/(\\)Q(?R){2}z\/\z/

Essayez ici.

Version originale, 188 octets

Merci à Martin Büttner pour avoir joué environ 100 octets!

/^(?=.{173}\Q\2\)){2}.{11}$\E\/\z)((?=(.2.|))\2\/\2\^\2\(\2\?=\2\.\2\{173}\2\\Q\2\\2\2\\\2\)\2\)\2\{2}\2\.\2\{11}\2\$\2\\E\2\\\2\/\2\\z\2\)\2\(\2\(\2\?=\2\(\2\.2\2\.\2\|\2\)\2\)){2}.{11}$/

Essayez ici.

Ou 210 octets sans \Q...\E:

/^(?=.{194}\\2\\.\)\{2}\.\{12}\$\/D$)((?=(.2.|))\2\/\2\^\2\(\2\?=\2\.\2\{194}\2\\\2\\2\2\\\2\\\2\.\2\\\2\)\2\\\2\{2}\2\\\2\.\2\\\2\{12}\2\\\2\$\2\\\2\/D\2\$\2\)\2\(\2\(\2\?=\2\(\2\.2\2\.\2\|\2\)\2\)){2}.{12}$/D

Essayez ici.

Version étendue:

/^(?=.{173}\Q\2\)){2}.{11}$\E\/\z)        # Match things near the end.
((?=(.2.|))                               # Capture an empty string or \2\ into group 2.
   \2\/\2\^\2\(\2\?=\2\.\2\{173}\2\\Q\2\\2\2\\\2\)\2\)\2\{2}\2\.
   \2\{11}\2\$\2\\E\2\\\2\/\2\\z\2\)      # 1st line escaped.
   \2\(\2\(\2\?=\2\(\2\.2\2\.\2\|\2\)\2\) # 2nd line escaped.
){2}
.{11}$/x

Les extensions aiment (?=et \1ont rendu les expressions dites "régulières" non plus régulières, ce qui rend également quines possible. La référence arrière n'est pas régulière, mais lookahead l'est.

Explication:

  • J'utilise \2\à la place de \pour échapper aux caractères spéciaux. Si \2correspond à la chaîne vide, \2\x(où xest un caractère spécial) correspond à xlui - même. Si \2correspond \2\, \2\xcorrespond à l'échappé. \2dans les deux matchs du groupe 1 peut être différent dans regex. Dans le premier temps \2devrait correspondre à la chaîne vide, et la deuxième fois \2\.
  • \Q\2\)){2}.{11}$\E\/\z(ligne 1) correspond à 15 caractères de la fin. Et .{11}$(ligne 7) correspond à 11 caractères à partir de la fin (ou avant une fin de ligne récente). Ainsi, le motif situé juste avant le deuxième motif doit correspondre aux 4 ou 3 premiers caractères du premier motif et \2\.\2\|\2\)\2\)doit donc correspondre à ...\2\)ou ...\2\. Il ne peut pas y avoir de fin de ligne car le dernier caractère devrait l'être ). Et le texte correspondant n'en contient pas d'autre )avant le plus à droite, donc tous les autres caractères doivent être dans le \2. \2est défini comme (.2.|), de sorte qu'il ne peut être que \2\.
  • La première ligne fait que l'expression entière correspond exactement à 188 caractères puisque tout a une longueur fixe. Les deux temps du groupe 1 correspondent à 45 * 2 caractères plus 29 fois \2. Et les choses après le groupe 1 correspondent à 11 caractères. Donc, la longueur totale des deux temps \2doit être exactement 3 caractères. Sachant que, \2pour la deuxième fois, il comporte 3 caractères, il doit être vide pour la première fois.
  • Tous les éléments sauf le lookahead et \2les littéraux du groupe 1. Avec les deux fois \2connus et les derniers caractères connus de la première ligne, cette expression rationnelle correspond exactement à une chaîne.
  • Martin Büttner a eu l’idée d’utiliser le préfixe pour capturer le groupe 2 et le faire chevaucher avec la partie quine. Cela supprimait les caractères non échappés de la manière habituelle entre les deux temps du groupe 1, évitait ainsi que le motif leur corresponde dans ma version originale et simplifiait beaucoup la regex.

Regex sans récursion ni références arrière, 85 octets

Quelqu'un peut dire que les expressions avec des récurrences ou des références arrières ne sont pas de véritables expressions "régulières". Toutefois, les expressions comportant uniquement une anticipation ne peuvent toujours correspondre qu'aux langues ordinaires, bien qu'elles puissent être beaucoup plus longues si elles sont exprimées par des expressions régulières traditionnelles.

/(?=.*(\QE\\){2}z\/\z)^\/\(\?\=\.\*\(\\Q.{76}\E\\){2}z\/\z)^\/\(\?\=\.\*\(\\Q.{76}\z/

Essayez ici.

610 octets sans \Q...\E(à jouer au golf):

/^(?=.{610}$)(?=.{71}(\(\.\{8\}\)\?\\.[^(]*){57}\)\{2\}\.\{12\}\$\/D$)((.{8})?\/(.{8})?\^(.{8})?\((.{8})?\?=(.{8})?\.(.{8})?\{610(.{8})?\}(.{8})?\$(.{8})?\)(.{8})?\((.{8})?\?=(.{8})?\.(.{8})?\{71(.{8})?\}(.{8})?\((.{8})?\\(.{8})?\((.{8})?\\(.{8})?\.(.{8})?\\(.{8})?\{8(.{8})?\\(.{8})?\}(.{8})?\\(.{8})?\)(.{8})?\\(.{8})?\?(.{8})?\\(.{8})?\\(.{8})?\.(.{8})?\[(.{8})?\^(.{8})?\((.{8})?\](.{8})?\*(.{8})?\)(.{8})?\{57(.{8})?\}(.{8})?\\(.{8})?\)(.{8})?\\(.{8})?\{2(.{8})?\\(.{8})?\}(.{8})?\\(.{8})?\.(.{8})?\\(.{8})?\{12(.{8})?\\(.{8})?\}(.{8})?\\(.{8})?\$(.{8})?\\(.{8})?\/D(.{8})?\$(.{8})?\)(.{8})?\(){2}.{12}$/D

Essayez ici.

L'idée est similaire.

/^(?=.{610}$)(?=.{71}(\(\.\{8\}\)\?\\.[^(]*){57}\)\{2\}\.\{12\}\$\/D$)
((.{8})?\/(.{8})?\^(.{8})?\((.{8})?\?=(.{8})?\.(.{8})?\{610(.{8})?\}(.{8})?\$(.{8})?\)
(.{8})?\((.{8})?\?=(.{8})?\.(.{8})?\{71(.{8})?\}
  (.{8})?\((.{8})?\\(.{8})?\((.{8})?\\(.{8})?\.(.{8})?\\(.{8})?\{8(.{8})?\\(.{8})?\}
    (.{8})?\\(.{8})?\)(.{8})?\\(.{8})?\?(.{8})?\\(.{8})?\\
    (.{8})?\.(.{8})?\[(.{8})?\^(.{8})?\((.{8})?\](.{8})?\*(.{8})?\)(.{8})?\{57(.{8})?\}
  (.{8})?\\(.{8})?\)(.{8})?\\(.{8})?\{2(.{8})?\\(.{8})?\}
  (.{8})?\\(.{8})?\.(.{8})?\\(.{8})?\{12(.{8})?\\(.{8})?\}
  (.{8})?\\(.{8})?\$(.{8})?\\(.{8})?\/D(.{8})?\$(.{8})?\)(.{8})?\(){2}.{12}$/D

L'expression régulière de base

Si le lookahead n'est pas autorisé, le mieux que je puisse faire maintenant est:

/\\(\\\(\\\\){2}/

qui correspond

\\(\\\(\\

Si le {m,n}quantificateur n'est pas autorisé, cela est impossible car rien qui ne peut correspondre à une seule chaîne ne peut correspondre à une chaîne plus longue qu'elle-même. Bien sûr, on peut toujours inventer quelque chose comme \qqui ne fait que correspondre /\q/, et toujours dire des expressions avec cette expression régulière. Mais apparemment, rien de tel n’est supporté par des implémentations majeures.

jimmy23013
la source
5
Impressionnant. J'ai passé un certain temps à essayer de le faire correspondre à quelque chose d'autre, sans succès.
dimanche
76
comment (l'enfer) un humain pourrait-il produire une telle chose?
xem
61
Cela mérite d'être la réponse la plus votée sur ce site.
Cruncher
44
C'est la chose la plus absurde et incroyable que j'ai jamais vue.
Alex A.
22
Quelqu'un a tweeté ce post, donc j'ai eu 49 votes positifs en un jour ...
jimmy23013