Embora o desafio tenha sido editado para mostrar que a leitura de sua fonte é permitida, eu já estava criando minha solução sem isso. Então, para mostrar que é possível, eu terminei. Nenhuma leitura do arquivo de origem:
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))
Experimente online! (Observe que isso não modificará a fonte. É necessário executá-lo localmente para que isso funcione)
Para mostrar que as transformações trabalhar, aqui está um programa de teste (atualmente configurado para sempre escolher 100
para r
, e imprime o resultado para cada combinação de n
e p
para a lista inicial.)
Explicação:
s='s=%r;print s%%s...';print s%s...
A primeira linha é o seu estilo clássico, mas muito mais para explicar o que vem depois.
from random import*;L=4;f=open(__file__,"wa"[L>5]);R=randint
Importar para números inteiros aleatórios. L
passará a fazer parte da lista de ordinais do código fonte, mas inicialmente é um número inteiro não usado em nenhum outro lugar na fonte para permitir a substituição de uma string. Abra o arquivo para escrever a nova fonte. Em execuções posteriores, ele será aberto para anexar.
f.write("\n".join((s%s).split("\n")[1:5:2]).replace("4",`map(ord,s%s)`))
Remova a primeira e a terceira linhas de código. Substitua o 4
acima pela lista de ordinais.
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))
Em pedaços:
if L>5:
- Ignora esta linha na primeira execução. Mais tarde, L
haverá uma lista, e isso será executado. Vou explicar o exec
último, porque não é executado pela primeira vez.
n
- Um número aleatório 0-2. Isso determina qual modificação ocorre (0 = inserir, 1 = substituir, 2 = excluir).
p
- Uma posição aleatória na lista em que a modificação ocorrerá.
r
- Um número aleatório para inserir ou substituir na lista
f.write("%03d"*3%(n,p,r))
- Anexe os 3 randoms ao final do arquivo de origem. A cada execução, isso adicionará um número inteiro que codifica todas as alterações na fonte inicial que ocorreram.
exec'b=[];h=%d...'%1...
- Obtenha os números aleatórios (encontrados depois %1
em execuções posteriores), aplique as alterações na lista e imprima.
while~-h:b+=[h%%1000];h/=1000
- Crie uma lista dos randoms gerados até o momento, respondendo pelo líder 1
, o que evita problemas com zeros à esquerda.
while b:r,p,n=b[-3:];b=b[:-3]
- Atribua os randoms para esta iteração.
L=[L[:p]+L[p+1:],L[:p]+[r]+L[p+n:]][n<2if L else 1]
- (0 = inserir, 1 = substituir, 2 = excluir)
print"".join(map(chr,L))
- Imprima a fonte modificada.