Khu phố xoắn ốc


19

Nếu chúng ta lấy các số tự nhiên và cuộn chúng ngược chiều kim đồng hồ thành một vòng xoắn ốc, chúng ta sẽ kết thúc với vòng xoắn vô hạn sau:

                  ....--57--56
                             |
36--35--34--33--32--31--30  55
 |                       |   |
37  16--15--14--13--12  29  54
 |   |               |   |   |
38  17   4---3---2  11  28  53
 |   |   |       |   |   |   |
39  18   5   0---1  10  27  52
 |   |   |           |   |   |
40  19   6---7---8---9  26  51
 |   |                   |   |
41  20--21--22--23--24--25  50
 |                           |
42--43--44--45--46--47--48--49

Đưa ra một số con số trong vòng xoắn ốc đó, nhiệm vụ của bạn là xác định hàng xóm của nó - nghĩa là phần tử bên trên, bên trái, bên phải và bên dưới nó.

Thí dụ

Nếu chúng ta nhìn vào 27chúng ta có thể thấy rằng nó có những người hàng xóm sau:

  • ở trên: 28
  • trái: 10
  • đúng: 52
  • phía dưới: 26

Vì vậy, đầu ra sẽ là: [28,10,52,26]

Quy tắc

  • Đầu vào sẽ là số ở bất kỳ định dạng I / O mặc định nàon0
  • Đầu ra sẽ là một danh sách / ma trận / .. trong số 4 hàng xóm đó theo thứ tự bất kỳ (nhất quán!)
  • Bạn có thể làm việc với hình xoắn ốc bắt đầu bằng 1 thay vì 0, tuy nhiên bạn nên chỉ định điều đó trong câu trả lời của mình

Ví dụ

Đầu ra có định dạng [above,left,right,below]và sử dụng hình xoắn ốc dựa trên 0:

0  ->  [3,5,1,7]
1  ->  [2,0,10,8]
2  ->  [13,3,11,1]
3  ->  [14,4,2,0]
6  ->  [5,19,7,21]
16  ->  [35,37,15,17]
25  ->  [26,24,50,48]
27  ->  [28,10,52,26]
73  ->  [42,72,74,112]
101  ->  [100,146,64,102]
2000  ->  [1825,1999,2001,2183]
1000000  ->  [1004003,1004005,999999,1000001]

Câu trả lời:


6

R , 156 byte

function(n){g=function(h)c(0,cumsum(h((4*(0:(n+2)^2)+1)^.5%%4%/%1/2)))
x=g(sinpi)
y=g(cospi)
a=x[n]
b=y[n]
which(x==a&(y==b+1|y==b-1)|y==b&(x==a+1|x==a-1))}

Hãy thử trực tuyến!

  • đã đăng một câu trả lời R khác vì đó là một cách tiếp cận hơi khác so với @ngn
  • 1 chỉ mục
  • hàng xóm luôn được sắp xếp theo giá trị tăng dần
  • đã lưu 6 byte loại bỏ roundvà sử dụng cospi(x)/sinpi(x)chính xác hơn cos(x*pi)/sin(x*pi)trong trường hợp một nửa số ( 0.5, 1.5v.v ...)
  • đã lưu một byte khác loại bỏ dấu trừ trên tọa độ y vì kết quả là như nhau (chỉ cần đảo ngược lên / xuống)

Giải trình :

Nếu chúng ta nhìn vào tọa độ ma trận của các giá trị, xem xét giá trị đầu tiên 0được đặt tại x=0, y=0, chúng là:

x = [0,  1,  1,  0, -1, -1, -1,  0,  1,  2,  2,  2,  2,  1,  0, ...] 
y = [0,  0,  1,  1,  1,  0, -1, -1, -1, -1,  0,  1,  2,  2,  2, ...]

Các xtọa độ tuân theo trình tự A174344 OEIS với công thức đệ quy:

a(1) = 0, a(n) = a(n-1) + sin(mod(floor(sqrt(4*(n-2)+1)),4)*pi/2)

Công thức tương tự giữ cho ytọa độ ma trận, nhưng costhay vì sinvà phủ định:

