三角形乌兰螺旋


21

我们已经有几个挑战有关乌拉螺旋。但这还不够。

在此挑战中,我们将绘制一个三角形的Ulam螺旋线(与通常的方形Ulam螺旋线相反)。这是螺旋形的草图。

在此处输入图片说明

众所周知,乌拉姆螺旋将所有自然数排列在一个向外的螺旋中,并且仅标记那些质数。因此,在上面的草图中,只会显示以黑色(质数)显示的数字。

挑战

接受数字N作为输入,并显示直至该数字的三角形Ulam螺旋。

  • 输入可以是stdin或函数参数。
  • 螺旋线应沿正方向(即逆时针)旋转,如上图所示。
  • 上图的120度转弯中的任何一个都是有效的,并且转弯对于不同的输入可能是不同的。但是隐含三角形的最低边应为水平,因为唯一允许的转弯为120度(的倍数)。
  • 理论上,代码应针对任何N运行(给定的时间和内存),直到使用默认数据类型进行的任何中间计算所允许的N。double足够; 不需要大整数类型。
  • 允许所有内置功能。
  • 我不会接受我自己的答案(不是我认为这将是最短的答案...)。

输出格式

选择以下任意一项。

  1. 显示带有质数的标记(点,圆,叉,任意)的图形,非质数不显示任何图形。两个轴的比例不必相同。也就是说,隐含三角形不必是等边的。轴,网格线和轴标签是可选的。仅需要质数上的标记。

    N = 12 的示例输出如下(与上面的草图比较)。第二个图是一个更有趣的示例,对应于N = 10000。

在此处输入图片说明

在此处输入图片说明

  1. 使用任何众所周知的图像格式(例如png,tiff,bmp),用上述文件生成图像文件
  2. 将螺旋显示为ASCII艺术,使用您选择的单个字符表示质数,使用空白表示非质数,并用空格分隔同一行中的数字位置。允许前导或尾随空格或换行符。例如,如果N = 12的情况下使用o字符

                 o
                · ·
               · o ·
                o · ·
               · o · o
    

    当然,只有o素数标记才会实际显示。将·在非质数如下所示,仅供参考。

获奖标准

实际的回报是亲眼看到那些惊人的模式 Code Golf,最短的代码获胜。


2
将来,我建议您只选择[图形输出]和[ascii-art]中的一种,因为这会使提交的内容具有较低的可比性。但是无论如何都是不错的挑战。:)
Alex A.

@AlexA。谢谢!我会考虑到这一点。所以...会有朱莉娅的答案吗?;-)
Luis Mendo

哇,谢谢您的悬赏,但是您应该接受自己的回答。它最短的。:)
Martin Ender

这是当之无愧的!至于接受答案,挑战规则之一是“我不会接受自己的答案”。当我想到这个挑战时,我不可避免地想到了MATL,它具有复数和图形功能,所以有点像作弊:-)
Luis Mendo

Answers:


13

CJam,49个 42字节

Lri{)mp0S?}%{1$,)/(a@Wf%z+\L*}h;eeSff*W%N*

在STDIN中输入为单个整数。输出为带0素数的ASCII网格。螺旋线的旋转不一致:螺旋线的最大数量始终位于最下面一行。

在这里测试。

说明

基本思想是在执行计算时将三角形表示为参差不齐的2D数组。您可以通过反转行并将所有行向左对齐来获得此数组:

   4
  5 3
 6 1 2
7 8 9 A

将表示为

[[7 8 9 A]
 [6 1 2]
 [5 3]
 [4]]

由于我们已经绘制了直线,因此我们希望以顺时针方式滚动螺旋线。这很方便,因为我们要做的就是逆时针旋转三角形并按顺序在下一个子列表之前。我们可以通过反转所有行并将其转置来旋转衣衫array的数组:

                                                           [[B C D E F]
[[7 8 9 A]         [[A 9 8 7]           [[A 2 3 4]          [A 2 3 4]
 [6 1 2]   reverse  [2 1 6]   transpose  [9 1 5]   prepend  [9 1 5]
 [5 3]      ---->   [3 5]      ------>   [8 6]      ---->   [8 6]
 [4]]               [4]]                 [7]]               [7]]

