Brainfuckでのゴルフのヒント


23

ブレインファックでゴルフをするための一般的なヒントは何ですか?私は、少なくとも一般的にゴルフの問題をコーディングするのに適用できるアイデアを探しています。これは、少なくともある程度、brainfuckに固有のものです(たとえば、「コメントを削除する」は答えではありません)。回答ごとに1つのヒントを投稿してください。

回答:


25

回答ごとに1つのヒントを入れると、回答が多すぎます。

  • Brainfuckで考えることを学ぶ。それは他のものとは非常に異なっています。多くのブレインファックプログラムの読み取りと書き込み、書き換え、および書き換え。この言語は作業にあまり役立ちません。そのため、柔軟で効率的な言語を使用することが重要です。あなたと言語との間に抽象化が入らないようにしてください-そこに入り込んで取り組みましょう。

  • 非破壊的なフロー制御で非常に快適になります。決定ループから抜け出すには、開始セルを他の場所にコピーしてゼロにし、ループを出た後にコピーして戻すのではなく、ポインターを近くの既存のゼロに移動することをお勧めします。はい、これは、ループを通過したかどうかに応じてポインターが異なる場所にあることを意味しますが、それはおそらくそれらの場所が近くのゼロと非ゼロの異なる配置を持っていることを意味し、別のループを使用してポインターの場所を再同期するために使用できます。この手法は、優れたBrainfuckプログラミングの基本であり、さまざまな形式が常に有用であることが証明されます。

  • それと、すべて>または<コストがメモリレイアウトの詳細が重要であることを意味するという事実。忍耐がある限り、レイアウトのバリエーションを試してください。また、メモリレイアウトは、データを場所に厳密にマッピングする必要はありません。実行中に変形する可能性があります。

  • より大規模な場合は、さまざまな異なるアルゴリズムの実装を検討し、試してください。最初は、どのアルゴリズムが最適であるかが正確には明らかではありません。どの基本的なアプローチが最適であるかさえ明らかではないかもしれませんし、おそらく通常の言語で最適なアプローチとは異なるものになるでしょう。

  • 大きなデータまたは可変サイズのデータ​​を扱う場合は、データの大きさやその中の数値の位置を追跡せずに、ローカルで処理できる方法があるかどうかを確認してください。

  • 同じデータには2つの異なるものがあります。(ほとんどの場合、数字または文字であり、ゼロ以外の位置マーカーです。しかし、ビットカウンターがセルオートマトンの1つのセルの値として2倍になるrandom.bを参照してください。)

  • 同じコードで2つの異なることができます<+<。コードがのように汎用的である言語では、そうするのがはるかに簡単です。そのような可能性に注意してください。実際、よく書かれたプログラムと思われるものであっても、完全に削除できる小さな部分があり、何も追加されず、偶然にも問題なく実行されることに気付く場合があります。

  • ほとんどの言語では、コンパイラまたはインタープリターを頻繁に使用して、プログラムの動作を確認します。Brainfuck言語では、より概念的な制御が必要です。あなたのプログラムが何をするのかを伝えるためにコンパイラが必要な場合、あなたはあなたのプログラムを十分にしっかりと把握していないので、おそらくそれをもっと凝視する必要があります-少なくともあなたが十分に明確なイメージを持ちたいならゴルフが得意な同様のプログラムの概念的なハロー。練習すれば、プログラムを実行する前にプログラムの数十のバージョンを作成し、その時点までに最短のプログラムが正しく実行されることを95%確信できます。

  • がんばろう!Brainfuckを簡潔に書くことを気にする人はほとんどいませんが、それは言語が驚くほどあいまいな芸術形式として、継続的な注意を正当化できる唯一の方法だと思います。


3
...これは私が今Brainfuckでプログラミングを試してみたくなるの読み込み
クラウディウ

なんてこった、あなたの名前を認識したと思った。あなたのブレインファックプログラム、特にあなたの超短い自己通訳の大ファン!
ジョーキング

