可以从素数生成方树年轮吗?


33

显然是的!三个简单的步骤。

步骤1

fn)表示素数计数函数(素数小于或等于n)。

如下定义整数序列 sn)。对于每个正整数n

  • t初始化n
  • 只要t既不是素数也不是1,则将t替换为ft)并进行迭代。
  • 迭代次数为sn)。

该迭代过程是保证最终因为˚FÑ)< ñ所有Ñ

考虑例如n= 25。我们初始化t =25。由于这不是素数也不是1,我们计算f(25)为9。这成为t的新值。这既不是素数也不是1,所以我们继续:f(9)是4。我们再次继续:f(4)是2。因为这是素数,所以我们在这里停止。我们完成了3次迭代(从25到9,然后到4,再到2)。因此s(25)为3。

序列的前40个词如下。该序列不在OEIS中。

0 0 0 1 0 1 0 2 2 2 0 1 0 2 2 2 0 1 0 3 3 3 0 3 3 3 3 3 0 3 0 1 1 1 1 1 0 2 2 2

第2步

给定一个奇数正整数N,通过缠绕有限序列s(1),s(2),...,sN 2)形成一个正方形的向外螺旋,以构建N×N数组(矩阵)。例如,给定N = 5,则螺旋为

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

或者,用值代替

 3       3       0       3       3
 3       0       2       2       2
 0       1       0       0       0
 1       0       1       0       1
 0       2       2       2       0

第三步

表示N×N阵列作为图像带有灰色的彩色地图,或者与自己的口味的一些其它颜色映射。映射应该是渐进的,以便数字的顺序与某种视觉上明显的颜色顺序相对应。下面的测试用例显示了一些示例颜色图。

挑战

给定一个奇数正整数N,生成上述图像。

规则

  • 螺旋线必须是向外的,但可以是顺时针或逆时针方向,并且可以开始向右(如上例所示),向左,向下或向上移动。

  • 水平轴和垂直轴的比例不必相同。轴标签,颜色条和类似元素也是可选的。只要可以清楚地看到螺旋线,图像就有效。

  • 图像可以通过任何标准方式输出。特别地,图像可以显示在屏幕上,或者可以产生图形文件,或者可以输出RGB值的阵列。如果输出文件或数组,请张贴一个显示时的示例。

  • 输入方式和格式像往常一样灵活。阿可以提供程序或函数禁止出现标准漏洞

  • 以字节为单位的最短代码获胜。

测试用例

以下图像(单击以获得完整的分辨率)对应于N的几个值。如上例所示,使用了顺时针,向右优先的螺旋线。这些图像还说明了几个有效的颜色图。

  • N = 301: 在此处输入图片说明

  • N = 501: 在此处输入图片说明

  • N = 701: 在此处输入图片说明


如果s(n)可以将的值数组输入到某些绘图函数/程序包中而无需修改(例如,我认为imshow在matplotlib中可以处理此问题),这是可接受的输出形式吗?
dylnan '18

@dylnan当然,只要它在屏幕上绘制图像或生成文件就有效。实际上,我生成的示例与您提到的类似。小心缩放值。例如,如果大于1的所有值都被赋予相同的颜色(例如Matlab(可能还包括Matplotlib)),imshow则颜色是不可接受的
Luis

好点子。不知道是否imshow这样做。
dylnan '18

1
@ kamoroso94请在此处查看
Luis

1
是的非常清楚
Christopher

Answers:


3

Dyalog APL,94个字节

'P2'
2⍴n←⎕
9
(⍪0){×≢⍵:(≢⍺)((⍉∘⌽⍺,↑)∇↓)⍵⋄⍺}2↓{⍵⌊1+⍵[+\p]}⍣≡9×~p←1=⊃+/(≠⍨,≠⍨,~⍴⍨(×⍨n)-2×≢)¨,\×⍳n

假设 ⎕IO=0

n = 701的输出(从.pgm转换为.png):

在此处输入图片说明


10

MATLAB - 197 185 178 175 184 163 162 148 142 140个字节

多亏了安德(Ander)和安德拉斯(Andras),将12字节削减了,而多亏了路易斯(Luis)将这两者合为一体。雷姆科(Remco)剃光了16岁,弗拉克(racker)剃了6岁

