Quines phủ định lẫn nhau


22

Điều này được lấy cảm hứng từ In một phủ định của Mã của bạnGolf một câu hỏi chung .


Hãy xem xét một hình chữ nhật của các ký tự, đáp ứng các hạn chế sau:

  1. Chỉ bao gồm các ký tự ASCII có thể in
  2. Kích thước cả lớn hơn 1
  3. Mỗi hàng và mỗi cột chứa ít nhất một khoảng trắng.
  4. Mỗi hàng và mỗi cột chứa ít nhất một ký tự không phải khoảng trắng.

Ví dụ: dưới đây là hình chữ nhật 6x4 hợp lệ:

%n 2e 
1  g 3
 &* __
 3  

Một âm cho hình chữ nhật này được định nghĩa là một hình chữ nhật có kích thước bằng nhau, với tất cả các khoảng trắng được thay thế bằng các ký tự không phải khoảng trắng và tất cả các ký tự không phải khoảng trắng được thay thế bằng khoảng trắng. Một tiêu cực của hình chữ nhật trên có thể là:

  f  ^
 33 > 
9  $  
^ }|Q'

Bất kỳ ký tự ASCII không thể in không gian có thể được sử dụng để thay thế một khoảng trắng.

Bài tập

Nhiệm vụ của bạn là viết một chương trình với mã nguồn hình chữ nhật, tạo ra âm bản hợp lệ cho chính nó. Đầu ra tiêu cực cũng phải là một chương trình hợp lệ, cùng ngôn ngữ với bản gốc và nó phải xuất nguồn gốc của bản gốc.

Không có khoảng trắng theo dõi nào có thể được thêm hoặc xóa, ngoại trừ một dòng mới duy nhất ở cuối một trong hai đầu ra, là tùy chọn.

Không chương trình nào được phép đọc mã nguồn của một trong hai; cũng không thể giả sử môi trường REPL.

Chấm điểm

Điểm của bạn là sản phẩm của các kích thước của mã của bạn (nghĩa là nếu mã nguồn của bạn nằm trong hình chữ nhật 12 x 25, điểm của bạn là 12 * 15 = 180). Ngoài ra, với mỗi ký tự được sử dụng trong một nhận xét, điểm của bạn tăng thêm 2 (Nếu bạn sử dụng /* .. */một lần trong mã của mình và mã của bạn nằm trong hình chữ nhật 10 x 10, điểm của bạn sẽ là 10 * 10 + 8 * 2 = 116).

Điểm thấp nhất sẽ thắng.

Nếu có một ràng buộc, bài nộp có số lượng khoảng trống ít nhất trong chương trình (bản gốc hoặc phần âm, phần nào có ít khoảng trắng hơn) sẽ thắng.

Nếu vẫn còn một ràng buộc, câu trả lời trước đó sẽ giành chiến thắng.

Có một phần thưởng là -52% , nếu kết hợp cả bản gốc và bản âm với nhau sẽ tạo ra một quine bình thường. Ví dụ:

Original   Negative   Combined
 A A       B B        BABA
A A         B B       ABAB

@Optimizer Đó là lý do tôi không bắt buộc tiền thưởng.
es1024

1
Tôi đang nói về chỉ phần tiêu cực lẫn nhau tiêu cực;)
Trình tối ưu hóa

@ MartinBüttner Ah, xấu của tôi. Tôi đã suy nghĩ trong điều khoản kỳ lạ.
Tối ưu hóa

1
Bất cứ ai có thể làm điều này trong c? +1 cho bất cứ ai sẽ đầu tiên!
MegaTom

Câu trả lời:


15

CJam, ( 51 49 47 46 45 42 x 2) * 48% = 40,32

{])"_~"+S41*'R+@,[{N@S}{SN@}{W=N]_}]=~}_~ 
                                         R

Chạy mã trên cho đầu ra này:

                                         R
{])"_~"+S41*'R+@,[{N@S}{SN@}{W=N]_}]=~}_~ 

chạy mà, in lại nguồn gốc.

Nguồn và đầu ra chỉ đơn giản là các dòng hoán đổi.

Bây giờ đến phép thuật.

