ゴルフ言語での保管のヒント


16

ゴルフの言語を書いています。

コードゴルフ言語で保存するための変数、スタック、テープ、レジスタなどを提案しますか?暗黙的な入力はどうですか?

大まかな定義:

  • 変数は、値が割り当てられ、以降その名前で取り出すことができることを単に名前(長いゴルフの言語で、通常は1文字)です。
  • レジスタは、変数のようなものですが、それは値を取得/設定するための(通常はシングルバイト)独自のコマンドがあります。
  • スタックは、最も最近追加された値(「上」値)が変更されるものである値の可変長配列/リストです。
  • キューは、「上の値を除いて、スタックのようなものです底が」改変されているものです。
  • テープは、各値がインデックスを有する値の静的配列/リストです。スタックとテープの主な違いは、テープ上の値がインプレースで変更されることです。

さまざまなシナリオおよび全体に対する各オプションの長所と短所を知っていただければ幸いです。意見を避け、推論を伴う陳述をバックアップしてください。


1
私はあなたがあなたの質問ではこれらの用語の定義を含めるべきだと思う
KritixiのLithos

2
@Fatalize技術的には、保存方法は作成するゴルフ言語の種類に依存せず、ゴルフ言語の種類は保存方法に依存します...
ETHproductions

1
@ETHproductions彼らは完全に相互依存しています。
致命的

1
さまざまなストレージ用語の大まかな定義を追加しました。気に入らない場合は、気軽に編集またはロールバックしてください。
-ETHproductions

2
保存方法と言語の種類の間には非常に密接な関係がありますが、両方を検討する必要があると思います。たとえば、「命令型」言語(命令を厳密に左から右に実行する言語)は、スタックベース(CJam、05AB1E)、テープベース(BrainF ***)、または完全に別のもの(V、 「バッファ」と呼ばれる1つの大きな2D文字列と、いくつかのレジスタ)。また、プレフィックスベースの言語(Pyth)、インフィックスベースの言語(Japt、Pip、および基本的にすべてのメインストリームlang)、リンクベースの言語(Jelly)などもあり、これらはすべて前述の方法をほとんど使用しません。
-ETHproductions

回答:


4

すべてのストレージタイプには、ある時点で何かを格納し、後でそれを取得することが含まれます。1つの操作のみでこれを行うには、自動的に保存または取得を行い、他の操作で保存された値の位置を指定する必要があります。

つまり、明示的なストレージの場合、この操作の前にn番目の計算値を取得する演算子を作成するか、n操作後に現在の値を戻すことができます。または、プログラムの最初から絶対位置を使用するか、いくつかの操作(スタック内など)の後にいくつかの要素を自動的に削除するなど、さらに多くのことを行うことができます。また、複数のオペレーターを作成して、これらの自動操作の有無にかかわらず、ストレージの異なるコピーから取得することもできます。また、操作で指定するのに必要な最大数を適度に小さくして、各数に1つの演算子を割り当てることができるようにする必要があります。

しかし、ほとんどの場合、演算子は不要であり、言語は暗黙的にこれを行います。スタックやキューなど、より標準化されたモデルを検討する必要がある場合です。今のところ最も成功しているのは暗黙のプログラミングであるように思われます。

新しいモデルを設計する場合は、評価をダグとして展開し、他に何も指定されていない場合はデフォルトのダグを考えてみてください。最も可能性が高いのは、複数のリーフが同じ入力にリンクされる場合があることを除いて、デフォルトは単なるツリーです。たとえば、バランスの取れたツリーにキューを使用したり、葉がほとんど一定である深いツリーにスタックを使用したり、葉がほとんど入力のコピーである深いツリーにゼリーのようなものを使用したりできます。

ただし、演​​算子ごとに2ビットのみでバイナリツリーの形状をエンコードできることに注意してください。そのため、言語の演算子が64個未満の場合、実際には従来のモデルを無視して、スペアビットで完全なツリーをエンコードするだけです(combined_pa​​rentフラグとbelow_leafフラグを呼び出します)。さらに多くの演算子がある場合でも、かなり良いデフォルト値(Jellyのモデルなど)とそれを変更するための3つの修飾子を作成できます。

便宜上、暗黙的および明示的なストレージに同じモデルを使用できますが、そうする必要はありません。たとえば、暗黙的なストレージにスタックを使用できますが、明示的なストレージ(または暗黙的なストレージに加えて別の明示的なストレージ)に要素をポップしないでください。最終ドキュメントではスタックと呼ばれない可能性がありますが、アイデアは得られます。

参考までに、バイナリツリーの完全なエンコーディングのサイズは、カタロニア語の数値の対数です。また、「バイナリ」DAGの完全なエンコードのサイズはA082161の対数ですが、明らかに非実用的です。これは、異なる引数順序を持つ演算子と2つの異なる演算子を想定し、そうでない場合は別のビットを追加します。

ループの変数が必要な場合があります。他の方法でループを書き換えることができる場合があります。ただし、本当に必要な場合は、変数の定義に名前に加えて1バイトの構造を使用しないでください。事前初期化された値のみを使用している場合を除き、通常、1ビットフラグを使用して、この変数の読み取りまたは書き込みを指定する方が効率的です。


