Lingkungan spiral

19

Jika kita mengambil bilangan alami dan menggulungnya dengan jarum jam menjadi spiral, kita akan berakhir dengan spiral tak terbatas berikut ini:

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

Mengingat beberapa angka dalam spiral itu, tugas Anda adalah menentukan tetangganya - artinya elemen di atas, kiri, kanan, dan di bawahnya.

Contoh

Jika kita melihat 27kita dapat melihat bahwa ia memiliki tetangga berikut:

  • atas: 28
  • kiri: 10
  • Baik: 52
  • di bawah: 26

Jadi hasilnya adalah: [28,10,52,26]

Aturan

  • Input akan berupa angka dalam format I / O standar apa punn0
  • Output akan menjadi daftar / matriks / .. dari 4 tetangga nomor itu dalam urutan (konsisten!) Apa pun
  • Anda dapat bekerja dengan spiral yang dimulai dengan 1 bukannya 0, namun Anda harus menentukannya dalam jawaban Anda

Contohnya

Outputnya dalam format [above,left,right,below]dan menggunakan spiral berbasis 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]
ბიმო
sumber
terkait
ბიმო

Jawaban:

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

Cobalah online!

  • diposting jawaban R lain karena pendekatannya sedikit berbeda dari @ngn
  • 1-diindeks
  • tetangga selalu diurutkan berdasarkan nilai naik
  • menyimpan 6 byte menghapus rounddan menggunakan cospi(x)/sinpi(x)yang lebih tepat daripada cos(x*pi)/sin(x*pi)dalam kasus setengah angka ( 0.5, 1.5dll ...)
  • menyimpan byte lain dengan menghapus minus pada koordinat y karena hasilnya sama (tetangga naik / turun terbalik)

Penjelasan:

Jika kita melihat koordinat matriks dari nilai-nilai tersebut, dengan mempertimbangkan nilai pertama yang 0ditempatkan x=0, y=0, mereka adalah:

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, ...]

The xkoordinat mengikuti urutan A174344 Oei dengan rumus rekursif:

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

Rumus yang sama berlaku untuk ykoordinat matriks, tetapi dengan cosbukannya sindan dinegasikan:

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

Jadi, di R kita bisa menerjemahkan rumus ke fungsi ini, dengan mengambil sinpi/cospisebagai parameter:

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

dan kami menghasilkan dua vektor koordinat (kami tidak meniadakan koordinat y karena kami akan mendapatkan hasil yang sama, hanya dengan tetangga naik / turun terbalik):

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

Perhatikan bahwa kami telah menghasilkan (n+2)^2koordinat, yang lebih dari koordinat minimum yang diperlukan yang mengandung keduanya ndan tetangganya (batas yang lebih ketat akan (floor(sqrt(n))+2)^2tetapi sayangnya kurang "golf").

Karena itu, sekarang kita memiliki semua koordinat, pertama-tama kita mencari koordinat yang a,bsesuai dengan kita n:

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

akhirnya kami memilih posisi tetangga mereka, yaitu:

  • tetangga naik / turun where x == a and y == b+1 or b-1
  • tetangga kanan / kiri where y == b and x == a+1 or a-1

menggunakan:

which(x==a&(y==b+1|y==b-1)|y==b&(x==a+1|x==a-1))
menggali semua
sumber
"sedikit berbeda" :)
ngm
@ ngm: eheh ... karena kode rosetta yang Anda gunakan cukup "tidak jelas" bagi saya, saya berasumsi entah bagaimana menghasilkan indeks posisi matriks dengan cara yang berbeda tetapi serupa dari urutan OEIS saya: D
digEmAll
4

Perl 6 , 94 83 byte

