Eratosthenes筛,一步一步


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

您的工作是逐步构建Eratosthenes筛。首先,从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=10100不是素数,所以会在某个时候删除。由于1003位数字,是否必须将所有数字都填充为3个字符?
mbomb007 '16

4
为什么要对齐数字?
丹尼斯

2
尾随的换行符可以接受吗?
丹尼斯

2
是否允许内置网格?输出将看起来与文章中的示例相同,但不会是字符串。
JungHwan Min

Answers:


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

两条文字换行符每个都保存一个字节代替\ 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:通过在一个被调用的位置显式使用$ d来保存12个字节,而不是创建一个单独的变量,方法是合并一些声明,并通过next在第一个foreach循环中的其他地方消除空格来消除我的一个条件。通过将两个for循环重新处理为一个循环,消除了两个变量声明,并将unless语句转换为if-not语句,从而获得了另外29个字节。声明my$e=$n*$n;然后用$ e替换$ n * $ n的三个实例(允许我为其中的一个添加括号)结果是±0字节,但无论如何我还是把它保留了下来。

编辑3:感谢@Dada,又节省了40个字节(变量声明,“ foreach”成为“ for”,在多个位置隐式$ _,并减小了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变量并使用$_will代替。)printf"%*s",1+length$e,$a[$c](有关此内容的详细信息,请参见``sprintf` doc *
达达

1
使用$"代替" "say""而不是print"\n"(您的代码中有乱七八糟的换行符,但是我不能在注释中写上它)(您将添加到-M5.010命令行中,但这并不计入字节数)。您可能会0..$e=$n*$n在初始化时使用来保存一个字节$e。看看perl高尔夫技巧,它包含许多有用的技巧。但是很高兴见到一位新的perl高尔夫球手,欢迎光临!:)(并原谅我的拼写错误,我之前的评论可能写得太快了)
Dada

@Dada谢谢您的建议!我对在命令行上运行代码不是很熟悉(我倾向于将其作为文件运行),但我将以这种方式来看一下。至于if!$c%$n,!运算符的优先级高于%运算符,因此从技术上讲,这if((!$c)%$n)对于$ c = 0以外的任何内容(对于我而言,我都不需要)都将为false。至于您的其他提示,我将尽我所能!非常感谢你!
加布里埃尔·贝纳米

你不必须在命令行中运行它,如果你把他们在文件中,以及那些修改工作。对不起!,我没有在计算机上进行检查。我认为您应该可以减少到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
加密

1
-3字节:$i=$d*$x=$d>1代替$i=$d<2?0:$d$x发生其他两次$d>1
Titus

1
-2个字节:$n*$n>=$i+=$d代替($i+=$d)<=$m=$n**2并且$n*$n针对其他情况$m
Titus

1
-1字节:开头而不是结尾的换行符
Titus

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         

取消高尔夫:

{
    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
这看起来并不像我左对齐。
丹尼斯

已修复...直到现在我才有机会对其进行编辑...
Magic Octopus Urn

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

代表


1
您可以在1和之间删除空格for
Oliver Ni

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以便可以使用loop 计算所需的列宽c和适当的填充量。外循环from 到然后对每个网格运行一次,调用子例程。首先检查该值以查看它是1还是素数。如果不是,则跳过该网格。内部循环从到然后处理网格的行和列,调用子例程p:l1n:i1n*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^2get 1 2 3 4。其次,如果定义a=b=1:n^2,则可以稍后使用,for(j in b)而不是定义另一个向量进行循环。应该可以节省几个字节。
Billywob

确实!谢谢!永远不记得运算符优先级的确切顺序...
plannapus 16-10-20

为什么在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个字节
约尔格Hülsermann

$i%$k<1而不是!($i%$k)保存一个字节
约尔格Hülsermann
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.