Quote-Safe Quines

17

Ihre Aufgabe ist einfach: Schreiben Sie ein Programm (oder eine Funktion), das keine Eingaben vornimmt und den Quellcode ausgibt (oder zurückgibt). Der Haken ist, dass wenn das Programm in "quotes"(Unicode-Zeichen 34) eingeschlossen ist, es wieder seinen (jetzt zitierten) Quellcode ausgeben sollte.

Es gelten die Standardregeln für Quines. Das ist , also gewinnt das kürzeste Programm (in Bytes).

Esolanging Fruit
quelle
8
@ATaco kreativ denken. Der Code in Anführungszeichen ist in der Regel nicht ausgeführt wird , aber wenn das gesamte Programm mit Anführungszeichen umgeben ist , diese Abschnitte werden ausgeführt.
Pavel
1
Hmm, guter Punkt.
ATaco
Dies funktioniert möglicherweise mit BF bei Implementierungen, die !
Folgendes
1
Müssen Sie verwenden "? Einige Sprachen unterstützen zwei oder drei Anführungszeichen.
Neil
1
@tkellehe Meta: Was zählt als richtige Quine? Soweit ich Ihre 1-Byte-Quine verstehe, verstößt sie gegen die Code- / Datenanforderungen, die im am höchsten bewerteten Beitrag formuliert sind.
Laikoni

Antworten:

4

Nudel , 9 7 Bytes

Diese Version funktioniert genauso wie die andere, nur dass ich vergessen habe, dass Noodel einen Codeblock einmal ausführen kann, und ich habe die Sprache ...

Ḷ1ḥ-Ð1ḥ@€

ḷḥ-Ðḥ@ḅ

Versuch es:)


Wie es funktioniert

ḷḥ-Ðḥ@ḅ # Single statement that builds itself as a string.
ḷ       # Loop the following block of code unconditionally.
 ḥ-     # Push the string literal of the token preceding this one which pushes "ḷ" onto the stack.
   Ð    # Push the stack as an array to stdout (since is an array it is done by reference).
    ḥ@  # Push the string literal for this block of code which pushes "ḥ-Ðḥ@ḅ" onto the stack.
      ḅ # Break out of the given loop. (The stack is now ["ḷ", "ḥ-Ðḥ@ḅ"]).

        # The top of the stack is popped off and displayed which modifies the array to produce {["ḷ"], "ḥ-Ðḥ@ḅ"} in stdout.

Zitat-Sicherheit

Das Platzieren des "Zeichens vor und nach dem Programm funktioniert, da Noodel eine Reihe von Zeichen hat, die dem gewidmet sind, was ich als Ausdrucke bezeichne . Diese werden sofort als String-Literale analysiert, wenn sie von selbst platziert werden, und ermöglichen es, einfach etwas auf den Bildschirm zu drucken. Im Gegensatz zu den meisten Sprachen sieht Noodel die normale ASCII- Menge, die als druckwürdig eingestuft wird, als direkte Zeichenfolgenliterale (mit Ausnahme von Leerzeichen und Zeilenvorschub), in denen der Code lediglich als Zeichenfolgen-Push betrachtet wird.

"ḷḥ-Ðḥ@ḅ"

"         # Pushes on the string literal "\"" onto the stack.

 ḷḥ-Ðḥ@ḅ  # Same execution as before, simply builds the Quine for this loop.
 ḷ        # Loop the following block of code unconditionally.
  ḥ-      # Push the string literal of the token preceding this one which pushes "ḷ" onto the stack.
    Ð     # Push the stack as an array to stdout (since is an array it is done by reference).
     ḥ@   # Push the string literal for this block of code which pushes "ḥ-Ðḥ@ḅ" onto the stack.
       ḅ  # Break out of the given loop. (The stack is now ["\"", "ḷ", "ḥ-Ðḥ@ḅ"]).

        " # Pushes on the string literal "\"" onto the stack.

          # The top of the stack is popped off and displayed which modifies the array to produce {["\"", "ḷ", "ḥ-Ðḥ@ḅ"], "\""} in stdout.

"Versuch es:)"


Schnipsel

