Entine Quine!


12

งานของคุณคือการเขียนโปรแกรมหรือฟังก์ชั่นซึ่ง:

  • เมื่อรันเป็นครั้งแรกเอาต์พุตของซอร์สโค้ด
  • ในการประมวลผลครั้งต่อไปมันควรจะเอาท์พุทสิ่งที่มันก่อนหน้านี้ แต่มีการเปลี่ยนแปลงตัวละครแบบสุ่มหนึ่งตัว (กำหนดไว้ด้านล่าง) ไม่จำเป็นต้องเป็นการเปลี่ยนแปลงแบบสุ่มอย่างสม่ำเสมอ แต่การเปลี่ยนแปลงที่เป็นไปได้ทุกครั้งควรมีโอกาสที่ไม่เกิดขึ้น

    หลังจากการดำเนินการครั้งแรกโปรแกรมของคุณจะไม่เป็น quine อีกต่อไป ผลลัพธ์จะมีการเปลี่ยนแปลง (และโปรแกรมมีอิสระที่จะแก้ไขตัวเองเช่นกัน)

ตัวอย่างเช่นหากควินินของคุณABCDทำงานซ้ำ ๆ มันอาจพิมพ์:

ABCD
A!CD
j!CD
j!CjD

ข้อมูลจำเพาะ

  • การเปลี่ยนแปลงตัวละครอย่างใดอย่างหนึ่ง:

    • การแทรกตัวอักษรแบบสุ่ม
    • การลบอักขระแบบสุ่มหรือ
    • การแทนที่อักขระด้วยอักขระสุ่มใหม่ โปรดทราบว่าตัวละครใหม่นั้นจะได้รับอนุญาตให้เป็นตัวละครตัวใหม่ที่เข้ามาแทนที่ซึ่งในกรณีนี้จะไม่มีการเปลี่ยนแปลงใด ๆ

    แน่นอนการลบหรือแทนที่อักขระจากสตริงว่างไม่ใช่การเปลี่ยนแปลงที่ถูกต้อง

  • แม้จะเป็นการแท็กกฎการอ่านซอร์สโค้ดของคุณก็ไม่ได้นำมาใช้

คุณสามารถใช้ชุดอักขระใดก็ได้ตราบใดที่มีอักขระที่ใช้ในซอร์สโค้ดของคุณ


1
อักขระแต่ละตัวหมายถึงอะไร
Dennis

2
ต้องทำงานบ่อยแค่ไหน? เห็นได้ชัดว่ามันไม่สามารถโดยพลการหรือโปรแกรมอื่น ๆ ที่เป็นไปได้ไม่ว่าจะนานหรือนานกว่าโปรแกรมเดิมจะต้องมีทางออกสำหรับการท้าทาย
Martin Ender

1
สามารถเพิ่มตัวละครได้ทุกที่หรือตอนจบ?
Conor O'Brien

1
@ ConorO'Brien ได้ทุกที่
แยกผลไม้

1
ต้องทำงานซ้ำกี่ครั้ง?
dylnan

คำตอบ:


7

Python 3 , 288 270 224 212 195 196 194 180 178 168 ไบต์

f=__file__
m=open(f).read()
x=m	
print(end=x)
h=hash
k=h(f)
n=k%2
a=h(m)%-~len(x)
x=x[:a]+(not(k%3)*x)*chr(k%127)+x[a+n:]
open(f,'w').write(m.replace("\t",";x=%r\t"%x))

ลองออนไลน์!

หลังจากพิมพ์ซอร์สโค้ดไฟล์ในการทำซ้ำครั้งแรกเราผนวกบรรทัดเพิ่มเติมเพื่อตั้งค่า x เป็นซอร์สโค้ดใหม่แทนที่จะเป็น m

คำอธิบาย:

f=__file__    #Open and read the source code
m=open(f).read()

x=m       #Set x to the source code for the first iteration
x="..."
...
x="..."   #Set x to the latest iteration
          #On the last iteration there's a tab character to mark progress
print(end=x)    #Print the previous iteration's text

#Modify the text
h=hash
k=h(f)            #Generate a random number to use
n=k%2             #Whether the character will be inserted or changed/deleted
a=h(m)%-~len(x) #The index of the change
                         #Add 1 to the range to append new characters, and to avoid mod by 0 in the case of an empty string
x=x[:a]+(not(k%3)*x)*chr(k%127)+x[a+n:]    #Make the change

open(f,'w').write(m.replace("\t",";x=%r\t"%x))   #Modify the source code, adding the new iteration of the source code

สมมติว่าhashส่งกลับตัวเลขสุ่มอย่างสม่ำเสมอมีโอกาสประมาณ 1/6 ในการแทรกอักขระใหม่โอกาส 1/6 ของการเปลี่ยนอักขระที่มีอยู่และโอกาส 2/6 ในการลบอักขระ โอกาส 2/6 ที่เหลืออยู่ที่คุณถามคืออะไร ทำไมมันไม่ทำอะไรเลย 2/6 ของเวลา!

