在quines,多語種quines,multi-quines中,你沒有什麼特別的,你的名字。他們都可以自動寫入。
舉例來說,C++中的bog標準,冗長,不雅,低效的奎因。但是,它有其缺點,很容易修改以實現我們想要的功能。
#include <iostream>
#include <string>
#include <cstdlib>
std::string show (const std::string& in) {
std::string res = "\"";
for (std::string::const_iterator it = in.begin(); it < in.end(); ++it) {
switch (*it) {
case '"':
case '\\':
res += '\\';
default:
res += *it;
}
}
res += "\"";
return res;
}
int main (int argc, char* argv[])
{
std::string arr[] = { // beginning ends here
"#include <iostream>",
"#include <string>",
"#include <cstdlib>",
"",
"std::string show (const std::string& in) {",
" std::string res = \"\\\"\";",
" for (std::string::const_iterator it = in.begin(); it < in.end(); ++it) {",
" switch (*it) {",
" case '\"':",
" case '\\\\':",
" res += '\\\\';",
" default:",
" res += *it;",
" }",
" }",
" res += \"\\\"\";",
" return res;",
"}",
"",
"int main (int argc, char* argv[])",
"{",
" std::string arr[] = { // beginning ends here",
"======",
" };",
" int n = argc == 1 ? 0 : std::atoi(argv[1]);",
" if (n == 0) {",
" int i, j;",
" for (i = 0; arr[i] != \"======\"; ++i) std::cout << arr[i] << std::endl;",
" for (j = 0; j < sizeof(arr)/sizeof(arr[0]); ++j) std::cout << show(arr[j]) << ',' << std::endl;",
" for (++i; i < sizeof(arr)/sizeof(arr[0]); ++i) std::cout << arr[i] << std::endl;",
" } else {",
" }",
"}",
};
int n = argc == 1 ? 0 : std::atoi(argv[1]);
if (n == 0) {
int i, j;
for (i = 0; arr[i] != "======"; ++i) std::cout << arr[i] << std::endl;
for (j = 0; j < sizeof(arr)/sizeof(arr[0]); ++j) std::cout << show(arr[j]) << ',' << std::endl;
for (++i; i < sizeof(arr)/sizeof(arr[0]); ++i) std::cout << arr[i] << std::endl;
} else {
}
}
正如你所看到的,程序的心臟是一個叫show
小函數,它接受一個字符串,並返回其表示爲C++的文字。整體結構如下:打印字符串數組的開始部分;打印通過show
傳送的整個陣列;打印數組的末尾部分。字符串數組是程序的副本,插入程序的中間。初始部分與最後部分分開,並且不會從程序中複製(僅打印一次,通過show
),該字符串爲"====="
。
很容易插入任何其他操作,例如用另一種語言打印另一個奎因。我爲這樣的行爲插入了佔位符。
現在,將它翻譯成任何編程語言(比如說FORTRAN)是絕對無足輕重的。假設我們已經完成了,它由線L1,L2,...,LN組成。我們將這些語句插入佔位符中:
std::cout << "L1" << std::endl;
std::cout << "L2" << std::endl;
...
std::cout << "LN" << std::endl;
我們相應地修改了字符串數組。 Voilà,我們有一個可以打印自己的quine,也可以是FORTRAN中的quine,具體取決於命令行參數。
好的,FORTRAN quine怎麼樣?它只能打印自己,而不是C++奎因。沒問題,讓我們將C++ quine複製回FORTRAN quine。
但是,C++奎因已經包含整個FORTRAN奎因,兩次?
沒問題,因爲FORTRAN quine已經可以自己打印。因此,我們只需要將原始的C++代碼複製回FORTRAN。無需再次(或兩次)在自身內部複製FORTRAN。
我們只需要稍微修改FORTRAN。當我們問FORTRAN蒯打印C++奎因,它應該打印所有的C++線也所有FORTRAN線,兩次:一次作爲Li
,一次爲std::cout << "Li" << std::endl;
,就像C++奎因它。然後我們得到C++奎因(包括FORTRAN奎因)。
我們還需要進行這些修改FORTRAN回C++(即,修改std::cout << "Li" << std::endl;
線)。這裏的修改浪潮將停止。
就是這樣,我們有兩個程序可以打印自己或每個其他,根據命令行參數。
我鼓勵你真正做了這一切。
得到這個答案的最好方法是去codegolf.SE,並要求人們嘗試寫一個multi-quine。設定的評價標準(像分鐘(S/N),N> = 2),其中s是碼大小,並等待答覆。 :) –
@Victor雖然這可能會得到一個解決方案,但我對醜陋,簡短,混淆的多重quines不感興趣。我不是在* *的解決方案,即使真的有興趣,而是,* *如何創建一個解決方案。這就是爲什麼我把這裏的問題,而不是codegolf,但我必須承認,我希望多一點的答案;) – Swadq