Sundaram筛(用于查找质数)


13

挑战

实施Sundaram筛子查找下面的质数n。取一个输入整数,n并输出下面的质数n。您可以假设该值n始终小于或等于一百万。


  1. 从从1到的整数列表开始n

  2. 删除以下形式的所有数字i + j + 2ij

    • i并且j小于nj始终大于或等于i,大于或等于1

    • i + j + 2ij 小于或等于 n

  3. 将剩余数字乘以2,然后加1

这将产生2小于的所有质数(除了应包含在输出中的质数)2n + 2


这是用来在下面找到素数的筛子的动画202


输出量

您的输出应该是每个素数≤ n(按升序排列),后跟换行符:

2
3
5

哪里n5


例子

> 10
2
3
5
7

> 30
2
3
5
7
11
13
17
19
23
29

输入用表示>


您的示例n=30在输出中缺少29。
isaacg

5
要求使用特定方法的挑战的麻烦在于,尚不清楚人们可以进行哪些修改。例如,您的描述仅(i,j)使用进行检查i<=j,但是如果我们忽略此要求,结果不会改变。我们可以这样做来节省字节吗?
xnor 2015年

我从没说过你必须检查一下i <= j。这只是筛子工作方式的一部分。所以是的,您可以i <= j在代码中省去。@xnor
扎克·盖茨

2
我们这里有多少余地?筛子等效于选择所有非奇数(因为结果为形式2n+1),而不是形式2(i + j + 2ij)+1-我们可以直接在潜在质数上测试此属性,还是我们的代码必须在某点做2加1的时间? ?
马丁·恩德

1
n整个事情让我有些困惑。在方法说明中,它说它将生成直到的所有素数2 * n + 2。但是在输入/输出描述中,它说输入为n,而输出全为n。因此,我们是否应该应用该方法来生成直至的所有素数2 * n + 2,然后删除大于n输出的素数?还是应该n从输入中计算方法描述中的n
Reto Koradi

Answers:



3

Haskell,93个 90字节

import Data.List
g n=unlines[show$2*x+1|r<-[[1..n]],x<-2:(r\\[i+j+2*i*j|j<-r,i<-r]),2*x<n]

