Connaissez vos arguments de fonction purs
Lorsque vous jouez au code de golf, vous utiliserez souvent une approche fonctionnelle, consistant à utiliser des fonctions anonymes (pures) avec une &
syntaxe abrégée. Il y a beaucoup de façons d'accéder aux arguments d'une telle fonction, et vous pouvez souvent supprimer quelques octets en ayant une bonne compréhension des possibilités.
Accéder à des arguments simples
Vous le savez probablement si vous avez déjà utilisé des fonctions pures. Le n ième argument est appelé #n
, et #
agit comme un alias pour #1
. Donc, si, par exemple, vous voulez écrire une fonction qui prenne comme paramètres une autre fonction et son argument (pour passer l'argument à cette fonction), utilisez
#@#2&
Cela ne fonctionne pas avec les nombres négatifs (tels que ceux que vous pourriez utiliser pour accéder aux listes).
Accès aux arguments nommés (nouveauté V10)
L’une des nouvelles fonctionnalités majeures de Mathematica 10 est Association
s, qui sont essentiellement des mappes clé-valeur avec des types de clé arbitraires, écrits comme suit:
<| x -> 1, "abc" -> 2, 5 -> 3 |>
Si une telle association est passée en tant que premier argument à une fonction pure, vous pouvez accéder à certains si ses arguments en tant que paramètres nommés:
{#, #2, #3, #abc, #xyz} & [<| "abc" -> "1st", "xyz" -> "2nd", abc -> "3rd" |>, "4th", "5th"]
(* {<| "abc" -> "1st", "xyz" -> "2nd", abc -> "3rd" |>, "4th", "5th", "1st", "2nd"} *)
Notez que #
fait toujours référence à toute l'association comme prévu. Pour que les paramètres nommés fonctionnent, les clés doivent être des chaînes (cela ne fonctionnera pas si vous utilisez des variables non définies, par exemple), et ces chaînes doivent commencer par une lettre et ne contenir que des lettres et des chiffres.
Le "soi" argument #0
Une fonctionnalité moins connue est celle qui #0
existe également et vous donne l'objet fonction lui-même. Cela peut être vraiment utile dans les quines et les quines généralisées. En fait, la quine la plus courte de Mathematica (à ma connaissance) est
ToString[#0][] & []
Ce qui est légèrement ennuyeux, c'est que cela ne vous donnera pas les caractères exacts que vous avez entrés. Par exemple si utilisation@
pour une application de fonction, il restera rendu en tant que [...]
et des espaces seront insérés à certains endroits. La quine sera généralement un peu plus longue que vous ne le voudriez, mais cela fonctionnera toujours, en jouant d'abord sur la quine, puis en copiant simplement sa sortie - qui devrait maintenant être une vraie quine.
Outre quines, cela signifie également que vous pouvez écrire du code récursif sans avoir à nommer votre fonction. Comparez ces trois implémentations de Fibonacci (naïves mais golfées):
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]]&
Séquences d'arguments
Maintenant, c’est là que commence la vraie magie. Les séquences ne sont pas souvent utilisées dans le golf, parce que Sequence
c'est un nom trop long pour qu'il en vaille la peine la plupart du temps. Mais dans les fonctions pures, c'est là où elles brillent. Si vous n'êtes pas familier avec les séquences, elles ressemblent fondamentalement aux splats dans d'autres langues. Si vous utilisez une séquence dans une List
liste d'arguments ou une liste d'arguments d'une fonction, ses éléments seront automatiquement développés dans des emplacements distincts. Alors
{1, Sequence[2, 3, 4], 5} == {1, 2, 3, 4, 5}
f["a", Sequence[0, {}], "b"] == f["a", 0, {}, "b"]
Maintenant, dans les fonctions pures ##
ou ##1
est une séquence de tous les arguments. De même, ##2
est une séquence de tous les arguments commençant à partir du deuxième, ##3
tous les arguments commençant à partir du troisième, etc. Ainsi, pour commencer, nous pouvons simplement réimplémenter Sequence
en ##&
économisant 5 octets. À titre d'exemple d'utilisation, cela nous fournit une alternative à Join@@list
(voir cette astuce ), qui ne sauvegarde aucun octet, mais qui est bon à savoir de toute façon:
##&@@@list
Cela aplatit efficacement le premier niveau d'une liste imbriquée. Que pouvons-nous faire avec ça? Voici une alternative plus courte de 2 octets à RotateLeft
:
RotateLeft@list
{##2,#}&@list
Rien que pour ces choses, il convient de garder cette caractéristique à l’esprit. Cependant, nous pouvons faire mieux! Les séquences deviennent vraiment intéressantes quand on considère que les opérateurs sont réellement implémentés en tant que fonctions sous le capot. Par exemplea+b
évalue à Plus[a,b]
. Donc, si nous donnons à cela une séquence ...
1+##&[1,2,3]
=> Plus[1,##]
=> Plus[1,1,2,3]
=> 7
Cette astuce a été utilisée dans cette astuce pour enregistrer un octet surTimes
, car la juxtaposition n’est techniquement qu’un opérateur:
1##&[1,2,3]
=> Times[1,##]
=> Times[1,1,2,3]
=> 6
Vous pouvez également l'utiliser pour enregistrer un octet Unequal
si vous avez une valeur à caractère unique ou une variable dont vous savez qu'elle ne figure pas dans vos arguments ( N
fonctionnera probablement dans 99% des cas):
Unequal[a,b,c]
N!=##&[a,b,c]
Cela devient encore plus intéressant avec les opérateurs unaires -
et /
- les deux derniers sont en réalité mis en œuvre en termes de multiplication et d’exponentiation. Voici une liste de choses que vous pouvez faire, où la dernière colonne suppose que la fonction a reçu les arguments 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
D' autres opérateurs sont communs !=
, ==
, &&
, ||
. Les moins communes à garder à l' esprit sont |
, @*
, /*
. Pour conclure, voici un petit bonus:
#### Times[##,##] Times[a,b,c,a,b,c] (a*b*c)^2
Continuez à expérimenter avec ceux-ci et faites-moi savoir si vous trouvez d'autres applications utiles ou particulièrement intéressantes!
(Norm[#-#2]&)
au lieu deEuclideanDistance
.