Сито Сундараму (для пошуку простих чисел)


13

Змагання

Реалізувати сито Сундара для знаходження простих чисел нижче n. Візьміть ціле число введення nта виведіть прості числа нижче n. Можна припустити, що nзавжди буде менше або дорівнює одному мільйону.


Решето

  1. Почніть зі списку цілих чисел від 1до n.

  2. Видаліть усі цифри у формі, i + j + 2ijде:

    • iі jменше n. jзавжди більше або дорівнює 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
Zach Gates

2
Скільки свободи у нас тут? Сито еквівалентно вибору всіх непарних чисел (оскільки результати мають форму 2n+1), які не є формою 2(i + j + 2ij)+1- чи можемо ми перевірити цю властивість безпосередньо на потенційних праймерах чи чи повинен наш код робити час 2 плюс 1 в якийсь момент ?
Мартін Ендер

1
Я трохи збентежений тим, що nє в цілому. В описі методу сказано, що він генерує всі праймери до 2 * n + 2. Але в описі вводу / виводу йдеться про те, що вхід є n, а вихід - всі праймери до n. Тож ми повинні застосувати метод, щоб генерувати всі праймери до 2 * n + 2, а потім відкинути ті, які є більшими, ніж nдля виведення? Або ми повинні обчислити nопис методу з вхідних даних n?
Ретро Коради

Відповіді:



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, 115 124 122 115 115 114 байт

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

@ThomasKwa Так, ти маєш рацію. Спасибі.
CoderCroc

0

CJam, 35 байт

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

Спробуйте в Інтернеті

Це здається дещо тривалим щодо рішення Pyth Isaacg, але це ... те, що я маю.

Пояснення:

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)


Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.