Sie müssen ein Programm erstellen, das die Syntax von Programmen derselben Sprache überprüfen kann. Wenn Sie dies beispielsweise in Python tun, wird die Python-Syntax überprüft. Ihr Programm erhält ein Programm bei Standardeingabe und überprüft, ob seine Syntax korrekt ist oder nicht. Wenn es korrekt ist, geben Sie bei der Standardausgabe nur "true" aus. Wenn nicht, geben Sie bei der Standardausgabe nur "false" aus.
Ihr Programm muss jedoch in einem Fall falsch sein. Wenn ein eigener Quellcode eingegeben wird, wird bei der Standardausgabe nur "false" ausgegeben. Dies ist Code Golf, also gewinnt das kürzeste Programm!
Hinweis: Obwohl dies technisch gesehen kein Quine ist, müssen Sie die Quine-Regeln befolgen. Dies bedeutet, dass Sie nicht über das Dateisystem oder was auch immer auf Ihren Quellcode zugreifen können.
Hinweis: Sie können kein Programm beanspruchen, das aufgrund eines Syntaxfehlers nicht ausgeführt werden konnte, um diese Herausforderung zu lösen, da es ausführbar sein muss.
try:exec(raw_input())...
erlaubt?Antworten:
Ruby 2.0, 65
76 164FigurenDies verwendet Rubys eingebauten Syntaxprüfer (
ruby -c
), um die Syntax der Eingabe zu überprüfen, was bedeutet, dass der Code nicht ausgewertet wird.Grundlegendes Anwendungsbeispiel:
Erläuterung
Diese Lösung basiert (war) auf dem Standard-Ruby-Quine:
%p
ist der Formatbezeichner fürarg.inspect
, der verglichen werden kann mituneval
: Wenneval
Sie die von zurückgegebene Zeichenfolge eingebenarg.inspect
, erhalten Sie (normalerweise) wieder den ursprünglichen Wert. Wenn Sie also dieq
Zeichenfolge mit sich selbst als Argument formatieren , wird das%p
Innere der Zeichenfolge durch die angegebene Zeichenfolge selbst ersetzt (dh wir erhalten so etwas wie"q=\"q=%p;puts q%%q\";puts q%q"
).Die Verallgemeinerung dieser Art von Quine führt zu folgenden Ergebnissen:
Dieser Ansatz hat jedoch einen großen Nachteil (zumindest beim Code-Golf ): Der gesamte Code muss dupliziert werden. Glücklicherweise
eval
kann verwendet werden, um dies zu umgehen:Was hier passiert, ist, dass der an eval übergebene Code darin gespeichert wird,
r
bevor ereval
aufgerufen wird. Infolgedessen kann der vollständige Quellcode dereval
Anweisung mit abgerufen werden'eval r=%p'%r
. Wenn wir dies imeval
d-Code tun und sicherstellen, dass die oberste Ebene von uns nur aus der eineneval
Anweisung besteht, gibt uns dieser Ausdruck tatsächlich den vollständigen Quellcode unseres Programms, da jeder zusätzliche Code, der an übergebeneval
wird, bereits darin gespeichert istr
.Randnotiz: Mit diesem Ansatz können wir tatsächlich eine Ruby-Quine in 26 Zeichen schreiben:
eval r="puts'eval r=%p'%r"
In dieser Lösung besteht der zusätzliche Code, der darin ausgeführt wird,
eval
aus vier Anweisungen:Zuerst lesen wir alle Eingaben von STDIN und speichern sie implizit in
$_
.Anschließend spulen wir STDIN zurück, damit die Eingabe für den im nächsten Schritt gestarteten Unterprozess wieder verfügbar ist.
Dadurch wird Ruby in seinem integrierten Syntaxprüfmodus gestartet und der Quellcode von stdin gelesen. Wenn die Syntax des mitgelieferten Skript (Dateiname oder stdin) OK ist, druckt er
Syntax OK
in seine stdout (die von der Eltern - Prozess erfasst wird), aber im Falle eines Syntaxfehlers, einer Beschreibung des Fehlers auf gedruckten Stderr - die würden sichtbar sein, also leiten wir das2>&0
stattdessen in nirvana ( ) um.Anschließend überprüfen wir den Exit-Code des Unterprozesses
$?
, der 0 ist, wenn die Syntax in Ordnung war. Zuletzt wird die Eingabe, die wir zuvor gelesen haben ($_
), mit unserem eigenen Quellcode verglichen (der, wie ich zuvor beschrieben habe, mit erhalten werden kann'eval r=%p'%r
).Bearbeiten: 14 Zeichen dank @histocrat gespeichert!
quelle
.write
mit<<
, und>>1<1
mit==0
.==
in denProcess::Status
Dokumenten verpasst . Vielen Dank!Rebol - 69 oder 74
75voll konform mit allen RegelnNeue Arbeitsversionen dank @rgchris! Nicht sicher, ob die erste Anforderung "Nicht auf die Quelle zugreifen" fehlschlägt, da der Interpreter den geladenen und analysierten Code enthält, der als cmd-Zeilenparameter im Systemobjekt (
system/options/do-arg
) übergeben wurde, das verwendet wird, um sich selbst zu erkennen.Dieser folgt allen Regeln:
Anwendungsbeispiel:
Zuerst wird eine gültige Ganzzahl gedruckt, dann wird eine ungültige Ganzzahl gedruckt.
Vollständig konforme Version:
Erläuterung:
Erste Version
Dies verwendet die in Rebols integrierte
load
Funktion, um den Code von stdin zu analysieren und zu laden, führt ihn jedoch nicht aus.Der
try
Block fängt alle Syntaxfehler ab und dieerror?
Funktion konvertiert den Fehler in einen einfachen Booleschen Wert.Das
i = system/options/do-arg
vergleicht die Eingabe von stdin (zugewiesen ani
) mit dem Code, der an dasdo-arg
Argument übergeben wurde (hinterhältig, aber sehr golf :).any
ist eine großartige Funktion, die zurückgibt,true
wennany
-thing im Block ausgewertet wirdtrue
(zum Beispiel zurückgebenany [ false false true ]
würdetrue
).not
Invertiert dann einfach den Booleschenprobe
Wert , um die richtige Antwort zu erhalten, und zeigt den Inhalt des zurückgegebenen Werts an.Vollständig konforme Version
Lassen Sie uns dies der Reihe nach durchgehen ...
Weisen Sie das Wort
b
dem folgenden Block [] zu.Verwenden Sie die
do
Funktion, um dendo
Dialekt imb
Block zu interpretieren .Innerhalb des
b
Blocks ...Stellen Sie das Wort so ein
i
, dass es auf den Inhalt von stdin (input
) verweist .Jetzt setzen
if
wirjoin
den String "do b:" auf denmold
'ed-Blockb
und er ist nicht gleich (<>
) für die stdin-Eingabe,i
dann versuchen wirload
die Eingabei
.Wenn das Ergebnis a ist
block
, haben wirload
die übergebenen Daten korrekt bearbeitet, andernfalls würden wir einenone
von den fehlgeschlagenen erhaltenif
.Verwenden Sie
prin
diese Option , um das Ergebnis anzuzeigen,block?
dessen Wert true zurückgibt, wenn das Ergebnis ein Block ist. Wenn Sieprin
im Gegensatz zuprint
verwenden, wird nach der Ausgabe kein Wagenrücklauf angezeigt (und es wird ein weiteres Zeichen gespeichert).quelle
print not error? try[load/all input]
c:[c: compose/only [c: (c)]print not error? try[if c = load/all input[1 / 0]]]
(prin none? attempt[load/all input] halt) 1a
Die ungültige Ganzzahl würde diechecksum/secure
Ihr Programm können und den Hash zu Vergleichszwecken in die Quelle selbst aufnehmen, möchte ich Ihre Dienste in mein Cybercrime-Syndikat aufnehmen. Wenn nicht, beginnen Sie mit meinem Code, der funktioniert. :-)do B[pb bl? iu a jn "do B" ml b [try [ld/all a]]]
Javascript -
8682Fügen Sie zum Testen in die Javascript-Konsole Ihres Browsers ein.
Erläuterung:
Hinweis: @ m.buettner hat den Punkt angesprochen, dass das Programm
true
für eine nackte return-Anweisung zurückgibt , zreturn 0;
. Da Javascript keinen Syntaxfehler für eine unzulässige return-Anweisung auslöst, bis sie tatsächlich ausgeführt wird (was bedeutet, dass Code wieif (0) { return 0; }
kein Syntaxfehler auslöst), gibt es meines Erachtens keine Möglichkeit, dieses Problem beim Schreiben eines Javascript-Parsers in Javascript zu beheben . Betrachten Sie zum Beispiel den Code:Wenn der Code ausgeführt wird, bleibt er aufgrund der Schleife hängen. Wenn der Code nicht ausgeführt wird, wird kein Fehler für die unzulässige return-Anweisung ausgegeben. Daher ist dies so gut wie Javascript für diese Herausforderung bekommen kann. Sie können Javascript jederzeit disqualifizieren, wenn Sie der Meinung sind, dass dies die Herausforderung nicht ausreichend erfüllt.
quelle
return 0
.Haskell - 222 Bytes
Beachten Sie, dass hierfür ein echter Parser verwendet wird. Es hängt nicht von
eval
ähnlichen Funktionen dynamischer Sprachen ab.Diese Lösung ist nicht besonders hübsch, funktioniert aber.
quelle
if take ...
Anweisung prüft, ob die Eingabe mit einem Zeichenfolgenliteral übereinstimmt, das der erste Teil des Programms ist.Ich denke, das folgt den Regeln:
JS (✖╭╮✖)
function f(s){if(s==f.toString())return false;try{eval(s)}catch(e){return false}return true}
Der Code wird ausgewertet, wenn er korrekt ist.
Schauen Sie sich die Pfeilnotation an, um zu sehen, ob sie nicht mehr gekürzt werden kann.!function f(){try{s=prompt();return"!"+f+"()"!=s?eval(s):1}catch(e){return 0}}()
Nach ein paar fehlgeschlagenen Versuchen und Zurücksetzen - neue Version!!function f(){try{s=prompt();"!"+f+"()"!=s?eval(s):o}catch(e){return 1}}()
Und ich bin zurück!!function f(){try{s=prompt();"!"+f+"()"!=s?eval(s):o}catch(e){return !(e instanceof SyntaxError)}}()
Und ich bin weg! Leider funktioniert dieser Ansatz aufgrund der Art der Bewertung und dank @scragar (verdammt noch mal @scragar!) Nicht (da
throw new SyntaxError
es sich um einen gültigen JS-Code handelt, der diese Methode aktiviert ) - als solches würde ich sagen, dass es unmöglich ist, einen zu erstellen Syntaxprüfer (zumindest unter Verwendung von eval oder einer Variation davon)(* siehe Kommentare!)
quelle
eval("x=function(){"+t+"}");
}//
oder gebrochen werden};{
.Error
nichtException
.throw new Error('')
verursacht das falsche Verhalten.Python (95)
quelle
c=u'#\u1e91'
weilord('#') + ord(u'\u1e91') == 7860
PHP - 140
Kommentar erforderlich, um den 'Hash' zu behalten (eine schamlose Kopie von s, ɐɔıʇǝɥʇuʎs). Verwenden Sie php -l / lint, um nach Fehlern zu suchen.
quelle
C 174
Erläuterung - Die Wand muss einen Systemfehler erzeugen, während sie noch kompilierbar ist. Der Syntaxfehler lautet no.
return 0;
Um nach dem Einfügen über stdin in die Windows-Konsole einzugeben, geben Sie Strg-Z ein und drücken Sie die Eingabetaste.Golf gespielt
Ungolfed:
quelle
T-SQL - 110
Ziemlich einfach, ich wollte hier schon eine Weile eine Herausforderung ausprobieren und bin endlich dazu gekommen. Dies ist nicht der schickste Code, aber ich hatte trotzdem Spaß.
Die "Golf" -Version.
Eine besser formatierte Version.
Es ist ziemlich selbsterklärend und verwendet SET NOEXEC, wodurch die Abfrage nur analysiert wird, anstatt Ergebnisse zurückzugeben. Der Rest ist meistens der Versuch / Fang, mit dem ich feststelle, was ich drucken muss.
EDIT: Ich hätte hinzufügen sollen, dass dies technisch für sich selbst scheitern wird. Da dynamisches SQL verwendet wird, müssen alle einfachen Anführungszeichen in der Eingabe verdoppelt werden. '->' '
quelle