{my \ s = 0, | [+] flat ((1, i ... ) Zxx flat (1..Inf Z 1..Inf)); peta {pertama: 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}

Cobalah online!

sadalah daftar koordinat spiral yang malas dan tidak terbatas, direpresentasikan sebagai bilangan kompleks. Itu dibangun dari dua daftar tak terbatas lainnya: 1, *i ... *membuat daftar 1, i, -1, -i .... 1, 1.5 ... *membuat daftar 1, 1.5, 2, 2.5, 3, 3.5 .... Zipping dua daftar ini bersama-sama dengan daftar replikasi menghasilkan daftar langkah-langkah dari setiap spiral mengkoordinasikan ke yang berikutnya: 1, i, -1, -1, -i, -i, 1, 1, 1, i, i, i .... (Bagian fraksional dari argumen kanan ke operator replikasi daftar dibuang.) Melakukan pengurangan penambahan segitiga ( [\+]) pada daftar ini (dan menempelkan 0 ke depan) menghasilkan daftar koordinat spiral.

Akhirnya, mulai dari bilangan kompleks s[$_]( $_menjadi satu-satunya argumen untuk fungsi), kita mencari indeks ( first :k) dalam spiral dari bilangan kompleks yang offset dari jumlah itu dengan i, -1, 1, dan -i.

Sean
sumber
4

Brain-Flak , 238 byte

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

Cobalah online!

Output dalam urutan kiri, atas, kanan, bawah.

Penjelasan

# 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)
{({}[()]<<>({}<>)<>({}<({}<({}<>)>)>)<>>)}<>
Nitrodon
sumber
Sangat mengesankan! Saya kira Anda tidak menghasilkan seluruh spiral seperti yang dilakukan orang lain, bukan?
ბიმო
3

MATL , 15 byte

2+1YLtG=1Y6Z+g)

Input dan output berbasis 1.

Outputnya memberikan tetangga kiri, bawah, atas dan kanan dalam urutan itu.

Cobalah online! Atau verifikasi semua kasus uji kecuali dua yang terakhir, yang waktunya habis pada 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
Luis Mendo
sumber
2
1YL- MATLAB memiliki spiralfungsi? Kapan MATLAB berubah menjadi Mathematica ?!
sundar - Reinstate Monica
Ya, saya menundukkannya setelah melihat apa yang dimaksud 1YL, dan entri kode Rosetta ini adalah satu-satunya tempat yang bisa saya temukan untuk mengonfirmasi bahwa itu adalah hal MATLAB dan bukan hanya fungsi kenyamanan MATL. Saya mulai berpikir itu mungkin sesuatu yang Anda tambahkan ke MATL untuk bermain golf, sampai saya melihat entri itu.
sundar - Pasang kembali Monica
@sundar Aneh bahwa itu tidak didokumentasikan lagi
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]])}

Cobalah online!

Ini R, jadi jelas jawabannya adalah 0-diindeks.

Sebagian besar pekerjaan adalah membuat matriks. Kode terinspirasi oleh: https://rosettacode.org/wiki/Spiral_matrix#R

ngm
sumber
2

JavaScript (ES6), 165 byte

Mencetak indeks dengan 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))

Cobalah online!

Bagaimana?

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

(diadaptasi dari jawaban ini dari math.stackexchange)

Arnauld
sumber
Hal ini tampaknya bekerja dengan baik dengan angka yang lebih kecil, tapi saya mendapatkan error ketika pengujian ini dengan sejumlah besar seperti 2000. Kesalahan pada tio.run: RangeError: Maximum call stack size exceededdan kesalahan pada konsol peramban: InternalError: too much recursion. Apakah saya melakukan sesuatu yang salah?
Night2
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]

Cobalah online!

Menghitung u,l,r,dlangsung dari n.

Chas Brown
sumber
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].' ';

Untuk menjalankannya:

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

Contoh:

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

Atau Coba online!

Catatan:

  • The -d error_reporting=0opsi digunakan untuk pemberitahuan tidak keluaran / peringatan.
  • Spiral ini dimulai dengan 1.

Bagaimana?

Saya menghasilkan spiral dengan versi modifikasi dari jawaban ini dalam array 2 dimensi.

Saya memutuskan ukuran spiral berdasarkan input ndengan formula untuk selalu mendapatkan angka putaran tambahan dalam spiral (jaminan untuk keberadaan di atas / di bawah / kiri / kanan). Putaran angka ekstra berarti +2tinggi dan +2lebar array 2 dimensi.

Jadi jika nakan ditempatkan di spiral dengan ukuran maksimum 3*3, maka spiral yang dihasilkan akan 5*5.

Ukuran spiral adalah di c*cmana c = ceil(sqrt(n)) + k, jika ceil(sqrt(n))ganjil, maka kadalah 2 dan jika ceil(sqrt(n))genap, maka kadalah 3.

Misalnya, rumus di atas akan menghasilkan ini:

  • Jika n = 1itu c = 3dan ukuran spiral akan3*3
  • Jika n <= 9itu c = 5dan ukuran spiral akan5*5
  • Jika n <= 25itu c = 7dan ukuran spiral akan7*7
  • Jika n <= 49itu c = 9dan ukuran spiral akan9*9
  • Dan seterusnya ...

Saat menghasilkan spiral, saya menyimpan xdan ydari ndan setelah generasi, saya menampilkan elemen di atas / di bawah / kiri / kanan itu.

Night2
sumber