APL (158 символов, оценка = 4)
'''{(((3+z)×^/⍵)-5+2×+/+/¨⍺=0)⌽(2×77+z)⍴(77+z←2×+/0=⊃,/⍺,⍵)⍴⊃,/(~^/¨⍺=0)/⍺}1 0 '''{(((3+z)×^/⍵)-5+2×+/+/¨⍺=0)⌽(2×77+z)⍴(77+z←2×+/0=⊃,/⍺,⍵)⍴⊃,/(~^/¨⍺=0)/⍺}1 0
Я использую Dyalog APL здесь. Количество циклов можно увеличить на один, добавив 0 (0 с последующим пробелом) в конец выражения и в конец строки (перед '''). Длина цикла равна (# 0's) + 1, а длина выражения равна 150 + 4*(cycle length)). Предположим , что мы продолжаем добавлять нули навсегда, счет Limit[(150 + 4*n)/(n - 1), n -> Infinity] = 4, где nдлина цикла.
Вот пример с длиной цикла = 6:
'''{(((3+z)×^/⍵)-5+2×+/+/¨⍺=0)⌽(2×77+z)⍴(77+z←2×+/0=⊃,/⍺,⍵)⍴⊃,/(~^/¨⍺=0)/⍺}1 0 0 0 0 0 '''{(((3+z)×^/⍵)-5+2×+/+/¨⍺=0)⌽(2×77+z)⍴(77+z←2×+/0=⊃,/⍺,⍵)⍴⊃,/(~^/¨⍺=0)/⍺}1 0 0 0 0 0
0 '''{(((3+z)×^/⍵)-5+2×+/+/¨⍺=0)⌽(2×77+z)⍴(77+z←2×+/0=⊃,/⍺,⍵)⍴⊃,/(~^/¨⍺=0)/⍺}1 0 0 0 0 0 '''{(((3+z)×^/⍵)-5+2×+/+/¨⍺=0)⌽(2×77+z)⍴(77+z←2×+/0=⊃,/⍺,⍵)⍴⊃,/(~^/¨⍺=0)/⍺}1 0 0 0 0
0 '''{(((3+z)×^/⍵)-5+2×+/+/¨⍺=0)⌽(2×77+z)⍴(77+z←2×+/0=⊃,/⍺,⍵)⍴⊃,/(~^/¨⍺=0)/⍺}1 0 0 0 0 0 '''{(((3+z)×^/⍵)-5+2×+/+/¨⍺=0)⌽(2×77+z)⍴(77+z←2×+/0=⊃,/⍺,⍵)⍴⊃,/(~^/¨⍺=0)/⍺}1 0 0 0 0
0 0 '''{(((3+z)×^/⍵)-5+2×+/+/¨⍺=0)⌽(2×77+z)⍴(77+z←2×+/0=⊃,/⍺,⍵)⍴⊃,/(~^/¨⍺=0)/⍺}1 0 0 0 0 0 '''{(((3+z)×^/⍵)-5+2×+/+/¨⍺=0)⌽(2×77+z)⍴(77+z←2×+/0=⊃,/⍺,⍵)⍴⊃,/(~^/¨⍺=0)/⍺}1 0 0 0
0 0 '''{(((3+z)×^/⍵)-5+2×+/+/¨⍺=0)⌽(2×77+z)⍴(77+z←2×+/0=⊃,/⍺,⍵)⍴⊃,/(~^/¨⍺=0)/⍺}1 0 0 0 0 0 '''{(((3+z)×^/⍵)-5+2×+/+/¨⍺=0)⌽(2×77+z)⍴(77+z←2×+/0=⊃,/⍺,⍵)⍴⊃,/(~^/¨⍺=0)/⍺}1 0 0 0
0 0 0 '''{(((3+z)×^/⍵)-5+2×+/+/¨⍺=0)⌽(2×77+z)⍴(77+z←2×+/0=⊃,/⍺,⍵)⍴⊃,/(~^/¨⍺=0)/⍺}1 0 0 0 0 0 '''{(((3+z)×^/⍵)-5+2×+/+/¨⍺=0)⌽(2×77+z)⍴(77+z←2×+/0=⊃,/⍺,⍵)⍴⊃,/(~^/¨⍺=0)/⍺}1 0 0
0 0 0 '''{(((3+z)×^/⍵)-5+2×+/+/¨⍺=0)⌽(2×77+z)⍴(77+z←2×+/0=⊃,/⍺,⍵)⍴⊃,/(~^/¨⍺=0)/⍺}1 0 0 0 0 0 '''{(((3+z)×^/⍵)-5+2×+/+/¨⍺=0)⌽(2×77+z)⍴(77+z←2×+/0=⊃,/⍺,⍵)⍴⊃,/(~^/¨⍺=0)/⍺}1 0 0
0 0 0 0 '''{(((3+z)×^/⍵)-5+2×+/+/¨⍺=0)⌽(2×77+z)⍴(77+z←2×+/0=⊃,/⍺,⍵)⍴⊃,/(~^/¨⍺=0)/⍺}1 0 0 0 0 0 '''{(((3+z)×^/⍵)-5+2×+/+/¨⍺=0)⌽(2×77+z)⍴(77+z←2×+/0=⊃,/⍺,⍵)⍴⊃,/(~^/¨⍺=0)/⍺}1 0
0 0 0 0 '''{(((3+z)×^/⍵)-5+2×+/+/¨⍺=0)⌽(2×77+z)⍴(77+z←2×+/0=⊃,/⍺,⍵)⍴⊃,/(~^/¨⍺=0)/⍺}1 0 0 0 0 0 '''{(((3+z)×^/⍵)-5+2×+/+/¨⍺=0)⌽(2×77+z)⍴(77+z←2×+/0=⊃,/⍺,⍵)⍴⊃,/(~^/¨⍺=0)/⍺}1 0
0 0 0 0 0 '''{(((3+z)×^/⍵)-5+2×+/+/¨⍺=0)⌽(2×77+z)⍴(77+z←2×+/0=⊃,/⍺,⍵)⍴⊃,/(~^/¨⍺=0)/⍺}1 0 0 0 0 0 '''{(((3+z)×^/⍵)-5+2×+/+/¨⍺=0)⌽(2×77+z)⍴(77+z←2×+/0=⊃,/⍺,⍵)⍴⊃,/(~^/¨⍺=0)/⍺}1
0 0 0 0 0 '''{(((3+z)×^/⍵)-5+2×+/+/¨⍺=0)⌽(2×77+z)⍴(77+z←2×+/0=⊃,/⍺,⍵)⍴⊃,/(~^/¨⍺=0)/⍺}1 0 0 0 0 0 '''{(((3+z)×^/⍵)-5+2×+/+/¨⍺=0)⌽(2×77+z)⍴(77+z←2×+/0=⊃,/⍺,⍵)⍴⊃,/(~^/¨⍺=0)/⍺}1
'''{(((3+z)×^/⍵)-5+2×+/+/¨⍺=0)⌽(2×77+z)⍴(77+z←2×+/0=⊃,/⍺,⍵)⍴⊃,/(~^/¨⍺=0)/⍺}1 0 0 0 0 0 '''{(((3+z)×^/⍵)-5+2×+/+/¨⍺=0)⌽(2×77+z)⍴(77+z←2×+/0=⊃,/⍺,⍵)⍴⊃,/(~^/¨⍺=0)/⍺}1 0 0 0 0 0
192 персонажа, оценка = 2
'''{2≠⍴⍺:¯3⌽(2×1+⍴⍺)⍴(1+⍴⍺)⍴⍺ ⋄ a←⊃2⌷⍺ ⋄ ⍵=0:¯2⌽(2×1+⍴a)⍴(1+⍴a)⍴a⋄(-4+⌊10⍟⊃⍺)⌽(2×1+⍴a)⍴(1+⍴a)⍴a}01'''{2≠⍴⍺:¯3⌽(2×1+⍴⍺)⍴(1+⍴⍺)⍴⍺⋄a←⊃2⌷⍺⋄⍵=0:¯2⌽(2×1+⍴a)⍴(1+⍴a)⍴a⋄(-4+⌊10⍟⊃⍺)⌽(2×1+⍴a)⍴(1+⍴a)⍴a}01
В зависимости от реализации одной из точек сбоя может быть случай, когда целое число с префиксом строки слишком велико. Тем не менее, теоретически мы можем добавить цикл, добавив два символа - a 1в конце строки (перед ''') и a 1в конце всей строки.
200 символов, оценка = 1
'''{a←{2=⍴⍵:⊃2⌷⍵⋄⍵}⍺⋄(⍺{⍵=9:⍬⋄⍕1+{2=⍴⍵:10×⊃⍵⋄0}⍺}⍵),(¯2⌽(2×1+⍴a)⍴(1+⍴a)⍴a),⍺{⍵=9:(⍕9),⍕⊃⍺⋄⍕⌊⍵÷10}⍵}'''{a←{2=⍴⍵:⊃2⌷⍵⋄⍵}⍺⋄(⍺{⍵=9:⍬⋄⍕1+{2=⍴⍵:10×⊃⍵⋄0}⍺}⍵),(¯2⌽(2×1+⍴a)⍴(1+⍴a)⍴a),⍺{⍵=9:(⍕9),⍕⊃⍺⋄⍕⌊⍵÷10}⍵}91
Моя реализация APL не имеет целочисленных значений неограниченной точности по умолчанию, поэтому целое число преобразуется в число с плавающей точкой, когда оно становится слишком большим, что приводит к неправильному выводу. Так что это самый привередливый, но теоретически (либо вручную, либо с другим интерпретатором APL) он должен иметь оценку 1. Просто добавьте a 1в конец выражения, и вы получите еще один цикл.
Обзор (с более короткой формой)
Я собираюсь дать обзор первой версии, потому что я думаю, что это, вероятно, легче всего понять. Однако, прежде чем заняться этой версией, мы рассмотрим простую форму в APL :
1⌽22⍴11⍴'''1⌽22⍴11⍴'''
Я обнаружил, что один из лучших способов понять некоторые выражения APL - это посмотреть на результат в каскаде операторов / функций. Все операторы и функции в APL являются ассоциативными справа и имеют одинаковый приоритет, так что вот, справа налево:
'''1⌽22⍴11⍴'''Это просто строковый литерал (список символов). ''APL способ избежать одиночных кавычек. Выход: '1⌽22⍴11⍴'.
11⍴'''1⌽22⍴11⍴''': Здесь мы изменяем ( ⍴) строку, чтобы иметь длину 11. Поскольку длина строки меньше 11, она повторяется (т. 5⍴'abc'Е. Дает результат 'abcab'). Выход: '1⌽22⍴11⍴''. Итак, теперь у нас есть две кавычки в конце - мы добираемся куда-то!
22⍴11⍴'''1⌽22⍴11⍴'''Точно так же мы теперь изменили наш предыдущий вывод, чтобы иметь длину 22. Выход: '1⌽22⍴11⍴'''1⌽22⍴11⍴''. Мы почти на месте - нам просто нужно переместить первую одинарную кавычку до конца.
1⌽22⍴11⍴'''1⌽22⍴11⍴''': Здесь мы вращаем ( ⌽) список символов на 1. Это перемещает первый символ строки в конец. В качестве другого примера, 2⌽'abcdef'возвращает 'cdefab'. Выход: 1⌽22⍴11⍴'''1⌽22⍴11⍴'''.
Вращающаяся квинна
Эта короткая квинна является основной основой нашей вращающейся квинны. Теперь, имея это в виду, давайте посмотрим на нашу квинну:
'''{(((3+z)×^/⍵)-5+2×+/+/¨⍺=0)⌽(2×77+z)⍴(77+z←2×+/0=⊃,/⍺,⍵)⍴⊃,/(~^/¨⍺=0)/⍺}1 0 '''{(((3+z)×^/⍵)-5+2×+/+/¨⍺=0)⌽(2×77+z)⍴(77+z←2×+/0=⊃,/⍺,⍵)⍴⊃,/(~^/¨⍺=0)/⍺}1 0
{ ... }определяет безымянную функцию, в которой мы будем работать. Обратите внимание, что функции в APL принимают правый аргумент, обозначаемый как ⍵, и необязательный левый аргумент, обозначаемый ⍺(думаю, infix). Мы хотим передать эту функцию как нашей строке quine, так и чему-то, что поможет нам в создании произвольного числа циклов. Чтобы упростить себе задачу (и всем, кто хочет добавить циклы), мы делаем строку quine левым аргументом. Правильный аргумент - это то, где мы помещаем наш список циклов. 2 или более элементов, разделенных пробелом, создают список, поэтому в этом примере у нас есть 2-элементный список, состоящий из a 1и a 0.
Мы можем видеть, что функция выглядит аналогично предыдущей. У нас та же ...⌽...⍴...⍴...форма, что и раньше. Так что это хорошо - по крайней мере, мы это понимаем! Давайте углубимся в эллипсы, начиная со всем после последнего ⍴: ⊃,/(~^/¨⍺=0)/⍺.
- Как вы можете видеть, посмотрев на приведенный выше пример, мы добавляем в строку префикс 0 с правой стороны, добавляя один к каждой итерации; но нас это сейчас не волнует. Мы просто хотим строку!
- Сначала рассмотрим, что в скобках. (Кстати, они группируются, как и в большинстве других языков.)
⍺=0возвращает список, в данном случае, такой же формы, что ⍺и каждый элемент в ⍺, заменяется на a, 1если он равен 0, и на a 0иначе. Это выполняется рекурсивно; так что если у нас есть список из списка символов, отдельные символы будут проверены на 0, и вы получите список из списка списка двоичных значений.
- Так что, если
⍺состоит только из нашей строки, мы получим список из 0. В противном случае, наш левый аргумент имеет префикс 0 (например, 0 0 0 'quinestring'), так что это список, состоящий из 0 и другого списка, нашей строки. Тогда наш вывод выглядит так 1 1 1 <sub-list of zeros>.
^/¨⍺=0: Мы применяем производную функцию ^/, которая уменьшает ( /) с помощью логической функции AND ( ^), к каждому ¨элементу ( ) ⍺=0. Это сделано для того, чтобы сгладить подсписок нулей, чтобы мы могли рассматривать строку quine как одно двоичное значение. Учитывая предыдущий пример, результат будет 1 1 1 0.
~: Мы бинарное НЕ каждое из значений до (например, возвращая 0 0 0 1).
(~^/¨⍺=0)/⍺: Для каждого элемента в ⍺мы реплицируем ( /) его количество раз, указанное соответствующим элементом в левом аргументе. Это исключает все 0, оставляя нас только с нашей строкой квин.
⊃,/это некоторая необходимая документация, чтобы мы могли получить сплющенный список символов, уменьшив результат с помощью функции конкатенации ( ,). Если входные данные уже являются сплюснутым списком (т. Е. Левый аргумент нашей главной функции - только строка), мы получаем 1-элементный список, содержащий этот список. В другом случае, когда у нас есть список, состоящий из подсписка для строки, мы получаем то же самое обратно (список с подсписком). Затем мы распаковываем this ( ⊃), давая нам только первый элемент списка (то есть подсписок символов). Это может показаться ненужным, но в противном случае мы бы попытались изменить список из 1 элемента!
Далее мы рассмотрим длину, указанную для первого изменения формы, в скобках:
⍺,⍵: Мы соединяем правильный аргумент с первым аргументом
⊃,/⍺,⍵: То же, что и раньше - сгладить список.
+/0=⊃,/⍺,⍵: Добавьте количество нулей в списке, уменьшив ( /) с помощью функции дополнения ( +).
2×+/0=⊃,/⍺,⍵: Умножьте это число на два.
z←2×+/0=⊃,/⍺,⍵: Присвоить ( ←) результат переменной, z. Напомним, zтеперь в два раза больше нулей, найденных в левом и правом аргументах.
77+z←2×+/0=⊃,/⍺,⍵Затем мы добавляем 77для символов в строке quine игнорирование всего, что следует после пробела 1. Как и в первоначальном примере с квине, мы добавляем 1 к длине строки, чтобы получить еще одну одинарную кавычку.
- Выход этого изменения в этом примере:
'{(((3+z)×^/⍵)-5+2×+/+/¨⍺=0)⌽(2×77+z)⍴(77+z←2×+/0=⊃,/⍺,⍵)⍴⊃,/(~^/¨⍺=0)/⍺}1 0 ''
Аргумент к изменению формы, который следует, прост и отражает короткую квинну (в 2 раза больше длины первого преобразования). Наш вывод сейчас:
'{(((3+z)×^/⍵)-5+2×+/+/¨⍺=0)⌽(2×77+z)⍴(77+z←2×+/0=⊃,/⍺,⍵)⍴⊃,/(~^/¨⍺=0)/⍺}1 0 '''{(((3+z)×^/⍵)-5+2×+/+/¨⍺=0)⌽(2×77+z)⍴(77+z←2×+/0=⊃,/⍺,⍵)⍴⊃,/(~^/¨⍺=0)/⍺}1 0 ''
Теперь для последнего шага, где мы вычисляем, сколько нужно повернуть выходную строку:
- Как вы можете видеть, посмотрев на предыдущий вывод, мы хотим повернуть его назад (отрицательное значение), чтобы привести 2 заключительные кавычки в начало. Поскольку мы хотим, чтобы
0(и другой пробел) также переместились в начало, мы хотим повернуть его еще на 3 символа назад.
+/+/¨⍺=0: Сложите количество нулей в левом аргументе. Первый (справа) +/¨суммирует количество каждого элемента (т. Е. Подсписок или просто целое число), а второй +/дает нам сумму этого результирующего списка.
5+2×+/+/¨⍺=0: Умножьте на два (чтобы повернуть и пробелы), и добавьте 5 (результат, который мы получили раньше).
- Теперь мы вычитаем предыдущее значение из левого аргумента,
-чтобы обработать случай, когда мы достигли конца нашего цикла:
(3+z)×^/⍵: И все элементы в правильном аргументе вместе, чтобы увидеть, достигли ли мы нашего конца ( 1), и умножить это на 3+z.
И мы сделали!