Взаимные негативные квины


22

Это было вдохновлено печатью негатива вашего кода и игрой в гольф .


Рассмотрим прямоугольник символов, который соответствует следующим ограничениям:

  1. Состоит исключительно из печатных символов ASCII
  2. Размеры больше 1
  3. Каждая строка и каждый столбец содержит хотя бы один пробел.
  4. Каждая строка и каждый столбец содержит хотя бы один непробельный символ.

Например, следующее является допустимым прямоугольником 6x4:

%n 2e 
1  g 3
 &* __
 3  

Отрицательный для этого прямоугольника определяются как прямоугольник равных размеров, причем все пространства заменяются некосмическими символами, и все без пробела заменены пробелами. Отрицательный знак вышеуказанного прямоугольника может быть:

  f  ^
 33 > 
9  $  
^ }|Q'

Любой непечатаемый ASCII-символ может быть использован для замены пробела.

задача

Ваша задача - написать программу с прямоугольным исходным кодом, который выводит действительный отрицательный знак для себя. Выведенный негатив должен также быть действительной программой на том же языке, что и оригинал, и он должен выводить источник оригинала.

Конечный пробел не может быть добавлен или удален, за исключением одного завершающего символа новой строки в конце любого вывода, что является необязательным.

Ни одна из программ не имеет права читать исходный код того или другого; также нельзя использовать среды REPL.

счет

Ваша оценка является продуктом измерений вашего кода (т. Е. Если ваш исходный код находится в прямоугольнике 12 на 25, ваша оценка равна 12 * 15 = 180). Кроме того, для каждого символа, используемого в комментарии, ваш счет увеличивается на 2 (если вы используете/* .. */ один раз в своем коде, а ваш код в прямоугольнике 10 на 10, ваша оценка будет 10 * 10 + 8 * 2 = 116).

Самый низкий балл побеждает.

При наличии связи выигрывает представление с наименьшим количеством пробелов в программе (либо оригинал, либо минус, в зависимости от того, сколько пробелов меньше).

Если все еще остается ничья, победит более ранний ответ.

Существует бонус -52% , если при объединении оригинала и негатива получается нормальная квинна. Например:

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

@Optimizer Вот почему я не сделал бонус обязательным.
es1024

1
Я говорю только об отрицательной взаимной части квин;)
Оптимизатор

@ MartinBüttner Ах, мой плохой. Я думал странным образом.
Оптимизатор

1
Кто-нибудь может сделать это в с? +1 тому, кто будет первым!
MegaTom

Ответы:


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

который является идеальным Quine!

Попробуйте их онлайн здесь


Как это работает

Вся логика печати находится в самой первой строке, которая обрабатывает все три случая, описанные ниже.

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

В этом случае вторая строка является запретной операцией в том, что касается вывода на печать.

Дело 2

                                         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элементов индекс 5является индексом 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 за единственную
заявку

Кажется, это не слишком далеко от бонуса.
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*}_`'"#)!*}_~                       

Непробельные символы в каждой строке остаются одинаковыми между двумя взаимными квинусами.

Но теперь действительно сладкая часть:

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

это Quine! :)

Проверьте это здесь.

Как это работает

Я рекомендую вам сначала прочитать объяснение о моем другом представлении, так как оно объясняет основы цитирования в CJam в целом.

Этот немного сложнее. Для взаимной квины, как и в другом случае, я изменяю строковое представление блока, добавляя пробелы до или после каждой строки и меняя 0 на 2, чтобы результирующая программа поместила пробелы в противоположный конец.

Обратите внимание, что пробелы вообще не влияют на взаимные квинусы. В первом они находятся в блоке, который на самом деле не используется, а во втором они находятся вокруг всего кода.

Чтобы получить обычную квинну при объединении обоих, нам нужно найти способ избежать всех этих модификаций. Обратите внимание, что структура пробела и кода означает, что, комбинируя оба, мы вставляем всю одну квинну в другую. Поэтому, если мы поместим весь код модификации в блок, мы можем запустить этот блок в зависимости от его фактического содержимого.

Итак, теперь у меня есть этот блок ... для взаимных квин, он содержит только код, который я на самом деле хочу запустить. Что касается объединенной квин, она также содержит всю квинну в произвольной позиции, что не имеет никакого смысла ... но, поскольку это блок, он не запускается автоматически. Таким образом, мы можем определить, следует ли изменять строку на основе содержимого этого блока. Вот для чего _`'"#)!. Он дублирует блок, преобразует его в строку, ищет символ "(который во взаимных квинах появляется только вне блока) - поиск возвращает, -1если символ не найден, и положительное целое число в противном случае - увеличивает результат и отрицает это логически. Таким образом, если "был найден, это дает в 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 х 10) * 48% = 57,6

Оказывается, этот код может быть легко разбит на несколько строк с некоторыми изменениями. Мы добавляем 2 символа, чтобы получить 48 строк, которые затем удобно разделить на 8, чтобы у нас было 8 строк с 6 символами кода и 6 пробелами. Для этого нам также необходимо изменить несколько чисел и переставить оператор или два, чтобы они не разбивались на обе строки. Это дает нам рабочую версию с размером 12 х 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*      
      }_`'"#
)!*}_~      

(Примечание: нет необходимости чередовать левую и правую череду на промежуточных строках, важна только позиция первой и последней строчек. Левая и правая стороны могут быть выбраны произвольно для всех остальных строк.)

И по чистой случайности, полный quine также все еще работает:

{`"_~"{`"_~"
+{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, но все равно это работает нормально.)

При этом, я мог бы просто добавить 44 строки 1;в мою первоначальную заявку, чтобы выполнить требование о вознаграждении, но 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;)
Оптимизатор

Разве это не должно быть Y/2в комбинированной квине?
Schnaader

"И по чистой случайности" нах;)
Timtech

@Timtech Смотрите мои изменения. Чистое совпадение не было преуменьшением. ^^
Мартин Эндер

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:

{"_~"}_~

Скобки просто определяют блок кода, например функцию, которая не выполняется немедленно. Если в стеке остается неисполненный блок, печатается его исходный код (включая фигурные скобки). _дублирует блок и ~выполняет вторую копию. Сам блок просто выталкивает строку, содержащую _~. Таким образом, этот код оставляет стек в следующем состоянии:

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

Блок и строка просто печатаются вплотную в конце программы, что делает это квинной.

Прелесть этого в том, что мы можем делать в блоке все, что захотим, и это остается квинной, потому что каждый фрагмент кода будет автоматически печататься в содержимом блока. Мы также можем изменить блок, получив его строковое представление с помощью `(который является просто строкой блока с фигурными скобками).

Теперь давайте посмотрим на это решение. Обратите внимание, что любая часть взаимной квине содержит квиноподобный блок с_~ , и an 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, где в коде выше есть пробел. Подвох в том, что порядок этих двух строк определяется обменом внутри { }*. И поскольку внешняя часть взаимной квайны имеет 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 >возвращает 1, потому что 32> 10, и ' \n' >возвращает 0, потому что два пробела равны.


Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.