7

それらすべてをお勧めします!

もっと真剣に、それらはすべて時に役立つことがあります、そしてより良いです!暗黙的な入力は決して悪いものではありません。それをオフにするためのフラグを持っているだけです。変数は役立つので、スタックやテープで見つける必要はありません。レジスタと同じ。スタックはデータを保存するのに役立ち、テープも同様です。スタックレジスター、またはGolfScriptなどのスタックと変数など、複数の実装を試みることをお勧めします。各機能を1バイトにすることができれば、それぞれの利点を活用できるので、おそらくあなたの言語はゴルフに効果的でしょう。

例:

  • 入力として2つの数値を取得し、それらの文字列の長さを追加するとします
  • これには変数の方が良いかもしれません(スタックはそうではないかもしれません)
  • GolfScriptのサンプルコード(暗黙的な入力あり):

    ~,\,+
    ~ # Eval input (e.g. "1 2" > 1, 2)
    , # Take Length
    \ # Reverse items on the stack
    , # Take Length
    + # Add
      # Implicit output
    

    ただし、変数の場合(もっと長いことはわかっていますが、スタック上の場所を入れ替える必要はありません):

    ~,:a;,:b;ab+
    ~ # Eval input
    , # Get length
    :a# Store in "a"
    ; # Discard value left on stack
    , # Length
    :b# Store in "b"
    ; # Discard
    a # Recall a
    b # Recall b
    + # Add
      # Implicit output
    

過負荷

役立つもう1つのことは、オーバーロードです。たとえば、変数を保存する関数がある場合、それをモナド(1入力関数。J/ K / APLのout sideという用語がわからない)として使用してスタックまたはテープに追加することができます。

例:

c12 # Stores "1" into register 2
c1] # Pushes "1" onto the stack ("]" is used to denote the end of the monad)

たぶん、引数が間違った型で呼び出された場合、キューに追加され、スタックが空の場合に値を入力するために使用されますか?
エソランジングフルーツ

5

プログラムが無関係なことをしているときに邪魔にならないように、すぐに使用可能なストレージ(テープ、キュー、スタックから)と永続的なストレージ(変数、レジスタ)を用意することをお勧めします。もっと多くの場合、何かを与えることはめったになく、より多くの文字を1バイトの命令のために残しておくと思います。

与えられた定義から、私が最もうまくいくと思うものは、スタックとレジスターでしょう。
スタックは、新しいものを格納するためだけに機能を使用する必要があるため、スタックは単純なプッシュおよびポップ機能(通常はコマンドに組み込まれている)を持っている必要があるためです。レジスタ。通常は変数と比較してバイト数が少なく、何かのために2〜4個以上の異なるものを保存する必要がある場合、何か間違ったことをしています。

それらの機能を、その名前または定義がトラフを示唆するものだけに制限しないでくださいput the 1st thing of the stack on top of the stack


5

基本的に2種類のストレージがあり、それぞれ異なる方法で処理する必要があります。最近生成された値や入力へのアクセス。長期保管。

長期保存の場合、変数が最適に機能するようです。限られた数のオプションを持つものはスケーリングしません(ただし、このプロパティを持つ言語はJellyのようですが、中規模のタスクでもかなりうまくいくことができます)。ただし、ほとんどの場合、変数を保存するときに変数を指定する必要はありません。変数に値を保存するコマンドを用意し、予測可能なパターンに従って名前を自動生成することで、値の保存と取得が単純な場合にそれぞれ1つのコマンドになるようにします。(たとえば、最後に割り当てられた変数、2番目に新しい変数、3番目に新しい変数など、小さい固定数まで復元するコマンドと、引数を取る一般的なコマンドを使用できます。)

短期保管の場合、できるだけ暗黙的に保管する必要があります。私が見たほとんどすべてのゴルフ言語は、デフォルトで、あるコマンドの出力を次のコマンドの入力に接続します。これを行う正確な方法は言語によって異なりますが、通常は同じことです。ただし、2入力コマンドの2番目の入力の方が興味深いです。スタックから値を取得することは、値が1回しか使用されない場合にはうまく機能しますが、値を再利用するときにはうまくスケーリングしません。(スタック操作プリミティブを避けるようにしてください。使用することに頼らなければならない場合、多くのバイトを浪費します。)あるいは、ユーザー入力または最近割り当てられた変数を暗黙の2番目の引数として使用すると、シンプルなプログラム、ただし

私が現在取り組んでいるゴルフ言語では、非常に安価なメカニズム(シングルビット)の組み合わせを使用して、解析ツリーの形状を指定し、デフォルトでユーザー入力から欠落している引数を自動的に入力し、欠落している引数のデフォルトを他の何か(さらに多くの特殊なケース)に設定できるようにするアプローチ。ある時点で変数を追加して、プログラムに沿ってより長い距離で情報をやり取りします。


0

テープとレジスターをお勧めします。

テープは要素が少ない傾向があり、それらの操作が簡単になるため、スタックよりもテープが好きです。また、レジスター内のテープに要素を配置することができ、その逆も簡単で短いコードになります。

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