我还没有一个完整的答案,但是Roger Hui 的这篇文章有一个默认的结构,你可以用它来替换显式的 while 循环。另一种(相关的)途径是将块的内部逻辑变成这样的默认表达:
FUNWITHTACIT =: ] , {: + {: +. 1 + #
rowland =: monad define
result =. >a:
t =. 7x
while. (# result) < y do.
t =. FUNWITHTACIT t
d =. | -/ _2 {. t
result =. ~.result,((d>1)#d)
end.
result
)
(但是,为了提高效率,您可能希望保留 if 块,因为我以这样一种方式编写代码,即result
无论是否满足条件都会被修改——如果不满足,则修改无效。if
甚至可以使用 Agenda 运算符将逻辑写回默认表达式。)
一个完整的解决方案将包括找出如何将 while 循环中的所有逻辑表示为单个函数,然后使用 Roger 的技巧将 while 逻辑实现为默认表达式。我会看看我能出现什么。
顺便说一句,我通过获取代码的前几行来为我构建 J FUNWITHTACIT
,手动替换为变量值声明的函数(我可以这样做,因为它们都以不同的方式对单个参数进行操作) ,替换了t
with的每个实例,y
并告诉 J 构建结果表达式的默认等价物:
]FUNWITHTACIT =: 13 : 'y,({:y)+(1+#y)+.({:y)'
] , {: + {: +. 1 + #
使用 13 来声明 monad 是 J 如何知道采用 monad(否则显式声明为3 : 0
,或monad define
您在程序中编写的)并将显式表达式转换为默认表达式。
编辑:
以下是我在评论中提到的为大道 (2) 编写的函数:
candfun =: 3 : '(] , {: + {: +. 1 + #)^:(y) 7'
firstdiff =: [: | 2 -/\ ]
triage =: [: /:~ [: ~. 1&~: # ]
rowland2 =: triage @firstdiff @candfun
此函数使用 Rowland 递归关系生成前 n 个候选数,评估它们的一阶差分,丢弃所有等于 1 的一阶差分,丢弃所有重复项,并按升序对它们进行排序。我认为这还不完全令人满意,因为参数设置了要尝试的候选人数量而不是结果数量。但是,它仍然是进步的。
例子:
rowland2 1000
3 5 7 11 13 23 47 101 233 467 941
这是我发布的第一个函数的一个版本,将每个参数的大小保持在最小:
NB. rowrec takes y=(n,an) where n is the index and a(n) is the
NB. nth member of the rowland candidate sequence. The base case
NB. is rowrec 1 7. The output is (n+1,a(n+1)).
rowrec =: (1 + {.) , }. + [: +./ 1 0 + ]
rowland3 =: 3 : 0
result =. >a:
t =. 1 7
while. y > #result do.
ts =. (<"1)2 2 $ t,rowrec t
fdiff =. |2-/\,>(}.&.>) ts
if. 1~:fdiff do.
result =. ~. result,fdiff
end.
t =. ,>}.ts
end.
/:~ result
)
它找到前 y 个不同的 Rowland 素数并按升序显示它们:
rowland3 20
3 5 7 11 13 23 47 53 101 233 467 941 1889 3779 7559 15131 30323 60647 121403 242807
这个函数的大部分复杂性来自我对盒装数组的处理。这不是漂亮的代码,但它只4+#result
在计算期间将许多数据元素(以对数规模增长)保留在内存中。原始函数rowland
将(#t)+(#result)
元素保存在内存中(以线性比例增长)。rowland2 y
构建一个 -many 元素的数组y
,这使得它的内存配置文件几乎相同,rowland
即使它永远不会超过指定的界限。我喜欢rowland2
它的紧凑性,但没有一个公式来预测生成 n 个不同素数所需的确切大小y
,该任务将需要在试错的基础上完成,因此可能会使用比rowland
或更多rowland3
的周期冗余计算。rowland3
可能比我的版本更有效rowland
,因为在每次循环迭代时重新计算——FUNWITHTACIT
只是增加一个计数器,计算量较小。#t
rowland3
rowland3
不过,我对' 的显式控制结构并不满意。似乎应该有一种方法可以使用递归或其他方法来完成此行为。