Đây là một trong số tôi đã viết sử dụng putchar
thay vì printf
; do đó nó phải xử lý tất cả các mã thoát riêng của nó. Nhưng nó là% 100 di động trên tất cả các bộ ký tự thực hiện C.
Bạn sẽ có thể thấy rằng có một đường may trong biểu diễn văn bản phản ánh một đường may trong chương trình văn bản riêng của mình, nơi mà nó thay đổi từ làm việc trên đầu đến làm việc ở cuối dòng. Bí quyết để viết một Quine là nhận được trên này "bướu", nơi bạn chuyển sang đào theo cách của bạn ra của lỗ! Các tùy chọn của bạn bị hạn chế bởi việc trình bày văn bản và các phương tiện đầu ra của ngôn ngữ.
#include <stdio.h>
void with(char *s) {
for (; *s; s++) switch (*s) {
case '\n': putchar('\\'); putchar('n'); break;
case '\\': putchar('\\'); putchar('\\'); break;
case '\"': putchar('\\'); putchar('\"'); break;
default: putchar(*s);
}
}
void out(char *s) { for (; *s; s++) putchar(*s); }
int main() {
char *a[] = {
"#include <stdio.h>\n\n",
"void with(char *s) {\n",
" for (; *s; s++) switch (*s) {\n",
" case '\\",
"n': putchar('\\\\'); putchar('n'); break;\n",
" case '\\\\': putchar('\\\\'); putchar('\\\\'); break;\n",
" case '\\\"': putchar('\\\\'); putchar('\\\"'); break;\n",
" default: putchar(*s);\n",
" }\n}\n",
"void out(char *s) { for (; *s; s++) putchar(*s); }\n",
"int main() {\n",
" char *a[] = {\n",
NULL }, *b[] = {
"NULL }, **p;\n",
" for (p = a; *p; p++) out(*p);\n",
" for (p = a; *p; p++) {\n",
" putchar('\\\"');\n",
" with(*p);\n",
" putchar('\\\"'); putchar(','); putchar('\\",
"n');\n",
" }\n",
" out(\"NULL }, *b[] = {\\",
"n\");\n",
" for (p = b; *p; p++) {\n",
" putchar('\\\"');\n",
" with(*p);\n",
" putchar('\\\"'); putchar(','); putchar('\\",
"n');\n",
" }\n",
" for (p = b; *p; p++) out(*p);\n",
" return 0;\n",
"}\n",
NULL }, **p;
for (p = a; *p; p++) out(*p);
for (p = a; *p; p++) {
putchar('\"');
with(*p);
putchar('\"'); putchar(','); putchar('\n');
}
out("NULL }, *b[] = {\n");
for (p = b; *p; p++) {
putchar('\"');
with(*p);
putchar('\"'); putchar(','); putchar('\n');
}
for (p = b; *p; p++) out(*p);
return 0;
}
Một thủ thuật phổ biến là nhảy bắt đầu các Quine bằng cách viết một chương trình để đọc một textfile và đầu ra một mảng các số. Sau đó, bạn sửa đổi nó để sử dụng một mảng tĩnh, và chạy chương trình đầu tiên chống lại chương trình mới (mảng tĩnh), tạo ra một mảng số đại diện cho chương trình. Chèn nó vào trong mảng tĩnh, chạy nó một lần nữa cho đến khi nó lắng xuống, và điều đó giúp bạn trở thành một quine. Nhưng, nó được gắn với một bộ ký tự cụ thể (== không phải 100% di động). Một chương trình như trên (và không phải là bản hack printf cổ điển) sẽ hoạt động tương tự trên ASCII hoặc EBCDIC (lỗi cổ điển printf không thành công trong EBCDIC vì nó chứa ASCII mã hoá cứng).
chỉnh sửa:
Đọc câu hỏi một lần nữa, cẩn thận (cuối cùng), dường như bạn đang thực sự tìm kiếm thêm triết lý kỹ thuật ít hơn. Bí quyết cho phép bạn thoát khỏi sự phục hồi vô hạn là hai-fer. Bạn phải có cả chương trình được mã hóa và chương trình được mở rộng ra khỏi cùng một dữ liệu: sử dụng cùng 2 cách dữ liệu. Do đó, dữ liệu này chỉ mô tả một phần của chương trình xung quanh biểu hiện tương lai của nó, khung . Hình ảnh trong khung này là bản sao thẳng của bản gốc.
Đây là cách bạn sẽ tự nhiên đi về sản xuất một bản vẽ đệ quy bằng tay: tv của một tv của tv. Tại một số điểm bạn cảm thấy mệt mỏi và chỉ phác thảo một số chói trên màn hình, bởi vì đệ quy đã được thiết lập đầy đủ.
chỉnh sửa:
Tôi đang tìm một lời giải thích tuyệt vời của lý do tại sao Quines là có thể.
"Khả năng" của Quine đi sâu vào các cuộc cách mạng toán học của thế kỷ 19 và 20. Các "cổ điển" Quine bởi WVO Quine, là chuỗi các từ (IIRC)
mang lại sai lầm khi nối vào bản thân
đó là một nghịch lý, giống như yêu cầu của David kiếm cái gì đó "khiến tôi hạnh phúc khi buồn, và làm cho tôi buồn khi hạnh phúc "trả lời bởi huy chương được ghi trên cả hai mặt:" điều này cũng sẽ vượt qua ".
Cùng loại knot đã được điều tra bởi những người tiên phong về logic toán học hiện đại như Frege, Russell và Whitehead, Łukasiewicz, và tất nhiên, con trai của chúng tôi Turing, Church và Thue. Bí quyết giúp có thể chuyển đổi Quine từ lĩnh vực wordplay sang một cuộc biểu tình có lập trình (không có phần nghịch lý trên đường đi), phương pháp của Gödel mã hóa các phép tính số học như số, vì vậy toàn bộ biểu thức toán học có thể được mã hóa thành một số nguyên (rất lớn). Đặc biệt, một hàm toán học thực hiện giải mã biểu diễn này có thể được biểu diễn dưới dạng (số) giống nhau. Số này (một hàm được mã hóa Gödel) là cả mã và dữ liệu.
Bộ ba điện này (Mã, Đại diện, Dữ liệu), có thể được chuyển đổi sang các lần lặp lại khác nhau. Bằng cách chọn một Đại diện khác (hoặc một chuỗi như: byte-> ASCII-> hệ thập lục phân-> số nguyên), làm thay đổi hành vi của Mã, làm thay đổi giao diện của Dữ liệu.
Làm thế nào đáng buồn, trang mà bạn đang đề cập đến (đó là bài thuyết trình Turing Award của Ken Thompson) đã bị gỡ xuống ngay sau khi tôi đọc nó: -/Cảm ơn trời tôi đã sao lưu ... – SasQ
@ SasQ Nó vẫn có sẵn cho tôi – paislee
Vâng, bây giờ nó cũng làm việc cho tôi. Ngày hôm đó tôi đã nhìn thấy một tin nhắn máy chủ mà đối tượng không được tìm thấy hoặc một cái gì đó như thế, vì vậy tôi nghĩ rằng họ đã loại bỏ nó. – SasQ