function F(n)
p=@primes
s=@isprime
for a=2:n^2
c=0
if~s(a)
b=nnz(p(a))
while~s(b)
b=nnz(p(b))
c=c+1
end
end
d(a)=c
end
imagesc(d(spiral(n)))

N=301F(301))的结果:

在此处输入图片说明

说明:

function F(n)
p=@primes % Handle
s=@isprime % Handle
for a=2:n^2 % Loop over all numbers
    c=0 % Set initial count
    if~s(a) % If not a prime
        b=nnz(p(a)) % Count primes
        while~s(b) % Stop if b is a prime. Since the code starts at 2, it never reaches 1 anyway
            b=nnz(p(b)) % count again
            c=c+1 % increase count
        end
    end
    d(a)=c % store count
end
imagesc(d(spiral(n))) % plot

8

Wolfram语言(Mathematica),124字节

感谢Martin Ender节省了12个字节!

Image[#/Max@#]&[Array[(n=0;Max[4#2#2-Max[+##,3#2-#],4#
#-{+##,3#-#2}]+1//.x_?CompositeQ:>PrimePi[++n;x];n)&,{#,#},(1-#)/2]]&

在线尝试!


生成的图像是:

螺旋

直接从我的答案得到的螺旋值的封闭形式公式。


5
#/2-.5保存一个字节。
user202729 '18

8
哈哈,你在向自己建议吗?
路易斯·门多

6
@ user202729似乎不起作用。
user202729 '18

18
我不是要打扰您的内心对话:-P
Luis Mendo,

推迟定义p直到您需要:...,{y,p=(1-#)/2,-p},{x,p,-p}
Martin Ender

7

MATLAB:115个 114 110字节

一根衬板(在R2016b +中作为脚本中的函数运行)115个字节

I=@(N)imagesc(arrayfun(@(x)s(x,0),spiral(N)));function k=s(n,k);if n>1&~isprime(n);k=s(nnz(primes(n)),k+1);end;end

按照faker的建议,将函数放在单独的文件中,并在每个附加文件规则中使用1个附加字节

在文件中s.m,代码+文件为64 +1字节

function k=s(n,k);if n>1&~isprime(n);k=s(nnz(primes(n)),k+1);end

命令窗口定义I,45字节

I=@(N)imagesc(arrayfun(@(x)s(x,0),spiral(N)))

总计:110个字节


它使用递归而不是while像其他MATLAB实现(gnoviceAdriaan)一样循环。作为脚本运行(在R2016b或更高版本中),这定义了I可以像一样运行的功能I(n)

结构化版本:

% Anonymous function for use, i.e. I(301)
% Uses arrayfun to avoid for loop, spiral to create spiral!
I=@(N)imagesc(arrayfun(@(x)s(x,0),spiral(N)));

% Function for recursively calculating the s(n) value
function k=s(n,k)
    % Condition for re-iterating. Otherwise return k unchanged
    if n>1 && ~isprime(n)
        % Increment k and re-iterate
        k = s( nnz(primes(n)), k+1 );
    end
end

例:

I(301)

情节

笔记:

  • 我也尝试使s函数匿名,这当然会大大减少计数。但是,有两个问题:

    1. 使用MATLAB函数时,很难避免无限递归,因为MATLAB没有提供中断条件的三元运算符。绑定各种三元运算符(请参见下文)也会花费字节,因为我们需要两次条件。

    2. 如果匿名函数是递归的(请参见此处),它会增加字节,则必须将其传递给自身。

    我最接近的代码使用以下几行,也许可以更改为起作用:

    % Condition, since we need to use it twice 
    c=@(n)n>1&&~isprime(n);
    % This uses a bodged ternary operator, multiplying the two possible outputs by
    % c(n) and ~c(n) and adding to return effectively only one of them
    % An attempt was made to use &&'s short-circuiting to avoid infinite recursion
    % but this doesn't seem to work!
    S=@(S,n,k)~c(n)*k+c(n)&&S(S,nnz(primes(n)),k+1);

6

MATLAB - 126个 121 *字节

我尝试了一种比Adriaan更矢量化的方法,并且能够节省更多字节。这是单行解决方案:

function t(n),M=1:n^2;c=0;i=1;s=@isprime;v=cumsum(s(M));while any(i),i=M>1&~s(M);c=c+i;M(i)=v(M(i));end;imagesc(c(spiral(n)))

这是格式精美的解决方案:

function t(n),
  M = 1:n^2;
  c = 0;
  i = 1;
  s = @isprime;
  v = cumsum(s(M));
  while any(i),         % *See below
    i = M > 1 & ~s(M);
    c = c+i;
    M(i) = v(M(i));
  end;
  imagesc(c(spiral(n)))

* 注意:如果您愿意允许不必要的迭代,那么可以将行更改 while any(i), for m=v, 并节省5个字节。


真好!我喜欢您用来cumsum向量化和避免的方式nnz(primes(...)
Luis Mendo

1
如果我理解正确,那么进行多次不必要的迭代(以速度为代价)不会受到伤害。因此,您可以替换while any(i)for m=M。谁在乎代码是否需要花几个小时才能运行:-)
Luis Mendo

2
@LuisMendo:当然,为什么不呢?它已经迭代了超过所需的次数,还有什么n^2迭代会很痛苦!;)
gnovice

1
就是那种精神!您还可以保留运行速度更快的版本,但是字节数是较短的版本
Luis Mendo

2

Python 3中,299个 265字节

由于Jonathan Frech和NoOneIsHere的格式化建议,节省了5个字节。通过删除仅调用一次的函数定义,删除了另外的34个字节。

由于python没有确定素数或螺旋数组的命令,因此它比其他一些更长。但是,它运行相对较快,大约需要1分钟n = 700

from pylab import*
def S(n):
 q=arange(n*n+1);t=ones_like(q)
 for i in q[2:]:t[2*i::i]=0
 c=lambda i:0 if t[i]else 1+c(sum(t[2:i]));S=[c(x)for x in q]
 t=r_[[[S[1]]]]
 while any(array(t.shape)<n):m=t.shape;i=multiply(*m)+1;t=vstack([S[i:i+m[0]],rot90(t)])
 return t

用它测试

n = 7
x = S(n)
imshow(x, interpolation='none')
colorbar()
show(block=False)


1
一个快速的事情:你可以删除之间的空间import*
NoOneIsHere18年

2

J,121字节

load 'viewmat'
a=:3 :'viewmat{:@((p:inv@{.,>:@{:)^:(-.@((=1:)+.1&p:)@{.)^:_)@(,0:)"0(,1+(i.@#+>./)@{:)@|:@|.^:(+:<:y),.1'

定义一个函数:

a=:3 :'viewmat{:@((p:inv@{.,>:@{:)^:(-.@((=1:)+.1&p:)@{.)^:_)@(,0:)"0(,1+(i.@#+>./)@{:)@|:@|.^:(+:<:y),.1' | Full fuction
                                                                     (,1+(i.@#+>./)@{:)@|:@|.^:(+:<:y),.1  | Creates the number spiral
              {:@((p:inv@{.,>:@{:)^:(-.@((=1:)+.1&p:)@{.)^:_)@(,0:)"0                                      | Applies S(n) to each element
       viewmat                                                                                             | View the array as an image

2

R,231字节

function(n){p=function(n)sum(!n%%2:n)<2;M=matrix(0,n,n);M[n^2%/%2+cumsum(c(1,head(rep(rep(c(1,-n,-1,n),l=2*n-1),rev(n-seq(n*2-1)%/%2)),-1)))]=sapply(1:(n^2),function(x){y=0;while(x>2&!p(x)){x=sum(sapply(2:x,p));y=y+1};y});image(M)}

略少打高尔夫球:

function(n){
    p=function(n)sum(!n%%2:n)<2 #"is.prime" function
    M=matrix(0,n,n)             #empty matrix
    indices=n^2%/%2+cumsum(c(1,head(rep(rep(c(1,-n,-1,n),l=2*n-1),rev(n-seq(n*2-1)%/%2)),-1)))
    values=sapply(1:(n^2),function(x){
        y=0
        while(x>2&!p(x)){
            x=sum(sapply(2:x,p))
            y=y+1
            }
        y})
    M[indices]=values
    image(M) #Plotting
}

匿名函数。在图形窗口中输出。等级为红色等级,最深的阴影等于0,更清晰的阴影增加值。

n = 101的结果:

n = 101

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.