Quine—— 输出自身的程序

如果一段程序的代码运行之后,产生的输出和其自身的源码完全相同,那么这段程序就被称为 Quine,以哲学家 Willard van Orman Quine(1908-2000)而命名。
Quine 在任何图灵完备,且能输出任意字符串的语言中都是可行的。在可计算性理论(computability theory)中,图灵等价指的是:对于两个计算机 A 和 B,如果 A 可以模拟 B,B 可以模拟 A,就称他们是图灵等价的。根据「丘奇 - 图灵」理论,图灵机是表达能力最强大的计算系统,对现实世界中的任何计算机,都可以用图灵机来模拟它。而如果一个编程语言可以完全模拟图灵机,那么它就是图灵完备的。
大部分编程语言都是图灵完备的,在这些语言中,构造 Quine 的思路也是类似的。Quine 中往往需要包含数据和程序两部分。数据是程序的表示(例如将程序中的特殊字符编码,存储在一个字符串中),而程序负责解析数据并将其输出。此外,利用一些语言的语法特性也可以构造出比较简单的 Quine。


Bash

1
z=\' a='z=\\$z a=$z$a$z\; eval echo \$a'; eval echo $a

JavaScript

1
!function $(){console.log('!'+$+'()')}()
1
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))

Python 3

1
2
r='r=%r\nprint(r%%r)'
print(r%r)
1
2
3
x='y="x="+repr(x)+"\\n"\nprint(y+x)'
y="x="+repr(x)+"\n"
print(y+x)

C

1
char*s="char*s=%c%s%c;main(){printf(s,34,s,34);}";main(){printf(s,34,s,34);}
1
main(){char s[]="main(){char s[]=%c%s%c;printf(s,34,s,34);return 0;}";printf(s,34,s,34);return 0;}
1
2
3
4
5
6
7
8
9
10
#include <stdio.h>
char buff[80];
int main() {
FILE *fp;
fp = fopen(__FILE__, "r");
while (!feof(fp)) {
printf("%s", fgets(buff, 79, fp));
}
fclose(fp);
}

上面这个有些赖皮,直接读取并输出了源代码。有些 Quine 规则会不允许这样做。

PHP

1
echo file_get_contents(__FILE__);

这个同样是赖皮做法,笔者后来又仿造 C 语言的 Quine 的构思了一个

1
<?php $s = '<?php $s = %c%s%c; printf($s, 39, $s, 39); ?>'; printf($s, 39, $s, 39); ?>

Rust

1
fn main(){print!("{},{0:?})}}","fn main(){print!(\"{},{0:?})}}\"")}
1
2
3
fn main() {
println!("{}", include_str!("main.rs"))
}

Perl

1
$_=q{print"\$_=q{$_};eval"};eval

Pascal

1
CONST T=';BEGIN WRITE(#67#79#78#83#84#32#84#61#39,T,#39,T)END.';BEGIN WRITE(#67#79#78#83#84#32#84#61#39,T,#39,T)END.

Brainfuck

1
>+>+++>>+>++>+>+++>>+>++>>>+>+>+>++>+>>>>+++>+>>++>+>+++>>++>++>>+>>+>++>++>+>>>>+++>+>>>>++>++>>>>+>>++>+>+++>>>++>>++++++>>+>>++>+>>>>+++>>+++++>>+>+++>>>++>>++>>+>>++>+>+++>>>++>>+++++++++++++>>+>>++>+>+++>+>+++>>>++>>++++>>+>>++>+>>>>+++>>+++++>>>>++>>>>+>+>++>>+++>+>>>>+++>+>>>>+++>+>>>>+++>>++>++>+>+++>+>++>++>>>>>>++>+>+++>>>>>+++>>>++>+>+++>+>+>++>>>>>>++>>>+>>>++>+>>>>+++>+>>>+>>++>+>++++++++++++++++++>>>>+>+>>>+>>++>+>+++>>>++>>++++++++>>+>>++>+>>>>+++>>++++++>>>+>++>>+++>+>+>++>+>+++>>>>>+++>>>+>+>>++>+>+++>>>++>>++++++++>>+>>++>+>>>>+++>>++++>>+>+++>>>>>>++>+>+++>>+>++>>>>+>+>++>+>>>>+++>>+++>>>+[[->>+<<]<+]+++++[->+++++++++<]>.[+]>>[<<+++++++[->+++++++++<]>-.------------------->-[-<.<+>>]<[+]<+>>>]<<<[-[-[-[>>+<++++++[->+++++<]]>++++++++++++++<]>+++<]++++++[->+++++++<]>+<<<-[->>>++<<<]>[->>.<<]<<]

Lisp(mit-scheme)

1
((lambda (x) (list x (list (quote quote) x))) (quote (lambda (x) (list x (list (quote quote) x)))))

参考文章:
能不能写出一个代码,使代码的运行结果是输出这段代码本身? - 知乎
自生程式
Quines (self-replicating programs)

拓展阅读:
The Quine Page
是否无法写一段代码将这段代码自己打印出来? - 知乎
编程领域都有哪些牛逼闪闪的「禁术」? - 知乎

更多神奇的 Quine 代码:
quine-relay
quine-central
quinesnake
quine.bf