有没有一种方法可以缩短胖箭头功能?


15

从我在PPCG上所看到的时间来看,大多数涉及胖箭头功能的JavaScript条目往往是两个阵营之一:

  1. 能够作为单个语句运行并返回答案的简单示例,就像这样 x=(a,b)=>a*a+b

  2. 由于使用循环,通常比较复杂的花括号大括号,因此需要使用return语句。p=b=>{m=b;for(a=1;~-m;)--m,a*=m*m;return a%b}

以类别2的上述示例为例,使用花括号概念作为概念证明...是否有办法像这样重新投放此代码(或类似代码),以便消除花括号和return?我只是问这个问题,因为这有可能(并不是说会一直发生)从JS高尔夫球手的代码中消除8个字节。在这种情况下,可以使用任何技术吗?我尝试了递归,但是该m=b语句已被证明有点麻烦,因为我似乎无法动摇它。

对于上面的代码,return无论打高尔夫球的时间短与短,打高尔夫球如何进一步消除这种说法?

Answers:


18

使用递归

我发现递归(几乎)总是比eval+ 短for。从for转换为eval的一般方法是:

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

因此,让我们看一下您的示例:

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

我们可以首先将其简化为:

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

我们在这里做了什么?好吧,我们只是将for语句中的所有内容都移了进去,这有助于我们减少分号的数量,这不是直接好一点,但几乎总会导致高尔夫运动。


让我们将其放在eval中,并将其与递归版本进行比较:

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)

在for循环(a=n)的第一部分,我们可以通过将这些变量作为参数传递来开始。条件很简单:返回值b?(c,f(a)):d在哪里d。通常c只进行修改,a以便可以将其合并到其中。因此,我们可以使用我提到的内容进一步打高尔夫球:

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

就是说,正如@Niel所指出的,它正在简化您的算法。一种算法的一种语言可能无法用另一种语言进行,因此请确保尝试不同的算法并进行比较。


1
您错过了简化原始代码方面的巨大节省。~-mm-1,因此循环可以是for(m=b,a=1;--m;a*=m*m)a%b;,递归版本可以(未试用)b=>(f=a=>--m?f(a*=m*m):a%b)(1,m=b)
Peter Taylor

1
有时您只需要使用不同的算法,但在这种情况下,我能做的最好的长度就是与@PeterTaylor的答案相同的长度:b=>b>1&(f=a=>--a<2||b%a&&f(a))(b)
Neil

11

滥用评估。

这很简单。代替:

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

采用

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

Eval返回最后计算的语句。在这种情况下,由于最后一个求值的语句是c+=n,所以c无论如何我们将剩下两个字节。

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

一般来说:

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

比这个短一个字节:

f=n=>{code;return x}

请注意,使用坟墓调用eval可能保存字节不起作用,因为:

eval`string`

相当于

["string"]

有助于混淆!对于代码高尔夫而言,并没有那么多。


2
foo`string`始终等于foo(["string"]),只是很多函数然后将数组强制转换回所需的字符串。
尼尔

@Neil哦,真有趣!
科纳·奥布莱恩
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.