相互负的奎因


22

这是受“ 打印代码否定”和“打高尔夫球”的共同启发的。


考虑一个满足以下限制的矩形字符:

  1. 仅由可打印的ASCII字符组成
  2. 尺寸均大于1
  3. 每一行每一列至少包含一个空格。
  4. 每一行和每一列至少包含一个非空格字符。

例如,以下是有效的6x4矩形:

%n 2e 
1  g 3
 &* __
 3  

此矩形的负数定义为等长的矩形,所有空格均由非空格字符替换,所有非空格字符均由空格替换。上面矩形的负数可以是:

  f  ^
 33 > 
9  $  
^ }|Q'

任何不可空格打印的ASCII字符都可以用来替换空格。

任务

您的任务是编写一个带有矩形源代码的程序,该程序向自身输出有效的否定值。输出的负数也必须是与原始语言相同的有效程序,并且必须输出原始的源。

除了在任一输出末尾的单个尾随换行符(可选)外,不得添加或删除尾随空格。

任何程序都不允许读取其中任何一个的源代码;也不能假设为REPL环境。

计分

您的分数是代码尺寸的乘积(即,如果源代码在12 x 25的矩形中,则分数为12 * 15 = 180)。此外,对于注释中使用的每个字符,您的得分将增加2(如果您/* .. */在代码中使用一次,并且您的代码位于10 x 10的矩形中,则得分将为10 * 10 + 8 * 2 = 116)。

最低分获胜。

如果存在平局,则程序中空格最少的提交(原始空格或否定空格较小的提交)将获胜。

如果仍然平局,则较早的答案为准。

如果将原图和底图组合在一起产生正常的藜麦,则有-52%的奖金。例如:

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

@Optimizer这就是我没有强制执行奖金的原因。
es1024

1
我在说的只是负的相互奎因部分;)
Optimizer

@MartinBüttner啊,我不好。我在用奇怪的字眼思考。
Optimizer

1
谁能在c中做到这一点?+1谁先谁!
MegaTom,2014年

Answers:


15

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

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

运行上面的代码将给出以下输出:

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

运行,打印回原始源。

源和输出只是交换线。

现在来了魔术。

将源和输出结果重叠成以下代码:

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

这是一个完美的奎因!

在这里在线尝试


怎么运行的

所有打印逻辑都在第一行本身中,该行可以处理稍后说明的所有三种情况。

{])"_~"+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";

上面最后一行中的数组是具有对应于所有三种情况的代码块的数组。

情况1

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

在这种情况下,剩余的堆栈长度为0,因为执行该块时,它仅具有该块本身的副本,该副本最初在上述第三步中弹出。因此,我们0从最后一个数组中取出索引并执行它:

 {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";

在这种情况下,就打印输出而言,第二行是无操作的。

情况二

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

在这种情况下,堆栈已经包含一个空字符串,因此在执行复制的代码块时,它具有2个元素-空字符串和代码块本身。因此,我们1从最后一个数组中取出索引并执行它:

{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";

情况3

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

在这种情况下,堆栈具有6个元素。因此,在弹出最后一个代码块后,剩余的数组长度为5。我们从数组中取出索引5并执行它。(请注意,在3元素数组中,index 5为index 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

Python,97x2 + 2 = 196

首先,这不是一个很好的解决方案,但至少可以奏效(我认为)。

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

输出:

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

8
+1是迄今为止唯一使用真实语言的内容
WinnieNicklaus 2014年

似乎离奖金也不算太远。
mbomb007

23

CJam(58 56 54 48 46 x 2)* 48%= 44.16

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

哪个打印

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

每行中的非空格字符在两个互为quines之间保持相同。

但是现在最甜蜜的部分是:

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

是一个藜!:)

在这里测试。

怎么运行的

我建议您先阅读我的其他文章中的解释,因为它通常解释了CJam中的奎因的基本知识。

这个有点棘手。与其他情况一样,对于互为quine,我通过在每行之前或之后添加空格,并将0替换为2,来修改块的字符串表示形式,以便最终程序将空格放在另一端。

请注意,空格根本不会影响相互的奎因。在第一个中,它们位于一个未使用的块中,在第二个中,它们位于整个代码中。

为了在组合两者时获得规则的拉皮,我们需要找到一种避免进行所有修改的方法。注意,空格和代码的结构意味着通过将两者结合在一起,我们可以将一个quine的全部插入另一个。因此,如果将整个修改代码放在一个块中,则可以根据其实际内容运行该块。

所以现在我有了这个代码块……对于相互的奎因,它只包含我实际要运行的代码。对于组合的奎因,它还以随机位置再次包含整个奎因,这没有任何意义……但是由于它是一个块,因此不会自动运行。因此,我们可以基于该块的内容来确定是否修改字符串。那_`'"#)!是为了什么 它复制该块,将其转换为字符串,搜索字符"(在互为quine中,仅出现在块外部)- -1如果找不到字符,则搜索返回,否则返回正整数-,增加结果并在逻辑上将其否定。因此,如果"找到a ,0它将产生1。现在我们要做*,如果结果为1,则一次执行该块,否则完全不执行。

最后,这是修改代码的工作方式:

_,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.";

领取赏金(12 x 10)* 48%= 57.6

事实证明,通过一些修改,该代码可以很容易地拆分为更多行。我们添加2个字符,以连续获得48个字符,然后可以方便地将其除以8,这样我们就有8行包含6个字符的代码和6个空格。为此,我们还需要更改一些数字,并重新排列一个或两个运算符,以使它们不会在两条线上都分开。这样就给我们提供了一个12 x 8大小的工作版本...比要求少一个。因此,我们只添加了两行不做任何事情(按1,按1,按1,按1 ...,所以变成12 x 10

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

作为前一个,这产生了

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

(附带说明:无需在中间行上保持左右交替,只有第一行和最后一行的位置很重要。对于其他所有行,可以任意选择左右。)

而且,通过纯粹的巧合,完整的藜也仍然有效:

{`"_~"{`"_~"
+{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*
}_`'"#}_`'"#      
)!*}_~)!*}_~

