Spiral mahalleler


19

Doğal sayıları alıp saat yönünün tersine bir sarmal haline getirirsek, aşağıdaki sonsuz sarmalla sonuçlanırız:

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

Bu sarmaldaki bir sayı verildiğinde, göreviniz komşularını belirlemektir - yani yukarıdaki, sol, sağ ve altındaki eleman.

Misal

Eğer bir göz 27atarsak, aşağıdaki komşuları olduğunu görebiliriz:

  • yukarıda: 28
  • ayrıldı: 10
  • sağ: 52
  • altında: 26

Böylece çıktı: [28,10,52,26]

kurallar

  • Giriş, herhangi bir varsayılan G / Ç biçiminde sayısı olacaktırn0
  • Çıktı, bu sayıların 4 komşusunun (tutarlı!) Sırada bir listesi / matrisi / .. olacaktır
  • 0 yerine 1 ile başlayan bir spiral ile çalışabilirsiniz, ancak cevabınızda bunu belirtmelisiniz.

Örnekler

Çıktı biçimindedir [above,left,right,below]ve 0 tabanlı bir spiral kullanır:

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]

Yanıtlar:


6

R , 156 bayt

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

Çevrimiçi deneyin!

  • @ngn'den biraz farklı bir yaklaşım olduğu için başka bir R yanıtı yayınladı
  • 1 endeksli
  • komşular her zaman artan değere göre sıralanır
  • Kaydedilen çıkarmadan 6 bayt roundkullanarak cospi(x)/sinpi(x)daha hassas olan cos(x*pi)/sin(x*pi)yarım sayıların durumunda ( 0.5, 1.5vb ...)
  • sonuç aynı olduğu için y koordinatlarında eksi çıkarılarak başka bir bayt kaydedildi (sadece yukarı / aşağı komşuları ters çevrildi)

Açıklama:

Değerlerin matris koordinatlarına, 0yerleştirilen ilk değeri göz önüne alırsak x=0, y=0, bunlar:

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

xKoordinatlar aşağıdaki A174344 OEIS sekansı yinelemeli formüle sahip:

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

Aynı formül, ymatris koordinatları için geçerlidir , ancak cosyerine sinve reddedildi:

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

Böylece, R'de formülü sinpi/cospiparametre olarak alarak bu işleve çevirebiliriz :

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

ve iki koordinat vektörünü üretiyoruz (sadece yukarı / aşağı komşuları tersine çevirerek aynı sonucu alacağımız için y koordinatlarını yok etmiyoruz):

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

(n+2)^2Hem nkomşularını hem de komşularını içeren gerekli minimum koordinatlardan daha fazla olan koordinatlar oluşturduğumuza dikkat edin (daha sıkı bir bağ olacaktır, (floor(sqrt(n))+2)^2ancak ne yazık ki daha az "golfçidir").

Bu nedenle, şimdi tüm koordinatlara sahip olduğumuza göre, önce aşağıdakilere a,bkarşılık gelen koordinatları araştırıyoruz n:

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

son olarak komşularının konumlarını seçiyoruz, yani:

  • yukarı / aşağı komşular where x == a and y == b+1 or b-1
  • sağ / sol komşular where y == b and x == a+1 or a-1

kullanarak:

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

"biraz farklı" :)
ngm

@ngm: eheh ... Kullandığınız rosetta kodu benim için oldukça "belirsiz" olduğundan, bir şekilde matrisin konum indekslerini
OEIS

4

Perl 6 , 94 83 bayt

{my \ s = 0, | [+] düz ((1, i ... ) Zxx düz (1.Inf Z 1..Inf)); harita {ilk: k, s [$ _] + $ ^ d ı, 1,1, -i}} s

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

Çevrimiçi deneyin!

skarmaşık sayılarla temsil edilen tembel, sonsuz bir spiral koordinat listesidir. Diğer iki sonsuz listeden oluşturulur: 1, *i ... *listeyi yapar 1, i, -1, -i .... 1, 1.5 ... *listeyi yapar 1, 1.5, 2, 2.5, 3, 3.5 .... Liste çoğaltma ile birlikte bu iki listeyi Sıkıştırma her spiral adımların listesi aşağıdaki koordinat üretir: 1, i, -1, -1, -i, -i, 1, 1, 1, i, i, i .... (Liste çoğaltma işlecine sağ taraftaki bağımsız değişkenlerin kesirli kısımları atılır.) [\+]Bu listeye üçgen ekleme azalması ( ) yapılması (ve ön tarafa 0 yapıştırılması) spiral koordinatların listesini oluşturur.

