Entropic Quine!


12

Il tuo compito è scrivere un programma o una funzione che:

  • Quando eseguito per la prima volta, genera il suo codice sorgente.
  • Sulle esecuzioni successive, dovrebbe produrre ciò che ha prodotto in precedenza, ma con un cambio di carattere casuale (definito sotto). Non deve essere un cambiamento uniformemente casuale, ma ogni possibile cambiamento dovrebbe avere una possibilità diversa da zero.

    Dopo la prima esecuzione, il tuo programma non sarà più necessariamente un quine; l'output sarà cambiato (e anche il programma è libero di modificarsi).

Ad esempio, se il tuo quine lo fosse ABCD, eseguirlo ripetutamente potrebbe stampare:

ABCD
A!CD
j!CD
j!CjD

specificazioni

  • Un cambio di personaggio è:

    • L'inserimento di un personaggio casuale,
    • La cancellazione di un personaggio casuale, o
    • Una sostituzione di un personaggio con un nuovo personaggio casuale. Nota che il nuovo personaggio può essere uguale a quello che sostituisce, nel qual caso non verranno apportate modifiche.

    Naturalmente, l'eliminazione o la sostituzione di un carattere da una stringa vuota non è una modifica valida.

  • Nonostante questo essere etichettato , non si applicano le regole contro la lettura di codice sorgente.

È possibile utilizzare qualsiasi set di caratteri purché includa i caratteri utilizzati nel codice sorgente.


1
A quali personaggi si riferisce ogni personaggio ?
Dennis,

2
Quanto spesso deve funzionare? Chiaramente non può essere arbitrariamente spesso o altrimenti ogni possibile programma più lungo o più lungo di quello originale deve essere una soluzione alla sfida.
Martin Ender,

1
Il personaggio può essere aggiunto ovunque o alla fine?
Conor O'Brien,

1
@ ConorO'Brien Anywhere.
Esolanging Fruit,

1
Quante iterazioni deve funzionare?
dylnan,

Risposte:


7

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

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))

Provalo online!

Dopo aver stampato il codice sorgente del file sulla prima iterazione, aggiungiamo una riga aggiuntiva per impostare x sul nuovo codice sorgente, anziché m.

Spiegazione:

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

Supponendo che hashritorni un numero uniformemente casuale, ci sono circa 1/6 di possibilità di inserire un nuovo personaggio, 1/6 di possibilità di cambiare un personaggio esistente e 2/6 di possibilità di eliminarlo. Qual è la restante 2/6 possibilità che chiedi? Perché, non fa nulla per 2/6 del tempo!

(Ecco un programma di validazione adattato dalla risposta di mbomb007 . Provalo online! )


Penso f=__file__che aiuterebbe anche nel primo passo.
Ørjan Johansen,

4

Python 3 , 205 195 byte

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)

Provalo online!

Volevo provare una versione che non legge il codice sorgente. Si è rivelato non male come pensavo, ed è solo circa 30 byte dietro la versione che lo fa . La spiegazione di come funziona è sostanzialmente la stessa dell'altra risposta, ma inizializza x in modo diverso poiché non può semplicemente leggere il codice sorgente.


4

Python 2 , 779 801 byte

Sebbene la sfida sia stata modificata per mostrare che la lettura della tua fonte è consentita, stavo già creando la mia soluzione senza quella. Quindi, per dimostrare che è possibile, l'ho finito. Nessuna lettura del file sorgente:

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))


Provalo online! (Nota che questo non modificherà l'origine. Devi farlo localmente per farlo funzionare)

Per dimostrare che le trasformazioni funzionano, ecco un programma di test (attualmente impostato fino a raccogliere sempre 100per r, e stampa il risultato per ogni combinazione di ne pper la lista iniziale).



Spiegazione:

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

La prima riga è la tua classica quine, ma molto più a lungo per tenere conto di ciò che viene dopo.

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

Importazione per numeri interi casuali. Ldiventerà un elenco di ordinali del codice sorgente, ma inizialmente è un numero intero non utilizzato in nessun'altra parte del codice sorgente per consentire la sostituzione di una stringa. Apri il file per scrivere la nuova fonte. Nelle successive esecuzioni, si aprirà invece per aggiungere.

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

Rimuovere la prima e la terza riga di codice. Sostituisci quanto 4sopra con l'elenco degli ordinali.

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))

