CJamでのゴルフのヒント


43

CJamは、PPCGユーザーaditsuによって作成されたGolfScriptにヒントを得たスタックベースのゴルフ言語です

そのため、他の言語固有のヒントの質問に沿って:

CJamでゴルフをするための一般的なヒントは何ですか?回答ごとに1つのヒントを投稿してください。


4
GolfScriptでのゴルフのヒントも参照してください。言語は十分に類似しているため、多くのトリックをどちらの方法でも適合させることができます。
イルマリカロネン14年

2
@IlmariKaronenその質問の回答を読んだ後、言語の構文的または論理的な違いのために、CJamに適用されるのは約半分しかないと思います。
オプティマイザー14年

回答:


23

負数のモジュロを修正

モジュロ演算の結果が第1オペランドと同じ符号を与えることはしばしば迷惑です。例えば-5 3%、の-2代わりに与える1。多くの場合、後者が必要です。素朴な修正は、モジュロを適用し、除数を一度追加し、モジュロを再度適用することです:

3%3+3%

しかし、それは長くていです。代わりに、配列のインデックス付けは常にモジュラーであり、負のインデックスで正しく機能するという事実を使用できます。したがって、除数を範囲に変えて、それにアクセスします。

3,=

に適用すると-5、これは1予想通りになります。そして、組み込みよりも1バイトだけ長くなってい%ます!

モジュラスが2のべき乗である場合、ビット単位の算術演算を使用して別のバイトを保存できます(これも非常に高速です)。比較する:

32,=
31&

65536 == 2^16別のバイトの特殊なケースでは、文字タイプの折り返し動作を利用することで保存できます。

ci

13

連結文字範囲のプッシュ

  • すべての数字を含む文字列"0123456789"は次のように書くことができます

    A,s
    
  • 大文字のASCII文字(A-Z)は次のようにプッシュできます。

    '[,65>
    

    Zまでのすべての文字のストリングを生成し、最初の65(@まで)を破棄します。

  • すべてのASCII文字(A-Za-z)は、次のようにプッシュできます。

    '[,65>_el+
    

    上記のように機能し、コピーを作成し、小文字に変換して追加します。

    しかし、もっと簡単な方法があります!

    次に、見落とされがちな^演算子(リストの対称差)により、3バイトを節約しながら同じ範囲を作成できます。

    '[,_el^
    

    '[,までのすべてのASCII文字の範囲を作成し、Z_el小文字のコピーを作成し、^1ではなく、両方に表示され、両方の文字列の文字のみを保持します。

    最初の文字列のすべての文字は大文字であるため、2番目の文字はすべて小文字であり、すべての非文字は両方の文字列にあり、結果は文字列になります。

  • RFC 1642 Base64アルファベット(A-Za-z0-9+/)は、上記の手法を使用して非文字を追加してプッシュできます。

    '[,_el^A,s+"+/"+
    

    この文字列をプッシュする同様に短い方法は、対称的な違いのみを使用します。

    "+,/0:[a{A0":,:^
    

    最初に文字列を見つけるにはどうすればよいですか?

    全て使用する文字の範囲は(A-Za-z0-9+/)ヌル・バイト、すなわちで開始範囲の対称差としてプッシュすることができ'A,'[,^'a,'{,^'0,':,^'+,',,^および'/,'0,^

    したがって、:,:^on "A[a{):+,/0"を実行すると、目的の文字がプッシュされますが、正しい順序ではありません。

    正しい順序を見つけるにはどうすればいいですか?野Bruな力で救出せよ!プログラム

    '[,_el^A,s+"+/"+:T;"0:A[a{+,/0"e!{:,:^T=}=
    

    文字列のすべての可能な順列を反復し:,:^、結果を適用して、目的の出力と比較します(permalink)。

  • たとえば、crypt(.-9A-Za-z)で使用される基数64のアルファベットは、上記の方法を使用して生成できます。

    ".:A[a{":,:^
    

    これは私が知っている最短の方法です。

    目的の出力のすべての文字はASCII順であるため、順列を反復処理する必要はありません。

  • を使用して、連結されたすべての文字範囲を希望の順序でプッシュできるわけではありません:,:^

    たとえば、の順列を0-9A-Za-z;-?実行:,:^して範囲をプッシュすることはできません"0:A[a{;@"

    ただし、次のコードを使用して、目的の文字列の回転したバリエーションを見つけることができます

    A,'[,_el^'@,59>]s2*:T;"0:A[a{;@"e!{:,:^T\#:I)}=Ip
    

    次を印刷(パーマリンク)します:

    10
    0:@[a{A;
    

    この意味は

    "0:@[a{A;":,:^Am>
    

    と同じ効果があります

    A,'[,_el^'@,59>]s
    

    これは、先頭にaを付加せずに空のスタックでのみ使用できます[


11

{…} {…}を避けますか?

スタックに整数があると仮定します。奇数の場合は、3を掛けて1を加算します。それ以外の場合は、2で除算します。

「通常の」if / elseステートメントは次のようになります。

_2%{3*)}{2/}?

ただし、{}{}すでに4バイトが追加されているため、ブロックを使用する方法は通常は使用できません。?スタック上の2つのアイテムのいずれかを選択するためにも使用できます。

_2%1$3*)@2/?

これは1バイト短くなります。


ブロック-?空のifステートメントは常にノーゴーです。例えば、

{}{2/}?

より2バイト長い

{2/}|

代わりに持っている場合

{2/}{}?

そして、あなたがチェックしているものは非負の整数です、あなたはすることができます

g)/

新しい{}&{}|あなたがスタックを乱雑にすることができない場合に便利な、時には問題があります。

それでも、の場合

_{…}{;}?

代わりに一時変数を使用できます。

:T{T…}&

1
!)/そしてg)/例に短くなっています。
jimmy23013

