Tam giác Ulam xoắn ốc


21

Chúng tôi đã có một vài các thách thức về xoắn ốc Ulam. Nhưng điều đó là không đủ.

Trong thử thách này, chúng ta sẽ vẽ một hình xoắn ốc Ulam hình tam giác (trái ngược với hình xoắn ốc Ulam hình vuông thông thường). Đây là một bản phác thảo của hình xoắn ốc trông như thế nào.

nhập mô tả hình ảnh ở đây

Như chúng ta biết, xoắn ốc Ulam sắp xếp tất cả các số tự nhiên theo hình xoắn ốc hướng ra ngoài và chỉ đánh dấu những số nguyên tố. Vì vậy, trong bản phác thảo ở trên, chỉ những con số xuất hiện màu đen (số nguyên tố) sẽ được hiển thị.

Các thách thức

Chấp nhận một số N làm đầu vào và hiển thị hình xoắn ốc Ulam hình tam giác lên đến số đó.

  • Đầu vào có thể là stdin hoặc đối số chức năng.
  • Hình xoắn ốc phải quay theo chiều dương (nghĩa là ngược chiều kim đồng hồ), như trong hình trên.
  • Bất kỳ góc quay 120 độ nào của hình trên sẽ hợp lệ và lần lượt có thể khác nhau đối với các đầu vào khác nhau. Nhưng cạnh thấp nhất của các tam giác ngụ ý nên nằm ngang, vì các ngã rẽ duy nhất được phép là (bội số) 120 độ.
  • Mã phải chạy theo lý thuyết (được cung cấp đủ thời gian và bộ nhớ) cho bất kỳ N nào cho đến những gì được phép bởi bất kỳ phép tính trung gian nào bạn thực hiện với loại dữ liệu mặc định của mình. doubleLà đủ; không cần các loại số nguyên lớn.
  • Tất cả các chức năng tích hợp cho phép.
  • Tôi sẽ không chấp nhận câu trả lời của riêng mình (không phải tôi nghĩ rằng dù sao nó cũng sẽ ngắn nhất ...).

Định dạng đầu ra

Chọn bất kỳ thứ nào sau đây.

  1. Hiển thị biểu đồ với điểm đánh dấu (dấu chấm, vòng tròn, chữ thập, bất cứ thứ gì bạn thích) ở các số nguyên tố và không có gì ở các số không nguyên tố. Tỷ lệ không cần phải giống nhau cho hai trục. Đó là, các tam giác ngụ ý không cần phải bằng nhau. Trục, đường lưới và nhãn trục là tùy chọn. Chỉ các điểm đánh dấu ở các số nguyên tố được yêu cầu.

    Một ví dụ đầu ra cho N = 12 sẽ như sau (so sánh với bản phác thảo ở trên). Cốt truyện thứ hai là một ví dụ thú vị hơn, tương ứng với N = 10000.

nhập mô tả hình ảnh ở đây

nhập mô tả hình ảnh ở đây

  1. Tạo một tệp hình ảnh với ở trên, ở bất kỳ định dạng hình ảnh nổi tiếng nào (như png, tiff, bmp).
  2. Hiển thị hình xoắn ốc như nghệ thuật ASCII , sử dụng một ký tự bạn chọn cho các số nguyên tố và không gian trống cho các số nguyên tố, với một khoảng trắng để phân tách các vị trí số trong cùng một hàng. Không gian hàng đầu hoặc dấu hoặc dòng mới được cho phép. Ví dụ: trường hợp N = 12 sử dụng olàm ký tự sẽ là

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

    trong đó tất nhiên chỉ có odấu tại các số nguyên tố sẽ thực sự được hiển thị. Các ·phi số nguyên tố được hiển thị ở đây chỉ để tham khảo.

Tiêu chí chiến thắng

Phần thưởng thực tế là nhìn thấy cho chính bạn những mẫu golf tuyệt vời Code, mã ngắn nhất sẽ thắng.


2
Trong tương lai, tôi khuyên bạn chỉ nên chọn một trong số [đầu ra đồ họa] và [ascii-art] vì nó làm cho các bài nộp ít có thể so sánh được. Nhưng dù sao cũng là thử thách tốt. :)
Alex A.

@AlexA. Cảm ơn! Tôi sẽ tính đến điều đó. Vậy ... sẽ có câu trả lời của Julia chứ? ;-)
Luis Mendo

Wow, cảm ơn vì tiền thưởng, nhưng bạn nên chấp nhận câu trả lời của riêng bạn. Nó ngắn nhất. :)
Martin Ender

Nó rất xứng đáng! Đối với việc chấp nhận câu trả lời, một trong những quy tắc thách thức là "Tôi sẽ không chấp nhận câu trả lời của chính mình". Khi tôi nghĩ thử thách này chắc chắn tôi đã nghĩ đến MATL, với các hàm số và đồ họa phức tạp, vì vậy nó hơi giống như gian lận :-)
Luis Mendo