「ときどき気づくかもしれません...完全に削除できる小さな部分があり、何も追加されず、偶然にも問題なく動作することがあります。」これは、特に初心者にとってとても真実です。覚えている限り、BFで答えを1つだけ書いたことがありますが、その改訂履歴には、プログラムで遊んでランダムに行った少なくとも3つのインスタンスが含まれています。 」
ETHproductions

「忍耐がある限り、レイアウトのバリエーションをいくつでも試してみてください」、またはブルートフォースを行うことができます:P
エソランジングフルーツ

9

ここにいくつかのヒント:

定数:

Esolangs'定数ページは、特定の値を作成するための最短の方法の非常に便利なリストを持っています。私はプログラムごとに少なくとも2回このページを参照しています。

すべての始まり:

+++[[<+>>++<-]>]

これにより、テープが3 * n ^ 2の形式で設定されます。

3 6 12 24 48 96192128 0 0 '

なぜこれがそんなに重要なのですか?

リストを下に行きましょう:

  • 3と6は退屈です
  • 12:10(改行)または13(キャリッジリターン)に近い。0-9のカウンターにも使用できます
  • 24:アルファベットの文字数である26に近い
  • 48:ASCII 0
  • 96:97に近い、ASCII a
  • 196および128:196-128 = 64、65に近い、ASCIIのA

この1つのアルゴリズムから、それぞれのカウンターと簡単に到達できる改行とともに、ASCII範囲内の実質的にすべてのシーケンスの開始点にいます。

実用的な例:

すべての大文字と小文字および数字を印刷します。

アルゴリズムあり:

+++[[<+>>++<-]>]<<[-<->]<<<<++[->>+.>+.<<<]<--[>>.+<<-]

なし:

+++++++++++++[->+++++++>++>+++++>++++>+<<<<<]>+++++>[-<+.>>.+<]>>---->---[-<.+>]

2番目の例では、ほとんどのバイトをテープの初期化に費やしています。この一部は、最初の例の余分な動きによって相殺されますが、この方法には明らかに利点があります。

同じ脈絡の中で他のいくつかの興味深いアルゴリズム:

3 * 2 ^ n + 1:

+++[[<+>>++<-]+>]
Tape: 4 7 13 25 49 65 197 129 1 0'

これにより、値が1オフセットされ、いくつかの処理が実行されます。12はキャリッジリターン、64は実際の大文字アルファベットの開始、24はキャリッジリターンに近いものになります。

2 ^ n:

+[[<+>>++<-]>]
Tape: 1 2 4 8 16 32 64 128

64は大文字に適しているため、32はスペースのASCIIであり、128は26のカウンターとして使用できます(130/5 = 26)。これにより、数字や小文字が不要な特定の状況でバイトを節約できます。

