Gewundene Nachbarschaften

19

Wenn wir die natürlichen Zahlen nehmen und gegen den Uhrzeigersinn zu einer Spirale aufrollen, erhalten wir die folgende unendliche Spirale:

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

Bei einer bestimmten Anzahl in dieser Spirale besteht Ihre Aufgabe darin, die Nachbarn zu bestimmen - dh das Element darüber, links, rechts und darunter.

Beispiel

Wenn wir uns das ansehen 27, können wir sehen, dass es die folgenden Nachbarn hat:

  • über: 28
  • links: 10
  • Recht: 52
  • unten: 26

Die Ausgabe wäre also: [28,10,52,26]

Regeln

  • Die Eingabe erfolgt in jedem Standard-E / A-Format mit einer Zahl n0
  • Es wird eine Liste / Matrix / .. der 4 Nachbarn dieser Zahlen in beliebiger (konsistenter!) Reihenfolge ausgegeben
  • Sie können mit einer Spirale arbeiten, die mit 1 anstelle von 0 beginnt. Dies sollten Sie jedoch in Ihrer Antwort angeben

Beispiele

Die Ausgabe hat das Format [above,left,right,below]und verwendet eine 0-basierte Spirale:

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]
ბიმო
quelle
Related
ბიმო

Antworten:

6

R , 156 Bytes

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

Probieren Sie es online!

  • hat eine andere R-Antwort gepostet, da dies ein etwas anderer Ansatz als @ngn ist
  • 1-indiziert
  • Nachbarn werden immer nach aufsteigendem Wert sortiert
  • gespart 6 Bytes entfernen roundund verwenden, cospi(x)/sinpi(x)die genauer sind als cos(x*pi)/sin(x*pi)bei halben Zahlen ( 0.5, 1.5etc ...)
  • hat ein weiteres Byte gespeichert und das Minus auf den y-Koordinaten entfernt, da das Ergebnis dasselbe ist (nur die oberen und unteren Nachbarn sind vertauscht)

Erklärung:

Wenn wir die Matrixkoordinaten der Werte unter Berücksichtigung des ersten Wertes betrachten, der bei 0platziert wird x=0, y=0, sind sie:

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

Die xKoordinaten folgen der OEIS-Sequenz A174344 mit der rekursiven Formel:

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

Dieselbe Formel gilt für yMatrixkoordinaten, jedoch mit cosstatt sinund negiert:

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

Also können wir in R die Formel in diese Funktion übersetzen, wobei wir sinpi/cospials Parameter nehmen:

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

und wir generieren die beiden Koordinatenvektoren (wir negieren die y-Koordinaten nicht, da wir das gleiche Ergebnis erhalten, nur mit umgekehrten Nachbarn nach oben / unten):

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

Beachten Sie, dass wir (n+2)^2Koordinaten generiert haben , die mehr als die erforderlichen Mindestkoordinaten sind, die beide nund ihre Nachbarn enthalten (eine engere Grenze wäre (floor(sqrt(n))+2)^2aber leider weniger "golf").

Nachdem wir nun alle Koordinaten haben, suchen wir zuerst die Koordinaten a,b, die unseren entsprechen n:

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

Schließlich wählen wir die Positionen ihrer Nachbarn aus, dh:

  • die auf / ab Nachbarn where x == a and y == b+1 or b-1
  • die rechten / linken Nachbarn where y == b and x == a+1 or a-1

mit:

which(x==a&(y==b+1|y==b-1)|y==b&(x==a+1|x==a-1))
digEmAll
quelle
"etwas anders" :)
ngm
@ngm: eheh ... da der rosetta Code , den Sie verwendet wird , ist ziemlich „dunkel“ zu mir, ich angenommen , irgendwie wird die Positionsindizes der Matrix in einem anderen aber ähnlicher Weise als meine OEIS Sequenzen zu erzeugen: D
digEmAll
4

Perl 6 , 94 83 Bytes

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

Probieren Sie es online!

sist eine faule, unendliche Liste von Spiralkoordinaten, dargestellt als komplexe Zahlen. Es besteht aus zwei weiteren unendlichen Listen: 1, *i ... *Erstellt die Liste 1, i, -1, -i .... 1, 1.5 ... *macht die Liste 1, 1.5, 2, 2.5, 3, 3.5 .... Zipping diese beiden Listen zusammen mit der Liste der Replikation erzeugt die Liste der Schritte von jeder Spirale auf die nächste Koordinate: 1, i, -1, -1, -i, -i, 1, 1, 1, i, i, i .... (Die Nachkommastellen der Argumente auf der rechten Seite für den Listenreplikationsoperator werden verworfen.) Wenn Sie eine dreieckige Additionsreduktion ( [\+]) für diese Liste ausführen (und 0 auf die Vorderseite einfügen), wird die Liste der Spiralkoordinaten erstellt.