A pezzi:

  • if L>5:- Salta questa riga alla prima esecuzione. Più tardi, Lsarà un elenco e questo verrà eseguito. Spiegherò l' execultimo, perché non è eseguito la prima volta.

  • n- Un numero casuale 0-2. Questo determina quale modifica si verifica (0 = inserisci, 1 = sostituisci, 2 = cancella).

  • p - Una posizione casuale nell'elenco in cui avverrà la modifica.

  • r - Un numero casuale da inserire o sostituire nell'elenco

  • f.write("%03d"*3%(n,p,r))- Aggiungi i 3 randoms alla fine del file sorgente. Ad ogni esecuzione, questo verrà aggiunto a un numero intero che codifica tutte le modifiche all'origine iniziale che si sono verificate.

  • exec'b=[];h=%d...'%1...- Ottieni i numeri casuali (trovati dopo le %1esecuzioni successive), applica le modifiche all'elenco e stampa.

  • while~-h:b+=[h%%1000];h/=1000- Costruisci un elenco dei random generati finora, tenendo conto del lead 1, che impedisce problemi con zeri iniziali.

  • while b:r,p,n=b[-3:];b=b[:-3] - Assegna i randoms per questa iterazione.

  • L=[L[:p]+L[p+1:],L[:p]+[r]+L[p+n:]][n<2if L else 1] - (0 = inserisci, 1 = sostituisci, 2 = elimina)

  • print"".join(map(chr,L)) - Stampa la fonte modificata.


Questo a volte cancella un carattere inesistente dalla fine della stringa? Poiché ppuò essere la lunghezza della stringa. Inoltre, qual è il comportamento con una stringa vuota?
Jo King,

@JoKing Ho aggiunto un programma di test. Ogni possibile cambio di personaggio può avvenire. Mostra solo che ogni posizione può essere selezionata per un inserimento, sostituzione o eliminazione e che gestisce un elenco vuoto. tio.run/##LYoxDsMgDEVnOAUjCAZgRO0NuIHloUOaRIocy6JDT08dpdt/…
mbomb007

Non credo che nessuna modifica sia valida, anche se ho chiesto al PO. La domanda diceOf course, deleting or replacing a character from an empty string is not a valid change
Jo King,

Ho chiesto a Esolanging Fruit, e dicono che nessun cambiamento è valido, ma non per una stringa vuota.
Jo King,

1
@JoKing Dovrebbe essere risolto.
mbomb007,

1

Java 10, 370 byte

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));}}

Provalo online.

Spiegazione:

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

Spiegazione generale:

parte:

  • La stringa scontiene il codice sorgente non formattato.
  • %sè usato per inserire questa stringa in se stessa con s.format(...).
  • %c, %1$cE la 34vengono utilizzati per formattare le virgolette.
  • ( %%è usato per formattare il modulo- %).
  • s.format(s,34,s) mette tutto insieme.

Qui un programma base di Java Quine.

Parte sfida:

  • String s; è il codice sorgente che modificheremo a livello di classe.
  • int r=s.length();r*=Math.random();viene utilizzato per selezionare un indice casuale del codice sorgente nell'intervallo [0, length_of_modified_source_code).
  • char c=127;c*=Math.random();viene utilizzato per selezionare un carattere ASCII casuale (inclusi gli stampabili) nell'intervallo Unicode [0, 126].
  • c%3è usato per selezionare un'opzione casuale di 0, 1 o 2. L'opzione 0 aggiungerà il carattere casuale prima dell'indice r; l'opzione 1 sostituirà il carattere all'indice rcon il carattere casuale; e l'opzione 2 rimuoverà il carattere all'indice r.
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.