Kennen Sie Ihre reinen Funktionsargumente
Wenn Sie Code golfen, wenden Sie häufig einen funktionalen Ansatz an, bei dem Sie anonyme (reine) Funktionen mit der &
Kurzschreibensyntax verwenden. Es gibt viele verschiedene Möglichkeiten, auf die Argumente einer solchen Funktion zuzugreifen, und Sie können sich oft ein paar Bytes sparen, wenn Sie die Möglichkeiten genau kennen.
Zugriff auf einzelne Argumente
Sie wissen dies wahrscheinlich, wenn Sie zuvor reine Funktionen verwendet haben. Die n - te Argument wird als bezeichnet #n
und #
dient als Alias für #1
. Wenn Sie also beispielsweise eine Funktion schreiben möchten, die eine andere Funktion und ihr Argument als Parameter verwendet (um das Argument an diese Funktion zu übergeben), verwenden Sie
#@#2&
Dies funktioniert nicht mit negativen Zahlen (wie Sie sie möglicherweise beim Zugriff auf Listen verwenden).
Zugriff auf benannte Argumente (neu in V10)
Eine der wichtigsten neuen Sprachfunktionen in Mathematica 10 ist Association
s, bei denen es sich im Grunde um Schlüsselwertzuordnungen mit beliebigen Schlüsseltypen handelt, die wie folgt geschrieben wurden
<| x -> 1, "abc" -> 2, 5 -> 3 |>
Wenn eine solche Zuordnung als erstes Argument an eine reine Funktion übergeben wird, können Sie auf einige ihrer Argumente als benannte Parameter zugreifen:
{#, #2, #3, #abc, #xyz} & [<| "abc" -> "1st", "xyz" -> "2nd", abc -> "3rd" |>, "4th", "5th"]
(* {<| "abc" -> "1st", "xyz" -> "2nd", abc -> "3rd" |>, "4th", "5th", "1st", "2nd"} *)
Beachten Sie, dass sich #
immer noch wie erwartet auf die gesamte Zuordnung bezieht. Damit die genannten Parameter funktionieren, müssen die Schlüssel Zeichenfolgen sein (dies funktioniert beispielsweise nicht, wenn Sie nicht definierte Variablen verwenden). Diese Zeichenfolgen müssen mit einem Buchstaben beginnen und nur Buchstaben und Ziffern enthalten.
Das "Selbst" -Argument #0
Eine weniger bekannte Funktion ist die, die #0
ebenfalls vorhanden ist und Ihnen das Funktionsobjekt selbst gibt. Dies kann in Quines und verallgemeinerten Quines sehr nützlich sein. Tatsächlich ist die kürzeste Mathematica-Quine (die ich kenne)
ToString[#0][] & []
Etwas ärgerlich ist, dass Sie nicht genau die Zeichen erhalten, die Sie eingegeben haben. Wenn Sie sie beispielsweise @
für eine Funktionsanwendung verwenden, wird sie weiterhin als gerendert [...]
und an einigen Stellen werden Leerzeichen eingefügt. Dadurch wird das Quine normalerweise etwas länger, als Sie es gerne hätten, aber es funktioniert immer, wenn Sie zuerst das Quine golfen und dann nur dessen Ausgabe kopieren - was nun ein echtes Quine sein sollte.
Abgesehen von Quines bedeutet dies auch, dass Sie rekursiven Code schreiben können, ohne Ihre Funktion benennen zu müssen. Vergleichen Sie diese drei (naiven, aber golfenen) Fibonacci-Implementierungen:
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]]&
Folgen von Argumenten
Hier beginnt die wahre Magie. Sequenzen werden beim Golfen nicht oft verwendet, da Sequence
der Name einfach zu lang ist, um ihn die meiste Zeit wert zu sein. Aber in reinen Funktionen leuchten sie. Wenn Sie mit Sequenzen nicht vertraut sind, ähneln sie im Grunde Splats in anderen Sprachen. Wenn Sie eine Sequenz in einer List
oder der Argumentliste einer Funktion verwenden, werden ihre Elemente automatisch in separate Slots erweitert. Damit
{1, Sequence[2, 3, 4], 5} == {1, 2, 3, 4, 5}
f["a", Sequence[0, {}], "b"] == f["a", 0, {}, "b"]
Nun, in reinen Funktionen ##
oder ##1
ist eine Folge aller Argumente. Ebenso ##2
ist eine Folge aller Argumente aus der zweiten Start, ##3
alle Argumente aus der dritten etc. Also zunächst einmal gestartet wurde , können wir reimplementieren nur Sequence
wie ##&
, spart 5 Byte. Als Beispiel für die Verwendung bietet dies eine Alternative zu Join@@list
(siehe diesen Tipp ), die keine Bytes speichert, aber dennoch gut zu wissen ist:
##&@@@list
Dadurch wird die erste Ebene einer verschachtelten Liste effektiv geglättet. Was können wir sonst noch damit machen? Hier ist eine 2 Bytes kürzere Alternative zu RotateLeft
:
RotateLeft@list
{##2,#}&@list
Allein für diese Dinge lohnt es sich, diese Funktion zu berücksichtigen. Wir können es jedoch besser machen! Sequenzen werden wirklich interessant, wenn man bedenkt, dass Operatoren tatsächlich als Funktionen unter der Haube implementiert sind. ZB a+b
wertet das eigentlich aus Plus[a,b]
. Also, wenn wir das eine Sequenz geben ...
1+##&[1,2,3]
=> Plus[1,##]
=> Plus[1,1,2,3]
=> 7
Dieser Trick wurde in diesem Tipp verwendet , um ein Byte zu sparen Times
, da die Gegenüberstellung technisch gesehen auch nur ein Operator ist:
1##&[1,2,3]
=> Times[1,##]
=> Times[1,1,2,3]
=> 6
Sie können es auch verwenden, um ein Byte zu speichern, Unequal
wenn Sie einen Einzelzeichenwert oder eine Variable haben, von der Sie wissen, dass sie nicht in Ihren Argumenten enthalten sind (dies N
funktioniert wahrscheinlich in 99% der Fälle):
Unequal[a,b,c]
N!=##&[a,b,c]
Dies wird bei unären Operatoren noch interessanter -
und /
- die beiden letzteren werden tatsächlich in Bezug auf Multiplikation und Potenzierung implementiert. Hier ist eine Liste der Aktionen, bei denen in der letzten Spalte davon ausgegangen wird, dass der Funktion die Argumente übergeben wurden 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
Andere gemeinsame Operatoren sind !=
, ==
, &&
, ||
. Weniger häufig diejenigen im Auge zu behalten sind |
, @*
, /*
. Abschließend noch ein kleiner Bonus-Trick:
#### Times[##,##] Times[a,b,c,a,b,c] (a*b*c)^2
Experimentieren Sie weiter mit diesen und lassen Sie mich wissen, wenn Sie andere nützliche oder besonders interessante Anwendungen finden!
(Norm[#-#2]&)
alsEuclideanDistance
.