Mathematicaでのゴルフのヒント


41

Mathematicaでゴルフをするための一般的なヒントは何ですか?少なくともMathematicaにある程度特有のゴルフ問題全般のコーディングに適用できるアイデアを探しています(例えば、「コメントを削除する」は答えではありません)。

回答:


30

以下のヒントは、最も経済的なものから最も頻繁に使用されるものまでさまざまです。

  1. 可能な場合はMathematicaの高レベルのコマンドを使用します。大きなコマンドでも使用できます。

  2. Graphics and Textアスキーアートに使用:例:スタープログラミング!アナログ時計作ります

  3. 専用記号:

    • 長い形式の名前ではなく、ロジックおよび集合演算記号:⋂、⋃、∧、∨

    • Mapそして、Apply/@//@@@@@@

  4. プレフィックスおよびインフィックス表記法:

    • Print@"hello" 代わりに Print["hello"]

    • a~f~b 代わりに f[a,b]

  5. 関数が1回だけ使用される場合、純粋な関数は1つまたは2つの文字を節約できます。

  6. リスト内の文字列を結合します。""<>{"a","b","c"}の代わりにStringJoin@{"a","b","c"}

  7. リスト可能な関数を悪用します。リストが長いほど良い。

    {a, b, c} + {x, y, z}= {a+x, b+y, c+z}

    {2, 3, 4} {5, 6, 7}= {10, 18, 28}

    {{a, b}, {c, d}}^{2, 3} = {{a^2, b^2}, {c^3, d^3}}


