Gegenseitig negative Quines

22

Dies wurde inspiriert von Print a Negative Ihres Codes und Golf a mutual quine .


Betrachten Sie ein Rechteck von Zeichen, die die folgenden Einschränkungen erfüllen:

  1. Besteht ausschließlich aus druckbaren ASCII-Zeichen
  2. Abmessungen beide größer als 1
  3. Jede Zeile und jede Spalte enthält mindestens ein Leerzeichen.
  4. Jede Zeile und jede Spalte enthält mindestens ein Nicht-Leerzeichen.

Das folgende Beispiel ist ein gültiges 6 x 4-Rechteck:

%n 2e 
1  g 3
 &* __
 3  

Ein Negativ für dieses Rechteck ist ein Rechteck mit gleichen Abmessungen, bei dem alle Leerzeichen durch Nicht-Leerzeichen und alle Nicht-Leerzeichen durch Leerzeichen ersetzt werden. Ein Negativ des obigen Rechtecks ​​könnte sein:

  f  ^
 33 > 
9  $  
^ }|Q'

Jedes nicht durch Leerzeichen druckbare ASCII-Zeichen kann verwendet werden, um ein Leerzeichen zu ersetzen.

Aufgabe

Ihre Aufgabe ist es, ein Programm mit rechteckigem Quellcode zu schreiben, das ein gültiges Negativ an sich selbst ausgibt. Das ausgegebene Negativ muss ebenfalls ein gültiges Programm in derselben Sprache wie das Original sein und die Quelle des Originals ausgeben.

Es darf kein abschließendes Leerzeichen hinzugefügt oder entfernt werden, mit Ausnahme einer einzelnen abschließenden Zeile am Ende einer Ausgabe, die optional ist.

Keines der Programme darf den Quellcode eines der beiden Programme lesen. Es kann auch nicht von REPL-Umgebungen ausgegangen werden.

Wertung

Ihre Punktzahl ergibt sich aus den Dimensionen Ihres Codes (dh wenn sich Ihr Quellcode in einem Rechteck von 12 x 25 befindet, beträgt Ihre Punktzahl 12 * 15 = 180). Zusätzlich erhöht sich Ihre Punktzahl für jedes Zeichen, das in einem Kommentar verwendet wird, um 2 (Wenn Sie /* .. */einmal in Ihrem Code verwenden und sich Ihr Code in einem 10 x 10-Rechteck befindet, beträgt Ihre Punktzahl 10 * 10 + 8 * 2 = 116).

Die niedrigste Punktzahl gewinnt.

Bei Stimmengleichheit gewinnt die Einsendung mit der geringsten Anzahl von Leerzeichen im Programm (entweder das Original oder das Negativ, je nachdem, welches weniger Leerzeichen hat).

Bleibt noch ein Gleichstand bestehen, gewinnt die frühere Antwort.

Es gibt einen Bonus von -52% , wenn das Original und das Negativ zusammen ein normales Quine ergeben. Beispielsweise:

Original   Negative   Combined
 A A       B B        BABA
A A         B B       ABAB
es1024
quelle
@Optimizer Das ist der Grund, warum ich den Bonus nicht zur Pflicht gemacht habe.
es1024
1
Ich spreche nur über den negativen Teil der gegenseitigen Quine;)
Optimierer
@ Martinbüttner Ah, mein schlimmes. Ich habe komisch gedacht.
Optimierer
1
Kann jemand dies in c tun? +1 an wer zuerst kommt!
MegaTom

Antworten:

15

CJam, ( 51 49 47 46 45 42 × 2) × 48% = 40,32

{])"_~"+S41*'R+@,[{N@S}{SN@}{W=N]_}]=~}_~ 
                                         R

Wenn Sie den obigen Code ausführen, erhalten Sie folgende Ausgabe:

                                         R
{])"_~"+S41*'R+@,[{N@S}{SN@}{W=N]_}]=~}_~ 

Läuft was, druckt die Originalquelle zurück.

Die Quelle und die Ausgabe sind einfach vertauschte Zeilen.

Jetzt kommt die Magie.

