Peneira de Eratóstenes, passo a passo

15

Dado um número N , desenhar uma alinhada à esquerda de N x N placa de números, deixando um espaço em branco (como um espaço) (I mostram diagramas com 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

Seu trabalho é construir a Peneira de Eratóstenes, passo a passo. Primeiro, comece com 2. É primo, então deixe lá e substitua todos os outros números divisíveis por 2 pelo número adequado de espaços.

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

Em seguida, vá para o próximo número não impresso ( 3neste caso) e faça o mesmo.

   2  3     5
   7          
11    13      
   17    19   
      23    25

E assim por diante, até chegar N .

Você precisa primeiro imprimir a grade completa e, sempre que acessar um novo número, imprima o quadro com os múltiplos removidos. Certifique-se de imprimir uma linha em branco no meio!

Exemplos

O texto entre parênteses ()é apenas para referência, você não precisa imprimi-lo

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    

Lembre-se de que isso é , portanto o código com o menor número de bytes vence.

Oliver Ni
fonte
Normalmente, para uma N × N peneira você parar de peneiramento após N .
Neil
1
Por exemplo, se N=10, 100não for primo, será removido em algum momento. Todos os números devem ser preenchidos com 3 caracteres, pois 100possuem 3 dígitos?
mbomb007
4
Por que você deixou números alinhados?
Dennis
2
As novas linhas finais são aceitáveis?
Dennis
2
Grades embutidas são permitidas? A saída parecerá idêntica ao exemplo da postagem, mas não será uma sequência.
JungHwan Min 20/10/19

Respostas:

7

Geléia , 34 bytes

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

Experimente online!

Como funciona

²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.
Dennis
fonte
5

Perl, 250 243 231 202 157 bytes

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

Teste o golfe atual online! (certifique-se de executar como perl -M5.010 main.pl)

As duas novas linhas literais economizam 1 byte no lugar de \ n.

Saída de amostra (entrada de 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       

Tenho certeza de que não joguei muito bem, então, quando chegar em casa, darei outra olhada para ver o quanto posso me barbear.

Edite 1: -7 bytes (alterando "print sprintf" para o óbvio "printf")

Edit 2: Salva 12 bytes usando $ d explicitamente no local em que foi chamado, em vez de criar uma variável separada, combinando algumas declarações e eliminando uma das minhas condições para a nextinstrução dentro do primeiro foreachloop, adicionando um espaço em outro lugar . Outros 29 bytes foram extraídos, refazendo dois loops em um único loop, eliminando duas declarações de variáveis ​​e transformando unlessinstruções em instruções if-not. Declarar my$e=$n*$n;e substituir as três instâncias de $ n * $ n por $ e (permitindo que eu solte um paren para uma delas) acabou produzindo ± 0 bytes, mas eu a mantive mesmo assim.

Edit 3: Graças a @Dada, outros 40 bytes foram eliminados (declarações variáveis, 'foreach' se tornando 'for', $ _ implícito em vários locais e diminuindo o tamanho da instrução printf). Um byte adicional foi raspado ao se transformar if!($c%$p||$c==$p||$p==1)em if!($p~~[(1,$_)]||$_%$p). Infelizmente, o [] ao redor da matriz é necessário, porque o operador smartmatch ainda é experimental e parece não funcionar corretamente em matrizes reais, mas sim em referências a elas. Mais 4 bytes foram removidos removendo dois pontos e vírgulas e um conjunto de aspas vazio após o último say.

Gabriel Benamy
fonte
1
É um bom começo, mas você pode jogar muito mais. Não declare variáveis ​​(portanto, não use my). Use a -pbandeira para ter Ndentro em $_vez de usar $n=<>. Escreva em forvez de foreach(esta instrução é equivalente). Soltar o parêntese em torno da condição do ifque estão em posição de modificador de declaração (por exemplo if!$c%$n, em vez de if(!$c%$n)Não parêntese necessário para inicializar. @a: @a=0..$e. Você pode deixar cair a forvariável e $_sim ser utilizado em vez de gravação. printf"%*s",1+length$e,$a[$c](O `` doc sprintf` para obter detalhes sobre que *)
Dada
1
Use em $"vez de " ". say""em vez de print"\n"(você tem uma nova linha literal no seu código, mas não posso escrevê-la no comentário) (você adicionará à -M5.010linha de comando, mas isso não conta na contagem de bytes). Você provavelmente pode usar 0..$e=$n*$npara salvar um byte na inicialização de $e. Dê uma olhada nas dicas de golfe perl , que contém muitas dicas úteis. Mas é bom ver um novo jogador de golfe perl, bem-vindo! :) (e perdoe os meus erros de ortografia, eu posso ter escrever o meu comentário anterior muito rápido)
Dada
@ Dadá Obrigado pelo seu conselho! Não estou muito familiarizado com a execução de código na linha de comando (eu costumo executá-lo como um arquivo), mas analisarei o processo dessa maneira. Quanto a if!$c%$n, o! O operador tem precedência sobre o operador%, portanto, tecnicamente, isso seria if((!$c)%$n)falso para algo diferente de $ c = 0 (o que eu não quero). Quanto às suas outras dicas, verei o que posso fazer! Muito obrigado!
Gabriel Benamy
Você não precisa executá-lo na linha de comando; essas modificações funcionarão se você as colocar dentro de um arquivo também. Desculpe !, eu não estava no meu computador para verificá-lo. Você deve ter 160 caracteres, eu acho.
Dada
5

PHP, 155 bytes

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 Bytes Obrigado @Titus -6 Bytes Obrigado

Tente

Primeira vez que uso a impressão em uma condição de loop posterior

Demolir

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 

Versão anterior 174 bytes

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);  
Jörg Hülsermann
fonte
1
-3 bytes alterando a condição: !($d<2||$a[$d]>0)=>$d>1&&$a[$d]<1
Crypto
1
-1 de byte, usando este truque para obter comprimento inteiro $l=strlen($m)+1para$l=log10($m)+2
Cripto
1
-3 bytes: em $i=$d*$x=$d>1vez de $i=$d<2?0:$de $xpara as outras duas ocorrências de$d>1
Titus
1
-2 bytes: em $n*$n>=$i+=$dvez de ($i+=$d)<=$m=$n**2e $n*$npara a outra ocorrência de$m
Titus
1
-1 byte: líder em vez de linha nova à direita
Titus
3

Groovy, 201 195 191 Bytes

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

Este é um cluster absoluto ... O alinhamento à esquerda matou minha contagem de bytes. Mas ei, isso funciona. Aqui está a saída para 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.
    }        
}

O que outras pessoas estão dizendo

Urna de polvo mágico
fonte
2
Isso não parece alinhado à esquerda para mim.
Dennis
Fixo ... Eu só não tive a chance de editar até agora ...
Magia Octopus Urna
@Dennis Na verdade, vi seus comentários e pensei que ele havia mudado com base no seu comentário.
Magic Octopus Urn
3

Perl, 115 114 113 112 bytes

Inclui +1 para -a

Execute com o número de entrada no 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

Precisa de um perl recente o suficiente para que isso -aimplique -n. Se o seu perl é muito antigo, adicione uma -nopção.

Imprime uma nova linha à direita que é permitida.

Ton Hospel
fonte
2

Python 2, 199 202 201 bytes

+3 bytes (eu não estava parando cedo)
-1 byte graças a @Oliver (perdeu um espaço)

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

Jonathan Allan
fonte
1
Você pode remover um espaço entre 1efor
Oliver Ni
2

JavaScript (ES6), 190 189 bytes

Imprime diretamente no console.

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

Demo

Arnauld
fonte
2

Lote, 464 bytes

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

Isso foi um pouco trabalhoso. Explicação: Inicia ao quadrado npara calcular a largura da coluna desejada ce a quantidade apropriada de preenchimento p, usando o loop :l. O loop externo de 1até nentão é executado uma vez para cada grade, chamando a sub-rotina :i. Primeiro, o valor é verificado para ver se é 1 ou prime; caso contrário, essa grade é ignorada. O loop interno de 1para n*nmanipula as linhas e colunas da grade, chamando a sub-rotina:j. Cada valor é verificado para ver se é um dos números primos encontrados até agora ou se nenhum dos números primos encontrados até agora o divide. Nesse caso, o valor é concatenado para o buffer de saída, que é preenchido com a largura da coluna desejada. O buffer é impresso e limpo a cada nlinha, e uma linha em branco extra é adicionada ao final da grade. O:flabel indica a sub-rotina de verificação de fatores; f (x, y) adiciona 1 a fcada número inteiro entre 2 e xque se divide y, excluindo a ysi próprio.

Neil
fonte
2

R, 195 191 185 204 bytes

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

Graças a @Billywob por 6 bytes extras salvos!

Recuado, com novas linhas:

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

Uso:

> 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                     
plannapus
fonte
Bom, eu nunca consigo descobrir como imprimir matrizes corretamente para atender aos requisitos de codegolfing, não importando em justificá-las. Você pode salvar alguns bytes embora. O operador de exponenciação ^é o único que não é vetorizado ao gerar seqüências usando, o :que significa que você pode usar, por exemplo, 1:2^2para obter 1 2 3 4. Em segundo lugar, se você definir, a=b=1:n^2poderá usar mais tarde, em for(j in b)vez de definir outro vetor para repetir. Você deve economizar alguns bytes.
Billywob #
De fato! Obrigado! Nunca pode lembrar a ordem exata de precedência do operador ...
plannapus
Por que existem três espaços entre os números em f (2) ef (3) e dois espaços em f (9)? Deve sempre ser um espaço.
Oliver Ni
Ah, certo, eu configurei 3 caracteres como a norma, porque eu estava testando com N = 10, deixe-me corrigir isso.
plannapus
1

J, 125 bytes

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

Isso é explícito, não J tácito, mas deve haver uma maneira de jogar tacitamente.

Uso

   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      
milhas
fonte
1

Mathematica, 133 bytes

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

PHP, 155 150 147 145 142 140 bytes

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

demolir

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";
}
Titus
fonte
1
$a[$i]="";em vez de unset($a[$i]);salvar 4 bytes
Jörg Hülsermann 22/10
$i%$k<1em vez de !($i%$k)salvar um byte
Jörg Hülsermann 22/10