所以这是代码。我要引起注意的一个细节是创建三角形布局的最后一点。我认为这很不错。:)

L     e# Push an empty array. This will become the spiral.
ri    e# Read input and convert to integer N.
{     e# Map this block over 0 to N-1...
  )   e#   Increment to get 1 to N.
  mp  e#   Test for primality.
  0S? e#   Select 0 or a space correspondingly.
}%
{     e# While the list we just created is not empty yet...
  1$  e#   Copy the spiral so far.
  ,)  e#   Get the number of lines and increment.
  /   e#   Split the list into chunks of that size.
  (a@ e#   Pull off the first chunk, wrap it in an array, pull up the spiral.
  Wf% e#   Reverse the lines of the spiral.
  z   e#   Transpose the spiral.
  +   e#   Prepend the new line.
  \L* e#   Swap with the remaining chunks and join them back together into a single list.
}h
;     e# Discard the empty list that's left on the stack.
ee    e# Enumerate the spiral. This turns each line into a pair of 0-based index
      e# and the line itself.
Sff*  e# Multiply each element of each pair with a space. For the enumeration index i,
      e# this produces a string of i spaces - the required indentation (keeping in
      e# mind that our spiral is still upside down). For the line itself, this
      e# riffles the cells with spaces, creating the required gaps between the cells.
      e# All of this works because we always end the spiral on the bottom edge.
      e# This ensures that the left edge is always complete, so we don't need
      e# different indentation such as in the N=12 example in the challenge.
W%    e# Reverse the lines to make the spiral point upwards.
N*    e# Join the lines with linefeeds.

1
我知道你会是第一个!
路易斯·门多

@LuisMendo我实际上要跳过这一步,因为我认为网格索引的计算将是乏味的,但是后来我意识到我可以在附加线的同时旋转整个三角形。
Martin Ender

1
我一直很喜欢您对CJam程序的解释,因为我能理解它们,并且令我惊讶的是,这些程序如此复杂而又简短。
ETHproductions 2016年

10

MATL48 36字节