<div id="noodel" code='ḷḥ-Ðḥ@ḅ' input="" cols="10" rows="1"></div>
<script src="https://tkellehe.github.io/noodel/noodel-latest.js"></script>
<script src="https://tkellehe.github.io/noodel/ppcg.min.js"></script>


<div id="noodel" code='"ḷḥ-Ðḥ@ḅ"' input="" cols="10" rows="1"></div>
<script src="https://tkellehe.github.io/noodel/noodel-latest.js"></script>
<script src="https://tkellehe.github.io/noodel/ppcg.min.js"></script>

tkellehe
quelle
Ich denke nicht, dass die Verwendung egültig ist. Die Frage fragt nicht nach dem als Byte 34 codierten Zeichen, sondern nach dem Unicode-Zeichen 34. Egal welche Codierung Sie verwenden, es gibt nur eine:"
Dennis
@ Tennis, ich vermute, was Sie sagen, ist der Verweis auf das Unicode-Zeichen 34 nur, um sicherzustellen, dass alle das gleiche verwendeten "? (Entschuldigung, ich versuche nur sicherzustellen, dass ich verstehe, was Sie sagen.) Sollte ich auch den gesamten Text in der Antwort entfernen, der sich auf die Verwendung bezieht e?
Tkellehe
1
Ja, es gibt Tausende von Codierungen, aber nur einen Unicode-Zeichensatz. Da "funktioniert, würde ich einfach die Diskussion entfernen und einfach nutzen ".
Dennis
11

Python 2 3, 181 152 130 124 122 Bytes

""" """>" "or exec("oct=0");p='"""" """>" "or exec("oct=0");p=%r;a=oct==0;print(p[a:~a]%%p)#".';a=oct==0;print(p[a:~a]%p)#

Probieren Sie es online! Das TIO wird mit einer Kopf- und Fußzeile geliefert, die automatisch die Gültigkeit des Quines überprüft. Sie können sie löschen, um nur das Quine auszuführen.

Dieser Code funktioniert unter Verwendung der dreifach in Anführungszeichen gesetzten Zeichenfolgen in Python. """ """ist gleich ' 'und """" """ist gleich '" '.

Der Code verwendet exec, aber nicht für die "nicht quiney" Art der Ausführung von Daten als Code, nur zum Setzen einer Variablen innerhalb eines Ausdrucks. Das execist auch in den Daten richtig codiert.

Die erste Anweisung vergleicht die Zeichenfolge, möglicherweise mit einem vorangestellten Anführungszeichen, mit " "und setzt die Variable octentsprechend. (Die Variable könnte eine beliebige Kurzvariable sein.)

Der Rest des Codes implementiert dann das traditionelle Python-Quine unter Verwendung der %rZeichenfolgenformatierung mit zusätzlichem Code, der die zusätzlichen Anführungszeichen entfernt, wenn er octunverändert bleibt.

Eine alternative Version, die "cheaty" verwendet, enthält exec126 Bytes mit weniger wiederholtem Code:

""" """>" "and exec("oct=0");s='"""" """>" "and exec("oct=0");s=%r;p=%r;exec(p)#".';p='a=oct!=0;print(s[a:~a]%(s,p))';exec(p)#

Probieren Sie es online!

PurkkaKoodari
quelle
7

StandardML , 182 176 108 Bytes

";str(chr 34)^it;(print(it^it);fn x=>print(x^it^x^it))";str(chr 34)^it;(print(it^it);fn x=>print(x^it^x^it))

Nicht zitierte Version: Probieren Sie es auf Codingground.
Zitierte Version: Probieren Sie es auf Codingground.

Beachten Sie, dass die Ausgabe ungefähr so ​​aussieht

> val it = "{some string}" : string
> val it = "{some string}" : string
{output to stdout}> val it = fn : string -> unit

weil der Code deklarationsweise interpretiert wird (jede Deklaration ;endet) und den Wert und den Typ jeder Deklaration anzeigt.


Hintergrund

In SML gibt es eine Quine der Form <code>"<code in quotes>":

str(chr 34);(fn x=>print(x^it^x^it))"str(chr 34);(fn x=>print(x^it^x^it))" 

