C'è un modo per accorciare le funzioni della freccia grassa?


15

Da quello che ho visto durante il mio periodo qui su PPCG, la maggior parte delle voci JavaScript che coinvolgono le funzioni di freccia grassa tendono ad essere uno dei due campi:

  1. Quelli semplici che sono in grado di funzionare come una singola istruzione e restituire una risposta, immediatamente, come x=(a,b)=>a*a+b

  2. Quelli più complessi che di solito hanno parentesi graffe a causa dell'uso di anelli e, di conseguenza, richiedono l'uso di returnun'istruzione .. comep=b=>{m=b;for(a=1;~-m;)--m,a*=m*m;return a%b}

Prendendo l'esempio sopra dalla categoria 2 con il concetto di parentesi graffe come prova di concetto ... Ci sarebbe un modo per re-golf questo codice (o simile) in questo modo in modo da eliminare le parentesi graffe e il return? Lo sto chiedendo solo perché questo potrebbe potenzialmente (non dire che accadrà sempre) eliminare 8 byte dal codice di un giocatore JS. Ci sono delle tecniche che si potrebbero usare in questo caso? Ho provato la ricorsione, ma l' m=baffermazione si è rivelata un po 'problematica, dato che non riesco a scuoterla.

Per il codice di cui sopra, come si potrebbe golf ulteriormente così da eliminare l' returnaffermazione, indipendentemente dal fatto che il golf sia più corto o meno?

Risposte:


18

Usa la ricorsione

Ho scoperto che la ricorsione è (quasi) sempre più breve di eval+ for. Il modo generale per convertire da per a eval è:

for(a=n;b;c);d
(f=a=>b?f(c):d)(n)

Quindi vediamo il tuo esempio:

b=>{m=b;for(a=1;~-m;)--m,a*=m*m;return a%b}

Possiamo prima semplificarlo per:

for(m=b,a=1;~-m;--m,a*=m*m)a%b;

Cosa abbiamo fatto qui? Bene, abbiamo semplicemente spostato tutto all'interno fordell'istruzione, questo ci aiuta a ridurre la quantità di punti e virgola che non è direttamente migliore, ma quasi sempre porta a un po 'di golf.


Mettiamolo in eval e confrontiamolo con la versione ricorsiva:

b=>{m=b;for(a=1;~-m;)--m,a*=m*m;return a%b}
b=>eval('for(m=b,a=1;~-m;--m,a*=m*m)a%b')
b=>(f=a=>~-m?(--m,f(a*=m*m)):a%b)(1,m=b)

La prima parte del ciclo for ( a=n), possiamo iniziare passando quelle variabili come argomenti. La condizione è semplicemente: b?(c,f(a)):ddov'è dil valore di ritorno. Di solito si cmodifica solo in amodo che possa essere unito in esso. Quindi possiamo giocare a golf ancora di più usando ciò che ho menzionato:

b=>(f=a=>~-m?(--m,f(a*=m*m)):a%b)(1,m=b)
b=>(f=a=>~-m?f(a*=--m*m):a%b)(1,m=b) // --m moved into a*=
b=>(f=a=>--m?f(a*=m*m):a%b)(1,m=b) // --m moved to condition

Detto questo, come notato da @Niel sta semplificando il tuo algoritmo. Un algoritmo golfy in una lingua potrebbe non essere golfy in un'altra, quindi assicurati di provare algoritmi diversi e confrontarli.


1
Hai perso un grande risparmio nel semplificare il codice originale. ~-mè m-1, quindi il ciclo può essere for(m=b,a=1;--m;a*=m*m)a%b;e la versione ricorsiva può essere (non testata)b=>(f=a=>--m?f(a*=m*m):a%b)(1,m=b)
Peter Taylor

1
A volte devi solo usare un algoritmo diverso, ma in questo caso il meglio che potevo fare era la stessa lunghezza della risposta di @ PeterTaylor:b=>b>1&(f=a=>--a<2||b%a&&f(a))(b)
Neil

11

Abuso eval.

È semplice. Invece di:

f=n=>{for(i=c=0;i<n;i++)c+=n;return c}

Uso

f=n=>eval("for(i=c=0;i<n;i++)c+=n;c")

Eval restituisce l'ultima istruzione valutata. In questo caso, poiché l'ultima affermazione valutata sarebbe c+=n, cresteremmo comunque con un risparmio di due byte.

f=n=>eval("for(i=c=0;i<n;i++)c+=n")

In generale:

f=n=>eval("code;x")

è più breve di questo, di un byte:

f=n=>{code;return x}

Come nota, l'uso di tombe per chiamare eval per salvare eventualmente byte non funziona, poiché:

eval`string`

è equivalente a

["string"]

Utile per l'offuscamento! Non tanto per il golf del codice.


2
foo`string`è sempre equivalente a foo(["string"]), è solo che molte funzioni quindi riportano l'array nella stringa desiderata.
Neil,

@Neil Oh, che interessante!
Conor O'Brien,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.