Chồng chéo nguồn và kết quả đầu ra vào mã sau:

{])"_~"+S41*'R+@,[{N@S}{SN@}{W=N]_}]=~}_~R
{])"_~"+S41*'R+@,[{N@S}{SN@}{W=N]_}]=~}_~R

đó là một quine hoàn hảo!

Hãy thử chúng trực tuyến tại đây


Làm thế nào nó hoạt động

Tất cả logic in nằm trong chính dòng đầu tiên xử lý cả ba trường hợp được giải thích sau.

{])"_~"+S41*'R+@,[{N@S}{SN@}{W=N]_}]=~}_~
{                                     }_~   "Copy this code block and execute the copy";
 ]                                          "Wrap everything before it in array";
  )                                         "Pop the last element out of it";
   "_~"+                                    "Append string '_~' to the copied code block";
        S41*                                "Create a string of 41 spaces";
            'R+                             "Append character R to it";
               @,                           "Rotate the array to top and get its length";
                 [{   }{   }{     }]=~      "Get the corresponding element from this"
                                            "array and execute it";

Mảng trong dòng cuối cùng ở trên là mảng có các khối mã tương ứng với cả ba trường hợp.

Trường hợp 1

{])"_~"+S41*'R+@,[{N@S}{SN@}{W=N]_}]=~}_~ 
                                         R

Trong trường hợp này, độ dài của ngăn xếp còn lại là 0 như khi khối được thực thi, nó chỉ có bản sao của khối, ban đầu được bật ra trong bước thứ ba ở trên. Vì vậy, chúng tôi lấy chỉ mục 0ra khỏi mảng cuối cùng và thực hiện nó:

 {N@S}          "Note that at this point, the stack is something like:"
                "[[<code block that was copied> '_ '~ ] <41 spaces and R string>]";
  N             "Add newline to stack";
   @            "Rotate the code block to top of stack";
    S           "Put a trailing space which negates the original R";

Trong trường hợp này, dòng thứ hai là không có liên quan đến in ấn liên quan đến đầu ra.

Trường hợp 2

                                         R
{])"_~"+S41*'R+@,[{N@S}{SN@}{W=N]_}]=~}_~ 

Trong trường hợp này, ngăn xếp đã chứa một chuỗi rỗng, vì vậy khi khối mã được sao chép được thực thi, nó có 2 phần tử - một chuỗi rỗng và chính khối mã. Vì vậy, chúng tôi lấy chỉ mục 1ra khỏi mảng cuối cùng và thực hiện nó:

{SN@}            "Note at this point, the stack is same as in case 1";
 SN              "Push space and newline to stack";
   @             "Rotate last three elements to bring the 41 spaces and R string to top";

Trường hợp 3

{])"_~"+S41*'R+@,[{N@S}{SN@}{W=N]_}]=~}_~R
{])"_~"+S41*'R+@,[{N@S}{SN@}{W=N]_}]=~}_~R

Trong trường hợp này, ngăn xếp có 6 phần tử. Vì vậy, sau khi xuất hiện khối mã cuối cùng, độ dài mảng còn lại là 5. Chúng tôi lấy chỉ mục 5ra khỏi mảng và thực hiện nó. (Lưu ý rằng trong một mảng các 3phần tử, chỉ mục 5là chỉ mục 5%3 = 2)

{W=N]_}          "Note at this point, the stack is same as in case 1";
 W=              "Take the last character out of the 41 spaces and R string, i.e. R";
   N]            "Add a new line to stack and wrap the stack in an array";
     _           "Copy the array to get back the source of Case 3 itself";

27

Con trăn, 97x2 + 2 = 196

Không phải là một giải pháp tuyệt vời để bắt đầu, nhưng ít nhất nó hoạt động (tôi nghĩ).

c='o=1-%d;print("%%97s\\n%%97s"%%("#","c=%%r;exec(c%%%%%%d)\\40"%%(c,o),"#")[o:][:2])';exec(c%1) 
                                                                                                #

Đầu ra:

                                                                                                #
c='o=1-%d;print("%%97s\\n%%97s"%%("#","c=%%r;exec(c%%%%%%d)\\40"%%(c,o),"#")[o:][:2])';exec(c%0) 

