Гольф, ты идешь на отлично!


204

Используя ваш язык, поиграйте в гольф .

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

Нет обмана - это означает, что вы не можете просто прочитать исходный файл и распечатать его. Кроме того, во многих языках пустой файл также является квине: это также не считается допустимым квинем.

Нет ошибок-квин - уже есть отдельный вызов для ошибок.

Очки за:

  • Наименьший код (в байтах)
  • Самое запутанное / неясное решение
  • Использование эзотерических / неясных языков
  • Успешное использование языков, на которых сложно играть в гольф

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


4
Разве ты не имеешь в виду: «Гольф, ты - квин для большего блага!»
Матин Улхак,

50
@muntoo - это игра на тему «Узнай у тебя Haskell для хорошего блага».
Рэйф Кеттлер

Ответы:


106

Гексагония , длина стороны 17 16, 816 705 байт

180963109168843880558244491673953327577233938129339173058720504081484022549811402058271303887670710274969455065557883702369807148960608553223879503892017157337685576056512546932243594316638247597075423507937943819812664454190530214807032600083287129465751195839469777849740055584043374711363571711078781297231590606019313065042667406784753422844".".>.@.#.#.#.#.#.#.#.>.(...........................<.".......".".>./.4.Q.;.+.<.#.>...........................<.".....".".>.#.#.>.N.2.'.\.>.............=.=......._.<.".....".".>.>.;.'.=.:.\.>.......................<."...".".>.\.'.%.'.<.#.>..............._.....<."...".".>.#.#.>.<.#.>...............=.=.<.".".".>.#.\.'.R./.>.................<.".!.........../.>.

Попробуйте онлайн!

Вот как это выглядит в развернутом виде:

                1 8 0 9 6 3 1 0 9 1 6 8 8 4 3 8
               8 0 5 5 8 2 4 4 4 9 1 6 7 3 9 5 3
              3 2 7 5 7 7 2 3 3 9 3 8 1 2 9 3 3 9
             1 7 3 0 5 8 7 2 0 5 0 4 0 8 1 4 8 4 0
            2 2 5 4 9 8 1 1 4 0 2 0 5 8 2 7 1 3 0 3
           8 8 7 6 7 0 7 1 0 2 7 4 9 6 9 4 5 5 0 6 5
          5 5 7 8 8 3 7 0 2 3 6 9 8 0 7 1 4 8 9 6 0 6
         0 8 5 5 3 2 2 3 8 7 9 5 0 3 8 9 2 0 1 7 1 5 7
        3 3 7 6 8 5 5 7 6 0 5 6 5 1 2 5 4 6 9 3 2 2 4 3
       5 9 4 3 1 6 6 3 8 2 4 7 5 9 7 0 7 5 4 2 3 5 0 7 9
      3 7 9 4 3 8 1 9 8 1 2 6 6 4 4 5 4 1 9 0 5 3 0 2 1 4
     8 0 7 0 3 2 6 0 0 0 8 3 2 8 7 1 2 9 4 6 5 7 5 1 1 9 5
    8 3 9 4 6 9 7 7 7 8 4 9 7 4 0 0 5 5 5 8 4 0 4 3 3 7 4 7
   1 1 3 6 3 5 7 1 7 1 1 0 7 8 7 8 1 2 9 7 2 3 1 5 9 0 6 0 6
  0 1 9 3 1 3 0 6 5 0 4 2 6 6 7 4 0 6 7 8 4 7 5 3 4 2 2 8 4 4
 " . " . > . @ . # . # . # . # . # . # . # . > . ( . . . . . .
  . . . . . . . . . . . . . . . . . . . . . < . " . . . . . .
   . " . " . > . / . 4 . Q . ; . + . < . # . > . . . . . . .
    . . . . . . . . . . . . . . . . . . . . < . " . . . . .
     " . " . > . # . # . > . N . 2 . ' . \ . > . . . . . .
      . . . . . . . = . = . . . . . . . _ . < . " . . . .
       . " . " . > . > . ; . ' . = . : . \ . > . . . . .
        . . . . . . . . . . . . . . . . . . < . " . . .
         " . " . > . \ . ' . % . ' . < . # . > . . . .
          . . . . . . . . . . . _ . . . . . < . " . .
           . " . " . > . # . # . > . < . # . > . . .
            . . . . . . . . . . . . = . = . < . " .
             " . " . > . # . \ . ' . R . / . > . .
              . . . . . . . . . . . . . . . < . "
               . ! . . . . . . . . . . . / . > .
                . . . . . . . . . . . . . . . .

Ах, ну, это были довольно эмоциональные американские горки ... Я перестал считать, сколько раз я переключался между "ха-ха, это безумие" и "подожди, если я сделаю это, это должно быть вполне выполнимо". Ограничения, наложенные на код правилами компоновки Hexagony, были ... суровыми.

Может быть возможно уменьшить длину стороны на 1 или 2 без изменения общего подхода, но это будет сложно (только ячейки с #в настоящее время не используются и доступны для декодера). На данный момент у меня также нет абсолютно никаких идей о том, как более эффективный подход, но я уверен, что он существует. Я подумаю над этим в течение следующих нескольких дней и, возможно, попробую сыграть в гольф с одной стороны, прежде чем добавить объяснение и все остальное.

Ну, по крайней мере, я доказал, что это возможно ...

Некоторые скрипты CJam для моей будущей ссылки:


51
Дорогой Пит, что это?
Конор О'Брайен

2
Сколько времени понадобилось, чтобы сделать это?
Аднан

3
@AandN Со вчерашнего дня я время от времени играю с концепциями для общего «шаблона» (это не включало никакого реального тестирования ... просто набираю некоторые вещи в сетке 7x7 и смотрю, может ли это работать ..) Я отбросил, вероятно, полдюжины подходов уже там). Фактическое кодирование тогда заняло этот вечер ... может быть, 3 часа, я бы сказал.
Мартин Эндер

10
Слова не могут объяснить, как я удивлен, когда вижу это в действии с Esoteric IDE шаг за шагом ... Кому, возможно, захочется это понять, этот шестиугольник кодирует часть «декодера» в целое число, которое печатается с помощью, !а затем с помощью зеркало /во 2-ой последней строке входит в декодер, чтобы напечатать код декодера для завершения квин. Это имеет чудесное использование <и >которое читает многострочное очень большое целое число и создает область для хранения декодера. Мне бы очень хотелось узнать, какие "десятки подходов" рассматриваются?
Солнечный Пан

3
Объяснение? ---
MD XF

77

MySQL, 167 символов

SELECT REPLACE(@v:='SELECT REPLACE(@v:=\'2\',1+1,REPLACE(REPLACE(@v,\'\\\\\',\'\\\\\\\\\'),\'\\\'\',\'\\\\\\\'\'));',1+1,REPLACE(REPLACE(@v,'\\','\\\\'),'\'','\\\''));

Верно. :-)

Я действительно написал это сам. Первоначально он был размещен на моем сайте .


72

GolfScript, 2 байта

1

(примечание завершающей новой строки) Это помещает число 1 в стек. В конце программы GolfScript распечатывает все элементы в стеке (без пробелов между ними), а затем печатает новую строку.

Это настоящий quine (как указано в вопросе), потому что он фактически выполняет код; он не просто «читает исходный файл и печатает его» (в отличие от представления PHP).


Для другого примера вот программа GolfScript для печати 12345678:

9,(;
  1. 9: нажмите 9 в стек
  2. ,: использовать 9 в качестве аргумента, перенести массив [0 1 2 3 4 5 6 7 8]в стек
  3. (: использовать массив в качестве аргумента, поместить массив [1 2 3 4 5 6 7 8]и элемент 0в стек
  4. ;: отбросить верхний элемент стека

Стек теперь содержит массив [1 2 3 4 5 6 7 8]. Это записывается в стандартный вывод без пробелов между элементами, за которым следует символ новой строки.


18
Или PowerShell, или PHP :-)
Джои

6
Вы не вернулись в прошлое и не дали изобретателю идею изобрести GolfScript, не так ли?
Матин Улхак,

78
Технически, 1это не quine в GolfScript: он выводит 1\n, где \nобозначает новую строку . Тем не менее, программа с двумя символами 1\n - это quine.
Ильмари Каронен

17
Программа с одним символом, \nвероятно, также есть?
Линн

10
@ Псевдоним quine - это буквально программа, которая печатает свой собственный источник. Я не думаю, что есть какие-то произвольные ограничения на «структуру».
Хьюго Цинк,

71

Brain-Flak , 9,8e580 1,3e562 9,3e516 12818 11024 4452 4332 4240 4200 4180 3852 3656 3616 3540 2485 + 3 = 2488 байт

Теперь вписывается в наблюдаемую вселенную!

(())(()()())(())(())(()()())(())(())(()()())(())(()()()()())(()())(()()()()())(())(()()())(())(()()()()())(())(())(())(())(()()()()())(())(())(()()())(())(())(()()())(())(()()()()())(()())(()()()()())(())(()()())(())(()()()()())(())(())(())(())(())(())(()())(())(())(())(()())(()()()())(())(()()()()())(()())(()())(()())(()()())(())(()())(())(()()()()())(()())(()()()()())(())(())(())(())(())(()())(())(())(())(()()()()())(())(())(()()()()())(())(())(()()()()())(())(())(()())(())(()())(())(()())(())(()())(())(()())(()())(()())(()())(()())(()())(()())(()())(())(()()()()())(())(())(()()())(())(())(()()())(())(()()()()())(()())(()()()()())(())(()()())(())(())(()()())(()())(())(()()()()())(())(())(()()())(())(())(()()())(())(()()()()())(()())(()()()()())(())(())(())(()()())(())(())(()()())(())(())(()()())(())(()()()()())(()())(()()()()())(()()())(())(()()())(())(())(())(()())(()()())(()())(())(()()()()())(()())(())(()()())(())(()()()()())(())(())(())(()()())(())(())(())(()())(())(()())(()()()())(())(())(()()()()())(()())(()())(())(()()())(())(())(())(())(()()())(()())(())(())(()()()()())(())(())(()()()()())(())(())(()()()()())(())(())(()())(())(()())(())(()())(())(()())(()())(()())(()())(())(()()()()())(()())(())(()()())(())(()()()()())(()()()()())(())(()()())(())(())(()())(())(()()()()())(())(()()()()())(())(())(())(()()()()())(())(())(()())(())(()())(())(()())(())(()())(())(()())(()())(()())(()())(())(()()()()())(()())(())(()()())(())(())(()())(())(()()()()())(()())(()()()()())(())(()()())(())(())(()()()()())(())(()()()()())(())(())(())(()())(())(()()()()())(())(())(()())(())(()())(())(()())(()())(()())(()())(())(()()()()())(()())(())(()()()()())(())(()()())(())(())(()())(())(()()()()())(()())(()()()()())(())(()()())(())(())(())(()())(()()()())(())(())(()())(())(()()()()())(())(())(()()()()())(())(())(()()()()())(())(())(()())(())(()())(())(()())(())(()())(())(()())(()())(()())(()())(()())(()())(())(()()())(())(())(()())(())(()()()()())(()())(()()()()())(()()())(())(())(()())(())(())(()()()()())(()()()())(()())(()())(()()())(())(()())(())(()()()()())(()())(()()()()())(())(())(())(()()()())(()()()())(()())([[]]){({}()<(([{}]())<{({}())<>(((((()()()()()){}){}){}())[()])<>{({}())<>{}({}(((()()()){}())){}{})<>{({}())<>({}(((()()()()()){})){}{}())<>{{}<>({}(((()()()()){}){}){})(<>)}}<>(({})[()()])<>}}{}<>({}(<()>)<><{({}<>)<>}<>>){({}<>)<>}{}(<>)<>{({}<>)<>}{}(((((((()()()()()){}){}){}))()))>){({}()<((({}[()])()))>)}{}<>{({}<>)<>}{}>)}{}<>{({}<>)<>}<>

Попробуйте онлайн!


объяснение

Этот Quine работает как большинство Quines на эзотерических языках; он состоит из двух частей: кодера и декодера. Кодер - это все круглые скобки в начале, а декодер - более сложная часть в самом конце.

Наивным способом кодирования программы было бы поместить значение ASCII каждого символа в декодере в стек. Это не очень хорошая идея, потому что Brain-Flak использует только 8 символов ( ()<>[]{}), так что вы в конечном итоге платите немало байтов, чтобы закодировать очень мало информации. Более разумная идея, которая использовалась до сих пор, заключается в назначении каждой из 8 фигурных скобок гораздо меньшему числу (1-8) и преобразовании их в значения ASCII с помощью нашего декодера. Это хорошо, потому что кодирование символа стоит не более 18 байт, в отличие от предыдущих 252.

Однако эта программа не делает ни того, ни другого. Он основан на том факте, что все программы Brain-Flak сбалансированы для кодирования 8 фигурных скобок с номерами до 5. Он кодирует их следующим образом.

(       -> 2
<       -> 3
[       -> 4
{       -> 5
),>,],} -> 1

Все закрывающие скобки назначены 1, потому что мы можем использовать контекст, чтобы определить, какие из них нам нужно использовать в конкретном сценарии. Это может показаться сложной задачей для программы Brain-Flak, но на самом деле это не так. Возьмем, к примеру, следующие кодировки с расшифрованными открытыми скобками, а закрывающие скобки заменены на .:

(.
((..
<([.{...

Надеемся, что вы можете видеть, что алгоритм довольно прост, мы читаем слева направо, каждый раз, когда мы сталкиваемся с открытой фигурной скобкой, мы помещаем ее закрывающую фигурную скобку в воображаемый стек, и когда мы сталкиваемся с a, .мы выталкиваем верхнее значение и помещаем его вместо ., Это новое кодирование экономит нам огромное количество байтов в кодере, в то время как мы теряем лишь несколько байтов в декодере.

Низкоуровневое объяснение

Работа в процессе


25
Я думаю, что вы выиграли для самого длинного решения проблемы кода-гольфа ...
Mego

18
Только что сделал самый большой одиночный гольф в истории PPCG Nope . 9.8e580 все же впечатляет.
Деннис

19
+1 за вписывание в наблюдаемую вселенную. Кроме того, с TIO Nexus, постоянная ссылка должна соответствовать ответу. tio.run/nexus/…
Деннис

3
... очень большой гольф ...
Разрушаемый Лимон

3
Я думаю, что вы выиграли для большинства отрезанных байтов
Кристофер

68

Prelude , 5157 4514 2348 1761 1537 664 569 535 423 241 214 184 178 175 169 148 142 136 133 байта

Спасибо Sp3000 за сохранение 3 байта.

Это довольно долго ... (хорошо, это все еще долго ... по крайней мере, сейчас он побеждает самую короткую известную квинтину Brainfuck C # по этому заданию сейчас), но это первая квина, которую я обнаружил сам (мои представления Lua и Julia на самом деле просто переводы стандартные приемы квина на другие языки) и, насколько мне известно, до сих пор никто не написал квин в Prelude, так что я на самом деле очень горжусь этим. :)

7( -^^^2+8+2-!( 6+ !
  ((#^#(1- )#)8(1-)8)#)4337435843475142584337433447514237963742423434123534455634423547524558455296969647344257)

Это большое количество цифр является просто кодировкой основного кода, поэтому квин так длинна.

Цифры, кодирующие квин, были сгенерированы с помощью этого скрипта CJam .

Для этого требуется совместимый со стандартом интерпретатор, который печатает символы (используя значения в качестве кодов символов). Так что если вы используете интерпретатор Python, вам нужно установить NUMERIC_OUTPUT = False.

объяснение

Сначала несколько слов о Prelude: каждая строка в Prelude - это отдельный «голос», который управляет своим собственным стеком. Эти стеки инициализируются бесконечным числом 0. Программа выполняется столбец за столбцом, где все команды в столбце выполняются «одновременно» на основе предыдущих состояний стека. Цифры помещаются в стек по отдельности, поэтому 42нажмите a 4, затем a 2. Там нет никакого способа, чтобы подтолкнуть большие цифры напрямую, вам придется добавить их. Значения могут быть скопированы из соседних стеков с помощью vи ^. Циклы в стиле Brainfuck можно вводить в скобках. Смотрите ссылку в заголовке для получения дополнительной информации.

Вот основная идея Quine: сначала мы помещаем множество цифр в стек, которые кодируют ядро ​​Quine. Затем указанное ядро ​​берет эти цифры, декодирует их для печати и затем печатает цифры, как они появляются в коде (и в конце )).

Это немного усложняется тем, что мне пришлось разделить ядро ​​на несколько строк. Первоначально у меня была кодировка в начале, но затем нужно было заполнить другие строки таким же количеством пробелов. Вот почему начальные оценки были такими большими. Теперь я поставил кодировку в конце, но это означает, что мне сначала нужно пропустить ядро, затем нажать цифры и вернуться к началу и выполнить печать.

Кодировка

Поскольку код имеет только два голоса, а и смежность является циклической ^и vявляются синонимами. Это хорошо, потому что vимеет наибольший код символа, поэтому избегая его всегда используя ^делает кодирование проще. Теперь все коды символов находятся в диапазоне от 10 до 94 включительно. Это означает, что я могу кодировать каждый символ точно двумя десятичными цифрами. Однако есть одна проблема: некоторые символы, особенно перевод строки, имеют ноль в десятичном представлении. Это проблема, потому что нули трудно отличить от нижней части стека. К счастью, есть простое исправление: мы смещаем коды символов на 2, поэтому у нас есть диапазон от 12 до 96 включительно, который по-прежнему удобно помещается в две десятичные цифры. Теперь из всех символов, которые могут появиться в программе Prelude,0имеет 0 в своем представлении (50), но нам действительно не нужно 0вообще. Такую кодировку я использую, нажимая каждую цифру отдельно.

Однако, поскольку мы работаем со стеком, представления перемещаются в обратном направлении. Итак, если вы посмотрите на конец кодировки:

...9647344257

Разбейте на пары и переверните, затем вычтите два, а затем найдите коды символов:

57 42 34 47 96
55 40 32 45 94
 7  (     -  ^

где 32соответствует пробелам. Ядро выполняет именно это преобразование, а затем печатает символы.

Ядро

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

Мы хотим запустить код ровно дважды - в первый раз мы пропускаем ядро ​​и нажимаем все цифры в конце, во второй раз мы запускаем ядро. Фактически, после того, как мы запустим ядро, мы снова нажмем все эти числа, но поскольку цикл завершается впоследствии, это не имеет значения. Это дает следующий скелет:

7(
  (                   )43... encoding ...57)

Во-первых, мы нажимаем 7на первый голос - если мы этого не сделаем, мы никогда не войдем в цикл (для скелета важно только, чтобы он отличался от нуля ... почему это конкретно 7мы увидим позже) , Затем мы входим в основной цикл. Теперь второй голос содержит еще один цикл. На первом проходе этот цикл будет пропущен, поскольку второй стек пуст / содержит только 0 с. Итак, мы переходим прямо к кодированию и помещаем все эти цифры в стек. 7Мы толкнули на первый стек еще есть, так что цикл повторяется.

На этот раз 7во втором стеке также есть a , поэтому мы вводим цикл для второго голоса. Цикл второго голоса спроектирован таким образом, что в конце стек снова пуст, поэтому он запускается только один раз. Это также приведет к истощению первого стека ... Поэтому, когда мы оставляем цикл во втором голосе, мы снова заполняем все цифры, но теперь 7первый элемент стека отбрасывается, поэтому основной цикл заканчивается, и программа завершается.

Далее, давайте посмотрим на первый цикл в реальном ядре. Делать вещи одновременно с (или )довольно интересно. Я пометил тело цикла здесь =:

-^^^2+8+2-!
(#^#(1- )#)
 ==========

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

Итак, мы начнем с одного -, который превращает 7первый стек в -7... опять же, подробнее об этом позже. Что касается фактического цикла ...

Цикл продолжается, пока стек цифр не был очищен. Он обрабатывает две цифры одновременно. Цель этого цикла - декодировать кодировку, печатать символ и одновременно сдвигать стопку цифр в первый голос. Итак, эта часть первая:

^^^
#^#

Первый столбец перемещает 1 цифру к первому голосу. Во втором столбце копируется 10-значный в первый голос, а также копируется 1-значный во второй голос. Третий столбец перемещает эту копию обратно к первому голосу. Это означает, что первый голос теперь имеет 1 цифру дважды и 10 цифр между ними. Второй голос имеет только еще одну копию из 10 цифр. Это означает, что мы можем работать со значениями на вершинах стеков и быть уверенными, что в первом стеке осталось две копии на потом.

Теперь мы восстанавливаем код символа из двух цифр:

2+8+2-!
(1- )#

Внизу есть небольшая петля, которая просто уменьшает 10-значный до нуля. Для каждой итерации мы хотим добавить 10 к вершине. Помните, что первый 2не является частью цикла, поэтому тело цикла на самом деле +8+2добавляет 10 (используя 2ранее помещенный элемент) и добавляет еще 2. Поэтому, когда мы закончим с циклом, первый стек на самом деле имеет базовый Значение 10 и другое 2. Вычитаем 2 с -учетом смещения в кодировке и печатаем символ с !. #Просто сбрасывает в нуль на конце нижней петли.

Как только этот цикл завершается, второй стек становится пустым, и первый стек содержит все цифры в обратном порядке (и -7внизу). Остальное довольно просто:

( 6+ !
8(1-)8)#

Это второй цикл ядра, который теперь выводит обратно все цифры. Для этого нам нужно 48 к каждой цифре, чтобы получить правильный код символа. Мы делаем это с помощью простого цикла, который запускается 8раз и добавляет 6каждый раз. Результат печатается с помощью !и 8в конце для следующей итерации.

Так что насчет -7? Да, 48 - 7 = 41это код символа ). Магия!

Наконец, когда мы закончим с этим циклом, мы отбрасываем 8только что нажатый #, чтобы гарантировать, что мы оставляем внешний цикл на втором голосе. Мы снова нажимаем на все цифры, и программа завершается.



19
Мартин, ты должен где-нибудь остановиться.
Seequ

3
Мне нравится, что в нем более 5000 байтов, плюс благодарность Sp3000 за сохранение 3 из них.
Камил Дракари

2
@KamilDrakari Это были последние 3 байта, так что это довольно большое дело. ;)
Мартин Эндер

57

Гексагония , длина стороны 11, 314 байтов

164248894991581511673077637999211259627125600306858995725520485910920851569759793601722945695269172442124287874075294735023125483.....!/:;.........)%'=a':\....................\...................\..................\.................\................\...............\..............\..$@.........\$><>'?2='%.<\:;_;4Q

Попробуйте онлайн!


Старая версия:

Гексагония , длина стороны 11, 330 байт

362003511553420961423766261426252539048636523959468260999944549820033581478284471415809677091006384959302453627348235790194699306179..../:{;+'=1P'%'a{:..\.....................\...................\..................\.................\................\...............\..............\.............\!$><........\..@>{?2'%<......:;;4Q/

Попробуйте онлайн!

Кодировщик: попробуйте онлайн!

Программа примерно эквивалентна этому коду Python: попробуйте онлайн!

Развернутый код:

           3 6 2 0 0 3 5 1 1 5 5
          3 4 2 0 9 6 1 4 2 3 7 6
         6 2 6 1 4 2 6 2 5 2 5 3 9
        0 4 8 6 3 6 5 2 3 9 5 9 4 6
       8 2 6 0 9 9 9 9 4 4 5 4 9 8 2
      0 0 3 3 5 8 1 4 7 8 2 8 4 4 7 1
     4 1 5 8 0 9 6 7 7 0 9 1 0 0 6 3 8
    4 9 5 9 3 0 2 4 5 3 6 2 7 3 4 8 2 3
   5 7 9 0 1 9 4 6 9 9 3 0 6 1 7 9 . . .
  . / : { ; + ' = 1 P ' % ' a { : . . \ .
 . . . . . . . . . . . . . . . . . . . . \
  . . . . . . . . . . . . . . . . . . . \ 
   . . . . . . . . . . . . . . . . . . \  
    . . . . . . . . . . . . . . . . . \   
     . . . . . . . . . . . . . . . . \    
      . . . . . . . . . . . . . . . \     
       . . . . . . . . . . . . . . \      
        . . . . . . . . . . . . . \       
         ! $ > < . . . . . . . . \        
          . . @ > { ? 2 ' % < . .         
           . . . . : ; ; 4 Q / .          

Два .с занимает 1 бит. Любые другие символы занимают 1 бит и цифру от основания 97.

объяснение

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

Часть данных

Вместо сложной структуры, используемой в некоторых других ответах (с <, "и некоторых других вещах), я просто позволил IP пройти через нижнюю половину.

Данные

Во-первых, IP-адрес проходит через множество чисел, безоперационных операторов ( .) и зеркал ( \). Каждая цифра добавляется к номеру в памяти, поэтому в конце значение памяти равно числу в начале программы.

mem = 362003511...99306179

! печатает это,

stdout.write(str(mem))

и $прыгает через следующий >.

Начиная с <. Если значение памяти memложно ( <= 0т. Е. Условие mem > 0не выполнено), мы завершили печать программы и должны выйти. IP будет следовать по верхнему пути.

Выход

(пусть IP работает по всему миру около 33 команд, прежде чем нажать @(что завершает программу), потому что размещение его в другом месте требует дополнительных байтов)

Если это так, мы следуем по нижнему пути, несколько раз перенаправляемся и выполняем еще несколько команд перед выполнением другого условия.

# Python                    # Hexagony
# go to memory cell (a)     # {
a = 2                       # ?2
# go to memory cell (b)     # '
b = mem % a                 # %

Теперь память выглядит так:

mEM1

Если значение истинно:

if b > 0:

следующий код выполняется:

# Python                    # Hexagony
b = ord('Q')                # Q
b = b*10+4                  # 4
# Note: now b == ord('.')+256*3
stdout.write(chr(b%256))    # ;
stdout.write(chr(b%256))    # ;

См подробное объяснение Q4на HelloWorld Hexagony ответ MartinEnder в . Короче говоря, этот код печатается .дважды.

Первоначально я планировал это напечатать .один раз. Когда я придумал это (напечатать .дважды) и реализовал его, было сохранено около 10 цифр.

Затем,

b = mem // a                # :

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


Чтобы понять, что я говорю, давайте проведем аналогию с БФ. (пропустите это, если вы уже поняли)

Учитывая код

while a != 0:
    b, a = a * 2, 0
    a, b = b, 0
    print(a)

Предполагая, что мы позволим aбыть значением текущей ячейки и bзначением правой ячейки, прямой перевод этого в BF:

[             # while a != 0:
    [->++<]       # b, a = a * 2, 0
    >[-<+>]       # a, b = b, 0
    <.            # print(a)
]

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

[             # while a != 0:
    [->++<]       # b, a = a * 2, 0
                  # implicitly let (a) be at the position of (b) now
    .             # print(a)
]

что на несколько байт короче.


Кроме того, поведение обтекания углов также избавляет меня от наличия там \зеркала - без него я не смог бы уместить цифры (+2 цифры для самого \себя и +2 цифры для непарного .справа от него, не говоря уже о флаги)

(подробности:

  • IP входит в левый нижний угол, направляясь влево
  • Это искажено в правый угол, все еще головы налево
  • Он встречает, \который отражает это, теперь он направлен вверх
  • Он идет в угол и снова искажается в левом нижнем углу.

)


Если значение (операции выше для мода 2) является ложным (ноль), то мы идем по этому пути:

# Python                 # Hexagony   # Memory visualization after execution
b = mem // a             # :          # click here
base = ord('a') # 97     # a
y = b % base             # '%
offset = 33              # P1
z = y + offset           # ='+
stdout.write(chr(z))     # ;          # click here
mem = b // base          # {:         # click here

Я не буду объяснять слишком подробно здесь, но смещение на самом деле не совсем точно 33, но совпадает с 33модом 256. И chrимеет скрытое % 256.


3
Чувак, это много бездельников
Джо Кинг,

26
Я смеялся над «Чтобы понять, что я говорю, давайте проведем аналогию [BrainFuck]». Только на PPCG ... :)
Линн

2
Я прокрутил как 3 раза до вершины ответа, чтобы проголосовать, только чтобы узнать, что я это уже сделал ...
NieDzejkob

2
310 байтов , используя новое пространство от сокращения числа
Джо Кинг

2
308 байт , занимая еще больше места
Джо Кинг,

46

Vim, 11 байт

q"iq"qP<Esc>hqP
  • iq"qP<Esc>: Вручную вставьте дубликат текста, который должен находиться за пределами записи.
  • q"и hqP: запишите внутреннюю часть непосредственно в безымянный ""регистр, чтобы его можно было вставить в середину. Это hединственное необходимое изменение положения; если вы поместите его внутри макроса, он будет вставлен в результат.

редактировать

Примечание о записи с q": безымянный регистр ""- забавная вещь. Это не совсем настоящий регистр, как и другие, так как текст там не хранится. На самом деле это указатель на какой-то другой регистр (обычно "-для удаления без новой строки, "0для янки или "1для удаления с новой строкой ). q"нарушает правила; это на самом деле пишет "0. Если вы ""уже указывали на какой-либо регистр, отличный от "0, q"будет перезаписан, "0но оставлен ""без изменений. Когда вы начинаете новый Vim, ""автоматически указывает на "0, так что вы в этом случае хорошо.

По сути, Vim странный и глючный.


подожди, почему это не работает для меня
Разрушимый Лимон

@DestructibleWatermelon Не могу сказать точно, но одно объяснение наиболее вероятно. Вероятно, должно было быть это в рецензии раньше, так как это может сбить людей с толку. Прочитайте редактирование.
udioica

Вы, вероятно, должны кое-что рассказать о том, как yможет помочь нажатие или что-то еще перед тем, как бежать
Разрушаемый Лимон

Почему вы не используете, чтобы показать, нажав клавишу <Esc>? Часть этого блока Unicode «Control Pictures»
mbomb007

4
@ mbomb007 <Esc>Обозначение является стандартным в отображениях Vim ( :help <>), и это то, что использует vimgolf.com. Любой опытный вимголфер привыкнет к нему читать. Что касается юникода, мне приходится щуриться, чтобы прочитать маленькие буквы, и они скрывают способ их ввода и поиска в файле справки.
udioica

44

Cubix , 20 байтов

3434Qu$v@!<"OOw\o;/"

Почти получил \o/ ...

Сеть :

    3 4
    3 4
Q u $ v @ ! < "
O O w \ o ; / "
    . .
    . .

Попробуйте онлайн

Попробуй это здесь !

Дополнительные примечания

История вопроса

После впечатления от чтения этого замечательного ответа @ ais523 я начал думать о дальнейшей игре в гольф. В конце концов, там было довольно много бездействий, и это не казалось слишком сжатым. Однако, поскольку методика, которую использует его ответ (и мой тоже), требует, чтобы код занимал целые строки, требовалась экономия не менее 12 байт. В его объяснении было одно замечание, которое заставило меня задуматься:

Что касается игры в гольф на этом участке, [...] потребуется [...] какой-то другой способ представить верхнюю грань куба [...]

Затем, внезапно, когда я встал и ушел, чтобы что-нибудь выпить, меня поразило: что, если в программе используются не коды символов, а цифры для обозначения верхнего лица? Это особенно коротко, если номер, который мы печатаем, имеет 2 цифры. Cubix имеет 3 инструкции один байт для толкания двузначных чисел: N, Sи Q, которые толкают 10, 32и , 34соответственно, так что это должно быть довольно golfy, подумал я.

Первое осложнение этой идеи состоит в том, что верхняя грань теперь заполнена бесполезными числами, поэтому мы больше не можем ее использовать. Второе осложнение заключается в том, что верхняя грань имеет размер, равный квадрату куба, и должен иметь четный размер, в противном случае одно число также окажется в начальной позиции указателя инструкции, что приведет к загрязненному стеку. Из-за этих сложностей мой код должен был поместиться в куб размером 2 (который может содержать «только» 24 байта, поэтому мне пришлось отыграть как минимум 21 байт). Кроме того, поскольку верхняя и нижняя грани непригодны, у меня было только 16 эффективных байтов.

Итак, я начал с выбора числа, которое станет половиной верхней грани. Я начал с N(10), но это не сработало из-за подхода, который я использовал, чтобы напечатать все. В любом случае, я начал заново и использовал S(32) по какой-то причине. Это действительно привело к правильной муке, или я так думал. Все работало очень хорошо, но цитаты отсутствовали. Затем мне пришло в голову, что Q(34) будет действительно полезным. В конце концов, 34 - это код символа двойной кавычки, который позволяет нам хранить его в стеке, сохраняя (2 в используемом тогда макете) драгоценные байты. После того, как я немного изменил IP-маршрут, все, что осталось, - это упражнения для заполнения пробелов.

Как это устроено

Код можно разбить на 5 частей. Я пойду по ним один за другим. Обратите внимание, что мы кодируем средние грани в обратном порядке, потому что модель стека является первым в последнем.

Шаг 1: Печать верхней грани

Нерелевантные инструкции были заменены на no-ops ( .). IP начинается с третьей строки, слева, указывая на восток. Стек (очевидно) пуст.

    . .
    . .
Q u . . . . . .
O O . . . . . .
    . .
    . .

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

QOO
Q   # Push 34 (double quotes) to the stack
 OO # Output twice as number (the top face)

Стек содержит всего 34, представляющих последний символ источника.

Шаг 2: закодировать четвертую строку

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

Фактически, IP переместился на одну позицию влево, и в стеке теперь содержится представление четвертой строки в кодах символов и обратном порядке.

Шаг 3: Нажмите другую цитату

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

Вот чистая версия для этого шага. Нерелевантные вмешательства снова были заменены на no-ops, выполняемые no-ops были заменены на hashtags ( #) для целей иллюстрации, а IP начинается с последнего символа в четвертой строке.

    . .
    . .
Q u $ . . . . .
. . w \ . . / .
    . #
    . #

IP заканчивается в третьей строке в первой инструкции, собирается завершиться до конца этой строки, потому что он указывает на запад. Следующие инструкции (исключая поток управления) выполняются:

$uQ
$u  # Don't do anthing
  Q # Push the double quote

Эта двойная кавычка представляет собой одну в конце третьей строки.

Шаг 4: Кодирование третьей строки

Это работает точно так же, как шаг 2, поэтому, пожалуйста, посмотрите там объяснение.

Шаг 5: Распечатать стопку

Стек теперь содержит четвертую и третью строки в обратном порядке, поэтому все, что нам нужно сделать сейчас, это напечатать его. IP начинается с предпоследней инструкции в третьей строке, двигаясь на запад. Вот соответствующая часть куба (опять же, нерелевантные части были заменены на no-ops).

    . .
    . .
. . . v @ ! < .
. . . \ o ; / .
    . .
    . .

Это цикл, как вы могли видеть / ожидали. Основное тело это:

o;
o  # Print top of stack as character
 ; # Delete top of stack

Цикл заканчивается, если верхний элемент равен 0, что происходит только тогда, когда стек пуст. Если цикл заканчивается, @выполняется, завершая программу.


Жаль, что я не мог бы проголосовать больше
MickyT

Щедрости всегда приветствуются ;-)
Лука

42

Javascript ES6 - 21 байт

$=_=>`$=${$};$()`;$()

Я называю эту лозу "Побрякушкой".

Иногда ты должен играть в гольф в стиле.


Сохраняет ли !$=_=>`!$=${$}()`()ты 2 байта?
Вниз

Invalid assignment left hand side, Жаль, что это не сработало :(
Mama Fun Roll

1
@ TùxCräftîñg Устранение скобок вокруг литералов шаблонов работает только с собственными функциями прототипа, например Array.prototype.join.
Mama Fun Roll

2
Хм, не уверен. Я написал это более года назад (тогда это считалось действительным), и я не слишком внимательно следил за изменениями правил Куина. Тем не менее, добавление alertили console.logпосле функции стрелки и обертывание строки шаблона в скобках будет работать.
Mama Fun Roll

3
Также, если вы запустите это в консоли, он перезапишет $ (функция jQuery) на этом сайте, и функция upvote больше не будет работать. :)
Стивен Палинкас

41

Brainf * ck (755 символов)

Это основано на методике, разработанной Эриком Босманом (ejbosman at cs.vu.nl). Обратите внимание, что "ESulanik's Quine!" текст на самом деле необходим для того, чтобы он был Quine!

->++>+++>+>+>++>>+>+>+++>>+>+>++>+++>+++>+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>+>+>++>>>+++>>>>>+++>+>>>>>>>>>>>>>>>>>>>>>>+++>>>>>>>++>+++>+++>+>>+++>>>+++>+>+++>+>++>+++>>>+>+>+>+>++>+++>+>+>>+++>>>>>>>+>+>>>+>+>++>+++>+++>+>>+++>+++>+>+++>+>++>+++>++>>+>+>++>+++>+>+>>+++>>>+++>+>>>++>+++>+++>+>>+++>>>+++>+>+++>+>>+++>>+++>>>+++++++++++++++>+++++++++++++>++++++>+++++++++++++++>++++++++++>+++>+++>++++>++++++++++++++>+++>++++++++++>++++>++++++>++>+++++>+++++++++++++++>++++++++>++++>++++++++++++>+++++++++++++++>>++++>++++++++++++++>+++>+++>++++>++++++>+++>+++++++++>++++>+>++++>++++++++++>++++>++++++++>++>++++++++++>+>+++++++++++++++>+++++++++++++
ESultanik's Quine!
+[[>>+[>]+>+[<]<-]>>[>]<+<+++[<]<<+]>>+[>]+++[++++++++++>++[-<++++++++++++++++>]<.<-<]

13
Это умный способ сделать это.
Питер Олсон

13
Как это работает?
гордый haskeller

3
@proudhaskeller IIRC, часть перед которой ESultanik's Quine!устанавливает память как кодирование стека ESultanik's Quine!и далее, с двумя байтами памяти для каждого символа (смещение значения ASCII от 0x1F). Последний фрагмент кода проходит по памяти, сначала программно воспроизводя ++>+++…коды для каждого символа, а затем фактически печатая символы.
ESultanik

4
@CatsAreFluffy Они должны быть квинном! Хотя это правда, что они могут быть удалены, необходимо также изменить предыдущий код, чтобы сохранить свойство quine.
ESultanik

1
Это правда. Также необходимы новые строки.
CalculatorFeline

36

Гексагония , длина стороны 15 14 13 12, 616 533 456 383 байта

После нескольких дней тщательного игры в гольф, перестановки петель и начала заново, мне наконец удалось сбить его в боковой шестигранник с 12 сторонами.

1845711724004994017660745324800783542810548755533855003470320302321248615173041097895645488030498537186418612923408209003405383437728326777573965676397524751468186829816614632962096935858"">./<$;-<.....>,.........==.........<"......."">'....>+'\.>.........==........<"......"">:>)<$=<..>..............$..<"...."">\'Q4;="/@>...............<"....."">P='%<.>.............<"..!'<.\=6,'/>

Попробуйте онлайн!

Развернутая:

            1 8 4 5 7 1 1 7 2 4 0 0
           4 9 9 4 0 1 7 6 6 0 7 4 5
          3 2 4 8 0 0 7 8 3 5 4 2 8 1
         0 5 4 8 7 5 5 5 3 3 8 5 5 0 0
        3 4 7 0 3 2 0 3 0 2 3 2 1 2 4 8
       6 1 5 1 7 3 0 4 1 0 9 7 8 9 5 6 4
      5 4 8 8 0 3 0 4 9 8 5 3 7 1 8 6 4 1
     8 6 1 2 9 2 3 4 0 8 2 0 9 0 0 3 4 0 5
    3 8 3 4 3 7 7 2 8 3 2 6 7 7 7 5 7 3 9 6
   5 6 7 6 3 9 7 5 2 4 7 5 1 4 6 8 1 8 6 8 2
  9 8 1 6 6 1 4 6 3 2 9 6 2 0 9 6 9 3 5 8 5 8
 " " > . / < $ ; - < . . . . . > , . . . . . .
  . . . = = . . . . . . . . . < " . . . . . .
   . " " > ' . . . . > + ' \ . > . . . . . .
    . . . = = . . . . . . . . < " . . . . .
     . " " > : > ) < $ = < . . > . . . . .
      . . . . . . . . . $ . . < " . . . .
       " " > \ ' Q 4 ; = " / @ > . . . .
        . . . . . . . . . . . < " . . .
         . . " " > P = ' % < . > . . .
          . . . . . . . . . . < " . .
           ! ' < . \ = 6 , ' / > . .
            . . . . . . . . . . . .

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

объяснение

Это превосходит предыдущий ответ Hexagony, кодируя no-ops ( .) другим способом. В то время как этот ответ экономит место, превращая каждый другой символ в a ., мой кодирует число неактивных операций. Это также означает, что источник не должен быть таким ограниченным.

Здесь я использую кодировку base 80, где числа ниже 16 обозначают серии бездействий, а числа от 16 до 79 представляют диапазон от 32 ( !) до 95 ( _) (я только сейчас понимаю, что я играл в гольф все _из моих код лол). Какой-то Pythonic псевдокод:

i = absurdly long number
print(i)
base = 80
n = i%base
while n:
    if n < 16:
        print("."*(16-n))
    else:
        print(ASCII(n+16))
    i = i//base
    n = i%base

Число закодировано в первой половине шестиугольника, со всеми

" " > 
 " " > 
  ... etc

на левой стороне и

 > ,
< "
 >
< "
... etc

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

Затем он входит в нижнюю часть через ->:

       " " > \ ' Q 4 ; = " / @ > . . . .
        . . . . . . . . . . . < " . . .
         . . " " > P = ' % < . > . . .
          . . . . . . . . . . < " . .
     ->    ! ' < . \ = 6 , ' / > . .

!печатает номер и 'перемещается в правую ячейку памяти перед началом цикла. P='%Мод изменяет текущее число на 80. Если результат равен 0, переходите к завершению @, в противном случае перейдите вниз и создайте ячейку рядом с результатом мода со значением -16.

   . " " > ' . . . . > + ' \ . > . . . . . .
    . . . = = . . . . . . . . < " . . . . .
     . " " > : > ) < $ = < . . > . . . . .
      . . . . . . . . . $ . . < " . . . .
       " " > \ ' Q 4 ; = " / @ > . . . .
                      /
                     /

Установите ячейку в (значение мода + -16). Если это значение отрицательное, поднимитесь вверх по ветвлению >+'\, иначе уменьшитесь.

Если значение положительное:

 " " > . / < $ ; - < . . . . . > , . . . . . .
  . . . = = . . . . . . . . . < " . . . . . .
   . " " > ' . . . . > + ' \ . > . . . . . .

Указатель заканчивается на том, ;-<который устанавливает ячейку (значение мода - -16) и печатает ее.

Значение является отрицательным:

   . " " > ' . . . . > + ' \ . > . . . . . .
    . . . = = . . . . . . . . < " . . . . .
     . " " > : > ) < $ = < . . > . . . . .

Спуститесь в > ) <секцию, которая начинает цикл. Вот он изолирован:

     . . > ) < $ = < . .
      . . . . . . . . .
       \ ' Q 4 ; = " /

Который выполняет код, 'Q4;="=который печатает .(еще раз спасибо Мартину Эндеру, который написал программу для поиска буквенно-цифровых комбинаций для символов) и возвращается к начальной ячейке. Затем он увеличивает ( )) ячейку значения мода и повторяет цикл, пока значение мода не станет положительным.

Когда это сделано, он перемещается вверх и соединяется с другим разделом по адресу:

 " " > . / < $ ; - < . . .
            \
             \

Затем указатель снова возвращается к началу большей петли.

 " " > . / <--
  . . . = =
   . " " > ' 
    . . . = = 
     . " " > :
      . . . . .
       " " > \ ' . .
        . . . . . . .
         . . " " > P = ' % < . > . . .

Выполняется, ='=:'что делит текущее число на 80 и переходит к правильной ячейке.

Старая версия (длина стороны 13)

343492224739614249922260393321622160373961419962223434213460086222642247615159528192623434203460066247203920342162343419346017616112622045226041621962343418346002622192616220391962343417346001406218603959366061583947623434"">/':=<$;'<.....>(......................<"......"">....'...>=\..>.....................<"....."">....>)<.-...>...........==......<"...."">.."...'.../>.................<"..."">\Q4;3=/.@.>...............<".."".>c)='%<..>..!'<.\1*='/.\""

Попробуйте онлайн!

Я могу определенно сыграть в гольф с другой стороны, но мне придется оставить это до завтра, потому что уже поздно. Оказывается, я нетерпеливый и не могу ждать до завтра. Может быть, другая сторона может быть в гольфе? :( аааа, я сделал это!

Я даже выбрал пару дополнительных цифр с кодировкой base 77, но это не имеет значения, поскольку у него такой же счет.


13
Это потрясающе. Идея этого гибридного кодирования длин серий действительно хороша. :) Напомни мне дать тебе награду, если я забуду.
Мартин Эндер

35

PostScript, 20 символов

Коротко и законно. 20 символов, включая завершающий перевод строки.

(dup == =)
dup == =

33

Cubix , 45 байт

.....>...R$R....W..^".<R.!'.\)!'"R@>>o;?/o'u"

Вы можете проверить этот код здесь .

За этой программой довольно трудно следовать, но чтобы иметь какой-либо шанс сделать это, нам нужно начать с ее расширения в куб, как это делает интерпретатор Cubix:

      . . .
      . . >
      . . .
R $ R . . . . W . . ^ "
. < R . ! ' . \ ) ! ' "
R @ > > o ; ? / o ' u "
      . . .
      . . .
      . . .

Это квинэ в стиле Befunge, которая работает через использование переноса, чтобы строковые литералы «оборачивались» исполняемым кодом ( "при наличии только одной метки код находится внутри и снаружи кавычки одновременно, что становится возможным, когда вы программы, которые являются нелинейными и неплоскими). Обратите внимание, что это соответствует нашему определению правильной квинусы, потому что две из двойных кавычек не кодируют себя, а вычисляются позже с использованием арифметики.

В отличие от Befunge, мы используем здесь четыре строки, а не одну. Вот как они помещаются в стек;

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

  2. Команда uделает разворот вправо, поэтому следующая вещь, которую мы запускаем, - это '"дальше по средней линии. Это толкает "на стек. Продолжая оборачиваться, мы ударяем <около левой стороны куба и отскакиваем назад. При подходе с этого направления мы видим простую "команду, а не '"так, поэтому вся вторая строка помещается в стек назад над третьей строкой и двойной кавычкой.

  3. Мы начинаем с того, что помещаем a !в стек ( '!) и увеличиваем его ( )); это приводит к двойным кавычкам без необходимости использовать двойные кавычки в нашем исходном коде (что приведет к завершению строки). Зеркало ( \) отражает направление выполнения на север; затем Wкоманда отступает влево. Это оставляет нас идущими вверх по седьмому столбцу, который, поскольку это куб, оборачивается влево в третьем ряду, затем вниз в третьем столбце. Мы нажимаем R, чтобы повернуть направо и идти влево вдоль верхнего ряда; затем $пропускает канал, Rчерез который мы вошли в программу, поэтому выполнение оборачивается до "конца в конце строки, и мы записываем первую строку в строке так же, как мы делали для второй и третьей.

  4. Команда ^отправляет нас на север вверх по одиннадцатой колонне, которая (с учетом оборачивания куба) на юг пятого. Единственное, с чем мы сталкиваемся, это !(пропустить, если не ноль; вершина стека действительно не равна нулю), которое пропускает oкоманду, фактически делая пятый столбец полностью пустым. Итак, мы возвращаемся к uкоманде, которая снова разворачивается, но на этот раз мы остаемся в последнем столбце на юг, который оборачивается в четвертый столбец на север. Однако во время разворота мы удваиваем двойные кавычки, поэтому мы фиксируем весь четвертый столбец в строке снизу вверх. В отличие от большинства двойных кавычек в программе, этот не закрывается сам по себе; скорее это закрыто "в правом верхнем углу, означая, что мы захватили строку из девяти символов ...>......

Итак, расположение стека теперь сверху вниз: четвертый столбец; Верхний ряд; "; средний ряд; "; Нижний ряд. Каждый из них представлен в стеке с первым символом, ближайшим к вершине стека (Cubix толкает строки в обратном порядке, как это делает Befunge, но каждый раз, когда IP-адрес двигался в направлении, противоположном естественному направлению чтения, таким образом это эффективно было полностью изменено дважды). Можно отметить, что содержимое стека практически идентично исходной программе (поскольку четвертый столбец и северная / верхняя грань куба содержат одинаковые символы в том же порядке; очевидно, он был разработан специально так).

Следующим шагом является печать содержимого стека. После всех толчков IP идет на север в четвертой колонке, поэтому он попадает >туда и входит в тесную петлю >>o;?(то есть «повернуть на восток, повернуть на восток, вывести символ, всплыть, повернуть направо, если положительный»). Поскольку седьмая строка заполнена NOP, ?она будет перенесена на первую >, поэтому это фактически выталкивает все содержимое стека ( ?это не работает в пустом стеке). Мы почти распечатали всю программу! К сожалению, это еще не совсем сделано; мы пропускаем двойную кавычку в конце.

Как только цикл заканчивается, мы отражаемся на центральной линии, двигаясь на запад через пару зеркал. (Мы использовали «другую сторону» \зеркала ранее; теперь мы используем юго-западную сторону. /Зеркало раньше не использовалось.) Мы сталкиваемся '!, поэтому нажимаем восклицательный знак (т. Е. 33; мы используем ASCII и Cubix не различает целые и символы) в стеке. (Удобно, это то же самое, !что использовалось, чтобы пропустить oкоманду ранее.) Мы встречаем пару Rкоманд и используем их, чтобы сделать «ручной» разворот (вторая Rкоманда здесь использовалась ранее, чтобы достичь первой ряд, так что казалось более естественным, чтобы соответствовать другой Rкоманде рядом с ним.Wкоманда, чтобы обойти влево. Боковой шаг врезается прямо в >команду во второй строке, возвращая выполнение точно туда, где оно было. Таким образом, мы снова отступаем влево, но на этот раз мы идем на юг, поэтому следующая команда для выполнения - это )(увеличение восклицательного знака в двойные кавычки), за которым следует o(чтобы вывести его). Наконец, выполнение переносится по восьмой строке ко второму столбцу, где находит @выход для выхода из программы.

Прошу прощения за бездомный апостроф в третьей строке. В этой версии программы ничего не происходит; это была часть моей более ранней идеи, но она оказалась ненужной. Однако, как только я получил рабочий квин, я просто хотел отправить его, а не возиться с ним дальше, тем более что его удаление не изменит количество байтов. Что касается дальнейшей игры в гольф, я бы не удивился, если бы это было возможно в 3х3, используя только первые пять линий, но я не вижу очевидного способа сделать это, и это потребует еще более плотная упаковка всего потока управления вместе с каким-либо другим способом представления верхней грани куба (или модификацией алгоритма, чтобы он мог продолжать использовать четвертый столбец, даже если теперь он будет длиной десять или одиннадцать символов) ,


Хорошая работа, это действительно впечатляющий результат. Мне нравится, как ты закодировал верхнее лицо. :)
Мартин Эндер

Это просто невероятно! Если это поможет любому, еще один способ подтолкнуть "это Q.
ETHproductions

1
Вау! Я никогда не думал, что увижу кубинскую куину!
FlipTack

3
У меня не было времени, чтобы прочитать объяснение вчера, но теперь, когда у меня есть ... Просто ... ВАУ. Я не могу поверить, сколько символов используется для двух или даже трех совершенно разных целей. Это, наверное, самая крутая программа Cubix, которую я когда-либо видел.
ETHproductions

Хорошее объяснение.
Роберт Фрейзер,

33

Python 2, 30 байт

_='_=%r;print _%%_';print _%_

Взято отсюда


1
+1, вы победили мое аналогичное решение, поэтому я удалил его. Следует отметить, что это работает только в Python 2.
nyuszika7h

2
Это выглядит странно с именем переменной как _, но читается лучше, если вы назначите его для любой буквы, то есть s:s='s=%r;print s%%s';print s%s
Ehtesh Choudhury

5
Если это решение не ваше собственное творение, вы должны сделать его Community Wiki. Также ссылка мертва.
mbomb007

1
Я немного опоздал на вечеринку, но кто-нибудь может объяснить, как это работает?
MadTux

9
Это требует, чтобы завершающий перевод строки был действительным. Как таковой, исходный код не соответствует выводу.
Деннис

32

Vim, 17 , 14 нажатий клавиш

Кто-то случайно проголосовал за это, поэтому я вспомнил, что оно существует. Когда я перечитал его, я подумал: «Эй, я могу добиться большего!», Поэтому я проиграл два байта. Это все еще не самое короткое, но, по крайней мере, это улучшение.


В течение долгого времени я задавался вопросом, возможна ли Vim Quine. С одной стороны, это должно быть возможно, поскольку vim завершен. Но после того, как я долго искал Vim Quine, я не смог его найти. Я же найти эту PPCG проблему , но она закрыта и не совсем о буквальных quines. Поэтому я решил сделать один, так как я не мог найти один.

Я действительно горжусь этим ответом из-за двух первых :

  1. Это первая тварь, которую я когда-либо делал, и

  2. Насколько я знаю, это первый в мире vim-quine, который когда-либо был опубликован! Я могу ошибаться, так что если вы знаете об этом, пожалуйста, дайте мне знать.

Итак, после этого долгого вступления, вот оно:

qqX"qpAq@q<esc>q@q

Попробуйте онлайн!

Обратите внимание, что когда вы наберете это, он будет отображать <esc>нажатие клавиши как ^[. Это все еще точно, так как ^[представляет 0x1B, который является escape в ASCII , и способ, которым vim внутренне представляет <esc>ключ.

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

vim -u NONE -N -i NONE

или введите qqqперед запуском.

Объяснение:

qq                  " Start recording into register 'q'
  X                 " Delete one character before the cursor (Once we play this back, it will delete the '@')
   "qp              " Paste register 'q'
      Aq@q<esc>     " Append 'q@q' to this line
               q    " Stop recording
                @q  " Playback register 'q'

С другой стороны, этот ответ, вероятно, является мировым рекордом для большинства «q» в ответе PPCG, или что-то в этом роде.


1
2i2i<esc>так близко Я чувствую, что должен что-то сделать, чтобы сделать эту работу.
Цвей

@ Zwei Я знаю, это близко, это больно! На самом деле, <Esc>неявно в V, так что работает . К сожалению, он также добавляет новую строку, поэтому я еще не опубликовал его.
DJMcMayhem

q"iq"qbP<Esc>qbPэто 11. После того, как вы положили это на Reddit , я исследовал здесь vimgolfing и решил сделать аккаунт. Это ответ, который я разместил там.
udioica

2
@udioica Можете ли вы опубликовать это как ответ?
DJMcMayhem

28

Потерян , 120 116 98 96 76 70 66 байт

Редактировать: да, под 100

Изменить: сохранить кучу байтов, переключившись на все /s в нижней строке

:2+52*95*2+>::1?:[:[[[[@^%?>([ "
////////////////////////////////

Попробуйте онлайн! + проверка детерминированности для всех возможных состояний

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

Объяснение:

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

 ^%?>
 ////

Что очищает все ненулевые числа в стеке. ([После этого очищает любые дополнительные 0s , а также.

В середине очистки он попадает в %, что отключает «безопасность», что позволяет программе завершать работу при достижении @(без этого программа могла бы немедленно завершиться, если указатель начинался на @).

Оттуда он выполняет довольно простую двумерную языковую квиню, оборачивая строку literal ( ") вокруг первой строки, выдвигая "символ, дублируя пробел ( :2+), а затем символ новой строки ( 52*). Для второй строки он создает /символ ( 95*2+) и дублирует его в связку ( >::1?:[:[[[[), прежде чем окончательно завершиться с @и неявно печатать стек. Цель ?1состоит в том, чтобы остановить процесс от создания слишком большого числа нулей, если указатель вводится раньше, за исключением необходимости очищать их позже.

Я сэкономил здесь 20 байтов, сделав последнюю строку одним и тем же символом, что означало, что я могу перейти прямо из процесса дублирования в конец @.

Объяснение о процессе дублирования:

[это персонаж, известный как «Дверь». Если указатель попадает на плоскую сторону a [или a ], он отражает, иначе он проходит через него. Каждый раз, когда указатель взаимодействует с дверью, он переключается на противоположный тип. Используя это знание, мы можем построить простую формулу того, сколько раз инструкция будет выполняться в >:[блоке.

Добавьте начальное количество инструкций. Для каждого [, добавьте 2 раза количество инструкций слева от него. Для примера >::::[:[[[, мы начинаем с 5 в качестве начальной суммы. Первая Дверь имеет 4 инструкции по дублированию, поэтому мы добавляем 4 * 2 = от 8 до 5, чтобы получить 13. Остальные три Двери имеют 5 дубликатов слева, поэтому мы добавляем 3 * (5 * 2) = от 30 до 13, чтобы получить 43 выполняются дублирующие инструкции, и имеют >в стеке 44 с. Тот же процесс может быть применен к другим инструкциям, таким как (перемещение большого количества элементов из стека в область действия, или, как используется здесь, для удаления элементов из стека.

Уловка, которую я использовал здесь, чтобы избежать дублирования 0, это 1?. Если символ равен 0, ?он не пропускает 1, что означает, что он дублирует 1 для оставшейся части дублирования. Это значительно облегчает очистку стека в дальнейшем.


25

Это две самые короткие рубиновые квины из SO :

_="_=%p;puts _%%_";puts _%_

а также

puts <<2*2,2
puts <<2*2,2
2

Не спрашивайте меня, как работает второй ...


8
Второй использует heredoc, <<2запускает строку на следующей строке и *2повторяет строку
Ming-Tang

Зачем тебе 2?
CalculatorFeline

1
@CalculatorFeline Это терминатор строки heredoc (которая должна отображаться в отдельной строке). Это на самом деле не должно быть 2, хотя: tio.run/##KypNqvz/v6C0pFjBxsZAy0jHgAuFY8D1/z8A
Мартин Эндер

25

Деление , 6 байт

Похоже, что сейчас это самый короткий «правильный» вопрос среди этих ответов.

'!+OR"

объяснение

Поток управления начинается Rс одного правого (1,0)атома. Он "переключается в режим печати, а затем оборачивается вокруг строки, печатая '!+ORперед "повторным нажатием и выходя из режима печати.

Это оставляет "себя для печати. Кратчайший путь '"O(где '"масса атома устанавливается на код символа "и Oпечатается символ и уничтожается атом), но если бы мы это сделали, это "помешало бы режиму печати. Таким образом, вместо этого мы устанавливаем значение атома '!(на единицу меньше "), затем увеличиваем с +и затем печатаем результат с O.

альтернативы

Вот несколько альтернатив, которые длиннее, но, возможно, их методы вдохновляют кого-то находить более короткую версию, используя их (или, возможно, они будут более полезными в определенных обобщенных терминах).

8 байтов, используя JUMP

' |R@JO"

Опять же, код начинается с R. @Свопы массы и энергии , чтобы дать (0,1). Поэтому Jатом заставляет прыгнуть через Oпрямой на ". Затем, как и прежде, все, кроме ", печатаются в строковом режиме. После этого атом попадает |в обратное направление и проходит через '"Oпечать ". Пробел немного раздражает, но кажется необходимым, потому что в противном случае 'атом заставил бы рассматривать |символ как символ, а не зеркало.

8 байтов с использованием двух атомов

"'L;R@JO

Это имеет два атома, начиная налево Lи направо от R. Левый атом получает свое значение, '"которое затем сразу печатается с помощью O(и атом уничтожается). Для правого атома мы снова поменяем массу и энергию, перепрыгнем через, Oчтобы напечатать остальную часть кода в режиме печати. После этого его значение устанавливается с помощью, 'Lно это не имеет значения, потому что атом отбрасывается ;.


Технически неверен из-за отсутствия разделения кода / данных в источнике.
CalculatorFeline

4
@CalculatorFeline '!+кодирует ".
Мартин Эндер

Я не знаком с Fission, но |R@JO"'сработает, или вам все еще нужно это место после '?
MildlyMilquetoast

1
@MistahFiggins Я так думаю, но что более важно, вы напечатаете 'первый.
Мартин Эндер

24

Кросс-браузерный JavaScript (41 символ)

Он работает в 5 лучших веб-браузерах (IE> = 8, Mozilla Firefox, Google Chrome, Safari, Opera). Введите его в консоль разработчика в любом из них:

eval(I="'eval(I='+JSON.stringify(I)+')'")

Это не «обман» - в отличие от однобайтового квинуса Криса Джестера-Янга, так как его можно легко изменить, чтобы использовать alert()функцию (стоимостью 14 символов):

alert(eval(I="'alert(eval(I='+JSON.stringify(I)+'))'"))

Или преобразовать в букмарклет (стоимостью 22 символа):

javascript:eval(I="'javascript:eval(I='+JSON.stringify(I)+')'")

24

C 64 60 байт

main(s){printf(s="main(s){printf(s=%c%s%1$c,34,s);}",34,s);}

Пока что это самая короткая известная C-квина. Существует расширенная награда, если вы найдете более короткую.

Это работает в GCC , Clang и TCC в среде POSIX . Это вызывает чрезмерное количество неопределенного поведения со всеми из них.

Просто для удовольствия, вот репо, который содержит все известные мне C-квины. Не стесняйтесь раскошелиться / PR, если вы найдете или напишите другой, который добавляет что-то новое и креативное поверх существующих.

Обратите внимание, что он работает только в среде ASCII . Это работает для EBCDIC , но все еще требует POSIX . В любом случае, удачи в поиске среды POSIX / EBCDIC: P


Как это устроено:

  1. main(s)злоупотребляет mainаргументами, объявляя практически нетипизированную переменную s. (Обратите внимание, что на sсамом деле это не типизированный тип, но поскольку перечисленные компиляторы автоматически приводят его по мере необходимости, он также может быть *.)
  2. printf(s="..."устанавливает sв предоставленную строку и передает первый аргумент printf.
  3. sустановлен в main(s){printf(s=%c%s%1$c,34,s);}.
  4. %cУстановлен в ASCII 34, ". Это делает возможным Quine. Теперь sвыглядит следующим образом :
    main(s){printf(s="%s%1$c,34,s);}.
  5. Он %sнастроен на sсебя, что возможно благодаря # 2. Теперь sвыглядит следующим образом :
    main(s){printf(s="main(s){printf(s=%c%s%1$c,34,s);}%1$c,34,s);}.
  6. Значение %1$cустановлено в ASCII 34 ", printfпервый ** аргумент. Теперь sвыглядит следующим образом:
    main(s){printf(s="main(s){printf(s=%c%s%1$c,34,s);}",34,s);}
    ... что так и происходит с исходным кодом.

* Пример благодаря @Pavel
** первого аргумента после спецификатора формата - в этом случае s. Невозможно ссылаться на спецификатор формата.


Я думаю, что при таком же подходе это будет немного короче. Если бы printfспецификатор формата был доступен через $, это сработало бы для 52 байтов:

main(){printf("main(){printf(%c%0$s%1$c,34);}",34);}

Хотя это, конечно, не должно считаться конкурирующим, победитель «Наихудшего нарушения правил» на Международном конкурсе кодов С 1994, 1994_smr.c , определенно короче.
Рэй

@ Ray Это не разрешено. Это не правильная квиняна по любому определению. Из-за этой программы были изменены правила quien: P
MD XF

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

4
sимеет тип int, а не «нетипизированную переменную».
feersum

2
Все эти компиляторы, очевидно, допускают неявное преобразование указателя на int. s=3очевидно, не будет работать, потому что вам нужно дважды передать строку printf.
feersum

24

Java, 528 байт:

Решение Java с оригинальным подходом:

import java.math.*;class a{public static void main(String[]a){BigInteger b=new BigInteger("90ygts9hiey66o0uh2kqadro71r14x0ucr5v33k1pe27jqk7mywnd5m54uypfrnt6r8aks1g5e080mua80mgw3bybkp904cxfcf4whcz9ckkecz8kr3huuui5gbr27vpsw9vc0m36tadcg7uxsl8p9hfnphqgksttq1wlolm2c3he9fdd25v0gsqfcx9vl4002dil6a00bh7kqn0301cvq3ghdu7fhwf231r43aes2a6018svioyy0lz1gpm3ma5yrspbh2j85dhwdn5sem4d9nyswvx4wmx25ulwnd3drwatvbn6a4jb000gbh8e2lshp",36);int i=0;for(byte c:b.toByteArray()){if(++i==92)System.out.print(b.toString(36));System.out.print((char)c);}}}

в читаемой форме:

import java.math.*;
class a
{
    public static void main (String [] a)
    {
        BigInteger b=new BigInteger ("90ygts9hiey66o0uh2kqadro71r14x0ucr5v33k1pe27jqk7mywnd5m54uypfrnt6r8aks1g5e080mua80mgw3bybkp904cxfcf4whcz9ckkecz8kr3huuui5gbr27vpsw9vc0m36tadcg7uxsl8p9hfnphqgksttq1wlolm2c3he9fdd25v0gsqfcx9vl4002dil6a00bh7kqn0301cvq3ghdu7fhwf231r43aes2a6018svioyy0lz1gpm3ma5yrspbh2j85dhwdn5sem4d9nyswvx4wmx25ulwnd3drwatvbn6a4jb000gbh8e2lshp", 36); 
        int i=0; 
        for (byte c:b.toByteArray ())
        {
            if (++i==92) 
                System.out.print (b.toString (36)); 
            System.out.print ((char) c);
        }
    }
}

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

1
@Loovjo: Аналогично другим решениям, которые разбивают код на две части и вставляют всю строку, которая представляет код внутри снова, но весь код не просто строка, а кодируется как длинное число в базе 36 (26 алфавитных символов + 10 цифр).
пользователь неизвестен

1
Это может быть сокращено, если вы положите if(++i==92),
Tuskiomi

2
@tuskiomi: Спасибо, сокращено на два символа
пользователь неизвестен

1
@userunknown На самом деле, a*поскольку массив не выходит из Java, это C. Это некоторые другие части игры в гольф:, import java.math.*;class a{public static void main(String[]a){BigInteger b=new BigInteger("abc",36);int i=0;for(int c:b.toByteArray())System.out.printf("%s%c",++i==92?b.toString(36):"",c);}}где abcбудет только что вычисленное магическое число String. В Java 8+ также можно изменить class a{public static void mainна interface a{static void main, а в Java 10+ также можно изменить import java.math.*;и BigInteger b=new BigInteger(на var b=new java.math.BigInteger(.
Кевин Круйссен,

23

Цыпленок , 7

chicken

Нет, это не отражено напрямую :)


Черт, ты меня обыграл :)
Taconut

Это не повторяется, это строка chicken!
Эрик Outgolfer

Нет разделения кода / данных и, следовательно, недействительно.
CalculatorFeline

10
@CalculatorFeline Вы читали правила?
Timtech

1
@ JoKing Я не думаю, что это недопустимо, потому что правила конкурса запрещают только нулевую длину и мошенничество (чтение собственного исходного файла). Единственной вещью, которая запрещает неправильные квази, является стандартная лазейка - за исключением того, что стандартные лазейки обычно не применяются к ответам, которые предшествуют им.
pppery

23

Retina , 20 14 9 7 байт

Прежде чем мы начнем, я хотел бы упомянуть тривиальное решение файла, который содержит один 0. В этом случае Retina попытается посчитать 0s в пустом входе, результатом которого также является 0. Хотя я не считаю это правильным

Так что вот правильный:

>\`
>\`

Попробуйте онлайн!

В качестве альтернативы мы могли бы использовать ;вместо >.

объяснение

Программа состоит из одной замены, которую мы печатаем дважды.

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

Чтобы напечатать результат дважды, мы обертываем его в два этапа вывода. Внутренний \печатает результат с завершающей строкой, а внешний >печатает его без такового.

Если вы немного знакомы с Retina, вам может быть интересно, что случилось с неявным выводом Retina. Неявный вывод Retina работает, заключая заключительный этап программы в выходной этап. Однако Retina не делает этого, если финальная стадия уже является выходной. Причина этого в том, что в обычной программе более полезно иметь возможность заменить неявный выходной каскад специальным, например, \или ;для одного байта (вместо того, чтобы избавляться от неявного и с помощью .флага). К сожалению, это ведет к тому, что мы стоим нам два байта за квин.


20

Javascript (36 символов)

(function a(){alert("("+a+")()")})()

Это, AFAICT, самая короткая javascript quine, опубликованная до сих пор.


1
Это ... впечатляет. Вы должны объяснить, как это работает для меня 8- |
TehShrike

3
@TehShrike Подсказка: вы можете просмотреть содержимое функции, приведя ее к строке. Например, если у вас есть функция a, вы можете получить доступ к ее содержимому с помощью вызова a.toString.
Питер Олсон

7
Однако, чтобы быть педантичным, это всего лишь кавычка, если ваша реализация JavaScript структурирует функцию aточно так же, как это было написано выше. Тем не менее, вывод этого кода, скорее всего, будет quine на любой реализации JavaScript.
Ильмари Каронен

1
Вот тот же Куайн, 1 байт короче: !function a(){alert("!"+a+"()")}().
Исмаэль Мигель

1
(a=()=>alert(($ {a})))()
Деннис С

19

GolfScript, 8 байт

Я всегда думал, что самая короткая (истинная) квинта GolfScript была 9 байтов:

{'.~'}.~

Где необходим завершающий перевод строки, потому что GolfScript печатает завершающий перевод строки по умолчанию.

Но я только что нашел 8-байтовую квинну, которая работает точно в соответствии с этим ограничением перевода строки:

":n`":n`

Попробуйте онлайн!

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

Как отметил Томас Ква, 7-байтовый запрос CJam также может быть адаптирован к 8-байтовому решению:

".p"
.p

Опять же, нам нужен завершающий перевод строки.


6
Гольфскрипт странный.
CalculatorFeline

19

Лабиринт , 124 110 53 байта

Спасибо Sp3000 за игру в гольф с 9 байтами, что позволило мне сыграть еще 7.

44660535853919556129637653276602333!
1
:_98
/8 %
@9_.

Попробуйте онлайн!

объяснение

Лабиринт 101:

  • Лабиринт - это двумерный язык на основе стека. Стек бездонный и заполнен нулями, поэтому выталкивание из пустого стека не является ошибкой.
  • Выполнение начинается с первого действительного символа (здесь вверху слева). В каждом соединении, где есть два или более возможных путей для указателя инструкций (IP), вершина стека проверяется, чтобы определить, куда идти дальше. Отрицательным является поворот влево, нулевым - движение вперед, а положительным - поворот направо.
  • Цифры в исходном коде не выдвигают соответствующее число - вместо этого они выталкивают вершину стека и нажимают n*10 + <digit>. Это позволяет легко накапливать большие числа. Чтобы начать новый номер, используйте _, который толкает ноль.
  • " нет опс.

Сначала я объясню немного более простую версию, которая на байт длиннее, но немного менее волшебна:

395852936437949826992796242020587432!
"
:_96
/6 %
@9_.

Попробуйте онлайн!

Основная идея состоит в том, чтобы закодировать основную часть источника в одно число, используя некоторую большую базу. Затем этот номер можно легко распечатать обратно, прежде чем он будет декодирован для печати оставшейся части исходного кода. Декодирование - это просто повторное применение divmod base, где выведите modи продолжайте работу с divнулем.

Избегая {}, самый высокий код символа, который нам нужен, равен _(95), так что база 96 достаточна (если оставить базу низкой, число в начале будет короче). Итак, что мы хотим закодировать это:

!
"
:_96
/6 %
@9_.

Превращая эти символы в их кодовые точки и рассматривая результат как число base-96 (с самой младшей цифрой, соответствующей !и самой старшей цифрой ., потому что это порядок, в котором мы разберем число), мы получим

234785020242697299628949734639258593

Теперь код начинается с довольно крутого трюка (если можно так сказать), который позволяет нам напечатать кодировку и сохранить другую копию для декодирования с очень небольшими издержками: мы помещаем число в код в обратном порядке. Я вычислил результат с помощью этого скрипта CJam. Итак, давайте перейдем к реальному коду. Вот начало:

395852936437949826992796242020587432!
"

IP начинается в верхнем левом углу и идет на восток. Хотя он пробегает эти цифры, он просто строит это число поверх стека. Само число совершенно бессмысленно, потому что оно противоположно тому, что мы хотим. Когда IP-адрес попадает в !, этот номер извлекается из стека и печатает его. Это все, что нужно для воспроизведения кодировки в выводе.

Но теперь IP зашел в тупик. Это означает, что он поворачивается и теперь возвращается на запад (без !повторного выполнения ). На этот раз удобно, чтобы IP считывал число задом наперед, так что теперь число на вершине стека действительно кодирует оставшуюся часть источника.

Когда IP-адрес снова попадает в верхний левый угол, это не тупик, потому что IP-адрес может повернуть налево, поэтому он делает это и теперь движется на юг. Это "запрет, который нам нужен здесь, чтобы отделить число от основного цикла кода. Говоря о которых:

...
"
:_96
/6 %
@9_.

Пока вершина стека еще не равна нулю, IP будет проходить через этот довольно плотный код в следующем цикле:

"
>>>v
^< v
 ^<<

Или выложены линейно:

:_96%._96/

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

Сам код цикла на самом деле довольно прост (сжатие этого не было и есть основной вклад Sp3000):

:    # Duplicate the remaining encoding number N.
_96  # Push 96, the base.
%.   # Take modulo and print as a character.
_96  # Push 96 again.
/    # Divide N by 96 to move to the next digit.

При Nдостижении нуля поток управления меняется. Теперь ИП хотел бы двигаться прямо после /(то есть на запад), но там есть стена. Так что если вместо поворота (восток) выполняется 6снова. Это делает вершину стека положительной, поэтому IP поворачивается направо (на юг) и выполняет 9. Вершина стека сейчас 69, но все, что нас волнует, это то, что это положительно. IP делает еще один поворот направо (запад) и движется к тому, @который завершает код.

В общем, довольно просто на самом деле.

Хорошо, теперь, как мы можем сбрить этот дополнительный байт. Понятно, что эта операция кажется бесполезной, но нам нужна эта дополнительная строка: если бы цикл был рядом с номером, IP-адрес уже сразу переместился бы туда, а не пересекал все число. Так что мы можем сделать что-то полезное с этим без операции.

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

Хотя есть одна загвоздка, мы не можем просто сделать это:

95852936437949826992796242020587432!
3
:_96
/6 %
@9_.

Проблема в том, что теперь мы изменили на "a 3, что также меняет фактическое число, которое мы хотим получить. И конечно же, это число не заканчивается 3. Поскольку число полностью определяется кодом, начиная с, !мы ничего не можем с этим поделать.

Но, может быть, мы можем выбрать другую цифру? Нам не важно, есть ли 3в этом месте, если мы получим число, которое правильно кодирует источник. Ну, к сожалению, ни одна из 10 цифр не дает кодировки, чьи наименее значимые цифры соответствуют выбранным. К счастью, в оставшейся части кода есть некоторая свобода действий, так что мы можем попробовать еще несколько кодировок, не увеличивая количество байтов. Я нашел три варианта:

  1. Мы можем изменить @на /. В этом случае мы можем использовать любую цифру 1357и получить соответствующую кодировку. Однако это будет означать, что программа завершается с ошибкой, которая допускается, но не кажется очень чистой.
  2. Пробелы не единственные "настенные" персонажи. Каждый неиспользованный символ, особенно все буквы. Если мы используем заглавную букву, нам даже не нужно увеличивать основание для ее размещения (поскольку эти кодовые точки находятся ниже _). 26 вариантов дает множество возможностей. Например, для Aлюбой нечетной цифры работает. Это немного приятнее, но все же это не кажется таким уж изящным, поскольку вы никогда не использовали бы букву в реальном коде.
  3. Мы можем использовать большую базу. До тех пор, пока мы не увеличим основание значительно, количество десятичных цифр в кодировке останется неизменным (в частности, любое основание до 104 в порядке, хотя для оснований после 99 фактически потребуются дополнительные символы в самом коде). К счастью, база 98 дает единственное решение для сопоставления: когда мы используем цифру 1, кодировка также заканчивается 1. Это единственное решение среди баз 96, 97, 98, 99, так что это действительно очень удачно. И вот как мы в конечном итоге с кодом в верхней части этого ответа.

19

Потерянный , 293 262 249 байт

>:2+52*:6*:(84*+75*):>:::::[[[[[[[:[(52*)>::::[[[[[[:[84*+@>%?!<((((((((((([[[[[[[[[[[[[[ "
\#<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\

Попробуйте онлайн!

объяснение

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

Почему Lost Quine так сложно?

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

При этом есть несколько стандартных способов сделать что-то. Например, вот стандартный способ печати строки.

>%?"Stringv"(@
^<<<<<<<<<<<<<

Это внизу поток сбора, который захватывает большинство ips и тянет их к месту старта. Как только они достигают начального местоположения (вверху слева), мы очищаем их с помощью цикла, избавляясь от всех значений в стеке, затем поворачиваем безопасность, нажимаем на строку и выходим. (безопасность - это уникальная концепция. Потерянная каждая программа должна нажать %перед выходом, это предотвращает возможность ее завершения при запуске). Теперь моя идея состоит в том, чтобы расширить эту форму до полноценной муки.

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

>%?!<"Stringv"(@
^<<<<<<<<<<<<<<<
^<<<<<<<<<<<<<<<

Нам нужно добавить второй поток, чтобы избежать возможности !перепрыгнуть через поток и создать цикл.

Теперь мы хотим смешать это со стандартным форматом Quine. Так как Lost в значительной степени основан на Кляйне, я в основном украл заимствованную Клиен Куайн для Мартина Эндера .

:2+@>%?!< "
<<<<^<<<<<<
<<<<^<<<<<<

Это довольно удобно печатает первую строку quine. Теперь все, что нам нужно сделать, это жестко закодировать потоки. Ну, это легче сказать, чем сделать. Я попробовал примерно четыре разных способа сделать это. Я просто опишу тот, который работал.

Идея здесь состоит в том, чтобы использовать двери, чтобы получить желаемое количество стрелок. Дверь - это специальный тип зеркала, которое меняется при каждом ударе. [отражает ips, идущий слева и ]справа. Когда они попадают по ip с любой из этих сторон, переключите ориентацию. Мы можем составить линию из этих дверей и статического отражателя для многократного выполнения операции.

>:[[[

Будем выступать :трижды. Таким образом, если мы поместим a <в стек перед раздачей, мы сможем создать множество из них с меньшим количеством байтов. Мы делаем 2 из них, по одному для каждой строки, и между ними мы устанавливаем новую строку, однако второй нужно идти только до тех пор, пока она не покроет !добавленную нами, все остальное можно оставить пустым, сэкономив нам несколько байтов. Хорошо, теперь нам нужно добавить вертикальные стрелки в наши потоки. Вот тут-то и происходит оптимизация ключа. Вместо того, чтобы перенаправлять все ips на «запуск» программы напрямую, мы вместо этого перенаправим их в крайний левый угол, потому что мы уже знаем, что ips, начинающийся в крайнем левом углу, долженработать (или, по крайней мере, будет работать в окончательной версии), мы также можем просто перенаправить другие ips. Это не только делает его дешевле в байтах, я думаю, что эта оптимизация делает то, что возможно.

Однако все еще есть некоторые проблемы, наиболее важными из которых являются ips, запускаемые после >нажатия, но до того, как мы начнем копировать их. Такие ips войдут в копир и сделают несколько копий 0. Это плохо, потому что наш механизм очистки стека использует нули для определения дна стека, оставляя целую кучу нулей внизу. Нам нужно добавить более сильный метод очистки стека. Поскольку нет реального способа узнать, пуст ли стек, нам просто придется попытаться уничтожить как можно больше элементов в стеке. Здесь мы снова будем использовать метод двери, описанный ранее. Мы добавим ((((((((((([[[[[[[[[[[[[[в конец первой строки сразу после sanitizor избавиться от нулей.

Теперь есть еще одна проблема, так как мы перенаправили наши потоки на верхний левый ips, начиная с %и, двигаясь вниз, уже отключили безопасность и преждевременно выйдут. Поэтому нам нужно отключить безопасность. Мы делаем это, добавляя #к потоку, таким образом, ips, проходящий через поток, будет отключен, но ips, которые уже были очищены, не будет. Также #должен быть жестко закодирован в первой строке.

Вот и все, надеюсь, вы понимаете, как это работает сейчас.


: / так много опечаток и пропущенных ссылок
только ASCII

17

Да , 1165 879 606 561 540 522 498 + 7 = 505 байтов

Требуется -cheatфлаг, чтобы разрешить определение псевдонимов.

022222120211111102222122021121202222212021112202222110222212202112110222221202122212022222102222212021222120222221022222102222210222221202222110222211022222210222221022222210222212202222221022221102211110222221022221220222212202112120221111022212202211210222212022222102211120222122022111202222120212212021221202222221022111102221210222122022222102222120212212022221102211110222122022221102222120212212022112120221111022212202112120222212=%;0e-=<;0<-=>;:0~--=1;1>=2;0%{{>0<~{~>~<<}>>>]}>]}${<#}%{@}

Попробуйте онлайн!

объяснение

Есть две части к этому (как с большинством quines). Данные:

022222120211111102222122021121202222212021112202222110222212202112110222221202122212022222102222212021222120222221022222102222210222221202222110222211022222210222221022222210222212202222221022221102211110222221022221220222212202112120221111022212202211210222212022222102211120222122022111202222120212212021221202222221022111102221210222122022222102222120212212022221102211110222122022221102222120212212022112120221111022212202112120222212

И декодер:

=%;0e-=<;0<-=>;:0~--=1;1>=2;0%{{>0<~{~>~<<}>>>]}>]}${<#}%{@}

Данные представляют собой просто двоичное кодирование декодера (или, скорее, его обратное). Каждый 0начинает новый символ, а 1s и 2s 0- и 1-биты, соответственно.

Обратите внимание, что 0это стандартная команда Yup, которая выдвигает ноль, 1и 2пока не определена. Тем не менее, мы назначаем всю часть данных команде, %так что 1и 2может оставаться неопределенным до %фактического использования.

Далее мы определим еще несколько команд:

0e-=<;
0<-=>;
:0~--=1;
1>=2;

<уменьшает вершину стека, >увеличивает его. 1(несколько не интуитивно) удваивает вершину стека. 2удваивает, а затем увеличивает его. Благодаря этим определениям что-то подобное 0221111фактически оставит 48 (110000 в двоичном виде) в стеке.

Оставшиеся 32 байта выполняют фактическое декодирование в двух частях. Сначала нам нужно восстановить строку данных.

0%                ` Push a zero and then the data.
{                 ` For each value...
  {               `   Until that value is zero...
    >0<~{~>~<<}>  `   divmod 2. The div is the input to the next iteration,
                  `   the mod gives us the next bit.
    >>]           `   Increment twice (gives 2 or 3) and put at the bottom
                  `   of the stack.
  }
  >]              ` Increment the 0 and put it at the bottom as well.
}
$                 ` Reverse the entire stack.
{<#}              ` Decrement and print each number.

И, наконец, мы снова отправляем данные и печатаем каждое значение как символ:

%{@}

Для дальнейшего использования вот сценарий CJam для кодирования данных.


17

Fueue , 423 байта

Fueue - основанный на очереди esolang, в котором запущенная программа является очередью.

)$$4255%%1(~):[)$$24%%0:<[~:)~)]~[$11~)~<[[+$4--498+*-:~-10)):])<~][)))~]<]](H-):~:[)[):~[)~:~~([:~)*[):~[$1(+48]):~+]-:~~)10)~~]/]+:5):]~:](106328966328112328136317639696111819119696281563139628116326221310190661962811611211962861109696289611619628116111612896281115421063633063961111116163963011632811111819159628151213262722151522061361613096119619190661966311961128966130281807072220060611612811961019070723232022060611

Попробуйте онлайн!

Как это устроено

Это объяснение может или не может выйти из-под контроля. С другой стороны, я не знаю, как объяснить это намного короче, как я надеюсь, что люди могут следовать.

Fueue шпаргалка

Смотрите статью esolang wiki для подробностей, включая некоторые функции, не используемые в этой программе.

  • Начальная программа - это начальное состояние очереди, которое может содержать следующие элементы:

    • Целочисленные литералы (могут быть вычислены только неотрицательные в источнике, но отрицательные), при их выполнении печатается символ.
    • Квадратные скобки, разделенные вложенными блоками, инертны (сохраняются, если на них не действует какая-либо функция).
    • Функции, их аргументы - это элементы, следующие непосредственно за ними в очереди:
      • +*/-%: целочисленная арифметика ( -унарно, %логическое отрицание). Инертен, если не дано число аргументов.
      • ()<: поместить элемент в скобки, убрать скобки из блока, добавить последний элемент в блок. Последние два являются инертными, если за ними не следует блок.
      • ~:: swap, дублировать
      • $: копия (занимает число + элемент). Инертен перед не номером.
      • H: остановить программу.

    Обратите внимание, что в то время как []гнездо,() не надо - последние просто отдельные функции.

Синтаксис трассировки выполнения

Пробел необязателен в Fueue, кроме цифр. В следующих трассах выполнения он будет использоваться, чтобы предложить структуру программы, в частности:

  • Когда функция выполняется, она и ее аргументы будут выделяться из окружающих элементов пробелами. Если некоторые аргументы сложны, между ними также может быть пробел.
  • Многие следы выполнения разделены на «задержку» слева, отделенную от части справа, которая выполняет существенные манипуляции с данными. Смотрите следующий раздел.

Фигурные скобки {}(не используются в Fueue) используются в трассировках для представления целочисленного результата математических выражений. Это включает в себя отрицательные числа, так как Fueue имеет только неотрицательные литералы -- это функция отрицания.

Различные мета-переменные имена и ...используются для обозначения значений и сокращений.

Задержка тактики

Интуитивно понятно, что выполнение циклически повторяется вокруг очереди, частично изменяя то, через что она проходит. На результаты функции нельзя воздействовать снова до следующего цикла. Различные части программы эффективно развиваются параллельно, если они не взаимодействуют.

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

Эта тактика не всегда будет индивидуально упомянута ниже:

  • )[A]задержки Aна цикл. (Вероятно, самый простой и читаемый метод.)
  • ~efпереставляет элементы eи fкоторый также задерживает их выполнение. (Вероятно, наименее читаемый, но часто самый короткий для незначительных задержек.)
  • $1eзадерживает один элемент e.
  • -и %полезны для задержки чисел (последний для 0и 1.)
  • При задержке нескольких равных элементов подряд, :или $может быть использовано для их создания из одного.
  • (nЗаворачивает nв скобки, которые впоследствии могут быть удалены по желанию. Это особенно важно для числовых вычислений, поскольку числа слишком нестабильны, чтобы их можно было скопировать без предварительного помещения их в блок.

Общая структура

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

Вот как исходная программа делится между ними:

A:  )$$4255%%1(~
B:  ):[)$$24%%0:<[~:)~)]~[$11~)~<[[+$4--498+*-:~-10)):])<~][)))~]<]]
C:  
D:  (H-
E:  
F:  
G:  ):~:[)[):~[)~:~~([:~)*[):~[$1(+48]):~+]-:~~)10)~~]/]+:5):]~:](106328966328112328136317639696111819119696281563139628116326221310190661962811611211962861109696289611619628116111612896281115421063633063961111116163963011632811111819159628151213262722151522061361613096119619190661966311961128966130281807072220060611612811961019070723232022060611

Большая цифра в конце программы кодирует остаток в обратном порядке, две цифры на символ, причем 30 вычитается из каждого значения ASCII (например, 10кодирует( .)

На более высоком уровне вы можете думать о данных в этой программе (начиная с bignum) как о потоках справа налево, а о контроле - слева направо. Однако на более низком уровне Fueue постоянно запутывает различие между кодом и данными.

  • Секция G декодирует bignum в ASCII-цифры (например, цифра 0в качестве целого числа 48), сначала выделяя младшие значащие цифры. Он производит одну цифру каждые 15 циклов.
  • Раздел F содержит произведенные цифры ASCII-значений (каждое внутри блока), пока раздел E не сможет их использовать.
  • Секция E обрабатывает полученные цифры по две за раз, объединяя их в блоки формы [x[y]], а также печатая закодированный символ каждой пары.
  • Раздел D состоит из глубоко вложенного блока, постепенно построенного из [x[y]]блоков таким образом, что после того, как он содержит все цифры, его можно запустить, чтобы распечатать все из них, а затем остановить всю программу.
  • Раздел C обрабатывает построение раздела D, а также воссоздает раздел E.
  • Раздел B воссоздает раздел C, а также сам каждые 30 циклов.
  • Секция A ведет обратный отсчет циклов до последней итерации других секций. Затем он прерывает раздел B и запускает раздел D.

Раздел А

Раздел A управляет планированием конца программы. Требуется 4258 циклов, чтобы перейти к одной функции подкачки ~, которая затем выполняет настройку секции B, которая останавливает свой основной цикл и вместо этого начинает работу секции D.

)$ $4255% %1 (~
)$%%%...%% %0 [~]
)$%%%...% %1 [~]
⋮
)$ %0 [~]
) $1[~]
)[~]
~
  • $Функция создает 4255 копии следующих в %то время как (оборачивает ~в скобках.
  • Каждый последний цикл %используется для переключения следующего числа между 0и 1.
  • Когда все %s израсходованы, $1создается 1 копия [~](фактически NOP), а в следующем цикле )удаляются скобки.

Раздел Б

Раздел B обрабатывает сам себя, а также новую итерацию раздела C каждые 30 циклов.

) : [)$$24%%0:<[~:)~)]~[$11~)~<[[+$4--498+*-:~-10)):])<~][)))~]<]]
) [)$$24%%0:<[~:)~)]~[$11~)~<[[+$4--498+*-:~-10)):])<~][)))~]<]]            [BkB]
)$ $24%     %0  :<  [~:)~)]    ~ [$11~)~<[[+$4--498+*-:~-10)):])<~][)))~]<] [BkB]
)$ %...%%% %1   < < [~:)~)] [BkB]   [$11~)~<[[+$4--498+*-:~-10)):])<~][)))~]<]
)$ %...%% %0      < [~:)~)[BkB]] [$11~)~<[[+$4--498+*-:~-10)):])<~][)))~]<]
)$ %...% %1         [~:)~)[BkB][$11~)~<[[+$4--498+*-:~-10)):])<~][)))~]<]]
⋮
) $1 [~:)~)[BkB][$11~)~<[[+$4--498+*-:~-10)):])<~][)))~]<]]
) [~:)~)[BkB][$11~)~<[[+$4--498+*-:~-10)):])<~][)))~]<]]                    (1)
~:) ~)[BkB]                 [$11~)~<[[+$4--498+*-:~-10)):])<~][)))~]<]
) : [BkB]                 ) [$11~)~<[[+$4--498+*-:~-10)):])<~][)))~]<]      (2)
) [BkB] [BkB]               $11~)~<[[+$4--498+*-:~-10)):])<~][)))~]<
  • :Дублирует большой блок следующий (один экземпляр сокращенно [BkB]), а затем )удаляет скобку из первой копии.
  • $$24%%0 устанавливает обратный отсчет, аналогичный тому, который указан в разделе А.
  • Пока идет обратный отсчет, он :<превращается в два блока <<и ~меняет их местами, последний размещает код для нового раздела C.
  • Эти две <функции упаковывают два последних блока в первый - это избыточно в обычных итерациях, но позволит ~разделу А выполнить свою работу в конце.
  • (1) Когда обратный отсчет закончен, )удаляются внешние скобки. Далее ~:)превращается в ):и ~)меняет местами )на начало раздела C кода.
  • (2) Раздел B теперь вернулся к своему начальному циклу, в то время как a )собирается снять скобки, чтобы начать новую итерацию раздела C.

