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


13

Соревнование

Внедрите сито Sundaram для поиска простых чисел ниже 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 в выводе.
Исаак

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

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 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 в качестве аргумента и выводит результат на стандартный вывод.


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

МАТЛАБ, 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.