如何在J中重构这个?

时间:2009-10-12 17:16:11

标签: refactoring j tacit-programming

Project Euler#1的新手解决方案

+/((0=3|1+i.1000-1) +. (0=5|1+i.1000-1)) * (1+i.1000-1)

我知道这可以重构,转换成函数,我不知道怎么做,我必须阅读所有的实验来学习它。

2 个答案:

答案 0 :(得分:7)

没有必要“处理零”,因为添加零不会改变答案,因此您只需使用i.生成1000以下的数字列表,例如:

   i. 10
0 1 2 3 4 5 6 7 8 9

J最适合数组,所以你应该能够同时询问3和5的残差(|),你可以使用rank(")来控制参数的方式喂给残渣:

   3 5 |"0 1 i. 10
0 1 2 0 1 2 0 1 2 0
0 1 2 3 4 0 1 2 3 4

|"0 1表示将左参数一次性提供给|项目,同时一次一行地输入正确的参数。因为右边的参数只包含一行,所以它会反复输入每个左参数项。

现在我们可以对整个数组执行0=

   0 = 3 5 |"0 1 i. 10
1 0 0 1 0 0 1 0 0 1
1 0 0 0 0 1 0 0 0 0

在数组的两个项目(行)之间插入OR条件:

  +./ 0 = 3 5 |"0 1 i. 10
1 0 0 1 0 1 1 0 0 1

获取列表/向量中每个1的索引:

  I. +./ 0 = 3 5 |"0 1 i. 10
0 3 5 6 9

总结:

 +/ I. +./ 0 = 3 5 |"0 1 i. 10

23

你可以很容易地将它变成一个明确的函数/动词:

   euler1=: verb define
+/ I. +./ 0 = 3 5 |"0 1 i. y
)

或者,一旦你掌握了默契J,你可以定义:

   euler1=: +/@I.@(+./)@(0 = 3 5 |"0 1 i.)

答案 1 :(得分:1)

  • 重构0=(会增加程序大小)

+/((3|1+i.1000-1)+.&(0=])5|1+i.1000-1)*1+i.1000-1

  • 重构1+i.1000-1

+/(((3|])+.&(0=[)5|])1+i.1000-1)*1+i.1000-1

  • 再次重构1+i.1000-1

+/(*(3|])+.&(0=[)5|])1+i.1000-1

到目前为止,我唯一无法重构的是|运算符