Saringan Sundaram (untuk menemukan bilangan prima)


13

Tantangan

Terapkan saringan Sundaram untuk menemukan bilangan prima di bawah ini n. Ambil integer input n,, dan output bilangan prima di bawah ini n. Anda dapat mengasumsikan bahwa nakan selalu kurang dari atau sama dengan satu juta.


Saringan

  1. Mulai dengan daftar bilangan bulat dari 1hingga n.

  2. Hapus semua angka yang ada di formulir di i + j + 2ijmana:

    • idan jkurang dari n. jselalu lebih besar atau sama dengan i, yang lebih besar dari atau sama dengan 1.

    • i + j + 2ij kurang dari atau sama dengan n

  3. Lipat gandakan angka yang tersisa dengan 2, dan tambahkan 1.

Ini akan menghasilkan semua bilangan prima (kecuali 2, yang harus dimasukkan dalam output Anda) kurang dari 2n + 2.


Berikut ini adalah animasi dari saringan yang digunakan untuk menemukan bilangan prima di bawah ini 202.


Keluaran

Output Anda harus setiap bilangan bulat utama ≤ n(dalam urutan menaik) diikuti oleh baris baru:

2
3
5

Dimana nadalah 5.


Contohnya

> 10
2
3
5
7

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

Input dilambangkan dengan >.


Contoh Anda dengan n=3029 tidak ada dalam output.
isaacg

5
Masalah dengan tantangan yang meminta untuk menggunakan metode tertentu adalah tidak jelas modifikasi apa yang dapat dilakukan. Misalnya, deskripsi Anda hanya diperiksa (i,j)dengan i<=j, tetapi hasilnya tidak berubah jika kami mengabaikan persyaratan ini. Bisakah kita melakukannya untuk menghemat byte?
xnor

Saya tidak pernah mengatakan bahwa Anda harus memeriksa apakah i <= j. Itu hanya bagian dari cara kerja ayakan. Jadi ya, Anda dapat meninggalkan i <= jkode Anda. @xnor
Zach Gates

2
Berapa kelonggaran yang kita miliki di sini? Saringan ini setara dengan memilih semua angka ganjil (karena hasilnya berupa 2n+1) yang bukan dari bentuk 2(i + j + 2ij)+1- dapatkah kita menguji properti ini langsung pada bilangan potensial atau apakah kode kita harus melakukan kali 2 ditambah 1 pada beberapa titik ?
Martin Ender

1
Saya sedikit bingung dengan apa yang nada di semuanya. Dalam deskripsi metode, dikatakan bahwa itu akan menghasilkan semua bilangan prima hingga 2 * n + 2. Tetapi dalam uraian input / output, dikatakan bahwa inputnya adalah n, dan outputnya semuanya siap n. Jadi apakah kita harus menerapkan metode untuk menghasilkan semua bilangan prima hingga 2 * n + 2, dan kemudian drop yang lebih besar daripada nuntuk output? Atau haruskah kita menghitung ndeskripsi metode dalam dari input n?
Reto Koradi

Jawaban:


7

Pyth, 23 byte

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

Demonstrasi

Benar-benar hanya mengimplementasikan algoritma seperti yang diberikan.


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]

Cara kerjanya: [i+j+2*i*j|j<-r,i<-r]semua i+j+2ijyang dihapus ( \\) dari [1..n]. Scale to 2x+1dan mengubahnya menjadi string ( show). Bergabung dengan 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)}

Fungsi anonim; mengambil n sebagai argumen dan mencetak hasilnya ke stdout.


1

JavaScript (ES7), 107 105 byte

Pemahaman array sangat bagus! Tapi saya ingin tahu mengapa JS tidak memiliki sintaks rentang (mis. [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]}

Ini berhasil diuji di Firefox 40. Kerusakan:

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
}

Alternatif, solusi ramah 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)}

Saran diterima!


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

Dan dalam bentuk yang mudah dibaca

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

Untuk tipe data angka yang lebih besar dengan jangkauan luas dapat digunakan. Kita tidak perlu mengulangi karena seluruh Nindeks N/2sudah cukup.

Untuk memahami dengan benar mengikuti adalah metode yang setara.

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 Ya Anda benar. Terima kasih.
CoderCroc

0

CJam, 35 byte

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

Cobalah online

Ini tampaknya agak panjang relatif terhadap solusi Pyth isaacg, tapi itu ... apa yang saya miliki.

Penjelasan:

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

Jika saya benar-benar mengikuti deskripsi yang terpendek saya berhasil dapatkan adalah 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)
}

Jika saya bisa melakukan 2n + 1inisialisasi array, pre-inserting 2, dan membatasi itu hanya untuk nilai yang kurang dari atau sama dengan n; itu dapat dikurangi menjadi 84 byte.

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

Jika saya juga mengabaikan yang jseharusnya setidaknya i, saya bisa menguranginya menjadi 82 byte.

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

Contoh penggunaan:

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)

0

PHP, 126 Bytes

$r=range(1,$n=$argn/2-1);for(;++$i**2<=$n;)for($j=$i;$n>=$d=$j+$i+2*$i*$j++;)unset($r[$d-1]);foreach($r as$v)echo 1+2*$v."\n";

Versi Online


Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.