8
+1 cho lần gửi duy nhất cho đến nay để sử dụng ngôn ngữ thực
WinnieNicklaus

Nó dường như không quá xa so với tiền thưởng.
mbomb007

23

CJam, ( 58 56 54 48 46 x 2) * 48% = 44,16

{`"_~"+{_,94\m2/S*a_+\*                       
                       N/23f/Wf%N*}_`'"#)!*}_~

mà in

                       {`"_~"+{_,94\m2/S*a_+\*
N/23f/Wf%N*}_`'"#)!*}_~                       

Các ký tự không phải khoảng trắng trong mỗi dòng vẫn giữ nguyên giữa hai dòng tương hỗ.

Nhưng bây giờ là phần thực sự ngọt ngào:

{`"_~"+{_,94\m2/S*a_+\*{`"_~"+{_,94\m2/S*a_+\*
N/23f/Wf%N*}_`'"#)!*}_~N/23f/Wf%N*}_`'"#)!*}_~

là một quine! :)

Kiểm tra nó ở đây.

Làm thế nào nó hoạt động

Tôi khuyên bạn nên đọc phần giải thích về bài nộp khác của tôi trước, vì nó giải thích những điều cơ bản của việc khai thác ở CJam nói chung.

Đây là một chút phức tạp hơn. Đối với quine lẫn nhau, như trong trường hợp khác, tôi sửa đổi biểu diễn chuỗi của khối bằng cách thêm khoảng trắng trước hoặc sau mỗi dòng và hoán đổi 0 bằng 2, để chương trình kết quả đặt khoảng trắng ở đầu đối diện.

Lưu ý rằng các không gian không ảnh hưởng đến các hạn chế lẫn nhau. Trong phần đầu tiên, chúng nằm trong một khối, không thực sự được sử dụng và trong phần thứ hai, chúng nằm xung quanh toàn bộ mã.

Để có được một câu hỏi thường xuyên khi kết hợp cả hai, chúng ta cần tìm cách tránh thực hiện tất cả các sửa đổi đó. Lưu ý rằng cấu trúc của khoảng trắng và mã có nghĩa là bằng cách kết hợp cả hai, chúng ta chèn toàn bộ một quine vào cái kia. Vì vậy, nếu chúng ta đặt toàn bộ mã sửa đổi trong một khối, chúng ta có thể chạy khối đó tùy thuộc vào nội dung thực tế của nó.

Vì vậy, bây giờ tôi đã có khối này ... cho các quines lẫn nhau, nó chỉ chứa mã tôi thực sự muốn chạy. Đối với quine kết hợp, nó cũng chứa toàn bộ quine một lần nữa, ở một vị trí ngẫu nhiên, không có ý nghĩa gì cả ... nhưng vì nó là một khối, nên nó không tự động chạy. Vì vậy, chúng tôi có thể xác định xem có nên sửa đổi chuỗi dựa trên nội dung của khối đó hay không. Đó là những gì _`'"#)!dành cho. Nó sao chép khối, chuyển đổi nó thành một chuỗi, tìm kiếm ký tự "(trong các quine lẫn nhau, chỉ xuất hiện bên ngoài khối) - tìm kiếm trả về -1nếu không tìm thấy ký tự và một số nguyên dương -, làm tăng kết quả và phủ nhận nó một cách hợp lý. Vì vậy, nếu một "đã được tìm thấy năng suất này 0nếu không nó mang lại1 . Bây giờ chúng ta chỉ cần làm*, thực thi khối một lần, nếu kết quả là 1 và hoàn toàn không.

Cuối cùng, đây là cách mã sửa đổi hoạt động:

_,94\m2/S*a_+\*N/23f/Wf%N*
_,                         "Duplicate the quine string and get its length.";
  94\m                     "Subtract from 94.";
      2/                   "Divide by two.";
        S*                 "Create a string with that many spaces. This will be
                            an empty string for the first mutual quine, and contain
                            23 spaces for the second mutual quine.";
          a_+              "Create an array that contains this string twice.";
             \*            "Join the two copies together with the quine string.";
               N/          "Split into lines.";
                 23f/      "Split each line into halves (23 bytes each).";
                     Wf%   "Reverse the two halves of each line.";
                        N* "Join with a newline.";

Yêu cầu tiền thưởng, (12 x 10) * 48% = 57,6

Hóa ra mã này có thể được chia thành nhiều dòng rất dễ dàng với một số sửa đổi. Chúng tôi thêm 2 ký tự, để có 48 ký tự liên tiếp, sau đó chúng tôi có thể phân chia thuận tiện cho 8, để chúng tôi có 8 dòng với 6 ký tự mã và 6 khoảng trắng. Để làm điều đó, chúng ta cũng cần thay đổi một vài số và sắp xếp lại một hoặc hai toán tử để chúng không bị tách ra trên cả hai dòng. Điều đó mang lại cho chúng tôi một phiên bản hoạt động với kích thước 12 x 8 ... một yêu cầu. Vì vậy, chúng tôi chỉ cần thêm hai dòng không làm gì cả (đẩy 1, bật 1, đẩy 1, bật 1 ...), do đó, hãy đến 12 x 10 :

{`"_~"      
      +{129X
$,m2/S      
      *a_+\*
N/6f/1      
      ;1;1;1
;1;1;1      
      ;Wf%N*
}_`'"#      
      )!*}_~

Như cái trước, cái này tạo ra

      {`"_~"
+{129X      
      $,m2/S
*a_+\*      
      N/6f/1
;1;1;1      
      ;1;1;1
;Wf%N*      
      }_`'"#
)!*}_~      

(Lưu ý bên: không cần phải xen kẽ trái và phải trên các đường trung gian, chỉ có vị trí của dòng đầu tiên và cuối cùng là quan trọng. Có thể chọn tùy ý trái và phải cho tất cả các dòng khác.)

Và thông qua sự trùng hợp hoàn toàn, quine đầy đủ cũng vẫn hoạt động:

{`"_~"{`"_~"
+{129X+{129X
$,m2/S$,m2/S
*a_+\**a_+\*
N/6f/1N/6f/1
;1;1;1;1;1;1
;1;1;1;1;1;1
;Wf%N*;Wf%N*
}_`'"#}_`'"#      
)!*}_~)!*}_~

