Winde mir eine Zahlenschlange!

34

Bei einer gegebenen Eingang ganzer Zahl n, eine Anzahl Schlange zeichnen, die ein Gitter ist die Messung des n x naus den Zahlen 1durch , n^2die um miteinander in der folgenden Art und Weise gewickelt sind:

Eingabe n = 3:

7 8 9
6 1 2
5 4 3

Eingabe n = 4:

 7  8  9 10
 6  1  2 11
 5  4  3 12
16 15 14 13

Eingabe n = 5:

21 22 23 24 25
20  7  8  9 10
19  6  1  2 11
18  5  4  3 12
17 16 15 14 13

(Inspiriert von diesem Problem von Project Euler.)

Das ist , die kürzeste Antwort in Bytes gewinnt!

Julius
quelle
4
Beispiel 4:? Oder eine gerade Zahl.
TheLethalCoder
1
Dürfen wir annehmen, dass die Eingabe ungerade ist?
Mr. Xcoder
1
Related
Emigna
2
Möglicher Betrug ?
Shaggy
1
Siehe auch perlmonks.com/?node_id=487200 mit vielen Lösungen und Links in den Antworten.
b_jonas

Antworten:

43

MATL , 3 Bytes

1YL

Probieren Sie es online!

Erläuterung

Eingebaut ... ¯ \ _ (ツ) _ / ¯

Luis Mendo
quelle
31
Warum ... warum ist das ein eingebautes?
TheLethalCoder
2
Ich vermute, das hat etwas mit dem "Magic Square" -Stoff zu tun?
Magic Octopus Urn
8
@ TheLethalCoder Weil Matlab es hatte und ich dachte, es wäre nützlich ( was es in der Tat ist )
Luis Mendo
18

C # 203 202 196 193 178 Bytes

n=>{var r=new int[n,n];for(int o=n-2+n%2>>1,i=r[o,o]=1,c=2,w=o,h=o,b=1-2*(i%2),j;n>i++;){r[h,w+=b]=c++;for(j=0;j<i-1;++j)r[h+=b,w]=c++;for(j=0;j<i-1;++j)r[h,w-=b]=c++;}return r;}

Dank @StefanDelport ein Byte gespeichert.
22 Bytes dank @FelipeNardiBatista gespeichert.

Dies funktioniert anhand der folgenden Beobachtung, wie die Quadrate aufgebaut sind:

Bild des Quadrats mit n = 5

Wie Sie sehen, wird jedes Bit zum vorherigen Quadrat hinzugefügt. Bei geraden Zahlen gehen wir nach rechts, wo wir waren, runter, bis einer niedriger als der Platz war und dann bis zum Ende. Ungerade Zahlen sind im Wesentlichen das Gegenteil, wir gehen nach links, bis eine über der aktuellen Höhe und dann bis zum Ende.

Voll / Formatierte Version:

using System;
using System.Linq;

class P
{
    static void Main()
    {
        Func<int, int[,]> f = n =>
        {
            var r = new int[n, n];
            for (int o = n - 2 + n % 2 >> 1, i = r[o, o] = 1, c = 2, w = o, h = o, b = 1 - 2 * (i % 2), j; n > i++;)
            {
                r[h, w += b] = c++;

                for (j = 0; j < i - 1; ++j)
                    r[h += b, w] = c++;

                for (j = 0; j < i - 1; ++j)
                    r[h, w -= b] = c++;
            }

            return r;
        };

        Console.WriteLine(String.Join("\n", f(3).ToJagged().Select(line => String.Join(" ", line.Select(l => (l + "").PadLeft(2))))) + "\n");
        Console.WriteLine(String.Join("\n", f(4).ToJagged().Select(line => String.Join(" ", line.Select(l => (l + "").PadLeft(2))))) + "\n");
        Console.WriteLine(String.Join("\n", f(5).ToJagged().Select(line => String.Join(" ", line.Select(l => (l + "").PadLeft(2))))) + "\n");

        Console.ReadLine();
    }
}

