GolfScriptでのゴルフのヒント


35

この投稿はまだありませんか?

もちろん、GolfScriptはゴルフ用に作られているので、特定のヒントは本当に必要ないと思うかもしれません。しかし、GolfScriptの機能を最大限に活用するには、いくつかの非自明なトリックを学ぶ必要があります。この投稿は、このような役立つヒントやコツを収集するためのものです。

まず、公式のGolfScriptリファレンスページがあります。最初にこれらをよく理解する必要があります。

特に、この順序でページを読むことを強くお勧めします。クイックリファレンスは、組み込みに十分慣れているまではほとんど役に立ちません。チュートリアルには、他のページでは説明されていない重要な詳細が含まれます。 。


追伸 インスピレーションと個人的な興味のために、次の質問答えてください。

  • GolfScriptで文字変換を制限する方法は? {FROM?TO=}%作品ならば、あなたは必ずすべての入力がで発見されたことができますFROM(または、それらはすべての最後の要素にマッピングされて気にしないTO)が、私は変わらず、マッピングされていない値を残すために見てきたすべての方法は、多かれ少なかれklugeyされています。

  • 文字列をASCIIコードの配列に変換したり戻したりするにはどうすればよいですか?副作用としてこれを行う操作はどれですか?文字列の文字をスタックにダンプする最良の方法は何ですか(~配列の場合と同様)?


別の質問:変換するための良い方法がある... xには... [x]?私が見ることができる最高のものです[.;]
ピーターテイラー

@Peter:xが数値の場合、[]+機能し、1文字短くなります。そして、もちろん、xスタック上の唯一のものであれば、それだけで]十分です。
イルマリカロネン

最善の方法、最小値、最大値、絶対値を尋ねたいと思います。私のソリューションはすべて、必要以上に多くのキャラクターを使用しているようです。
クラウディウ14年

特定のインデックスで配列を変更する最良の方法は何ですか?
user1502040 14

@ user1502040:以下の回答。(誰かがより良い方法を知っているなら、共有してください!)
イルマリカロネン14

回答:


29

合理的/フロート/複雑

何回も読んだことがあるので、GolfScriptには整数しかないと信じ始めました。まあ、それは真実ではありません。

2-1? # Raise 2 to the power of -1. Result: 0.5
4-1? # Raise 4 to the power of -1. Result: 0.25
+    # Add. Result: 0.75

出力は

3/4

標準のGolfScriptインタープリターと

0.75

のWeb GolfScript

同様のハックにより、Rational、Float、さらにはComplexにキャストできます。