11

Switchステートメント

CJamにはswitchステートメントがありません。ステートメントが同様に機能する場合にネストされますが、{{}{}?}{}?すでに12バイトの長さです...

条件を負でない小さな整数に変換できる場合、区切り文字列のすべてのcaseステートメントを変換し、対応する結果を評価できます。

たとえばcode0、スタックの整数が0であるcode1場合、1であるcode2場合、および2である場合に実行する場合、次のいずれかを使用できます。

_{({code2}{code1}?}{;code0}?

または

[{code0}{code1}{code2}]=~

または

"code0 code1 code2"S/=~

S/文字列を["code0" "code1" "code2"]に分割し=、対応するチャンクを抽出して~、コードを評価します。

ここをクリックて、実行中のswitchステートメントを確認してください。

最後に、@ jimmy23013と@RetoKoradiが示唆するように、場合によってはスイッチをさらに短くすることができます。言うcode0code1そしてcode2持っている長さL 0L 1およびL 2のそれぞれを、。

もしL 0 = L 1 ≥L 2

"code0code1code2"L/=~

代わりに使用することができ、ここLL 0。区切り文字で/分割する代わりに、ここで文字列を等しい長さのチャンクに分割します。

もしL 0 ≥L 1 ≥L 2 ≥L 0 1 -

"cccooodddeee012">3%~

代わりに使用できます。>文字列の先頭から0、1、または2つの要素を削除し、3%3番目ごとに要素を抽出します(最初の要素から開始)。


最後の例では、それは何か利点があり "code0code1code2"5/=~ますか?私にはもっと簡単に思えます、そしてそれは同じ長さです。
レトコラディ

@RetoKoradiすべてのスニペットの長さが同じ場合、利点はありません。異なる長さの場合、メソッドはモジュラスメソッドよりも短くても長くてもかまいません。
デニス

11

ゴルフの一般的な配列と文字列値

グリッドを初期化するなど、時々現れる特定の短い配列または文字列があります。単純に、これらは4バイト以上のコストがかかる可能性があるため、同じ結果をもたらす組み込み値の操作を探す価値があります。特に、ベース変換はしばしば有用です。

  • [0 1]と書くことができます2,
  • [1 0]として書くことができますYYb(つまり、バイナリで2)。
  • [1 1]と書くことができますZYb(つまり、バイナリで3)。
  • 行列[[0 1] [1 0]]はと書くことができます2e!
  • [LL]SS/(単一のスペースをスペースで分割する) と書くことができます。
  • "\"\""と書くことができますL`
  • "{}"と書くことができます{}s

後者は、すべてのブラケットタイプで別のバイトを保存する場合に拡張できます。

  • "[{<()>}]"と書くことができます{<()>}a`
  • "()<>[]{}"と書くことができます{<()>}a`$

特に、ベース変換のトリックは、時々ポップアップする不明瞭なケースに留意するのに役立ちます。例えば[3 2]あろうE4b(ベース4における14)。

さらにまれなケースでは、因数分解演算子がmf役立つことさえあります。例えば[2 7]ですEmf

他の例に出くわした場合は、このリストを自由に拡張してください。


10

スタックをクリアする

スタック全体をクリアする場合は、配列にラップしてポップします。

];

もう少し注意が必要なのは、多くの計算を行ったが、一番上のスタック要素を保持し、その下のすべてを破棄したい場合です。素朴なアプローチは、変数に一番上の要素を保存し、スタックをクリアし、変数をプッシュすることです。しかし、はるかに短い選択肢があります:スタックを配列にラップし、最後の要素を抽出します:

]W=

(先日これを見せてくれたOptimizerに感謝します。)

もちろん、スタックに要素が2つしかない場合\;は、より短くなります。


\;TOSの下の要素のみをポップします。もしかして;;
電卓

1
@CalculatorFeline答えの後半は、TOS以外のすべてをクリアすることです。
マーティンエンダー

9

e そして10のべき乗

他の多くの言語と同様1e31000、CJamの代わりに書くことができます。

これは、整数以外の基数、および整数以外の指数に対しても機能します。例えば、1.23e2プッシュ123.0及び1e.5プッシュ3.1622776601683795を(の平方根10)。

すぐには明らかにならないのは、1e3実際には2つのトークンであるということです。

  • 1スタックに整数1をプッシュします。

  • e31000で乗算します。

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

  • e<numeric literal>既にスタック上にあるものを呼び出すことができます。

    2 3 + e3 e# Pushes 5000.
    
  • e<numeric literal>配列にマップできます。

    5 , :e3  e# Pushes [0 1000 2000 3000 4000].
    

9

ユークリッド規範

ベクトルのユークリッドノルム、つまりその要素の平方和の平方根を計算する簡単な方法は、

2f#:+mq

ただし、はるかに短い方法があります。

mh、斜辺演算子は、スタックから2つの整数abをポップし、sqrt(a 2 + b 2をプッシュします。

スタック上にベクトルx:= [x 1 …x n ]、n> 1がある場合、:mh(斜辺によって減少)は以下を達成します。

  • 最初にx 1x 2がプッシュmhされて実行され、スタックにsqrt(x 1 2 + x 2 2)が残ります。

  • 次に、x 3がプッシュmhされて再び実行され、スタックに
    sqrt(sqrt(x 1 2 + x 2 22 + x 3 2)= sqrt(x 1 2 + x 2 2 + x 3 2が残ります。

  • のx nは処理されている、我々はと残されているのsqrt(X 1 2 +···X N 2、のユークリッドノルムXを

場合N = 1及びX 1 <0は、上記のコードは、誤った結果を生成します。:mhz無条件に動作します。(指摘してくれた@MartinBüttnerに感謝します。)

この答えでこのトリックを初めて使用しました。


2
もちろん、これは...あなたのプログラムの数値解析のための意味合いを持っている
ピーター・テイラー

8

基数nからnより大きい数のリストに変換します

CJamは、リストを次の式で数値に変換します:A 0 * n l + A 1 * n l-1 + A 2 * n l-2 + A l * n 0(非負n)。nはベースでl、リストの長さです。これは、A iが任意の整数であり、の範囲にある必要がないことを意味します[0,n)

いくつかの例:

  • 0b最後のアイテムを抽出し、整数にキャストします。W=i整数ではない場合、バイトのように機能し、保存します。ただし、リスト内の他のすべても整数にキャストできる必要があります。
  • 1b合計を返します。:i:+整数でなかった場合のように動作し、2バイトを節約します。空のリストでも機能しますが、:+機能しません。
  • [i{_1&9 32?_@\m2/}16*;]W%:c文字を行末とタブの文字列に変換します。これは、で変換し直すことができます2bc。ただし、エンコード関数は、コードゴルフプログラムで簡単に操作することはできません。ただし、通常は必要ありません。
  • 次のコードを使用して、文字列を16ビットではないUnicode文字に変換できます2A#b128b:c。これはで変換できます。(説明は後で追加されます。または、新しいバージョンを後で書くかもしれません。)

    128b2A#b         " Convert to base 1024. ";
    W%2/)W%\:+       " Convert to two base 1024 digit groups. ";
    [0X@
    {
      _54+
      @I+_Am>@\-
      _Am<@+ 0@-@1^
    }fI
    ]);)
    @\+[~+]2A#b_2G#<!{2A#b}*
    \W%+:c
    

同様の方法は、最上位桁を取り除く何らかの方法を見つけることができる場合、n異なる値modを持つ整数のセットで機能しますn


8

$三項としての使用if

メモリのリークを気にしない場合、つまり、後でクリアするスタックに未使用の要素を残す];場合、コピー演算子$は三項演算子の代わりに便利?です。

? 選択する2つのアイテムをプッシュする前に条件を計算できればうまく機能しますが、多くの場合、条件は実際にはそれらのアイテムに依存し、それらの上に置くことでより自然になります。

あなたが持っている場合はA B C、スタック上で、あなたが実行することができます

!$

の代わりに

\@?

真実BかどうかをコピーCAます。

場合C(実際のブール型である01)、あなたが実行することができます

$

の代わりに

@@?

真実AかどうかをコピーCBます。


後から考えると、これはかなり明らかなトリックですが、私はそれを考えたことがありませんでした。この答えで初めて使いました。
デニス

7

ネストされたリストのマップ

マトリックスのようなネストされたリストがあるとします:

[[0 1 2][3 4 5][6 7 8]]

または文字列の配列:

["foo""bar"]

そして、ネストされたレベルにブロックをマップする(つまり、各番号または各文字に適用する)必要があります。素朴な解決策は、ネストされてい%ます:

{{...}%}%

ただし、実際には内部ブロックをスタックにプッシュしてからを使用できますf%fは「追加パラメータ付きのマップ」であるため%、ブロックを2番目のパラメータとして使用して、外部リストにマップします。

{...}f%

2バイト節約します。

のような何かをするためのもう一つのきちんとしたトリックfor (i=0; i<5; ++i) for (j=0; j<5; ++j) {...}

5,_f{f{...}}

外側fは最初の範囲にマッピングされ、2番目の範囲を追加パラメーターとして提供します。しかし、今度は、fもう一度使用すると、一番上のスタック要素のみが配列になるためf、内側のブロックをその上にマッピングし、追加のパラメーターとして外側の「反復変数」を指定します。これは、内部ブロックがスタック上iおよびjスタック上で実行されることを意味します。

これは、ブロックをデカルト積にマッピングするだけの文字数と同じです(ただし、ペアを配列として必要とする場合、後者は短くなります)。

5,_m*{~...}%

違いは、このバージョンではすべてのペアに対して単一の配列の結果がf得られるのに対して、double- はネストされたリストを生成することです。これは、結果をグリッドに格納する場合に役立ちます

このトリックを見せてくれたデニスに感謝します。

0.6.4アップデート

fそして:、自分自身を含む他のオペレーターを採用することで、大幅に改善されました。これは、さらに多くのバイトを節約できることを意味します。ネストされたリストへの演算子のマッピングがさらに短くなりました。

{:x}%
{x}f%
::x

ただし、これはブロックをネストされたリストにマッピングするのにはあまり役立ちません。

デカルト積へのブロックまたは演算子の適用に関しては、ブロックと演算子の場合、これも短くなりました。

5,_f{f{...}}
5,_ff{...}

5,_f{fx}
5,_ffx

素晴らしいのは、これらをネストできるようになったことです。そのため、リストの3番目のレベルに同じように簡単に演算子を適用できます。

:::x

または、いくつかのトリックのあるブロック:

{...}ff%

素晴らしいアップデート。しかし、まだありませf~
...-jimmy23013

@ user23013 fは二項演算子を想定し、~単項です。おそらくしたい:~ですか?また、チャットで
-aditsu

この0.6.4の更新について何か不足していますか?Unhandled char after ':': :リンク
-Runer112

2
@ Runer112は私のために働く。適切にリロードしてください(つまり、キャッシュからではない)。ブラウザによっては、Ctrl + F5が機能するはずです。
マーティンエンダー

@MartinBüttnerそれは確かに愚かなキャッシュによって引き起こされました。ありがとう。
Runer112

7

ASCIIアートのベクトル化された演算子

多くのASCIIアートの課題では、後で重ね合わせるために2つの異なるパターンを生成すると便利です。ベクトル化された演算子は、さまざまな種類の重ね合わせを実現するのに非常に役立ちます。

演算子ベクトル化の有用な特性の1つは、短い文字列/配列の各要素に対して演算子が1回だけ実行され、対応するものがない大きな要素の要素は変更されないことです。

  • .e<

    最小演算子e<は、文字列、文字、配列、整数のペアに対して機能します。スタックから2つのアイテムをポップし、eを押し下げます。

    スペースは、他のすべての印刷可能なASCII文字よりもコードポイントが低いため、.e<生成されたパターンの一部を「消去」するために使用できます。

    "\/\/\/\/\/" "    " .e<
    
    e# This pushes "    \/\/\/".
    

    完全な例については、Me Want Honeycombへの私の回答を参照してください。

  • .e>

    最大演算子e>は最小演算子として機能し、逆の結果になります。

    繰り返しになりますが、スペースのコードポイントが低いため、スペース.e>のブロックに印刷可能な文字のパターンを挿入するために使用できます。

    [[" " " " " " " "] [" " " " " " " "]][["+" "" "-" ""]["" "*" "" "/"]] ..e>
    
    e# This pushes [["+" " " "-" " "] [" " "*" " " "/"]].
    

    完全な例については、Seven Slash Displayに対する私の回答を参照してください。

  • .e&

    論理AND演算子e&は、偽の場合は左の引数をプッシュし、そうでない場合は右の引数をプッシュします。

    どちらのパターンにも偽の要素が含まれていない場合、これを使用して、あるパターンを別のパターンに無条件に課すことができます。

    "################" " * * * *" .e&
    
    e# This pushes " * * * *########".
    

    完全な例については、アメリカ国旗の印刷に対する私の答えをご覧ください

  • .e|

    論理OR演算子e|は、上記のように、引数の順序を逆にして使用できます。

    " * * * *" "################" .e|
    
    e# This pushes " * * * *########".
    

6

&アイテムがリストにあるかどうかを確認するために使用します

ために

1 [1 2 3] #W>
1 [1 2 3] #)

使用できます

1 [1 2 3] &,
1 [1 2 3] &

代わりに、それぞれ0/1とtruthy / falseyを返します。


6

z および非長方形配列

zip演算子zは、2次元の1配列Aの行と列を転置します。その配列要素も反復可能です。

非長方形配列の場合- zip例えば、Python(行を同じ長さに切り捨てる)やRuby(行をでnil埋める)などの組み込み関数とは異なり、CJamは単純に配列の列を行に変換し、その長さとギャップ。

たとえば、配列を圧縮する

[
  [1]
  [2 4]
  [3 5 6]
]

配列の圧縮と同等です

[
  [1 4 6]
  [2 5]
  [3]
]

または配列

[
  [1]
  [2 4 6]
  [3 5]
]

3つのアクションすべてがプッシュするように

[
  [1 2 3]
  [4 5]
  [6]
]

スタック上。

これは、それzがインボリューションではないことを意味しますが(これは場合に役立ちます)、いくつかの用途があります。

例えば:

  • 2回圧縮することにより、配列の列を一番上に揃えることができます(つまり、最初の配列を2番目に配列します)。

    zz
    
  • 上記の方法のマイナーな修正は、同様の問題に使用できます。

    たとえば、配列の列を下に揃える(つまり、2番目の配列を最初の配列にする)には、行の順序を逆にして2回圧縮できます。

    W%zzW%
    
  • 文字列の配列を指定すると、次のように最長の文字列の長さを計算できます。

    :,:e>
    

    ただし、結果の行数を圧縮して計算することで、3バイトを節約できます。

    z,
    

1 Aの「行」のいずれかが反復可能でない場合、それらをシングルトンとして扱うため、zipは任意の配列に対して機能します。z


1
同じものを視覚化するためのまったく異なる方法zですが、空の値がスキップされている間に列を行に変換することを想像すると、私にとっての動作ははるかに論理的です。この例では、入力の最初の列は1、2、3、2番目の列は4、5(空の位置はスキップされます)、3番目の列は6です。これらは結果の行です。
レトコラディ

@RetoKoradiそれはそれを説明するはるかに良い方法です。
デニス

6

例外

CJamでは例外はすべて致命的です。以来STDERRへの出力は、デフォルトでは無視され、我々は我々の利点にこれを使用することができます。

CJamのすべての演算子は、スタックから0個以上の要素をポップし、何らかのタスクを実行し、スタック上で0個以上の要素をプッシュすることで機能します。タスクの実行中に例外が発生するため、要素は引き続きポップされますが、代わりにプッシュされるものはありません。

以下にいくつかの使用例を示します。

  • 小さなスタックをクリアする

    2つの要素を含むスタックをクリアするに@は、使用できます。@3つのスタック要素をポップしようとしますが、2番目のスタック要素をポップした後に失敗します。

    3つの要素をポップする他の演算子も同じ目的に役立ちます。

    アクションでそれを参照してくださいここに

  • スタックから2つまたは3つの要素を削除する

    これらの特定の要素に実装されていない演算子は、終了する直前にスタックから2つまたは3つの要素をポップするために使用できます。

    2つの要素をポップするためにb、それらの1つが文字であるか、いずれも整数でない場合に機能します。

    3つの要素をポップするにtは、一番下の2つが反復可能でない場合、一番下の反復可能が空である場合、またはそれらのいずれも整数でない場合に機能します。

  • ループを抜ける

    場合によっては、整数がゼロになるか、文字列が短くなりすぎるとループを終了する必要があります。これらの条件をテストするのではなく、関係する操作がゼロ、空の文字列、またはシングルトンで失敗した場合、プログラムに自然なコースをとらせることができます。

    算術を含む例については、こちらを参照してください

    文字列を含む例については、こちらを参照してください

  • 条件付き実行

    特定のタイプの入力に対してソースコードを実行しない場合、その種の入力に失敗する演算子を使用できる場合があります。

    たとえばi、整数に評価されないew文字列では失敗し、長さ0または1の文字列では失敗します。

    アクションでそれを参照してくださいここに


5

配列の最大/最小

初心者向けです!

配列から最大数または最小数を見つける必要がある場合、最も簡単で最小の方法は、配列をソートしてから最初または最後の要素を取り出すことです。

配列が変数内にある場合 A

A$W=

最大

A$0=

最小値です。

両方を同時に取得することも可能です

A$)\0=

これは読んだ後は明らかなように見えるかもしれませんが、誰もが最初の試みは、配列の使用e<またはe>配列の反復を経由する傾向があります。

A{e<}*

これは2バイト長くなり、最大と最小の両方が必要な場合はさらに長くなります。


もちろん、スタックに残っている残りの配列を気にしない場合は、実際に(andの)代わりに0=andを使用できますW=
マーティンエンダー14年

今そこにある:e<:e>
aditsu

@aditsuしかし、それらは上記のヒントより短くありません。
オプティマイザー

5

大きな数値にはタイムスタンプを使用します

非常に大きいが、任意の数が必要な場合は、通常、次のような科学表記法を使用するか9e9、大きな組み込み変数のいずれかを同様の累乗、たとえばのように累乗しKK#ます。ただし、実際の数値が何であるかを気にせず、一貫して同じである必要がない場合(たとえば、乱数の上限として)、次を使用して2バイトで実行できます。

es

代わりに。これは、ミリ秒単位の現在のタイムスタンプを提供し、10 12のオーダーです。


3
また、任意の大きな数値が必要で、正の数値を一緒に破棄する場合は、を使用できることに注意してくださいe9
jimmy23013 14

5

2つの文字列/配列が等しくないことを確認する

2つの文字列または配列が等しくない場合に真実の値が必要な場合があり、そうであれば偽の値が必要です。明らかな解決策は2バイトです。

=!

等しいかどうかを確認し、結果を逆にします。ただし、いくつかの条件下では、使用できます

#

場合には、#第一(及びあなたのサブアレイが開始インデックスを与える)のサブアレイとして二番目の配列のための2つのアレイが実際の検索に適用されます。そのため、2つの配列が同じである場合、0サブ配列は開始時にすぐに検出され、偽になります。しかし、2番目の配列が見つからない場合は、-1どちらが真実かを示します。

2つの配列に追加条件が必要な理由は、2番目の配列が最初の配列の自明ではない接頭辞である場合、偽の値も生成されるためです。

"abc""ab"#

0文字列は同じではありませんが与えます。この場合を除外する最も単純な条件は、両方の配列が同じ長さになることを知っている場合です。その場合、一方が他方のプレフィックスである場合、それらが等しいことがわかります。しかし、特定の状況では、より弱い条件でも十分な場合があります。たとえば、文字列がソートされていることがわかっている場合、プレフィックスは常に2番目ではなく最初の文字列になります。


5

c および16ビット整数

適切なラッピングで符号なし16ビット整数を追加(または減算)するには、+65536%またはを使用できます+2G#%

しかしながら、

+ci

ずっと短いです。文字は65536で折り返されるため、Character(c)からLong(i)へのキャストはに似た効果があり65536%、結果が負にならないという利点もあります。

同じトリックを使用して65535をプッシュできます。

Wci

4

パワーセット

配列があり、その配列のすべての可能なサブセットを持つ配列が必要だとします。トリックは、空の配列から始めてから、各要素について、既に持っているサブセットを複製し、それらに新しい要素を追加することです(要素が追加されなかった以前の結果を保持します)。基本ケース、つまり空の配列のみを含む配列でスタックを初期化する必要があることに注意してください。これは次のようになります。

[1 2 3 4 5]La\{1$f++}/

これの良い点は、サブセットで計算をすぐに実行できることです。文字を追加する必要はありません。すべてのサブセットの製品が必要だとします。その場合、基本ケースはを含む配列1であり、各ステップで、可能な製品の前のリストを取得して複製し、複製内のすべてに新しい要素を乗算します。

[1 2 3 4 5]1a\{1$f*+}/

4

リスト内のアイテムがすべて同じかどうかを確認します

これも言及する価値があると思います。つかいます:

)-

すべてが同じでない場合は真実を返し、すべてが同じ場合は空のリストを返します。リストが空の場合のエラー。

抽出されたアイテムが配列(または文字列)自体である場合:

)a-

!または!!を使用してブール値を取得します。抽出されたアイテムが配列で、最大2種類の異なるアイテムがあり、すべて同じではないにしても1にしたい場合、これは短くなります。

_|,(

4

0= 文字列用

配列の最初の要素を取得するには、使用する必要があります0=(または(、残りの配列をスタックに残しても構わない場合は、)。

ただし、その配列が文字列の場合、文字にキャストするだけで十分です。

"xyz"c e# Pushes 'x.

なぜCJamがc配列の最初の要素を抽出させないのかわかりません。これはより便利で一貫性があります。
エソランジングフルーツ

4

配列(またはスタック)を1ユニット左に回転させる

CJamには左回転演算子m<があります。これは通常、任意の数のユニットを左に配列を回転させるために使用するものです。

では、いくつかのケースでは、あなたも使用することができます(+シフトおよび追加します:

[1 2 3]       (+ e# Pushes [2 3 1].
[[1] [2] [3]] (+ e# Pushes [[2] [3] 1].

配列の最初の要素も反復可能であるため、2番目の例は機能しませんでした+。したがって、追加ではなく連結されました。

また、スタック上の回転した配列をダンプする場合は、:\無条件で使用できます(スワッピングによって削減)。

[1 2 3]       :\ e# Pushes 2 3 1.
[[1] [2] [3]] :\ e# Pushes [2] [3] [1].

openがない限り[、このトリックを使用してスタック全体を回転させることもできます。つまり、一番下のスタックアイテムを一番上に移動します。

]:\

3

リストを印刷してスタックをクリアする

スタックに文字列/数字/などのリストがあるとしましょう。上部に、その下に他の追加アイテムがあります。すなわち

123 "waste" ["a" "b" "rty" "print" "me" "please"]

今、あなたは最後のリストのみを印刷することに興味があるので、

S*]W=

どの出力

a b rty print me please

スタッククリアトリックを使用して、スペースで結合されたリストのみを印刷するため、これは本当に賢いようです(リストを印刷するための望ましい方法ではない場合があります)。

これはさらにゴルフすることができます!

p];

それは2バイト短くなります!

リスト以外のスタックにアイテムが1つしかない場合は、さらに短くなります!

p;

美しさはp、それがスタックから最上位の項目を削除することであるstringifiesそれは(また終了時に改行を追加)し、コードの完了を待たずに、即座にSTDOUTに印刷します。

したがって、上記のコードは出力されます

["a" "b" "rty" "print" "me" "please"]

これは、リストがスタックにあったときの正確な表現です!


3

デカルト積または2つ以上のセットのすべての可能な組み合わせ

CJamには、m*スタック上の上位2つの配列リスト/文字列を取得し、そこから可能なすべてのペアを作成する、デカルト積計算機が組み込まれています。例えば

[1 2 3 4]"abc"m*

[[1 'a] [1 'b] [1 'c] [2 'a] [2 'b] [2 'c] [3 'a] [3 'b] [3 'c] [4 'a] [4 'b] [4 'c]]

スタックとして

しかし、3つ以上のリスト/文字列から可能なすべての組み合わせが必要な場合はどうでしょう。あなたはm*何度も使用しますか?例えば

[1 2 3 4][5 6]"abc"m*m*

スタックに次のものを残します

[[1 [5 'a]] [1 [5 'b]] [1 [5 'c]] [1 [6 'a]] [1 [6 'b]] [1 [6 'c]] [2 [5 'a]] [2 [5 'b]] [2 [5 'c]] [2 [6 'a]] [2 [6 'b]] [2 [6 'c]] [3 [5 'a]] [3 [5 'b]] [3 [5 'c]] [3 [6 'a]] [3 [6 'b]] [3 [6 'c]] [4 [5 'a]] [4 [5 'b]] [4 [5 'c]] [4 [6 'a]] [4 [6 'b]] [4 [6 'c]]]

製品はまだペアであり、アイテムの1つがペアそのものであることに注意してください。これは予期されていないため、フラット化された組み合わせが必要です。

それを行う簡単な方法があります。デカルト積に必要なすべてのリストを配列にラップし、デカルト積をペアワイズで作成し、毎回フラット化します。

[1 2 3 4][5 6]"abc"]{m*{(+}%}*

これは去る

[['a 5 1] ['b 5 1] ['c 5 1] ['a 6 1] ['b 6 1] ['c 6 1] ['a 5 2] ['b 5 2] ['c 5 2] ['a 6 2] ['b 6 2] ['c 6 2] ['a 5 3] ['b 5 3] ['c 5 3] ['a 6 3] ['b 6 3] ['c 6 3] ['a 5 4] ['b 5 4] ['c 5 4] ['a 6 4] ['b 6 4] ['c 6 4]]

スタック上。

注文を維持したいですか?、ポップしたアイテムを配列に追加する前に、単にスワップします。すなわち

{m*{(\+}%}*

順列のみが必要ですか?

{m*{(+$}%_&}*

組み合わせで一意の要素のみが必要ですか?

{m*{(+_&}%}*

それはすべての人々です。今のところ


1
これ]:m*:e_で、任意の数のアレイを使用して行うこともできます
-aditsu

3

文字列の操作

複雑なデータ構造で作業している場合、その中のアイテムは単純ですが、文字列に変換すると役立つ場合があります。

たとえば、ビットの2D配列の最初または最後のいくつかのアイテムを取得し、返されるタイプを気にしない場合は、またはsA<からバイトを保存します。0=A<:+A<

または、入力の一部のビットを変更する場合は、評価する前に文字列を変更できます。

または、この構造を取得して、単純なリストに変換する場合:

[[[[[[[[[1]2]3]4]5]6]7]8]9]

他の方法で多くのキャラクターでそれを行うことができます:

[a{~)\}h;]W%

ただし、文字列を使用するとはるかに短くなります。

s:~

1桁以上の数字がある場合でも、より短くなります。

[`La`-~]

または:

`']-~]

そのような配列の多くを含む別の配列が必要ない場合。


e_今があります
-aditsu

@aditsu この回答とコメントをご覧ください。時々、sまだうまく機能します。
jimmy23013

もちろん、文字列を直接操作できる場合は短くなります。
-aditsu

3

使用するN代わりに、La

多くの場合、空の配列を唯一の要素として含む配列に初期化されたものが必要ですLa

多くの場合、印刷前に各要素の後に改行を追加する必要があります。これは、NoまたはのようなものN*です。

しかし、両方が当てはまる場合N、改行文字を唯一の要素として持つ配列を使用して配列を初期化できることがわかります。コードの残りの要素にのみ先頭に追加するようにしてください。先頭に追加するのは常に文字または配列です。または、先頭の改行が許容され、それが短くなる場合にのみ追加します。

S出力をスペースで区切る必要がある場合にも機能する場合があります。

まれに、初期要素は文字列でなければなりません。ただしNa、後で改行を追加するよりも短い方を使用できます。


2

1つ以上のオカレンスでの分割

文字列が"abbcdbbfghbdbb"あり、それを分割したいとしますb

"abbcdbbfghbdbb"'b/

これはスタックに残ります:

["a" "" "cd" "" "fgh" "d" "" ""]

空の文字列に注意してください?それらが存在するのは、2つbが一緒になっていて、その間に何もなかったからです。時々、あなたはこれを避けたいです。あなたはこれをすることができます

"abbcdbbfghbdbb"'b/La-

または空の文字列を除外する

"abbcdbbfghbdbb"'b/{},

しかし、それは3バイト余分です。

この特定のユースケースのあまり知られていない演算子は%です。modとmapを実行し、数値("abcd"2%= "ac")に基づいて分割する以外に、%文字列/配列で分割することもできます。したがって、上記のユースケースの場合:

"abbcdbbfghbdbb"'b%

残します

["a" "cd" "fgh" "d"]

スタック上。

今日の私の回答の1つでこれを指摘してくれた@ user23013に感謝します。


これは、「GolfScriptも学ぶ」という名前にする必要があると思います。
jimmy23013

@ user23013しかし、すべてがGSに似ているものとそうではないものはわかりません。
オプティマイザー

2

fold / reduceを中置として使用するforeach

我々は持っている:xの省略形として{x}%およびまたは{x}*(かどうかに応じてx単項またはバイナリです)。残念ながら、短縮する同等の挿入演算子はありません{x}/。しかし、非常に頻繁に行うのは{x}/x実際にはスタックの下にあるアイテムを繰り返し変更する二項演算子です。その場合で、アイテムが配列ではない場合、fold / reduceをforeachとして乱用することでバイトを節約できます。

5 [1 2 3 4]{-}/  e# Gives -5
5 [1 2 3 4]+:-

これは、foldが常に最初の要素に手を加えないために機能します。残念ながら、変更された要素が配列の場合、追加するとラップが解除されるため、バイトは保存されません。ただし、幸運にも配列の先頭にその要素が含まれている場合があります。その場合、reduceを念頭に置く必要があります({}/残りの要素を使用する前に要素を手動で削除する代わりに)。


2

printおよびprintln

CJamにはprint演算子:がありoます。動作しますが、すべてのコードが実行された直後にスタックが印刷されます。プログラムの最後でスタックをクリアすると、停止できます。最後にこれを置くだけです:

];

printlnには、oNoまたはp(として機能する`oNo)を使用できます


3
との間には大きな違いがoありpます。pまず、印刷するアイテムを明確な文字列表現に変換します。pは、実行と同等​`oNoです。
デニス
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.