public static class ArrayExtensions
{
    public static T[][] ToJagged<T>(this T[,] value)
    {
        T[][] result = new T[value.GetLength(0)][];

        for (int i = 0; i < value.GetLength(0); ++i)
            result[i] = new T[value.GetLength(1)];

        for (int i = 0; i < value.GetLength(0); ++i)
            for (int j = 0; j < value.GetLength(1); ++j)
                result[i][j] = value[i, j];

        return result;
    }
}
TheLethalCoder
quelle
1
++i<=n;kann werden n>++i, nichts anderes kann ich sehen, +1.
LiefdeWen
1
n%2<1?2:1zu 2-x%2? Ich habe es nicht in C # getestet, aber in C und Python hat es funktioniert.
Felipe Nardi Batista
1
for(int o=n-2+n%2>>1,i=r[o,o]=1,c=2,w=o,h=o,j;n>i++;){var b=i%2<1; ....ein bisschen Golf gespielt
Felipe Nardi Batista
@FelipeNardiBatista Awesome hätte nie an diese beiden gedacht! Vielen Dank.
TheLethalCoder
1
var b=1-2*(i%2);r[h,w+=b]=c++;for(j=0;j<i-1;++j)r[h+=b,w]=c++;for(j=0;j<i-1;++j)r[h,w-=b]=c++;
Felipe Nardi Batista
15

Dyalog APL, 70 56 45 41 Bytes

,⍨⍴∘(⍋+\)×⍨↑(⌈2÷⍨×⍨),(+⍨⍴1,⊢,¯1,-)(/⍨)2/⍳

Probieren Sie es online!

Wie?

(+⍨⍴1,⊢,¯1,-)(/⍨)2/⍳

berechnet die Differenzen zwischen den Indizes; 1und ¯1für rechts und links ¯⍵und für oben und unten.

1,⊢,¯1,-Kommt als 1 ⍵ ¯1 ¯⍵, +⍨⍴streckt dieses Array auf die Länge von ⍵×2, so dass das Finale 2/⍳jedes von ihnen wiederholen kann, wobei die Anzahl der Wiederholungen mit jedem zweiten Element zunimmt:

      (1,⊢,¯1,-) 4
1 4 ¯1 ¯4
      (+⍨⍴1,⊢,¯1,-) 4
1 4 ¯1 ¯4 1 4 ¯1 ¯4
      (2/⍳) 4
1 1 2 2 3 3 4 4
      ((+⍨⍴1,⊢,¯1,-)(/⍨)2/⍳) 4
1 4 ¯1 ¯1 ¯4 ¯4 1 1 1 4 4 4 ¯1 ¯1 ¯1 ¯1 ¯4 ¯4 ¯4 ¯4

dann,

(⌈2÷⍨×⍨),

stellt das obere linke Element der Spirale voran,

×⍨↑

begrenzen Sie die ersten ⍵ 2 Elemente dieser Abstandsliste,

+\

führt kumulative Summe,

sortiert die Indizes ( ⍵[i] = ⍵[⍵[i]]), um die ursprüngliche Matrix mit den Indizes jedes Elements zu übersetzen, und schließlich

,⍨⍴

Formen als ⍵×⍵Matrix.

Uriel
quelle
Für Interessierte wird diese Technik in diesem ausgezeichneten Artikel ausführlich besprochen .
Jonah
9

C, 321 307 295 284 283 282 Bytes

Vielen Dank an @Zachary T und @Jonathan Frech für das Golfen eines Bytes!

#define F for(b=a;b--;)l
i,j,k,a,b,m;**l;f(n){n*=n;l=calloc(a=m=3*n,4);F[b]=calloc(m,4);for(l[i=j=n][j]=a=k=1;n>k;++a){F[i][++j]=++k;F[++i][j]=++k;++a;F[i][--j]=++k;F[--i][j]=++k;}for(i=0;i<m;++i,k&&puts(""))for(j=k=0;j<m;)(a=l[i][j++])>0&&a<=n&&printf("%*d ",(int)log10(n)+1,k=a);}

Weist ein zweidimensionales Array von Nullen zu und füllt es dann von einer Stelle in der Mitte aus. Zuletzt werden die Werte gedruckt, die größer als Null, aber kleiner oder gleich dem Quadrat der Eingabe sind.

Probieren Sie es online!

Formatiert:

#define F for(b=a; b--;)l
i, j, k, a, b, m; **l;
f(n)
{
    n *= n;
    l = calloc(a=m=3*n, 4);

    F[b] = calloc(m, 4);

    for(l[i=j=n][j]=a=k=1; n>k; ++a)
    {
        F[i][++j] = ++k;
        F[++i][j] = ++k;
        ++a;

        F[i][--j] = ++k;
        F[--i][j] = ++k;
    }

    for(i=0; i<m; ++i, k&&puts(""))
        for(j=k=0; j<m;)
            (a=l[i][j++])>0 && a<=n && printf("%*d ", (int)log10(n)+1, k=a);
}
Steadybox
quelle
1
Ist es möglich , zu ersetzen , i,j,k,a,b,m;f(n){n*=n;int**l=calloc(a=m=3*n,4);mit i,j,k,a,b,m,**l;f(n){n*=n;l=calloc(a=m=3*n,4);einem Byte speichern?
Zacharý
1
Sie können ersetzen können k<=n;mit n>k;zu speichern ein Byte.
Jonathan Frech
6

PHP , 192 Bytes

for($l=strlen($q=($a=$argn)**2)+$d=1,$x=$y=$a/2^$w=0;$i++<$q;${yx[$w%2]}+=$d&1?:-1,$i%$d?:$d+=$w++&1)$e[$x-!($a&1)][$y]=sprintf("%$l".d,$i);for(;$k<$a;print join($o)."\n")ksort($o=&$e[+$k++]);

Probieren Sie es online!

Auf die gleiche Weise wird eine Zeichenfolge anstelle eines Arrays erstellt

PHP , 217 Bytes

for($l=strlen($q=($a=$argn)**2)+$d=1,$x=$y=($a/2^$w=0)-!($a&1),$s=str_pad(_,$q*$l);$i++<$q;${yx[$w%2]}+=$d&1?:-1,$i%$d?:$d+=$w++&1)$s=substr_replace($s,sprintf("%$l".d,$i),($x*$a+$y)*$l,$l);echo chunk_split($s,$a*$l);

Probieren Sie es online!

Jörg Hülsermann
quelle
1
[-1,1][$d&1]->$d&1?:-1
Titus
@Titus Danke Ich habe es nicht gesehen
Jörg Hülsermann
1
Hier ist ein weiteres Byte: for(;$k<$a;print join($o)."\n")ksort($o=&$e[+$k++]);. Und noch eines: "%$l".d. Und noch eins: $x*$l*$a+$y*$l-> ($x*$a+$y)*$l.
Titus
1
Und ich denke, dass Sie in der zweiten Version $sauf einen gepolsterten Unterstrich (oder Buchstaben oder Ziffern) initialisieren können ; Dieses Zeichen wird überschrieben.
Titus
@Titus Danke und Sie können den .din Ihrem eigenen Ansatz verwenden, um 2 Bytes zu sparen
Jörg Hülsermann
6

PHP, 185 176 174 Bytes

for(;$n++<$argn**2;${xy[$m&1]}+=$m&2?-1:1,$k++<$p?:$p+=$m++%2+$k=0)$r[+$y][+$x]=$n;ksort($r);foreach($r as$o){ksort($o);foreach($o as$i)printf(" %".strlen($n).d,$i);echo"
";}

Laufen Sie als Pipe mit -nRoder testen Sie es online .

Nervenzusammenbruch

for(;$n++<$argn**2;     # loop $n from 1 to N squared
    ${xy[$m&1]}+=$m&2?-1:1, # 2. move cursor
    $k++<$p?:               # 3. if $p+1 numbers have been printed in that direction:
        $p+=$m++%2+             # increment direction $m, every two directions increment $p
        $k=0                    # reset $k
)$r[+$y][+$x]=$n;           # 1. paint current number at current coordinates

ksort($r);              # sort grid by indexes
foreach($r as$o){       # and loop through it
    ksort($o);              # sort row by indexes
    foreach($o as$i)        # and loop through it
        printf(" %".strlen($n).d,$i);   # print formatted number
    echo"\n";               # print newline
}
Titus
quelle
6

APL (Dyalog Classic) , 32 bis 29 Byte

1+×⍨-{⊖∘⌽⍣⍵⌽{⌽⍉,⌸⍵+≢⍵}⍣2⍣⍵⍪⍬}

Probieren Sie es online!

Verwendet ⎕io←1. Beginnt mit einer 0-mal-1-Matrix ( ⍪⍬). 2N times ( ⍣2⍣⍵) fügt die Höhe der Matrix ( ≢⍵) zu jedem ihrer Elemente hinzu, setzt sie 1 2...heightrechts ( ,⌸) und dreht ( ⌽⍉). Wenn dies abgeschlossen ist, korrigiert die Ausrichtung des Ergebnisses ( ⊖∘⌽⍣⍵⌽) und kehrt die Zahlen um, indem sie von N 2 +1 ( 1+×⍨-) subtrahiert werden .

ngn
quelle
5

Mathematica, 177 Bytes

(n=#;i=j=Floor[(n+1)/2];c=1;d=0;v={{1,0},{0,-1},{-1,0},{0,1}};a=Table[j+n(i-1),{i,n},{j,n}];Do[Do[Do[a[[j,i]]=c++;{i,j}+=v[[d+1]], {k,l}];d=Mod[d+1,4],{p,0,1}],{l,n-1}];Grid@a)&
J42161217
quelle
8
Waaait, in Mathematica nicht eingebaut?
Mr. Xcoder
5

C ++, 245 228 Bytes

void f(){for(int i=0,j=-1,v,x,y,a,b;i<n;i++,j=-1,cout<<endl)while(++j<n){x=(a=n%2)?j:n-j-1;y=a?i:n-i-1;v=(b=y<n-x)?n-1-2*(x<y?x:y):2*(x>y?x:y)-n;v=v*v+(b?n-y-(y>x?x:y*2-x):y+1-n+(x>y?x:2*y-x));cout<<setw(log10(n*n)+1)<<v<<' ';}}

Probieren Sie es online!

Die Funktion berechnet und druckt den Wert jeder Zahl der Matrix abhängig von ihrer x-, y- Position, indem sie diese Logik anwendet:

Schlangenwertberechnung je nach Position

Formatierte Version :

#include <iostream>
#include <iomanip>
#include <math.h>

using namespace std;

void f(int n)
{
    for (int i = 0; i < n; i++)
    {
        for (int j = 0; j < n; j++)
        {
            int value = 0;

            // Invert x and y when n is even
            int x = n % 2 == 0 ? n - j - 1 : j;
            int y = n % 2 == 0 ? n - i - 1 : i;
            if (y < (n - x))
            {
                // Left-top part of the matrix
                int padding = x < y ? x : y;
                value = n - 1 - padding * 2;
                value *= value;
                value += y >= x ? n - x - y : n + x - y - (y * 2);
            }
            else
            {
                // Right-bottom part of the matrix
                int padding = x > y ? n - x : n - y;
                value = n - padding * 2;
                value *= value;
                value += x > y ? y - padding + 1 : n + y - x - (padding * 2) + 1;
            }

            cout << setw(log10(n * n) + 1);
            cout << value << ' ';
        }

        cout << endl;
    }
}

int main()
{
    int n;
    while (cin >> n && n > 0)
    {
        f(n);
        cout << endl;
    }
}
Julio E. Rodríguez Cabañas
quelle
5

Python 3 , 249 247 Bytes

Ich initialisiere ein 2D-Array und finde den Startpunkt, der der Mittelpunkt für ungerades n oder der Versatz (-1, -1) für gerades n ist, skaliere dann das Füll- / Cursormuster mit der aktuellen "Ring" -Nummer. Ich habe das Gefühl, dass mir ein Trick für die Interpretation der Anweisungen fehlt, aber ich habe mir nichts Billigeres ausgedacht.

def f(n):
 M=[n*[0]for a in range(n)]
 x=y=n//2-1+n%2
 M[x][y]=i=s=1
 while 1:
  t=s*2
  for d in'R'+'D'*(t-1)+'L'*t+'U'*t+'R'*t:
   if i==n*n:print(*M,sep='\n');return
   v=[1,-1][d in'LU']
   if d in'UD':x+=v
   else:y+=v
   M[x][y]=i=i+1
  s+=1

Probieren Sie es online!

-2 danke an Zachary T!

nocturama
quelle
Wie hast du deine Bytes gezählt? Tabulatoren, Leerzeichen und Zeilenumbrüche zählen auch
Felipe Nardi Batista
Ich habe alle \ n und \ t durch "" ersetzt und ein len () genommen. Ich habe nur das Obige kopiert und es nochmals überarbeitet, um sicherzustellen, dass ich nichts geändert und vergessen habe, es noch einmal zu erzählen, aber ich habe die gleiche Nummer bekommen. Habe ich etwas verpasst?
nocturama
Ich zähle \tund \nals 1 Byte und immer noch 249 Bytes
Felipe Nardi Batista
e: ^^^ Gibt es eine bessere / einfachere Methode, die ich verwenden sollte? sie schienen für mich immer austauschbar zu sein. ^^^ Seltsam, das bekomme ich im LEERLAUF:len("def f(n): M=[n*[0]for a in range(n)] x=y=n//2-(n%2<1) M[x][y]=i=s=1 while 1: t=s*2 for d in'R'+'D'*(t-1)+'L'*t+'U'*t+'R'*t: if i==n*n:print(*M,sep='\n');return v=[1,-1][d in'LU'] if d in'UD':x+=v else:y+=v M[x][y]=i=i+1 s+=1") 223
nocturama
In der Regel teilen Ihnen Texteditoren mit, wie viele Zeichen ausgewählt sind. Halten Sie also STRG + A gedrückt und lesen Sie, was darin steht
Felipe Nardi Batista
5

Wolfram-Sprache (Mathematica) , (...) 83 Bytes

In UTF8 gemessene Bytes \[LeftFloor]( ) und \[RightFloor]( ) kosten jeweils 3 Bytes. Mathematica hat keinen speziellen Byte-Zeichensatz.

Table[Max[4x^2-Max[x+y,3x-y],4y
y-{x+y,3y-x}]+1,{y,b+1-#,b=⌊#/2⌋},{x,b+1-#,b}]&

Probieren Sie es online!


Verwendet das geschlossene Formular für jeden der 4 Fälle und verwendet dann das Maximum, um das gewünschte Ergebnis zu erzielen.

Gibt ein 2D-Array von Ganzzahlen zurück. Ich bin nicht sicher, ob dies zulässig ist, und obwohl dies in den Kommentaren angefragt wurde , antwortete das OP nicht.

user202729
quelle
4

Clojure, 206 Bytes

(defmacro F[s]`(if(~'r(+ ~'p ~'v ~s))~'v ~s))
#(loop[i 1 p(*(quot(dec %)2)(inc %))v 1 r{}](if(<(* % %)i)(partition %(map r(range i)))(recur(inc i)(+ p v)({1(F %)-1(F(- %))%(F -1)(- %)(F 1)}v)(assoc r p i))))

Ich denke, dies ist ein anständiger Anfang, baut das Board nacheinander zu einer Hash-Map auf und partitioniert es dann in n x n Listen. Das defmacroendete ziemlich lang, aber der Code ist immer noch kürzer als ohne. Gibt es eine genauere Syntax, um dies zu beschreiben?

Eine große Anzahl von Bytes berechnet den Startpunkt und erstellt die Nachschlagelogik für die nächste Geschwindigkeit v. Vielleicht wäre ein verschachteltes vecbesser, aber dann haben Sie zwei Indizes und Geschwindigkeiten, die Sie im Auge behalten müssen.

NikoNyrh
quelle
3

J , 41 Bytes

(]|.@|:@[&0](|.@|:@,.*/@$+#\)@]^:[1:)2*<:

Probieren Sie es online!

Entspricht der APL-Übermittlung von ngn , beginnt jedoch mit einer 1-zu-1-Matrix und wird 2 × N-2-mal wiederholt.

FrownyFrog
quelle
Können Sie meinen alternativen Ansatz (jetzt bei 41 gebunden) verbessern , um sich selbst zu schlagen? Bisher habe ich mein Bestes gegeben, aber ich vermute, dass noch ein paar Bytes weggeschabt werden könnten.
Jonah
1

Python 165 (oder 144)

from pylab import *
def S(n):
 a=r_[[[1]]];r=rot90;i=2
 while any(array(a.shape)<n):
  q=a.shape[0];a=vstack([range(i,i+q),r(a)]);i+=q
 if n%2==0:a=r(r(a))
 print(a)

Dadurch wird ein numpy-Array erstellt, dann gedreht und eine Seite hinzugefügt, bis die richtige Größe erreicht ist. In der Frage wurde nicht angegeben, ob derselbe Startpunkt für gerade und ungerade Zahlen verwendet werden muss. Ist dies nicht der Fall, if n%2==0:a=r(r(a))kann die Zeile entfernt werden, wodurch 21 Byte gespart werden.

user2699
quelle
1
Dies ist nicht Python, sondern Python + Numpy
ASCII
@ Nur ASCII Gibt es irgendwo eine Hauptliste mit zulässigen Sprachnamen? Dies ist perfekt gültige Python.
user2699
Es wird eine Bibliothek verwendet, daher müssen Sie auch den Namen der Bibliothek angeben. Für zulässige Sprachen ist jede Sprache mit einer öffentlich verfügbaren Implementierung zulässig, die Sie ausführen können
ASCII.
@ ASCII-only wo steht das ausgeschrieben? Ich habe es mit den meisten Python-Antworten noch nicht gesehen.
user2699
Ja, da die meisten von ihnen kein numpy verwenden ... und die stdlib nicht als externe Bibliothek zählt
ASCII-
0

J , 41 Bytes

,~$[:/:[:+/\_1|.1&,(]##@]$[,-@[)2}:@#1+i.

Standardformatierung

,~ $ [: /: [: +/\ _1 |. 1&, (] # #@] $ [ , -@[) 2 }:@# 1 + i.

Dieser Ansatz basiert auf At Play With J Volutes (Uriels APL verwendet eine ähnliche Technik).

Es ist unerwartet und elegant genug, um eine zweite Antwort zu rechtfertigen, dachte ich.

Grundsätzlich machen wir nichts Prozedurales oder gar Geometrisches. Stattdessen erstellen wir arithmetisch eine einfache Sequenz, die beim Aufsummieren und Skalieren die richtige Reihenfolge der spiralförmigen Zahl von links nach rechts von oben nach unten angibt. Wir formen das dann zu einer Matrix und sind fertig.

Ich werde eine detailliertere Erklärung hinzufügen, wenn es die Zeit erlaubt, aber der verlinkte Artikel erklärt es ausführlich.

Probieren Sie es online!

Jona
quelle
0

Python 3 (ohne Stapel) , 192 188 179 150 Bytes

lambda n:[list(map(v,list(range(t-n,t)),[y]*n))for t in[1+n//2]for y in range(n-t,-t,-1)]
v=lambda x,y,r=0:y>=abs(x)and(3-2*r+4*y)*y+x+1or v(y,-x,r+1)

Probieren Sie es online!

(2y+1)2-(y-x)-2yr

4 Bytes gespart, da eine 90-Grad-Phasendrehung ohne komplexe Zahlen problemlos möglich ist

SmileAndNod
quelle
0

R , 183 Bytes

x=scan()
b=t(d<-1)
while(2*x-1-d){m=max(b)
y=(m+1):(m+sum(1:dim(b)[2]|1))
z=d%%4
if(z==1)b=cbind(b,y)
if(z==2)b=rbind(b,rev(y))
if(z==3)b=cbind(rev(y),b)
if(z==0)b=rbind(y,b)
d=d+1}
b

Probieren Sie es online!

Die Ausgabe ist eine Matrixschlange (oder eine Schlangenmatrix, was auch immer). Es ist wahrscheinlich nicht die effizienteste Methode, und es könnte wahrscheinlich Golf gespielt werden, aber ich dachte, es wäre es wert, gezeigt zu werden. Darauf bin ich eigentlich ziemlich stolz!

Die Methode erstellt die Matrix von innen nach außen und fügt vor dem Anhängen immer eine zusätzliche Anzahl von Ganzzahlen hinzu, die der Anzahl der Spalten in der Matrix entspricht. Das folgende Muster ist entweder spalten- oder zeilengebunden, wobei einige Werte umgekehrt werden, sodass sie in der richtigen Reihenfolge angehängt werden.

193 Bytes

Exakt gleiche wie oben, aber endgültig bheißt

matrix(b,x)

Probieren Sie es online!

Das gibt eine etwas sauberere Ausgabe, aber ich habe keine speziellen Kriterien für die Ausgabe gesehen, daher sollte die erste Antwort funktionieren, wenn ich mich nicht irre.

Sumner18
quelle