Das Überlappen der Quelle und der Ausgabe führt zu folgendem Code:

{])"_~"+S41*'R+@,[{N@S}{SN@}{W=N]_}]=~}_~R
{])"_~"+S41*'R+@,[{N@S}{SN@}{W=N]_}]=~}_~R

das ist eine perfekte quine!

Probieren Sie sie hier online aus


Wie es funktioniert

Die gesamte Drucklogik befindet sich in der ersten Zeile, in der alle drei später erläuterten Fälle behandelt werden.

{])"_~"+S41*'R+@,[{N@S}{SN@}{W=N]_}]=~}_~
{                                     }_~   "Copy this code block and execute the copy";
 ]                                          "Wrap everything before it in array";
  )                                         "Pop the last element out of it";
   "_~"+                                    "Append string '_~' to the copied code block";
        S41*                                "Create a string of 41 spaces";
            'R+                             "Append character R to it";
               @,                           "Rotate the array to top and get its length";
                 [{   }{   }{     }]=~      "Get the corresponding element from this"
                                            "array and execute it";

Das Array in der letzten Zeile oben ist das Array, dessen Codeblöcke allen drei Fällen entsprechen.

Fall 1

{])"_~"+S41*'R+@,[{N@S}{SN@}{W=N]_}]=~}_~ 
                                         R

In diesem Fall war die Länge des verbleibenden Stapels 0, als der Block ausgeführt wurde, er hatte nur die Kopie des Blocks selbst, die ursprünglich im dritten Schritt oben herausgesprungen war. Also nehmen wir den Index 0aus dem letzten Array und führen ihn aus:

 {N@S}          "Note that at this point, the stack is something like:"
                "[[<code block that was copied> '_ '~ ] <41 spaces and R string>]";
  N             "Add newline to stack";
   @            "Rotate the code block to top of stack";
    S           "Put a trailing space which negates the original R";

In diesem Fall ist die zweite Zeile für das Drucken der Ausgabe ein No-Op.

Fall 2

                                         R
{])"_~"+S41*'R+@,[{N@S}{SN@}{W=N]_}]=~}_~ 

In diesem Fall enthielt der Stapel bereits eine leere Zeichenfolge. Als der kopierte Codeblock ausgeführt wurde, hatte er zwei Elemente - eine leere Zeichenfolge und den Codeblock selbst. Also nehmen wir den Index 1aus dem letzten Array und führen ihn aus:

{SN@}            "Note at this point, the stack is same as in case 1";
 SN              "Push space and newline to stack";
   @             "Rotate last three elements to bring the 41 spaces and R string to top";

Fall 3

{])"_~"+S41*'R+@,[{N@S}{SN@}{W=N]_}]=~}_~R
{])"_~"+S41*'R+@,[{N@S}{SN@}{W=N]_}]=~}_~R

In diesem Fall hat der Stapel 6 Elemente. Nach dem Aufrufen des letzten Codeblocks beträgt die verbleibende Arraylänge 5. Wir nehmen den Index 5aus dem Array und führen ihn aus. (Beachten Sie, dass in einem Array von 3Elementen index index 5ist. 5%3 = 2)

{W=N]_}          "Note at this point, the stack is same as in case 1";
 W=              "Take the last character out of the 41 spaces and R string, i.e. R";
   N]            "Add a new line to stack and wrap the stack in an array";
     _           "Copy the array to get back the source of Case 3 itself";
Optimierer
quelle
27

Python, 97 x 2 + 2 = 196

Für den Anfang keine gute Lösung, aber zumindest funktioniert es (glaube ich).

c='o=1-%d;print("%%97s\\n%%97s"%%("#","c=%%r;exec(c%%%%%%d)\\40"%%(c,o),"#")[o:][:2])';exec(c%1) 
                                                                                                #

Ausgabe:

                                                                                                #
c='o=1-%d;print("%%97s\\n%%97s"%%("#","c=%%r;exec(c%%%%%%d)\\40"%%(c,o),"#")[o:][:2])';exec(c%0) 
grc
quelle
8
+1 für die einzige Einreichung bis jetzt, um eine echte Sprache zu verwenden
WinnieNicklaus
Es scheint auch nicht zu weit vom Bonus entfernt zu sein.
mbomb007
23

