34

私は、実行時に独自のソースを出力するプログラムを作成する必要がある、この問題に対する C/C++ ベースのソリューションを数多く見てきました。

いくつかの解決策 --

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

多くの言語でのQuine Pageソリューション

ネット上にはさらに多くのソリューションがあり、それぞれが他とは異なります。このような問題にどのようにアプローチするのか、それを解決する人の心の中はどうなっているのだろうか。この問題についていくつかの洞察を貸してください... perl、php、rubyなどの解釈された言語での解決策は簡単かもしれません...コンパイルされた言語でそれを設計する方法を知りたいです...

4

10 に答える 10

56

不正行為¹ を除けば、コンパイルされた言語と解釈された言語の間に違いはありません。

クインへの一般的なアプローチは非常に簡単です。まず、プログラムがどのようなものであれ、ある時点で何かを出力する必要があります:

印刷 ...

しかし、何を印刷すればよいのでしょうか? 自体。したがって、「印刷」コマンドを印刷する必要があります。

印刷「印刷...」

次に何を印刷しますか?その間、プログラムは大きくなったため、"print" で始まる文字列も出力する必要があります。

print "print \"print ...\""

プログラムが再び大きくなったので、印刷するものがまた増えました。

print "print \"print \\\"...\\\"\""

等々。コードを追加するたびに、印刷するコードが増えます。このアプローチはうまくいきませんが、興味深いパターンが明らかになります: 文字列 "print \"" が何度も繰り返されます。繰り返し部分を変数に入れるとよいでしょう:

a = "印刷\""
印刷する

ただし、プログラムが変更されたばかりなので、以下を調整する必要があります。

a = "a = ...\n印刷 a"
印刷する

「...」を入力しようとすると、以前と同じ問題に遭遇します。最終的には、次のように書きたいと思います。

a = "a = " + (a の内容を引用) + "\nprint a"
印刷する

しかし、それは不可能です。なぜならquoted()、引用のためのそのような関数があったとしても、それ自体に関して定義する問題がまだあるaからです:

a = "a = " + quoted(a) + "\nprint a"
印刷する

したがって、私たちができる唯一のことは、プレースホルダーを に入れることですa:

a = "a = @\nprint a"
印刷する

そして、それがすべてのトリックです!他のことはもう明らかです。プレースホルダーを次の引用された内容に置き換えるだけですa

a = "a = @\nprint a"
print a.replace("@", quoted(a))

コードを変更したため、文字列を調整する必要があります。

a = "a = @\nprint a.replace(\"@\", quoted(a))"
print a.replace("@", quoted(a))

以上です!すべての言語のすべてのクインはそのように機能します (不正行為を除く)。

そうですね、プレースホルダーの最初の出現のみを置き換えるようにする必要があります。また、2 番目のプレースホルダーを使用すると、文字列を引用する必要がなくなります。

しかし、これらは小さな問題であり、簡単に解決できます。quoted()実際には、との実現はreplace() 、さまざまなクインが実際に異なる唯一の詳細です。


¹ プログラムにソース ファイルを読み込ませる

于 2008-09-20T01:01:52.530 に答える
9

クワインを書くには、いくつかの異なる戦略があります。明らかな方法は、コードを開いて出力するコードを書くことです。しかし、より興味深いものには、多くの言語での %s スタイルの printf 機能など、自己埋め込みを可能にする言語機能が含まれます。何かを埋め込む方法を見つけて、最終的に埋め込み要求に解決されるようにする必要があります。回文のように、多くの試行錯誤が必要だと思います。

于 2008-09-19T21:24:41.660 に答える
1

楽しみのために、Scheme で 1 つ思いつきました。これは、以前に発見されたことに気付くまでの約 5 分間、非常に誇りに思っていました。とにかく、Lisp のデータとコードの二重性をより適切にカウントするために、ゲームの「ルール」にわずかな変更があります: プログラムのソースを出力する代わりに、それ自体を返す S 式です:

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

ウィキペディアにあるものは同じ概念を持っていますが、引用のためのメカニズムが少し異なります (より冗長)。私の方が好きだけど。

于 2008-10-12T03:07:20.850 に答える
1

通常のアプローチ (ごまかすことができない場合*) は、そのソースを文字列定数にエンコードするものを記述し、その定数を 2 回出力します。1 回は文字列リテラルとして、もう 1 回はコードとして出力します。これは、「コードを 1 行書くたびに、それを出力するために別のコードを書かなければならない!」という問題を回避します。問題。

「不正行為」には以下が含まれます: - 解釈された言語を使用し、単にソースをロードして印刷する - C などの一部の言語で有効な 0 バイト長のファイル。

于 2008-09-19T21:25:42.767 に答える
0

ソースコードを実際に読んで印刷してみませんか?全然難しくありません!! これはphpの1つです:

<?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

これに興味のある人のために、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 に答える
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

エンコーディングと、何かに二重の意味を与える方法を考えて、それを使用して何かをいくつかの形式で出力できるようにするための 1 つのアイデア。プログラム出力自体以外のルールがなければ、空のプログラムが解決策であるため、このタイプの問題には制限があり、それを難し​​くするというキャバエもあります。

于 2008-09-19T21:27:08.253 に答える
-1

bashでは本当に簡単です

タッチテスト; chmod oug+x テスト; 。/テスト

空のファイル、空の出力

于 2020-10-30T13:05:33.243 に答える
-2

ルビーで:

puts File.read(_ _ FILE _ _)

于 2008-09-19T21:22:48.763 に答える