Sundaram Eleği (asal sayıları bulmak için)


13

Meydan okuma

Uygulamak Sundaram elek altında asal sayılar bulmak için n. Bir girdi tamsayı alın nve aşağıdaki asal sayıları çıktılayın n. Bunun nher zaman bir milyondan az veya ona eşit olacağını varsayabilirsiniz .


Elek

  1. Arasındaki tam sayıların bir listeyle başlayın 1için n.

  2. Aşağıdaki formdaki tüm sayıları kaldırın i + j + 2ij:

    • ive jdaha küçüktür n. jher zaman büyük veya eşittir i, bu büyük veya eşittir 1.

    • i + j + 2ij küçük veya eşit n

  3. Kalan sayıları ile çarpın 2ve ekleyin 1.

Bu, tüm asal sayıları ( 2çıktınıza dahil edilmeleri dışında ) daha az verir 2n + 2.


Aşağıda, asalları bulmak için kullanılan eleğin bir animasyonu 202.


Çıktı

Çıktınız her asal tam sayı ≤ n(artan sırada) ve ardından yeni satır olmalıdır:

2
3
5

Nerede nolduğunu 5.


Örnekler

> 10
2
3
5
7

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

Girişler ile gösterilir >.


İle örneğiniz n=30çıktıda 29 eksik.
isaacg

5
Belirli bir yöntemi kullanmayı isteyen zorluklarla ilgili bir sorun, kişinin hangi değişiklikleri yapabileceğinin açık olmamasıdır. Örneğin, açıklamanız yalnızca (i,j)ile kontrol eder i<=j, ancak bu gereksinimi göz ardı edersek sonuç değişmez. Bayt tasarrufu için bunu yapabilir miyiz?
xnor

Kontrol etmen gerektiğini söylemedim i <= j. Elek nasıl çalışıyor sadece bir parçası. Yani evet, i <= jkodunuzda bırakabilirsiniz . @xnor
Zach Gates

2
Burada ne kadar boşluğumuz var? (Sonuçlar formun çünkü elek tüm tek sayılar seçerek eşdeğerdir 2n+1formun değildir) 2(i + j + 2ij)+1potansiyel asal doğrudan bu özelliği test edebilirsiniz veya kod yapar - sahip bir noktada kez 2 artı 1 yapmak ?
Martin Ender

1
Her şeyin niçinde olanla biraz kafam karıştı . Yöntem açıklamasında, tüm primerleri üreteceğini söylüyor 2 * n + 2. Ancak, giriş / çıkış açıklamasında, girişin olduğunu nve çıkışın tümünün hazır olduğunu söyler n. Öyleyse, tüm primerleri üretmek için yöntemi uygulayıp 2 * n + 2sonra nçıktıdan daha büyük olanları düşürmemiz gerekiyor mu? Veya ngirişteki yöntem açıklamasında hesaplamalı mıyız n?
Reto Koradi

Yanıtlar:


7

Pyth, 23 bayt

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

gösteri

Gerçekten sadece verilen algoritmayı uygular.


3

Haskell, 93 90 bayt

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]

Nasıl çalışır: [i+j+2*i*j|j<-r,i<-r]hepsi i+j+2ijkaldırılır ( \\) [1..n]. Ölçekleyin 2x+1ve bunları bir dizeye ( show) dönüştürün. NL ( unlines) ile katılın .


1

Scala, 115 124 122 115 114 bayt

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

Anonim bir işlev; n'yi bağımsız değişken olarak alır ve sonucu stdout'a yazdırır.


1

JavaScript (ES7), 107 105 bayt

Dizi anlayışları harika! Ama neden JS'nin aralık sözdizimi olmadığını merak ediyorum (örneğin [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]}

Bu, Firefox 40'ta başarıyla test edildi.

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, ES6 dostu çözüm (111 bayt):

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

Öneriler hoş geldiniz!


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

Ve okunabilir bir biçimde

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 bayt

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

Daha büyük sayı için geniş aralıklı veri tipi kullanılabilir. Tüm Ndizinler için yinelemeye gerek yoktur N/2.

Düzgün anlamak için eşdeğer bir yöntemdir.

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 Evet haklısın. Teşekkürler.
CoderCroc

0

CJam, 35 bayt

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

Çevrimiçi deneyin

Bu, isaacg'ın Pyth çözümüne göre biraz uzun görünüyor, ama ... sahip olduğum şey.

Açıklama:

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 bayt

Açıklamayı kesinlikle takip edersem, en kısa sürede 96 bayt elde ettim.

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

Ben 2n + 1dizi başlatma, ön ekleme 2ve bunu sadece daha küçük veya eşit değerlerle sınırlama yapabilirdi n; 84 bayta düşürülebilir.

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

jEn azından bunun olması gerektiğini göz ardı iedersem, 82 bayta düşürebilirim.

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

Örnek kullanım:

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)


Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.