Schließlich ist aus der komplexen Zahl beginnen s[$_]( $_das einzige Argument für die Funktion ist), sehen wir die Indizes (bis first :k) in der Spirale der komplexen Zahlen , die durch von dieser Zahl versetzt sind i, -1, 1, und -i.

Sean
quelle
4

Brain-Flak , 238 Bytes

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

Probieren Sie es online!

Die Ausgabe erfolgt in der Reihenfolge links, oben, rechts und unten.

Erläuterung

# 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
quelle
Sehr beeindruckend! Ich vermute, Sie erzeugen nicht die ganze Spirale wie andere, oder?
21.
3

MATL , 15 Bytes

2+1YLtG=1Y6Z+g)

Eingang und Ausgang sind 1-basiert.

Die Ausgabe gibt die linken, unteren, oberen und rechten Nachbarn in dieser Reihenfolge an.

Probieren Sie es online! Oder überprüfen Sie alle Testfälle mit Ausnahme der letzten beiden, bei denen eine Zeitüberschreitung bei TIO auftritt.

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
quelle
2
1YL- MATLAB hat eine spiralFunktion? Wann ist MATLAB zu Mathematica geworden ?!
Sundar - Reinstate Monica
Ja, ich habe es nach dem Lesen der Bedeutung von 1YL überprüft. Dieser Rosetta-Code-Eintrag war der einzige Ort, an dem ich bestätigen konnte, dass es sich um eine MATLAB-Sache und nicht nur um eine MATL-Convenience-Funktion handelt. Ich begann zu denken, dass es etwas sein könnte, das Sie MATL zum Golfen hinzugefügt haben, bis ich diesen Eintrag sah.
Sundar - Reinstate Monica
@ Sundar Seltsam, dass es nicht mehr dokumentiert ist
Luis Mendo
3

R , 172 Bytes

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

Probieren Sie es online!

Dies ist R, daher ist die Antwort offensichtlich 0-indiziert.

Der größte Teil der Arbeit ist das Erstellen der Matrix. Code inspiriert von: https://rosettacode.org/wiki/Spiral_matrix#R

ngm
quelle
2

JavaScript (ES6), 165 Byte

Druckt die Indizes mit 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))

Probieren Sie es online!

Wie?

x,yZichx,y

EINx,y=||x|-|y||+|x|+|y|
Sx,y={1,ob yx-1,ob y<x
ichx,y=EINx,y2+(EINx,y+x+y)×Sx,y

(angepasst aus dieser Antwort von math.stackexchange)

Arnauld
quelle
Dies scheint mit kleineren Zahlen gut zu funktionieren, aber ich erhalte eine Fehlermeldung , wenn diese Prüfung mit einer großen Zahl wie 2000 Fehler auf tio.run: RangeError: Maximum call stack size exceededund Fehler in Browser - Konsole: InternalError: too much recursion. Mache ich etwas falsch?
Night2
1
4n2
2

Python 2 , 177 164 1 46 144 Bytes

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]

Probieren Sie es online!

Berechnet u,l,r,ddirekt von n.

Chas Brown
quelle
1

PHP (> = 5,4), 208 Bytes

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

Um es auszuführen:

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

Beispiel:

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

Oder versuchen Sie es online!

Anmerkungen:

  • Die -d error_reporting=0Option wird verwendet, um keine Benachrichtigungen / Warnungen auszugeben.
  • Diese Spirale beginnt mit 1.

Wie?

Ich generiere die Spirale mit einer modifizierten Version dieser Antwort in einem zweidimensionalen Array.

Die Größe der Spirale entscheide ich anhand der Eingabe nmit einer Formel, um immer eine zusätzliche Zahlenrunde in der Spirale zu erhalten (Existenzgarantie für oben / unten / links / rechts). Eine zusätzliche Runde von Zahlen bedeutet +2in der Höhe und +2in der Breite des zweidimensionalen Arrays.

Wenn nsich also eine Spirale mit maximaler Größe von befindet 3*3, dann wird die Spirale erzeugt 5*5.

Spiral Größe ist , c*cwo c = ceil(sqrt(n)) + k, wenn ceil(sqrt(n))ungerade ist, dann k2 ist , und wenn ceil(sqrt(n))gerade ist, dann kist 3.

Die obige Formel ergibt beispielsweise Folgendes:

  • Wenn n = 1dann c = 3und Spiralgröße wird3*3
  • Wenn n <= 9dann c = 5und Spiralgröße wird5*5
  • Wenn n <= 25dann c = 7und Spiralgröße wird7*7
  • Wenn n <= 49dann c = 9und Spiralgröße wird9*9
  • Und so weiter ...

Während der Erzeugung der Spirale speichere ich das xund yvon nund nach der Erzeugung gebe ich die Elemente darüber / darunter / links / rechts davon aus.

Night2
quelle