Entropic Quine!

12

Ihre Aufgabe ist es, ein Programm oder eine Funktion zu schreiben, die:

  • Bei der ersten Ausführung wird der Quellcode ausgegeben.
  • Bei nachfolgenden Ausführungen sollte das ausgegeben werden, was zuvor ausgegeben wurde, jedoch mit einer zufälligen Zeichenänderung (unten definiert). Es muss sich nicht um eine einheitlich zufällige Änderung handeln, es sollte jedoch für jede mögliche Änderung eine Wahrscheinlichkeit ungleich Null bestehen.

    Nach der ersten Ausführung ist Ihr Programm nicht mehr unbedingt ein Quine. Die Ausgabe hat sich geändert (und das Programm kann sich auch selbst ändern).

Wenn Ihr Quine beispielsweise ABCDwiederholt ausgeführt wurde, wird möglicherweise Folgendes gedruckt:

ABCD
A!CD
j!CD
j!CjD

Spezifikationen

  • Eine Zeichenänderung ist entweder:

    • Das Einfügen eines zufälligen Zeichens,
    • Das Löschen eines zufälligen Zeichens oder
    • Ein Ersetzen eines Zeichens durch ein neues zufälliges Zeichen. Beachten Sie, dass das neue Zeichen das gleiche sein darf, das es ersetzt. In diesem Fall wird keine Änderung vorgenommen.

    Das Löschen oder Ersetzen eines Zeichens aus einer leeren Zeichenfolge ist natürlich keine gültige Änderung.

  • Obwohl dieses Tag , gelten die Regeln gegen das Lesen Ihres Quellcodes nicht.

Sie können einen beliebigen Zeichensatz verwenden, sofern dieser die in Ihrem Quellcode verwendeten Zeichen enthält.

Esolanging Fruit
quelle
1
Auf welche Zeichen bezieht sich jedes Zeichen ?
Dennis
2
Wie oft muss das gehen? Natürlich kann es nicht beliebig oft oder anders sein, dass jedes mögliche Programm, das länger oder länger als das ursprüngliche ist, eine Lösung für die Herausforderung sein muss.
Martin Ender
1
Kann der Charakter irgendwo oder nur am Ende hinzugefügt werden?
Conor O'Brien
1
@ ConorO'Brien Überall.
Esolanging Fruit
1
Wie viele Iterationen muss es funktionieren?
Dylnan

Antworten:

7

Python 3 , 288 270 224 212 195 196 194 180 178 168 Bytes

f=__file__
m=open(f).read()
x=m	
print(end=x)
h=hash
k=h(f)
n=k%2
a=h(m)%-~len(x)
x=x[:a]+(not(k%3)*x)*chr(k%127)+x[a+n:]
open(f,'w').write(m.replace("\t",";x=%r\t"%x))

Probieren Sie es online!

Nachdem wir den Datei-Quellcode in der ersten Iteration gedruckt haben, fügen wir eine zusätzliche Zeile hinzu, um x anstelle von m auf den neuen Quellcode zu setzen.

Erläuterung:

f=__file__    #Open and read the source code
m=open(f).read()

x=m       #Set x to the source code for the first iteration
x="..."
...
x="..."   #Set x to the latest iteration
          #On the last iteration there's a tab character to mark progress
print(end=x)    #Print the previous iteration's text

#Modify the text
h=hash
k=h(f)            #Generate a random number to use
n=k%2             #Whether the character will be inserted or changed/deleted
a=h(m)%-~len(x) #The index of the change
                         #Add 1 to the range to append new characters, and to avoid mod by 0 in the case of an empty string
x=x[:a]+(not(k%3)*x)*chr(k%127)+x[a+n:]    #Make the change

open(f,'w').write(m.replace("\t",";x=%r\t"%x))   #Modify the source code, adding the new iteration of the source code

Unter der Annahme, dass hasheine einheitliche Zufallszahl zurückgegeben wird, besteht eine Chance von etwa 1/6, ein neues Zeichen einzufügen, eine Chance von 1/6, ein vorhandenes Zeichen zu ändern und eine Chance von 2/6, ein Zeichen zu löschen. Was ist die verbleibende 2/6 Chance, die Sie fragen? Na ja, es macht überhaupt nichts 2/6 der Zeit!

(Hier ist ein Validierungsprogramm, das an die Antworten von mbomb007 angepasst wurde . Probieren Sie es online aus! )

Scherzen
quelle
Ich denke, f=__file__würde auch im ersten Schritt helfen.
Ørjan Johansen
4

Python 3 , 205 195 Bytes

s='print(end=x);h=hash;k=h(x);n=k%2;a=h(s)%-~len(x);x=x[:a]+(not(k%3)*x)*chr(k%127)+x[a+n:];open(__file__,"w").write("s=%r;x=%r;exec(s)"%(s,x))';x='s=%r;x=%r;x=x%%(s,x);exec(s)';x=x%(s,x);exec(s)

Probieren Sie es online!

