これは驚くほどトリッキーで、最適だとは思いません...
<.@!$?
コードのパディングと展開後、これは次の16進グリッドを表します。

これは、対角線に沿って移動する、最近のエラーのないcatプログラムのような同様の制御フローを使用します。それを達成するために、紫色のパスが左下隅に回り込むように、命令ポインター(IP)を左にそらすことから始めます。
?
入力を整数として読み取ります。!
それを印刷します。.
無操作です。これで、グリッドのコーナーがブランチとして機能します。
入力がの0
場合、IPは赤いパスに沿って続行し@
ます。これは単にでプログラムを終了します。
入力がの1
場合、IPは緑のパスで続行します。繰り返しますが、これ.
は単なる操作ではありません$
が、Befungeのトランポリンと同等です。次の命令をスキップします。ラップした後、次の命令はになりますが?
、$
実行により、実際には青いパスで続行され、の!
別のコピーの印刷から始まり1
ます。のみを含むこのループ!..$
は、無期限に繰り返されます。
六角形の制御フローの研究...
上記のソリューションが最適だと思います。私はブルートフォーサーを作成しました。これは、少なくとも1つ?!@
(必要です。チェック:
し%
、@
ゼロ除算エラーで終了する代わりに)を含む、すべての6バイトのHexagonyプログラムをチェックしますが、それも助けにはなりませんでした)。このチェックは、a)0
入力で生成して0
終了し、b)少なくとも2つ1
(およびそれ以外)を生成し、プログラムの最初の60ティック(5バイトソリューションでは200ティック)以内に終了しないすべてのプログラムを印刷します。。有効な解決策では、このような小さなグリッドで最初0
または2番目を正しく印刷するのに200ティック以上かかる1
とは思わないので、解決策を逃したとは思わない。
検索では5バイトの結果は得られませんでしたが、6バイトでは57の結果が得られます(@
同じバイト数で問題なく解決できれば、エラーで終了する必要はありません)。それらの57のうち6つだけが誤検知で、実際には2つしか印刷されず1
、それ以上印刷せずに無限ループに入りました。2つの!
コマンドが含まれていたため、1つのソリューションが2回リストされました。有効なソリューションは正確に50個です。
1つまたは2つのキャラクターが実質的ではないソリューションの間には、ある程度の縮退があります。たとえば、とにかく効果的にノーオペレーションです。ソリューションは23セットのまったく異なるプログラムにグループ化できます(場合によっては、2セットの間に文字の違いが1つしかありませんが、制御フローが大幅に変更されるため、個別にカウントしました)。2つのグループは、非常に予期しない方法で複数の命令ポインターを使用します。ブランチとミラーを使用するこれらの方法のほとんどを思いつかなかったので、これらは六角形でどのような制御フローが可能かについて非常に興味深い研究を行い、将来のゴルフのためのいくつかの新しいトリックを間違いなく学びました。
全体的な制御の流れは、ほぼ常に同じです:番号を読んで、それを印刷します。それはだた場合0
への道を見つけること@
をループ保持しない場合、!
のエッジ値をmainting中1
。4つの注目すべき例外があります。
- 1つのソリューション(2のあるソリューション)は、グリッドを介して反復ごとに
!
2 1
秒を印刷するため、大部分のプログラムの約2倍の速度で印刷されます。これにx2
以下のマークを付けました。
- いくつかのソリューション(含むものは
o
)置き換える1
と111
(の文字コードo
)ので、彼らは印刷3 1
彼らが早くプログラムの過半数の3倍程度に印刷すること、反復ごと秒。これらをx3
以下でマークしました。
- 2つのソリューションは、各反復でエッジ値にa を追加し
1
ます(つまり、1
-> 11
-> 111
-> ...)。これらは非常に高速に印刷されますが、最終的にはメモリ不足になります。これらをOoM
以下でマークしました。
- 2つのソリューションは非常にタイトなループに入り、単に
!
5回ごとではなく1刻みごとに前後にバウンドします。これにより、わずかに高速になります。これらを><
以下でマークしました。
ここに動物園全体があります:
#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つの異なるコマンドで置き換えることができるため、1つのセルで最大数のバリエーションが可能になります。