Câu trả lời:


13

CJam, 49 42 byte

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

Nhập dưới dạng một số nguyên duy nhất trong STDIN. Đầu ra dưới dạng lưới ASCII với 0các số nguyên tố. Vòng xoay của vòng xoắn ốc không nhất quán: số vòng xoắn lớn nhất sẽ luôn nằm ở hàng dưới cùng.

Kiểm tra nó ở đây.

Giải trình

Ý tưởng cơ bản là biểu diễn tam giác dưới dạng mảng 2D rách rưới trong khi thực hiện tính toán. Bạn có được mảng này bằng cách đảo ngược các dòng và căn chỉnh tất cả các hàng sang trái:

   4
  5 3
 6 1 2
7 8 9 A

Sẽ được đại diện là

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

Vì chúng tôi đã nhân đôi đường kẻ, chúng tôi muốn cuộn tròn theo chiều kim đồng hồ . Điều đó thật tiện lợi, vì tất cả những gì chúng ta cần làm là xoay tam giác ngược chiều kim đồng hồ và sắp xếp lại danh sách con tiếp theo theo thứ tự. Chúng ta có thể xoay mảng rách rưới bằng cách đảo ngược tất cả các dòng và hoán vị nó:

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

Vì vậy, đây là mã. Một chi tiết tôi muốn thu hút sự chú ý là bit cuối cùng tạo ra bố cục hình tam giác. Tôi nghĩ rằng đó là khá tiện lợi. :)

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
Tôi biết bạn là người đầu tiên!
Luis Mendo

@LuisMendo Tôi thực sự sẽ bỏ qua cái này, vì tôi nghĩ tính toán của các chỉ số lưới sẽ tẻ nhạt, nhưng sau đó tôi nhận ra rằng tôi chỉ có thể xoay toàn bộ tam giác trong khi nối thêm các đường.
Martin Ender

1
Tôi luôn thích những lời giải thích của bạn về các chương trình của CJam bởi vì tôi có thể hiểu chúng, và tôi ngạc nhiên về sự phức tạp, nhưng ngắn gọn, những chương trình này có thể.
Sản phẩm ETH

10

MATL , 48 36 byte

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

Sử dụng bản phát hành hiện tại (9.3.0) .

Hãy thử trực tuyến! Không biết làm thế nào trình biên dịch trực tuyến quản lý để dịch đầu ra đồ họa sang ASCII, nhưng nó thực hiện Điều này tạo ra một âm mưu ASCII gần đúng nhờ một tính năng Octave được trình biên dịch trực tuyến hỗ trợ!

Chỉnh sửa (ngày 4 tháng 4 năm 2016): chức năng Y[đã được đổi tên thành kkể từ khi phát hành 13.0.0. Liên kết đến trình biên dịch trực tuyến kết hợp thay đổi này, để mã có thể được kiểm tra.

Thí dụ

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

tạo đầu ra đồ họa (phiên bản MATLAB hiển thị):

nhập mô tả hình ảnh ở đây

Giải trình

Mã sử ​​dụng các số phức để theo dõi đường dẫn theo vòng xoắn ốc. Như có thể thấy từ hình đầu tiên trong thử thách, mỗi chân thẳng của hình xoắn ốc là một đoạn có chiều dài tăng 1, 2, 3, 4 ... và tăng theo chu kỳ 120 độ, 240 độ, 0 độ, 120 độ. ..

Mã đầu tiên tạo ra các chuyển vị phức tạp riêng lẻ từ mỗi số nguyên sang số tiếp theo. Những chuyển vị phức tạp này có cường độ 1 và góc 2*pi/3, 4*pi/3hoặc0 (tính bằng radian). Do đó, chúng có thể dễ dàng được tạo ra theo cấp số nhân tưởng tượng. Do đó, chuỗi số nguyên 0,1,2,2,3,3,3,4,4,4 ... được sử dụng đầu tiên.

Chuỗi số nguyên này gần giống như chuỗi "n xuất hiện n lần" ( OEIS A002024 ) và có thể được lấy floor(sqrt(2*n)+.5)ở vị trí n0,1,2,3, .... Nhân với 2j*pi/3, jđơn vị tưởng tượng, tạo ra các chuyển vị phức tạp mong muốn.

Các chuyển vị được tích lũy để tính toán các vị trí tương ứng với các số nguyên trong vòng xoắn ốc. Số nguyên đầu tiên trong vòng xoắn ốc 1, được đặt tùy ý tại vị trí 1trong mặt phẳng phức.

Cuối cùng, các vị trí tương ứng với các số không nguyên tố bị loại bỏ và phần còn lại được vẽ trong mặt phẳng phức.

: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 '.'

Tôi cần đọc gì thêm nữa
Brain Guider

Có thử trực tuyến không! hỗ trợ đầu ra đồ họa cho MATL?
Alex A.

Tôi nghĩ TIO không hỗ trợ đầu ra đồ họa? Nếu vậy, tôi có thể dễ dàng để MATL tự động kết xuất hình ảnh vào một .pngtệp để được hiển thị bởi trang web @AlexA
Luis Mendo

Chào! Tôi đã làm thử nghiệm đơn giản ( plot(1:5)) và nó tạo ra đầu ra văn bản-đồ họa !! matl.tryitonline.net/#code=NTpYRw&input= @AlexA. Cái này thế nào ??
Luis Mendo

4
WHOA! Thật tuyệt vời!
Alex A.

8

Vẽ nên được thực hiện với

LaTeX / PGF, 527 594 byte

\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 byte là tài liệu đầy đủ như trên, nghĩa là bao gồm phần mở đầu và tham số (ở đây là 4000, vì vậy ~ 523 không có tham số). Tạo một tệp PDF.

Ý tưởng cơ bản: tốt, chỉ cần vẽ. Sử dụng một phép biến đổi ma trận cho lưới tam giác. Vấn đề duy nhất là các chấm cũng bị ảnh hưởng (và kéo dài) ra bởi sự biến đổi. Vì vậy, tôi chọn đánh dấu hình elip :) ý tôi là rõ ràng trong hình ảnh thứ hai (n = 250, 5pt).