На заключительной итерации ~секция A появляется в точке (1) выше:

~ ) [~:)~)[BkB][$11~)~<[[+$4--498+*-:~-10)):])<~][)))~]<]]                  (1)
[~:)~)[BkB][$11~)~<[[+$4--498+*-:~-10)):])<~][)))~]<]]              )

В ~свопы )через блок и в секции С, предотвращая раздел В от быть снова запустить.

Раздел С

Секция C обрабатывает слияние новых пар цифровых символов в блок секции D, а также создает новые итерации секции E.

Ниже показана типичная итерация с кодами ASCII цифр xи их yпредставление. На самой первой итерации входящие элементы «D» и «E» являются начальными [H]и -вместо этого, так как ни один из предыдущих разделов E не выполнялся, чтобы создать какие-либо пары цифр.

C                                               D             E
$11~ )  ~<[[+$4--498+*-:~-10)):])<~]  [)))~]  < [)))~[...]]   [x[y]]
~~~ ~~~ ~~~ ~~) [[+$4--498+*-:~-10)):])<~]  < [)))~] [)))~[...][x[y]]]
~~~ ~~~     )  ~ [[+$4--498+*-:~-10)):])<~] [)))~[)))~[...][x[y]]]]
~~~       ~ )   [)))~[....]]                                  [[+$4--498+*-:~-10)):])<~]
                                              ~~[)))~[....]] )[[+$4--498+*-:~-10)):])<~]
                                                [)))~[....]]  ~[+$4--498+*-:~-10)):])<~
  • При этом используется другой метод синхронизации, который я обнаружил для этого ответа. Когда у вас есть несколько функций подкачки ~в строке, строка будет уменьшаться примерно до 2/3 каждого цикла (потому что один ~меняет местами два следующих), но иногда с остатком ~s, который наносит ущерб тщательным манипуляциям с последующим.
  • $11~производит такой ряд. Следующий ~меняет местами <следующий блок. Другой <в конце добавляет новый блок пары цифр (цифры x и y как коды ASCII) в блок секции D.
  • В следующем цикле у ~строки есть ~~остаток, который заменяет ~следующий ). Другой <добавляет раздел D в [)))~]блок.
  • Затем сам поменял ~местами следующий блок с новым кодом раздела E в блоке раздела D. Тогда новый остаток ~обменивает )поперек, и , наконец, последний ~~в ~ряду своп один из них через к секции Е так же , как )снял свои квадратные скобки.