a(1) = 0, a(n) = a(n-1) - cos(mod(floor(sqrt(4*(n-2)+1)),4)*pi/2)

Vì vậy, trong R chúng ta có thể dịch công thức cho hàm này, lấy sinpi/cospitham số:

g=function(h)c(0,cumsum(h((4*(0:(n+2)^2)+1)^.5%%4%/%1/2)))

và chúng tôi tạo ra hai vectơ tọa độ (chúng tôi không phủ nhận các hợp âm y vì chúng tôi sẽ nhận được cùng một kết quả, chỉ với các hàng xóm lên / xuống đảo ngược):

x=g(sinpi)
y=g(cospi)

Lưu ý rằng chúng tôi đã tạo các (n+2)^2tọa độ, nhiều hơn các tọa độ cần thiết tối thiểu có chứa cả hai nvà các lân cận của chúng (một ràng buộc chặt chẽ hơn (floor(sqrt(n))+2)^2nhưng không may là ít "golfy" hơn).

Do đó, bây giờ chúng ta có tất cả các tọa độ, trước tiên chúng ta tìm kiếm các tọa độ a,btương ứng với n:

a=x[n]
b=y[n]

cuối cùng chúng tôi chọn vị trí của hàng xóm của họ, tức là:

  • hàng xóm lên / xuống where x == a and y == b+1 or b-1
  • hàng xóm bên phải / bên trái where y == b and x == a+1 or a-1

sử dụng:

which(x==a&(y==b+1|y==b-1)|y==b&(x==a+1|x==a-1))

"hơi khác" :)
ngm

@ngm: eheh ... từ mã Rosetta bạn sử dụng là khá "mơ hồ" với tôi, tôi cho rằng là bằng cách nào đó tạo ra các chỉ số vị trí của ma trận một cách khác nhau nhưng giống nhau hơn so với chuỗi OEIS của tôi: D
digEmAll

4

Perl 6 , 94 83 byte

{my \ s = 0, | [+] phẳng ((1, i ... ) Zxx phẳng (1..Inf Z 1..Inf)); map {đầu tiên: k, s [$ _] + $ ^ d, s}, i, -1,1, -i}

{my \s=0,|[\+] flat((1,*i...*)Zxx(1,1.5...*));map {first :k,s[$_]+$^d,s},i,-1,1,-i}

Hãy thử trực tuyến!

slà một danh sách lười biếng, vô tận của tọa độ xoắn ốc, được biểu diễn dưới dạng số phức. Nó được xây dựng từ hai danh sách vô hạn khác: 1, *i ... *tạo danh sách 1, i, -1, -i .... 1, 1.5 ... *làm cho danh sách 1, 1.5, 2, 2.5, 3, 3.5 .... Nén hai danh sách này cùng với sao chép danh sách tạo ra danh sách các bước từ mỗi tọa độ xoắn ốc sang tiếp theo : 1, i, -1, -1, -i, -i, 1, 1, 1, i, i, i .... (Các phần phân số của các đối số bên phải cho toán tử sao chép danh sách sẽ bị loại bỏ.) Thực hiện giảm cộng tam giác ( [\+]) trong danh sách này (và dán 0 lên phía trước) tạo ra danh sách tọa độ xoắn ốc.

Cuối cùng, bắt đầu từ số phức tạp s[$_]( $_là đại diện duy nhất đến chức năng), chúng tôi tìm kiếm các chỉ số ( first :k) trong vòng xoáy của số phức được bù đắp từ con số đó bởi i, -1, 1, và -i.


4

Brain-Flak , 238 byte

((){[()]<((({}[((()))]<>)<<>{((([{}]({}))([{}]{})())[()]){({}[()])<>}{}}>)<<>({}<(((({}{})()){}<>({}))()())<>>)<>>()())<>{{}((()()()[({})]){}<>({}<{}>))(<>)}>}{}){<>((((())()())()())()())(<>)}{}{({}[()]<<>({}<>)<>({}<({}<({}<>)>)>)<>>)}<>

Hãy thử trực tuyến!

Đầu ra theo thứ tự trái, lên, phải, xuống.