und eine in der Form "<code in quotes>"<code>:

";str(chr 34)^it;print(it^it)";str(chr 34)^it;print(it^it)

Beide stützen sich auf die Tatsache, dass der <code>-Teil keine Anführungszeichen enthält und somit ohne die Notwendigkeit, irgendetwas zu entgehen, zitiert werden kann, die "zur Ausgabe des Quines erforderlich sind, gegeben durch str(chr 34).

Sie hängen auch stark von der impliziten Kennung ab, itdie verwendet wird, wenn in einer Deklaration keine explizite Kennung angegeben ist.

Im ersten str(chr 34);bindet quine an itdie Zeichenkette, die enthält ", fn x=>startet eine anonyme Funktion mit einem Argument x, verkettet x^it^x^itund druckt die resultierende Zeichenkette. Diese anonyme Funktion wird direkt auf eine Zeichenfolge angewendet, die den Programmcode enthält, sodass sich die Verkettung x^it^x^itergibt <code>"<code>".

Das zweite Quine beginnt nur mit dem Programmcode als String, an ";str(chr 34)^it;print(it^it)";den gebunden wird it. Dann str(chr 34)^it;verkettet ein Zitat an den Anfang des Strings und als wieder keine explizite Kennung gegeben wird, den resultierenden String"<code> ist gebunden it. Schließlich print(it^it)verkettet die Zeichenfolge mit sich selbst ergibt , "<code>"<code>die dann gedruckt wird.


Erläuterung

Bearbeiten: Mit der 108-Byte-Version nicht mehr auf dem neuesten Stand, aber man könnte es auch nach dem Lesen dieser Erklärung verstehen.

Die Quine, die für Anführungszeichen sicher ist, kombiniert beide oben genannten Ansätze und ist selbst von der Form "<code>"<code> . Wenn Sie dies erneut in Anführungszeichen setzen ""<code>"<code>", erhalten Sie eine leere Zeichenfolge und dann eine Quine der anderen Form.

Das heißt, das Programm erhält entweder eine eigene Quelle in Form "<code>des Bezeichners it, oder es itist gerecht "und wir erhalten eine eigene Quelle<code> als Argument und müssen daher eine Funktion sein, die mit einem solchen Argument umgeht.

(if size it>1then(print(it^it);fn _=>())else fn x=>print(it^it^x^it^x^it))

Um festzustellen, in welchem ​​Fall wir uns befinden, prüfen wir, ob die Größe von itgrößer als 1 ist. Wenn nicht, itist dies "der Fall, und wir befinden uns im zweiten Fall, sodass der else-Teil eine anonyme Funktion zurückgibtfn x=>print(it^it^x^it^x^it) die dann aufgerufen wird, weil die Quelle als Zeichenfolge folgt . Beachten Sie den it^it^Zeilenabstand, der zu Beginn des Programms für die leere Zeichenfolge benötigt wird.

Wenn size itgrößer als 1 ist, sind wir im then-Part und führen einfach durch print(it^it), oder? Nicht ganz, weil ich versäumt habe, Ihnen zu sagen, dass SML stark typisiert ist, was bedeutet, dass eine Bedingung if <cond> then <exp_1> else <exp_2>immer den gleichen Typ haben muss, was wiederum bedeutet, dass die Ausdrücke <exp_1>und <exp_2>der gleiche Typ sein müssen. Wir kennen bereits den Typ des elseTeils: Eine anonyme Funktion, die eine Zeichenfolge verwendet und dann aufruft, printhat den Typ string -> <return type of print>und printden Typ string -> unit( unitist in gewisser Weise ähnlich wievoid in anderen Sprachen), daher lautet der resultierende Typ erneut string -> unit.

