Existe-t-il un moyen de raccourcir les fonctions des flèches grasses?

15

D'après ce que j'ai vu tout au long de mon séjour ici sur PPCG, la plupart des entrées JavaScript impliquant des fonctions de flèche grasse ont tendance à être l'un des deux camps:

  1. Les simples qui sont capables de fonctionner comme une seule déclaration et de retourner une réponse, tout de suite, comme x=(a,b)=>a*a+b

  2. Les plus complexes qui ont généralement des accolades en raison de l'utilisation de boucles, et nécessitent par conséquent l'utilisation d'une returninstruction .. commep=b=>{m=b;for(a=1;~-m;)--m,a*=m*m;return a%b}

En prenant l'exemple ci-dessus de la catégorie 2 avec le concept d'accolades comme preuve de concept ... Y aurait-il un moyen de rejouer ce code (ou similaire) comme celui-ci afin d'éliminer les accolades ainsi que le return? Je pose seulement cette question car cela pourrait potentiellement (ne pas dire que cela se produira tout le temps) éliminer 8 octets du code d'un golfeur JS. Y a-t-il des techniques que l'on pourrait utiliser dans ce cas? J'ai essayé la récursivité, mais la m=bdéclaration s'est avérée être un peu un bugbear, car je n'arrive pas à la secouer.

Pour le code ci-dessus, comment golferait-on plus loin afin d'éliminer la returndéclaration, qu'il joue au golf plus court ou non?

WallyWest
la source

Réponses:

18

Utiliser la récursivité

J'ai trouvé que la récursivité est (presque) toujours plus courte que eval+ for. La façon générale de convertir de for en eval est:

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

Voyons donc votre exemple:

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

Nous pouvons d'abord le simplifier pour:

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

Qu'avons-nous fait ici? Eh bien, nous avons simplement tout déplacé à l'intérieur de la fordéclaration, cela nous aide à réduire la quantité de points-virgules, ce qui n'est pas directement meilleur, mais conduit presque toujours à du golf.


Mettons cela dans eval et comparons-le à la version récursive:

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 première partie de la boucle for ( a=n), nous pouvons commencer cela en passant ces variables comme arguments. La condition est simplement: b?(c,f(a)):ddest la valeur de retour. Modifie généralement cjuste aafin qu'il puisse y être fusionné. Nous pouvons donc jouer au golf encore plus en utilisant ce que j'ai mentionné:

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

Cela dit, comme l'a noté @Niel simplifie votre algorithme. Un algorithme golfy dans une langue peut ne pas être golfy dans une autre alors assurez-vous d'essayer différents algorithmes et de les comparer.

Downgoat
la source
1
Vous avez raté une grosse économie en simplifiant le code d'origine. ~-mest m-1, donc la boucle peut être for(m=b,a=1;--m;a*=m*m)a%b;et la version récursive peut être (non testée)b=>(f=a=>--m?f(a*=m*m):a%b)(1,m=b)
Peter Taylor
1
Parfois, il suffit d'utiliser un algorithme différent, mais dans ce cas, le mieux que j'ai pu faire était la même longueur que la réponse de @ PeterTaylor:b=>b>1&(f=a=>--a<2||b%a&&f(a))(b)
Neil
11

Abus eval.

C'est simple. Au lieu de:

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

Utilisation

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

Eval renvoie la dernière instruction évaluée. Dans ce cas, puisque la dernière instruction évaluée serait c+=n, nous nous retrouverions de ctoute façon, en économisant deux octets.

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

En général:

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

est plus court que cela, d'un octet:

f=n=>{code;return x}

Notez que l'utilisation de graves pour appeler eval pour éventuellement économiser des octets ne fonctionne pas, car:

eval`string`

est équivalent à

["string"]

Utile pour l'obscurcissement! Pas tant pour le golf de code.

Conor O'Brien
la source
2
foo`string`est toujours équivalent à foo(["string"]), c'est juste que de nombreuses fonctions puis convertissent le tableau dans la chaîne souhaitée.
Neil
@Neil Oh, comme c'est intéressant!
Conor O'Brien du