Wollte eine Version ausprobieren, die den Quellcode nicht liest. Es stellte sich als nicht schlecht heraus, wie ich dachte, und es sind nur etwa 30 Bytes hinter der Version , die das tut . Die Erklärung für die Funktionsweise ist größtenteils dieselbe wie bei der anderen Antwort, initialisiert x jedoch anders, da nicht nur der Quellcode gelesen werden kann.

Scherzen
quelle
4

Python 2 , 779 801 Bytes

Obwohl die Herausforderung dahingehend bearbeitet wurde, dass das Lesen Ihrer Quelle erlaubt ist, habe ich bereits meine Lösung ohne diese erstellt. Um zu zeigen, dass es möglich ist, habe ich es beendet. Kein Lesen der Quelldatei:

s='s=%r;print s%%s\nfrom random import*;L=4;f=open(__file__,"wa"[L>5]);R=randint\nf.write("\\n".join((s%%s).split("\\n")[1:5:2]).replace("4",`map(ord,s%%s)`))\nif L>5:exec\'b=[];h=%%d\\nwhile~-h:b+=[h%%%%1000];h/=1000\\nwhile b:r,p,n=b[-3:];b=b[:-3];L=[L[:p]+L[p+1:],L[:p]+[r]+L[p+n:]][n<2if L else 1]\\nprint"".join(map(chr,L))\'%%1\n\nn=R(0,2);p=R(0,len(L if L>5else s%%s));r=R(0,255);f.write("%%03d"*3%%(n,p,r))';print s%s
from random import*;L=4;f=open(__file__,"wa"[L>5]);R=randint
f.write("\n".join((s%s).split("\n")[1:5:2]).replace("4",`map(ord,s%s)`))
if L>5:exec'b=[];h=%d\nwhile~-h:b+=[h%%1000];h/=1000\nwhile b:r,p,n=b[-3:];b=b[:-3];L=[L[:p]+L[p+1:],L[:p]+[r]+L[p+n:]][n<2if L else 1]\nprint"".join(map(chr,L))'%1

n=R(0,2);p=R(0,len(L if L>5else s%s));r=R(0,255);f.write("%03d"*3%(n,p,r))

Probieren Sie es online! (Beachten Sie, dass dadurch die Quelle nicht geändert wird. Sie müssen sie lokal ausführen, damit dies funktioniert.)

Um zu zeigen , dass die Transformationen arbeiten, hier ist ein Testprogramm (derzeit eingerichtet, um immer zu wählen 100für r, und es gibt das Ergebnis für jede Kombination von nund pfür die erste Liste.)



Erläuterung:

s='s=%r;print s%%s...';print s%s...

Die erste Zeile ist Ihre klassische Quine, aber viel länger, um zu berücksichtigen, was danach kommt.

from random import*;L=4;f=open(__file__,"wa"[L>5]);R=randint

Import für zufällige ganze Zahlen. Lwird aus der Liste der Ordnungszahlen des Quellcodes, aber anfänglich ist es eine Ganzzahl, die an keiner anderen Stelle in der Quelle verwendet wird, um ein Ersetzen der Zeichenfolge zu ermöglichen. Öffnen Sie die Datei, um die neue Quelle zu schreiben. Bei späteren Ausführungen wird es stattdessen zum Anhängen geöffnet.

f.write("\n".join((s%s).split("\n")[1:5:2]).replace("4",`map(ord,s%s)`))

Entfernen Sie die erste und dritte Codezeile. Ersetzen Sie das 4Obige durch die Liste der Ordnungszahlen.

if L>5:exec'b=[];h=%d\nwhile~-h:b+=[h%%1000];h/=1000\nwhile b:r,p,n=b[-3:];b=b[:-3];L=[L[:p]+L[p+1:],L[:p]+[r]+L[p+n:]][n<2if L else 1]\nprint"".join(map(chr,L))'%1

n=R(0,2);p=R(0,len(L if L>5else s%s));r=R(0,255);f.write("%03d"*3%(n,p,r))

In Stücken:

  • if L>5:- Überspringt diese Zeile bei der ersten Ausführung. Später Lwird eine Liste erstellt, die ausgeführt wird. Ich erkläre das execletzte, weil es nicht das erste Mal läuft.

  • n- Eine Zufallszahl 0-2. Hiermit wird festgelegt, welche Änderung vorgenommen wird (0 = Einfügen, 1 = Ersetzen, 2 = Löschen).

  • p - Eine zufällige Position in der Liste, an der die Änderung vorgenommen wird.

  • r - Eine Zufallszahl zum Einfügen oder Ersetzen in die Liste

  • f.write("%03d"*3%(n,p,r))- Hängen Sie die 3 Zufälle an das Ende der Quelldatei an. Bei jedem Durchlauf wird dies zu einer Ganzzahl hinzugefügt, die alle Änderungen an der ursprünglichen Quelle codiert, die aufgetreten sind.

  • exec'b=[];h=%d...'%1...- Holen Sie sich die Zufallszahlen (die Sie %1später finden), übernehmen Sie die Änderungen in die Liste und drucken Sie sie aus.

  • while~-h:b+=[h%%1000];h/=1000 - Erstellen Sie eine Liste der bisher generierten Zufälle unter Berücksichtigung der führenden 1 führenden Nullen, um Probleme mit führenden Nullen zu vermeiden.

  • while b:r,p,n=b[-3:];b=b[:-3] - Weisen Sie die Zufälligkeiten für diese Iteration zu.

  • L=[L[:p]+L[p+1:],L[:p]+[r]+L[p+n:]][n<2if L else 1] - (0 = Einfügen, 1 = Ersetzen, 2 = Löschen)

  • print"".join(map(chr,L)) - Drucken Sie die geänderte Quelle.

