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