34

我已经看到很多基于 C/C++ 的解决方案来解决这个问题,我们必须编写一个程序,在执行时打印它自己的源代码。

一些解决方案——

http://www.cprogramming.com/challenges/solutions/self_print.html

多种语言的 Quine Page 解决方案

网络上有更多的解决方案,每个解决方案都各不相同。我想知道我们如何处理这样一个问题,解决这个问题的人的内心是什么。借给我一些关于这个问题的见解......虽然解释语言(如 perl、php、ruby 等)的解决方案可能很容易......我想知道如何用编译语言设计它......

4

10 回答 10

56

除了作弊¹之外,编译语言和解释语言之间没有区别。

quines 的通用方法非常简单。首先,无论程序是什么样的,在某些时候它必须打印一些东西:

打印 ...

但是,它应该打印什么?本身。所以它需要打印“打印”命令:

打印“打印...”

接下来应该打印什么?好吧,与此同时程序也在增长,所以它也需要打印以“print”开头的字符串:

打印“打印\”打印...\“”

现在程序再次增长,所以还有更多要打印的内容:

打印"打印\"打印\\\"...\\\"\""

等等。每添加一个代码,就会有更多代码要打印。这种方法无济于事,但它揭示了一个有趣的模式:字符串“print \”“一遍又一遍地重复。将重复部分放入变量中会很好:

a = "打印\""
打印一个

但是,程序刚刚改了,所以我们需要调整一个:

a = "a = ...\n打印一个"
打印一个

当我们现在尝试填写“...”时,我们遇到了和以前一样的问题。最终,我们想写这样的东西:

a = "a = " + (a 的引用内容) + "\nprint a"
打印一个

但这是不可能的,因为即使我们有这样的quoted()引用功能,仍然存在我们a根据自身定义的问题:

a = "a = " + 引用(a) + "\nprint a"
打印一个

所以我们唯一能做的就是将占位符放入a

a = "a = @\n打印一个"
打印一个

这就是全部技巧!现在其他任何事情都清楚了。只需将占位符替换为以下引用的内容a

a = "a = @\n打印一个"
打印 a.replace("@", 引用(a))

由于我们更改了代码,我们需要调整字符串:

a = "a = @\nprint a.replace(\"@\", 引用(a))"
打印 a.replace("@", 引用(a))

就是这样!所有语言的所有 quines 都以这种方式工作(作弊的除外)。

那么,您应该确保只替换第一次出现的占位符。如果你使用第二个占位符,你可以避免需要引用字符串。

但这些都是小问题,很容易解决。事实上,实现quoted()replace() 是各种 quines 真正不同的唯一细节。


¹ 通​​过让程序读取其源文件

于 2008-09-20T01:01:52.530 回答
9

编写quines有几种不同的策略。显而易见的一种是只编写打开代码并将其打印出来的代码。但更有趣的是涉及允许自嵌入的语言功能,例如许多语言中的 %s 样式的 printf 功能。您必须弄清楚如何嵌入某些内容,以便最终解决要嵌入的请求。我怀疑,就像回文一样,涉及到大量的反复试验。

于 2008-09-19T21:24:41.660 回答
1

通常的方法(当你不能作弊时*)是编写一些将其源编码为字符串常量的东西,然后将该常量打印出两次:一次作为字符串文字,一次作为代码。这绕过了“每次我写一行代码,我都必须再写一个来打印出来!” 问题。

“作弊”包括: - 使用解释语言并简单地加载源并打印它 - 0 字节长的文件,在某些语言中有效,例如 C。

于 2008-09-19T21:25:42.767 回答
1

为了好玩,我在 Scheme 中想出了一个,我为此骄傲了大约 5 分钟,直到我发现之前已经被发现。无论如何,为了更好地计算 Lisp 中数据和代码的对偶性,对游戏的“规则”进行了轻微修改:它不是打印出程序的源代码,而是一个返回自身的 S 表达式:

((lambda (x) (list x `',x)) '(lambda (x) (list x `',x)))

维基百科上的那个具有相同的概念,但引用机制略有不同(更冗长)。不过我更喜欢我的。

于 2008-10-12T03:07:20.850 回答
0

一个想法是考虑编码以及如何赋予某些东西双重含义,以便它可以用于以几种形式输出某些东西。还有一个警告,这种类型的问题带有限制,使其更难,因为除了程序输出本身之外没有任何规则,空程序是一个解决方案。

于 2008-09-19T21:27:08.253 回答
0

实际阅读和打印您的源代码怎么样?一点都不难!!这是php中的一个:

<?php
{
header("Content-Type: text/plain");
    $f=fopen("5.php","r");
    while(!feof($f))
    {
        echo fgetc($f);
    } 
    fclose($f);
}
?>
于 2013-01-01T17:45:07.383 回答
0

在python中,您可以编写:

s='c=chr(39);print"s="+c+s+c+";"+s';c=chr(39);print"s="+c+s+c+";"+s

受此自打印伪代码的启发:

Print the following line twice, the second time with quotes.
"Print the following line twice, the second time with quotes."
于 2013-08-02T11:56:17.403 回答
0

我为那些对此感兴趣的人做了一个 AS3 示例

var program = "var program = @; function main(){trace(program.replace('@', 

String.fromCharCode(34) + program + String.fromCharCode(34)))} main()"; 
function main(){
   trace(program.replace('@', String.fromCharCode(34) + program + String.fromCharCode(34)))
}
main()
于 2013-12-11T17:11:15.363 回答
-1

在 bash 中,这真的很容易

触摸测试;chmod oug+x 测试;。/测试

空文件,空输出

于 2020-10-30T13:05:33.243 回答
-2

在红宝石中:

将 File.read(_ _ FILE _ _)

于 2008-09-19T21:22:48.763 回答