В последней итерации секция A ~поменялась местами )через секцию B и секцию C. Однако секция C настолько недолговечна, что уже исчезла, и )заканчивается в начале секции D.

Раздел D

В разделе D распечатывается последняя большая цифра и останавливается программа. На протяжении большей части работы программы это инертный блок, в котором секции B – G взаимодействуют при сборке.

    (H -
    [H]-
    ⋮
    [)))~[H-]]                  After one iteration of section C
    ⋮
    [)))~[)))~[H-][49[49]]]]    Second iteration, after E has also run
    ⋮
)   [)))~[...]]     [49[48]]    Final printing starts as ) is swapped in
    ))) ~[...][49[48]]
    )) )[49[48]] [...]
    )) 49 [48][...]             Print first 1
    ) )[48] [...]
    ) 48 [...]                  Print 0
    )[...]                      Recurse to inner block
    ...
    ⋮
    )[H-]                       Innermost block reached
    H -                         Program halts
  • В первом цикле программы (функция остановки заключает Hв скобки. -Следующим образом , он будет использоваться как фиктивный элемент для первой итерации вместо цифр пары.
  • Первая введенная пара вещественных цифр [49[49]]соответствует последней 11цифре.
  • Очень последняя цифра пара [49[48]](соответствующая 10в начале цифры) на самом деле не включена в блок, но это не имеет никакого значения , как )[A[B]]и )[A][B]эквивалентны, и превращается в A[B].