工作原理:[i+j+2*i*j|j<-r,i<-r]都已i+j+2ij从中删除(\\[1..n]。缩放至2x+1并将它们变成字符串(show)。加入NL(unlines)。


1

Scala,115124122115114字节

n=>{println(2);for{m<-1 to n;if !(for{j<-1 to n;i<-1 to j}yield i+j+2*i*j).contains(m);o=2*m+1;if o<=n}println(o)}

匿名函数;将n作为参数并将结果输出到stdout。


1

的JavaScript(ES7),107个 105字节

数组理解很棒!但是我不知道为什么JS没有范围语法(例如[1..n])...

n=>{for(a=[i=1];i<n;a[i++]=i);for(i=0;i++<n;)for(j=0;j<n;a[i+j+++2*i*j]=0);return[for(i of a)if(i)i*2+1]}

这已在Firefox 40中成功测试。

n=>{
  for(a=[i=1];i<n;a[i++]=i); // fill a list with 1..n
  for(i=0;i++<n;)            // for each integer i in 0..n
    for(j=0;j<n;)            //   for each integer j in 0..n
      a[i+j+++2*i*j-1]=0;    //     set the corresponding item of the list to 0
  return[for(i of a)         // filter the list by:
          if(i)              //   item != 0 AND item != undefined
           i*2+1]            // and return each result * 2 + 1
}

替代ES6的解决方案(111字节):

n=>{for(a=[i=1];i<n;a[i++]=i);for(i=0;i++<n;)for(j=0;j<n;a[i+j+++2*i*j]=0);return a.filter(x=>x).map(x=>x*2+1)}

建议欢迎!


0

MATLAB,98

n=1:input('');m=n;for p=m for i=1:p j=i:p;for k=i+j+2*i*j n(n==k)=[];end;end;end;disp(2*n'+1);

并以可读的形式

n=1:input(''); %Ask for the input number (e.g. 100) and form a range
m=n; %Back up the range as we will be editing 'n', but need 'm' as a loop list
for p=m %For each number between 1 and n inclusive
    for i=1:p %'i' is all numbers greater than or equal to 1 up to p
        j=i:p; %'j' is all numbers greater than or equal to i up to p
        for k=i+j+2*i*j %Calculate the numbers to remove, and loop through them
            n(n==k)=[]; %Remove that value from the 'n' array
        end
    end
end
disp([2;2*n'+1]); %An display the list including the number 2 seperated by a new line.

0

Java8:168个 165字节

N->{int[]A=new int[N*N];int i=1,j;N=N/2;for(;i<N;i++)for(j=i;j<N;)A[i+j+2*i*j++]=1;System.out.println(N>1?2:\"\");for(i=1;i<N;i++)if(A[i]<1)System.out.println(2*i+1);}

对于更大的数字,可以使用范围广泛的数据类型。我们不需要遍历整个N索引N/2就足够了。

要正确理解,以下是等效方法。

static void findPrimeSundar(int N){
    int[] A = new int[N*N];
    int i=1,j;
    N=N/2;
    for(;i<N;i++)
      for(j=i;j<N;)
        A[i+j+2*i*j++]=1;
    System.out.println(N>1?2:"");
    for(i=1;i<N;i++)
        if(A[i]<1)System.out.println(2*i+ 1);
}

1
N>=2-> N>1A[i]==0-> A[i]<1
lirtosiast,2015年

@ThomasKwa是的,您是对的。谢谢。
CoderCroc 2015年

0

CJam,35个字节

2li:V,:)__2m*{_:+\:*2*+}%m2f*:)&+N*

在线尝试

相对于isaacg的Pyth解决方案,这似乎有些冗长,但这是...我所拥有的。

说明:

2       Push a 2, will be part of final output.
li      Get input and convert to integer n.
:V      Save in variable V for later use.
,       Generate list [0 ... n-1].
:)      Increment list elements to get list [1 ... n].
__      Create two copies, one for sieve, and for clamping results.
2m*     Cartesian power, generating all i,k pairs.
{       Loop over all i,j pairs.
  _     Copy pair.
  :+    Calculate sum i + j.
  \     Swap copy of pair to top.
  :*    Calculate product i * j.
  2*    Multiply by 2, to get 2 * i * j.
  +     Add both values, to get i + j + 2 * i * j.
}%      End loop over all i,j pairs.
m       Sieve operation, remove the calculated values from the list of all values.
2f*     Multiply the remaining values by 2...
:)      ... and add 1 to the. We now have the list of all primes up to 2 * n + 2.
&       Intersect with [1 ... n] list, because output is only values <= n.
+       Concatenate with the 2 we pushed at the start.
N*      Join with newlines.

0

Perl 6,96个字节

如果我严格按照说明进行操作,那么我设法得到的最短长度是96个字节。

->\n {$_=@=1..n;for 1..n {for $^i..n {.[$i+$^j+2*$i*$j-1]=0}};2,|.[0..n].map(* *2+1).grep(3..n)}
->\n {
  $_=@=1..n; # initialize array
  for 1..n { # $i
    for $^i..n { # $j
      .[$i+$^j+2*$i*$j-1]=0 # remove value
    }
  };
  2,|.[0..n].map(* *2+1).grep(3..n)
}

如果可以2n + 1对数组进行初始化,则将其预插入2,并将其限制为仅小于或等于n; 可以减少到84个字节。

->\n {$_=@=2,{++$*2+1}...^*>n;for 1..n {for $^i..n {.[$i+$^j+2*$i*$j]=$}};.grep(?*)}

如果我也忽略了j至少应该将其i减少到82个字节。

->\n {$_=@=2,{++$*2+1}...^*>n;for 1..n X 1..n ->(\i,\j){.[i+j+2*i*j]=$};.grep(?*)}

用法示例:

my $code = ->\n {...} # insert one of the lambdas from above

say $code(30).join(',');
# 2,3,5,7,11,13,17,19,23,29

my &code = $code;
say code 11;
# (2 3 5 7 11)


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.