質問に合った実装を選択してください。

  • 負のセルはほとんどの場合に有用であり、それらを回避する理由はありません(バイトカウントを変更しない限り)
  • 多くの定数がラッピングを使用するため、セルのラッピングでもほぼ同じことが言えます。
  • 任意のセルサイズは、フィボナッチ数列を無限に計算する(+[[-<+>>+>+<<]>])や、より大きな/負の数を処理するなど、無限の数学数列に役立ちます。欠点は、次のようないくつかの一般的な方法、ということである[-][->+<]数値が負である場合だけに、依存することができません。
  • EOF 0、-1、または変更なし。余分なチェックなしで入力全体をループできるため、通常は0が望ましいです。-1は、配列構造をループするときに役立ちます。変更なしの使用法はまだ見つかりませんでした:(。

フリックの進行状況を追跡します。

常に、ポインターがその周囲のデータとの関係でどこにあるべきかについてのコメントがあり、各セルの可能な値の範囲を知っていることを確認する必要があります。これは、ループの前にポインターを分割した場合に特に重要です。2つの可能性を後で結合する必要があるためです。

いずれの時点でも、私のコードには、次のような他のすべての行のコメントが散らばっています。

*0 *dat a_1 ?  0' !0 0*
 or
*0 *dat 0' ap1 0  !0 0*

いくつかの特別なアドバイスは、シンボルに特別な意味を割り当てることです。上記の例で'は、isはポインタの位置で、*その方向の繰り返しを?意味し、未知の値を持つセルを!0意味し、ゼロ以外のセルを意味し_、の代替で-ありp、の代替です+orテープはどちらかの表現のように見える可能性があり、そのように処理する必要があることを意味します。

シンボルスキームは必ずしも私のものと同じである必要はなく(いくつかの欠陥があります)、一貫している必要があります。これはデバッグ時にも非常に便利です。その時点まで実行して、実際のテープを必要なものと比較し、コードの潜在的な欠陥を指摘できるためです。


5

私の主なアドバイスはそうではないでしょう

わかりました、それよりも便利なものが必要です。BFは既に非常に簡潔な言語ですが、実際にあなたを殺すのは算術であり、単項で効果的に行う必要があります。Esolang の定数ページを読んで、大量の数字を効率的に書く方法を正確に選び、可能な限りラッピングを活用する価値があります。

メモリアクセスも非常に高価です。テープから読んでいるので、常に頭が動いている場所を覚えておく必要があります。あなただけの書き込みができ、他の言語とは異なりabc、BFに、あなたが何を保存する場所の留意でなければならないので、明示的に、数バイトを左または右に頭を移動する必要があります。最適な方法で記憶を整理することはNP困難であると確信しています。幸運を祈ります。


5

この回答では、テープ上の特定のセルを何度も参照します。どのセルであるかは関係ありませんが、回答全体を通して同じセルです。この投稿では、そのセルを「Todd」と呼びます。

セルを一定の値に設定しようとすると、セルをすぐに終了しないことがあります。たとえば、Toddに30を含めるようにしたいとします。コードの後半で(Toddの値は変更される可能性がありますが、読み取られません)、Toddに戻ります。Toddの値が0の場合、プログラムは終了します。それ以外の場合、Toddの値は永久に出力されます。

よるとbrainfuck定数のesolangs.orgページ(おそらく、独自の!上の先端の対象となりうる)30を取得するための最短の方法です>+[--[<]>>+<-]>+。その先頭>は、ポインターの左側の何も変更されないことを保証するためだけにありますが、この場合、それを気にしないと仮定してドロップします。そのコードを使用すると、コードは次のようになります。

+[--[<]>>+<-]>+(MISC. CODE)(GO TO TODD)[.]

次のようなコードの最初のチャンクを考えることができます。

(SET TODD TO 30)(MISC. CODE)(GO TO TODD)[.]

ただし、そのチャンクの最後の2文字を思い出してください>+。次のように考えることも同様に有効です。

(SET TODD TO 29)(GO TO TODD)(ADD 1 TO TODD)(MISC. CODE)(GO TO TODD)[.]

あなたは(GO TO TODD)二度注意してください!代わりに、この方法でコードを書くことができます。

(SET TODD TO 29)(MISC. CODE)(GO TO TODD)(ADD 1 TO TODD)[.]
+[--[<]>>+<-](MISC. CODE)(GO TO TODD)+[.]

(GO TO TODD)以前に必要なバイト数が同じであると仮定すると、1つ少ない移動== 1つ少ないバイトです!時々、開始位置が変わったという事実がその恩恵を奪いますが、必ずしもそうではありません。


0

入力なしのチャレンジのための小さな小さなヒント。ほとんどのインタープリター(TIO.runを含む)はセルの内容をEOF表現がゼロに設定するため、セルをすばやくクリアする必要がある場合,[-]、の代わりに使用できます。これはプログラムをほんの少し移植性のないものにしますが、とにかくコードゴルフで誰がそれを気にしますか?

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.