var QUESTION_ID=69;
var OVERRIDE_USER=98;
var ANSWER_FILTER="!t)IWYnsLAZle2tQ3KqrVveCRJfxcRLe";var COMMENT_FILTER="!)Q2B_A2kjfAiU78X(md6BoYk";var answers=[],answers_hash,answer_ids,answer_page=1,more_answers=!0,comment_page;function answersUrl(index){return"https://api.stackexchange.com/2.2/questions/"+QUESTION_ID+"/answers?page="+index+"&pagesize=100&order=desc&sort=creation&site=codegolf&filter="+ANSWER_FILTER}
function commentUrl(index,answers){return"https://api.stackexchange.com/2.2/answers/"+answers.join(';')+"/comments?page="+index+"&pagesize=100&order=desc&sort=creation&site=codegolf&filter="+COMMENT_FILTER}
function getAnswers(){jQuery.ajax({url:answersUrl(answer_page++),method:"get",dataType:"jsonp",crossDomain:!0,success:function(data){answers.push.apply(answers,data.items);answers_hash=[];answer_ids=[];data.items.forEach(function(a){a.comments=[];var id=+a.share_link.match(/\d+/);answer_ids.push(id);answers_hash[id]=a});if(!data.has_more)more_answers=!1;comment_page=1;getComments()}})}
function getComments(){jQuery.ajax({url:commentUrl(comment_page++,answer_ids),method:"get",dataType:"jsonp",crossDomain:!0,success:function(data){data.items.forEach(function(c){if(c.owner.user_id===OVERRIDE_USER)
answers_hash[c.post_id].comments.push(c)});if(data.has_more)getComments();else if(more_answers)getAnswers();else process()}})}
getAnswers();var SCORE_REG=(function(){var headerTag=String.raw `h\d`
var score=String.raw `\-?\d+\.?\d*`
var normalText=String.raw `[^\n<>]*`
var strikethrough=String.raw `<s>${normalText}</s>|<strike>${normalText}</strike>|<del>${normalText}</del>`
var noDigitText=String.raw `[^\n\d<>]*`
var htmlTag=String.raw `<[^\n<>]+>`
return new RegExp(String.raw `<${headerTag}>`+String.raw `\s*([^\n,]*[^\s,]),.*?`+String.raw `(${score})`+String.raw `(?=`+String.raw `${noDigitText}`+String.raw `(?:(?:${strikethrough}|${htmlTag})${noDigitText})*`+String.raw `</${headerTag}>`+String.raw `)`)})();var OVERRIDE_REG=/^Override\s*header:\s*/i;function getAuthorName(a){return a.owner.display_name}
function process(){var valid=[];answers.forEach(function(a){var body=a.body;a.comments.forEach(function(c){if(OVERRIDE_REG.test(c.body))
body='<h1>'+c.body.replace(OVERRIDE_REG,'')+'</h1>'});var match=body.match(SCORE_REG);if(match)
valid.push({user:getAuthorName(a),size:+match[2],language:match[1],link:a.share_link,})});valid.sort(function(a,b){var aB=a.size,bB=b.size;return aB-bB});var languages={};var place=1;var lastSize=null;var lastPlace=1;valid.forEach(function(a){if(a.size!=lastSize)
lastPlace=place;lastSize=a.size;++place;var answer=jQuery("#answer-template").html();answer=answer.replace("{{PLACE}}",lastPlace+".").replace("{{NAME}}",a.user).replace("{{LANGUAGE}}",a.language).replace("{{SIZE}}",a.size).replace("{{LINK}}",a.link);answer=jQuery(answer);jQuery("#answers").append(answer);var lang=a.language;lang=jQuery('<i>'+a.language+'</i>').text().toLowerCase();languages[lang]=languages[lang]||{lang:a.language,user:a.user,size:a.size,link:a.link,uniq:lang}});var langs=[];for(var lang in languages)
if(languages.hasOwnProperty(lang))
langs.push(languages[lang]);langs.sort(function(a,b){if(a.uniq>b.uniq)return 1;if(a.uniq<b.uniq)return-1;return 0});for(var i=0;i<langs.length;++i)
{var language=jQuery("#language-template").html();var lang=langs[i];language=language.replace("{{LANGUAGE}}",lang.lang).replace("{{NAME}}",lang.user).replace("{{SIZE}}",lang.size).replace("{{LINK}}",lang.link);language=jQuery(language);jQuery("#languages").append(language)}}
body{text-align:left!important}#answer-list{padding:10px;float:left}#language-list{padding:10px;float:left}table thead{font-weight:700}table td{padding:5px}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <link rel="stylesheet" type="text/css" href="https://cdn.sstatic.net/Sites/codegolf/primary.css?v=f52df912b654"> <div id="language-list"> <h2>Winners by Language</h2> <table class="language-list"> <thead> <tr><td>Language</td><td>User</td><td>Score</td></tr></thead> <tbody id="languages"> </tbody> </table> </div><div id="answer-list"> <h2>Leaderboard</h2> <table class="answer-list"> <thead> <tr><td></td><td>Author</td><td>Language</td><td>Size</td></tr></thead> <tbody id="answers"> </tbody> </table> </div><table style="display: none"> <tbody id="answer-template"> <tr><td>{{PLACE}}</td><td>{{NAME}}</td><td>{{LANGUAGE}}</td><td><a href="{{LINK}}">{{SIZE}}</a></td></tr></tbody> </table> <table style="display: none"> <tbody id="language-template"> <tr><td>{{LANGUAGE}}</td><td>{{NAME}}</td><td><a href="{{LINK}}">{{SIZE}}</a></td></tr></tbody> </table>
Ответы:
Гексагония , длина стороны
1716,816705 байтПопробуйте онлайн!
Вот как это выглядит в развернутом виде:
Ах, ну, это были довольно эмоциональные американские горки ... Я перестал считать, сколько раз я переключался между "ха-ха, это безумие" и "подожди, если я сделаю это, это должно быть вполне выполнимо". Ограничения, наложенные на код правилами компоновки Hexagony, были ... суровыми.
Может быть возможно уменьшить длину стороны на 1 или 2 без изменения общего подхода, но это будет сложно (только ячейки с
#
в настоящее время не используются и доступны для декодера). На данный момент у меня также нет абсолютно никаких идей о том, как более эффективный подход, но я уверен, что он существует. Я подумаю над этим в течение следующих нескольких дней и, возможно, попробую сыграть в гольф с одной стороны, прежде чем добавить объяснение и все остальное.Ну, по крайней мере, я доказал, что это возможно ...
Некоторые скрипты CJam для моей будущей ссылки:
источник
!
а затем с помощью зеркало/
во 2-ой последней строке входит в декодер, чтобы напечатать код декодера для завершения квин. Это имеет чудесное использование<
и>
которое читает многострочное очень большое целое число и создает область для хранения декодера. Мне бы очень хотелось узнать, какие "десятки подходов" рассматриваются?MySQL, 167 символов
Верно. :-)
Я действительно написал это сам. Первоначально он был размещен на моем сайте .
источник
GolfScript, 2 байта
(примечание завершающей новой строки) Это помещает число 1 в стек. В конце программы GolfScript распечатывает все элементы в стеке (без пробелов между ними), а затем печатает новую строку.
Это настоящий quine (как указано в вопросе), потому что он фактически выполняет код; он не просто «читает исходный файл и печатает его» (в отличие от представления PHP).
Для другого примера вот программа GolfScript для печати
12345678
:9
: нажмите 9 в стек,
: использовать 9 в качестве аргумента, перенести массив[0 1 2 3 4 5 6 7 8]
в стек(
: использовать массив в качестве аргумента, поместить массив[1 2 3 4 5 6 7 8]
и элемент0
в стек;
: отбросить верхний элемент стекаСтек теперь содержит массив
[1 2 3 4 5 6 7 8]
. Это записывается в стандартный вывод без пробелов между элементами, за которым следует символ новой строки.источник
1
это не quine в GolfScript: он выводит1\n
, где\n
обозначает новую строку . Тем не менее, программа с двумя символами1\n
- это quine.\n
вероятно, также есть?Brain-Flak ,
9,8e5801,3e5629,3e51612818110244452433242404200418038523656361635402485 + 3 = 2488 байтТеперь вписывается в наблюдаемую вселенную!
Попробуйте онлайн!
объяснение
Этот Quine работает как большинство Quines на эзотерических языках; он состоит из двух частей: кодера и декодера. Кодер - это все круглые скобки в начале, а декодер - более сложная часть в самом конце.
Наивным способом кодирования программы было бы поместить значение ASCII каждого символа в декодере в стек. Это не очень хорошая идея, потому что Brain-Flak использует только 8 символов (
()<>[]{}
), так что вы в конечном итоге платите немало байтов, чтобы закодировать очень мало информации. Более разумная идея, которая использовалась до сих пор, заключается в назначении каждой из 8 фигурных скобок гораздо меньшему числу (1-8) и преобразовании их в значения ASCII с помощью нашего декодера. Это хорошо, потому что кодирование символа стоит не более 18 байт, в отличие от предыдущих 252.Однако эта программа не делает ни того, ни другого. Он основан на том факте, что все программы Brain-Flak сбалансированы для кодирования 8 фигурных скобок с номерами до 5. Он кодирует их следующим образом.
Все закрывающие скобки назначены 1, потому что мы можем использовать контекст, чтобы определить, какие из них нам нужно использовать в конкретном сценарии. Это может показаться сложной задачей для программы Brain-Flak, но на самом деле это не так. Возьмем, к примеру, следующие кодировки с расшифрованными открытыми скобками, а закрывающие скобки заменены на
.
:Надеемся, что вы можете видеть, что алгоритм довольно прост, мы читаем слева направо, каждый раз, когда мы сталкиваемся с открытой фигурной скобкой, мы помещаем ее закрывающую фигурную скобку в воображаемый стек, и когда мы сталкиваемся с a,
.
мы выталкиваем верхнее значение и помещаем его вместо.
, Это новое кодирование экономит нам огромное количество байтов в кодере, в то время как мы теряем лишь несколько байтов в декодере.Низкоуровневое объяснение
Работа в процессе
источник
Prelude ,
51574514234817611537664569535423241214184178175169148142136133 байтаСпасибо Sp3000 за сохранение 3 байта.
Это довольно долго ...(хорошо, это все еще долго ... по крайней мере, сейчас он побеждает самую короткуюизвестную квинтину BrainfuckC # по этому заданию сейчас), но это первая квина, которую я обнаружил сам (мои представления Lua и Julia на самом деле просто переводы стандартные приемы квина на другие языки) и, насколько мне известно, до сих пор никто не написал квин в Prelude, так что я на самом деле очень горжусь этим. :)Это большое количество цифр является просто кодировкой основного кода, поэтому квин так длинна.
Цифры, кодирующие квин, были сгенерированы с помощью этого скрипта CJam .
Для этого требуется совместимый со стандартом интерпретатор, который печатает символы (используя значения в качестве кодов символов). Так что если вы используете интерпретатор Python, вам нужно установить
NUMERIC_OUTPUT = False
.объяснение
Сначала несколько слов о Prelude: каждая строка в Prelude - это отдельный «голос», который управляет своим собственным стеком. Эти стеки инициализируются бесконечным числом 0. Программа выполняется столбец за столбцом, где все команды в столбце выполняются «одновременно» на основе предыдущих состояний стека. Цифры помещаются в стек по отдельности, поэтому
42
нажмите a4
, затем a2
. Там нет никакого способа, чтобы подтолкнуть большие цифры напрямую, вам придется добавить их. Значения могут быть скопированы из соседних стеков с помощьюv
и^
. Циклы в стиле Brainfuck можно вводить в скобках. Смотрите ссылку в заголовке для получения дополнительной информации.Вот основная идея Quine: сначала мы помещаем множество цифр в стек, которые кодируют ядро Quine. Затем указанное ядро берет эти цифры, декодирует их для печати и затем печатает цифры, как они появляются в коде (и в конце
)
).Это немного усложняется тем, что мне пришлось разделить ядро на несколько строк. Первоначально у меня была кодировка в начале, но затем нужно было заполнить другие строки таким же количеством пробелов. Вот почему начальные оценки были такими большими. Теперь я поставил кодировку в конце, но это означает, что мне сначала нужно пропустить ядро, затем нажать цифры и вернуться к началу и выполнить печать.
Кодировка
Поскольку код имеет только два голоса, а и смежность является циклической
^
иv
являются синонимами. Это хорошо, потому чтоv
имеет наибольший код символа, поэтому избегая его всегда используя^
делает кодирование проще. Теперь все коды символов находятся в диапазоне от 10 до 94 включительно. Это означает, что я могу кодировать каждый символ точно двумя десятичными цифрами. Однако есть одна проблема: некоторые символы, особенно перевод строки, имеют ноль в десятичном представлении. Это проблема, потому что нули трудно отличить от нижней части стека. К счастью, есть простое исправление: мы смещаем коды символов на2
, поэтому у нас есть диапазон от 12 до 96 включительно, который по-прежнему удобно помещается в две десятичные цифры. Теперь из всех символов, которые могут появиться в программе Prelude,0
имеет 0 в своем представлении (50), но нам действительно не нужно0
вообще. Такую кодировку я использую, нажимая каждую цифру отдельно.Однако, поскольку мы работаем со стеком, представления перемещаются в обратном направлении. Итак, если вы посмотрите на конец кодировки:
Разбейте на пары и переверните, затем вычтите два, а затем найдите коды символов:
где
32
соответствует пробелам. Ядро выполняет именно это преобразование, а затем печатает символы.Ядро
Итак, давайте посмотрим, как эти цифры на самом деле обрабатываются. Во-первых, важно отметить, что соответствующие скобки не обязательно должны быть в одной строке в Prelude. В каждом столбце может быть только одна скобка, поэтому нет никакой двусмысленности, в которой скобки принадлежат друг другу. В частности, вертикальная позиция закрывающей скобки всегда не имеет значения - стек, который проверяется, чтобы определить, заканчивается ли цикл (или пропущен полностью), всегда будет тем, который имеет
(
.Мы хотим запустить код ровно дважды - в первый раз мы пропускаем ядро и нажимаем все цифры в конце, во второй раз мы запускаем ядро. Фактически, после того, как мы запустим ядро, мы снова нажмем все эти числа, но поскольку цикл завершается впоследствии, это не имеет значения. Это дает следующий скелет:
Во-первых, мы нажимаем
7
на первый голос - если мы этого не сделаем, мы никогда не войдем в цикл (для скелета важно только, чтобы он отличался от нуля ... почему это конкретно7
мы увидим позже) , Затем мы входим в основной цикл. Теперь второй голос содержит еще один цикл. На первом проходе этот цикл будет пропущен, поскольку второй стек пуст / содержит только 0 с. Итак, мы переходим прямо к кодированию и помещаем все эти цифры в стек.7
Мы толкнули на первый стек еще есть, так что цикл повторяется.На этот раз
7
во втором стеке также есть a , поэтому мы вводим цикл для второго голоса. Цикл второго голоса спроектирован таким образом, что в конце стек снова пуст, поэтому он запускается только один раз. Это также приведет к истощению первого стека ... Поэтому, когда мы оставляем цикл во втором голосе, мы снова заполняем все цифры, но теперь7
первый элемент стека отбрасывается, поэтому основной цикл заканчивается, и программа завершается.Далее, давайте посмотрим на первый цикл в реальном ядре. Делать вещи одновременно с
(
или)
довольно интересно. Я пометил тело цикла здесь=
:Это означает, что содержащий столбец
(
не считается частью цикла (символы там выполняются только один раз, и даже если цикл пропущен). Но столбец, содержащий часть,)
является частью цикла и запускается один раз на каждой итерации.Итак, мы начнем с одного
-
, который превращает7
первый стек в-7
... опять же, подробнее об этом позже. Что касается фактического цикла ...Цикл продолжается, пока стек цифр не был очищен. Он обрабатывает две цифры одновременно. Цель этого цикла - декодировать кодировку, печатать символ и одновременно сдвигать стопку цифр в первый голос. Итак, эта часть первая:
Первый столбец перемещает 1 цифру к первому голосу. Во втором столбце копируется 10-значный в первый голос, а также копируется 1-значный во второй голос. Третий столбец перемещает эту копию обратно к первому голосу. Это означает, что первый голос теперь имеет 1 цифру дважды и 10 цифр между ними. Второй голос имеет только еще одну копию из 10 цифр. Это означает, что мы можем работать со значениями на вершинах стеков и быть уверенными, что в первом стеке осталось две копии на потом.
Теперь мы восстанавливаем код символа из двух цифр:
Внизу есть небольшая петля, которая просто уменьшает 10-значный до нуля. Для каждой итерации мы хотим добавить 10 к вершине. Помните, что первый
2
не является частью цикла, поэтому тело цикла на самом деле+8+2
добавляет 10 (используя2
ранее помещенный элемент) и добавляет еще 2. Поэтому, когда мы закончим с циклом, первый стек на самом деле имеет базовый Значение 10 и другое 2. Вычитаем 2 с-
учетом смещения в кодировке и печатаем символ с!
.#
Просто сбрасывает в нуль на конце нижней петли.Как только этот цикл завершается, второй стек становится пустым, и первый стек содержит все цифры в обратном порядке (и
-7
внизу). Остальное довольно просто:Это второй цикл ядра, который теперь выводит обратно все цифры. Для этого нам нужно 48 к каждой цифре, чтобы получить правильный код символа. Мы делаем это с помощью простого цикла, который запускается
8
раз и добавляет6
каждый раз. Результат печатается с помощью!
и8
в конце для следующей итерации.Так что насчет
-7
? Да,48 - 7 = 41
это код символа)
. Магия!Наконец, когда мы закончим с этим циклом, мы отбрасываем
8
только что нажатый#
, чтобы гарантировать, что мы оставляем внешний цикл на втором голосе. Мы снова нажимаем на все цифры, и программа завершается.источник
Гексагония , длина стороны 11, 314 байтов
Попробуйте онлайн!
Старая версия:
Гексагония , длина стороны 11, 330 байт
Попробуйте онлайн!
Кодировщик: попробуйте онлайн!
Программа примерно эквивалентна этому коду Python: попробуйте онлайн!
Развернутый код:
Два
.
с занимает 1 бит. Любые другие символы занимают 1 бит и цифру от основания 97.объяснение
Нажмите на изображения для увеличения. Каждая часть объяснения имеет соответствующий код Python, чтобы помочь пониманию.
Часть данных
Вместо сложной структуры, используемой в некоторых других ответах (с
<
,"
и некоторых других вещах), я просто позволил IP пройти через нижнюю половину.Во-первых, IP-адрес проходит через множество чисел, безоперационных операторов (
.
) и зеркал (\
). Каждая цифра добавляется к номеру в памяти, поэтому в конце значение памяти равно числу в начале программы.!
печатает это,и
$
прыгает через следующий>
.Начиная с
<
. Если значение памятиmem
ложно (<= 0
т. Е. Условиеmem > 0
не выполнено), мы завершили печать программы и должны выйти. IP будет следовать по верхнему пути.(пусть IP работает
по всему мируоколо 33 команд, прежде чем нажать@
(что завершает программу), потому что размещение его в другом месте требует дополнительных байтов)Если это так, мы следуем по нижнему пути, несколько раз перенаправляемся и выполняем еще несколько команд перед выполнением другого условия.
Теперь память выглядит так:
Если значение истинно:
следующий код выполняется:
См подробное объяснение
Q4
на HelloWorld Hexagony ответ MartinEnder в . Короче говоря, этот код печатается.
дважды.Первоначально я планировал это напечатать
.
один раз. Когда я придумал это (напечатать.
дважды) и реализовал его, было сохранено около 10 цифр.Затем,
Вот важный факт, который я понял, который спас мне около 14 цифр: вам не нужно быть там, где вы начали.
Чтобы понять, что я говорю, давайте проведем аналогию с БФ. (пропустите это, если вы уже поняли)
Учитывая код
Предполагая, что мы позволим
a
быть значением текущей ячейки иb
значением правой ячейки, прямой перевод этого в BF:Однако учтите, что нам не нужно постоянно находиться в одной и той же позиции во время программы. Мы можем позволить значению
a
быть тем, кем мы являемся в начале каждой итерации, тогда у нас есть этот код:что на несколько байт короче.
Кроме того, поведение обтекания углов также избавляет меня от наличия там
\
зеркала - без него я не смог бы уместить цифры (+2 цифры для самого\
себя и +2 цифры для непарного.
справа от него, не говоря уже о флаги)(подробности:
\
который отражает это, теперь он направлен вверх)
Если значение (операции выше для мода 2) является ложным (ноль), то мы идем по этому пути:
Я не буду объяснять слишком подробно здесь, но смещение на самом деле не совсем точно
33
, но совпадает с33
модом256
. Иchr
имеет скрытое% 256
.источник
Vim, 11 байт
iq"qP<Esc>
: Вручную вставьте дубликат текста, который должен находиться за пределами записи.q"
иhqP
: запишите внутреннюю часть непосредственно в безымянный""
регистр, чтобы его можно было вставить в середину. Этоh
единственное необходимое изменение положения; если вы поместите его внутри макроса, он будет вставлен в результат.редактировать
Примечание о записи с
q"
: безымянный регистр""
- забавная вещь. Это не совсем настоящий регистр, как и другие, так как текст там не хранится. На самом деле это указатель на какой-то другой регистр (обычно"-
для удаления без новой строки,"0
для янки или"1
для удаления с новой строкой ).q"
нарушает правила; это на самом деле пишет"0
. Если вы""
уже указывали на какой-либо регистр, отличный от"0
,q"
будет перезаписан,"0
но оставлен""
без изменений. Когда вы начинаете новый Vim,""
автоматически указывает на"0
, так что вы в этом случае хорошо.По сути, Vim странный и глючный.
источник
y
может помочь нажатие или что-то еще перед тем, как бежать␛
чтобы показать, нажав клавишу <Esc>? Часть этого блока Unicode «Control Pictures»<Esc>
Обозначение является стандартным в отображениях Vim (:help <>
), и это то, что использует vimgolf.com. Любой опытный вимголфер привыкнет к нему читать. Что касается юникода, мне приходится щуриться, чтобы прочитать маленькие буквы, и они скрывают способ их ввода и поиска в файле справки.Cubix , 20 байтов
Почти получил
\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 начинается с третьей строки, слева, указывая на восток. Стек (очевидно) пуст.IP заканчивается в крайнем левом положении на четвертой строке, указывая на запад, и собирается развернуться к крайнему правому положению на этой же линии. Выполненные инструкции (без символа потока управления):
Стек содержит всего 34, представляющих последний символ источника.
Шаг 2: закодировать четвертую строку
Этот бит в значительной степени делает то, что вы ожидаете: кодировать четвертую строку. IP начинается с двойной кавычки в конце этой строки и идет на запад, нажимая коды символов каждого символа, на который он попадает, пока не найдет соответствующую двойную кавычку. Эта двойная кавычка также является последним символом в четвертой строке, поскольку IP-адрес снова переносится, когда он достигает левого края.
Фактически, IP переместился на одну позицию влево, и в стеке теперь содержится представление четвертой строки в кодах символов и обратном порядке.
Шаг 3: Нажмите другую цитату
Нам нужно выдвинуть еще одну цитату, и что может быть лучше, чем перезапустить ее
Q
в начале программы, подойдя к ней справа? Это имеет дополнительный бонус, что IP напрямую попадает в цитату, которая кодирует третью строку.Вот чистая версия для этого шага. Нерелевантные вмешательства снова были заменены на no-ops, выполняемые no-ops были заменены на hashtags (
#
) для целей иллюстрации, а IP начинается с последнего символа в четвертой строке.IP заканчивается в третьей строке в первой инструкции, собирается завершиться до конца этой строки, потому что он указывает на запад. Следующие инструкции (исключая поток управления) выполняются:
Эта двойная кавычка представляет собой одну в конце третьей строки.
Шаг 4: Кодирование третьей строки
Это работает точно так же, как шаг 2, поэтому, пожалуйста, посмотрите там объяснение.
Шаг 5: Распечатать стопку
Стек теперь содержит четвертую и третью строки в обратном порядке, поэтому все, что нам нужно сделать сейчас, это напечатать его. IP начинается с предпоследней инструкции в третьей строке, двигаясь на запад. Вот соответствующая часть куба (опять же, нерелевантные части были заменены на no-ops).
Это цикл, как вы могли видеть / ожидали. Основное тело это:
Цикл заканчивается, если верхний элемент равен 0, что происходит только тогда, когда стек пуст. Если цикл заканчивается,
@
выполняется, завершая программу.источник
Javascript ES6 - 21 байт
Я называю эту лозу "Побрякушкой".
Иногда ты должен играть в гольф в стиле.
источник
!$=_=>`!$=${$}()`()
ты 2 байта?Invalid assignment left hand side
, Жаль, что это не сработало :(Array.prototype.join
.alert
илиconsole.log
после функции стрелки и обертывание строки шаблона в скобках будет работать.Brainf * ck (755 символов)
Это основано на методике, разработанной Эриком Босманом (ejbosman at cs.vu.nl). Обратите внимание, что "ESulanik's Quine!" текст на самом деле необходим для того, чтобы он был Quine!
источник
ESultanik's Quine!
устанавливает память как кодирование стекаESultanik's Quine!
и далее, с двумя байтами памяти для каждого символа (смещение значения ASCII от 0x1F). Последний фрагмент кода проходит по памяти, сначала программно воспроизводя++>+++…
коды для каждого символа, а затем фактически печатая символы.Гексагония , длина стороны
15 14 1312,616 533 456383 байтаПосле нескольких дней тщательного игры в гольф, перестановки петель и начала заново, мне наконец удалось сбить его в боковой шестигранник с 12 сторонами.
Попробуйте онлайн!
Развернутая:
Хотя этот код не выглядит самым удачным из кода Hexagony, тип кодировки, который я использовал, оптимизирован для более длительных циклов бездействия, чего в противном случае вы бы избегали.
объяснение
Это превосходит предыдущий ответ Hexagony, кодируя no-ops (
.
) другим способом. В то время как этот ответ экономит место, превращая каждый другой символ в a.
, мой кодирует число неактивных операций. Это также означает, что источник не должен быть таким ограниченным.Здесь я использую кодировку base 80, где числа ниже 16 обозначают серии бездействий, а числа от 16 до 79 представляют диапазон от 32 (
!
) до 95 (_
) (я только сейчас понимаю, что я играл в гольф все_
из моих код лол). Какой-то Pythonic псевдокод:Число закодировано в первой половине шестиугольника, со всеми
на левой стороне и
на правой стороне перенаправить указатель для кодирования числа в одну ячейку. Это взято из ответа Мартина Эндера (спасибо), потому что я не мог найти более эффективный способ.
Затем он входит в нижнюю часть через
->
:!
печатает номер и'
перемещается в правую ячейку памяти перед началом цикла.P='%
Мод изменяет текущее число на 80. Если результат равен 0, переходите к завершению@
, в противном случае перейдите вниз и создайте ячейку рядом с результатом мода со значением-16
.Установите ячейку в (значение мода + -16). Если это значение отрицательное, поднимитесь вверх по ветвлению
>+'\
, иначе уменьшитесь.Если значение положительное:
Указатель заканчивается на том,
;-<
который устанавливает ячейку (значение мода - -16) и печатает ее.Значение является отрицательным:
Спуститесь в
> ) <
секцию, которая начинает цикл. Вот он изолирован:Который выполняет код,
'Q4;="=
который печатает.
(еще раз спасибо Мартину Эндеру, который написал программу для поиска буквенно-цифровых комбинаций для символов) и возвращается к начальной ячейке. Затем он увеличивает ()
) ячейку значения мода и повторяет цикл, пока значение мода не станет положительным.Когда это сделано, он перемещается вверх и соединяется с другим разделом по адресу:
Затем указатель снова возвращается к началу большей петли.
Выполняется,
='=:'
что делит текущее число на 80 и переходит к правильной ячейке.Старая версия (длина стороны 13)
Попробуйте онлайн!
Я могу определенно сыграть в гольф с другой стороны, но мне придется оставить это до завтра, потому что уже поздно.Оказывается, я нетерпеливый и не могу ждать до завтра.Может быть, другая сторона может быть в гольфе?:(аааа, я сделал это!Я даже выбрал пару дополнительных цифр с кодировкой base 77, но это не имеет значения, поскольку у него такой же счет.
источник
PostScript, 20 символов
Коротко и законно. 20 символов, включая завершающий перевод строки.
источник
Cubix , 45 байт
Вы можете проверить этот код здесь .
За этой программой довольно трудно следовать, но чтобы иметь какой-либо шанс сделать это, нам нужно начать с ее расширения в куб, как это делает интерпретатор Cubix:
Это квинэ в стиле Befunge, которая работает через использование переноса, чтобы строковые литералы «оборачивались» исполняемым кодом (
"
при наличии только одной метки код находится внутри и снаружи кавычки одновременно, что становится возможным, когда вы программы, которые являются нелинейными и неплоскими). Обратите внимание, что это соответствует нашему определению правильной квинусы, потому что две из двойных кавычек не кодируют себя, а вычисляются позже с использованием арифметики.В отличие от Befunge, мы используем здесь четыре строки, а не одну. Вот как они помещаются в стек;
Программа начинается в верхней части левого края и идет вправо; он поворачивает вправо дважды (
R
), заставляя его идти влево вдоль третьей и последней линий, которые обвивают весь куб. Двойная кавычка совпадает сама по себе, поэтому мы помещаем всю третью строку в стек назад. Затем выполнение продолжается после двойной кавычки.Команда
u
делает разворот вправо, поэтому следующая вещь, которую мы запускаем, - это'"
дальше по средней линии. Это толкает"
на стек. Продолжая оборачиваться, мы ударяем<
около левой стороны куба и отскакиваем назад. При подходе с этого направления мы видим простую"
команду, а не'"
так, поэтому вся вторая строка помещается в стек назад над третьей строкой и двойной кавычкой.Мы начинаем с того, что помещаем a
!
в стек ('!
) и увеличиваем его ()
); это приводит к двойным кавычкам без необходимости использовать двойные кавычки в нашем исходном коде (что приведет к завершению строки). Зеркало (\
) отражает направление выполнения на север; затемW
команда отступает влево. Это оставляет нас идущими вверх по седьмому столбцу, который, поскольку это куб, оборачивается влево в третьем ряду, затем вниз в третьем столбце. Мы нажимаемR
, чтобы повернуть направо и идти влево вдоль верхнего ряда; затем$
пропускает канал,R
через который мы вошли в программу, поэтому выполнение оборачивается до"
конца в конце строки, и мы записываем первую строку в строке так же, как мы делали для второй и третьей.Команда
^
отправляет нас на север вверх по одиннадцатой колонне, которая (с учетом оборачивания куба) на юг пятого. Единственное, с чем мы сталкиваемся, это!
(пропустить, если не ноль; вершина стека действительно не равна нулю), которое пропускаетo
команду, фактически делая пятый столбец полностью пустым. Итак, мы возвращаемся кu
команде, которая снова разворачивается, но на этот раз мы остаемся в последнем столбце на юг, который оборачивается в четвертый столбец на север. Однако во время разворота мы удваиваем двойные кавычки, поэтому мы фиксируем весь четвертый столбец в строке снизу вверх. В отличие от большинства двойных кавычек в программе, этот не закрывается сам по себе; скорее это закрыто"
в правом верхнем углу, означая, что мы захватили строку из девяти символов...>.....
.Итак, расположение стека теперь сверху вниз: четвертый столбец; Верхний ряд;
"
; средний ряд;"
; Нижний ряд. Каждый из них представлен в стеке с первым символом, ближайшим к вершине стека (Cubix толкает строки в обратном порядке, как это делает Befunge, но каждый раз, когда IP-адрес двигался в направлении, противоположном естественному направлению чтения, таким образом это эффективно было полностью изменено дважды). Можно отметить, что содержимое стека практически идентично исходной программе (поскольку четвертый столбец и северная / верхняя грань куба содержат одинаковые символы в том же порядке; очевидно, он был разработан специально так).Следующим шагом является печать содержимого стека. После всех толчков IP идет на север в четвертой колонке, поэтому он попадает
>
туда и входит в тесную петлю>>o;?
(то есть «повернуть на восток, повернуть на восток, вывести символ, всплыть, повернуть направо, если положительный»). Поскольку седьмая строка заполнена NOP,?
она будет перенесена на первую>
, поэтому это фактически выталкивает все содержимое стека (?
это не работает в пустом стеке). Мы почти распечатали всю программу! К сожалению, это еще не совсем сделано; мы пропускаем двойную кавычку в конце.Как только цикл заканчивается, мы отражаемся на центральной линии, двигаясь на запад через пару зеркал. (Мы использовали «другую сторону»
\
зеркала ранее; теперь мы используем юго-западную сторону./
Зеркало раньше не использовалось.) Мы сталкиваемся'!
, поэтому нажимаем восклицательный знак (т. Е. 33; мы используем ASCII и Cubix не различает целые и символы) в стеке. (Удобно, это то же самое,!
что использовалось, чтобы пропуститьo
команду ранее.) Мы встречаем паруR
команд и используем их, чтобы сделать «ручной» разворот (втораяR
команда здесь использовалась ранее, чтобы достичь первой ряд, так что казалось более естественным, чтобы соответствовать другойR
команде рядом с ним.W
команда, чтобы обойти влево. Боковой шаг врезается прямо в>
команду во второй строке, возвращая выполнение точно туда, где оно было. Таким образом, мы снова отступаем влево, но на этот раз мы идем на юг, поэтому следующая команда для выполнения - это)
(увеличение восклицательного знака в двойные кавычки), за которым следуетo
(чтобы вывести его). Наконец, выполнение переносится по восьмой строке ко второму столбцу, где находит@
выход для выхода из программы.Прошу прощения за бездомный апостроф в третьей строке. В этой версии программы ничего не происходит; это была часть моей более ранней идеи, но она оказалась ненужной. Однако, как только я получил рабочий квин, я просто хотел отправить его, а не возиться с ним дальше, тем более что его удаление не изменит количество байтов. Что касается дальнейшей игры в гольф, я бы не удивился, если бы это было возможно в 3х3, используя только первые пять линий, но я не вижу очевидного способа сделать это, и это потребует еще более плотная упаковка всего потока управления вместе с каким-либо другим способом представления верхней грани куба (или модификацией алгоритма, чтобы он мог продолжать использовать четвертый столбец, даже если теперь он будет длиной десять или одиннадцать символов) ,
источник
"
этоQ
.Python 2, 30 байт
Взято отсюда
источник
_
, но читается лучше, если вы назначите его для любой буквы, то есть s:s='s=%r;print s%%s';print s%s
Vim,
17, 14 нажатий клавишКто-то случайно проголосовал за это, поэтому я вспомнил, что оно существует. Когда я перечитал его, я подумал: «Эй, я могу добиться большего!», Поэтому я проиграл два байта. Это все еще не самое короткое, но, по крайней мере, это улучшение.
В течение долгого времени я задавался вопросом, возможна ли Vim Quine. С одной стороны, это должно быть возможно, поскольку vim завершен. Но после того, как я долго искал Vim Quine, я не смог его найти. Я же найти эту PPCG проблему , но она закрыта и не совсем о буквальных quines. Поэтому я решил сделать один, так как я не мог найти один.
Я действительно горжусь этим ответом из-за двух первых :
Это первая тварь, которую я когда-либо делал, и
Насколько я знаю, это первый в мире vim-quine, который когда-либо был опубликован! Я могу ошибаться, так что если вы знаете об этом, пожалуйста, дайте мне знать.
Итак, после этого долгого вступления, вот оно:
Попробуйте онлайн!
Обратите внимание, что когда вы наберете это, он будет отображать
<esc>
нажатие клавиши как^[
. Это все еще точно, так как^[
представляет0x1B
, который является escape в ASCII , и способ, которым vim внутренне представляет<esc>
ключ.Также обратите внимание, что тестирование может закончиться неудачей, если вы загрузите существующий сеанс vim. Я написал ответ с подсказками, объясняющий, что здесь , если вам нужна дополнительная информация, но в основном вам нужно запустить vim с
или введите
qqq
перед запуском.Объяснение:
С другой стороны, этот ответ, вероятно, является мировым рекордом для большинства «q» в ответе PPCG, или что-то в этом роде.
источник
2i2i<esc>
так близко Я чувствую, что должен что-то сделать, чтобы сделать эту работу.<Esc>
неявно в V, так что работает . К сожалению, он также добавляет новую строку, поэтому я еще не опубликовал его.q"iq"qbP<Esc>qbP
это 11. После того, как вы положили это на Reddit , я исследовал здесь vimgolfing и решил сделать аккаунт. Это ответ, который я разместил там.Потерян ,
120 116 98 96 76 7066 байтРедактировать: да, под 100
Изменить: сохранить кучу байтов, переключившись на все
/
s в нижней строкеПопробуйте онлайн! + проверка детерминированности для всех возможных состояний
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 для оставшейся части дублирования. Это значительно облегчает очистку стека в дальнейшем.источник
Это две самые короткие рубиновые квины из SO :
а также
Не спрашивайте меня, как работает второй ...
источник
<<2
запускает строку на следующей строке и*2
повторяет строкуДеление , 6 байт
Похоже, что сейчас это самый короткий «правильный» вопрос среди этих ответов.
объяснение
Поток управления начинается
R
с одного правого(1,0)
атома. Он"
переключается в режим печати, а затем оборачивается вокруг строки, печатая'!+OR
перед"
повторным нажатием и выходя из режима печати.Это оставляет
"
себя для печати. Кратчайший путь'"O
(где'"
масса атома устанавливается на код символа"
иO
печатается символ и уничтожается атом), но если бы мы это сделали, это"
помешало бы режиму печати. Таким образом, вместо этого мы устанавливаем значение атома'!
(на единицу меньше"
), затем увеличиваем с+
и затем печатаем результат сO
.альтернативы
Вот несколько альтернатив, которые длиннее, но, возможно, их методы вдохновляют кого-то находить более короткую версию, используя их (или, возможно, они будут более полезными в определенных обобщенных терминах).
8 байтов, используя
J
UMPОпять же, код начинается с
R
.@
Свопы массы и энергии , чтобы дать(0,1)
. ПоэтомуJ
атом заставляет прыгнуть черезO
прямой на"
. Затем, как и прежде, все, кроме"
, печатаются в строковом режиме. После этого атом попадает|
в обратное направление и проходит через'"O
печать"
. Пробел немного раздражает, но кажется необходимым, потому что в противном случае'
атом заставил бы рассматривать|
символ как символ, а не зеркало.8 байтов с использованием двух атомов
Это имеет два атома, начиная налево
L
и направо отR
. Левый атом получает свое значение,'"
которое затем сразу печатается с помощьюO
(и атом уничтожается). Для правого атома мы снова поменяем массу и энергию, перепрыгнем через,O
чтобы напечатать остальную часть кода в режиме печати. После этого его значение устанавливается с помощью,'L
но это не имеет значения, потому что атом отбрасывается;
.источник
'!+
кодирует"
.|R@JO"'
сработает, или вам все еще нужно это место после'
?'
первый.Кросс-браузерный JavaScript (41 символ)
Он работает в 5 лучших веб-браузерах (IE> = 8, Mozilla Firefox, Google Chrome, Safari, Opera). Введите его в консоль разработчика в любом из них:
Это не «обман» - в отличие от однобайтового квинуса Криса Джестера-Янга, так как его можно легко изменить, чтобы использовать
alert()
функцию (стоимостью 14 символов):Или преобразовать в букмарклет (стоимостью 22 символа):
источник
C
6460 байтПока что это самая короткая известная C-квина. Существует расширенная награда, если вы найдете более короткую.
Это работает в GCC , Clang и TCC в среде POSIX . Это вызывает чрезмерное количество неопределенного поведения со всеми из них.
Просто для удовольствия, вот репо, который содержит все известные мне C-квины. Не стесняйтесь раскошелиться / PR, если вы найдете или напишите другой, который добавляет что-то новое и креативное поверх существующих.
Обратите внимание, что он работает только в среде ASCII . Это работает для EBCDIC , но все еще требует POSIX . В любом случае, удачи в поиске среды POSIX / EBCDIC: P
Как это устроено:
main(s)
злоупотребляетmain
аргументами, объявляя практически нетипизированную переменнуюs
. (Обратите внимание, что наs
самом деле это не типизированный тип, но поскольку перечисленные компиляторы автоматически приводят его по мере необходимости, он также может быть *.)printf(s="..."
устанавливаетs
в предоставленную строку и передает первый аргументprintf
.s
установлен вmain(s){printf(s=%c%s%1$c,34,s);}
.%c
Установлен в ASCII34
,"
. Это делает возможным Quine. Теперьs
выглядит следующим образом :main(s){printf(s="%s%1$c,34,s);}
.%s
настроен наs
себя, что возможно благодаря # 2. Теперьs
выглядит следующим образом :main(s){printf(s="main(s){printf(s=%c%s%1$c,34,s);}%1$c,34,s);}
.%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 байтов:источник
s
имеет типint
, а не «нетипизированную переменную».s=3
очевидно, не будет работать, потому что вам нужно дважды передать строкуprintf
.Java, 528 байт:
Решение Java с оригинальным подходом:
в читаемой форме:
источник
if(++i==92)
,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(
.Цыпленок , 7
Нет, это не отражено напрямую :)
источник
chicken
!Retina ,
201497 байтПрежде чем мы начнем, я хотел бы упомянуть тривиальное решение файла, который содержит один
0
. В этом случае Retina попытается посчитать0
s в пустом входе, результатом которого также является0
. Хотя я не считаю это правильнымТак что вот правильный:
Попробуйте онлайн!
В качестве альтернативы мы могли бы использовать
;
вместо>
.объяснение
Программа состоит из одной замены, которую мы печатаем дважды.
В первой строке
`
отделяет конфигурацию от регулярного выражения, поэтому регулярное выражение пусто. Поэтому пустая строка (то есть несуществующий ввод) заменяется второй строкой, дословно.Чтобы напечатать результат дважды, мы обертываем его в два этапа вывода. Внутренний
\
печатает результат с завершающей строкой, а внешний>
печатает его без такового.Если вы немного знакомы с Retina, вам может быть интересно, что случилось с неявным выводом Retina. Неявный вывод Retina работает, заключая заключительный этап программы в выходной этап. Однако Retina не делает этого, если финальная стадия уже является выходной. Причина этого в том, что в обычной программе более полезно иметь возможность заменить неявный выходной каскад специальным, например,
\
или;
для одного байта (вместо того, чтобы избавляться от неявного и с помощью.
флага). К сожалению, это ведет к тому, что мы стоим нам два байта за квин.источник
Javascript (36 символов)
Это, AFAICT, самая короткая javascript quine, опубликованная до сих пор.
источник
a
, вы можете получить доступ к ее содержимому с помощью вызоваa.toString
.a
точно так же, как это было написано выше. Тем не менее, вывод этого кода, скорее всего, будет quine на любой реализации JavaScript.!function a(){alert("!"+a+"()")}()
.(a=()=>alert(
($ {a})))()
GolfScript, 8 байт
Я всегда думал, что самая короткая (истинная) квинта GolfScript была 9 байтов:
Где необходим завершающий перевод строки, потому что GolfScript печатает завершающий перевод строки по умолчанию.
Но я только что нашел 8-байтовую квинну, которая работает точно в соответствии с этим ограничением перевода строки:
Попробуйте онлайн!
Таким образом, выгода в том, что GolfScript не печатает завершающий перевод строки, но печатает содержимое
n
в конце программы. Это простоn
содержит перевод строки для начала. Таким образом, идея состоит в том, чтобы заменить это строкой":n`"
, а затем привести ее в строку , так что копия в стеке печатается с кавычками, а копия хранится вn
печатных изданиях без.Как отметил Томас Ква, 7-байтовый запрос CJam также может быть адаптирован к 8-байтовому решению:
Опять же, нам нужен завершающий перевод строки.
источник
Лабиринт ,
12411053 байтаСпасибо Sp3000 за игру в гольф с 9 байтами, что позволило мне сыграть еще 7.
Попробуйте онлайн!
объяснение
Лабиринт 101:
n*10 + <digit>
. Это позволяет легко накапливать большие числа. Чтобы начать новый номер, используйте_
, который толкает ноль."
нет опс.Сначала я объясню немного более простую версию, которая на байт длиннее, но немного менее волшебна:
Попробуйте онлайн!
Основная идея состоит в том, чтобы закодировать основную часть источника в одно число, используя некоторую большую базу. Затем этот номер можно легко распечатать обратно, прежде чем он будет декодирован для печати оставшейся части исходного кода. Декодирование - это просто повторное применение
divmod base
, где выведитеmod
и продолжайте работу сdiv
нулем.Избегая
{}
, самый высокий код символа, который нам нужен, равен_
(95), так что база 96 достаточна (если оставить базу низкой, число в начале будет короче). Итак, что мы хотим закодировать это:Превращая эти символы в их кодовые точки и рассматривая результат как число base-96 (с самой младшей цифрой, соответствующей
!
и самой старшей цифрой.
, потому что это порядок, в котором мы разберем число), мы получимТеперь код начинается с довольно крутого трюка (если можно так сказать), который позволяет нам напечатать кодировку и сохранить другую копию для декодирования с очень небольшими издержками: мы помещаем число в код в обратном порядке. Я вычислил результат с помощью этого скрипта CJam. Итак, давайте перейдем к реальному коду. Вот начало:
IP начинается в верхнем левом углу и идет на восток. Хотя он пробегает эти цифры, он просто строит это число поверх стека. Само число совершенно бессмысленно, потому что оно противоположно тому, что мы хотим. Когда IP-адрес попадает в
!
, этот номер извлекается из стека и печатает его. Это все, что нужно для воспроизведения кодировки в выводе.Но теперь IP зашел в тупик. Это означает, что он поворачивается и теперь возвращается на запад (без
!
повторного выполнения ). На этот раз удобно, чтобы IP считывал число задом наперед, так что теперь число на вершине стека действительно кодирует оставшуюся часть источника.Когда IP-адрес снова попадает в верхний левый угол, это не тупик, потому что IP-адрес может повернуть налево, поэтому он делает это и теперь движется на юг. Это
"
запрет, который нам нужен здесь, чтобы отделить число от основного цикла кода. Говоря о которых:Пока вершина стека еще не равна нулю, IP будет проходить через этот довольно плотный код в следующем цикле:
Или выложены линейно:
Причина, по которой это происходит, заключается в семантике потока управления Лабиринта. Когда в текущей ячейке есть по крайней мере три соседа, IP будет поворачиваться влево при отрицательном значении стека, переходить в ноль и поворачиваться направо при положительном значении стека. Если выбранное направление невозможно из-за наличия стены, вместо этого IP будет использовать противоположное направление (поэтому в коде есть два левых поворота, хотя вершина стека никогда не бывает отрицательной).
Сам код цикла на самом деле довольно прост (сжатие этого не было и есть основной вклад Sp3000):
При
N
достижении нуля поток управления меняется. Теперь ИП хотел бы двигаться прямо после/
(то есть на запад), но там есть стена. Так что если вместо поворота (восток) выполняется6
снова. Это делает вершину стека положительной, поэтому IP поворачивается направо (на юг) и выполняет9
. Вершина стека сейчас69
, но все, что нас волнует, это то, что это положительно. IP делает еще один поворот направо (запад) и движется к тому,@
который завершает код.В общем, довольно просто на самом деле.
Хорошо, теперь, как мы можем сбрить этот дополнительный байт. Понятно, что эта операция кажется бесполезной, но нам нужна эта дополнительная строка: если бы цикл был рядом с номером, IP-адрес уже сразу переместился бы туда, а не пересекал все число. Так что мы можем сделать что-то полезное с этим без операции.
Ну, в принципе, мы можем использовать это для добавления последней цифры в кодировку. Кодирование не действительно должны быть все на первой линии ...
!
только гарантирует , что все , что есть там и получает там печататься.Хотя есть одна загвоздка, мы не можем просто сделать это:
Проблема в том, что теперь мы изменили на
"
a3
, что также меняет фактическое число, которое мы хотим получить. И конечно же, это число не заканчивается3
. Поскольку число полностью определяется кодом, начиная с,!
мы ничего не можем с этим поделать.Но, может быть, мы можем выбрать другую цифру? Нам не важно, есть ли
3
в этом месте, если мы получим число, которое правильно кодирует источник. Ну, к сожалению, ни одна из 10 цифр не дает кодировки, чьи наименее значимые цифры соответствуют выбранным. К счастью, в оставшейся части кода есть некоторая свобода действий, так что мы можем попробовать еще несколько кодировок, не увеличивая количество байтов. Я нашел три варианта:@
на/
. В этом случае мы можем использовать любую цифру1357
и получить соответствующую кодировку. Однако это будет означать, что программа завершается с ошибкой, которая допускается, но не кажется очень чистой._
). 26 вариантов дает множество возможностей. Например, дляA
любой нечетной цифры работает. Это немного приятнее, но все же это не кажется таким уж изящным, поскольку вы никогда не использовали бы букву в реальном коде.1
, кодировка также заканчивается1
. Это единственное решение среди баз 96, 97, 98, 99, так что это действительно очень удачно. И вот как мы в конечном итоге с кодом в верхней части этого ответа.источник
Потерянный ,
293262249 байтПопробуйте онлайн!
объяснение
Весь этот проект был вверх и вниз. Я продолжал думать, что это невозможно, и затем придумал сумасшедшую идею, которая могла бы сработать.
Почему Lost Quine так сложно?
Как вы, возможно, знаете, Lost - это двумерный язык программирования, где начальное местоположение и направление абсолютно случайны. Это делает написание любой потерянной программы столь же сложной, как написание кода, защищенного от радиации. Вы должны рассмотреть все возможные места и направления.
При этом есть несколько стандартных способов сделать что-то. Например, вот стандартный способ печати строки.
Это внизу поток сбора, который захватывает большинство ips и тянет их к месту старта. Как только они достигают начального местоположения (вверху слева), мы очищаем их с помощью цикла, избавляясь от всех значений в стеке, затем поворачиваем безопасность, нажимаем на строку и выходим. (безопасность - это уникальная концепция. Потерянная каждая программа должна нажать
%
перед выходом, это предотвращает возможность ее завершения при запуске). Теперь моя идея состоит в том, чтобы расширить эту форму до полноценной муки.Первое, что нужно было сделать, это немного переработать цикл, существующий цикл был специфичен для формата String.
Нам нужно добавить второй поток, чтобы избежать возможности
!
перепрыгнуть через поток и создать цикл.Теперь мы хотим смешать это со стандартным форматом Quine. Так как Lost в значительной степени основан на Кляйне, я в
основном укралзаимствованную Клиен Куайн для Мартина Эндера .Это довольно удобно печатает первую строку quine. Теперь все, что нам нужно сделать, это жестко закодировать потоки. Ну, это легче сказать, чем сделать. Я попробовал примерно четыре разных способа сделать это. Я просто опишу тот, который работал.
Идея здесь состоит в том, чтобы использовать двери, чтобы получить желаемое количество стрелок. Дверь - это специальный тип зеркала, которое меняется при каждом ударе.
[
отражает ips, идущий слева и]
справа. Когда они попадают по ip с любой из этих сторон, переключите ориентацию. Мы можем составить линию из этих дверей и статического отражателя для многократного выполнения операции.Будем выступать
:
трижды. Таким образом, если мы поместим a<
в стек перед раздачей, мы сможем создать множество из них с меньшим количеством байтов. Мы делаем 2 из них, по одному для каждой строки, и между ними мы устанавливаем новую строку, однако второй нужно идти только до тех пор, пока она не покроет!
добавленную нами, все остальное можно оставить пустым, сэкономив нам несколько байтов. Хорошо, теперь нам нужно добавить вертикальные стрелки в наши потоки. Вот тут-то и происходит оптимизация ключа. Вместо того, чтобы перенаправлять все ips на «запуск» программы напрямую, мы вместо этого перенаправим их в крайний левый угол, потому что мы уже знаем, что ips, начинающийся в крайнем левом углу, долженработать (или, по крайней мере, будет работать в окончательной версии), мы также можем просто перенаправить другие ips. Это не только делает его дешевле в байтах, я думаю, что эта оптимизация делает то, что возможно.Однако все еще есть некоторые проблемы, наиболее важными из которых являются ips, запускаемые после
>
нажатия, но до того, как мы начнем копировать их. Такие ips войдут в копир и сделают несколько копий 0. Это плохо, потому что наш механизм очистки стека использует нули для определения дна стека, оставляя целую кучу нулей внизу. Нам нужно добавить более сильный метод очистки стека. Поскольку нет реального способа узнать, пуст ли стек, нам просто придется попытаться уничтожить как можно больше элементов в стеке. Здесь мы снова будем использовать метод двери, описанный ранее. Мы добавим((((((((((([[[[[[[[[[[[[[
в конец первой строки сразу после sanitizor избавиться от нулей.Теперь есть еще одна проблема, так как мы перенаправили наши потоки на верхний левый ips, начиная с
%
и, двигаясь вниз, уже отключили безопасность и преждевременно выйдут. Поэтому нам нужно отключить безопасность. Мы делаем это, добавляя#
к потоку, таким образом, ips, проходящий через поток, будет отключен, но ips, которые уже были очищены, не будет. Также#
должен быть жестко закодирован в первой строке.Вот и все, надеюсь, вы понимаете, как это работает сейчас.
источник
Да ,
1165879606561540522498 + 7 = 505 байтовТребуется
-cheat
флаг, чтобы разрешить определение псевдонимов.Попробуйте онлайн!
объяснение
Есть две части к этому (как с большинством quines). Данные:
И декодер:
Данные представляют собой просто двоичное кодирование декодера (или, скорее, его обратное). Каждый
0
начинает новый символ, а1
s и2
s0
- и1
-биты, соответственно.Обратите внимание, что
0
это стандартная команда Yup, которая выдвигает ноль,1
и2
пока не определена. Тем не менее, мы назначаем всю часть данных команде,%
так что1
и2
может оставаться неопределенным до%
фактического использования.Далее мы определим еще несколько команд:
<
уменьшает вершину стека,>
увеличивает его.1
(несколько не интуитивно) удваивает вершину стека.2
удваивает, а затем увеличивает его. Благодаря этим определениям что-то подобное0221111
фактически оставит 48 (110000 в двоичном виде) в стеке.Оставшиеся 32 байта выполняют фактическое декодирование в двух частях. Сначала нам нужно восстановить строку данных.
И, наконец, мы снова отправляем данные и печатаем каждое значение как символ:
Для дальнейшего использования вот сценарий CJam для кодирования данных.
источник
Fueue , 423 байта
Fueue - основанный на очереди esolang, в котором запущенная программа является очередью.
Попробуйте онлайн!
Как это устроено
Это объяснение
может или не можетвыйти из-под контроля. С другой стороны, я не знаю, как объяснить это намного короче, как я надеюсь, что люди могут следовать.Fueue шпаргалка
Смотрите статью esolang wiki для подробностей, включая некоторые функции, не используемые в этой программе.
Начальная программа - это начальное состояние очереди, которое может содержать следующие элементы:
+*/-%
: целочисленная арифметика (-
унарно,%
логическое отрицание). Инертен, если не дано число аргументов.()<
: поместить элемент в скобки, убрать скобки из блока, добавить последний элемент в блок. Последние два являются инертными, если за ними не следует блок.~:
: swap, дублировать$
: копия (занимает число + элемент). Инертен перед не номером.H
: остановить программу.Обратите внимание, что в то время как
[]
гнездо,()
не надо - последние просто отдельные функции.Синтаксис трассировки выполнения
Пробел необязателен в Fueue, кроме цифр. В следующих трассах выполнения он будет использоваться, чтобы предложить структуру программы, в частности:
Фигурные скобки
{}
(не используются в Fueue) используются в трассировках для представления целочисленного результата математических выражений. Это включает в себя отрицательные числа, так как Fueue имеет только неотрицательные литералы --
это функция отрицания.Различные мета-переменные имена и
...
используются для обозначения значений и сокращений.Задержка тактики
Интуитивно понятно, что выполнение циклически повторяется вокруг очереди, частично изменяя то, через что она проходит. На результаты функции нельзя воздействовать снова до следующего цикла. Различные части программы эффективно развиваются параллельно, если они не взаимодействуют.
В результате большая часть кода посвящена синхронизации, в частности задержке выполнения частей программы до нужного времени. Существует множество вариантов игры в гольф, что превращает эти части в нечитаемые капли, которые можно понять, только проследив за их циклом выполнения.
Эта тактика не всегда будет индивидуально упомянута ниже:
)[A]
задержкиA
на цикл. (Вероятно, самый простой и читаемый метод.)~ef
переставляет элементыe
иf
который также задерживает их выполнение. (Вероятно, наименее читаемый, но часто самый короткий для незначительных задержек.)$1e
задерживает один элементe
.-
и%
полезны для задержки чисел (последний для0
и1
.):
или$
может быть использовано для их создания из одного.(n
Заворачиваетn
в скобки, которые впоследствии могут быть удалены по желанию. Это особенно важно для числовых вычислений, поскольку числа слишком нестабильны, чтобы их можно было скопировать без предварительного помещения их в блок.Общая структура
Остальная часть объяснения разделена на семь частей, каждая для части работающей программы. Большие циклы, после которых большинство из них повторяются, будут называться «итерациями», чтобы отличать их от «циклов» одиночных проходов по всей очереди.
Вот как исходная программа делится между ними:
Большая цифра в конце программы кодирует остаток в обратном порядке, две цифры на символ, причем 30 вычитается из каждого значения ASCII (например,
10
кодирует(
.)На более высоком уровне вы можете думать о данных в этой программе (начиная с bignum) как о потоках справа налево, а о контроле - слева направо. Однако на более низком уровне Fueue постоянно запутывает различие между кодом и данными.
0
в качестве целого числа48
), сначала выделяя младшие значащие цифры. Он производит одну цифру каждые 15 циклов.[x[y]]
, а также печатая закодированный символ каждой пары.[x[y]]
блоков таким образом, что после того, как он содержит все цифры, его можно запустить, чтобы распечатать все из них, а затем остановить всю программу.Раздел А
Раздел A управляет планированием конца программы. Требуется 4258 циклов, чтобы перейти к одной функции подкачки
~
, которая затем выполняет настройку секции B, которая останавливает свой основной цикл и вместо этого начинает работу секции D.$
Функция создает 4255 копии следующих в%
то время как(
оборачивает~
в скобках.%
используется для переключения следующего числа между0
и1
.%
s израсходованы,$1
создается 1 копия[~]
(фактически NOP), а в следующем цикле)
удаляются скобки.Раздел Б
Раздел B обрабатывает сам себя, а также новую итерацию раздела C каждые 30 циклов.
:
Дублирует большой блок следующий (один экземпляр сокращенно[BkB]
), а затем)
удаляет скобку из первой копии.$$24%%0
устанавливает обратный отсчет, аналогичный тому, который указан в разделе А.:<
превращается в два блока<<
и~
меняет их местами, последний размещает код для нового раздела C.<
функции упаковывают два последних блока в первый - это избыточно в обычных итерациях, но позволит~
разделу А выполнить свою работу в конце.)
удаляются внешние скобки. Далее~:)
превращается в):
и~)
меняет местами)
на начало раздела C кода.)
собирается снять скобки, чтобы начать новую итерацию раздела C.На заключительной итерации
~
секция A появляется в точке (1) выше:В
~
свопы)
через блок и в секции С, предотвращая раздел В от быть снова запустить.Раздел С
Секция C обрабатывает слияние новых пар цифровых символов в блок секции D, а также создает новые итерации секции E.
Ниже показана типичная итерация с кодами ASCII цифр
x
и ихy
представление. На самой первой итерации входящие элементы «D» и «E» являются начальными[H]
и-
вместо этого, так как ни один из предыдущих разделов E не выполнялся, чтобы создать какие-либо пары цифр.~
в строке, строка будет уменьшаться примерно до 2/3 каждого цикла (потому что один~
меняет местами два следующих), но иногда с остатком~
s, которыйнаносит ущербтщательным манипуляциям с последующим.$11~
производит такой ряд. Следующий~
меняет местами<
следующий блок. Другой<
в конце добавляет новый блок пары цифр (цифры x и y как коды ASCII) в блок секции D.~
строки есть~~
остаток, который заменяет~
следующий)
. Другой<
добавляет раздел D в[)))~]
блок.~
местами следующий блок с новым кодом раздела E в блоке раздела D. Тогда новый остаток~
обменивает)
поперек, и , наконец, последний~~
в~
ряду своп один из них через к секции Е так же , как)
снял свои квадратные скобки.В последней итерации секция A
~
поменялась местами)
через секцию B и секцию C. Однако секция C настолько недолговечна, что уже исчезла, и)
заканчивается в начале секции D.Раздел D
В разделе D распечатывается последняя большая цифра и останавливается программа. На протяжении большей части работы программы это инертный блок, в котором секции B – G взаимодействуют при сборке.
(
функция остановки заключаетH
в скобки.-
Следующим образом , он будет использоваться как фиктивный элемент для первой итерации вместо цифр пары.[49[49]]
соответствует последней11
цифре.[49[48]]
(соответствующая10
в начале цифры) на самом деле не включена в блок, но это не имеет никакого значения , как)[A[B]]
и)[A][B]
эквивалентны, и превращается вA[B]
.После последней итерации происходит
)
переключение вправо из секции B, и блок секции D деблокируется. В)))~
начале каждого подблока убедитесь, что все части выполнены в правильном порядке. Наконец, самый внутренний блок содержитH
остановку программы.Раздел Е
В разделе E обрабатываются пары пар цифр ASCII, создаваемых секцией G, и оба печатают соответствующий кодированный символ и отправляют блок с объединенной парой влево в секции C и D.
Снова ниже показана типичная итерация с
x
иy
представляющая коды ASCII цифр.10*x+y-498
значения ASCII закодированного символа.498 = 10*48+48-30
, То48
s отменить ASCII кодировкуx
и вy
то время как30
сдвигает кодирование от00–99
до30–129
, которая включает в себя все печатаемые ASCII.Раздел F
Раздел F состоит из инертных блоков, содержащих ASCII-коды цифр. Для большей части запуска программы здесь будет не более двух, поскольку секция E потребляет их с той же скоростью, с которой их производит G. Однако на заключительном этапе печати
0
здесь будут собираться лишние цифры.Раздел G
Раздел G обрабатывает разбиение большого числа в конце программы, сначала младшие значащие цифры, и отправку блоков с их кодами ASCII влево в другие разделы.
Так как у него нет проверки остановки, он фактически продолжит
0
генерировать цифры, когда число будет уменьшено до 0, пока секция D не остановит всю программу с помощьюH
функции.[BkG]
сокращает копию большого блока начального кода, который используется для саморепликации для запуска новых итераций.Инициализация в первых циклах:
Типичная итерация,
N
обозначает число для разделения:+:5
вместо--10
задержки10
два цикла. Увы10
, этому помог только один из участников программы.[N]
И[BkG]
блоки дублируются, то один экземплярN
делится10
.[{N/10}]
дублируется, тогда для вычисления кода ASCII последней цифрыN
as используется больше арифметических функций48+((-10)*(N/10)+N)
. Блок с этим кодом ASCII оставлен для секции F.[{N/10}]
обменивается между[BkG]
блоками, чтобы установить начало новой итерации.Bonus Quine (540 байт)
Попробуйте онлайн!
Поскольку я не был уверен, какой метод будет самым коротким, я сначала попытался кодировать символы в виде двузначных чисел, разделенных символом
(
s. Базовый код немного короче, но более полное представление данных на 50% компенсирует это. Не так хорошо, как в других, потому что я остановился, когда понял, что это не победит. У него есть одно преимущество: оно не требует реализации с поддержкой bignum.Его общая структура чем-то похожа на основную. Раздел G отсутствует, поскольку представление данных заполняется непосредственно в разделе F. Однако в разделе E необходимо выполнить аналогичный расчет divmod для восстановления цифр двузначных чисел.
источник
)$n[)](
короче байта для счетчика задержки.Желе, 3 байта
Попробуйте онлайн!
верификация
Как это устроено
источник
LANG=en_US
достигается именно этим. tio.run/nexus/bash#@@/…