Python 2 , 779 801 octets
Bien que le défi ait été modifié pour montrer que la lecture de votre source est autorisée, je créais déjà ma solution sans cela. Donc, pour montrer que c'est possible, je l'ai terminé. Pas de lecture du fichier source:
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))
Essayez-le en ligne! (Notez que cela ne modifiera pas la source. Vous devez l'exécuter localement pour que cela fonctionne)
Pour montrer que les transformations fonctionnent, voici un programme de test (actuellement mis en place pour prendre toujours 100
pour r
, et il imprime le résultat pour chaque combinaison de n
et p
pour la liste initiale.)
Explication:
s='s=%r;print s%%s...';print s%s...
La première ligne est votre quine classique, mais beaucoup plus longue pour tenir compte de ce qui vient après.
from random import*;L=4;f=open(__file__,"wa"[L>5]);R=randint
Importer pour des entiers aléatoires. L
deviendra une liste d'ordinaux du code source, mais au départ c'est un entier qui n'est utilisé nulle part ailleurs dans la source pour permettre un remplacement de chaîne. Ouvrez le fichier pour écrire la nouvelle source. Lors des exécutions ultérieures, il s'ouvrira pour s'ajouter à la place.
f.write("\n".join((s%s).split("\n")[1:5:2]).replace("4",`map(ord,s%s)`))
Supprimez les première et troisième lignes de code. Remplacez ce qui 4
précède par la liste des ordinaux.
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 morceaux:
if L>5:
- Ignore cette ligne lors de la première exécution. Plus tard, L
sera une liste, et cela s'exécutera. Je vais expliquer le exec
dernier, car il n'est pas exécuté la première fois.
n
- Un nombre aléatoire 0-2. Ceci détermine quelle modification se produit (0 = insérer, 1 = remplacer, 2 = supprimer).
p
- Une position aléatoire dans la liste où la modification se produira.
r
- Un nombre aléatoire à insérer ou à remplacer dans la liste
f.write("%03d"*3%(n,p,r))
- Ajoutez les 3 aléas à la fin du fichier source. À chaque exécution, cela s'ajoutera à un entier qui code toutes les modifications apportées à la source initiale qui se sont produites.
exec'b=[];h=%d...'%1...
- Obtenez les nombres aléatoires (trouvés après %1
lors des exécutions ultérieures), appliquez les modifications à la liste et imprimez.
while~-h:b+=[h%%1000];h/=1000
- Construisez une liste des aléas générés jusqu'à présent, en tenant compte de l'interlignage 1
, ce qui évite les problèmes avec les zéros non significatifs.
while b:r,p,n=b[-3:];b=b[:-3]
- Attribuez les aléas pour cette itération.
L=[L[:p]+L[p+1:],L[:p]+[r]+L[p+n:]][n<2if L else 1]
- (0 = insérer, 1 = remplacer, 2 = supprimer)
print"".join(map(chr,L))
- Imprimez la source modifiée.