Một cảnh báo khác: chỉ có thể xử lý tối đa ít hơn 5000 một chút do kích thước ngăn xếp tối đa của TeX. Hình ảnh đầu tiên là cho n = 4000. Rõ ràng là có thể tăng kích thước ngăn xếp , tôi đã không thử nó.

Sử dụng PGF isprime().

nhập mô tả hình ảnh ở đây

nhập mô tả hình ảnh ở đây

Ung dung:

\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
Ồ Nó sẽ không bao giờ xảy ra với tôi để làm điều này trong LaTeX
Luis Mendo

Sử dụng lualatexhoặc một số trình biên dịch phân bổ động khác sẽ cho phép bạn bỏ qua kích thước ngăn xếp, nếu tôi hiểu chính xác nhận xét tương ứng của bạn. Vì vậy, đó không phải là giới hạn câu trả lời của bạn, hầu hết các triển khai nơi bạn chạy nó.
Andras Deak

Xin lỗi, tôi đã kiểm tra và giới hạn kích thước ngăn xếp đầu vào không liên quan đến cấp phát bộ nhớ mà tôi đã đề cập trong nhận xét trước đây của mình :(
Andras Deak

@AndrasDeak không sao, cảm ơn vì đã tìm nó. Tôi đã tìm thấy một phương pháp rõ ràng là làm tăng kích thước ngăn xếp, nhưng tôi đã không thử nó (chưa).

@CamilStaps cảm ơn, tôi đã tìm thấy những bài viết tương tự khác, nhưng tôi cũng không thử chúng. Dù sao, tôi lấy bài viết của Christian Feuersänger là canon :)
Andras Deak

2

Toán học, 94 byte

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

Kết quả

%[10000]

nhập mô tả hình ảnh ở đây


2

Python, 263 byte

Là người mới đối với Python, chắc chắn có chỗ để cải thiện :)

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

Thí dụ:

f(100000)

nhập mô tả hình ảnh ở đây


Bạn có thể rút ngắn s=[];X=[];Y=[];i=1;x=0;y=0xuốngs=X=Y=[];i=1;x=y=0;
rp.beltran

Bỏ qua dấu chấm phẩy thừa đó ở cuối. Nó sẽ dành cho bạn 8 byte.
rp.beltran

@ rp.beltran. Điều này không hoạt động. Tôi nghĩ rằng nó có liên quan đến thực tế các đối tượng chia sẻ cùng một giá trị. Chỉ có thể thêm x=y=0.
lambruscoAcido

Xấu của tôi, bạn đúng Tôi quên rằng Python vượt qua danh sách bằng cách tham khảo. Số là bất biến và vì vậy nó an toàn để làm với số nguyên.
rp.beltran

1

R, 137 byte

Chỉ sử dụng các hàm dựng sẵn, ngay cả đối với các số nguyên tố. Với cách tiếp cận véc tơ của nó thay vì lặp đi lặp lại, nó nhanh, nhưng không thể xử lý số lượng lớn.

Chơi gôn

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

Ung dung:

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
}

Thí dụ:

g(10000)

nhập mô tả hình ảnh ở đây


Bạn có thể thêm một kết quả ví dụ?
Luis Mendo

@LuisMendo. Chắc chắn rồi. Tôi chỉ phải tìm ra cách thêm một cốt truyện.
lambruscoAcido
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.