XORソリューションに必要なインスピレーションを提供してくれたFryAmTheEggmanに感謝します。
0000 !@
0001 ?.|@!
0010 #?#!)@
0011 ?!@
0100 +?|@!?
0101 ??!@
0110 ?<@!!<_\~(
0111 ?<<@!
1000 )\!#?@{
1001 (~?/@#!
1010 ??|@!)
1011 \#??!1@
1100 ?(~!@
1101 ?.|@!)
1110 ?$@#)!<
1111 1!@
すべてのプログラム0
はfalseおよび1
trueに使用します。
オンラインでお試しください!これはテストスイートではありません。さまざまなプログラムや入力を自分でコピーする必要があります。
上記の解決策は、2バイト以内の最適化です(真実/偽の解釈を緩和しない限り)。サイドレングス2に適合するすべてのプログラム、つまり最大7バイト(完全にすべてのプログラムではない-すべての有効なプログラムが何を必要とし、何が有効なプログラムが持つことができます)。この検索では、16の可能なゲートのうち15のソリューションが見つかりました。多くの場合、1つだけではありません。このペーストビンにはすべての代替ソリューションのリストがあり、同等の動作でグループ化しています。上に示したものは、最も単純なソリューションまたは最も興味深いソリューションのいずれかであるため選択しました。明日、それらの説明を追加します。
16番目のゲートについては、XORは明らかに7バイトで実装できない唯一のゲートです。残念ながら、現在使用しているコードでは、大規模なプログラムに対するブルートフォース検索は実行できません。そのため、XORは手書きで書かなければなりませんでした。私がこれまでに発見した最短のものは、上記の10バイトのプログラムです。これは、FryAmTheEggmanによる失敗した(ただし非常に近い)試みに基づいています。8バイトまたは9バイトのソリューションが存在する可能性がありますが、それ以外はすべてのソリューションが実際に最適である必要があります。
説明
警告:テキストの壁。これらの高度に圧縮されたHexagonyプログラムが実際にどのように機能するかに興味を持っている人は、偶然に、それぞれの説明を以下に含めました。説明を合理的に短くするために、複数の最適なプログラムが存在する場合、各ゲートに最も簡単なソリューションを選択しようとしました。しかし、それらのいくつかはまだ心を揺さぶるので、彼らはもう少し精巧に値すると思いました。
0000
:偽
この図は必要ないと思う:
! @
. . .
. .
メモリグリッド全体がゼロに初期化されるため、!
単純にゼロを出力し@
てプログラムを終了します。
これも唯一の2バイトソリューションです。
0001
:そして
? .
| @ !
. .
これは基本的に短絡を実装します。以下の灰色の図は、プログラムの開始を示しています。最初の入力が読み取られ?
、命令ポインター(IP)が|
ミラーが反映する左隅に回り込みます。これで、コーナーは条件として機能し、最初の入力の値に応じて2つの異なる実行パスがあります。赤の図は、の制御フローA = 0
と緑の図を示していA = 1
ます。
ご覧のとおり、A
isの場合0
、それを単に出力して終了します(すべて.
がノーオペレーションであることを思い出してください)。しかし、A
がの1
場合、IPは最初の行を再度走査し、B
代わりにそれを読み取り、印刷します。
合計で、このゲートには16個の5バイトソリューションがあります。そのうちの14個は基本的に上記と同じで、実質的に何もしないコマンドの>
代わりに使用するか、コマンドで|
置き換える.
か?
、2番目の位置に配置します。
?.|@! .?|@! ?=|@! =?|@! ?_|@! _?|@! ?0|@!
?.>@! .?>@! ?=>@! =?>@! ?_>@! _?>@! ?0>@!
そして、他に2つのソリューションがあります(これらは互いに同等です)。これらも同じショートサーキットロジックを実装しますが、実行パスは少しクレイジーです(そして読者への演習として残しておきます):
?<!@|
?<!@<
0010
:BではなくA
# ?
# ! )
@ .
これは、短絡の形式も実装しますが#
、制御フローを使用するため、はるかに注意が必要です。#
条件付きIPスイッチです。Hexagonyには、のラベルが付いた6つのIPが実際に付属し0
ています5
。これらのIP は、グリッドの6つのコーナーで始まり、時計回りのエッジに沿ってポイントします(プログラムは常にIPで始まります0
)。ときに#
遭遇すると、電流値はモジュロを取られ6
、制御フローは、対応するIPに続きます。この機能を追加した狂気のフィット感がわからないが、確かにいくつかの驚くべきプログラム(このような)を可能にします。
3つのケースを区別します。の場合A = 0
、プログラムはかなり単純です。これは、IPスイッチングが発生しないよう0
に値が常に検出されるためです#
。
#
何もせず、?
読み取りA
(つまりも何もせず)、#
まだ何もせず、を!
出力し0
、)
それをインクリメントします(これは重要です。そうでない場合、IPは3行目にジャンプしません)、@
プログラムを終了します。簡単です。ケースを考えてみましょう(A, B) = (1, 0)
:
赤いパスはまだIP 0
に対応しており、IPに緑のパスを追加しました1
。?
読み取り後A
(1
今回)、#
右上隅から開始するIPに切り替わります。つまり、?
読むことができますB
(0
)。今)
、それを増加させて1
、#
左上隅が何もしないようにし、IPのままにします1
。を!
印刷し1
、IPが左の対角線の周りにラップします。#
それでも何もせず@
、プログラムを終了します。
最後に、両方の入力が本当に奇妙な場合1
:
今回は、2番目の入力もで1
あり、)
それをにインクリメントし2
ます。つまり、#
左上隅にあるIPに別の IPスイッチが発生し2
、青色で示されます。そのパスでは、まずそれをさらに増やして3
(それは無関係ですが)?
、3回目に渡します。EOFにヒットしたため(入力が使い果たされたため)、を?
返し0
、それを!
出力して、@
プログラムを終了します。
特に、これはこのゲートの唯一の6バイトソリューションです。
0011
:A
? !
@ . .
. .
これは、ダイアグラムを必要としないほど単純です:?
読み取りA
、!
印刷、@
終了します。
これは、このゲートの唯一の3バイトソリューションです。(原則として、実行することも可能です,;@
が、検索にはが含ま;
れていませんでした。なぜなら!
、このタスクのためにバイトを節約できるとは思わないからです。)
0100
:BではなくA
+ ?
| @ !
? .
これは、その「兄弟」よりもずっと単純です0010
。制御フローは0001
(And)について上で見たものと実際には同じです。の場合A = 0
、IPは下の行を走査し、B
終了する前にそれを読み取って印刷します。もしA = 1
その後、IPも読んで、もう一度最初の行を横断B
が、+
2つの未使用のメモリはそれがないすべては、現在の値をリセットであるので、エッジ追加し0
、そのので、!
必ずプリントを0
。
これには非常に多くの6バイトの代替があります(合計42)。まず、上記と同等のソリューションがたくさんあります。私たちは再び間で自由に選ぶことができる|
と>
、そして+
私たちの空の端を与える他のコマンドに置き換えることができます。
"?|@!? &?|@!? '?|@!? *?|@!? +?|@!? -?|@!? ^?|@!? {?|@!? }?|@!?
"?>@!? &?>@!? '?>@!? *?>@!? +?>@!? -?>@!? ^?>@!? {?>@!? }?>@!?
さらに、の]
代わりに使用することもできます?
。]
次のIPに移動します(つまりIPを選択します1
)。そのため、代わりにこのブランチ?
は右上隅で再利用します。それは別の18のソリューションを提供します:
"?|@!] &?|@!] '?|@!] *?|@!] +?|@!] -?|@!] ^?|@!] {?|@!] }?|@!]
"?>@!] &?>@!] '?>@!] *?>@!] +?>@!] -?>@!] ^?>@!] {?>@!] }?>@!]
そして、さまざまなレベルの狂気ですべてが異なる方法で動作する他の6つのソリューションがあります:
/[<@!? ?(#!@] ?(#>@! ?/@#/! [<<@!? [@$\!?
0101
:B
? ?
! @ .
. .
Woohoo、もう1つの単純なもの:read A
、read B
、print B
、terminate。ただし、実際にはこれに代わるものがあります。以来A
唯一の単一の文字で、我々はまた、でそれを読むことができます,
:
,?!@
また、単一?
のミラーを使用し、ミラーを使用して2回実行するオプションもあります。
?|@! ?>@!
0110
:Xor
? < @
! ! < _
\ ~ ( . .
. . . .
. . .
上で言ったように、これはサイドレングス2に収まらない唯一のゲートなので、これはFryAmTheEggmanと私による手書きのソリューションであり、最適ではない可能性が十分にあります。区別するための2つのケースがあります。場合はA = 0
、制御フローは、(その場合には、我々は唯一の印刷する必要があるので、非常に簡単ですB
):
赤い道から始めます。?
読み取りA
、<
ゼロを左に偏向するブランチです。IPは下に折り返され、_
別のミラーになります。IPが角に達すると、左上に折り返され、青いパスを進みます。?
読み取りB
、!
印刷します。今、(
それをデクリメントします。これは、値が正でないことを保証するために重要です(どちらか0
または-1
現在)。これにより、IPが右端に折り返され@
、プログラムが終了します。
A = 1
物事が少し複雑になるとき。その場合not B
、それ自体はそれほど難しくはありませんが、実行パスは少しトリッピーです。
今回<
は、IPを右に偏向し、次に<
ミラーとしてのみ機能します。そのため、IPは同じパスを逆にたどり、再びB
遭遇?
したときに読み取ります。IPは右隅に折り返され、緑色のパスを継続します。次に(~
「減少、-1の乗算」に遭遇します。これはスワップを0
行い1
、したがって計算しnot B
ます。\
は単なる鏡であり!
、望ましい結果を出力します。次に、?
別の数値を返そうとしますが、ゼロを返します。これで、IPは青いパスの左下隅に続きます。(
減少、<
反映、(
再び減少します。そのため、IPがコーナーに達する現在の値は負になります。右下の対角線を横切って移動し、最後にヒット@
してプログラムを終了します。
0111
: または
? <
< @ !
. .
より短絡。
ここでは、A = 0
ケース(赤いパス)が少しわかりにくいです。IPは左に偏向され、左下隅に折り返され、すぐにに反映され、読み取りに<
戻ります。次に、リグコーナーにラップし、印刷して終了します。?
B
B
!
A = 1
ケース(グリーンパス)は、ビット簡単です。<
ブランチは、IPは、右偏向ので、我々は単に印刷し!
、左上に戻ってラップし、で終了します@
。
他の5バイトソリューションは1つだけです。
\>?@!
基本的には同じように機能しますが、実際の実行パスはまったく異なり、分岐の代わりにコーナーを使用します <
ます。
1000
:いいえ
) \
! # ?
@ {
これは、この検索で見つかった私のお気に入りのプログラムかもしれません。最もクールなことは、この実装がnor
実際に最大5つの入力に対して機能することです。これを説明するために、メモリモデルの詳細について少し説明する必要があります。したがって、Hexagonyのメモリモデルはクイックリフレッシャーとして、各エッジが整数値(最初はすべてゼロ)を保持する個別の六角形グリッドです。エッジとそのエッジに沿った方向を示すメモリポインター(MP)があります(現在のエッジの前後に2つの隣接するエッジがあり、意味のある左右の隣人があるように)。以下に、使用するエッジの図を示します。MPは赤で示されています。
まず、両方の入力が0
次の場合を考えてみましょう。
我々は、単にエッジ増分グレー経路、上で起動Aをする1
ように#
IPにスイッチ1
ブルーパスで、右上から開始します。\
そこでは何もせず?
、入力を読み取ります。)
入力をインクリメントする左上隅に折り返します。今限り、入力がゼロであるように、これはにつながる1
ことはので、#
何もしません。次に{
、MPを左に移動します。つまり、最初の反復でAからBに移動します。このエッジにはまだ初期ゼロがあるため、IPは右上隅と新しいメモリエッジにラップバックします。したがって、このループは継続します。?
、ゼロ読み取る、MPをBから六角形の周りに移動ます。CのDなど。?
入力であるかEOFであるため、ゼロを返すかどうかは関係ありません。
このループを6回繰り返した後、Aに{
戻ります。今回は、エッジは最初の反復からの値をすでに保持しているため、IPは左隅に折り返され、代わりに緑のパスに進みます。単にそれを印刷してプログラムを終了します。1
!
1
@
では、入力のいずれかが1
どうなるのでしょうか?
次に、ある時点でそれを?
読み取り、それを1に増やします。つまり、IPが再び切り替えられ、赤いパスの右隅に進みます。別の入力(ある場合)を読み取ります。これは実際には重要ではなく、1つのエッジをさらに移動します。これは未使用のエッジである必要があるため、最大5つの入力に対して機能します。IPは右上に折り返されてすぐに反映され、左隅に折り返されます。未使用のエッジにを出力し、IPに切り替えます。そのIPはまだ南西に向かって(灰色のパス)待機していたので、すぐにヒットしてプログラムを終了します。1
)
2
#
?
{
!
0
#
0
#
@
このゲートには合計で7つの7バイトソリューションがあります。それらのうち5つはこれと同じように動作し、他のコマンドを使用して未使用のエッジに移動します(別の六角形の周りや別の方向に移動できます)。
)\!#?@" )\!#?@' )\!#?@^ )\!#?@{ )\!#?@}
また、2つの入力のみで機能するソリューションの別のクラスが1つありますが、その実行パスは実際にはさらに厄介です。
?]!|<)@ ?]!|<1@
1001
:平等
( ~
? / @
# !
また、これにより、条件付きIP選択が非常に巧妙に使用されます。とを再度区別する必要がA = 0
ありA = 1
ます。最初のケースでは印刷したいのですnot B
が、2番目では印刷したいですB
。以下のためにA = 0
我々はまたのための2つのケースを区別するB
。始めましょうA = B = 0
:
灰色のパスから始めます。(~
無視することができ、IPは(まだ灰色のパス上)左の隅にラップし、読み込みA
に?
。(
それを減らすので-1
、左下隅にIPラップを取得します。さっきも言ったように、IPを選択#
する6
前にモジュロの値を取るので、-1
実際にはIPを取得します5
。これは、赤いパスの左隅から始まります。?
を読み取りB
、(
同様にデクリメントして、再び5
ヒット#
したときにIPのままになるようにします。~
を無効に-1
して、IPが右下に折り返され、印刷し1
て終了するようにします。
あれば今B
ある1
代わりに、現在の値になります0
私たちはヒット時に#
二時間を私たちはIPに切り替え、0
(緑のパスになりました)。?
3回目にヒットし、yield 0
を!
出力し、@
終了します。
最後に、ケースどこA = 1
。今回#
は、最初にヒットしたときに現在の値がすでにゼロになっているため、最初はIP 5
に切り替わりません。すぐに緑の道を進みます。?
今はゼロを与えるだけでB
なく、代わりに戻ります。!
それを印刷して、@
再び終了します。
合計で、このゲートには3つの7バイトソリューションがあります。他の2つの機能は非常に異なっており(お互いからでも)、をさらに奇妙に使用し#
ます。特に、1つ以上の値を,
(整数の代わりに文字コードを読み取る)で読み取り、その値をモジュロ6で使用してIPを選択します。それはかなりナッツです。
),)#?@!
?~#,~!@
1010
:Bではない
? ?
| @ !
) .
これはかなり簡単です。実行パスは、and
以前からすでに知っている水平ブランチです。??
読んA
ですぐにB
。で反射し|
て分岐した後B = 0
、下の分岐を実行し)
ます。ここで値がインクリメントされ、その値に1
印刷され!
ます。上部ブランチ(場合にB = 1
)?
単にエッジをリセットし0
、次にによっても印刷され!
ます。
このゲートには8つの6バイトプログラムがあります。それらの4つはほとんど同じで、>
代わりに、|
または1
代わりに)
(または両方)を使用します。
??>@!) ??>@!1 ??|@!) ??|@!1
2つ?
は、ミラーのために2回使用されるシングルを使用します。否定はxor
、(~
またはで行ったように発生します~)
。
?>!)~@ ?>!~(@
最後に、2つのソリューションは条件付きIPスイッチを使用します。なぜなら、複雑なものも機能するのであれば、なぜ簡単な方法を使用するのかという理由からです。
??#)!@ ??#1!@
1011
:BはAを意味します
\ #
? ? !
1 @
これはかなり複雑なIPスイッチングを使用します。A = 1
今回はより簡単なので、今回のケースから始めましょう。
私たちは、読み込みグレー路上に開始A
し?
、その後ヒット#
。これA
は1
IP 1
(緑のパス)に切り替わるためです。!
すぐに、IPは左上に折り返されることを、読み込み出力しますB
(不必要に)して終了します。
ときにA = 0
、物事はもう少し面白く。最初に考えてみましょうA = B = 0
:
今回#
は何もせず、IPのままです0
(その時点から赤いパス)。?
読み取りB
、1
それを1
。左上隅に折り返した後、#
再びヒットしたので、結局緑のパスに行き、印刷します1
前に以前のようにします。
最後に(A, B) = (0, 1)
、これはfalseケースです。
わかりやすくするために最初の灰色のパスを削除しましたが、プログラムは同じ方法で始まり、以前と同じように赤いパスになります。したがって、今回は2番目?
が戻ります1
。今、私たちはに遭遇し1
ます。この時点で、Hexagonyで実際に数字が何をするかを理解することが重要です(これまでゼロでのみ使用していました)。これは通常、10進数をソースコードに逐語的に書き込むために使用されますが、B = 1
実際にはvalueにマッピングされます11
。したがって、を押すと#
、これはモジュロ6
で与えられて与えられるため5
、5
(1
以前のようにではなく)IPに切り替えて、青いパスに進みます。ヒッティング?
3回目はゼロを返すため、IPはプログラムが終了する右下に折り返されます。!
出力し、別の2つの後に?
これには7バイトのソリューションが4つあり、それらはすべて異なる動作をします。
#)/!?@$ <!?_@#1 \#??!1@ |/)#?@!
1100
:Aではない
? (
~ ! @
. .
ただ、単純な線形1:読んA
で?
、と否定(~
して印刷する、!
で終了し、@
。
代替ソリューションが1つありますが、~)
代わりにそれを無効にします。
?~)!@
1101
:AはBを意味します
? .
| @ !
) .
これは、先ほど説明した反対の意味合いよりもはるかに単純です。これも、のような水平分岐プログラムの1つですand
。場合A
で0
、それは単ににインクリメントされます1
一番下の枝の上に印刷します。それ以外の場合は、最上位のブランチが再度実行され、代わりにそれが?
読み取られB
て!
出力されます。
ありますトン、主に起因する効果的な空命令を自由に選択し、ここでの選択肢の(合計で66社のソリューションは)、。スタートのために我々は我々ができた全て同じ方法で、上記の溶液を変えることができand
、我々はまたの間に選択することができます)
と1
:
?.|@!) .?|@!) ?=|@!) =?|@!) ?_|@!) _?|@!) ?0|@!)
?.|@!1 .?|@!1 ?=|@!1 =?|@!1 ?_|@!1 _?|@!1 ?0|@!1
?.>@!) .?>@!) ?=>@!) =?>@!) ?_>@!) _?>@!) ?0>@!)
?.>@!1 .?>@!1 ?=>@!1 =?>@!1 ?_>@!1 _?>@!1 ?0>@!1
そして、最初のコマンドは、ほぼ任意に選ぶことができ、条件付きIPの選択を、使用して異なるバージョンがあります、との間の選択もあります)
し、1
それらのオプションのいくつかについては:
"?#1!@ &?#1!@ '?#1!@ )?#1!@ *?#1!@ +?#1!@ -?#1!@ .?#1!@
0?#1!@ 1?#1!@ 2?#1!@ 3?#1!@ 4?#1!@ 5?#1!@ 6?#1!@ 7?#1!@
8?#1!@ 9?#1!@ =?#1!@ ^?#1!@ _?#1!@ {?#1!@ }?#1!@
"?#)!@ &?#)!@ '?#)!@ *?#)!@ +?#)!@ -?#)!@
0?#)!@ 2?#)!@ 4?#)!@ 6?#)!@
8?#)!@ ^?#)!@ _?#)!@ {?#)!@ }?#)!@
1110
:ナンド
? $
@ # )
! <
最後の複雑なもの。まだ読んでいるのなら、もうほとんど完成です。:) A = 0
最初に見てみましょう:
?
読み取りA
、ヒットし$
ます。これはジャンプコマンド(Befungeのような#
)で、次の命令をスキップして、で終了しないようにし@
ます。代わりに、IPはに続き#
ます。ただし、A
is 0
なので、これは何もしません。)
をインクリメントし1
て、IP 1
が印刷される一番下のパスに続くようにします。<
それは左隅にラップし、プログラムが終了右にIPを偏向させます。
次に、入力が(A, B) = (1, 0)
この状況になったとき:
それは本質的にことを除いて、前と同じだ#
、我々はIPに切り替える1
(緑道)が、以来B
で0
、我々はIPに切り替える0
我々は打ったとき#
、それは印刷し二回目(今ブルーパス)、1
以前のようにします。
最後に、A = B = 1
ケース:
今回は#
、2回目に、現在の値がまだである1
ため、IPを再度変更することはありません。<
それを反映して、我々はヒット三度目は、?
私たちは、ゼロを取得します。したがって、IPは左下に!
折り返され、ゼロが出力されてプログラムが終了します。
これには、合計で9つの7バイトソリューションがあります。最初の選択肢は、次の代わりに単に使用し1
ます)
:
?$@#1!<
次に、進行中のIPスイッチングの量に頭を悩ます2つのソリューションがあります。
)?#_[!@ 1?#_[!@
これらは実際に私の心を吹き飛ばしました。興味深い部分は、IPスイッチングを遅延条件として使用できることです。言語のIP切り替えルールは、切り替えが発生する前に現在のIPが別のステップを実行するようなものです。そのステップがたまたまコーナーを通過した場合、現在の値は、IPに戻った場合にIPを継続するブランチを決定します。まさにこれは入力がのときに起こりますA = B = 1
。これは私が言語をどのように設計したかと一致していますが、仕様のこの含意に気付いたことはありませんでした。
次に、IPスイッチングの量がさらに悪い3番目のソリューションがあります(ただし、その遅延条件付き効果は使用されません)。
>?1]#!@
そして、別のものがあります:
?$@#)!<
そして、これらの4つの同等のソリューションがあります。これらのソリューションは、無条件のIPスイッチングを使用し、代わりにブランチとコーナーを介してすべてのロジックを実装します。
]<?<@!) ]<?<@!1 ]|?<@!) ]|?<@!1
1111
:本当
1 !
@ . .
. .
あなたは最後にシンプルなものを手に入れました:エッジを1
に設定し、で印刷し!
、で終了し@
ます。:)
もちろん、1つの選択肢があります。
)!@
いつものように、すべての制御フロー図はTimwiのHexagonyColorerで作成され、メモリ図は彼のEsotericIDEで作成されました。