После последней итерации происходит )переключение вправо из секции B, и блок секции D деблокируется. В )))~начале каждого подблока убедитесь, что все части выполнены в правильном порядке. Наконец, самый внутренний блок содержит Hостановку программы.

Раздел Е

В разделе E обрабатываются пары пар цифр ASCII, создаваемых секцией G, и оба печатают соответствующий кодированный символ и отправляют блок с объединенной парой влево в секции C и D.

Снова ниже показана типичная итерация с xи yпредставляющая коды ASCII цифр.

E                                                   F
~ [+$4--498+*-:~-10)):] )              <  ~         [y] [x]
) [+$4--498+*-:~-10)):]                   < [x] [y]
+ $4-  - 498  +*- :~ -10 ) )              : [x[y]]
+---  -{-498} +*- ~~{-10} )       ) [x[y]]  [x[y]]
+--    - 498  +*   -{-10}       ~ ) x  [y]  [x[y]]
+-    -{-498} +               * 10 x  )[y]  [x[y]]
+      - 498                    + {10*x} y  [x[y]]
                         + {-498} {10*x+y}  [x[y]]
{10*x+y-498}  [x[y]]
[x[y]]
  • Поступающие блоки цифр меняются местами, затем блок y добавляется к блоку x, и весь блок пары копируется. Один экземпляр останется до конца для разделов C и D.
  • Другая копия снова разблокируется, затем применяется последовательность арифметических функций для вычисления 10*x+y-498значения ASCII закодированного символа. 498 = 10*48+48-30, То 48s отменить ASCII кодировку xи в yто время как 30сдвигает кодирование от 00–99до30–129 , которая включает в себя все печатаемые ASCII.
  • Полученное число затем оставляется для выполнения, что печатает его символ.