(Tôi nói sự trùng hợp, bởi vì phần quan tâm đến việc không thực thi mã bên trong bây giờ bị xen kẽ một cách kỳ lạ với các câu hỏi khác, nhưng nó vẫn hoạt động tốt.)

Điều đó đang được nói, tôi có thể chỉ cần thêm 44 dòng 1;vào bản gốc của mình để đáp ứng yêu cầu tiền thưởng, nhưng 12 x 10trông gọn gàng hơn nhiều. ;)

Chỉnh sửa: Haha, khi tôi nói "sự trùng hợp thuần túy", tôi không thể chú ý nhiều hơn. Tôi đã xem xét cách thức hoạt động cuối cùng thực sự hoạt động, và nó hoàn toàn vô lý. Có ba khối lồng nhau (4 khối thực sự, nhưng trong cùng là không liên quan). Phần quan trọng duy nhất trong cùng của 3 khối đó là nó chứa một "(và không phải là khối mà nó đã làm trong bản đệ trình ban đầu, nhưng phần '"cuối được sử dụng để kiểm tra cùng ký tự này). Vì vậy, cấu trúc cơ bản của quine là:

{`"_~"{`"_~"+{___'"___}_`'"#)!*}_~)!*}_~

Hãy mổ xẻ rằng:

{`"_~"                               }_~ "The standard CJam quine.";
      {`"_~"+                  }_~       "Another CJam quine. Provided it doesn't do 
                                          anything in the rest of that block, this 
                                          will leave this inner block as a string on 
                                          the stack.";
                                  )      "Slice the last character off the string.";
                                   !     "Negate... this yields 0.";
                                    *    "Repeat the string zero times.";

Vì vậy, điều này thực sự làm một số phép thuật vui nhộn, nhưng vì khối bên trong để lại một chuỗi duy nhất trên ngăn xếp, )!*tình cờ biến nó thành một chuỗi trống. Điều kiện duy nhất là các công cụ trong khối bên trong sau +đó không làm gì khác với ngăn xếp, vì vậy hãy xem xét điều đó:

             {___'"___}                  "Push a block which happens to contain 
                                          quotes.";
                       _`'"#)!*          "This is from the original code and just 
                                          removes the block if it does contain 
                                          quotes.";

4
TLDR; upvote;)
Trình tối ưu hóa

Không nên Y/2trong quine kết hợp?
schnaader

"Và thông qua sự trùng hợp thuần túy" nah;)
Timtech

@Timtech Xem chỉnh sửa của tôi. Sự trùng hợp thuần túy không phải là một cách nói nhẹ nhàng. ^^
Martin Ender

10

Camam, 42 37 33 x 2 = 66

{`As_W%er"_~"+S 33*F'Lt1{\}*N\}_~
               L                 

mà in

               L                 
{`As_W%er"_~"+S 33*F'Lt0{\}*N\}_~

(Các dòng được hoán đổi và 1biến thành a 0.)

Kiểm tra nó ở đây.

Làm thế nào nó hoạt động

Trước tiên, bạn nên hiểu về câu hỏi cơ bản của CJam:

{"_~"}_~

Các dấu ngoặc chỉ định nghĩa một khối mã, giống như một hàm, không được thực thi ngay lập tức. Nếu một khối chưa được thực hiện vẫn còn trên ngăn xếp, mã nguồn của nó (bao gồm cả dấu ngoặc nhọn) sẽ được in. _nhân đôi khối và ~thực hiện bản sao thứ hai. Các khối chỉ đơn giản là đẩy chuỗi chứa _~. Vì vậy, mã này, để lại ngăn xếp trong trạng thái sau:

Stack: [{"_~"} "_~"]

Khối và chuỗi được in đơn giản là back-to-back ở cuối chương trình, điều này làm cho điều này trở thành một vấn đề.

Cái hay của việc này là chúng ta có thể làm bất cứ điều gì chúng ta muốn trong khối và nó vẫn là một nguyên tắc, bởi vì mỗi đoạn mã sẽ tự động được in trong nội dung của khối. Chúng ta cũng có thể sửa đổi khối, bằng cách lấy biểu diễn chuỗi của nó bằng `(chỉ là một chuỗi của khối có dấu ngoặc).

Bây giờ hãy xem xét giải pháp này. Lưu ý rằng một phần của quine lẫn nhau chứa khối giống như quine với _~và an L. Việc Lđẩy một chuỗi trống lên ngăn xếp, không đóng góp vào đầu ra. Vì vậy, đây là những gì khối làm:

`                             "Convert block to its string representation.";
 As                           "Push 10 and convert to string.";
   _W%                        "Duplicate and reverse, to get another string 01.";
      er                      "Swap 0s and 1s in the block string.";
        "_~"+                 "Append _~.";
             S 33*            "Push a string with 33 spaces.";
                  F'Lt        "Set the character at index 15 to L.";
                      1{ }*   "Repeat this block once.";
                        \     "Swap the code string and the space string.";
                           N\ "Push a newline and move it between the two lines.";

Vì vậy, điều này sẽ thực hiện phần quine, nhưng đổi 1 thành 0 và nó cũng sẽ thêm một dòng khác với một L, trong đó đoạn mã ở trên có một khoảng trắng. Điều đáng chú ý là thứ tự của hai dòng đó được xác định bằng cách hoán đổi bên trong { }*. Và bởi vì phần bên ngoài của quine lẫn nhau có 0mặt trước được thay thế bằng a 1, nó không bao giờ thực hiện việc hoán đổi này, và do đó tạo ra thứ tự ban đầu một lần nữa.


5

CJam, 27 × 2 = 54

{ ` " _ ~ " + N - ) 2 * ' '
 > @ t s G B + / N * } _ ~ 

Đầu ra:

 { ` " _ ~ " + N - ) 2 * ' 
' > @ t s G B + / N * } _ ~

'A'B>so sánh các ký tự A và B. ' '\n >trả về 1 vì 32> 10 và ' \n' >trả về 0 vì hai khoảng trắng bằng nhau.


Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.