回答:
以下のヒントは、最も経済的なものから最も頻繁に使用されるものまでさまざまです。
可能な場合はMathematicaの高レベルのコマンドを使用します。大きなコマンドでも使用できます。
MorphologicalComponents
:Code-Golf:カウント諸島
画像操作機能:たとえば、今日(9月24日)はホンダの誕生日です
Subsets
IntegerPartitions
距離と類似性の尺度:たとえばEuclideanDistance
、バイトセーバーにすることができます。ただし、のTotal@Abs[a-b]
代わりにa~ManhattanDistance~b
およびのMax@Abs[a-b]
代わりに記述する方が通常は短いことに注意してくださいa~ChessboardDistance~b
。
Graphics and
Text
アスキーアートに使用:例:スタープログラミング!アナログ時計
を作ります
専用記号:
長い形式の名前ではなく、ロジックおよび集合演算記号:⋂、⋃、∧、∨
Map
そして、Apply
:/@
、//@
。@@
、@@@
プレフィックスおよびインフィックス表記法:
Print@"hello"
代わりに Print["hello"]
a~f~b
代わりに f[a,b]
関数が1回だけ使用される場合、純粋な関数は1つまたは2つの文字を節約できます。
リスト内の文字列を結合します。""<>{"a","b","c"}
の代わりにStringJoin@{"a","b","c"}
リスト可能な関数を悪用します。リストが長いほど良い。
{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}}
長い名前の一部の組み込み関数は、短い式に置き換えることができます。
例えば:
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
のリストである0
sおよび1
sはComplex@z
=> の形式のリストであります{1,I}.z
z
{x,y}
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}}]
Fold
ためのトリックはFromDigits
、以外の他のベースでも機能すると思います10
。例FromDigits[n,5]
-> Fold[4#+##&,n]
(ベース100
とのために余分なバイトを保存するボーナス付き1000
)。
U+F3C7
です。
Echo
ため、オプションとは思いません>>
。
Complex[x,y] => {1,I}.{x,y}
、私x+y*I
は同じ効果ではるかに短いと思いますか?
これは、動作する非常に一般的なベクトルです。
{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
1^{,,,}
は、のサイズより1バイト小さくなり0{,,,}+1
ます。
{,,}^0
。投稿を編集します。
コードをゴルフするときは、多くの場合、関数型アプローチを採用します。このアプローチでは、&
短縮構文で匿名(純粋)関数を使用します。このような関数の引数にアクセスするには、さまざまな方法があります。可能性を十分に把握することで、数バイトを削ることができます。
以前に純粋な関数を使用したことがあるなら、おそらくこれを知っているでしょう。N番目の引数はと呼ばれ#n
、そして#
の別名として働きます#1
。したがって、たとえば、別の関数とその引数を引数として取る関数を作成する場合(その関数に引数を渡すため)、次を使用します。
#@#2&
これは、リストにアクセスするときに使用するような負の数では機能しません。
Mathematica 10の主要な新しい言語機能の1つはAssociation
sです。これは基本的に、任意のキータイプを持つキー値マップで、
<| 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
これらの実験を続け、他の有用なアプリケーションや特に興味深いアプリケーションを見つけたら教えてください!
Sqrt@2
または2^.5
=>√2
a[[1]]
=>a〚1〛
#+#2&
=>+##&
Flatten@a
=> Join@@a
(時々)
Function[x,x^2]
=> xx^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
〚
、および〛
かかる3は、それぞれ(UTF8を想定)バイト
デニスのジュリアに関する最近の発見に触発されて、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
これらのコードポイントをシングルバイトから読み取ることができなくなります。
間で選択する素朴なアプローチy
とz
、かどうかに依存しx
ている0
か1
であります
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]]
Length
これはLegionMammal978とMisha Lavrovからのいくつかの提案で完全に書き直されました。両方に感謝します。
多くの場合、Length
を使用することで少し短縮できますTr
。基本的な考え方は、入力を1
sのリストに変換することです。これにより、入力がTr
合計され、リストの長さに等しくなります。
これを行う最も一般的な方法は、1^x
(リスト用x
)を使用することです。これが機能するのPower
はListable
、1^n
ほとんどのアトミック値n
が1
(すべての数字、文字列、記号を含む)だけであるためです。したがって、これですでに1バイトを保存できます。
Length@x
Tr[1^x]
もちろん、これは、それx
がの優先順位よりも高い式であることを前提としてい^
ます。
sとs x
のみが含まれている場合は、次を使用して別のバイトを保存できます(仮定の優先順位はより大きい):0
1
Factorial
x
!
Length@x
Tr[x!]
まれに、乗算よりx
も優先順位が低くて^
も、乗算より優先順位が高い場合があります。その場合、それよりも低い優先順位を持つ@
ため、と比較する必要がありLength[x]
ます。そのような演算子の例は.
です。そのような場合でも、次の形式でバイトを保存できます。
Length[x.y]
Tr[0x.y+1]
最後に、これがどの種類のリストで機能するかについてのコメント:
冒頭で述べたように、これは数字、文字列、記号のみを含むフラットリストで機能します。ただし、実際には少し異なるものを計算しますが、より深いリストでも機能します。以下のためのn -D長方形アレイ、使用はTr
あなたに与える最短(最初のとは対照的に)寸法。最も外側の次元が最も短いことを知っている場合、またはそれらがすべて同じであることがわかっている場合、Tr
-expressionsはまだと同等Length
です。
Length@x == Tr[1^x]
。ほとんどのリストで動作するはずです。
Tr[x!]
代わりに使用していることに気付きました。Tr[1^x]
x
再帰的ソリューションの探索-Mathematicaはマルチパラダイムですが、機能的なアプローチが最も経済的です。NestWhile
検索問題に対する非常にコンパクトなソリューションでありNestWhileList
、FoldList
中間の反復の結果を返すか処理する必要がある場合に強力です。Map (/@)
、Apply (@@, @@@)
、MapThread
、と本当にWolframの上のすべての関数型プログラミングのドキュメントページには強力なものです。
増加/減少のための短縮形 -例えば、代わりにWhile[i<1,*code*;i++]
あなたが行うことができますWhile[i++<1,*code*]
事前にインクリメント/デクリメントできることを忘れないでください -たとえば、の--i
代わりにi--
。これにより、準備操作が不要になり、周囲のコードで数バイト節約できる場合があります。
David Carraherの#5の結果:同じ関数が何度も使用される場合、それにシンボルを割り当てるとバイトを節約できます。たとえばToExpression
、ソリューションで4回使用している場合、その後t=ToExpression
使用できますt@*expression*
。ただし、これを行う前に、同じ関数を繰り返し適用することが、より経済的な再帰アプローチの機会を示しているかどうかを検討してください。
{}
場合は使用しないでください@@@
。場合によっては、次のような式に遭遇する可能性があります。
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}
。
オペレーターフォーム
Mathematica 10はいわゆる「演算子形式」をサポートします。これは基本的に、いくつかの関数をカリー化できることを意味します。関数をカリー化するとは、演算子の1つを修正して新しい関数を作成することです。たとえば、SortBy[list, somereallylongfunction&]
多くの異なるを使用しているとしますlist
。前に、あなたはおそらく割り当てられているだろうSortBy
にs
、純粋な関数にf
そう
s=SortBy;
f=somereallylongfunction&;
list1~s~f;
list2~s~f;
list3~s~f;
これでカレーSortBy
できます
s=SortBy[somereallylongfunction&];
s@list1;
s@list2;
s@list3;
含むリストまたは関数の引数を取る(これらに限定されない)他の機能の多くも同じ作品Select
、Map
、Nearest
、など
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]
このようなコードは必要ありません。
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
%
自由変数を取得するために使用このヒントは、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=
ます。
これは本質的にこのヒントの結果ですが、これは十分に一般的なタスクであるため、独自の答えが必要だと思います。
リストが正しいかどうかを確認する単純な方法は、
OrderedQ@a
私たちは1バイトをより良くすることができます
Sort@a==a
ただし、既に変数をチェックインしたいものがない場合、これは機能しません。(Sort[a=...]==a
不必要に長いものが必要です。)ただし、別のオプションがあります。
#<=##&@@a
最も良いのは、これを使用して、入力が同じバイトカウントに対して逆ソートされているかどうかを確認できることです。
#>=##&@@a
a)リスト要素が明確であることがわかっている場合、およびb)0〜9の下限(両端を含む、または逆ソート順の上限)がわかっている場合は、もう1バイト節約できます。
0<##&@@a
5>##&@@a
これが機能する理由を確認するには、上部にリンクされているヒントの「引数のシーケンス」を確認してください。
##>0&@@a
。ソートの上限についても同様です。
Break
1つまたは2つの文字を保存できる式を貼り付けることができます。例(わかりやすくするためにゴルフを使用していないその他の詳細):
result = False;
Break[]
に変えることができます
Break[result = False]
1文字を保存します。問題の式の優先順位が関数アプリケーションより低い場合、別の文字を保存することもできます。
Print@x;
Break[]
に変えることができます
Break@Print@x
文書化されていませんが、への引数Break
は周囲のループによって返されるようであり、さらに節約につながる可能性があります。
文字列からすべての空白を削除するにはs
、次を使用します
StringSplit@s<>""
つまり、StringSplit
のデフォルト(空白以外のコンポーネントに分割)を使用し、単純にそれらを結合します。他の文字や部分文字列を取り除きたい場合、おそらく同じものがおそらく最も短いです:
s~StringSplit~"x"<>""
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]
定期的に...
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
。
以下は、多くのことを短縮できるオペレーター入力フォームのリストです。これらのいくつかは他の投稿で言及されていますが、リストは長く、そこにいくつかの新しいものを見つけることにいつも驚いています:
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] :> ...
)
コードゴルフでは、s Function
を使用して純粋な引数が最も一般的に参照されSlot
ます。たとえば#
、最初の引数、#2
2番目の引数など(詳細はこの回答を参照)。
多くの場合、Function
s をネストする必要があります。たとえば、1##&@@#&
はFunction
最初の引数としてリストを取り、その要素の積を出力します。以下にその関数を示しますTreeForm
。
最上位に渡された引数は、最上位にあるsおよびs Function
のみを埋めることができます。これは、この場合、内部にある最上位の引数にアクセスする方法がないことを意味します。Slot
SlotSequence
SlotSequence
Function
Function
ただし、場合によっては、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バイト節約されます。
xArray[Mod[#^2,x]&,...]
は、U+F4A1
バイナリ中置演算子を表す3バイトの私用文字\[Function]
です。Function
別の内部ののバイナリ形式を使用することもできますFunction
:
Array[xMod[x^2,#],...]&
これは上記と同等です。その理由は、名前付き引数を使用している場合、Slot
sとSlotSequences
は、Function
名前付き引数を使用しない上記の次のものに属すると想定されるためです。
Function
このようにsをネストできるからといって、常にそうする必要があるわけではありません。たとえば、入力よりも小さいリストの要素を選択したい場合、次のようなことをしたくなるかもしれません。
Select[...,xx<#]&
実際には、使用する方が短くなりCases
、ネストされたFunction
完全な必要性を回避できます。
Cases[...,x_/;x<#]&
あなたの周りの作業でバイトを保存することができますPrepend
かPrependTo
。
l~Prepend~x
{x}~Join~l
{x,##}&@@l
または
l~PrependTo~x
l={x}~Join~l
l={x,##}&@@l
残念ながら、これは他の言語のにAppend
相当する最も短いと思われる、より一般的なには役立ちませんArray.push()
。
BlockMap
はPartition
+Map
このヒントには、「リリースノートをすべて読んでください」というタイトルも付けることができます。(参照用に、ここに10.2のリリースノートと、今日の10.3リリースのリリースノートがあります。)
とにかく、マイナーリリースにも豊富な新機能が含まれており、10.2の(ゴルフで)より便利な機能の1つは新しいBlockMap
機能です。これは基本的にとを組み合わせたものPartition
でMap
、ゴルファーにとっては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... *)
答えが同じ関数または式を複数回使用することになった場合は、変数に保存することを検討してください。
式が長さで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])&]&
Sort
代わりにSortBy
などのリストのlist = {{1, "world"}, {0, "universe"}, {2, "country"}}
場合、次の3つのステートメントはほぼ同等です。
SortBy[list,#[[1]]&]
list~SortBy~First
Sort@list
Select
てSortBy
場合によっては、より大きなセットからエントリを選択してソートし、最小/最大を見つける必要があります。状況によっては、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/0
はComplexInfinity
、すべての実数より「大きい」です。
キーと値のリストの場合、たとえば:
{SortValue,#}&/@SortBy[Select[l,SomeFormula==SomeConstant],SortValue&]
Sort[{SortValue+99!(SomeFormula-SomeConstant)^2,#})&/@l]
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
デフォルト値は、欠落しているパターン引数を効率的な方法で処理します。たとえば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_.
。
デフォルト値は操作に関連付けられています。上記の例では、操作はTimes
in 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] *)
(Norm[#-#2]&)
EuclideanDistance