In dieser Aufgabe müssen Sie ein Programm schreiben, das einen regulären Ausdruck liest und ein anderes Programm generiert, das ausgibt, ob eine Eingabezeichenfolge von diesem regulären Ausdruck akzeptiert wird. Die Ausgabe muss ein Programm sein, das in derselben Sprache wie Ihre Einreichung geschrieben ist.
Eingang
Der Eingang ist ein regulärer Ausdruck r die folgende ABNF Matching (die anfängliche Produktionsregel ist REGEX
):
REGEX = *( STAR / GROUP / LITERAL / ALTERNATIVE )
STAR = REGEX '*'
GROUP = '(' REGEX ')'
LITERAL = ALPHA / DIGIT
ALTERNATIVE = REGEX '|' REGEX
Wenn die Eingabe nicht mit dieser Grammatik übereinstimmt, ist das Verhalten Ihres Programms undefiniert.
Deutung
Die Eingabe als regulären Ausdruck interpretieren, wobei *
der Kleene-Stern (dh das Argument links null oder mehrmals wiederholen ) |
eine Alternative darstellt (
und eine )
Gruppe und überhaupt kein Operator verkettet ist. Gruppierung hat Vorrang vor Stern, Stern hat Vorrang vor Verkettung, Verkettung hat Vorrang vor Alternative.
Eine Zeichenfolge gilt als akzeptiert, wenn der reguläre Ausdruck mit der gesamten Zeichenfolge übereinstimmt.
Ausgabe
Die Ausgabe des Programms ist ein anderes Programm, das in derselben Sprache wie Ihre Einreichung geschrieben ist und das zur Laufzeit einen String s in einer durch die Implementierung definierten Weise liest , ausgibt, ob r s akzeptiert und dann beendet. Die Ausgabe kann auf benutzerdefinierte Weise erfolgen, obwohl es für akzeptierte und abgelehnte Programme nur zwei unterschiedliche Ausgaben geben muss.
Sie können davon ausgehen, dass die Eingabe Ihres Ausgabeprogramms niemals länger als 2 16 -1 Bytes ist.
Beschränkungen
Weder Ihr Beitrag noch ein von Ihrem Beitrag erstelltes Programm dürfen eingebaute Funktionen oder Bibliotheken verwenden, die
- Spiel Regexes
- reguläre Ausdrücke transformieren
- kompiliere reguläre Ausdrücke
- Parser aus einer Grammatik generieren
- Vereinfachen Sie das Problem auf eine Weise, dass Ihre Eingabe trivial wird
Wertung
Die Punktzahl Ihrer Einreichung ist die Anzahl der Zeichen. Die Einsendung mit der niedrigsten Punktzahl gewinnt.
Testfälle
Alle Testfälle enthalten einen regulären Ausdruck, eine Reihe akzeptierter Zeichenfolgen, eine Reihe abgelehnter Zeichenfolgen und ein Beispielprogramm in C99, das eine gültige Ausgabe einer (hyptothetischen) C99-Übermittlung darstellt.
(leerer regulärer Ausdruck)
Akzeptierte Zeichenfolgen
- (leere Eingabe)
Abgelehnte Zeichenfolgen
- foo
- Bar
- baz
- quux
Beispielprogramm
#include <stdio.h>
int main() {
char input[65536];
gets(input);
return input[0] != 0;
}
(b|)(ab)*(a|)
( a
und b
abwechselnd)
akzeptierte Zeichenfolgen
a
ba
abababababa
abab
abgelehnte Zeichenfolgen
afba
foo
babba
Beispielprogramm
#include <stdio.h>
int main() {
char input[65536];
int state = 0;
for (;;) switch (state) {
case 0: switch (getchar()) {
case 'a': state = 1; break;
case 'b': state = 2; break;
case EOF: return 0;
default: return 1;
} break;
case 1: switch (getchar()) {
case 'b': state = 2; break;
case EOF: return 0;
default: return 1;
} break;
case 2: switch (getchar()) {
case 'a': state = 1; break;
case EOF: return 0;
default: return 1;
} break;
}
(0|1(0|1)*)(|A(0|1)*1)
(binäre Gleitkommazahlen)
akzeptierte Zeichenfolgen
- 10110100
- 0
- 1A00001
abgelehnte Zeichenfolgen
- 011
- 10 A
- 1A00
- 100A010
return (regex.match(stdin) is not null)
nicht erlaubt ist.Antworten:
Ruby,
641651543 ZeichenDiese rubinrote Version wurde aufgrund mehrerer Eckfälle im Regex-Parser ziemlich lang (vielleicht sollte ich einen anderen Ansatz ausprobieren). Es erwartet den regulären Ausdruck für STDIN und gibt den entsprechenden Ruby-Code für den Matcher an STDOUT aus.
Das Programm generiert direkt Code für ein NFA-ε, das dann im Matcher ausgeführt wird.
Testfall 1: (Ausgabe enthält zusätzliche Zeilenumbrüche und Einrückungen)
Testfall 2:
Ein anderes Beispiel:
Bearbeiten: Es wurde ein Übergang hinzugefügt, um den in den Kommentaren angegebenen Fehler PleaseStand zu beheben . Auch Statusinitialisierung geändert.
quelle
011
für reguläre Ausdrücke(0|1(0|1)*)(|A(0|1)*1)
führen zutrue
- es sollte seinfalse
.C 627 Zeichen
Dieses Programm behandelt sein erstes Befehlszeilenargument als Eingabe und generiert C-Code als Ausgabe.
Hier ist die Ausgabe für
(0|1(0|1)*)(|A(0|1)*1)
(mit hinzugefügten Zeilenumbrüchen):Wenn Sie als erstes Befehlszeilenargument eine gültige Eingabe angeben, wird der Beendigungsstatus 1 zurückgegeben. Andernfalls wird der Beendigungsstatus 0 zurückgegeben.
Wenn Sie das Befehlszeilenargument nicht angeben, wird in beiden Programmen ein Nullzeiger dereferenziert, wodurch ein Segmentierungsfehler verursacht wird. Ein ausreichend langer regulärer Ausdruck überläuft die Puffer dieser Übermittlung, und die Größe der Eingabe in ein generiertes Programm ist durch die Größe des Stapels begrenzt. Alle Testfälle funktionieren jedoch.
Beachten Sie, dass
e(g=h++,C=h++,0,0);
undefiniertes Verhalten eingeführt wird. Wenn beispielsweise generierte Programme nicht kompiliert werden können, können Sie versuchen, die Anweisung durchh+=2;e(g=h-1,C=h-2,0,0);
eine fünf Zeichen längere Anweisung zu ersetzen .quelle