Setaccio di Eratostene, passo dopo passo


15

Dato un numero N , disegna una tavola di numeri N x N allineata a sinistra , lasciando 1 vuoto (come spazio) (mostrerò i diagrammi con 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

Il tuo compito è costruire il setaccio di Eratostene, passo dopo passo. Innanzitutto, inizia con 2. È primo, quindi lascialo lì e sostituisci tutti gli altri numeri divisibili per 2 con il numero corretto di spazi.

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

Quindi, passare al numero non stampato successivo ( 3in questo caso) e fare lo stesso.

   2  3     5
   7          
11    13      
   17    19   
      23    25

E così via, fino ad arrivare N .

Devi prima stampare la griglia completa e ogni volta che vai a un nuovo numero, stampa la scheda con i multipli rimossi. Assicurati di stampare una linea vuota in mezzo!

Esempi

Il testo tra parentesi ()è solo per riferimento, non è necessario stamparlo

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    

Ricorda, questo è , quindi vince il codice con il minor numero di byte.


Normalmente per un N × N setaccio si smette di setacciatura dopo N .
Neil,

1
Ad esempio, se N=10, 100non è primo, quindi verrà rimosso ad un certo punto. Tutti i numeri devono essere riempiti con 3 caratteri perché 100ha 3 cifre?
mbomb007,

4
Perché dovresti lasciare i numeri allineati?
Dennis,

2
Le newline finali sono accettabili?
Dennis,

2
Sono consentite le griglie integrate? L'output apparirà identico all'esempio nel post, ma non sarà una stringa.
JungHwan Min

Risposte:


7

Gelatina , 34 byte

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

Provalo online!

Come funziona

²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 byte

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

Prova l'attuale golf online! (assicurati di eseguire come perl -M5.010 main.pl)

Le due nuove righe letterali salvano ognuna 1 byte al posto di \ n.

Esempio di output (input di 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       

Sono sicuro di non averlo giocato molto bene, quindi quando torno a casa lo guarderò per vedere quanto posso radere.

Modifica 1: -7 byte (cambiando "print sprintf" nell'ovvio "printf")

Modifica 2: salvato 12 byte usando $ d esplicitamente nell'unica posizione in cui è stato chiamato invece di creare una variabile separata, combinando alcune dichiarazioni ed eliminando una delle mie condizioni per l' nextistruzione all'interno del primo foreachciclo aggiungendo uno spazio altrove . Altri 29 byte sono stati eliminati rielaborando due per i loop in un singolo loop, eliminando due dichiarazioni variabili e trasformando le unlessdichiarazioni in istruzioni if-no. Dichiarare my$e=$n*$n;quindi la sostituzione delle tre istanze di $ n * $ n con $ e (permettendomi di rilasciare una parentesi per una di esse) si è rivelato produrre ± 0 byte, ma l'ho tenuto comunque.

Modifica 3: Grazie a @Dada, sono stati eliminati altri 40 byte (dichiarazioni variabili, 'foreach' diventando 'for', $ _ implicito in diverse posizioni e riduzione della dimensione dell'istruzione printf). Un ulteriore 1 byte è stato eliminato trasformandolo if!($c%$p||$c==$p||$p==1)in if!($p~~[(1,$_)]||$_%$p). Sfortunatamente, [] attorno all'array è necessario, perché l'operatore smartmatch ~~ è ancora sperimentale e non sembra funzionare correttamente sugli array reali, ma funziona invece sui riferimenti ad essi. Altri 4 byte sono stati rimossi rimuovendo due punti e virgola e un set vuoto di virgolette dopo l'ultimo say.


1
È un buon inizio, ma puoi giocare a golf molto di più. Non dichiarare le variabili (quindi non usare my). Usa -pflag per avere Ndentro $_invece di usare $n=<>. Scrivi forinvece di foreach(questa istruzione è equivalente). Rilascia la parentesi attorno alla condizione della ifposizione del modificatore dell'istruzione (ad esempio if!$c%$ninvece di if(!$c%$n). Non è necessaria alcuna parentesi per inizializzare @a:. @a=0..$ePuoi passare afor passare variabile e $_usare invece. Scrivi printf"%*s",1+length$e,$a[$c](il documento `` sprintf` per i dettagli a riguardo) *)
Dada,

1
Usa $"invece di " ". say""invece di print"\n"(hai una nuova riga nel tuo codice ma non posso scriverla nei commenti) (aggiungerai per aggiungere -M5.010alla riga di comando, ma questo non conta nel conteggio dei byte). Probabilmente puoi usare 0..$e=$n*$nper salvare un byte all'inizializzazione di $e. Dai un'occhiata ai suggerimenti per il golf Perl , contiene molti consigli utili. Ma è bello vedere un nuovo giocatore di golf Perl, benvenuto! :) (e perdona i miei errori di ortografia, potrei aver scritto il mio commento precedente troppo in fretta)
Dada,

@Dada Grazie per il tuo consiglio! Non ho molta familiarità con l'esecuzione del codice sulla riga di comando (tendo a eseguirlo come file) ma darò un'occhiata a farlo in questo modo. Per quanto riguarda if!$c%$nil! L'operatore ha la precedenza sull'operatore%, quindi tecnicamente questo sarebbe il risultato if((!$c)%$n)falso per qualsiasi cosa diversa da $ c = 0 (che non voglio). Per quanto riguarda i tuoi altri consigli, vedrò cosa posso fare! Grazie mille!
Gabriel Benamy,

Non è necessario eseguirlo dalla riga di comando, quelle modifiche funzioneranno se le inserisci anche in un file. !Ci scusiamo per , non ero sul mio computer per controllarlo. Dovresti riuscire a ridurre a 160 caratteri, credo.
Dada,

5

PHP, 155 byte

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 byte Grazie @Titus -6 byte Grazie

Provalo

La prima volta che utilizzo la stampa in condizioni di ciclo dopo

Abbattersi

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 

Versione precedente 174 byte

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 byte modificando la condizione: !($d<2||$a[$d]>0)=>$d>1&&$a[$d]<1
Crypto

1
-1 byte usando questo trucco per ottenere la lunghezza intera $l=strlen($m)+1a$l=log10($m)+2
Crypto

1
-3 byte: $i=$d*$x=$d>1invece di $i=$d<2?0:$de $xper le altre due occorrenze di$d>1
Tito

1
-2 byte: $n*$n>=$i+=$dinvece di ($i+=$d)<=$m=$n**2e $n*$nper l'altra occorrenza di$m
Tito

1
-1 byte: in vantaggio anziché trascinare la nuova riga
Tito

3

Groovy, 201 195 191 byte

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

Questo è un cluster assoluto ... L'allineamento a sinistra ha ucciso il mio conteggio dei byte. Ma hey, funziona. Ecco l'output per 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
Questo non mi sembra allineato a sinistra.
Dennis,

Risolto ... Non ho avuto la possibilità di modificarlo fino ad ora ...
Magic Octopus Urn

@Dennis In realtà ho visto i tuoi commenti e ho pensato che lo avesse cambiato in base al tuo commento.
Magic Octopus Urn,

3

Perl, 115 114 113 112 byte

Include +1 per -a

Esegui con il numero di input su 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

Ha bisogno di un perl abbastanza recente e ciò -aimplica -n. Se il tuo perl è troppo vecchio, aggiungi -nun'opzione.

Stampa una nuova riga finale consentita.


2

Python 2, 199202 201 byte

+3 byte (non mi sono fermato in anticipo)
-1 byte grazie a @Oliver (perso uno spazio)

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
Puoi rimuovere uno spazio tra 1efor
Oliver Ni

2

JavaScript (ES6), 190 189 byte

Stampa direttamente sulla 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)))

dimostrazione


2

Lotto, 464 byte

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

Questo è stato piuttosto laborioso. Spiegazione: inizia quadrando in nmodo da poter calcolare la larghezza della colonna desiderata ce la quantità appropriata di riempimento p, usando il loop :l. Il ciclo esterno da 1a nviene quindi eseguito una volta per ogni griglia, chiamando la subroutine :i. Innanzitutto viene controllato il valore per vedere se è 1 o primo; in caso contrario, la griglia verrà ignorata. Il ciclo interno da 1a n*nquindi gestisce le righe e le colonne della griglia, chiamando la subroutine:j . Ogni valore viene controllato per vedere se è uno dei numeri primi trovati finora o se nessuno dei numeri primi trovati finora lo divide. In tal caso, il valore viene concatenato al buffer di output, che viene quindi riempito con la larghezza della colonna desiderata. Il buffer viene stampato e cancellato ogninlinee e una riga vuota aggiuntiva viene aggiunta alla fine della griglia. L' se stesso.:f etichetta indica la subroutine di controllo dei fattori; f (x, y) aggiunge 1 a fper ogni numero intero compreso tra 2 e xche divide y, esclusoy


2

R, 195 191 185 204 byte

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

Grazie a @Billywob per 6 byte extra salvati!

Rientrato, con nuove righe:

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                     

Bene, non riesco mai a capire come stampare correttamente le matrici per soddisfare i requisiti di codegolfing, non importa se sono giustificate. Tuttavia, è possibile salvare alcuni byte. L'operatore di esponenziazione ^è l'unico che non viene vettorizzato quando si generano sequenze usando il :che significa che è possibile utilizzare ad esempio 1:2^2per ottenere 1 2 3 4. In secondo luogo, se si definisce, a=b=1:n^2è possibile utilizzare in seguito for(j in b)invece di definire un altro vettore su cui eseguire il loop. Dovrebbe salvarti un paio di byte.
Billywob,

Infatti! Grazie! Non riesco mai a ricordare l'ordine esatto di precedenza dell'operatore ...
plannapus,

Perché ci sono tre spazi tra i numeri in f (2) ef (3) e due spazi in f (9)? Dovrebbe essere sempre uno spazio.
Oliver Ni,

Oh giusto ho impostato 3 caratteri come norma perché stavo testando con N = 10, fammi correggere.
plannapus,

1

J, 125 byte

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

Questo è esplicito, non tacito J, ma dovrebbe esserci un modo per giocarlo 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      

1

Mathematica, 133 byte

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 byte

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

abbattersi

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]="";invece di unset($a[$i]);salvare 4 byte
Jörg Hülsermann il

$i%$k<1invece di !($i%$k)salvare un byte
Jörg Hülsermann il
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.