C Jam, ( 58 56 54 48 46 × 2) × 48% = 44,16

{`"_~"+{_,94\m2/S*a_+\*                       
                       N/23f/Wf%N*}_`'"#)!*}_~

welche druckt

                       {`"_~"+{_,94\m2/S*a_+\*
N/23f/Wf%N*}_`'"#)!*}_~                       

Die Nicht-Leerzeichen in jeder Zeile bleiben zwischen den beiden Quines gleich.

Aber jetzt der wirklich süße Teil:

{`"_~"+{_,94\m2/S*a_+\*{`"_~"+{_,94\m2/S*a_+\*
N/23f/Wf%N*}_`'"#)!*}_~N/23f/Wf%N*}_`'"#)!*}_~

ist eine Quine! :)

Teste es hier.

Wie es funktioniert

Ich empfehle Ihnen, zuerst die Erklärung zu meinem anderen Beitrag zu lesen, da hier die Grundlagen des Quining in CJam im Allgemeinen erläutert werden.

Dieser ist etwas kniffliger. Für das gegenseitige Quine ändere ich wie im anderen Fall die Zeichenfolgendarstellung des Blocks, indem ich vor oder nach jeder Zeile Leerzeichen hinzufüge und eine 0 durch eine 2 tausche, sodass das resultierende Programm die Leerzeichen an das entgegengesetzte Ende setzt.

Beachten Sie, dass sich die Leerzeichen überhaupt nicht auf die Quines auswirken. In der ersten befinden sie sich in einem Block, der nicht wirklich verwendet wird, und in der zweiten befinden sie sich um den gesamten Code.

Um eine regelmäßige Quine zu erhalten, wenn beide kombiniert werden, müssen wir einen Weg finden, um all diese Modifikationen zu vermeiden. Beachten Sie, dass die Struktur von Whitespace und Code bedeutet, dass durch die Kombination von beiden die Gesamtheit eines Quines in das andere eingefügt wird. Wenn wir also den gesamten Änderungscode in einen Block einfügen, können wir diesen Block abhängig von seinem tatsächlichen Inhalt ausführen.

Jetzt habe ich also diesen Block ... für die gegenseitigen Quines enthält er nur den Code, den ich eigentlich ausführen möchte. Für das kombinierte Quine enthält es auch wieder das gesamte Quine in einer zufälligen Position, was keinen Sinn ergibt ... aber da es ein Block ist, wird es nicht automatisch ausgeführt. So können wir anhand des Inhalts dieses Blocks bestimmen, ob der String geändert werden soll. Dafür _`'"#)!ist es da. Es dupliziert den Block, konvertiert ihn in einen String, sucht nach dem Zeichen "(das in den Quines nur außerhalb des Blocks vorkommt) - die Suche gibt zurück, -1wenn das Zeichen nicht gefunden wird, und ansonsten eine positive ganze Zahl - und erhöht das Ergebnis und negiert es logisch. Wenn also a "gefunden wurde, ergibt dies, 0andernfalls ergibt es 1. Jetzt machen wir es einfach*, der den Block einmal ausführt, wenn das Ergebnis 1 war und ansonsten gar nicht.

Schließlich funktioniert der Änderungscode wie folgt:

_,94\m2/S*a_+\*N/23f/Wf%N*
_,                         "Duplicate the quine string and get its length.";
  94\m                     "Subtract from 94.";
      2/                   "Divide by two.";
        S*                 "Create a string with that many spaces. This will be
                            an empty string for the first mutual quine, and contain
                            23 spaces for the second mutual quine.";
          a_+              "Create an array that contains this string twice.";
             \*            "Join the two copies together with the quine string.";
               N/          "Split into lines.";
                 23f/      "Split each line into halves (23 bytes each).";
                     Wf%   "Reverse the two halves of each line.";
                        N* "Join with a newline.";

Inanspruchnahme der Prämie (12 x 10) * 48% = 57,6

Es hat sich herausgestellt, dass dieser Code mit einigen Änderungen sehr einfach auf mehrere Zeilen aufgeteilt werden kann. Wir addieren 2 Zeichen, um 48 in einer Reihe zu erhalten, die wir dann bequem durch 8 teilen können, so dass wir 8 Zeilen mit 6 Codezeichen und 6 Leerzeichen haben. Dazu müssen wir auch einige Zahlen ändern und einen oder zwei Operatoren neu anordnen, damit sie nicht auf beide Zeilen aufgeteilt werden. Das gibt uns eine funktionierende Version mit der Größe 12 x 8 ... einmalig. Also fügen wir einfach zwei Zeilen hinzu, die nichts bewirken (eine 1 drücken, eine 1 drücken, eine 1 drücken, eine 1 drücken ...), und erhalten 12 x 10 :

{`"_~"      
      +{129X
$,m2/S      
      *a_+\*
N/6f/1      
      ;1;1;1
;1;1;1      
      ;Wf%N*
}_`'"#      
      )!*}_~

Wie der vorherige erzeugt dies

      {`"_~"
+{129X      
      $,m2/S
*a_+\*      
      N/6f/1
;1;1;1      
      ;1;1;1
;Wf%N*      
      }_`'"#
)!*}_~      

(Randnotiz: In den Zwischenzeilen muss nicht immer links und rechts gewechselt werden, sondern es ist nur die Position der ersten und letzten Zeile wichtig. Links und rechts können für alle anderen Zeilen beliebig gewählt werden.)

Und durch reinen Zufall funktioniert das ganze Quine auch noch:

{`"_~"{`"_~"
+{129X+{129X
$,m2/S$,m2/S
*a_+\**a_+\*
N/6f/1N/6f/1
;1;1;1;1;1;1
;1;1;1;1;1;1
;Wf%N*;Wf%N*
}_`'"#}_`'"#      
)!*}_~)!*}_~

