在知乎上看到一个问题
是否无法写一段代码将这段代码自己打印出来?
答1
var s = '__'; console.log(unescape(s).replace('__', s))
然后把程序的源码 escape 下塞进 s 后面的引号里:
var s = 'var%20s%20%3D%20%27__%27%3B%20console.log%28unescape%28s%29.replace%28%27__%27%2C%20s%29%29'; console.log(unescape(s).replace('__', s))
上面这种是所谓「正统 Quine」(不依赖各种反射)的做法:先写出一个解码-替换-输出的过程,源码部分只留下「槽」,然后把程序整体编码一次塞进原来留的「槽」里,这样就能得到一个有效的 Quine 程序。
写出形如 AABCC 的代码,其中 C 的作用是打印 ABC,并把 B 替换成 ABC,这样就能打印出 AABCC
互相输出对方的 Ouroboros Quine 也能弄啊,方式也是类似的,写两个程序:只不过要小心处理「槽」替换的过程就是了。
答2
网上流传很广的一个经典例子是Ken Thompson很早之前用C写的
char*f="char*f=%c%s%c;main(){printf(f,34,f,34,10);}%c";main(){printf(f,34,f,34,10);}
答3
char a[]="#include \n"
"main(){char*p=a;printf(\"char a[]=\\\"\");while(*p){\n"
"switch(*p){case'\\\"':printf(\"\\\\\\\"\");break;case'\\\\':\n"
"printf(\"\\\\\\\\\");break;case'\\n':printf(\"\\\\n\\\"\\n\\\"\");\n"
"break;default:putchar(*p);}p++;}printf(\"\\\";\\n\");\n"
"fwrite(a,sizeof(a)-1,1,stdout);}\n"
"";
#include
main(){char*p=a;printf("char a[]=\"");while(*p){
switch(*p){case'\"':printf("\\\"");break;case'\\':
printf("\\\\");break;case'\n':printf("\\n\"\n\"");
break;default:putchar(*p);}p++;}printf("\";\n");
fwrite(a,sizeof(a)-1,1,stdout);}
答4
原理:将引号中的话抄一遍,再抄在引号里,再画一个句号“将引号中的话抄一遍,再抄在引号里,再画一个句号”。
python3
all="print('all={}{}{}{}{}'.format(chr(34),all,chr(34),chr(10),all))"
print('all={}{}{}{}{}'.format(chr(34),all,chr(34),chr(10),all))
python3(使用语言反射功能)
def run_self(x):
def f(x):
if type(x)==bytes:
return repr(x[::-1].decode())
else:
return x.encode()[::-1]
import inspect
print(inspect.getsource(run_self) + 'run_self({})'.format(f(x)))
run_self(b'\x95\xb3\xe6\x9e\x8a\xe5\x8d\xa7\xe7\x83\x8d\xe5\x80\xb8\xe4\x89\x9c\xe6\x91\xb0\xe5\xb3\x87\xe8\x9d\xaf\xe8\xb4\xaf\xe8\x81\xa6\xe8')
scheme
((lambda (THIS-IS-QUINE) `(,THIS-IS-QUINE ',THIS-IS-QUINE)) '(lambda (THIS-IS-QUINE) `(,THIS-IS-QUINE ',THIS-IS-QUINE)))
JS
((x)=>{console.log('('+x+')'+'('+x+')');})((x)=>{console.log('('+x+')'+'('+x+')');})
。。。。。。。