:1-H*X^.5+Y[2j3/*YP*ZeYsG:Zp)'.'2$XG

使用当前版本(9.3.0)

在线尝试! 不知道在线编译器如何设法将图形输出转换为ASCII,但确实如此。这要归功于在线编译器支持的八度功能,从而生成了近似的ASCII图!

编辑(2016年4月4日):自版本13.0.0起,该功能Y[已重命名为k。联机编译器的链接包含此更改,因此可以测试代码。

>> matl
 > :1-H*X^.5+Y[2j3/*YP*ZeYsG:Zp)'.'2$XG
 > 
> 20000

产生图形输出(显示为MATLAB版本):

在此处输入图片说明

说明

该代码使用复数来跟踪螺旋线所遵循的路径。从挑战中的第一张图可以看出,螺旋的每个直腿都是一个段,其长度增加1、2、3、4 ...,并周期性地增加方向120度,240度,0度,120度。 ..

该代码首先生成从每个整数到下一个整数的各个复数位移。这些复杂的位移的大小为1,角度为2*pi/34*pi/30(弧度)。因此,它们可以容易地生成为虚指数。为此,首先使用整数序列0,1,2,2,3,3,3,4,4,4,4...。

该整数序列几乎类似于“ n次出现n次”序列(OEIS A002024),并且可以从floor(sqrt(2*n)+.5)那里获得n0、1、2、3,...。乘以2j*pi/3,其中j虚部为,产生所需的复数位移。

累积位移以计算与螺旋中的整数相对应的位置。螺旋中的第一个整数,即1,任意位于1复平面中的位置。

最后,丢弃与非素数相对应的位置,并将其余位置绘制在复平面上。

:1-H*X^.5+Y[     % floor(sqrt(2*n)+.5) for n from 0 to N-1, where N is implicit input
2j3/*YP*Ze       % exp(2j*pi/3* ... )
Ys               % cumulative sum. Produces complex positions
G:               % vector 1,2...,N, where N is previous input
Zp               % logical index to select only prime numbers
)                % use that index to keep only complex positions of primes
'.'2$XG          % plot using marker '.'

我需要进一步阅读的内容
Brain Guider

可以在线尝试!支持MATL的图形输出?
Alex A.

我以为TIO不支持图形输出?如果可以,我可以轻松地使MATL自动将图像转储到.png文件中,以显示在网页上@AlexA
Luis

嘿! 我做了简单的测试(plot(1:5)),它确实产生了文本图形输出!matl.tryitonline.net/#code=NTpYRw&input= @AlexA。这个怎么样??
路易斯·门多

4
哇!棒极了!
Alex A.

8

绘图应与

LaTeX / PGF,527594字节

\documentclass{standalone}\usepackage{pgf}\let\z\let\z\e\advance\z\f\ifnum\z\h\the\z\a\newcount\a\i\a\j\a\l\a\x\a\y\a\p\a\q\a\n\i=1\l=1\p=-1\q=1\def\m#1{\e\i by1\e\j by1\e\x by\h\p\e\y by\h\q\pgfmathparse{isprime(\h\i)}\f\pgfmathresult=1\pgfpathcircle{\pgfpoint{\h\x cm}{\h\y cm}}3pt\fi\f\j=\l\e\l by1\j=0\f\p=1\p=-1\q=1\else\f\p=-1\p=0\q=-1\else\p=1\q=0\fi\fi\fi\f#1>0\e#1by-1\m#1\fi}\begin{document}\begin{pgfpicture}\pgftransformcm10{cos(60)}{sin(60)}\pgfpointorigin\n=4000\m\n\pgfusepath{fill}\end{pgfpicture}\end{document}

527字节是上述的完整文档,即包括前导和参数(此处为4000,所以〜523无参数)。产生一个PDF文件。

基本思想:好吧,画画。对三角形网格使用矩阵变换。唯一的问题是,变换也会影响(延伸)点。因此,我选择了椭圆形标记:)在第二张图片中我的意思很清楚(n = 250,5pt)。

另一个警告:由于TeX的最大堆栈大小,最多只能处理少于5000个位。第一幅图像的n = 4000。显然可以增加堆栈大小,但我没有尝试过。

使用PGF的isprime()

在此处输入图片说明

在此处输入图片说明

取消高尔夫:

\documentclass[border=10cm]{standalone}

\usepackage{pgf}

\newcount\ulami
\newcount\ulamj
\newcount\ulamlen

\newcount\ulamx
\newcount\ulamy
\newcount\ulamdx
\newcount\ulamdy

\ulami=1 %
\ulamj=0 %
\ulamlen=1 %
\ulamdx=-1 %
\ulamdy=1 %
\ulamx=0 %
\ulamy=0 %

\def\ulamplot#1{%
  \advance\ulami by 1 %
  \advance\ulamj by 1 %

  \advance\ulamx by \the\ulamdx %
  \advance\ulamy by \the\ulamdy %

  \pgfpathmoveto{\pgfpoint{\the\ulamx cm}{\the\ulamy cm}}

  \pgfmathparse{isprime(\the\ulami)}
  \let\r=\pgfmathresult
  \ifnum\r=1
    \pgfpathcircle{\pgfpoint{\the\ulamx cm}{\the\ulamy cm}}{5pt}
  \fi

  \ifnum\ulamj=\the\ulamlen %
    \advance\ulamlen by 1 %
    \ulamj=0 %
    \ifnum\ulamdx=1 %
      \ulamdx=-1 %
      \ulamdy=1 %
    \else%
      \ifnum\ulamdx=-1 %
        \ulamdx=0 %
        \ulamdy=-1 %
      \else%
        \ulamdx=1 %
        \ulamdy=0 %
      \fi
    \fi
  \fi

  \ifnum#1>0 %
    \advance#1 by -1 %
    \ulamplot{#1}%
  \fi
}

\begin{document}

\begin{pgfpicture}
  \pgfmathsetmacro{\x}{cos(60)}
  \pgfmathsetmacro{\y}{sin(60)}
  \pgftransformcm{1}{0}{\x}{\y}{\pgfpointorigin}

  \pgfpathmoveto{\pgfpointorigin}
  \color{blue}
  \newcount\ulamn
  \ulamn=400
  \ulamplot{\ulamn}
  \pgfusepath{stroke,fill}
\end{pgfpicture}

\end{document}

1
哇。我永远不会在LaTeX中做到这一点
Luis Mendo,2016年

lualatex如果我正确理解了您的相应注释,则使用或其他一些动态分配的编译器应该使您绕过堆栈大小。因此,这不是您答案的限制,只是您运行它的大多数实现的限制。
Andras Deak

抱歉,我检查了一下,输入堆栈的大小限制与我先前的评论中提到的内存分配无关:(
Andras Deak 2016年

@AndrasDeak没关系,感谢您查找它。我发现了一种显然可以增加堆栈大小的方法,但是我自己还没有尝试过。

@CamilStaps谢谢,我发现了其他类似的帖子,但我也没有尝试。无论如何,我将ChristianFeuersänger的帖子作为经典:)
Andras Deak

2

Mathematica,94个字节

ListPlot@Accumulate[Join@@Table[ReIm@Exp[2i Pi/3I],{i,2#^.5},{i}]][[Prime@Range@PrimePi@#-1]]&

结果

%[10000]

在此处输入图片说明


2

Python,263个字节

作为Python的新手,肯定还有改进的余地:)

from matplotlib.pyplot import*
from math import*
def f(m):
 s=[];X=[];Y=[];i=x=y=0
 while len(s)<m:i+=1;s+=[i%3*pi*2/3]*i
 for i in range(m):
  x+=cos(s[i]);y+=sin(s[i]);j=i+2
  if all(map(lambda a:j%a>=1,range(2,int(j**.5+1)))):X+=[x];Y+=[y]
 scatter(X,Y);show()

例:

f(100000)

在此处输入图片说明


您可以缩短s=[];X=[];Y=[];i=1;x=0;y=0s=X=Y=[];i=1;x=y=0;
rp.beltran '16

最后忽略多余的分号。它应该为您节省8个字节。
rp.beltran '16

@ rp.beltran。这是行不通的。我认为这与对象共享相同值的事实有关。只能添加x=y=0
lambruscoAcido16年

我的坏,你是对的。我忘记了Python通过引用传递列表。数字是不可变的,因此可以安全地使用整数。
rp.beltran '16

1

R,137个字节

仅使用内置函数,即使是质数。鉴于其向量化方法而不是迭代方法,它速度很快,但无法处理大量数据。

打高尔夫球:

g=function(m){M=1:m;s=rep(M,M)[M]%%3*pi*2/3;k=cumsum;j=sapply(seq(s)+1,function(n)n<4|all(n%%2:n^.5>=1));plot(k(cos(s))[j],k(sin(s))[j])}

取消高尔夫:

g=function(m) {
  M = 1:m
  s = rep(M,M)[M] %% 3 * pi * 2/3
  k=cumsum
  j=sapply(seq(s)+1,function(n)n<4|all(n%%2:n^.5>=1)) # primes
  plot(k(cos(s))[j],k(sin(s))[j])    # cumulated coordinates
}

例:

g(10000)

在此处输入图片说明


您可以添加示例结果吗?
Luis Mendo

@LuisMendo。当然。我只需要弄清楚如何添加绘图。
lambruscoAcido16年
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.