Sàng của Sundaram (để tìm số nguyên tố)


13

Các thách thức

Thực hiện sàng Sundaram để tìm số nguyên tố dưới đây n. Lấy một số nguyên đầu vào nvà xuất các số nguyên tố bên dưới n. Bạn có thể cho rằng nsẽ luôn nhỏ hơn hoặc bằng một triệu.


Sàng

  1. Bắt đầu với một danh sách các số nguyên từ 1đến n.

  2. Xóa tất cả các số có dạng i + j + 2ij:

    • ijít hơn n. jluôn luôn lớn hơn hoặc bằng i, lớn hơn hoặc bằng 1.

    • i + j + 2ij nhỏ hơn hoặc bằng n

  3. Nhân các số còn lại với 2và thêm 1.

Điều này sẽ mang lại tất cả các số nguyên tố (ngoại trừ 2, nên được bao gồm trong đầu ra của bạn) ít hơn 2n + 2.


Dưới đây là một hình ảnh động của sàng được sử dụng để tìm các số nguyên tố dưới đây 202.


Đầu ra

Đầu ra của bạn phải là mọi số nguyên tố ≤ n(theo thứ tự tăng dần) theo sau là một dòng mới:

2
3
5

Trong trường hợp n5.


Ví dụ

> 10
2
3
5
7

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

Đầu vào được ký hiệu là >.


Ví dụ của bạn n=30bị thiếu 29 trong đầu ra.
isaacg

5
Một rắc rối với những thách thức yêu cầu sử dụng một phương pháp cụ thể là nó không rõ những sửa đổi nào người ta có thể thực hiện. Ví dụ: mô tả của bạn chỉ kiểm tra (i,j)với i<=j, nhưng kết quả không thay đổi nếu chúng tôi bỏ qua yêu cầu này. Chúng ta có thể làm như vậy để tiết kiệm byte?
xnor

Tôi không bao giờ nói rằng bạn phải kiểm tra nếu i <= j. Nó chỉ là một phần trong cách thức hoạt động của sàng. Vì vậy, có, bạn có thể để lại i <= jtrong mã của bạn. @xnor
Zach Gates

2
Chúng ta có bao nhiêu thời gian ở đây? Sàng tương đương với việc chọn tất cả các số lẻ (vì kết quả có dạng 2n+1) không phải là dạng 2(i + j + 2ij)+1- chúng ta có thể kiểm tra tính chất này trực tiếp trên các số nguyên tố tiềm năng hay mã của chúng ta phải thực hiện lần 2 cộng 1 ?
Martin Ender

1
Tôi hơi bối rối bởi những gì ntrong toàn bộ. Trong mô tả phương thức, nó nói rằng nó sẽ tạo ra tất cả các số nguyên tố lên đến 2 * n + 2. Nhưng trong mô tả đầu vào / đầu ra, nó nói rằng đầu vào là nvà đầu ra tất cả các số nguyên tố lên đến n. Vì vậy, chúng ta có nên áp dụng phương pháp để tạo ra tất cả các số nguyên tố 2 * n + 2, và sau đó thả các số lớn hơn ncho đầu ra không? Hoặc chúng ta nên tính toán ntrong mô tả phương pháp từ đầu vào n?
Reto Koradi

Câu trả lời:


7

Bình thường, 23 byte

2j@JSQmhyd-Jm+sdy*Fd^J2

Trình diễn

Thực sự chỉ cần thực hiện các thuật toán như được đưa ra.


3

Haskell, 93 90 byte

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]

Cách thức hoạt động: [i+j+2*i*j|j<-r,i<-r]là tất cả i+j+2ijnhững gì được gỡ bỏ ( \\) khỏi [1..n]. Chia tỷ lệ 2x+1và biến chúng thành một chuỗi ( show). Tham gia với NL ( unlines).


1

Scala, 115 124 122 115 114 byte

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)}

Một chức năng ẩn danh; lấy n làm đối số và in kết quả ra thiết bị xuất chuẩn.


1

JavaScript (ES7), 107 105 byte

Hiểu mảng là tuyệt vời! Nhưng tôi tự hỏi tại sao JS không có cú pháp phạm vi (ví dụ [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]}

Điều này đã được thử nghiệm thành công trong Firefox 40. Phân tích:

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
}

Giải pháp thay thế, thân thiện với ES6 (111 byte):

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)}

Đề nghị chào mừng!


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);

Và ở dạng có thể đọc được

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 byte

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);}

Đối với loại dữ liệu số lớn hơn với phạm vi rộng có thể được sử dụng. Chúng ta không cần lặp lại cho toàn bộ Nchỉ mụcN/2 là đủ.

Để hiểu đúng sau đây là phương pháp tương đương.

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>1? A[i]==0-> A[i]<1?
lirtosiast

@ThomasKwa Có bạn đúng. Cảm ơn.
CoderCroc

0

CJam, 35 byte

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

Dùng thử trực tuyến

Điều này có vẻ hơi dài so với giải pháp Pyth của isaacg, nhưng đó là ... những gì tôi có.

Giải trình:

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 byte

Nếu tôi thực hiện đúng theo mô tả ngắn nhất tôi quản lý để có được là 96 byte.

->\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)
}

Nếu tôi có thể thực hiện việc 2n + 1khởi tạo mảng, chèn trước 2và giới hạn chỉ với các giá trị nhỏ hơn hoặc bằng n; nó có thể giảm xuống còn 84 byte.

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

Nếu tôi cũng bỏ qua điều đó jđược cho là ít nhất i, tôi có thể giảm nó xuống còn 82 byte.

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

Ví dụ sử dụng:

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)


Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.