Giải trình

# If n is nonzero:
((){[()]<

  ((

    # Push 1 twice, and push n-1 onto other stack.
    ({}[((()))]<>)

    # Determine how many times spiral turns up to n, and whether we are on a corner.
    # This is like the standard modulus algorithm, but the "modulus" used
    # increases as 1, 1, 2, 2, 3, 3, ...
    <<>{((([{}]({}))([{}]{})())[()]){({}[()])<>}{}}>

  # Push n-1: this is the number behind n in the spiral.
  )<

    # While maintaining the "modulus" part of the result:
    <>({}<

      # Push n+2k+1 and n+2k+3 on top of n-1, where k is 3 more than the number of turns.
      # n+2k+1 is always the number to the right in the direction travelled.
      # If we are on a corner, n+2k+3 is the number straight ahead.
      (((({}{})()){}<>({}))()())<>

    >)<>

  # Push n+1.  If we are on a corner, we now have left, front, right, and back
  # on the stack (from top to bottom)
  >()())

  # If not on a corner:
  <>{{}

    # Remove n+2k+3 from the stack entirely, and push 6-2k+(n+1) on top of the stack.
    ((()()()[({})]){}<>({}<{}>))

  (<>)}

>}{})

# If n was zero instead:
{

  # Push 1, 3, 5, 7 on right stack, and implicitly use 1 (from if/else code) as k.
  <>((((())()())()())()())

(<>)}{}

# Roll stack k times to move to an absolute reference frame
# (switching which stack we're on each time for convenience)
{({}[()]<<>({}<>)<>({}<({}<({}<>)>)>)<>>)}<>

Rất ấn tượng! Tôi đoán bạn không tạo ra toàn bộ xoắn ốc như những người khác làm, phải không?
ბიმო

3

MATL , 15 byte

2+1YLtG=1Y6Z+g)

Đầu vào và đầu ra là 1 dựa trên.

Đầu ra cho các hàng xóm trái, xuống, lên và phải theo thứ tự đó.

Hãy thử trực tuyến! Hoặc xác minh tất cả các trường hợp kiểm tra ngoại trừ hai trường hợp cuối cùng, hết thời gian trên TIO.

2+      % Implicit input: n. Add 2. This is needed so that
        % the spiral is big enough
1YL     % Spiral with side n+2. Gives a square matrix
t       % Duplicate
G=      % Compare with n, element-wise. Gives 1 for entry containing n
1Y6     % Push 3×3 mask with 4-neighbourhood
Z+      % 2D convolution, keeping size. Gives 1 for neighbours of the
        % entry that contained n
g       % Convert to logical, to be used as an index
)       % Index into copy of the spiral. Implicit display

2
1YL- MATLAB có spiralchức năng gì? Khi nào MATLAB biến thành Mathicala?!
- Phục hồi Monica

Vâng, tôi đã sử dụng nó sau khi xem ý nghĩa của 1YL và mục nhập mã Rosetta này là nơi duy nhất tôi có thể tìm thấy để xác nhận rằng đó là một thứ MATLAB chứ không chỉ là chức năng tiện lợi MATL. Tôi đã bắt đầu nghĩ rằng nó có thể là thứ gì đó bạn đã thêm vào MATL để chơi gôn, cho đến khi tôi thấy mục đó.
- Phục hồi Monica

@sundar Lạ là nó không được ghi chép lại
Luis Mendo

3

R , 172 byte

function(x,n=2*x+3,i=cumsum(rep(rep(c(1,n,-1,-n),l=2*n-1),n-seq(2*n-1)%/%2))){F[i]=n^2-1:n^2
m=matrix(F,n,n,T)
j=which(m==x,T)
c(m[j[1],j[2]+c(-1,1)],m[j[1]+c(-1,1),j[2]])}

Hãy thử trực tuyến!

Đây là R, vì vậy rõ ràng câu trả lời là 0-index.

Hầu hết các công việc đang tạo ra ma trận. Mã được lấy cảm hứng từ: https://rosettacode.org/wiki/Spirus_matrix#R


2

