Conosci i tuoi argomenti di pura funzione
Quando giochi a golf, utilizzerai spesso un approccio funzionale, in cui usi funzioni anonime (pure) con la &
sintassi abbreviata. Esistono molti modi diversi per accedere agli argomenti di tale funzione e spesso puoi radere un paio di byte avendo una buona conoscenza delle possibilità.
Accesso a singoli argomenti
Probabilmente lo sai se hai già usato funzioni pure. Il n ° argomento è indicato come #n
, e #
agisce come un alias per #1
. Quindi, se, per esempio, vuoi scrivere una funzione che accetta come parametri un'altra funzione e il suo argomento (per passare l'argomento a quella funzione), usa
#@#2&
Questo non funziona con numeri negativi (come potresti usare quando accedi agli elenchi).
Accesso agli argomenti denominati (novità in V10)
Una delle principali nuove funzionalità del linguaggio in Mathematica 10 è Association
s, che sono fondamentalmente mappe di valori-chiave con tipi di chiavi arbitrari, scritte come
<| x -> 1, "abc" -> 2, 5 -> 3 |>
Se tale associazione viene passata come primo argomento a una funzione pura, è possibile accedervi se i suoi argomenti sono denominati parametri:
{#, #2, #3, #abc, #xyz} & [<| "abc" -> "1st", "xyz" -> "2nd", abc -> "3rd" |>, "4th", "5th"]
(* {<| "abc" -> "1st", "xyz" -> "2nd", abc -> "3rd" |>, "4th", "5th", "1st", "2nd"} *)
Si noti che #
fa ancora riferimento all'intera associazione come previsto. Perché i parametri nominati funzionino, le chiavi devono essere stringhe (non funzionerà se ad esempio si utilizzano variabili non definite) e tali stringhe devono iniziare con una lettera e contenere solo lettere e cifre.
L'argomento "auto" #0
#0
Esiste anche una caratteristica meno conosciuta , che fornisce l'oggetto funzione stesso. Questo può essere davvero utile in quines e quines generalizzate. In effetti, il quine Mathematica più corto (lo so) è
ToString[#0][] & []
La cosa leggermente fastidiosa è che non ti darà i caratteri esatti che hai inserito. Ad esempio, se utilizzato @
per l'applicazione della funzione, verrà comunque visualizzato come [...]
e gli spazi verranno inseriti in alcuni punti. Questo di solito renderà il quine un po 'più lungo di quanto vorresti che fosse, ma funzionerà sempre, giocando prima sul golf e poi copiandone l'output, che ora dovrebbe essere un vero quin.
Oltre alle quines, questo significa anche che puoi scrivere codice ricorsivo senza dover nominare la tua funzione. Confronta queste tre implementazioni di Fibonacci (ingenue ma giocate a golf):
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]]&
Sequenze di argomenti
Ora è qui che inizia la vera magia. Le sequenze non vengono utilizzate spesso nel golf, perché Sequence
è un nome troppo lungo per valerne la pena il più delle volte. Ma nelle funzioni pure è dove brillano. Se non hai familiarità con le sequenze, sono fondamentalmente come simboli in alcune altre lingue, se usi una sequenza in una List
o nella lista degli argomenti di una funzione, i suoi elementi verranno automaticamente espansi in slot separati. Così
{1, Sequence[2, 3, 4], 5} == {1, 2, 3, 4, 5}
f["a", Sequence[0, {}], "b"] == f["a", 0, {}, "b"]
Ora, in pure funzioni ##
o ##1
è una sequenza di tutti gli argomenti. Allo stesso modo, ##2
è una sequenza di tutti gli argomenti a partire dal secondo, ##3
tutti gli argomenti a partire dal terzo ecc. Quindi, per cominciare, possiamo semplicemente reimplementarli Sequence
come ##&
, salvando 5 byte. Come esempio di utilizzo, questo ci fornisce un'alternativa a Join@@list
(vedi questo suggerimento ), che non salva alcun byte, ma è bene sapere comunque:
##&@@@list
Ciò appiattisce efficacemente il primo livello di un elenco nidificato. Cos'altro possiamo fare con questo? Ecco un'alternativa più breve di 2 byte a RotateLeft
:
RotateLeft@list
{##2,#}&@list
Solo per queste cose vale la pena tenere presente questa funzionalità. Tuttavia, possiamo fare di meglio! Le sequenze diventano davvero interessanti se si considera che gli operatori sono effettivamente implementati come funzioni sotto il cofano. Ad esempio, in a+b
realtà valuta Plus[a,b]
. Quindi se diamo una sequenza ...
1+##&[1,2,3]
=> Plus[1,##]
=> Plus[1,1,2,3]
=> 7
Questo trucco è stato utilizzato in questo suggerimento per salvare un byte Times
, poiché la giustapposizione è tecnicamente anche solo un operatore:
1##&[1,2,3]
=> Times[1,##]
=> Times[1,1,2,3]
=> 6
Puoi anche usarlo per salvare un byte Unequal
se hai un valore a singolo carattere o una variabile che sai non è nei tuoi argomenti ( N
probabilmente funzionerà nel 99% dei casi):
Unequal[a,b,c]
N!=##&[a,b,c]
Ciò diventa ancora più interessante con gli operatori unari -
e /
- gli ultimi due sono effettivamente implementati in termini di moltiplicazione ed esponenziazione. Ecco un elenco di cose che puoi fare, in cui l'ultima colonna presuppone che gli argomenti siano stati passati alla funzione 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
Altri operatori sono comuni !=
, ==
, &&
, ||
. Quelli meno comuni da tenere a mente sono |
, @*
, /*
. Per concludere, ecco un piccolo trucco bonus:
#### Times[##,##] Times[a,b,c,a,b,c] (a*b*c)^2
Continua a sperimentare con questi e fammi sapere se trovi altre applicazioni utili o particolarmente interessanti!
(Norm[#-#2]&)
invece diEuclideanDistance
.