2
の代わりに記述する方が常に短くなります。(Norm[#-#2]&)EuclideanDistance
user202729

32

長い名前の一部の組み込み関数は、短い式に置き換えることができます。

例えば:

  • Total => Tr
  • Transpose=> Threadまたは\[Transpose]
  • True => 1<2
  • False => 1>2
  • Times => 1##&
  • Alternatives => $|##&
  • IntegerQ => ⌊#⌋==#&
  • a[[1]] => #&@@a
  • a[[All,1]] => #&@@@a
  • ConstantArray[a,n]=> Array[a&,n]またはTable[a,{n}]
  • Union@a=> {}⋃aまたはa⋃a
  • ToExpression@n=> が数値のFromDigits@n場合n
  • Divisible[n,m] => m∣n
  • FromDigits[n,2]=> Fold[#+##&,n]場合nのリストである0sおよび1sは
  • Complex@z=> の形式のリストであります{1,I}.zz{x,y}

5
@belisarius Thread[{{a,b},{c,d}}]== Thread[List[{a,b},{c,d}]]== {List[a,c],List[b,d]}== {{a,c},{b,d}}==Transpose[{{a,b},{c,d}}]
alephalpha 14年

2
あなたのFoldためのトリックはFromDigits、以外の他のベースでも機能すると思います10。例FromDigits[n,5]-> Fold[4#+##&,n](ベース100とのために余分なバイトを保存するボーナス付き1000)。
マーティン・エンダー

1
@ mbomb007 3バイトのUTF-8。実際、このキャラクターはU+F3C7です。
alephalpha

1
最終的に10.3をインストールしました。完全なプログラムを検討している場合、実際の文字列を印刷する前にSTDOUTに(およびスペースを)印刷するEchoため、オプションとは思いません>>
マーティンエンダー

2
のためにComplex[x,y] => {1,I}.{x,y}、私x+y*Iは同じ効果ではるかに短いと思いますか?
浅琴しえる

22

繰り返される値を持つリスト

これは、動作する非常に一般的なベクトルです。

{0,0}

これは1バイト短くすることができます:

0{,}

ベクトルが2つのゼロよりも長い場合、さらに多くのバイトが保存されます。これは、ゼロ行列を初期化するためにも使用できます。たとえば、次の例では、ゼロの2x2行列が得られます。

0{{,},{,}}

これは、ゼロ以外の値が十分に大きいか、十分に多いか負の場合にも使用できます。次のペアを比較します。

{100,100}
0{,}+100
{-1,-1}
0{,}-1
{3,3,3,3}
0{,,,}+3

ただし、6つの値から始めて1~Table~6、この場合(優先順位の要件に応じて、より早い可能性があります)の方がよいことに注意してください。

これが機能する理由は,、リストに2つの引数を導入するが、省略された引数(Mathematicaのどこでも)は暗黙的なものNullだからです。さらに、乗算はあるListable、と0*xある0ほぼすべてのためx(のようなものを除くInfinityと、Indeterminateので、ここで)何が起こっているかです。

  0{,}
= 0*{,}
= 0*{Null,Null}
= {0*Null,0*Null}
= {0,0}

のリストについては、1べき乗規則を利用することで同様のトリックを使用できます。1リストに少なくとも3つある場合、バイトを保存するには2つの異なる方法があります。

{1,1,1}
1^{,,}
{,,}^0

7
+1; これはMathematicaがあらゆるものに組み込まれているかもしれないが、その中でゴルフをすることは本当に難しいことを示しているだけです。
LegionMammal978

最終的に1で埋められる配列が必要な場合1^{,,,}は、のサイズより1バイト小さくなり0{,,,}+1ます。
ミシャラヴロフ

@MishaLavrovああ、いいキャッチ。これにより、3つの値で短くなり、を使用することもできます{,,}^0。投稿を編集します。
マーティンエンダー

19

純粋な関数の引数を知る

コードをゴルフするときは、多くの場合、関数型アプローチを採用します。このアプローチでは、&短縮構文で匿名(純粋)関数を使用します。このような関数の引数にアクセスするには、さまざまな方法があります。可能性を十分に把握することで、数バイトを削ることができます。

単一の引数へのアクセス

以前に純粋な関数を使用したことがあるなら、おそらくこれを知っているでしょう。N番目の引数はと呼ばれ#n、そして#の別名として働きます#1。したがって、たとえば、別の関数とその引数を引数として取る関数を作成する場合(その関数に引数を渡すため)、次を使用します。

#@#2&

これは、リストにアクセスするときに使用するような負の数で機能しませ

名前付き引数へのアクセス(V10の新機能)

Mathematica 10の主要な新しい言語機能の1つはAssociationsです。これは基本的に、任意のキータイプを持つキー値マップで、

<| x -> 1, "abc" -> 2, 5 -> 3 |>

このような関連付けが純粋な関数の最初の引数として渡された場合、その引数が名前付きパラメーターである場合、いくつかにアクセスできます。

{#, #2, #3, #abc, #xyz} & [<| "abc" -> "1st", "xyz" -> "2nd", abc -> "3rd" |>, "4th", "5th"]
(* {<| "abc" -> "1st", "xyz" -> "2nd", abc -> "3rd" |>, "4th", "5th", "1st", "2nd"} *)

#期待どおりに関連付け全体を参照していることに注意してください。仕事への名前付きパラメータの場合は、キーがなければならない文字列(インスタンスのために未定義の変数を使用している場合、それは動作しません)、およびそれらの文字列の文字で始まり、文字だけと数字が含まれている必要があります。

「自己」の議論 #0

あまり知られていない機能#0も存在し、関数オブジェクト自体を提供します。これは、クインおよび一般化されたクインで本当に役立ちます。実際、最短のMathematicaキイン(私が知っている)は

ToString[#0][] & []

少し面倒なのは、入力した正確な文字が表示されないことです。たとえば@、関数アプリケーションに使用する場合、レンダリングは引き続き[...]行われ、一部の場所にスペースが挿入されます。これは通常、クインをあなたが望むよりも少し長くしますが、クインを最初にゴルフし、次にその出力をコピーするだけで常に機能します-これは実際のクインになるはずです。

クインとは別に、これは、関数に名前を付けることなく再帰的なコードを書くことができることも意味します。これら3つの(単純だがゴルフを使った)フィボナッチ実装を比較します。

f@0=0;f@1=1;f@n_:=f[n-1]+f[n-2]
f@n_:=If[n<2,n,f[n-1]+f[n-2]]
If[#<2,#,#0[#-1]+#0[#-2]]&

引数のシーケンス

これが本当の魔法の始まりです。シーケンスはSequence、名前が長すぎてほとんどの場合価値がないため、ゴルフではあまり使用されません。しかし、純粋な関数では、それらが輝く場所です。シーケンスに慣れていない場合、それらは基本的に他のいくつかの言語の感嘆符のようなものです。List関数の引数リストまたは引数リストでシーケンスを使用すると、要素は自動的に別のスロットに展開されます。そう

{1, Sequence[2, 3, 4], 5} == {1, 2, 3, 4, 5}
f["a", Sequence[0, {}], "b"] == f["a", 0, {}, "b"]

さて、純粋な関数では、##または##1すべての引数のシーケンスです。同様に、##2第二から始まるすべての引数の順序は、ある##3すべての引数がスタートのためにそう等の第三から始まる、私たちは再実装することができますSequenceように##&5バイトを保存し、。使用例として、これはJoin@@listこのtipを参照)に代わるものを提供します。これは、バイトを保存しませんが、とにかく知っておくと便利です:

 ##&@@@list

これにより、ネストされたリストの最初のレベルが効果的にフラット化されます。これで他に何ができますか?以下は、2バイトの短い代替案RotateLeftです。

 RotateLeft@list
 {##2,#}&@list

これらのことだけでも、この機能を念頭に置く価値があります。しかし、もっとうまくやることができます!演算子が実際に内部の関数として実装されていることを考えると、シーケンスは非常に興味深いものになります。たとえば、a+b実際にはに評価されPlus[a,b]ます。シーケンスを指定すると...

1+##&[1,2,3]
=> Plus[1,##] 
=> Plus[1,1,2,3]
=> 7

このヒントでは、バイトを節約するためにこのトリックを使用しました。これTimesは、並置も技術的には単なる演算子であるためです。

1##&[1,2,3]
=> Times[1,##]
=> Times[1,1,2,3]
=> 6

Unequal引数にない単一文字の値または変数がある場合、バイトを保存するために使用することもできます(Nおそらく99%のケースで動作します)。

Unequal[a,b,c]
N!=##&[a,b,c]

これは、さらに興味深い単項演算子で取得し、-及び/-後者の二つは、実際には乗算と累乗の面で実装されています。以下に、できることのリストを示します。最後の列では、関数に引数が渡されたと想定していますa, b, c

Operator    Function                Expanded                    Equivalent to

+##         Plus[##]                Plus[a,b,c]                 a+b+c
1##         Times[1,##]             Times[1,a,b,c]              a*b*c
-##         Times[-1,##]            Times[-1,a,b,c]             -a*b*c
x+##        Plus[x,##]              Plus[x,a,b,c]               x+a+b+c
x-##        Plus[x,Times[-1,##]]    Plus[x,Times[-1,a,b,c]]     x-a*b*c
x##         Times[x,##]             Times[x,a,b,c]              x*a*b*c
x/##        Times[x,Power[##,-1]]   Times[x,Power[a,b,c,-1]]    x*a^b^c^-1
##/x        Times[##,Power[x,-1]]   Times[a,b,c,Power[x,-1]]    a*b*c/x
x^##        Power[x,##]             Power[x,a,b,c]              x^a^b^c
##^x        Power[##,x]             Power[a,b,c,#]              a^b^c^x
x.##        Dot[x,##]               Dot[x,a,b,c]                x.a.b.c

他の一般的な演算子です!===&&||。心に留めておくべきあまり一般的なものです|@*/*。最後に、少しおまけのトリックを示します。

####        Times[##,##]            Times[a,b,c,a,b,c]          (a*b*c)^2

これらの実験を続け、他の有用なアプリケーションや特に興味深いアプリケーションを見つけたら教えてください!


15

Sqrt@2または2^.5=>√2

a[[1]]=>a〚1〛

#+#2&=>+##&

Flatten@a=> Join@@a(時々)

Function[x,x^2]=> xx^2または#^2&

a〚1;;-1;;2〛=>a〚;;;;2〛

a〚2;;-1 ;;2〛=>a〚2;;;;2〛

a〚All,1〛=>a〚;;,1〛

{{1}}〚1,1〛=>Tr@{{1}}

0&~Array~10=>0Range@10

Range[10^3]=>Range@1*^3


1
注使用し、バイトで測定したときこと、およびかかる3は、それぞれ(UTF8を想定)バイト
user202729

12

関数としての演算子

デニスのジュリアに関する最近の発見に触発されて、Mathematicaでこれを調べると思いました。Mathematicaは未使用の演算子を多数定義していることを知っていましたが、あまり注意を払っていませんでした。

参考のために、すべての演算子のリストは優先順位表の形式でここにあります。最後の列の三角形は、その演算子に組み込みの意味があるかどうかを示します。定義されていないものすべてを簡単に定義できるわけではありませんが、ほとんどは定義できます。

便利なことに、コードポイントが256未満の未使用の演算子が2つあり、ISO 8859-1でエンコードされたソースファイルでシングルバイトとして使用できます。

  • ± (0xB1)は、単項前置演算子または二項中置演算子として使用できます。
  • · (0xB7)は、n> 2の場合、可変長演算子またはn項中置演算子として使用できます。

ただし、もう1つ注意点があります。これらの演算子を定義するときの奇妙な理由のために、演算子の前にスペースが1つ必要です。そうしないと、Mathematicaは乗算を解析しようとします。ただし、それらを使用する場合、スペースは必要ありません。

±x_:=2x
x_ ±y_:=x+y
x_ ·y_ ·z_:=x*y+z
Print[±5]  (* 10 *)
Print[3±4] (*  7 *)
Print[3·4·5] (* 17 *)

これと比較してください:

f@x_:=2x
x_~g~y_:=x+y
h[x_,y_,z_]:=x*y+z
Print[f@5]   (* 10 *)
Print[3~g~4] (*  7 *)
Print[h[x,y,z]] (* 17 *)

したがって、これにより、関数を定義するときに1バイト、関数を使用するときに2バイト節約されます。の定義は·4つのオペランドのバイトを節約せず、より多くのオペランドのバイトのコストを開始しますが、引数で使用される演算子の優先順位に応じて、使用法によってバイトを節約できることに注意してください。また、より効率的に呼び出すことができる可変引数関数を安価に定義できることに注意してください。

x_ ·y__:={y}
Print[1·2·3·4·5] (* {2, 3, 4, 5} *)

ただし、これらの可変引数関数を1つの引数で呼び出すことは簡単にできないことに注意してください。(あなたは何ができるCenterDot[x]か、##&[]·xあなたが実際にあなたがより良いオフに別のソリューションとしているの良いチャンスがあることを必要とする場合は。)

もちろん、これは名前のない関数で十分なソリューションには何も保存しませんが、ヘルパー関数を後で使用するために定義する必要がある場合もあります。そのような場合、代わりに演算子を使用すると、かなりのバイト数を節約できます。

これらのISO 8859-1エンコードファイルを使用する$CharacterEncodingには、Windowsのデフォルトのような互換性のある値に設定する必要があることに注意してくださいWindowsANSI。一部のシステムでは、これがデフォルトとなり、UTF-8これらのコードポイントをシングルバイトから読み取ることができなくなります。


これは本当に素晴らしいことです。Mathematicaに演算子のリストがあり、それらの優先順位も含まれていることは知りませんでした。あなたが見つけたこれらの2つの演算子は、きっと役に立つでしょう。
マイル

8

整数に基づいて値を選択する

間で選択する素朴なアプローチyz、かどうかに依存しxている01であります

If[x<1,y,z]

ただし、もっと短い方法があります。

y[z][[x]]

この作品のために[[0]]提供しますHead。この場合には、表現のyに対し、[[1]]この場合には最初の引数を、 -ちょうど最初の要素を提供しますz

これを使用して、3つ以上の値から選択することもできます。

u[v,w][[x]]

u実際に何かを評価する関数の場合、これは機能しないことに注意してください。Mathematicaをそのまま維持u[v,w]することが重要です。ただし、これuは、が数値、文字列、またはリストである場合を含め、ほとんどの場合に機能します。

このトリックの功績はalephalphaにあります-私は彼の答えの一つでこれを発見しました。

xゼロベースではなく1ベースの場合、使用

{y,z}[[x]]

または

{u,v,w}[[x]]

まれに、乗算が一部の値に対して評価されないという事実を利用することさえできます:

{"abc","def"}[[x]]
("abc""def")[[x]]

Mathematicaは、実際の引数再注文、それは未評価のままであれば乗算のため、上記であることに注意してくださいかかわらず同じ

("def""abc")[[x]]

8

に代わるもの Length

これはLegionMammal978とMisha Lavrovからのいくつかの提案で完全に書き直されました。両方に感謝します。

多くの場合、Lengthを使用することで少し短縮できますTr。基本的な考え方は、入力を1sのリストに変換することです。これにより、入力がTr合計され、リストの長さに等しくなります。

これを行う最も一般的な方法は、1^x(リスト用x)を使用することです。これが機能するのPowerListable1^nほとんどのアトミック値n1(すべての数字、文字列、記号を含む)だけであるためです。したがって、これですでに1バイトを保存できます。

Length@x
Tr[1^x]

もちろん、これは、それxがの優先順位よりも高い式であることを前提としてい^ます。

sとs xのみが含まれている場合は、次を使用して別のバイトを保存できます(仮定の優先順位はより大きい):01Factorialx!

Length@x
Tr[x!]

まれに、乗算よりxも優先順位が低くて^も、乗算より優先順位が高い場合があります。その場合、それよりも低い優先順位を持つ@ため、と比較する必要がありLength[x]ます。そのような演算子の例は.です。そのような場合でも、次の形式でバイトを保存できます。

Length[x.y]
Tr[0x.y+1]

最後に、これがどの種類のリストで機能するかについてのコメント:

冒頭で述べたように、これは数字、文字列、記号のみを含むフラットリストで機能します。ただし、実際には少し異なるものを計算しますが、より深いリストでも機能します。以下のためのn -D長方形アレイ、使用はTrあなたに与える最短(最初のとは対照的に)寸法。最も外側の次元が最も短いことを知っている場合、またはそれらがすべて同じであることがわかっている場合、Tr-expressionsはまだと同等Lengthです。


3
さらに短い解決策が見つかりました:Length@x == Tr[1^x]。ほとんどのリストで動作するはずです。
LegionMammal978 16

@ LegionMammal978それはすごい、ありがとう:)。すぐに編集します。
マーティンエンダー

1
2回、ゼロと1だけが含まれる特別な場合に1バイトを保存するTr[x!]代わりに使用していることに気付きました。Tr[1^x]x
ミシャラヴロフ

@MishaLavrovそれは本当にすてきです!:)
マーティン・エンダー

7
  1. 再帰的ソリューションの探索-Mathematicaはマルチパラダイムですが、機能的なアプローチが最も経済的です。NestWhile検索問題に対する非常にコンパクトなソリューションでありNestWhileListFoldList中間の反復の結果を返すか処理する必要がある場合に強力です。Map (/@)Apply (@@, @@@)MapThread、と本当にWolframの上のすべての関数型プログラミングのドキュメントページには強力なものです。

  2. 増加/減少のための短縮形 -例えば、代わりにWhile[i<1,*code*;i++]あなたが行うことができます
    While[i++<1,*code*]

  3. 事前にインクリメント/デクリメントできることを忘れないでください -たとえば、の--i代わりにi--。これにより、準備操作が不要になり、周囲のコードで数バイト節約できる場合があります。

  4. David Carraherの#5の結果:同じ関数が何度も使用される場合、それにシンボルを割り当てるとバイトを節約できます。たとえばToExpression、ソリューションで4回使用している場合、その後t=ToExpression使用できますt@*expression*。ただし、これを行う前に、同じ関数を繰り返し適用することが、より経済的な再帰アプローチの機会を示しているかどうかを検討してください。


MapThread多くの場合、に置き換えることができ\[Transpose]ます。TIO
user202729

7

を使用している{}場合は使用しないでください@@@

場合によっては、次のような式に遭遇する可能性があります。

f@@@{{a,b},{c,d}}

次のように記述することでバイトを減らすことができます。

f@@@{a|b,c|d}

Alternatives優先順位が非常に低いため、一般的に式を記述しても問題ありません(注目すべき例外は純粋な関数です。これはの左端の要素でのみ使用できますAlternatives)。

f@@@{f@a|b~g~1,#^2&@c|d@2}

f@@a|b|c(の代わりにf@@{a,b,c}Applyは、の優先順位が高いため機能しないことに注意してくださいAlternative

この場合、単にを使用する必要がありますf@@{a,b,c}


6

Mathematica 10のみ

オペレーターフォーム

Mathematica 10はいわゆる「演算子形式」をサポートします。これは基本的に、いくつかの関数をカリー化できることを意味します。関数をカリー化するとは、演算子の1つを修正して新しい関数を作成することです。たとえば、SortBy[list, somereallylongfunction&]多くの異なるを使用しているとしますlist。前に、あなたはおそらく割り当てられているだろうSortBys、純粋な関数にfそう

s=SortBy;
f=somereallylongfunction&;
list1~s~f;
list2~s~f;
list3~s~f;

これでカレーSortByできます

s=SortBy[somereallylongfunction&];
s@list1;
s@list2;
s@list3;

含むリストまたは関数の引数を取る(これらに限定されない)他の機能の多くも同じ作品SelectMapNearest、など

Mathematica.SEについてybeltukov がこれらの完全なリストを作成できました

{"AllTrue", "AnyTrue", "Append", "Apply", "AssociationMap", "Cases", 
 "Count", "CountDistinctBy", "CountsBy", "Delete", "DeleteCases", 
 "DeleteDuplicatesBy", "Extract", "FirstCase", "FirstPosition", 
 "FreeQ", "GroupBy", "Insert", "KeyDrop", "KeyExistsQ", "KeyMap", 
 "KeySelect", "KeySortBy", "KeyTake", "Map", "MapAt", "MapIndexed", 
 "MatchQ", "MaximalBy", "MemberQ", "Merge", "MinimalBy", "NoneTrue", 
 "Position", "Prepend", "Replace", "ReplacePart", "Scan", "Select", 
 "SelectFirst", "SortBy", "StringCases"}

構成と権利

Composition@*)およびRightComposition/*)の新しい略記があります。これらが文字を保存できる明らかに不自然な例は、次の3つの同等の行に見られます。

Last@Range@# & /@ Range[5]
Last@*Range /@ Range[5]
Range /* Last /@ Range[5]

5

引数なしの関数を作成しない

このようなコードは必要ありません。

f[]:=DoSomething[1,2]
(*...*)
f[]
(*...*)
f[]

変数を使用して:=、右側の再評価を強制することができます。

f:=DoSomething[1,2]
(*...*)
f
(*...*)
f

これはまたn++、5バイトのコストで、頻繁に実行するアクションを(たとえそれが単なるものであっても)1文字にエイリアスできることを意味します。そのn++ため、4回目の使用後に返済されます。

n++;n++;n++;n++
f:=n++;f;f;f;f

5

%自由変数を取得するために使用

このヒントは、MathematicaのREPL環境を想定できる場合にのみ適用できます。 %コードがスクリプトとして実行されるときは定義されません。

あなたはときにすることができます REPLの機能を利用するため、これをしません。

a=someLongExpression;some[other*a,expression@a,using^a]

代わりに、Mathematicaが最後に評価された(改行で終わる)式を%次の場所に保存することを覚えておいてください:

someLongExpression;
some[other*%,expression@%,using^%]

追加された改行には1バイトかかりますが、を削除することa=で2 個節約できるため、全体として1バイト節約できます。

場合によっては(aとにかく値を出力したい場合など)、;2バイトを節約することもできます:

someLongExpression
some[other*%,expression@%,using^%]

1バイトまたは2バイトはかなり小さいように思えるかもしれませんが、これは重要なケースです。なぜなら、ゴルフをするとき、繰り返し表現の抽出(非常に一般的な手法)がはるかに役立つからです。

繰り返される式を抽出する通常の手法では、4バイトのオーバーヘッドがかかります。これは、式をさらに使用することで節約する必要があります。これは、名前付き変数に抽出して何かを保存するための、式の最小使用回数(式の長さによる)の短い表です。

Length   Min. Uses
2        6
3        4
4        3
5        3
6        2
...      2

名前のない変数を使用すると、数バイトをはるかに頻繁に保存できます。

When ; is required                        When ; can be omitted

Length   Min. Uses                        Length   Min. Uses
2        5                                2        4
3        3                                3        3
4        3                                4        2
5        2                                ...      2
...      2

ゴルフに使用するとは思わないか%%%n使用できません。少なくとも2回使用しないと、必要な場所に表現を配置できるからです。また、2回使用すると、変数名に追加の文字があるため、一部を省略しても節約が相殺されx=ます。


スクリプトモードでは機能しないことに注意してください。
alephalpha

@alephalphaスクリプトモードとは何ですか?
マーティンエンダー


@alephalphaああ、私はそこで一時的に脳を遮断しました...そのため、REPL環境が想定されない限り、それは実際にはまったく使用できません。
マーティンエンダー

5

リストがソートされているかどうかを確認する

これは本質的にこのヒントの結果ですが、これは十分に一般的なタスクであるため、独自の答えが必要だと思います。

リストが正しいかどうかを確認する単純な方法は、

OrderedQ@a

私たちは1バイトをより良くすることができます

Sort@a==a

ただし、既に変数をチェックインしたいものがない場合、これは機能しません。(Sort[a=...]==a不必要に長いものが必要です。)ただし、別のオプションがあります。

#<=##&@@a

最も良いのは、これを使用して、入力が同じバイトカウントに対して逆ソートされているかどうかを確認できることです。

#>=##&@@a

a)リスト要素が明確であることがわかっている場合、およびb)0〜9の下限(両端を含む、または逆ソート順の上限)がわかっている場合は、もう1バイト節約できます。

0<##&@@a
5>##&@@a

これが機能する理由を確認するには、上部にリンクされているヒントの「引数のシーケンス」を確認してください。


または、逆ソートの(厳密な)下限も機能します##>0&@@a。ソートの上限についても同様です。
-user202729

@ user202729ああ、良い点です。自由に編集してください(そうでなければ、覚えているなら週末にやろうとします)。
マーティンエンダー

5

文字列を繰り返す

StringRepeat[str,n]使用する代わりに(0Range[n]+str)<>""。場合またはstr任意のスロットの引数に依存しない、より良いですArray[str&,n]<>""につきとして、この先端。


1
結果:StringRepeat[s,n+1]使用する代わりにArray[s&,n]<>s(既にn+1変数に含まれている場合でも)。
マーティンエンダー

より良いTable[str,n]<>""
attinat

5

逆にソートされた数値のリストが必要な場合は、使用しないでください

Reverse@Sort@x

しかし

-Sort@-x

6バイトを節約します。負の値による並べ替えは、SortByシナリオにも役立ちます。

Reverse@SortBy[x,Last]
SortBy[x,-Last@#&]

2
どう-Sort@-x
ジョンファンミン

1
@JungHwanMinああ、ええと、ええ、それははるかに良いです。:)
マーティンエンダー

4

Break1つまたは2つの文字を保存できる式を貼り付けることができます。例(わかりやすくするためにゴルフを使用していないその他の詳細):

result = False;
Break[]

に変えることができます

Break[result = False]

1文字を保存します。問題の式の優先順位が関数アプリケーションより低い場合、別の文字を保存することもできます。

Print@x;
Break[]

に変えることができます

Break@Print@x

文書化されていませんが、への引数Breakは周囲のループによって返されるようであり、さらに節約につながる可能性があります。


4

文字列からすべての空白を削除するにはs、次を使用します

StringSplit@s<>""

つまり、StringSplitのデフォルト(空白以外のコンポーネントに分割)を使用し、単純にそれらを結合します。他の文字や部分文字列を取り除きたい場合、おそらく同じものがおそらく最も短いです:

s~StringSplit~"x"<>""

4

に代わるもの Range

非常に一般的なタスクは、ある種の関数を1からaまでのすべての数値に適用することですn(通常は入力として与えられます)。これを行うには、本質的に3つの方法があります(名前のないID関数を例として使用):

#&/@Range@n
Array[#&,n]
Table[i,{i,n}]

私は(何らかの理由で)最初のものに行く傾向がありますが、これはめったに最良の選択ではありません。

Array代わりに使用

上記の例は、usingのArrayバイトカウントが同じであることを示しています。ただし、単一の式であるという利点があります。特に、関数fを使用して結果をさらに処理する場合は、プレフィックス表記を使用できます。これにより、バイトを1つ節約できますRange

f[#&/@Range@n]
f@Array[#&,n]

さらに、Rangeたとえばで必要となるかもしれない名前のない関数の周りの括弧を省略できるかもしれません。

15/(#&)/@Range@n
15/Array[#&,n]

さらに使用したくない場合(または優先順位の低い演算子を使用する場合)、代わりArrayに挿入記法でそれ自体を記述し、バイトを保存することもできます。

#&/@Range@n
#&~Array~n

したがって、Arrayほぼ確実によりも優れていRangeます。

Table代わりに使用

テーブルは3バイト、または中置記法がオプションの場合は少なくとも2バイトを補う必要があります。

#&/@Range@n
i~Table~{i,n}

ときではない中置記法を使用して、Tableあなたの関数が複数の文で構成されている場合は、あなたが括弧を省略することが可能かもしれません。

(#;#)&/@Range@n
Table[i;i,{i,n}]

これはまだ長くなりますが、下記のケースではさらに節約できます。

本当の節約Tableは、実行中の変数に名前を付ける必要があるという事実に由来します。多くの場合、内部関数の1つの内部で外部変数を使用する、名前のない関数をネストします。それが起こるとき、Tableより短いRange

(i=#;i&[])&/@Range@n
Table[i&[],{i,n}]
i&[]~Table~{i,n}

を割り当てるために文字を保存するだけでなくi、プロセス内で関数を単一のステートメントに縮小することもできます。これにより、その上で中置表記法を使用できます。参照用に、Arrayこの場合も長くなりますが、それでもRange

(i=#;i&[])&~Array~n

実際に使用するのはRangeいつですか?

値を処理するために関数呼び出しが必要ないときはいつでも、たとえば、ベクトル化された操作を介してマッピングを実行できるとき。例えば:

5#&~Array~n
5Range@n
#^2&~Array~n
Range@n^2

もちろん、関数をまったくマッピングしたくない場合も短くなります。たとえば、

Mean@Array[#&,n]
Mean@Range@n

最後に使用して他の誰かf/@Range[x]定期的に...
LegionMammal978

4

条件を満たす最小数を見つける

のような一部の構造i=1;While[cond[i],i++]はそのままでも問題ありませんが、2バイト短い代替案があります。

1//.i_/;cond[i]:>i+1

上記のコードは、条件を満たしている間、数値iを繰り返し置き換えi+1ますcond[i]。この場合、iから始まり1ます。

デフォルトの最大反復回数は2 ^ 16(= 65536)であることに注意してください。それより多くの反復が必要な場合Whileは、より良いでしょう。(MaxIterations->∞長すぎる)


4

虐待短絡評価

If論理演算子に置き換えることができる場合があります。

たとえば、数値が素数であるかどうかをチェックする関数を作成し、2*(number) - 1それがtrueの場合はprint を作成するとします。

If[PrimeQ@#,Print[2#-1]]&

&&代わりに使用すると短くなります。

PrimeQ@#&&Print[2#-1]&

複数の式がある場合でも、バイトを保存します:

If[PrimeQ@#,a++;Print[2#-1]]&

PrimeQ@#&&a++&&Print[2#-1]&
(* or *)
PrimeQ@#&&(a++;Print[2#-1])&

||条件を次のようにする場合に使用できますFalse

If[!PrimeQ@#,Print[2#-1]]&
(* or *)
If[PrimeQ@#,,Print[2#-1]]&
(* can become *)
PrimeQ@#||Print[2#-1]&

これらのトリックは、論理演算子が短絡する可能性があるため機能します。2番目の引数以降は、有効なブール式である必要さえありません。

もちろん、これは、の戻り値が必要な場合、Ifまたはの真実の引数と偽の引数の両方が必要な場合には機能しませんIf



3

を使用して Optional (:)

Optional (:) 展開用に別のルールを定義することなく、置換でリストを展開するために使用できます。

私がこの回答@ngenisisすることによって、この答えは、例です。

使用法

... /. {p___, a_: 0, b_, q___} /; cond[b] :> ...

上記の置換では、最初にパターン{p___, a_, b_, q___}を使用しb、特定の条件を満たす一致を見つけます。

そのような一致が見つからない場合、省略a_して代わりに検索し{p___, b_, q___}ます。aは検索に含まれず、値を持つと想定されます0

2番目のパターン検索はb、リストの先頭でのみ実行されることに注意してください。場合b条件を満足する値が中央にある場合、{p___, a_, b_, q___}(より高い優先順位を有する)代わりにそれを一致させることになります。

置換は、リストの先頭で条件を満たす条件を満たす0ときにa bを追加することと同じです。(つまり、別のルールを定義する必要はありません、{b_, q___} /; cond[b] :> ...


3

名前付きの純粋な関数引数を使用するタイミング(および使用しないタイミング)を知る

コードゴルフでは、s Functionを使用して純粋な引数が最も一般的に参照されSlotます。たとえば#、最初の引数、#22番目の引数など(詳細はこの回答を参照)。

多くの場合、Functions をネストする必要があります。たとえば、1##&@@#&Function最初の引数としてリストを取り、その要素の積を出力します。以下にその関数を示しますTreeForm

ここに画像の説明を入力してください

最上位に渡された引数は、最上位にあるsおよびs Functionのみを埋めることができます。これは、この場合、内部にある最上位の引数にアクセスする方法がないことを意味します。SlotSlotSequenceSlotSequenceFunctionFunction

ただし、場合によっては、Function別の内部にネストされたFunction引数が外部への引数を参照できるようにすることができFunctionます。たとえばArray[fun,...]&、関数funがトップレベルへの引数に依存するようなものが必要な場合がありますFunction。具体的funには、最上位への入力を法とする入力の平方の余りを与えるとしましょうFunction。これを実現する1つの方法は、変数にトップレベルの引数を割り当てることです。

(x=#;Array[Mod[#^2,x]&,...])&

どこxの内側に表示されFunction Mod[#^2,x]&、それが外に最初の引数を参照するFunction一方で、#内部の最初の引数を参照しますFunction。より良いアプローチはFunction、最初の引数がFunction(名前Slotのないsではなく)の名前付き引数を表すシンボルまたはシンボルのリストである2つの引数形式を持つ事実を使用することです。これにより、この場合は3バイト節約されます。

xArray[Mod[#^2,x]&,...]

は、U+F4A1バイナリ中置演算子を表す3バイトの私用文字\[Function]です。Function別の内部ののバイナリ形式を使用することもできますFunction

Array[xMod[x^2,#],...]&

これは上記と同等です。その理由は、名前付き引数を使用している場合、SlotsとSlotSequencesは、Function名前付き引数を使用しない上記の次のものに属すると想定されるためです。

Functionこのようにsをネストできるからといって、常にそうする必要があるわけではありません。たとえば、入力よりも小さいリストの要素を選択したい場合、次のようなことをしたくなるかもしれません。

Select[...,xx<#]&

実際には、使用する方が短くなりCases、ネストされたFunction完全な必要性を回避できます。

Cases[...,x_/;x<#]&

2

あなたの周りの作業でバイトを保存することができますPrependPrependTo

l~Prepend~x
{x}~Join~l
{x,##}&@@l

または

l~PrependTo~x
l={x}~Join~l
l={x,##}&@@l

残念ながら、これは他の言語のにAppend相当する最も短いと思われる、より一般的なには役立ちませんArray.push()


2

Mathematica 10.2:BlockMapPartition+Map

このヒントには、「リリースノートをすべて読んでください」というタイトルも付けることができます。(参照用に、ここに10.2のリリースノート、今日の10.3リリースのリリースノートがあります。)

とにかく、マイナーリリースにも豊富な新機能が含まれており、10.2の(ゴルフで)より便利な機能の1つは新しいBlockMap機能です。これは基本的にとを組み合わせたものPartitionMap、ゴルファーにとってはPartition非常によく使用されます。これは非常に頻繁に使用されるため、非常に迷惑なほど長い関数名です。新しい関数はPartitionそれ自体では短縮されませんが、パーティションに関数をマップしたい場合(おそらく頻繁に起こります)、1バイトまたは2バイトを保存できるようになりました。

#&/@l~Partition~2
BlockMap[#&,l,2]
#&/@Partition[l,3,1]
BlockMap[#&,l,3,1]

名前のない関数の新しい位置により、いくつかの括弧を節約できる場合、節約はさらに大きくなります。

#&@@(#&/@Partition[l,3,1])
#&@@BlockMap[#&,l,3,1]

残念ながら、BlockApply彼らがそこにいた間になぜ追加もしなかったのか分かりません...

また、巡回リストを取得するBlockMapために使用できる4番目のパラメーターをサポートしていないことに注意してくださいPartition

Partition[Range@5, 2, 1, 1]
(* Gives {{1, 2}, {2, 3}, {3, 4}, {4, 5}, {5, 1}} *)
BlockMap[f, Range@5, 2, 1, 1]
(* Nope... *)

2

変数に関数と式を保存する

答えが同じ関数または式を複数回使用することになった場合は、変数に保存することを検討してください。

式が長さでlありn、それを何度も使用する場合、通常はl * nバイトを使い果たします。

ただし、長さ1の変数に格納する場合、必要なのは3 + l + nバイトだけです(または2 + l + n、必要のない場所に変数を割り当てCompoundExpression (;)たり、括弧で囲んだ場合はバイト)。


たとえば、単純な問題を考えてみましょう。N未満の双子素数を見つけます。

この54バイトのソリューションを書くことができます:

Select[Range@#,PrimeQ@#&&(PrimeQ[#+2]||PrimeQ[#-2])&]&

この例では、関数PrimeQが3回使用されています。

PrimeQ変数名を割り当てることにより、バイト数を減らすことができます。以下は両方とも48バイト(54-6バイト)です。

Select[p=PrimeQ;Range@#,p@#&&(p[#+2]||p[#-2])&]&
Select[Range@#,(p=PrimeQ)@#&&(p[#+2]||p[#-2])&]&

2

昇順のキーと値のリストを実現するには、Sort代わりにSortBy

などのリストのlist = {{1, "world"}, {0, "universe"}, {2, "country"}}場合、次の3つのステートメントはほぼ同等です。

SortBy[list,#[[1]]&]
list~SortBy~First
Sort@list

組み合わせSelectSortBy

場合によっては、より大きなセットからエントリを選択してソートし、最小/最大を見つける必要があります。状況によっては、2つの操作を1つにまとめることができます。

たとえば、最低限、次の2つのステートメントはほぼ同等です。

SortBy[Select[l,SomeFormula==SomeConstant&],SortValue&]
SortBy[l,SortValue+99!(SomeFormula-SomeConstant)^2&]

そして

SortBy[Select[l,SomeFormula!=SomeConstant&],SortValue&]
SortBy[l,SortValue+1/(SomeFormula-SomeConstant)&]

1/0ComplexInfinity、すべての実数より「大きい」です。

キーと値のリストの場合、たとえば:

{SortValue,#}&/@SortBy[Select[l,SomeFormula==SomeConstant],SortValue&]
Sort[{SortValue+99!(SomeFormula-SomeConstant)^2,#})&/@l]

1

フラット化Array##&

多次元配列を使用し##&て、フラット化する必要がある結果のリストを計算する場合は、4番目の引数として使用します。これにより、配列のヘッドがの代わりに##&(と同等Sequence)に置き換えListられるため、最終結果は結果の(フラット)Sequenceになります。

2次元で比較する

{Array[f,dims,origin,##&]}
Join@@Array[f,dims,origin]

もちろん、 Join@@Array[f,dims] まだ2バイト(または中置記法を使用できる場合は3)バイトは未満 {Array[f,dims,1,##&]}です。

3次元以上で{Array[f,dims,origin,##&]}は、原点が1であっても、常に代替よりも短くなります。

{Array[f,dims,1,##&]}
f~Array~dims~Flatten~2

1

デフォルト値

デフォルト値は、欠落しているパターン引数を効率的な方法で処理します。たとえばExp[c_*x]、任意の値のルールでパターンマッチを行いたい場合c、ナイーブ

Exp[x] + Exp[2x] /. {Exp[c_*x] -> f[c], Exp[x] -> f[1]}
(*    f[1] + f[2]    *)

c欠落している場合にデフォルト値を使用する場合よりも多くのバイトを使用します。

Exp[x] + Exp[2 x] /. Exp[c_.*x] -> f[c]
(*    f[1] + f[2]    *)

デフォルトの使用は、パターンの後のドットで示されます:c_.

デフォルト値は操作に関連付けられています。上記の例では、操作はTimesin c_.*xであり、の欠損値c_はに関連付けられたデフォルト値1から取得されますTimes。の場合Plus、デフォルト値は0です。

Exp[x] + Exp[x + 2] /. Exp[x + c_.] -> f[c]
(*    f[0] + f[2]    *)

Power指数、デフォルトは1です。

x + x^2 /. x^n_. -> p[n]
(*    p[1] + p[2]    *)
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.