(我说的是巧合,因为负责执行内部代码的部分现在被奇怪地散布在另一个quine中,但仍然可以正常工作。)

话虽如此,我本可以在1;原始提交的内容中添加44行来满足赏金要求,但12 x 10看起来却更加整洁。;)

编辑:哈哈,当我说“纯粹的巧合”时,我再也没有出现过。我研究了最后的奎因现在是如何工作的,这绝对是荒谬的。有三个嵌套块(实际上是4个,但是最里面的块是不相关的)。这3个块中最里面的唯一重要部分是它包含一个"(而不是它在原始提交中所做的一个,而是'"结尾处用于检查该相同字符的那个)。因此,该藜麦的基本结构为:

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

我们来剖析一下:

{`"_~"                               }_~ "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.";

因此,确实确实做了一些有趣的魔术,但是由于内部块在堆栈上留下了一个字符串,因此)!*碰巧将其变成了一个空字符串。唯一的条件是,内部块+中的内容对堆栈没有任何其他作用,因此让我们看一下:

             {___'"___}                  "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;)
Optimizer

它不应该Y/2放在组合的麦片中吗?
schnaader 2014年

“而且纯属巧合”罗;)
Timtech

@Timtech参见我的编辑。纯粹的巧合并不是轻描淡写。^^
Martin Ender 2014年

10

CJam,42 37 33 x 2 = 66

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

哪个打印

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

(这些线被交换,并1变成一个0。)

在这里测试。

怎么运行的

首先,您应该了解基本的CJam quine:

{"_~"}_~

花括号只是定义了不会立即执行的代码块(例如函数)。如果未执行的块保留在堆栈中,则会打印其源代码(包括大括号)。_复制该块,并~执行第二个副本。块本身只是简单地推送包含的字符串_~。因此,此代码使堆栈处于以下状态:

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

只需在程序结束时以背对背的方式打印块和字符串,这便成为了一个包装。

这样做的好处是我们可以在块中做任何我们想做的事情,而且它仍然是一个难题,因为每段代码都会自动打印在块内容中。我们还可以通过获取块的字符串表示形式来修改块`(这只是带括号的块的字符串)。

现在让我们看一下这个解决方案。请注意,互为quine的任一部分都包含带有_~和的quine-like块L。所述L推压空字符串压入堆栈,这无助于所述输出。所以这是该块的作用:

`                             "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.";

因此,这将完成quine部分,但将1替换为0,并且还将在另一行之前添加L,其中上面的代码具有空格。要注意的是,这两行的顺序是由内部交换确定的{ }*。并且由于互用quine的外部将其0前面的替换为a 1,所以它从不执行此交换,因此再次产生原始顺序。


5

CJam,27×2 = 54

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

输出:

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

'A'B>比较字符A和B。' '\n >因为32> 10返回1,并且' \n' >因为两个空格相等而返回0。


2

CJam,30 29 x 2 = 58

{"_~"SN]_,4=S28*'R+\{N@}*}_~ 
                            R

输出:

                            R
{"_~"SN]_,4=S28*'R+\{N@}*}_~ 

输出原始源。

这是基于与其他解决方案相同的原理。

在这里在线尝试

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.