JavaScript (ES6), 165 byte

In các chỉ số với alert().

f=(n,x=w=y=n+2)=>y+w&&[0,-1,0,1].map((d,i)=>(g=(x,y,A=Math.abs)=>(k=A(A(x)-A(y))+A(x)+A(y))*k+(k+x+y)*(y>=x||-1))(x+d,y+~-i%2)-n||alert(g(x,y)))|f(n,x+w?x-1:(y--,w))

Hãy thử trực tuyến!

Làm sao?

x,yZIx,y

Ax,y=||x||y||+|x|+|y|
Sx,y={1,if yx1,if y<x
Ix,y=Ax,y2+(Ax,y+x+y)×Sx,y

(phỏng theo câu trả lời này từ math.stackexchange)


Điều này có vẻ hoạt động tốt với các số nhỏ hơn, nhưng tôi gặp lỗi khi kiểm tra điều này với một số lớn như 2000. Lỗi trên tio.run: RangeError: Maximum call stack size exceededvà lỗi trong bảng điều khiển trình duyệt : InternalError: too much recursion. Tôi có làm điều gì sai?
Đêm2

1
4n2

2

Python 2 , 177 164 1 46 144 byte

def f(n):N=int(n**.5);S=N*N;K=S+N;F=4*N;return[n+[F+3,[-1,1-F][n>K]][n>S],n+[F+5,-1][n>K],n+[[1,3-F][n<K],-1][0<n==S],n+[F+7,1][n<K]][::1-N%2*2]

Hãy thử trực tuyến!

Tính u,l,r,dtrực tiếp từ n.


1

PHP (> = 5,4), 208 byte

<?$n=$argv[1];for(;$i++<($c=ceil(sqrt($n))+($c%2?2:3))**2;$i!=$n?:$x=-$v,$i!=$n?:$y=+$h,${hv[$m&1]}+=$m&2?-1:1,$k++<$p?:$p+=$m++%2+$k=0)$r[-$v][+$h]=$i;foreach([0,1,0,-1]as$k=>$i)echo$r[$x+$i][$y+~-$k%2].' ';

Để chạy nó:

php -n -d error_reporting=0 <filename> <n>

Thí dụ:

php -n -d error_reporting=0 spiral_neighbourhoods.php 2001

Hoặc dùng thử trực tuyến!

Ghi chú:

  • Các -d error_reporting=0tùy chọn được sử dụng để không ra thông báo / cảnh báo.
  • Vòng xoắn ốc này bắt đầu bằng 1.

Làm sao?

Tôi đang tạo vòng xoắn ốc với phiên bản sửa đổi của câu trả lời này trong mảng 2 chiều.

Tôi quyết định kích thước của hình xoắn ốc dựa trên đầu vào nvới một công thức để luôn có thêm một vòng số trong vòng xoắn ốc (đảm bảo cho sự tồn tại của trên / dưới / trái / phải). Một vòng số thêm có nghĩa là +2chiều cao và +2chiều rộng của mảng 2 chiều.

Vì vậy, nếu nsẽ nằm trong một vòng xoắn ốc với kích thước tối đa 3*3, thì xoắn ốc được tạo ra sẽ là 5*5.

Kích thước xoắn ốc là c*cở đâu c = ceil(sqrt(n)) + k, nếu ceil(sqrt(n))là số lẻ, thì klà 2 và nếu ceil(sqrt(n))là số chẵn thì klà 3.

Ví dụ: công thức trên sẽ dẫn đến kết quả này:

  • Nếu n = 1sau đó c = 3và kích thước xoắn ốc sẽ là3*3
  • Nếu n <= 9sau đó c = 5và kích thước xoắn ốc sẽ là5*5
  • Nếu n <= 25sau đó c = 7và kích thước xoắn ốc sẽ là7*7
  • Nếu n <= 49sau đó c = 9và kích thước xoắn ốc sẽ là9*9
  • Và cứ thế ...

Khi tạo hình xoắn ốc, tôi lưu trữ các xycủa nvà sau khi thế hệ, tôi đầu ra các yếu tố trên / dưới / trái / phải của nó.

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.