(นี่คือโปรแกรมการตรวจสอบที่ดัดแปลงมาจากคำตอบ mbomb007 's . ลองออนไลน์! )


ฉันคิดว่าf=__file__จะช่วยในขั้นตอนแรกด้วย
Ørjan Johansen

4

Python 3 , 205 195 ไบต์

s='print(end=x);h=hash;k=h(x);n=k%2;a=h(s)%-~len(x);x=x[:a]+(not(k%3)*x)*chr(k%127)+x[a+n:];open(__file__,"w").write("s=%r;x=%r;exec(s)"%(s,x))';x='s=%r;x=%r;x=x%%(s,x);exec(s)';x=x%(s,x);exec(s)

ลองออนไลน์!

ต้องการลองรุ่นที่ไม่ได้อ่านซอร์สโค้ด เปิดออกไม่ได้เลวร้ายอย่างที่คิดและเป็นเพียง 30 หรือดังนั้นไบต์อยู่เบื้องหลังรุ่นที่ไม่ คำอธิบายสำหรับวิธีการทำงานส่วนใหญ่จะเหมือนกับคำตอบอื่น ๆ แต่จะเริ่มต้น x แตกต่างกันเนื่องจากไม่สามารถอ่านซอร์สโค้ดได้


4

Python 2 , 779 801 ไบต์

แม้ว่าความท้าทายจะได้รับการแก้ไขเพื่อแสดงว่าอนุญาตให้อ่านแหล่งข้อมูลของคุณได้ ดังนั้นเพื่อแสดงว่าเป็นไปได้ฉันทำมันเสร็จแล้ว ไม่มีการอ่านไฟล์ต้นฉบับ:

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))

ลองออนไลน์! (โปรดทราบว่าสิ่งนี้จะไม่แก้ไขแหล่งที่มาคุณต้องเรียกใช้ภายในเครื่องเพื่อให้ทำงานได้)

แสดงให้เห็นว่าการเปลี่ยนแปลงการทำงานของที่นี่เป็นโปรแกรมการทดสอบ (ชุดปัจจุบันถึงเคยรับ100สำหรับrและพิมพ์ผลการรวมกันของทุกคนnและpสำหรับรายการเริ่มต้น.)



คำอธิบาย:

s='s=%r;print s%%s...';print s%s...

บรรทัดแรกคือคลาสสิกของคุณ แต่นานกว่าที่จะพิจารณาว่าเกิดอะไรขึ้น

from random import*;L=4;f=open(__file__,"wa"[L>5]);R=randint

นำเข้าสำหรับจำนวนเต็มแบบสุ่ม Lจะกลายเป็นรายการของเลขลำดับของซอร์สโค้ด แต่เริ่มแรกเป็นจำนวนเต็มที่ไม่ได้ใช้ที่อื่นในแหล่งที่มาเพื่ออนุญาตให้มีการแทนที่สตริง เปิดไฟล์เพื่อเขียนต้นฉบับใหม่ เมื่อเรียกใช้ในภายหลังจะเปิดเพื่อผนวกแทน

f.write("\n".join((s%s).split("\n")[1:5:2]).replace("4",`map(ord,s%s)`))

ลบรหัสบรรทัดแรกและบรรทัดที่สาม แทนที่4ข้างต้นด้วยรายการของเลขลำดับ

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))

เป็นชิ้น ๆ:

  • if L>5:- ข้ามบรรทัดนี้ไปที่การดำเนินการครั้งแรก หลังจากนั้นLจะเป็นรายการและสิ่งนี้จะทำงาน ฉันจะอธิบายexecครั้งสุดท้ายเพราะมันไม่ได้ทำงานครั้งแรก

  • n- สุ่มหมายเลข 0-2 สิ่งนี้พิจารณาว่าการแก้ไขใดที่เกิดขึ้น (0 = insert, 1 = แทนที่, 2 = ลบ)

  • p - ตำแหน่งสุ่มในรายการที่จะเกิดการเปลี่ยนแปลงที่

  • r - ตัวเลขสุ่มที่จะแทรกหรือแทนที่ในรายการ

  • f.write("%03d"*3%(n,p,r))- ผนวก 3 randoms ต่อท้ายไฟล์ต้นฉบับ ทุกครั้งที่ดำเนินการสิ่งนี้จะถูกเพิ่มลงในจำนวนเต็มที่เข้ารหัสการเปลี่ยนแปลงทั้งหมดไปยังแหล่งข้อมูลเริ่มต้นที่เกิดขึ้น

  • exec'b=[];h=%d...'%1...- รับตัวเลขสุ่ม (พบหลังจาก%1ทำงานในภายหลัง) นำการเปลี่ยนแปลงไปใช้กับรายการและพิมพ์

  • while~-h:b+=[h%%1000];h/=1000- สร้างรายการของ randoms ที่สร้างขึ้น, การบัญชีสำหรับนำ1หน้าซึ่งป้องกันปัญหากับศูนย์นำหน้า

  • while 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] - (0 = แทรก, 1 = แทนที่, 2 = ลบ)

  • print"".join(map(chr,L)) - พิมพ์แหล่งที่แก้ไข


