Python 2 , 779 801 bajtów
Chociaż wyzwanie zostało zredagowane, aby pokazać, że czytanie Twojego źródła jest dozwolone, już bez niego tworzyłem swoje rozwiązanie. Aby pokazać, że to możliwe, skończyłem. Brak odczytu pliku źródłowego:
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))
Wypróbuj online! (Pamiętaj, że nie spowoduje to modyfikacji źródła. Aby działało, musisz uruchomić je lokalnie)
Aby pokazać, że transformacje działają, oto program testowy (obecnie skonfigurowany tak, aby zawsze wybierał 100
dla r
, i drukuje wynik dla każdej kombinacji n
i p
dla początkowej listy).
Wyjaśnienie:
s='s=%r;print s%%s...';print s%s...
Pierwsza linia to twoja klasyczna quine, ale o wiele dłużej, aby uwzględnić to, co nastąpi później.
from random import*;L=4;f=open(__file__,"wa"[L>5]);R=randint
Importuj losowe liczby całkowite. L
stanie się listą porządków kodu źródłowego, ale początkowo jest liczbą całkowitą, która nie jest używana nigdzie indziej w źródle, aby umożliwić zamianę ciągu. Otwórz plik, aby napisać nowe źródło. W późniejszych uruchomieniach zostanie ono otwarte, aby dołączyć.
f.write("\n".join((s%s).split("\n")[1:5:2]).replace("4",`map(ord,s%s)`))
Usuń pierwszą i trzecią linię kodu. Zamień 4
powyższe na listę rzędnych.
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))
W kawałkach:
if L>5:
- Pomija tę linię przy pierwszym wykonaniu. Później L
pojawi się lista, która się uruchomi. Wyjaśnię to exec
ostatnie, ponieważ nie jest uruchamiane za pierwszym razem.
n
- Liczba losowa 0-2. Określa, która modyfikacja nastąpi (0 = wstaw, 1 = zamień, 2 = usuń).
p
- Losowa pozycja na liście, na której nastąpi modyfikacja.
r
- Liczba losowa do wstawienia lub zastąpienia na liście
f.write("%03d"*3%(n,p,r))
- Dołącz 3 losowe na końcu pliku źródłowego. Przy każdym uruchomieniu będzie to dodawane do liczby całkowitej, która koduje wszystkie zmiany w początkowym źródle, które miały miejsce.
exec'b=[];h=%d...'%1...
- Uzyskaj losowe liczby (znalezione po %1
późniejszych uruchomieniach), zastosuj zmiany do listy i wydrukuj.
while~-h:b+=[h%%1000];h/=1000
- Zbuduj listę losowych generowanych do tej pory, uwzględniając wiodące 1
, co zapobiega problemom z zerami wiodącymi.
while b:r,p,n=b[-3:];b=b[:-3]
- Przypisz losowe dla tej iteracji.
L=[L[:p]+L[p+1:],L[:p]+[r]+L[p+n:]][n<2if L else 1]
- (0 = wstaw, 1 = zamień, 2 = usuń)
print"".join(map(chr,L))
- Wydrukuj zmodyfikowane źródło.