(Ich sage Zufall, weil der Teil, der dafür sorgt, dass der innere Code nicht ausgeführt wird, jetzt seltsamerweise mit dem anderen Quine verwechselt wird, aber es funktioniert trotzdem gut.)

Davon abgesehen hätte ich 1;meiner ursprünglichen Einreichung nur 44 Zeilen hinzufügen können , um die Kopfgeldanforderung zu erfüllen, 12 x 10sieht aber viel ordentlicher aus. ;)

Edit: Haha, als ich "purer Zufall" sagte, hätte ich nicht besser sein können. Ich habe mir angesehen, wie das letzte Quine jetzt tatsächlich funktioniert, und es ist absolut lächerlich. Es gibt drei verschachtelte Blöcke (4 tatsächlich, aber der innerste ist irrelevant). Der einzig wichtige Teil des innersten dieser 3 Blöcke ist, dass er einen enthält "(und nicht den, den er in der ursprünglichen Einreichung getan hat, sondern den '", der am Ende verwendet wird, um nach demselben Zeichen zu suchen). Die Grundstruktur des Quines ist also:

{`"_~"{`"_~"+{___'"___}_`'"#)!*}_~)!*}_~

Lassen Sie uns das analysieren:

{`"_~"                               }_~ "The standard CJam quine.";
      {`"_~"+                  }_~       "Another CJam quine. Provided it doesn't do 
                                          anything in the rest of that block, this 
                                          will leave this inner block as a string on 
                                          the stack.";
                                  )      "Slice the last character off the string.";
                                   !     "Negate... this yields 0.";
                                    *    "Repeat the string zero times.";

Das mag zwar etwas komisch, aber da der innere Block eine einzelne Zeichenfolge auf dem Stapel belässt )!*, verwandelt sich diese zufällig in eine leere Zeichenfolge. Die einzige Bedingung ist, dass das Zeug im inneren Block danach +nichts mehr mit dem Stapel zu tun hat, also schauen wir uns das an:

             {___'"___}                  "Push a block which happens to contain 
                                          quotes.";
                       _`'"#)!*          "This is from the original code and just 
                                          removes the block if it does contain 
                                          quotes.";
Martin Ender
quelle
4
TLDR; upvote;)
Optimierer
Sollte es nicht Y/2in der kombinierten Quine sein?
Schnaader
"Und durch reinen Zufall" nah;)
Timtech
@ Timtech Siehe meine bearbeiten. Reiner Zufall war keine Untertreibung. ^^
Martin Ender
10

CJam, 42, 37, 33 × 2 = 66

{`As_W%er"_~"+S 33*F'Lt1{\}*N\}_~
               L                 

welche druckt

               L                 
{`As_W%er"_~"+S 33*F'Lt0{\}*N\}_~

(Die Zeilen werden vertauscht und a 1wird zu a 0.)

Teste es hier.

Wie es funktioniert

Zunächst sollten Sie das grundlegende CJam-Quine verstehen:

{"_~"}_~

Die geschweiften Klammern definieren einfach einen Codeblock, wie eine Funktion, die nicht sofort ausgeführt wird. Wenn ein nicht ausgeführter Block auf dem Stapel verbleibt, wird sein Quellcode (einschließlich geschweifter Klammern) gedruckt. _dupliziert den Block und ~führt die zweite Kopie aus. Der Block selbst drückt einfach die Zeichenfolge, die enthält _~. Dieser Code belässt den Stack also im folgenden Zustand:

Stack: [{"_~"} "_~"]

Der Block und der String werden am Ende des Programms einfach hintereinander gedruckt, was dies zu einem Quine macht.

Das Schöne daran ist, dass wir im Block tun können, was immer wir wollen, und es bleibt ein Quine, da jeder Code automatisch im Blockinhalt gedruckt wird. Wir können den Block auch modifizieren, indem wir seine Zeichenfolgendarstellung mit `(die nur eine Zeichenfolge des Blocks mit geschweiften Klammern ist) erhalten.

Schauen wir uns nun diese Lösung an. Beachten Sie, dass jeder Teil des gemeinsamen Quines den quine-ähnlichen Block mit _~und enthält L. Das Lschiebt einen leeren String auf den Stack, was nicht zur Ausgabe beiträgt. Also hier ist, was der Block tut:

`                             "Convert block to its string representation.";
 As                           "Push 10 and convert to string.";
   _W%                        "Duplicate and reverse, to get another string 01.";
      er                      "Swap 0s and 1s in the block string.";
        "_~"+                 "Append _~.";
             S 33*            "Push a string with 33 spaces.";
                  F'Lt        "Set the character at index 15 to L.";
                      1{ }*   "Repeat this block once.";
                        \     "Swap the code string and the space string.";
                           N\ "Push a newline and move it between the two lines.";

Dies erledigt also den Quine-Teil, tauscht jedoch eine 1 gegen eine 0 und stellt eine weitere Zeile mit einem voran L, wobei der obige Code ein Leerzeichen enthält. Der Haken ist, dass die Reihenfolge dieser beiden Zeilen durch das Vertauschen im Inneren bestimmt wird { }*. Und weil der äußere Teil des gemeinsamen Quines das 0davor befindliche durch ein ersetzt 1, führt es diesen Tausch niemals aus und stellt daher die ursprüngliche Reihenfolge wieder her.

Martin Ender
quelle
5

C Jam, 27 × 2 = 54

{ ` " _ ~ " + N - ) 2 * ' '
 > @ t s G B + / N * } _ ~ 

Ausgabe:

 { ` " _ ~ " + N - ) 2 * ' 
' > @ t s G B + / N * } _ ~

'A'B>vergleicht die Zeichen A und B. ' '\n >gibt 1 zurück, weil 32> 10 und ' \n' >gibt 0 zurück, weil die beiden Leerzeichen gleich sind.

jimmy23013
quelle
2

CJam, 30 29 × 2 = 58

{"_~"SN]_,4=S28*'R+\{N@}*}_~ 
                            R

Ausgänge:

                            R
{"_~"SN]_,4=S28*'R+\{N@}*}_~ 

welches die ursprüngliche Quelle ausgibt.

Dies basiert auf dem gleichen Prinzip wie meine andere Lösung.

Probieren Sie es hier online aus

Optimierer
quelle