一个程序,在没有任何外部输入的情况下,打印自身的源代码,这类程序在英文里有一个专门的称呼,叫做Quine,之所以叫这个名字,是为了纪念美国哲学家及逻辑学家Willard Van Orman Quine。
问题分析
首先要搞清楚问题的约束条件,即程序不能有任何的外部输入,否则可以通过把文件路径传入程序来获取源文件再打印出来,这种情况被看作是作弊。
我们以Python2作为示例语言。我们知道 printprint 关键字能够将内容输出到控制台:它实际上是一个函数,接受一个入参,并把它打印到控制台。但是我们的程序是没有输入的,因此,最最简单直观的思路,我们的程序(假设为 <P><P> )至少应该包含两个语句(假设为 <A>,<B><A>,<B> ),即:
<P> := <A><B>
他们分别有如下职责:
<A> : 定义<B> (或者说在程序没有输入的情况下要为print函数创造输入)
<B> : 首先要打印<A>的源代码,其次要把自身的源代码打印出来
用中文来说,可以是:
把以下的话抄一遍后再抄在引号里“把以下的话抄一遍后再抄在引号里”
基本上编写一个Quine的精髓就在上面这段话里。
在Python中有一个 %r\%r ,它的意思就是调用对象的 repr()repr() 方法后替换本身在字符串中的位置,对于字符串对象,会保留其本身的引号(这点在我们实现Quine的时候会减少很多麻烦)。我们可以借助它实现一个最简单的Quine:
s = s = %r\nprint s %% s
print s % s
程序第一行我们定义了一个变量 ss ,在第二行我们首先将 ss 的字面量传进 ss 用于生成本程序的完整代码随即打印它。如果不借助 %r\%r 程序会复杂一些,但基本的思路是差不多的:
# -*- coding:utf-8 -*-
q = chr(39) # 定义单引号
n = chr(10) # 定义换行符
s = # -*- coding:utf-8 -*-%sq = chr(39) # 定义单引号%sn = chr(10) # 定义换行符%ss = %s%s%s%sprint s %% (n, n, n, q, s, q, n)
print s % (n, n, n, q, s, q, n)
如何使程序输出MD5等于自身源代码的MD5
这个其实和上面的问题是等价的,能够输出自身源代码,当然也能输出自身的MD5了:
import hashlib
m = hashlib.md5()
s = import hashlib\nm = hashlib.md5()\ns = %r\nm.update(s %% s)\nprint m.hexdigest()
m.update(s % s)
print m.hexdigest()
测试一下:
zhaoyuyu@FISHZHAO-MB0 demo % md5sum quine.py
0499c0b4e56111ba6587db5624f21345 quine.py
zhaoyuyu@FISHZHAO-MB0 demo % python quine.py
0499c0b4e56111ba6587db5624f21345
完美!
拓展阅读:
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END