查看文章 |
一段代码 m 经过编译,运行后,得到的输出与 m 完全相同,则称 m 为能自我复现的程序。也就是说,这样的代码 m 是其运行环境里的一个“不动点”。 这样的程序在 Mathematica 里很容易写,比如“1”,“a”等等。这还不是最短的:最短的 m 即“没有代码”。 相对更“严肃”一些的自我复制程序是这样的:Print[# <> quote[#]]& @ "Print[# <> quote[#]]& @ "。 其中,quote = "\"" <> # <> "\""&。 C 语言实现起来要难很多:char*f="char*f=%c%s%c;main(){printf(f,34,f,34,10);}%c";main(){printf(f,34,f,34,10);}。 zip 压缩文件也存在类似的不动点。这样的压缩包弄不好会让反病毒程序进入死循环。为此,反病毒程序可以检测一下解压后是否与解压前相同。那么,能不能构造出 a.zip -> b.zip -> a.zip 这样的文件? 或者,能否构造出 m0 -> m1 -> m0 的程序呢?答案是肯定的。 比如下面的 Mathematica 程序: Print[#1 <> quote[#1] <> "," <> quote[#3] <> "," <> quote[#2] <> "]"] & ["Print[#1 <> quote[#1] <> \",\" <> quote[#3] <> \",\" <> quote[#2] <> \"]\"] & [","a","b"] 输出得: Print[#1 <> quote[#1] <> "," <> quote[#3] <> "," <> quote[#2] <> "]"] & ["Print[#1 <> quote[#1] <> \",\" <> quote[#3] <> \",\" <> quote[#2] <> \"]\"] & [","b","a"] 其中 quote = "\"" <> FromCharacterCode[Join@@(fMap[qc, ToCharacterCode[#]])] <> "\"" &,qc = If[# == 34, {93, 34}, {#}]&。 显然,上述做法可推广到 m0 经过 n 步回到 m0 的情况。 |

