らせん状の周辺


19

自然数を取り、それらを反時計回りにらせんに丸めると、次の無限らせんになります。

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

そのスパイラルのいくつかの数字を考えると、あなたの仕事はその隣人、つまりその上、左、右、下の要素を決定することです。

見てみると27、次の隣人がいることがわかります。

  • 上記: 28
  • 左: 10
  • 右: 52
  • 以下: 26

したがって、出力は次のようになります。 [28,10,52,26]

ルール

  • 入力は、デフォルトのI / O形式で数値になりますn0
  • 出力は、任意の(一貫した!)順序でのその番号の4つの隣人のリスト/マトリックス/。
  • 0ではなく1で始まるスパイラルを使用することもできますが、回答で指定する必要があります

出力は形式で[above,left,right,below]あり、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]

回答:


6

R、156バイト

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

オンラインでお試しください!

  • @ngnとは少し異なるアプローチなので、別のR回答を投稿しました
  • 1インデックス付き
  • 隣人は常に昇順でソートされます
  • 除去バイト6を保存roundし、使用してcospi(x)/sinpi(x)より正確であるcos(x*pi)/sin(x*pi)(半分の数の場合には0.51.5...等)
  • 結果が同じであるため、y座標のマイナスを削除して別のバイトを保存しました(上下の隣同士が逆になります)

説明 :

我々は最初の値を考慮して、値の行列座標を見れば0に配置しx=0, y=0、彼らは以下のとおりです。

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

x座標は以下の通りA174344 OEIS配列を再帰式を有します:

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

同じ式がy行列座標にも当てはまりますが、のcos代わりにsinとが否定されます:

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

したがって、Rでは、sinpi/cospiパラメーターとして次の式をこの関数に変換できます。

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

そして、2つの座標ベクトルを生成します(上/下隣人を逆にしただけで同じ結果が得られるため、y座標を無効にしません):

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

(n+2)^2座標を生成していることに注意してください。座標は、両方nとその近傍を含む必要最小限の座標を超えています(より厳しい境界は(floor(sqrt(n))+2)^2、残念ながら「ゴルフ」ではありません)。

したがって、すべての座標が得られたので、まず、にa,b対応する座標を検索しますn

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

最後に、彼らの隣人の位置を選択します、すなわち:

  • アップ/ダウンネイバー where x == a and y == b+1 or b-1
  • 右/左隣人 where y == b and x == a+1 or a-1

を使用して:

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

「わずかに異なる」:)
ngm

@ngm:eheh ...あなたが使用したロゼッタコードは私にとってかなり「あいまい」なので、私は何らかの形で私のOEISシーケンスとは異なるが類似した方法でマトリックスの位置インデックスを生成していると推測しました:D
digEmAll

4

Perl 6の94の 83バイト

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

オンラインでお試しください!

sは、複素数として表されるスパイラル座標の怠laな無限リストです。これ1, *i ... *は、他の2つの無限リストから構成されます:リストを作成します1, i, -1, -i ...1, 1.5 ... *リストを作成します1, 1.5, 2, 2.5, 3, 3.5 ...。これらの2つのリストをリスト複製と一緒に圧縮すると、各スパイラル座標から次のステップまでのステップのリストが生成されます1, i, -1, -1, -i, -i, 1, 1, 1, i, i, i ...。(リスト複製演算子への右側の引数の小数部分は破棄されます。)[\+]このリストで三角の加算削減()を行う(および先頭に0を貼り付ける)と、螺旋座標のリストが生成されます。

最後に、複素数から始まるs[$_]$_関数の唯一の引数である)、我々は(インデックスを検索first :k)することにより、その番号からオフセットされた複素数のスパイラルではi-11、と-i


4

Brain-Flak、238バイト

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

オンラインでお試しください!

出力は、左、上、右、下の順になります。

説明

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

非常に印象的!他の人のようにスパイラル全体を生成しているのではないでしょうか?
ბიმო

3

MATL、15バイト

2+1YLtG=1Y6Z+g)

入力と出力は1ベースです。

出力は、左、下、上、および右の隣人をこの順序で提供します。

オンラインでお試しください!または、TIOでタイムアウトする最後の2つを除くすべてのテストケース確認します

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にはspiral機能がありますか?MATLABがMathematicaになったのはいつですか?!
スンダ-復活モニカ

ええ、私は1YLの意味を見てダックダックしました。このRosettaコードエントリは、MATLの便利な関数ではなく、MATLABのものであることを確認できる唯一の場所でした。そのエントリーを見るまで、ゴルフのためにあなたがMATLに追加したものであると考え始めていました。
スンダ

@sundarもはや文書化されていないのは奇妙です
ルイスメンドー


2

JavaScript(ES6)、165バイト

インデックスを印刷します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))

オンラインでお試しください!

どうやって?

バツyZバツy

Aバツy=||バツ||y||+|バツ|+|y|
Sバツy={1もし yバツ1もし y<バツ
バツy=Aバツy2+Aバツy+バツ+y×Sバツy

(math.stackexchange からのこの回答から適応)


これは小さい数字でも問題なく動作するようですが、2000などの大きな数字でテストするRangeError: Maximum call stack size exceededとエラーが発生します。tio.runのエラー:およびブラウザーコンソールのエラー:InternalError: too much recursion。私は何か間違っていますか?
Night2

1
4n2


1

PHP(> = 5.4)、208バイト

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

実行するには:

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

例:

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

または、オンラインでお試しください!

ノート:

  • この-d error_reporting=0オプションは、通知/警告を出力しないために使用されます。
  • このスパイラルは1から始まります。

どうやって?

この答えを修正した2次元配列のスパイラルを生成しています。

入力に基づいてスパイラルのサイズをn数式で決定し、常にスパイラルに余分な数のラウンドを取得します(上/下/左/右の存在の保証)。余分な数字のラウンドは、2次元配列の+2高さと+2幅を意味します。

したがって、n最大サイズのスパイラルに配置される場合3*3、生成されるスパイラルはになります5*5

スパイラルサイズであるc*c場合c = ceil(sqrt(n)) + kならば、ceil(sqrt(n))奇数である場合、k2であり、そして場合ceil(sqrt(n))もあり、次いで、k3です。

たとえば、上記の式は次のようになります。

  • 場合はn = 1、その後c = 3スパイラルサイズは次のようになります3*3
  • 場合はn <= 9、その後c = 5スパイラルサイズは次のようになります5*5
  • 場合はn <= 25、その後c = 7スパイラルサイズは次のようになります7*7
  • 場合はn <= 49、その後c = 9スパイラルサイズは次のようになります9*9
  • 等々 ...

螺旋の生成中、Iは、格納xおよびyn上/下/左/右のそれの発生以降、I出力が要素。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.