{-2.?./*}:rational
{2.-1??./*}:float
{-2.-1??./*}:complex

9
OMGWTFHAX o_O !!!
イルマリカロネン

3
ワット!これはインタープリターのバグであることは確かですが、すごい
Doorknob

3
最新の通訳の82行目:Gint.new(@val**b.val)。と思われるGintコンストラクタはint型のキャスト...不足している
プリモ

10

数字を否定する

GolfScriptに欠けているものの1つは、組み込みの否定演算子です。-1*またはのようなスタック上の数値を負の値に変換する明白な方法には、0\-3つの文字が必要です。ただし、2つの方法があります。

~)

この作品GolfScriptは、使用しているため、2の補数〜ように、算術X等しい- X -1。

もちろん、バリアント(~も機能します。それらの間で選択することは、一般的に好みの問題です。


9

配列のシャッフル

GolfScriptで配列をシャッフルする最も簡単な方法は、ランダムソートキーでソートすることです。いくつかの値を粗くシャッフルする必要がある場合は、次のコードで行います。

{;9rand}$

短いリストであっても、これはあまり良いシャッフルを与えないことに注意してください。以下のために誕生日のパラドックス合理的に均一なシャッフルを得るために、引数randシャッフルされているリストの長さの平方よりも有意に大きくする必要があります。

この9ように上記を置き換えると、99最大10個の要素のリストに対してかなり良い結果が得られますが、より長いリストについては顕著なバイアスが示されます。

9 9 = 387,420,489の可能な値を使用する次のコードは、最大約1000個のアイテムに適しています(最大約20,000個に対応可能)。

{;9.?rand}$

本当に長いリストの場合、99 99≈3.7×10 197の値にさらに9を追加します。

{;99.?rand}$

テスト:

以下は、上記のさまざまなバリエーションを使用してシャッフルされ、10,000回以上試行された10要素リストの最初の要素の分布です。

  • の出力は10,{;9rand}$0=非常に明確なバイアスを示し0ており、最初の位置に到達する可能性が3倍以上あり1ます。

    0 16537 #######################################################
    1 5444  ##################
    2 7510  #########################
    3 8840  #############################
    4 9124  ##############################
    5 12875 ##########################################
    6 9534  ###############################
    7 8203  ###########################
    8 7300  ########################
    9 14633 ################################################
    
  • を使用すると10,{;99rand}$0=、ほとんどのバイアスはなくなりますが、まだかなりの量が残っています。

    0 10441 ##################################
    1 9670  ################################
    2 9773  ################################
    3 9873  ################################
    4 10134 #################################
    5 10352 ##################################
    6 10076 #################################
    7 9757  ################################
    8 9653  ################################
    9 10271 ##################################
    
  • では10,{;9.?rand}$0=、出力が真にランダムなサンプルから基本的に区別がつきません。

    0 9907  #################################
    1 9962  #################################
    2 10141 #################################
    3 10192 #################################
    4 9965  #################################
    5 9971  #################################
    6 9957  #################################
    7 9984  #################################
    8 9927  #################################
    9 9994  #################################
    

追伸 数値配列または文字列の本当に悪いシャッフルについて、次のコードが受け入れられる場合があります。

{rand}$

一般的にばかげた偏りがありますが、入力配列のすべての要素(または文字列内のすべての文字コード)が1より大きい限り、配列の順列を生成する確率はゼロではありません。不十分に書かれたチャレンジ要件。


3
私は、彼が:(右だった兄はそれについて私に言った後、私は一度懐疑的誕生日のパラドックスのための数学をやった覚え
ajax333221

8

特定のサブ質問に対処するには:

文字列をASCIIコードの配列に変換したり戻したりするにはどうすればよいですか?副作用としてこれを行う操作はどれですか?文字列内の文字をスタックにダンプする最良の方法は何ですか(配列の場合〜のように)?

問題を理解していない人のために、GolfScriptの型システムは、整数、配列、文​​字列、ブロックの順に型を優先します。つまり、文字列に適用される通常の配列演算は、ほとんど常に文字列を提供します。例えば

'ABC123'{)}%

去る'BCD234'スタック上に。

その結果、文字列をASCIIコードの配列に変換する最良の方法は、ほぼ確実にスタック上の文字をダンプしてから配列に収集することです。

文字列の文字をスタックにダンプする最良の方法は何ですか? {}/

文字列をASCIIコードの配列に変換する最良の方法は何ですか?[{}/](通常の注意事項として、スタックに他に何もない場合はスキップできます[

ASCIIコードの配列を文字列に変換する最良の方法は何ですか?''+(例えばので注意これはまた、配列を平坦化することを[65 [66 67] [[[49] 50] 51]]''+示します'ABC123'


単一のASCIIコードを文字列に変換する最良の方法は何ですか?[]+''+?(かなり長いようです)
ジャスティン

@Quincunx、それはかなり長いですが、私はより良い方法を知りません。すべきことは、ASCIIコードがどこから来たのかを調べて、配列にすでに到達できるかどうかを確認することです。
ピーターテイラー

6

プログラムが不可解に壊れた場合は、変数を確認してください

!変数として使用された明らかに正しいプログラムをデバッグするのにしばらく時間を費やしました(これを再び使用しないという理由で)。残念ながら、私はを使用しましたがif、どのブランチに従うかを決定するためのif呼び出しの実装が判明しました!


6

スタックの一番上のアイテムを配列にラップする

変換するための良い方法がある... xには... [x]

完全な一般性のために、最適なオプションは4文字です。ただし、特定の特殊なケースでは、これを減らすことができます。

1文字

]xスタック上の唯一のものである特別な場合に機能します。

3文字

[]+x整数である特別な場合に機能します。

.,/x真の配列または文字列である特別な場合に機能します。例えば、"AB".,/与える["AB"]; 3,.,/与える[[0 1 2]]。しかし、"".,/そして[].,/両方ギブ[]

4文字

[.;] 無条件に動作します。


6

特定のインデックスで配列を変更する最良の方法は何ですか?– user1502040

それは良い質問です。GolfScriptの配列要素に値を割り当てる直接的な方法はないため、何らかの方法で、配列全体を再構築する必要があります。

配列のxインデックスiに新しい値を挿入する最も一般的な方法は、指定されたインデックスで配列を分割し、x前半に追加してから再び結合することです。

  • .i<[x]+\i>+(11文字)- x(0から始まる)インデックスで配列に値を挿入しますi

するに置き換えたインデックスに値をiしてx、私たちはただ一つの要素によって、配列の後半を短くする必要があります。

  • .i<[x]+\i)>+(12文字)-(0から始まる)インデックスの要素をi値に置き換えますx

あるいは、代わりに前半を短くすると効果的に同じようになりますが、1ベースのインデックス付けが使用される場合があります。

  • .i(<[x]+\i>+(12文字)-(1から始まる)インデックスの要素をi値に置き換えますx

上記のすべての例で、xが数値である場合、2つの文字を保存するために角括弧を省略してもかまいませ+ん。とにかく配列に自動強制されるためです。

  • .i<x+\i>+(9文字)- x(0から始まる)インデックスで配列に数値を挿入しますi
  • .i<x+\i)>+(10文字) -で要素を交換(0系)のインデックスi番号とx
  • .i(<x+\i>+(10文字)-(1から始まる)インデックスの要素をi数字に置き換えますx

括弧は、次のいずれかの場合に省略できます。 xまたは入力 "配列"(または両方)が実際に文字列である場合、その場合、結果も文字列に強制変換されます(通常の配列→文字列変換規則を使用)。


追伸 特殊なケースとして、配列に〜2 i× i要素があることがわかっている場合、x(0ベースの)インデックスii/[x]*(6文字)で新しい要素を挿入できます。これが実際に行うのは、配列をi要素までのチャンクに分割し、x各チャンクの間に挿入することです。この場合、x数字であっても括弧が必要なことに注意してください。


Pps。別のアプローチは、動的に名前が付けられた変数を使用することです。例えば、

 'foo' 42 ':x'\+~

'foo'変数x42に値を割り当てますが、

 42 'x'\+~

それを取得します。

これをさらに最適化するには、xプレフィックスを省略し、数値リテラルに直接割り当てるだけです。これはGolfScriptで完全に正当であり、割り当てコードから1つの文字を保存し、検索コードをただ`~(またはインデックスは一定です!)。欠点は、もちろん、数値リテラルに代入すると、コード内の他の場所でそのリテラルの値がオーバーライドされることです。ただし、多くの場合、数値リテラルの使用は回避できます(または、少なくともプログラムの先頭に制限してから、それらのいずれかを再割り当てします)。この場合、このトリックは完全に問題ありません。


3
完全にトピック外:10kでおめでとうございます!:-D
ドアノブ

1
あなたは、配列が重複する値を持っていないことがわかっている場合は、インデックスの値を置き換えることができますi9バイトのために:.[i=]/[x]*
マーティン・エンダー

5

最終出力操作

デフォルトでは、プログラムが終了すると、GolfScriptインタープリターは、プログラムが次のように終了したかのように、スタック上のすべてと最終的な改行を出力します。

]puts

ドキュメントが直接言及していないのは、インタープリターが文字通り組み込みを呼び出してputsこの出力を生成し、この組み込みが文字通り次のように定義されていることです。

{print n print}:puts;

したがって、あなたが抑制または再定義することで最終的な出力を操作することができputsprint および/またはn(または あなたがしている感じが本当にねじれている場合)。ここではいくつかの例を示します。

最終改行を抑制する:

'':n;

(もちろん、除外することができます ;、スタック上の余分な空の文字列を気にしない場合は省略できます。)

最終出力を完全に抑制する:

:puts

これputsは、スタックの一番上にあるもので上書きされます。それが実行したくないものである場合は、0:puts;代わりにegを使用できます。これによりp(として定義される{`puts}:p;)も抑制されることに注意してください。ただし、print必要に応じて出力に引き続き使用できます。


そして、nothingあなたはどういう意味\nですか?
電卓

末尾の改行を気にしない場合は、];最終出力を抑制するためにも使用できます。
wastl

5

最善の方法、最小値、最大値、絶対値を尋ねたいと思います。私のソリューションはすべて、必要以上に多くのキャラクターを採用しているようです。–クラウディウ

最小/最大

配列の最小値/最大値を見つけるには、並べ替えて最初/最後の要素を取得するだけです:

  • $0= (3文字)-arryの最小要素
  • $-1= (4文字)-配列の最大要素

配列の長さがわかっていて、それが10要素以下の場合-1、最後の要素のインデックスに置き換えることにより、3文字で最大値を見つけることができます。

スタックに値がある場合、最初にそれらを配列に収集するだけです。このため[\]、スタックの上位2つの要素を配列に[@]収集し、上位3 つの要素を収集するという便利なトリックがあります。したがって、次のようになります。

  • [\]$0= (6文字)-スタック上の最小2つの値
  • [@]$0= (6文字)-スタック上の最小3つの値
  • [\]$1= (6文字)-スタック上の最大2つの値
  • [@]$2= (6文字)-スタック上の最大3つの値

同じトリックを使用して、3つの値の中央値を見つけることもできます。

  • [@]$1= (6文字)-スタック上の3つの値の中央値

スタックに元の値を残したまま 2つの値の最小値/最大値見つけるための、別の潜在的に有用なトリックを次に示します

  • .2$>$ (5文字)-元の値を変更せずに、スタック上の最小2つの値を見つけます
  • .2$<$ (5文字)-元の値を変更せずに、スタック上の最大2つの値を検索します

それが動作する方法は、すなわち.2$クローン逆の順序でスタック(すなわち、一番上の二つの要素a ba b b a</ >コピー戻る0または1であり、スカラー比較$をコピーいずれかの比較結果に応じて、2つの入力値のを。


スタックに2つの非負整数がある場合、,\,&,(5文字)を使用して最小値を見つけ、,\,|,(5文字)を使用して最大値を見つけることができます。このトリックは、範囲全体でそれぞれ積集合と集合を使用します。,引数を交換せずに各引数に個別に適用できる場合は、別の文字を保存できます。このメソッドは各引数の範囲を計算するため、大きな数値ではあまり効率的ではありませんが、小さな入力では非常に便利です。

スタック上の最小の2つの非負整数を見つけるさらに短い方法は,<,(3文字)です。残念ながら、このトリックは最大値を見つけるためには機能しません。


絶対値

GolfScript 組み込みの絶対値演算子abs(3文字)です。これは私が好むよりも2文字多いですが、一般的に打つのは難しいです。

場合によっては(たとえば、絶対値でソートする場合)、数値の2乗がその絶対値の適切な代替となることがあります。これは、2?またはの2つの文字で計算できます.*。したがって、次のようになります。

  • {.*}$0= (7文字)-配列の絶対値による最小要素
  • {.*}$-1= (8文字)-配列内の絶対値による最大要素

同様に、たとえば数値の絶対値が3未満abs 3<(スペースを含む6文字)であるかどうかをテストする代わりに、正方形が9未満.*9<(4文字、スペース不要)であるかどうかをテストできます。


スタックに2つの非負整数がある場合、,\,&,(5文字)を使用して最小値を見つけ、,\,|,(5文字)を使用して最大値を見つけることができます。このトリックは、範囲全体でそれぞれ積集合と集合を使用します。,引数を交換せずに各引数に個別に適用できる場合は、別の文字を保存できます。このメソッドは各引数の範囲を計算するため、大きな数値ではあまり効率的ではありませんが、小さな入力では非常に便利です。
KirarinSnow

@KirarinSnow:ありがとう!答えに追加しました。
イルマリカロネン14年

4

アレイから重複を削除する

集合演算子|(結合)、&(交差)、および^(対称差)は、複数の配列要素を1つにまとめます。したがって、配列から重複した要素を削除する最も簡単な方法は、それ自体との結合または交差を取ることです。

.|

または:

.&

これらの演算子は文字列を文字の配列として扱うため、文字列から重複する文字を削除するためにも使用できます。


4

限られた音訳

特定のサブtr質問に対処するには:文字列を指定して、実行する最良の方法は何ですか?例えばtr/ABC/abc/

文字列内のすべての文字が影響を受ける場合、これは非常に簡単です:({'ABC'?'abc'=}%オーバーヘッド:9文字)。

ただし、文字の一部が音訳されていない場合、それは壊れ、'ABC'?が与えられ-1ます。

文字変換が非周期的である場合、文字列の分割と結合で一度に1つの置換を実行できます'AaBbCc'1/2/{~@@/\*}/(オーバーヘッド:15文字)。これは改善可能かもしれませんが、現在より優れており、周期的な音訳に有効な代替アプローチがあります。

現在、最も短い一般的なソリューションには、14文字のオーバーヘッドがあります。

  • :一つのアプローチは、エスケープ文字が含ま、リテラルのnullバイトを意味します。(もちろん、この方法は完全ではありません{.'ABC'?'abc0'=\or}%0一般的なものではありません。他の文字をヌルバイトにマッピングすることはできません。)

  • または、{.'ABC'?'abc'@),+=}%同じオーバーヘッドがありますが、印刷可能なASCII文字のみを使用します。これ@),+は、置換文字列が常に入力文字で終わるようにするための複雑な(ただし、明らかに最短の)方法です。


最後のアプローチを使用して、入力文字列に対して'ABCDEF'結果を取得します'abc000'が、正しい結果はになります'abcDEF'。何か不足していますか?
クリスチャンルパスク

1
@ w0lf、それは前述のエスケープ文字なので0が太字になっていること-つまりバイト0
ピーター・テイラー

4

文字列をcharの配列に変換します

これを行うには、1/その後に「:」と入力します 。

例: "String"1/プッシュして配列をスタックします['S''t''r''i''n''g']

これは、文字列の周りで文字を移動する場合に便利です。


1
これがどのように役立つか例を示してもらえますか?文字列はすでに配列のように振る舞うため、これはそれほど有用ではないようです。
ジャスティン14年

あなたはそれらのASCII値出ていない文字をポップにしたいとき@Quincunxそれは便利です
user3700847

そしていつそれをしたいですか?
ジャスティン

5
@Quincunx:たとえば、文字列の回転。"abc"1/(+-> "bca"、しかし"abc"(+-> bc97
デニス14

4

数値リテラルへの割り当て

多くの場合、1:x変数を記述してから使用/更新する代わりに、直接x使用して1直接更新することができます:

1:^;{^.p.+:^;}5*
{1.p.+:1;}5*       (4 bytes shorter)

もちろん、これは他の開始値に対しても機能しますが、その値がコードの他の場所で発生すると壊れます。

変数名としての句読点

あなたがいる場合持っている変数を使用するために、それはしばしば賢明な利用にもあなたのコードになっていない句読点だ-プログラムの多くはせずに行うことができます&|^、または?。この方法では、たとえば、変数をプッシュしてから改行をプッシュする&n代わりに書くことができx nます。


3
ただし、割り当てによっては予期しない副作用が生じる場合があります。具体的には、への割り当ては、!それが壊れると、多くの場合、悪い考えであるifdo(だけでなくwhileuntilandorおよびxor)。同様に、はのorエイリアスとしてインタープリターによって定義されているため1$\if、を再定義1する$か、それ\を壊します。`ブレークの再定義p
イルマリカロネン

3

配列のフィルタリング

配列をフィルター処理する最も一般的な方法は、を使用することです{ },。これは、配列の各要素のコードブロックを評価し、結果の値が真である要素を選択します(grepPerlのように動作します)。

ただし、配列減算演算子を使用する-方が短いことがよくあります。この演算子は2つの配列を取り、最初の配列から2番目の配列に出現するすべての要素を削除します。最初の配列の要素の順序を変更したり、重複を折りたたみませ。便利なトリックは、減算演算を2回適用して、崩壊しない配列交差演算子を生成することです。

  • a b -:配列bから見つかった要素を配列から削除しますa
  • a. b --:配列にない要素を配列bから削除しますa

特に、これは配列内で要素が出現する回数カウントするために使用できます。

  • a.[c]--,c配列内で要素が出現する回数をカウントしますa

一般に、次のいずれかの理由により、この方法は最適ではありません。

  • a[c]/,(c配列内で要素が出現する回数をカウントしますa
  • a{c=},,c配列内で要素が出現する回数をカウントしますa

は1文字短くなります(また、カウントが1つずつずれていても問題ない場合は、a[c]/,さらに1文字節約されます)。ただし、がc数値でaあり、通常の配列(文字列ではない)である特殊なケースではc-演算子が引数を同じ型に強制するため、角括弧を省略できます。

  • a.c--,c配列内で発生する回数を数えます(文字列ではありません!)a

aが文字列cで0〜9 a.c--の数値の場合、数字 cがで発生する回数をカウントしaます。)


同様のトリックを使用して、配列内最も一般的な要素を見つけることができます。

:a{a\[.]-,}$0=

繰り返しますが、入力が数値の配列である場合、[.]シーケンス全体を省略できます。残念ながら、これはのない文字列では機能しませ[.]


カウント出現(一般の場合)のために、a[c]/,(そしてa{c=},,短い1バイトです。
デニス14年

@デニス:ありがとう!私は中にいることを編集した。
イルマリKaronen

3

STDINから読み取る

GolfScriptはstdinから読み取ることができます。

"#{STDIN.read}"

これは、EOFに達するまでSTDINから読み取りを続けます。代わりに:

"#{STDIN.gets}"

または

"#{STDIN.readline}"

利用可能な他のもの:

getbyte
getc
gets([sep])
gets(limit)
gets(sep, limit)
inspect # perhaps useful for an underhanded contest
isatty
read([length])
readbyte
readchar
readline([sep])
readline(limit)
readline(sep, limit)
readlines([sep])
readlines(limit)
readlines(sep, limit)
readpartial(maxlen [, outbuf])

これらのそれぞれに対して、それらは1回だけ使用できます(また、パラメーターの変更ごとに1回、空の括弧でもう一度使用できます)。その後、元の値が新しい値ではなく取得されます。


2
{"#{STDIN.readline}"p}2*2行を読み取らないが、代わりに文字列が1回だけ評価されるコメントを追加することができます。
ハワード14年

2
i整数に初期化する'"#{'i):i';STDIN.gets}"'++~と、評価されるたびに異なる結果が得られます。バックティックも言及する価値があります。Linuxを想定している場合、たとえばの`head -1`代わりに使用できますSTDIN.gets
デニス14年

@Dennis:"#{var'g','gpush Gstring.new(STDIN.gets)'.cc}";また、stdinから行を読み取り、スタックにプッシュする新しいGolfScript演算子定義できgます。
イルマリカロネン

2

16進入力のデコード

GolfScriptには16進整数リテラルがないため、残念ながら、で16進入力を解析することはできません~。代わりに、コードが16進入力を取る必要がある場合は、手動で解析する必要があります。

文字列に適用されるこの8文字のループは、小文字の16進数を同等の数値に変換します。

{39%9-}%

大文字の16進数を(も)受け入れる必要がある場合、最も簡単な(そしておそらく最も短い)解決策は、最初にそれらを小文字32|で、合計11文字にすることです:

{32|39%9-}%

出力は技術的には文字列(ASCII文字0〜15で構成される)のままですが、ほとんどのGolfScript配列関数も文字列を受け入れます。絶対に配列が必要な場合は、いつでも使用できます[{39%9-}/][スタックが空の場合、最初の配列はオプションです)。

上記のコードの出力を整数に変換するには、単純に16base(6文字)を使用できます。代わりにバイトの配列が必要な場合は、16進数の各ペアを2/{16base}%(11文字)で単にデコードすることで見つけた最短の解決策です。まとめると、16進文字列をバイト配列に変換するために見つけた最短のコードは8 + 11 = 19文字です。

{39%9-}%2/{16base}%

このコードの出力は、実際には文字列ではなく配列であることに注意してください。必要に応じて、たとえば""+またはで連結して文字列化できますn+。最後に余分な改行が必要ない場合は、


2

新しい組み込み演算子の定義

標準のGolfScriptインタープリターには、二重引用符で囲まれた文字列リテラルで補間されたRubyコードを許可する、めったに使用されない機能があります。

この機能がより一般的に使用されない理由の1つは、厄介なことに、補間コードがコンパイル時に実行されることです。に、出力がGolfScriptインタープリターによってキャッシュされるため、その後も同じ文字列リテラルが常に同じ値を生成するためです文字列評価。

ただし、この機能の利点の1つは、Rubyコードで実装された新しいGolfScript演算子を定義することです。たとえば、標準の組み込み演算子と同じように機能する新しいバイナリ加算演算子を定義する方法は+次のとおりです。

"#{var'add','gpush a+b'.cc2}";

コードのどこに定義を入れてもかまいません。new演算子は、Rubyコードを含む二重引用符で囲まれた文字列が解析されるとすぐに定義されます。add作品上で定義された演算子を正確に内蔵されたような+オペレータ、およびまったく同じように使用できます。

1 2 add          # evaluates to 3
"foo" "bar" add  # evaluates to "foobar"

もちろん、組み込み演算子を消去するような愚かなことをしていない限り、新しい加算演算子を定義することはほとんど役に立たない+。しかし、同じトリックを使用して、Golfscriptがネイティブに(簡単に)できないことを行う新しい演算子を定義できます。たとえば、配列を均一にシャッフルするなどです。

"#{var'shuf','gpush a.factory(a.val.shuffle)'.cc1}";

10,shuf          # evaluates to 0,1,2,...,9 in random order

または、スタック全体の内容を印刷します。

"#{var'debug','puts Garray.new($stack).ginspect'.cc}";

4,) ["foo" debug  # prints ["" [0 1 2] 3 "foo"], leaving the stack untouched

またはインタラクティブな入力:

"#{var'gets','gpush Gstring.new(STDIN.gets)'.cc}";

]; { "> " print gets ~ ]p 1 } do   # simple GolfScript REPL

またはWebアクセス:

"#{
  require 'net/http'
  require 'uri'
  var'get','gpush Gstring.new(Net::HTTP.get_response(URI.parse(a.to_s)).body)'.cc1
}";

"http://example.com" get

もちろん、後者のややゴルファーな(そしてより危険な!)実装は次のようになります:

"#{var'get','gpush Gstring.new(`curl -s #{a}`)'.cc1}";

それ自体は特にゴルフではありませんが、これにより、組み込みコマンドが提供するものを超えてGolfScriptの機能を拡張できます。


どのように機能しますか?

この方法で新しいGolfScriptオペレーターを定義する方法に関する信頼できるリファレンスは、もちろんインタープリターのソースコードです。。とはいえ、ここにいくつかの簡単なヒントがあります。

  • nameRubyコードを実行する新しい演算子を定義するにはcode、次を使用します。

    var'name','code'.cc
  • コード内でを使用gpopして、スタックから値を読み取り、gpush1つをプッシュバックします。また、配列を介してスタックに直接アクセスすることもできます$stack。たとえば、両方abスタックにプッシュするには$stack<<a<<b、ゴルファーよりもgpush a;gpush b

    • [配列の開始マーカーの位置は、配列に保存され$lbます。このgpop関数は、スタックがその位置よりも小さくなった場合にこれらのマーカーを調整しますが、$stack配列を直接操作してもしません。
  • .ccGolfScriptオペレータに文字列にRubyコードをコンパイル列方法は、ラッパーだけ便宜ですGblock.new()。また、バリアントを持っている.cc1.cc2そして.cc3それは、オペレータが自動的にスタックから1、2または3つの引数をポップし、変数に割り当てる作るabc.order同様.cc2に機能するメソッドもありますが、タイプ優先度によって引数を自動的にソートします。

  • GolfScriptスタック上のすべての値がある(とする必要があります!)型のオブジェクトGintGarrayGstringまたはGblock。基になるネイティブ整数または配列は、必要に応じて、.valメソッドを介してアクセスできます。

    • ただし、sのGstring.val配列を返すことに注意してくださいGint!をGstringネイティブのRuby文字列に変換するには、.to_s代わりに呼び出します(または、文字列補間のように自動的にそれを行うコンテキストで使用します)。.to_gsGS値を呼び出すと、aに変換されるGstringため、GS値はで文字列化できます.to_gs.to_s
  • このgpush関数は、ネイティブのRubyの数値、文字列、または配列を対応するGS型に自動ラップしないため、明示的に次のように呼び出すことで、多くの場合自分で行う必要がありますGstring.new()。GS値タイプの1つ以外をスタックにプッシュすると、後でそれを操作しようとするコードがクラッシュする可能性があります。

  • GS値型に.factoryは、型のコンストラクターを呼び出すメソッドもあります。これは、たとえば、コンテンツを操作した後に配列/文字列を再ラップする場合に便利です。すべてのタイプも持って.coerce行うことメソッド型変換はa.coerce(b)を含む一対の戻りab同じ型に強制します。

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