Раздел F

Раздел F состоит из инертных блоков, содержащих ASCII-коды цифр. Для большей части запуска программы здесь будет не более двух, поскольку секция E потребляет их с той же скоростью, с которой их производит G. Однако на заключительном этапе печати 0здесь будут собираться лишние цифры.

[y] [x] ...

Раздел G

Раздел G обрабатывает разбиение большого числа в конце программы, сначала младшие значащие цифры, и отправку блоков с их кодами ASCII влево в другие разделы.

Так как у него нет проверки остановки, он фактически продолжит 0генерировать цифры, когда число будет уменьшено до 0, пока секция D не остановит всю программу с помощью Hфункции.

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

Инициализация в первых циклах:

) :~  : [)[):~[)~:~~([:~)*[):~[$1(+48]):~+]-:~~)10)~~]/]+:5):]~:]  ( 106328966328112328136317639696111819119696281563139628116326221310190661962811611211962861109696289611619628116111612896281115421063633063961111116163963011632811111819159628151213262722151522061361613096119619190661966311961128966130281807072220060611612811961019070723232022060611
)  ~ ~ [)[):~[)~:~~([:~)*[):~[$1(+48]):~+]-:~~)10)~~]/]+:5):]~:]  [BkG] [10...11]
) [)[):~[)~:~~([:~)*[):~[$1(+48]):~+]-:~~)10)~~]/]+:5):]~:]     ~ [BkG] [10...11]
) [):~[)~:~~([:~)*[):~[$1(+48]):~+]-:~~)10)~~]/]+:5):]       ~ : [10...11]  [BkG]

