熵奎因!


12

您的任务是编写一个程序或函数,其中:

  • 首次运行时,输出其源代码。
  • 在随后的执行中,它应该输出先前输出的内容,但是会随机更改一个字符(定义如下)。它不必是一致的随机变化,但是每个可能的变化都应该有非零的发生机会。

    第一次执行后,您的程序将不再是奎因。输出将已更改(该程序也可以自由修改自己)。

例如,如果您的quine是ABCD,则反复运行它可能会打印:

ABCD
A!CD
j!CD
j!CjD

技术指标

  • 字符更改是:

    • 插入一个随机字符,
    • 删除随机字符,或
    • 用新的随机字符替换字符。请注意,新字符允许与其替换的字符相同,在这种情况下,将不会进行任何更改。

    当然,从空字符串中删除或替换字符不是有效的更改。

  • 尽管将其标记为,但禁止阅读源代码的规则并不适用。

您可以使用任何字符集,只要它包含源代码中使用的字符即可。


1
每个字符指的是什么字符?
丹尼斯,

2
它必须多久工作一次?显然,它不可能任意频繁地出现,否则,每个可能比原始程序更长或更长时间的程序都必须是应对挑战的解决方案。
Martin Ender

1
角色可以在任何地方添加还是在结尾添加?
Conor O'Brien

1
@ ConorO'Brien任何地方。
Esolanging Fruit

1
它必须工作多少次迭代?
迪南2018年

Answers:


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的答案改编而成的验证程序。请在线尝试!


我认为f=__file__这也会对第一步有所帮助。
与Orjan约翰森

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

在线尝试! (请注意,这不会修改源代码。您必须在本地运行它才能正常工作)

为了证明转换有效,这是一个测试程序(当前设置为始终选择100for r,并且它为np初始列表的每个组合打印结果。)



说明:

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

第一行是您的经典quine,但是要花很多时间才能解释后面的内容。

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 =插入,1 =替换,2 =删除)。

  • p -修改将在列表中出现的随机位置。

  • r -要在列表中插入或替换的随机数

  • f.write("%03d"*3%(n,p,r))-将3个随机数附加到源文件的末尾。每次运行时,它将添加一个整数,该整数对已发生的对初始源的所有更改进行编码。

  • exec'b=[];h=%d...'%1...-获取随机数(%1在以后的运行中找到),将更改应用于列表,然后打印。

  • while~-h:b+=[h%%1000];h/=1000-建立到目前为止生成的随机变量列表,并考虑前导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
'18

尽管我已经询问过OP,但我认为没有任何改变是有效的。问题确实在说Of course, deleting or replacing a character from an empty string is not a valid change
乔·金

我问过Esolanging Fruit,他们说没有任何更改有效的,但对于空字符串来说无效。
Jo King

1
@JoKing应该是固定的。
mbomb007 '18

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

一般说明:

-part:

  • 字符串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();用于选择unicode范围内的随机ASCII字符(包括不可打印的字符)[0, 126]
  • c%3用于选择0、1或2的随机选项。选项0将在index之前添加随机字符r;选项1将r使用随机字符替换索引处的字符;选项2将删除index处的字符r
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.