グループ2
これは水平方向にしか移動しないため、非常に興味深いものです。にラップした>
後、IPはすぐに反転し、角にある枝を取ります。ダイアグラムが完全に見えないわけではありません1
が、最初の行をもう一度走査する場合、今回は逆方向に走査します。これはまた?
、再び0
(EOF)を返すことを意味します。これは)
、印刷を維持するために(増分)で修正されます1
。これは、また、5つのバリエーションがあり)
、また可能性があり1
、またはo
、及び>
またあり得ます|
。

グループ3
これは前のものとほとんど同じに見えますが、地獄のように面倒です。|
最下行または最上行をヒットしてからトラバースするまでは同じです。しかし、ループの場合は、$
今をスキップ)
上にミラー。だから我々は、スキップ、今増分を打つ、右にターコイズパスをたどる@
我々はラップアラウンドする前に|
もう一度とその後、上部の緑道に戻ります。

グループ4
これは特に気の利いたものだと思いました。

_
右上隅のミラーは、最初は何も操作していません。そのため、で印刷して!
を押します<
。0
パスは今、水平ミラーに当たると終了します。しかし、この1
経路は非常に興味深い軌道をたどります。下に曲がり、折り返し!
、水平方向にリダイレクトされ、!
再び折り返します。その後、この菱形の形状で動き続け、反復ごとに2回(3目盛りごとに)印刷します。
グループ8
これは、非常にタイトな印刷ループを持つ2つのソリューションの1つです。

<
ブランチとして機能します。2回ラップした後、を0
押し@
ます。1
一方、最初にをスキップし?
、次にに>
送信します。$
そのため、がスキップされ@
ます。その後、IPは、前後間のバウンスターコイズ路にラップ>
と<
(その間のエッジの周りにラッピング)。
グループ10
他の命令ポインターを使用する2つのグループのうちの1つ。六角形には6があります。それぞれが時計回りのエッジに沿って異なるコーナーから始まりますが、一度にアクティブになるのはそのうちの1つだけです。

いつものように、で読みます?
。今~
単項否定である:それはターン1
へ-1
。次に、を押します#
。これは、IPを切り替える1つの方法です。現在のエッジ値をモジュロ6で取り、対応するIPに切り替えます(IPは0
時計回りに番号が付けられます)。入力がの場合、0
IPは単純に同じままで、退屈にまっすぐに進み!@
ます。ただし、入力がの場合、1
現在の値は-1
である5 (mod 6)
。したがって、まったく同じセル(緑色のパス)で開始するIPに切り替えます。今#
は何もしないで?
、メモリエッジをに設定します0
。)
増分するため、を!
出力し1
ます。今、~
もう一度ヒットして#
(プログラムを終了するIP 1に切り替えるのとは対照的に)それでも操作は行われません。この小さなプログラムですべてがうまく調和するのは驚くべきことです。
グループ22
ただ、これは私の元のソリューションが属するグループです。また、no-opは2つの異なる場所にある可能性があり、実際の(効果的なno-op)コマンドにはいくつかの選択肢があるため、最大のグループになります。
グループ23
これは、複数のIPを使用するもう1つのグループです。実際、これは3つの異なるIPを使用します。右上隅は少し混乱していますが、これについて説明します。

だから、あなたが前に見た始まり:<
北東をそらし、?
入力を読む。これ]
はIPを切り替えるもう1つの方法です。時計回りに次のIPに制御を渡します。そこで、制御を、ターコイズブルーのパス(見づらいことは知っていますが)に切り替えます。すぐに反映される<
ので、南東の角に回り込んで北西に向かいます。また、ヒットする]
ため、次の IPに切り替えます。これは、東の角から始まり、南西に向かう灰色の道です。入力を出力し、北東の角に折り返します。<
パスを水平方向に偏向し、そこで他 のパスに反映され<
ます。今右<
ブランチとして機能します。入力がの0
場合、IPは北東に移動し、にラップします@
。入力がの1
場合、IPはに移動し、!
lef-thandに折り返され<
、そこで反射されます...今、コーナーで!
折り返され、右に偏向<
され、左に反射され<
、パスが開始されます以上...
かなり混乱しているが、美しい混乱。:)
Timwiの驚くべきHexagonyColorerで生成されたダイアグラム。