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 100
per r
, e stampa il risultato per ogni combinazione di n
e p
per 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. L
diventerà 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 4
sopra 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, L
sarà un elenco e questo verrà eseguito. Spiegherò l' exec
ultimo, 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 %1
esecuzioni 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.