スンダラムのふるい(素数を見つけるため)


13

チャレンジ

以下の素数を見つけるためにスンダラムふるいを実装ますn。入力整数を受け取り、n以下の素数を出力しますn。これnは常に100万以下であると想定できます。


ふるい

  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

どこにnあり5ますか。


> 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

私はあなたが 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か?
レトコラディ

回答:



3

ハスケル、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を取り、結果を標準出力に出力します。


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
リルトシアスト

@ThomasKwaはい、あなたは正しいです。ありがとう。
-CoderCroc

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)


弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.