Aunque el desafío se editó para mostrar que la lectura de su fuente está permitida, ya estaba creando mi solución sin eso. Entonces, para demostrar que es posible, lo terminé. Sin lectura del archivo fuente:
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))
Pruébalo en línea! (Tenga en cuenta que esto no modificará la fuente. Debe ejecutarlo localmente para que funcione)
Para demostrar que las transformaciones funcionan, aquí es un programa de prueba (actualmente configurada para recoger siempre 100
para r
, y se imprime el resultado para cada combinación de n
y p
para la lista inicial.)
Explicación:
s='s=%r;print s%%s...';print s%s...
La primera línea es su quine clásico, pero mucho más para dar cuenta de lo que viene después.
from random import*;L=4;f=open(__file__,"wa"[L>5]);R=randint
Importar para enteros aleatorios. L
se convertirá en una lista de ordinales del código fuente, pero inicialmente es un número entero que no se usa en ningún otro lugar de la fuente para permitir el reemplazo de una cadena. Abra el archivo para escribir la nueva fuente. En ejecuciones posteriores, se abrirá para agregar en su lugar.
f.write("\n".join((s%s).split("\n")[1:5:2]).replace("4",`map(ord,s%s)`))
Elimina la primera y tercera línea de código. Reemplace lo 4
anterior con la lista de ordinales.
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))
En pedazos:
if L>5:
- Omite esta línea en la primera ejecución. Más tarde, L
habrá una lista, y esto se ejecutará. Explicaré lo exec
último, porque no se ejecuta la primera vez.
n
- Un número aleatorio 0-2. Esto determina qué modificación ocurre (0 = insertar, 1 = reemplazar, 2 = eliminar).
p
- Una posición aleatoria en la lista en la que ocurrirá la modificación.
r
- Un número aleatorio para insertar o reemplazar en la lista
f.write("%03d"*3%(n,p,r))
- Agregue los 3 randoms al final del archivo fuente. En cada ejecución, esto se agregará a un número entero que codifica todos los cambios en la fuente inicial que se han producido.
exec'b=[];h=%d...'%1...
- Obtenga los números aleatorios (que se encuentran después %1
en ejecuciones posteriores), aplique los cambios a la lista e imprima.
while~-h:b+=[h%%1000];h/=1000
- Construya una lista de los randoms generados hasta el momento, teniendo en cuenta el inicio 1
, lo que evita problemas con los ceros iniciales.
while b:r,p,n=b[-3:];b=b[:-3]
- Asignar los randoms para esta iteración.
L=[L[:p]+L[p+1:],L[:p]+[r]+L[p+n:]][n<2if L else 1]
- (0 = insertar, 1 = reemplazar, 2 = eliminar)
print"".join(map(chr,L))
- Imprime la fuente modificada.