Сито Эратосфена, шаг за шагом


15

Учитывая число N , нарисуйте выровненную по левому краю N x N доску чисел, оставив 1 пустым (как пробел) (я покажу диаграммы с N = 5)

   2  3  4  5
6  7  8  9  10
11 12 13 14 15
16 17 18 19 20
21 22 23 24 25

Ваша задача - построить Сито Эратосфена, шаг за шагом. Сначала начните с 2. Это простое число, поэтому оставьте его там и замените все остальные числа, делимые на 2, соответствующим количеством пробелов.

   2  3     5
   7     9    
11    13    15
   17    19   
21    23    25

Затем перейдите к следующему номеру без печати ( 3в данном случае) и сделайте то же самое.

   2  3     5
   7          
11    13      
   17    19   
      23    25

И так далее, пока вы не дойдете до N .

Сначала необходимо распечатать всю сетку, и каждый раз, когда вы переходите к новому номеру, печатайте доску со снятыми кратными числами. Убедитесь, что вы печатаете пустую строку между ними!

Примеры

Текст в скобках ()только для справки, вам не нужно его печатать

N = 2:

  2 (complete grid)
3 4

  2 (remove multiples of 2)
3  

N = 3:

  2 3 (complete grid)
4 5 6
7 8 9

  2 3 (remove multiples of 2)
  5  
7   9

  2 3 (remove multiples of 3)
  5  
7    

Помните, это , поэтому выигрывает код с наименьшим количеством байтов.


Обычно для N × N решето вы перестанете просеивание после N .
Нил

1
Например, если N=10, 100не простое, поэтому будут удалены в какой - то момент. Должны ли все числа быть дополнены до 3 символов, потому что 100имеет 3 цифры?
mbomb007

4
Зачем вы оставили номера?
Деннис

2
Допустимы ли переводы с новой строки?
Деннис

2
Разрешены ли встроенные сетки? Вывод будет выглядеть идентично примеру в посте, но не будет строкой.
JungHwan Мин

Ответы:


7

Желе , 34 байта

Ṿ€“1“ ”ys³G
>®i©1ḍoṛ®¦
²R;1©ÇÐĿÑ€Y

Попробуйте онлайн!

Как это устроено

²R;1©ÇÐĿÑ€Y  Main link. Argument: n (integer)

²            Yield n².
 R           Range; yield [1, ..., n²].
   1©        Yield 1 and copy it to the register.
  ;          Append 1 to the range.
             This is the initial state. Let's call it S.
     ÇÐĿ     Call the second helper link until the results are no longer unique.
             This returns all unique results as an array.
        Ṅ€   Call the first helper link on each result.
          Y  Join, separating by linefeeds.

>®i©1ḍoṛ®¦   Second helper link. Argument: S (state)

