编写我的第一个 J 程序来求解欧拉问题 #1(找到所有低于 1000 且是 3 或 5 的倍数的自然数之和),我得到了以下解决方案:
+/(+./0=3 5|/n)#n=.i.1000
但是,我很确定有一种巧妙的方法可以做到这一点,而无需使用变量。我尝试使用 fork 重写它,但我不知道如何将 () 之间的表达式替换为应用于3 5
and的动词i.1000
。有人可以帮助我吗?
编写我的第一个 J 程序来求解欧拉问题 #1(找到所有低于 1000 且是 3 或 5 的倍数的自然数之和),我得到了以下解决方案:
+/(+./0=3 5|/n)#n=.i.1000
但是,我很确定有一种巧妙的方法可以做到这一点,而无需使用变量。我尝试使用 fork 重写它,但我不知道如何将 () 之间的表达式替换为应用于3 5
and的动词i.1000
。有人可以帮助我吗?
为了参数化这两个值,从而泛化为二元动词,我们需要将每个参数传递到需要它们的地方。从这个分叉开始,我们可以专注于3 5
实际需要的唯一点:
3 5 ([ |/ i.@]) 1000
在整个程序中,我们需要两个地方的整数列表。名称 ( n
) 为我们提供了在两个地方使用该列表的简单方法。为了快速完成整个程序,在写这篇文章时,我最初计算了两次列表:
3 5 ([: +/ i.@] # [:+./ 0= [ |/ i.@]) 1000
i.
这成功地将整个程序表述为二元动词,但出现两次也有缺点。我们可以通过将其设为正确的叉齿,将其提取为仅发生一次。那个叉子的中心是一个新的、内在的动词。
3 5 ([: +/ [ (] # [:+./ 0= [ |/ ]) i.@]) 1000
NB. ___________________ new "inner" verb, parenthesized
这个内在动词需要接收3 5
作为参数,所以我通过最外层动词的左参数作为这个内在动词的左参数。这意味着内部动词中的 Left ( [
) 与之前版本中的值相同,当它引用最外层参数时。在这个新动词中 Right ( ]
) 指的是整数列表,i.@]
出现在之前出现的两个地方。
后记:正如您在评论中显示的那样,[ |/ ]
简化为|/