Wenn das thenTeil also nur print(it^it)den Typ hat unit, erhalten wir einen Typinkongruenzfehler. Also wie wäre es fn _=>print(it^it)? ( _Ist ein Platzhalter für ein Argument , das nicht verwendet wird) Diese anonyme Funktion auf seine eigene Art hat , 'a -> unitwo 'afür einen beliebigen Typ steht, so im Rahmen unserer bedingten , die eine erzwingt string -> unitArt dies funktionieren würde. (Die Variable type 'awird mit type instanziiert string.) In diesem Fall würden wir jedoch nichts ausgeben, da die anonyme Funktion niemals aufgerufen wird! Denken Sie daran, wenn wir in den then-teil gehen, ist der Gesamtcode "<code>"<code>, so dass der <code>-teil zu einer Funktion ausgewertet wird, aber da nichts danach kommt, wird er nicht aufgerufen.

Stattdessen wir eine Sequentialisierung verwenden , die die Form hat , (<exp_1>; ...; <exp_n>)wo <exp_1>auf <exp_n-1>beliebige Arten und die Art kann von <exp_n>der Art der ganzen Sequentialisierung bietet. Aus funktionaler Sicht werden die Werte von <exp_1>to <exp_n-1>einfach verworfen, SML unterstützt jedoch auch imperative Konstrukte, sodass die Ausdrücke möglicherweise Nebenwirkungen haben. Kurz gesagt, wir nehmen (print(it^it);print)als then-teil, also zuerst drucken und dann die Funktion zurückgeben, printdie den richtigen Typ hat.

Laikoni
quelle
7

V , 27 , 23 Bytes

éPñi"éP241"qpá"lxx|xÿ

Probieren Sie es online!

Da dies einige nicht druckbare Zeichen enthält, ist hier eine lesbare Version:

éPñi"éP<C-v>241<esc>"qpá"lxx|xÿ

Und hier ist ein Hexdump:

00000000: e950 f169 22e9 5016 3234 311b 2271 70e1  .P.i".P.241."qp.
00000010: 226c 7878 7c78 ff                        "lxx|x.

Das allererste, was wir tun müssen, ist festzustellen, ob das erste Zeichen ein Zitat ist. éPfügt ein 'P' ein, ist aber "éPein NOOP. Danach führen wir eine leichte Modifikation am ausziehbaren Standardquine durch, nämlich:

ñi<C-v>241<esc>"qpÿ

Wir werden es allerdings etwas anders machen. Zuerst müssen wir den Starttext "éP" einfügen. So machen wir es

ñ                        " Start recording into register 'q'
 i                       " Enter insert mode
  "éP<C-v>241<esc>       " Enter the following text: '"éPñ'
                  "qp    " Paste the text in register 'q'
                     á"  " Append a '"'

Hier findet die Verzweigung statt. Der aktuell im Puffer befindliche Text lautet

"éPñi"éP<C-v>241<esc>"qpá"P
Cursor is here ----------^

Wenn wir es nicht in Anführungszeichen setzen, wäre in diesem Fall das 'P' niemals eingefügt worden, und der Puffer lautet:

"éPñi"éP<C-v>241<esc>"qpá"
Cursor is here ----------^

Da wir noch aufnehmen, können wir hier tun, was immer wir wollen, und es wird dem Puffer hinzugefügt, wenn das "qppassiert. Von hier aus ist es also ziemlich einfach, die Anführungszeichen bedingt zu löschen:

l           " Move one character to the right. If there is no character to the right, 
            " then this is effectively a "break" statement, stopping playback of the recording
 xx         " Delete two characters (the '"P')
   |        " Move to the first character on this line
    x       " Delete one character
     ÿ      " End the program
DJMcMayhem
quelle
3

JavaScript (ES6), 239 - 237 Byte

Set=``;eval(";a='Set=``;eval(~;a=1;S=String.fromCharCode;q=S(34);r=Set&&q;s=S(39);alert(r+a.replace(/[^ -}]/g,q).replace(1,s+a+s)+r);~)';S=String.fromCharCode;q=S(34);r=Set&&q;s=S(39);alert(r+a.replace(/[^ -}]/g,q).replace(1,s+a+s)+r);")

Achten Sie darauf, jede Version in einer neuen Umgebung (z. B. einem neuen Browser-Tab) zu testen.

Es muss mindestens einen Weg geben, dies zu vereinfachen ...

ETHproductions
quelle
1
Ich nehme an, Sie könnten ein Array für die Ersetzungen wie folgt verwenden: [x = "replace"]. Könnte aber brechen, ich bin nicht sehr erfahren mit Quines ...
Luke