Regex che corrisponde solo a se stesso


339

Ci sono alcune sfide piuttosto interessanti là fuori che coinvolgono regex (regex auto-matching , regex di convalida Regex )

Questo potrebbe essere impossibile, ma esiste una regex che si abbinerà SOLO a se stessa?

NOTA, i delimitatori devono essere inclusi:

per esempio /thing/deve corrispondere /thing/e non thing. L'unica corrispondenza possibile per la tua espressione deve essere l'espressione stessa. Molte lingue consentono l'implementazione di una stringa al posto di un'espressione regolare. Ad esempio in Go

package main

import "fmt"
import "regexp"

func main() {

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

ma per il bene della sfida, lascia che l'espressione sia delimitata (simbolo di inizio, espressione, simbolo di fine es: /fancypantpattern/o @[^2048]@), se vuoi discutere le virgolette come delimitatore, così sia. Penso che, data l'apparente difficoltà di questo problema, non farà molta differenza.

Per aiutarti lungo:

Trucco rapido che ho messo insieme per rubular.com (una pagina web per l'editing di 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;

Anche se tecnicamente si tratta di "codice golf", rimarrò molto colpito dal fatto che qualcuno possa trovare una risposta / dimostrare che è impossibile.

Il collegamento è ora risolto. Mi dispiace a tutti

Risposta vincente finora: jimmy23013 con 40 caratteri


3
Ovviamente qualsiasi espressione regolare che includa solo valori letterali funzionerà: //, / a /, / xyz /, ecc. Potrebbe essere utile richiedere che il regex debba includere un'operazione non letterale.
breadbox,

9
i valori letterali non funzioneranno perché è necessario abbinare le barre rovesciate ad esempio / aaa / corrisponderà aaama non / aaa /
Dylan Madisetti,

2
@DylanMadisetti Dobbiamo usare i //delimitatori o possiamo scegliere altri delimitatori (PCRE supporta praticamente qualsiasi carattere, e in particolare puoi usare parentesi / parentesi graffe / parentesi abbinate come delimitatori).
Martin Ender,

3
Penso che questo sia un bel problema matematico / computazionale e la prova potrebbe non essere facile ... Molti teoremi importanti sono iniziati come una semplice domanda con cui giocare, quindi forse tra 5 anni ci sarà l'articolo di Wikipedia "Problema Madisetti";)
Paweł Tokarz,

3
Si, esattamente. In alcune lingue (pensa grep in bash) il delimitatore è essenzialmente una stringa vuota. Quindi supporre che regexp richieda delimitatori è già sbagliato in primo luogo. Infatti, poiché grep è una delle prime implementazioni di regexp, la definizione canonica di regexp non ha delimitatori. La manifestazione più sbagliata di questa ipotesi è PHP che richiede due delimitatori: "/e/"
slebetman,

Risposte:


590

Sapore PCRE, 261 289 210 184 127 109 71 53 51 44 40 byte

Sì, è possibile!

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

Provalo qui. (Ma /si dimostra che è il delimitatore su Regex101.)

Si prega di astenersi dal fare modifiche non necessarie (aggiornamenti) sulla pagina Regex101. Se la tua modifica in realtà non comporta il miglioramento, il tentativo o il test di questa regex, puoi forkarla o crearne di nuovi dalla loro homepage .

La versione funziona più correttamente su Regex101 (44 byte):

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

Provalo qui.

Questo è molto più semplice rispetto alla versione originale e funziona più come un quine tradizionale. Cerca di definire una stringa senza usarla e di usarla in un posto diverso. Quindi può essere posizionato molto vicino a un'estremità della regex, per ridurre il numero di caratteri che necessitano di più caratteri per definire il modello di corrispondenza e ripetersi più volte.

spiegazioni:

  • \Q^\/()(?R){2}\/\z|\1\Qcorrisponde alla stringa ^\/()(?R){2}\/\z|\1\Q. Questo utilizza una stranezza che \Q...\Enon deve essere chiusa e funzionano i delimitatori senza escape \Q. Ciò ha fatto funzionare alcune versioni precedenti solo su Regex101 e non localmente. Ma fortunatamente l'ultima versione ha funzionato, e ho usato qualche altro byte usando questo.
  • \1prima che \Qcorrisponda al gruppo catturato 1. Poiché il gruppo 1 non esiste in questa opzione, può corrispondere solo nelle chiamate ricorsive. Nelle chiamate ricorsive corrisponde a stringhe vuote.
  • (?R){2}chiama ricorsivamente l'intero regex due volte, che corrisponde ^\/()(?R){2}\/\z|\1\Qper ogni volta.
  • () non fa altro che catturare una stringa vuota nel gruppo 1, che abilita l'altra opzione nelle chiamate ricorsive.
  • ^\/()(?R){2}\/\zcorrispondenze (?R){2}con delimitatori aggiunti, dall'inizio alla fine. Il \/prima delle chiamate ricorsive si è anche assicurato che questa stessa opzione non corrispondesse alle chiamate ricorsive, perché non sarà all'inizio della stringa.

51 byte con chiuso \Q...\E:

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

Provalo qui.

Versione originale, 188 byte

Grazie a Martin Büttner per aver giocato a golf a circa 100 byte!

/^(?=.{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}$/

Provalo qui.

O 210 byte senza \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

Provalo qui.

Versione estesa:

/^(?=.{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

Le estensioni come (?=e \1hanno reso le cosiddette espressioni "regolari" non più regolari, il che rende anche possibili le quine. Il backreference non è regolare, ma lo è lookahead.

Spiegazione:

  • Uso \2\al posto di \per sfuggire a personaggi speciali. Se \2corrisponde alla stringa vuota, \2\x(dove xè un carattere speciale) corrisponde alla xstessa. Se \2corrisponde \2\, \2\xcorrisponde a quello evaso. \2nelle due partite del gruppo 1 può essere diverso in regex. Nella prima volta \2dovrebbe corrispondere alla stringa vuota e la seconda volta \2\.
  • \Q\2\)){2}.{11}$\E\/\z(riga 1) corrisponde a 15 caratteri dalla fine. E .{11}$(riga 7) corrisponde a 11 caratteri dalla fine (o prima di una nuova riga finale). Quindi il modello appena prima del secondo motivo deve corrispondere ai primi 4 o 3 caratteri nel primo motivo, quindi \2\.\2\|\2\)\2\)deve corrispondere a ...\2\)o ...\2\. Non ci può essere una nuova riga finale perché dovrebbe essere l'ultimo carattere ). E il testo corrispondente non ne contiene un altro )prima di quello più a destra, quindi tutti gli altri caratteri devono essere nel \2. \2è definito come (.2.|), quindi può essere solo \2\.
  • La prima riga fa sì che l'intera espressione corrisponda esattamente a 188 caratteri poiché tutto ha una lunghezza fissa. Le due volte del gruppo 1 corrispondono a 45 * 2 caratteri più 29 volte \2. E le cose dopo il gruppo 1 corrispondono a 11 caratteri. Quindi la lunghezza totale delle due volte \2deve essere esattamente di 3 caratteri. Sapendo \2per la seconda volta che è lungo 3 caratteri, deve essere vuoto per la prima volta.
  • Tutto tranne il lookahead e \2sono letterali nel gruppo 1. Con le due volte \2conosciute e gli ultimi pochi caratteri noti dalla prima riga, questa regex corrisponde esattamente a una stringa.
  • Martin Büttner ha avuto l'idea di usare lookahead per catturare il gruppo 2 e farlo sovrapporre con la parte quine. Ciò ha rimosso i personaggi non sfuggiti nel modo normale tra le due volte del gruppo 1, e ha aiutato a evitare lo schema per abbinarli nella mia versione originale e ha semplificato molto la regex.

Regex senza ricorsioni o riferimenti secondari, 85 byte

Qualcuno potrebbe obiettare che le espressioni con ricorsioni o riferimenti arretrati non sono vere espressioni "regolari". Ma le espressioni con solo un lookahead possono ancora corrispondere solo alle lingue normali, sebbene possano essere molto più lunghe se espresse dalle espressioni regolari tradizionali.

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

Provalo qui.

610 byte senza \Q...\E(da giocare a 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

Provalo qui.

L'idea è simile.

/^(?=.{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'espressione regolare di base

Se lookahead non è permesso, il meglio che posso fare ora è:

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

che corrisponde

\\(\\\(\\

Se il {m,n}quantificatore non è consentito, è impossibile perché nulla che può corrispondere a una sola stringa può corrispondere a una stringa più lunga di se stessa. Naturalmente si può ancora inventare qualcosa di simile \qche corrisponde solo /\q/e dire espressioni con quel normale. Ma a quanto pare nulla di simile è supportato da importanti implementazioni.


5
Degno di nota. Ho trascorso un po 'di tempo cercando di farlo corrispondere a qualcos'altro, senza successo.
primo

76
come (diavolo) un essere umano potrebbe produrre una cosa del genere?
xem,

61
Questo merita di essere la risposta più votata su questo sito.
Cruncher,

44
Questa è la cosa più assurda, incredibile che abbia mai visto.
Alex A.

22
Qualcuno ha twittato questo post così ho ottenuto 49 voti in un giorno ...
jimmy23013
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.