mbomb007
quelle
Löscht dies manchmal ein nicht existierendes Zeichen am Ende der Zeichenfolge? Da pkann die Länge der Zeichenkette sein. Wie verhält es sich mit einer leeren Zeichenfolge?
Jo King
@JoKing Ich habe ein Testprogramm hinzugefügt. Jeder mögliche Charakterwechsel kann passieren. Es wird lediglich gezeigt, dass jede Position für ein Einfügen, Ersetzen oder Löschen ausgewählt werden kann und dass eine leere Liste behandelt wird. tio.run/##LYoxDsMgDEVnOAUjCAZgRO0NuIHloUOaRIocy6JDT08dpdt/…
mbomb007
Ich glaube nicht, dass eine Änderung gültig ist, obwohl ich das OP gefragt habe. Die Frage sagtOf course, deleting or replacing a character from an empty string is not a valid change
Jo König
Ich habe gefragt , Esolanging Obst, und sie sagen , dass keine Änderung ist gültig, aber nicht für eine leere Zeichenfolge.
Jo King
1
@JoKing Sollte behoben sein.
mbomb007
1

Java 10, 370 Bytes

String s;v->{if(s==null){s="String s;v->{if(s==null){s=%c%s%1$c;s=s.format(s,34,s);}else{int r=s.length();r*=Math.random();char c=127;c*=Math.random();s=s.substring(0,r)+(c%%3<2?c:%1$c%1$c)+s.substring(r+(c%%3>0?1:0));}}";s=s.format(s,34,s);}else{int r=s.length();r*=Math.random();char c=127;c*=Math.random();s=s.substring(0,r)+(c%3<2?c:"")+s.substring(r+(c%3>0?1:0));}}

Probieren Sie es online aus.

Erläuterung:

String s;               // Class-level String variable to store the modifying source code
v->{                    // Method without parameter nor return-type
  if(s==null){          //  If this is the first execution of this function:
    s="String s;v->{if(s==null){s=%c%s%1$c;s=s.format(s,34,s);}else{int r=s.length();r*=Math.random();char c=127;c*=Math.random();s=s.substring(0,r)+(c%%3<2?c:%1$c%1$c)+s.substring(r+(c%%3>0?1:0));}}";
                        //   Set `s` to the unformatted source-code
    s=s.format(s,34,s);}//   And then to the formatted source-code
else{                   //  For any following executions of this function:
  int r=s.length();r*=Math.random();
                        //   Random index in range [0, length_of_modified_source_code)
  char c=127;c*=Math.random();
                        //   Random ASCII character in unicode range [0, 127)
  s=                    //   Replace the current String `s` with:
    s.substring(0,r)    //    The first [0, `r`) characters of the modified source code `s`
    +(c%3<2?            //    If the random option is 0 or 1:
           c:"")        //     Append the random character
        +s.substring(r  //    Append the rest of the modified source code `s`, but:
          +(c%3>0?      //     If the random option is 1 or 2:
             1:0));}}   //      Skip the first character of this second part

Allgemeine Erklärung:

-Teil:

  • Der String senthält den unformatierten Quellcode.
  • %swird verwendet, um diesen String in sich selbst mit dem einzugeben s.format(...).
  • %c, %1$cund 34werden zum Formatieren der doppelten Anführungszeichen verwendet.
  • ( %%dient zur Formatierung des Modulo- %).
  • s.format(s,34,s) setzt alles zusammen.

Hier ein grundlegendes Java-Quine-Programm.

Herausforderungsteil:

  • String s; ist der Quellcode, den wir auf Klassenebene ändern werden.
  • int r=s.length();r*=Math.random(); wird verwendet, um einen zufälligen Index des Quellcodes im Bereich auszuwählen [0, length_of_modified_source_code) .
  • char c=127;c*=Math.random();wird verwendet, um ein zufälliges ASCII-Zeichen (einschließlich nicht druckbarer Zeichen) im Unicode-Bereich auszuwählen [0, 126].
  • c%3wird verwendet, um eine zufällige Option von entweder 0, 1 oder 2 auszuwählen. Option 0 fügt das zufällige Zeichen vor dem Index hinzu r; Option 1 ersetzt das Zeichen am Index rdurch das zufällige Zeichen. und Option 2 entfernt das Zeichen am Index r.
Kevin Cruijssen
quelle