>®           Compare all integers in S with the value in the register.
  i 1        Find the first index of 1 (i.e., the first number that is greater
             than the register.
   ©         Copy the index to the register. Let's call the index p.
     ḍ       Test all numbers in S for divisibility by p. This yield 1 for
             multiples of p, 0 otherwise.
      o      Logical OR; replace 0's with the corresponding values of S.
       ṛ®¦   Replace the 0 at index p with the corresponding element of S (p).
             For the purposes of the explanation, S is now the updated state.

Ṿ€“1“ ”ys³G  First helper link. Argument: A (array)

Ṿ€           Uneval each; convert all integers in A into strings.
  “1“ ”y     Replace each string "1" with the string " ".
        s³   Split into chunks of length n (command-line argument).
          G  Grid; separate row items by spaces (left-padding since the row items
             are strings), the rows themselves by linefeeds.

5

Perl, 250 243 231 202 157 байт

$n=<>;@a=0..($e=$n*$n);$a[1]=$";for$p(1..$n){next if!$a[$p];for(1..$e){$a[$_]=""if!($p~~[(1,$_)]||$_%$p);printf"%-*s",1+length$e,$a[$_];say""if!($_%$n)}say}

Проверьте текущий гольф онлайн! (не забудьте запустить как perl -M5.010 main.pl)

Каждое из двух буквальных символов новой строки сохраняет 1 байт вместо \ n.

Пример вывода (ввод 7):

   2  3  4  5  6  7  
8  9  10 11 12 13 14 
15 16 17 18 19 20 21 
22 23 24 25 26 27 28 
29 30 31 32 33 34 35 
36 37 38 39 40 41 42 
43 44 45 46 47 48 49 

   2  3     5     7  
   9     11    13    
15    17    19    21 
   23    25    27    
29    31    33    35 
   37    39    41    
43    45    47    49 

   2  3     5     7  
         11    13    
      17    19       
   23    25          
29    31          35 
   37          41    
43          47    49 

   2  3     5     7  
         11    13    
      17    19       
   23                
29    31             
   37          41    
43          47    49 

   2  3     5     7  
         11    13    
      17    19       
   23                
29    31             
   37          41    
43          47       

Я уверен, что не очень хорошо играл в гольф, поэтому, когда я вернусь домой, я еще раз посмотрю на это, чтобы увидеть, насколько я могу побриться.

Отредактируйте 1: -7 байт (изменив «print sprintf» на очевидный «printf»)

Редактировать 2: 12 байтов были сохранены, явно используя $ d в одном месте, где она была вызвана, вместо создания отдельной переменной, путем объединения некоторых объявлений и устранения одного из моих условий для nextоператора внутри первого foreachцикла, добавив пробел где-то еще , Дополнительные 29 байтов были выведены путем преобразования двух циклов for в один цикл, исключив два объявления переменных и превратив unlessоператоры в операторы if-not. Объявление, а my$e=$n*$n;затем замена трех экземпляров $ n * $ n на $ e (что позволило мне отбросить парен для одного из них), привело к получению ± 0 байт, но я все равно сохранил его.

Редактировать 3: Благодаря @Dada, еще 40 байтов были выведены из игры (объявления переменных, «foreach» становится «для», неявный $ _ в нескольких местах и ​​сокращение размера оператора printf). Дополнительный 1 байт был сброшен путем превращения if!($c%$p||$c==$p||$p==1)в if!($p~~[(1,$_)]||$_%$p). К сожалению, [] вокруг массива необходимо, потому что оператор smartmatch ~~ все еще экспериментален и, похоже, не работает должным образом с реальными массивами, но вместо этого работает с ссылками на них. Еще 4 байта были удалены путем удаления двух точек с запятой и пустого набора кавычек после последнего say.


1
Это хорошее начало, но вы можете играть в гольф намного больше. Не объявляйте переменные (поэтому не используйте my). Используйте -pфлаг, чтобы иметь Nвнутри $_вместо использования $n=<>. Напишите forвместо foreach(эта инструкция является эквивалентом). Удалите круглые скобки вокруг условия, ifкоторое находится в позиции модификатора оператора (например, if!$c%$nвместо if(!$c%$n). Для инициализации не нужно использовать круглые скобки @a:. @a=0..$eВы можете перейти к forпеременной и $_использовать вместо нее. Записать printf"%*s",1+length$e,$a[$c](документ `` sprintf` для подробностей об этом) *)
Дада

1
Используйте $"вместо " ". say""вместо print"\n"(у вас есть буквальный символ новой строки в вашем коде, но я не могу написать его в комментарии) (вы добавите, чтобы добавить -M5.010в командную строку, но это не считается в счетчике байтов). Вы, вероятно, можете использовать0..$e=$n*$n чтобы сохранить один байт при инициализации $e. Посмотрите на советы Perl гольфу , он содержит много полезных советов. Но приятно видеть нового игрока в Perl, добро пожаловать! :) (и простите мои орфографические ошибки, возможно, я слишком быстро написал свой предыдущий комментарий)
Dada

@Dada Спасибо за ваш совет! Я не очень знаком с запуском кода в командной строке (я склонен запускать его как файл), но я посмотрю, как это сделать. Что касается if!$c%$n, то! Оператор имеет приоритет над оператором%, так что технически это будет if((!$c)%$n)ложью для всего, кроме $ c = 0 (что мне не нужно). Что касается других ваших советов, я посмотрю, что я могу сделать! Большое спасибо!
Габриэль Бенами

Вам не нужно запускать его из командной строки, эти изменения будут работать, если вы также поместите их в файл. Извините за !, я не был на моем компьютере, чтобы проверить это. Вы должны быть в состоянии получить до 160 символов, я думаю.
Дада

5

PHP, 155 байт

for(;$d++<$n=$argv[1];$x&$a[$d]<1?:print"\n".chunk_split(join($a),$n*$l))for($i=$d*$x=$d>1;$n**2>=$i+=$d;)$a[$i]=str_pad($x|$i<2?"":$i,$l=strlen($n**2)+1);

@Crypto -3 байта спасибо @Titus -6 байтов спасибо

Попытайся

Впервые я использую печать в состоянии после цикла

Сломать

for(;$d++<$n=$argv[1];
$x&$a[$d]<1?:print"\n".chunk_split(join($a),$n*$l))
#after loop print the grid if $d = 1 or is prime
for($i=$d*$x=$d>1;$n**2>=$i+=$d;)
$a[$i]=str_pad($x|$i<2?"":$i,$l=strlen($n**2)+1);
#fills the array at first run and replace positions with space in the next runs 

Предыдущая версия 174 байта

for(;$d++<=$n=$argv[1];!($d<2||$a[$d]>0)?:print chunk_split(join($a),$n*$l)."\n")for($i=$d<2?1:2*$d;$i<=$m=$n**2;$i+=$d)$a[$i]=str_pad($d<2?($i<2?"":$i):" ",$l=strlen($m)+1);  

1
-3 байта, меняющие условие: !($d<2||$a[$d]>0)=>$d>1&&$a[$d]<1
Crypto

1
-1 байт, используя этот трюк, чтобы получить целую длину $l=strlen($m)+1до$l=log10($m)+2
Crypto

1
-3 байта: $i=$d*$x=$d>1вместо $i=$d<2?0:$dи $xдля двух других случаев$d>1
Тит

1
-2 байта: $n*$n>=$i+=$dвместо ($i+=$d)<=$m=$n**2и $n*$nдля другого случая$m
Тит

1
-1 байт: ведущий вместо завершающего символа новой строки
Тит

3

Groovy, 201 195 191 байт

{n->a=(1..n*n).toArray();y={a.collect{(it?"$it":"").padRight((""+n*n).size())}.collate(n).each{println it.join(" ")}};a[0]=0;y(a);(2..n).each{b->(b+1..n*n).each{if(it%b==0){a[it-1]=0}};y(a)}}

Это абсолютный кластер ... Выравнивание по левому краю убило мой счетчик байтов. Но эй, это работает. Вот вывод для 4:

   2  3  4 
5  6  7  8 
9  10 11 12
13 14 15 16

   2  3    
5     7    
9     11   
13    15   

   2  3    
5     7    
      11   
13         

   2  3    
5     7    
      11   
13         

Ungolfed:

{
    n->
    a = (1..n*n).toArray();                           // Create initial array.
    y = {                                             // Createa  printing utility closure.
        a.collect {                                   // Create an array collection of...
            (it ? "$it":"").padRight((""+n*n).size()) // If 0, store "", else store number & right pad it.
        }.collate(n).each{                            // Collate by n (break into nxn grid).
            println it.join(" ")                      // print each separated by spaces.
        }
    };
    a[0]=0;                                           // Remove first element.
    y(a);                                             // Print initial status.
    (2..n).each{                                      // From 2 to n...
        b->
        (b+1..n*n).each{                              // From current number + 1 to end of grid...
            if(it%b==0){                              // If current grid position is divisible...
                a[it-1]=0                             // Replace with 0.
            }
        }
        y(a)                                          // Print it.
    }        
}


2
Это не выглядит по левому краю для меня.
Деннис

Исправлено ... У меня просто не было возможности редактировать его до сих пор ...
Волшебная Урна Осьминога

@Dennis Я действительно видел ваши комментарии и думал, что он изменил их, основываясь на вашем комментарии.
Волшебная Урна Осьминога

3

Perl 115 114 113 112 байт

Включает +1 для -a

Запустить с номером ввода на STDIN:

perl -M5.010 sieving.pl <<< 7

sieving.pl:

#!/usr/bin/perl -a
$_*=$_;$a.="$_"x$|++|$"x"@+".($_%"@F"?$":$/)for/\d+/..$_;*_=a;s^^$$_++||say;$.++;s//$&%$.|$&==$.?$&:$&&$_/eg^eg

Нужен достаточно свежий Perl, что -aподразумевает -n. Если ваш Perl слишком стар, добавьте-n опцию.

Печатает завершающий символ новой строки, который разрешен.


2

Python 2, 199 202 201 байт

+3 байта (я не останавливался рано)
-1 байт благодаря @Oliver (пропустил пробел)

def f(n,p={()}):
 m=n*n;g=['']+[[i,''][any(i>n and i%n<1for n in p)]for i in range(2,m+1)];x=min(set(g)-p);i=0
 while i<m+n:print' '.join('%%%ds'%-len(`m`)%v for v in g[i:i+n]);i+=n
 if x<=n:f(n,p|{x})

repl.it


1
Вы можете удалить пробел между 1иfor
Оливер Ни

2

JavaScript (ES6), 190 189 байт

Непосредственно печатает на консоль.

f=(w,k=1,a=[...Array(w*w)].map((_,n)=>n&&n+1))=>k++<=w&&(k==2|a[k-2]&&console.log(a.map((n,x)=>`${n||''}    `.slice(0,`_${w*w}`.length)+(++x%w?'':`
`)).join``),f(w,k,a.map(n=>n==k|n%k&&n)))

демонстрация


2

Пакет, 464 байта

@echo off
set/an=%1,s=n*n,t=s,c=1
set p=
:l
set/ac+=1,t/=10
set p= %p%
if %t% gtr 0 goto l
for /l %%i in (1,1,%1)do call:i %%i
exit/b
:i
set l=
set/af=0
call:f %1 %1
if %f%==0 for /l %%j in (1,1,%s%)do call:j %1 %%j
exit/b
:j
set/am=%2,f=!(m-1),g=%2%%n
call:f %1 %2
if %f% gtr 0 set m=
set m=%m% %p%
call set l=%%l%%%%m:~0,%c%%%
if %g%==0 echo(%l%&set l=
if %2==%s% echo(
exit/b
:f
for /l %%l in (2,1,%1)do if %%l neq %2 set/af+=!(%2%%%%l)

Это было несколько трудоемко. Объяснение: Начинается с возведения в квадрат, nчтобы можно было вычислить желаемую ширину столбца cи соответствующее количество отступов p, используя цикл :l. Затем внешний цикл от 1до nзапускается один раз для каждой сетки, вызывая подпрограмму :i. Сначала проверяется значение, чтобы увидеть, является ли оно 1 или простым; если нет, то эта сетка пропускается. Внутренний цикл от 1до n*nзатем обрабатывает строки и столбцы сетки, вызывая подпрограмму:j . Каждое значение проверяется, чтобы увидеть, является ли оно одним из простых чисел, найденных до сих пор, или если ни одно из найденных простых чисел не разделило его. Если это так, то значение объединяется с выходным буфером, который затем дополняется до желаемой ширины столбца. Буфер распечатывается и очищается каждыйnлинии, и дополнительная пустая строка добавляется в конце сетки. :fЭтикетке обозначает фактор проверки подпрограммы; f (x, y) добавляет 1 к fкаждому целому числу от 2 до xделения y, исключая yсебя.


2

R 195 191 185 204 байта

f=function(N){a=b=1:N^2;i=1;a[1]="";S=sprintf;while(i<=N){for(j in b)cat(a[j]<-S(S("%%-%is",nchar(N^2)),if(j==i|j%%i|i<2)a[j]else ""),if(j%%N)"" else"\n");cat("\n");i=(grep("\\d",a[-(1:i)],v=T)[1]:1)[1]}}

Спасибо @Billywob за сохранение 6 дополнительных байтов!

С отступом, с новыми строками:

f=function(N){
   a=b=1:N^2 #Initial array
   i=1 #Turn counter
   a[1]="" #1 never shown
   S=sprintf
   while(i<=N){
      for(j in b)
         cat(a[j]<-S(S("%%-%is",nchar(N^2)),if(j==i|j%%i|i<2)a[j]else ""),
             if(j%%N)"" else"\n") #Newline at end of row
      cat("\n") #Newline between turns
      i=(grep("\\d",a[-(1:i)],v=T)[1]:1)[1] #Select next prime as next i
   }
}

Использование:

> f(2)
  2 
3 4 

  2 
3   

> f(3)
  2 3 
4 5 6 
7 8 9 

  2 3 
  5   
7   9 

  2 3 
  5   
7     

> f(9)
   2  3  4  5  6  7  8  9  
10 11 12 13 14 15 16 17 18 
19 20 21 22 23 24 25 26 27 
28 29 30 31 32 33 34 35 36 
37 38 39 40 41 42 43 44 45 
46 47 48 49 50 51 52 53 54 
55 56 57 58 59 60 61 62 63 
64 65 66 67 68 69 70 71 72 
73 74 75 76 77 78 79 80 81 

   2  3     5     7     9  
   11    13    15    17    
19    21    23    25    27 
   29    31    33    35    
37    39    41    43    45 
   47    49    51    53    
55    57    59    61    63 
   65    67    69    71    
73    75    77    79    81 

   2  3     5     7        
   11    13          17    
19          23    25       
   29    31          35    
37          41    43       
   47    49          53    
55          59    61       
   65    67          71    
73          77    79       

   2  3     5     7        
   11    13          17    
19          23             
   29    31                
37          41    43       
   47    49          53    
            59    61       
         67          71    
73          77    79       

   2  3     5     7        
   11    13          17    
19          23             
   29    31                
37          41    43       
   47                53    
            59    61       
         67          71    
73                79       

> f(12)
    2   3   4   5   6   7   8   9   10  11  12  
13  14  15  16  17  18  19  20  21  22  23  24  
25  26  27  28  29  30  31  32  33  34  35  36  
37  38  39  40  41  42  43  44  45  46  47  48  
49  50  51  52  53  54  55  56  57  58  59  60  
61  62  63  64  65  66  67  68  69  70  71  72  
73  74  75  76  77  78  79  80  81  82  83  84  
85  86  87  88  89  90  91  92  93  94  95  96  
97  98  99  100 101 102 103 104 105 106 107 108 
109 110 111 112 113 114 115 116 117 118 119 120 
121 122 123 124 125 126 127 128 129 130 131 132 
133 134 135 136 137 138 139 140 141 142 143 144 

    2   3       5       7       9       11      
13      15      17      19      21      23      
25      27      29      31      33      35      
37      39      41      43      45      47      
49      51      53      55      57      59      
61      63      65      67      69      71      
73      75      77      79      81      83      
85      87      89      91      93      95      
97      99      101     103     105     107     
109     111     113     115     117     119     
121     123     125     127     129     131     
133     135     137     139     141     143     

    2   3       5       7               11      
13              17      19              23      
25              29      31              35      
37              41      43              47      
49              53      55              59      
61              65      67              71      
73              77      79              83      
85              89      91              95      
97              101     103             107     
109             113     115             119     
121             125     127             131     
133             137     139             143     

    2   3       5       7               11      
13              17      19              23      
                29      31                      
37              41      43              47      
49              53                      59      
61                      67              71      
73              77      79              83      
                89      91                      
97              101     103             107     
109             113                     119     
121                     127             131     
133             137     139             143     

    2   3       5       7               11      
13              17      19              23      
                29      31                      
37              41      43              47      
                53                      59      
61                      67              71      
73                      79              83      
                89                              
97              101     103             107     
109             113                             
121                     127             131     
                137     139             143     

    2   3       5       7               11      
13              17      19              23      
                29      31                      
37              41      43              47      
                53                      59      
61                      67              71      
73                      79              83      
                89                              
97              101     103             107     
109             113                             
                        127             131     
                137     139                     

Хорошо, я никогда не смогу понять, как правильно печатать матрицы, чтобы они соответствовали требованиям игры в гольф, не говоря уже о том, чтобы оправдать их. Вы можете сохранить несколько байтов, хотя. Оператор возведения в степень ^- единственный, который не векторизован при генерации последовательностей, используя :которые вы можете использовать, например, 1:2^2чтобы получить 1 2 3 4. Во-вторых, если вы определите, a=b=1:n^2вы можете позже использовать for(j in b)вместо определения другого вектора для зацикливания. Должен сэкономить вам пару байтов.
Billywob

В самом деле! Благодарность! Никогда не могу вспомнить точный порядок приоритета оператора ...
plannapus

Почему между числами в f (2) и f (3) существуют три пробела и два в f (9)? Это всегда должен быть один пробел.
Оливер Ни

Ах да, я установил 3 символа как норму, потому что я тестировал с N = 10, позвольте мне исправить это.
plannapus

1

J 125 байтов

p=:3 :'}."1,./('' '',.>)"1|:(-%:#y)]\((a:"_)`(<@":)@.*)"+y'
3 :'p@>~.|.(]*](*@|~+.=)({[:I.*){])&.>/\.(<"+i.-y),<]`>:@.*i.*:y'

Это явно, не молчаливый J, но должен быть способ молчаливо сыграть в гольф.

использование

   p =: 3 :'}."1,./('' '',.>)"1|:(-%:#y)]\((a:"_)`(<@":)@.*)"+y'
   f =: 3 :'p@>~.|.(]*](*@|~+.=)({[:I.*){])&.>/\.(<"+i.-y),<]`>:@.*i.*:y'
   f 2
  2
3 4

  2
3  
   f 3
  2 3
4 5 6
7 8 9

  2 3
  5  
7   9

  2 3
  5  
7    
   f 4
   2  3  4 
5  6  7  8 
9  10 11 12
13 14 15 16

   2  3    
5     7    
9     11   
13    15   

   2  3    
5     7    
      11   
13         
   f 5
   2  3  4  5 
6  7  8  9  10
11 12 13 14 15
16 17 18 19 20
21 22 23 24 25

   2  3     5 
   7     9    
11    13    15
   17    19   
21    23    25

   2  3     5 
   7          
11    13      
   17    19   
      23    25

   2  3     5 
   7          
11    13      
   17    19   
      23      

1

Mathematica, 133 байта

Grid[#,Alignment->Left]~Print~"
"&/@FoldList[#/.(##|1&@@(2~r~i#2)->Null)&,(r=Range)[i=#^2]~Partition~#/.Rule[1,],Prime@r@PrimePi@#];&

1

PHP, 155 150 147 145 142 140 байт

for(;$k++<$n=$argv[1];)if($k<2||$a[$k]){for($i=0;$i++<$n*$n;)echo$a[$i]=$k>1?$i>$k&$i%$k<1?"":$a[$i]:($i<2?"":$i),"\t\n"[$i%$n<1];echo"\n";}

сломать

for(;$k++<$n=$argv[1];)
    if($k<2||$a[$k])    // if first iteration or number unprinted ...
{
    for($i=0;$i++<$n*$n;)
        echo
            $a[$i]=$k>1
                ?$i>$k&$i%$k<1
                    ?""         // sieve
                    :$a[$i]     // or copy value
                :($i<2?"":$i)   // first iteration: init grid
            ,
            // append tab, linebreak every $n columns
            "\t\n"[$i%$n<1]
        ;
    // blank line after each iteration
    echo"\n";
}

1
$a[$i]="";вместо того, unset($a[$i]);чтобы сохранить 4 байта
Йорг Хюльсерманн

$i%$k<1 вместо того !($i%$k) сохранения одного байта
Йорг Хюльсерманн
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.