Son olarak, karmaşık sayının başlayarak s[$_]( $_işleve tek argüman olmak üzere), biz dizinleri (bakmak first :ktarafından bu numaradan ofset karmaşık sayılar sarmal içinde) i, -1, 1, ve -i.


4

Brain-Flak , 238 bayt

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

Çevrimiçi deneyin!

Çıktı sol, yukarı, sağ, aşağı sırada.

açıklama

# 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)
{({}[()]<<>({}<>)<>({}<({}<({}<>)>)>)<>>)}<>

Çok etkileyici! Sanırım bütün spirali diğerleri gibi üretmiyorsunuz, değil mi?
ბიმო

3

MATL , 15 bayt

2+1YLtG=1Y6Z+g)

Giriş ve çıkış 1 tabanlıdır.

Çıktı sol, aşağı, yukarı ve sağ komşuları bu sırayla verir.

Çevrimiçi deneyin! Veya TIO'da zaman aşımına uğrayan son ikisi hariç tüm test senaryolarını doğrulayın .

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'ın bir spiralişlevi var mı? MATLAB ne zaman Mathematica'ya dönüştü ?!
sundar - Monica'yı eski haline

Evet, 1YL'nin ne anlama geldiğini gördükten sonra bunu duckduckgo-ed ve bu Rosetta kod girişi , sadece bir MATL kolaylık işlevi değil, bir MATLAB şey olduğunu onaylamak için bulabildiğim tek yerdi. Bu girişi görünceye kadar golf için MATL'ye eklediğiniz bir şey olabileceğini düşünmeye başlamıştım.
sundar - Monica'yı eski haline

@sundar Artık belgelenmediği garip
Luis Mendo


2

JavaScript (ES6), 165 bayt

İle indeksleri yazdırır 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))

Çevrimiçi deneyin!

Nasıl?

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

( math.stackexchange'in bu cevabından uyarlanmıştır )


Bu daha küçük sayılarla cezası iş gibi görünüyor, ancak bir tio.run üzerinde 2000 Hata gibi çok sayıda bu test hatayı alıyorum: RangeError: Maximum call stack size exceededtarayıcı konsoluna ve hatayı: InternalError: too much recursion. Yanlış bir şey mi yapıyorum?
Night2

1
4n2

2

Python 2 , 177 164 1 46 144 bayt

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]

Çevrimiçi deneyin!

u,l,r,dDoğrudan üzerinden hesaplar n.


1

PHP (> = 5.4), 208 bayt

<?$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].' ';

Çalıştırmak için:

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

Misal:

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

Veya çevrimiçi deneyin!

Notlar:

  • Bu -d error_reporting=0seçenek, uyarı / uyarı vermemek için kullanılır.
  • Bu spiral 1 ile başlar.

Nasıl?

Ben 2 boyutlu bir dizi bu cevap değiştirilmiş bir versiyonu ile spiral üretiyorum .

Spiralin nher zaman fazladan bir sayı turu elde etmek için bir formülü olan girdiye dayanarak spiralin boyutuna karar veriyorum (yukarıda / aşağıda / sol / sağın varlığını garanti eder). Fazladan bir sayı turu 2 boyutlu dizinin +2yüksekliği ve +2genişliği anlamına gelir .

Dolayısıyla n, maksimum boyutu olan bir sarmal içinde 3*3bulunacaksa, üretilen sarmal olacaktır 5*5.

Spiral boyutu c*cburada c = ceil(sqrt(n)) + keğer ceil(sqrt(n))tek, daha sonra k2 ise ve ceil(sqrt(n))hatta, daha sonra k3 'tür.

Örneğin, yukarıdaki formül bununla sonuçlanır:

  • Eğer n = 1öyleyse c = 3ve spiral boyutu3*3
  • Eğer n <= 9öyleyse c = 5ve spiral boyutu5*5
  • Eğer n <= 25öyleyse c = 7ve spiral boyutu7*7
  • Eğer n <= 49öyleyse c = 9ve spiral boyutu9*9
  • Ve bunun gibi ...

Spirali oluştururken, x ve yarasında nve üretim sonra, çıkış / Yukarıda elemanları aşağıda / sağ ve sol /.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.