Это было удивительно сложно, и я не уверен, что это оптимально ...
<.@!$?
После дополнения и развертывания кода это представляет следующую шестнадцатеричную сетку:

При этом используется тот же поток управления, что и в моей недавней безошибочной программе для кошек , движущейся по антидиагоналам. Чтобы добиться этого, мы начинаем с отклонения указателя инструкций (IP) влево, где фиолетовый путь оборачивается в нижний левый угол.
?читает входные данные как целое число. !печатает его обратно. .это просто неоперация. Теперь угол сетки действует как ветвь:
Если вход был 0, IP будет продолжаться по красной дорожке, которая просто завершает программу с @.
Если вход был 1, IP будет продолжаться по зеленому пути. Опять же, .это просто запрет, но $это эквивалент батута Бефунге: он пропускает следующую инструкцию. После переноса следующей инструкцией будет ?, но из-за $выполнения фактически продолжается синий путь, начиная с !печати другой копии 1. Этот цикл, который только содержит !..$, теперь повторяется бесконечно.
Исследование потока управления в шестиугольнике ...
Я считаю, что вышеуказанное решение является оптимальным. Я написал брутфорсер, который проверяет все 6-байтовые программы Hexagony, которые содержат по крайней мере одну из них ?!@(которые необходимы; я также проверил :и %вместо того, @чтобы завершить с ошибкой деления на ноль, но это тоже не помогло). Проверка печатает все программы, которые a) выдают 0на входе 0и завершают, и b) выдают по крайней мере два 1с (и ничего больше) и не завершаются в течение первых 60 тактов программы (200 тактов для 5-байтовых решений) , Я сомневаюсь, что любое правильное решение потребовало бы более 200 тиков, чтобы правильно напечатать первое 0или второе 1на такой маленькой сетке, поэтому я не думаю, что упустил какие-либо потенциальные решения.
Поиск не дал никаких результатов для 5 байтов, но 57 результатов для 6 байтов (используя @; нет необходимости завершать с ошибкой, если мы можем решить это чисто в том же количестве байтов). Из этих 57 только 6 были ложными срабатываниями, которые фактически напечатали только два 1с, а затем вошли в бесконечный цикл, не печатая больше. Одно решение было указано дважды, поскольку оно содержало две !команды. Это оставляет ровно 50 действительных решений.
Существует определенная степень вырождения между решениями, в которых один или два символа несущественны, например потому, что они в любом случае фактически не работают. Решения могут быть сгруппированы в 23 набора действительно различных программ (в некоторых случаях разница между двумя наборами составляет всего один символ, но это существенно меняет поток управления, поэтому я их подсчитал отдельно). Две группы даже используют несколько указателей инструкций очень неожиданным образом. Поскольку я никогда не смог бы придумать большинство из этих способов использования ветвей и зеркал, они очень интересно изучают, какие виды управления потоками возможны в гексагонии, и я определенно изучил некоторые новые приемы для будущих гольфов.
Общий поток управления почти всегда одинаково: читать номер, распечатать его. Если это 0найти путь к @, если нет, продолжайте циклически проходить !при сохранении значения ребра 1. Есть четыре заметных исключения:
- Одно решение (одно с двумя
!) печатает два 1s за итерацию по сетке, поэтому печатает примерно в два раза быстрее, чем большинство программ. Я отметил это x2ниже.
- Несколько решений (те , которые содержат
o) заменить 1с 111(символьным кодом o), поэтому они печатают три 1 с на итерацию, что делают их напечатать примерно в три раза быстрее, чем в большинстве программ. Я пометил их x3ниже.
- Два решения добавляют a
1к значению ребра в каждой итерации (так 1-> 11-> 111-> ...). Они печатаются очень быстро, но со временем у них заканчивается память. Я пометил их OoMниже.
- Два решения входят в очень узкую петлю, которая просто подпрыгивает вперед и назад
!, печатая на каждом другом тике (вместо каждого 5-го или около того), что делает их немного быстрее (и аккуратнее). Я пометил их ><ниже.
Так вот и весь зоопарк:
#1 #5 #12 #19
?!/$.@ ?$!>$@ .?!/$@ |!|?$@ # ><
?!/$1@ # OoM ?$!|$@ =?!/$@
?!/$=@ #20
?!/$\@ #6 #13 $@.?<!
?!/$o@ # x3 ?/!<|@ .?/!$@ $@1?<! # OoM
?!/$!@ # x2 =?/!$@ $@=?<!
#7 $@o?<! # x3
#2 ?\!<|@ #14
?!>$)@ \!?__@ #21
?!>$1@ #8 _>_!?@
?!>$o@ # x3 ?<!>$@ # >< #15
?!|$)@ \_?!$@ #22
?!|$1@ #9 <!@.$?
?!|$o@ # x3 ?\$!@$ #16 <!@/$?
\_?!_@ <!@=$?
#3 #10 <$@!$?
?!|)$@ ?~#!@) #17 <.@!$?
?!|1$@ ?~#!@1 $$?\@! </@!$?
?!|o$@ # x3 <=@!$?
#11 #18
#4 ?$)\@! \$?\@! #23
?_!<@> ?$1\@! <<@]!?
?$o\@! # x3
Ниже приведен краткий обзор нескольких наиболее представительных групп. Особенно группы 10 и 23 стоит проверить. В других группах есть много других интересных и порой запутанных путей, но я думаю, что в конце этого вам достаточно скучно. Для тех, кто действительно хочет изучать гексагонию, их, безусловно, стоит исследовать, поскольку они демонстрируют еще более возможное использование зеркал и $.
Группа 1
Это не намного сложнее, чем мое первоначальное решение, но пути идут в разных направлениях. Это также учитывает наибольшее количество вариантов в одной ячейке, так как самый правый неоперативный объект может быть заменен 5 различными командами, которые все еще делают это действительным без изменения структуры:

Группа 2
Этот довольно интересный, потому что он движется только горизонтально. После перехода к >IP-адрес сразу же меняется на противоположный, принимая ветку в углу. Это не совсем хорошо видно на диаграмме, но в случае 1мы снова пересекаем первый ряд, но на этот раз в обратном направлении. Это также означает, что мы сталкиваемся ?снова, который теперь возвращает 0(EOF). Это исправлено с )(приращением), чтобы сохранить печать 1s. Это также имеет 5 вариантов, которые )также могут быть 1или o, и >также могут быть |:

Группа 3
Это выглядит почти идентично предыдущему, но чертовски грязно. До удара, |а затем прохождения нижнего или верхнего ряда это то же самое. Но в случае цикла, $теперь пропускается ) на зеркало. Таким образом, мы идем по бирюзовой дорожке направо, теперь нажимаем на приращение, пропускаем все @до того, как | снова обернемся, а затем возвращаемся к зеленой дорожке наверху.

Группа 4
Я думал, что это было особенно изящно:

_Зеркало в верхнем правом углу не является изначально не-оп, поэтому мы печатаем с !и ударил <. Теперь 0путь попадает в горизонтальное зеркало и заканчивается. 1Путь занимает очень интересную траекторию , хотя: она отклоняется вниз, заворачивает к !, перенаправляется в сторону по горизонтали , а затем заворачивает назад к ! снова . Затем он продолжает двигаться в форме ромба, печатая дважды за итерацию (каждый третий тик).
Группа 8
Это одно из двух решений с очень плотным циклом печати:

В <выступает в качестве филиала. После оборачивания дважды, 0удары @. 1с другой стороны, сначала пропускает ?, затем снова >отправляет его на $, то есть пропускает @. Затем IP оборачивается в бирюзовый путь, где он подпрыгивает назад и вперед между >и <(обтекание края между ними).
Группа 10
Одна из двух групп, которые используют другие указатели инструкций, и это абсолютно красиво. Гексагония имеет 6 - каждый начинается с другого угла по краю по часовой стрелке, но одновременно активен только один из них.

Как обычно, мы читаем с ?. Теперь ~унарное отрицание: оно превращается 1в -1. Далее мы попали #. Это один из способов переключения между IP-адресами: он принимает текущее граничное значение по модулю 6 и переключается на соответствующий IP-адрес (IP-адреса нумеруются 0по часовой стрелке). Так что, если вход был 0, то IP просто остается прежним, и скучно идет прямо вперед !@. Но если вход был 1, то текущее значение, -1которое есть 5 (mod 6). Поэтому мы переключаемся на IP, который начинается в той же ячейке (зеленый путь). Сейчас #не работает и ?устанавливает край памяти на 0. )увеличивает, так что !печатает 1. Теперь мы ~снова ударили, чтобы убедиться, что#до сих пор не работает (в отличие от переключения на IP 1, который завершит программу). Удивительно, насколько хорошо все сочетается в этой маленькой программе.
Группа 22
Просто отметим, что это группа, в которой находится мое первоначальное решение. Это также самая большая группа, потому что no-op может находиться в двух разных местах, и есть несколько вариантов для действительной (действующей no-op) команды.
Группа 23
Это другая группа, использующая несколько IP-адресов. На самом деле этот использует 3 разных IP. В верхнем правом углу немного беспорядка, но я постараюсь провести вас через это:

Итак, начало, которое вы видели раньше: <отклоняет северо-восток, ?читает ввод. Теперь ]есть еще один способ переключения между IP-адресами: он передает управление следующему IP-адресу по часовой стрелке. Таким образом, мы переключаем управление на бирюзовый путь, который (я знаю, что это трудно увидеть) начинается в северо-восточном углу юго-востока. Это сразу же отражается <тем, что оно охватывает юго-восточный угол, идущий на северо-запад. Это также ударил, ]поэтому мы переключаемся на следующий IP. Это серая тропа, начинающаяся в восточном углу и идущая на юго-запад. Он печатает ввод, затем переносится в северо-восточный угол. <отклоняет путь в горизонтальное положение, где он отражается другим < . Теперь правая рука<действует как ветвь: если вход был 0, IP перемещается на северо-восток и переносится на @. Если вход был 1, IP перемещается в !, оборачивается в левую и <там, где он отражается ... теперь в углу, он оборачивается обратно в !, отклоняется вправо <, отражается слева <и начинается путь над...
Довольно беспорядок, но красивый беспорядок. :)
Диаграммы, созданные с помощью удивительного HexagonyColorer Тимви .