Mặc dù thử thách đã được chỉnh sửa để cho thấy rằng việc đọc nguồn của bạn được cho phép, tôi đã tạo ra giải pháp của mình mà không cần điều đó. Vì vậy, để cho thấy rằng nó có thể, tôi đã hoàn thành nó. Không đọc tệp nguồn:
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))
Hãy thử trực tuyến! (Lưu ý rằng điều này sẽ không sửa đổi nguồn. Bạn phải chạy nó cục bộ để nó hoạt động)
Để chứng minh rằng các biến đổi làm việc, đây là một chương trình thử nghiệm (hiện được thiết lập để luôn luôn chọn 100
cho r
, và nó in kết quả cho mỗi sự kết hợp của n
và p
cho danh sách ban đầu.)
Giải trình:
s='s=%r;print s%%s...';print s%s...
Dòng đầu tiên là quine cổ điển của bạn, nhưng lâu hơn nhiều để tính đến những gì đến sau.
from random import*;L=4;f=open(__file__,"wa"[L>5]);R=randint
Nhập cho số nguyên ngẫu nhiên. L
sẽ trở thành danh sách thứ tự của mã nguồn, nhưng ban đầu nó là một số nguyên không được sử dụng ở bất kỳ nơi nào khác trong nguồn để cho phép thay thế chuỗi. Mở tệp để viết nguồn mới. Trong các lần chạy sau, nó sẽ mở để nối thêm.
f.write("\n".join((s%s).split("\n")[1:5:2]).replace("4",`map(ord,s%s)`))
Loại bỏ các dòng mã đầu tiên và thứ ba. Thay thế 4
ở trên với danh sách các chức.
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))
Trong phần:
if L>5:
- Bỏ qua dòng này trong lần thực hiện đầu tiên. Sau đó, L
sẽ là một danh sách, và điều này sẽ chạy. Tôi sẽ giải thích exec
lần cuối, vì nó không chạy lần đầu tiên.
n
- Một số ngẫu nhiên 0-2. Điều này xác định sửa đổi nào xảy ra (0 = insert, 1 = thay thế, 2 = xóa).
p
- Một vị trí ngẫu nhiên trong danh sách mà sửa đổi sẽ xảy ra tại.
r
- Một số ngẫu nhiên để chèn hoặc thay thế trong danh sách
f.write("%03d"*3%(n,p,r))
- Nối 3 randoms vào cuối tệp nguồn. Mỗi lần chạy, điều này sẽ được thêm vào một số nguyên mã hóa tất cả các thay đổi đối với nguồn ban đầu đã xảy ra.
exec'b=[];h=%d...'%1...
- Nhận các số ngẫu nhiên (được tìm thấy sau các %1
lần chạy sau), áp dụng các thay đổi cho danh sách và in.
while~-h:b+=[h%%1000];h/=1000
- Xây dựng một danh sách các randoms được tạo ra cho đến nay, chiếm vị trí hàng đầu 1
, trong đó ngăn ngừa các vấn đề với các số 0 đứng đầu.
while b:r,p,n=b[-3:];b=b[:-3]
- Chỉ định các randoms cho lần lặp này.
L=[L[:p]+L[p+1:],L[:p]+[r]+L[p+n:]][n<2if L else 1]
- (0 = chèn, 1 = thay thế, 2 = xóa)
print"".join(map(chr,L))
- In nguồn đã sửa đổi.