Типичная итерация, Nобозначает число для разделения:

) [):~[)~:~~([:~)*[):~[$1(+48]):~+]-:~~)10)~~]/]+:5):]        ~ : [N]  [BkG]
) :~ [)~:~~([:~)*[):~[$1(+48]):~+]-:~~)10)~~]/]+ :5 )         : [N]  : [BkG]
)  ~ ~ [)~:~~([:~)*[):~[$1(+48]):~+]-:~~)10)~~]/]  +5 5     ) [N]  [N] [BkG] [BkG]
) [)~:~~([:~)*[):~[$1(+48]):~+]-:~~)10)~~]/]               ~ 10 N  [N] [BkG] [BkG]
) ~:~  ~ ( [:~)*[):~[$1(+48]):~+]-:~~)10)~~]               / N 10  [N] [BkG] [BkG]
)  ~ : [:~)*[):~[$1(+48]):~+]-:~~)10)~~]                 ( {N/10}  [N] [BkG] [BkG]
) [:~)*[):~[$1(+48]):~+]-:~~)10)~~]                    : [{N/10}]  [N] [BkG] [BkG]
:~ )*[):~[$1(+48]):~+]- :~ ~)10 )           ~ ~ [{N/10}]  [{N/10}] [N] [BkG] [BkG]
~~) *[):~[$1(+48]):~+]- ~~10 )             ) [{N/10}]  ~ [{N/10}] [N]  [BkG] [BkG]
)  ~ * [):~[$1(+48]):~+]  -10            ~ ) {N/10}  [N] [{N/10}] [BkG] [BkG]
) [):~[$1(+48]):~+]               * {-10} {N/10}  ) [N]  [{N/10}] [BkG] [BkG]
) :~ [$1(+48]) :~                 + {-10*(N/10)} N  [{N/10}] [BkG] [BkG]
)  ~ ~ [$1(+48]  )                 ~ ~ {N%10}  [{N/10}] [BkG] [BkG]
) [$1(+48]                 ~ ) {N%10}  ~ [{N/10}] [BkG]  [BkG]
$1(                     + 48 {N%10}    ) [BkG]  [{N/10}] [BkG]
                        ( {48+N%10}   BkG [{N/10}] [BkG]            New iteration starts
                        [{48+N%10}]   ....
  • Капля задержки здесь особенно волосатая. Тем не менее, единственный новый трюк с задержкой - использовать +:5вместо --10задержки 10два цикла. Увы 10, этому помог только один из участников программы.
  • [N]И [BkG]блоки дублируются, то один экземпляр Nделится 10.
  • [{N/10}]дублируется, тогда для вычисления кода ASCII последней цифры Nas используется больше арифметических функций 48+((-10)*(N/10)+N). Блок с этим кодом ASCII оставлен для секции F.
  • Другая копия [{N/10}]обменивается между [BkG]блоками, чтобы установить начало новой итерации.

Bonus Quine (540 байт)

)$$3371%%1[~!~~!)!]):[)$$20%%0[):]~)~~[)$$12%%0[<$$7%~~0):~[+----48+*-~~10))]<]<~!:~)~~[40~[:~))~:~[)~(~~/[+--48):]~10]+30])):]]][)[H]](11(06(06(21(21(25(19(07(07(19(61(96(03(96(96(03(11(03(63(11(28(61(11(06(06(20(18(07(07(18(61(11(28(63(96(11(96(96(61(11(06(06(19(20(07(07(18(61(30(06(06(25(07(96(96(18(11(28(96(61(13(15(15(15(15(22(26(13(12(15(96(96(19(18(11(11(63(30(63(30(96(03(28(96(11(96(96(61(22(18(96(61(28(96(11(11(96(28(96(61(11(96(10(96(96(17(61(13(15(15(22(26(11(28(63(96(19(18(63(13(21(18(63(11(11(28(63(63(63(61(11(61(42(63(63

Попробуйте онлайн!

Поскольку я не был уверен, какой метод будет самым коротким, я сначала попытался кодировать символы в виде двузначных чисел, разделенных символом (s. Базовый код немного короче, но более полное представление данных на 50% компенсирует это. Не так хорошо, как в других, потому что я остановился, когда понял, что это не победит. У него есть одно преимущество: оно не требует реализации с поддержкой bignum.

Его общая структура чем-то похожа на основную. Раздел G отсутствует, поскольку представление данных заполняется непосредственно в разделе F. Однако в разделе E необходимо выполнить аналогичный расчет divmod для восстановления цифр двузначных чисел.


1
Вы должны объяснить гольф XD
VFDan

1
)$n[)](короче байта для счетчика задержки.
jimmy23013

15

Желе, 3 байта

”ṘṘ

Попробуйте онлайн!

верификация

$ echo $LANG
en_US
$ xxd -g 1 quine.jelly
0000000: ff cc cc                                         ...
$ ./jelly f quine.jelly | xxd -g 1
0000000: ff cc cc                                         ...

Как это устроено

”ṘṘ    Main link. No input.

”Ṙ     Set the return value to the character 'Ṙ'.
  Ṙ    Print a string representation of the return value.
       This prints: ”Ṙ
       (implicit) Print the return value.
       This prints: Ṙ

Какая версия переводчика используется? Когда я проверяю его, он выводит в UTF-8, даже если ввод находится в кодовой странице Jelly (и изменение в кодировке сделало бы это не просто).

1
Кодировка вывода зависит от настроек вашего терминала: если он установлен в UTF-x, он использует это; если он установлен на что-то еще, он использует кодовую страницу Jelly. В Linux это LANG=en_USдостигается именно этим. tio.run/nexus/bash#@@/…
Деннис
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.