บางครั้งสิ่งนี้จะลบอักขระที่ไม่มีอยู่ออกจากจุดสิ้นสุดของสตริงหรือไม่ เนื่องจากpสามารถเป็นความยาวของสตริงได้ นอกจากนี้พฤติกรรมของสตริงว่างคืออะไร
Jo King

@JoKing ฉันเพิ่มโปรแกรมทดสอบ ทุกการเปลี่ยนแปลงตัวละครที่เป็นไปได้สามารถเกิดขึ้นได้ มันแสดงให้เห็นว่าทุกตำแหน่งอาจถูกเลือกเพื่อแทรกแทนที่หรือลบและมันจะจัดการรายการที่ว่างเปล่า tio.run/##LYoxDsMgDEVnOAUjCAZgRO0NuIHloUOaRIocy6JDT08dpdt/…
mbomb007

ฉันไม่คิดว่าการเปลี่ยนแปลงจะไม่ถูกต้อง แต่ฉันได้ขอ OP คำถามจะบอกว่าOf course, deleting or replacing a character from an empty string is not a valid change
Jo King

ฉันถาม Esolanging ผลไม้และพวกเขาบอกว่าไม่มีการเปลี่ยนแปลงเป็นที่ถูกต้อง แต่ไม่ได้สำหรับสตริงที่ว่างเปล่า
Jo King

1
@ โจกิ้งควรได้รับการแก้ไข
mbomb007

1

Java 10, 370 ไบต์

String s;v->{if(s==null){s="String s;v->{if(s==null){s=%c%s%1$c;s=s.format(s,34,s);}else{int r=s.length();r*=Math.random();char c=127;c*=Math.random();s=s.substring(0,r)+(c%%3<2?c:%1$c%1$c)+s.substring(r+(c%%3>0?1:0));}}";s=s.format(s,34,s);}else{int r=s.length();r*=Math.random();char c=127;c*=Math.random();s=s.substring(0,r)+(c%3<2?c:"")+s.substring(r+(c%3>0?1:0));}}

ลองออนไลน์

คำอธิบาย:

String s;               // Class-level String variable to store the modifying source code
v->{                    // Method without parameter nor return-type
  if(s==null){          //  If this is the first execution of this function:
    s="String s;v->{if(s==null){s=%c%s%1$c;s=s.format(s,34,s);}else{int r=s.length();r*=Math.random();char c=127;c*=Math.random();s=s.substring(0,r)+(c%%3<2?c:%1$c%1$c)+s.substring(r+(c%%3>0?1:0));}}";
                        //   Set `s` to the unformatted source-code
    s=s.format(s,34,s);}//   And then to the formatted source-code
else{                   //  For any following executions of this function:
  int r=s.length();r*=Math.random();
                        //   Random index in range [0, length_of_modified_source_code)
  char c=127;c*=Math.random();
                        //   Random ASCII character in unicode range [0, 127)
  s=                    //   Replace the current String `s` with:
    s.substring(0,r)    //    The first [0, `r`) characters of the modified source code `s`
    +(c%3<2?            //    If the random option is 0 or 1:
           c:"")        //     Append the random character
        +s.substring(r  //    Append the rest of the modified source code `s`, but:
          +(c%3>0?      //     If the random option is 1 or 2:
             1:0));}}   //      Skip the first character of this second part

คำอธิบายทั่วไป:

:

  • String sมีซอร์สโค้ดที่ยังไม่ฟอร์แมต
  • %sจะใช้ในการป้อนข้อมูล String s.format(...)นี้ลงในตัวเองด้วย
  • %c, %1$cและ34จะใช้ในการจัดรูปแบบราคาสองครั้ง
  • ( %%ใช้เพื่อจัดรูปแบบโมดูโล - %)
  • s.format(s,34,s) ทำให้มันเข้าด้วยกัน

นี่คือโปรแกรม Java Quine พื้นฐาน

ส่วนที่ท้าทาย:

  • String s; เป็นซอร์สโค้ดที่เราจะแก้ไขในระดับชั้นเรียน
  • int r=s.length();r*=Math.random();[0, length_of_modified_source_code)จะใช้ในการเลือกดัชนีสุ่มรหัสที่มาในช่วง
  • char c=127;c*=Math.random();จะใช้ในการเลือกอักขระ ASCII สุ่ม (รวม unprintables) [0, 126]อยู่ในช่วงของ
  • c%3จะใช้ในการเลือกตัวเลือกสุ่มของทั้ง 0, 1 หรือ 2 ตัวเลือกที่ 0 จะเพิ่มตัวละครสุ่มก่อนที่ดัชนีr; ตัวเลือกที่ 1 จะแทนที่อักขระที่ดัชนีrด้วยอักขระแบบสุ่ม และทางเลือกที่ 2 rจะลบตัวอักษรที่ดัชนี
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.