Eratosthenes的J(Tacit)筛子

时间:2012-11-28 15:46:37

标签: primes j sieve-of-eratosthenes

我正在寻找J代码来执行以下操作。

假设我有一个随机整数列表(已排序), 2 3 4 5 7 21 45 49 61 我想从第一个元素开始并删除列表中任何元素的倍数,然后继续下一个元素取消它的倍数,依此类推。

因此输出 我看的是2 3 5 7 61.基本上是Eratosthenes的筛子。如果有人能够解释代码,我将不胜感激,因为我正在学习J并且发现很难获得大多数代码:(

此致 babsdoc

2 个答案:

答案 0 :(得分:4)

这不完全是你问的问题,但这是Sieve的一个更惯用的(以及更多更快)版本。

基本上,您需要检查哪个数字是多个。您可以从模数表中获取此信息:|/~

l =: 2 3 4 5 7 21 45 49 61
|/~ l
  0 1 0 1 1  1  1  1  1
  2 0 1 2 1  0  0  1  1
  2 3 0 1 3  1  1  1  1
  2 3 4 0 2  1  0  4  1
  2 3 4 5 0  0  3  0  5
  2 3 4 5 7  0  3  7 19
  2 3 4 5 7 21  0  4 16
  2 3 4 5 7 21 45  0 12
  2 3 4 5 7 21 45 49  0

每对倍数在表格上给出0。现在,我们对与自模相对应的0不感兴趣(2 mod 2,3 mod 3等;对角线上的0 s)所以我们必须删除它们。一种方法是在其位置添加1,如下所示:

=/~ l
  1 0 0 0 0 0 0 0 0
  0 1 0 0 0 0 0 0 0
  0 0 1 0 0 0 0 0 0
  0 0 0 1 0 0 0 0 0
  0 0 0 0 1 0 0 0 0
  0 0 0 0 0 1 0 0 0
  0 0 0 0 0 0 1 0 0
  0 0 0 0 0 0 0 1 0
  0 0 0 0 0 0 0 0 1
(=/~l) + (|/~l)
  1 1 0 1 1  1  1  1  1
  2 1 1 2 1  0  0  1  1
  2 3 1 1 3  1  1  1  1
  2 3 4 1 2  1  0  4  1
  2 3 4 5 1  0  3  0  5
  2 3 4 5 7  1  3  7 19
  2 3 4 5 7 21  1  4 16
  2 3 4 5 7 21 45  1 12
  2 3 4 5 7 21 45 49  1

这也可以写成(=/~ + |/~) l

从此表中我们得到最终的数字列表:其列中包含0的每个数字都将被排除。

我们只需乘以列来构建此排除列表。如果列包含0,则其产品为0,否则为正数:

*/ (=/~ + |/~) l
   256 2187 0 6250 14406 0 0 0 18240

在完成最后一步之前,我们必须稍微改进一下。没有理由进行长乘法,因为我们只对0not-0感兴趣。因此,在构建表格时,我们只会通过获取每个数字的“符号”(这是signum:*)来保留01

* (=/~ + |/~) l
  1 1 0 1 1 1 1 1 1
  1 1 1 1 1 0 0 1 1
  1 1 1 1 1 1 1 1 1
  1 1 1 1 1 1 0 1 1
  1 1 1 1 1 0 1 0 1
  1 1 1 1 1 1 1 1 1
  1 1 1 1 1 1 1 1 1
  1 1 1 1 1 1 1 1 1
  1 1 1 1 1 1 1 1 1

所以,

*/ * (=/~ + |/~) l
  1 1 0 1 1 0 0 0 1

从排除列表中,您只需将copy#数字添加到最终列表中:

l #~ */ * (=/~ + |/~) l
   2 3 5 7 61

,或者

(]#~[:*/[:*=/~+|/~) l
   2 3 5 7 61

答案 1 :(得分:2)

隐性迭代通常使用连接Power完成。当完成测试需要不是命中一个固定点时,Do While构造运行良好。

在此解决方案中,重复应用filterMultiplesOfHead,直到没有更多数字未应用或过滤。已经应用的数字在部分答案中累积。当要处理的列表为空时,在剥离用于隔离未处理数据处理的装箱后,部分答案就是结果。

   filterMultiplesOfHead=: {. (((~: >.)@ %~) # ]) }.
   appendHead=: (>@[ , {.@>@])/
   pass=: appendHead ; filterMultiplesOfHead@>@{:
   prep=: a: , <
   unfinished=: [: -. a: -: {:
   sieve=: [: ; [: pass^:unfinished^:_ prep

   sieve 2 3 4 5 7 21 45 49 61 
2 3 5 7 61

   prep 2 3 4 7 9 10
┌┬────────────┐
││2 3 4 7 9 10│
└┴────────────┘
   appendHead prep 2 3 4 7 9 10
2
   filterMultiplesOfHead 2 3 4 7 9 10
3 7 9
   pass^:2 prep 2 3 4 7 9 10
┌───┬─┐
│2 3│7│
└───┴─┘
   sieve 1-.~/:~~.>:?.$~100
2 3 7 11 29 31 41 53 67 73 83 95 97