Wind me a number snake!


34

Dato un numero intero di ingresso n, disegnare un serpente numero, cioè, una griglia di misura n x ncostituito dai numeri 1attraverso n^2cui avvolte una intorno all'altra nel seguente modo:

Input n = 3:

7 8 9
6 1 2
5 4 3

Input n = 4:

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

Input 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

(Ispirato da questo problema dal Project Euler.)

Questo è , vince la risposta più breve in byte!


4
Esempio 4:? O qualsiasi numero pari.
TheLethalCoder

1
Possiamo supporre che l'input sia strano?
Mr. Xcoder,



1
Vedi anche perlmonks.com/?node_id=487200 con molte soluzioni e collegamenti nelle risposte.
b_jonas,

Risposte:



18

C #, 203 202 196 193 178 byte

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

Salvataggio di un byte grazie a @StefanDelport.
22 byte salvati grazie a @FelipeNardiBatista.

Questo funziona con la seguente osservazione di come sono costruiti i quadrati:

Immagine del quadrato dove n = 5

Come puoi vedere, ogni bit viene aggiunto al quadrato precedente. Per i numeri pari andiamo a destra di dove eravamo, giù fino a quando uno era più in basso rispetto a dove era il quadrato e poi lasciato alla fine. I numeri dispari sono essenzialmente l'opposto, andiamo a sinistra uno, fino a quando uno era sopra l'altezza attuale e poi fino alla fine.

Versione completa / formattata:

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

1
++i<=n;può diventare n>++i, nient'altro che posso vedere, +1.
LiefdeWen

1
n%2<1?2:1a 2-x%2? Non l'ho provato in C #, ma in C e Python ha funzionato.
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; ....golf un po '
Felipe Nardi Batista,

@FelipeNardiBatista Awesome non avrebbe mai pensato a quei due! Grazie.
TheLethalCoder il

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 byte

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

Provalo online!

Come?

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

calcola le differenze tra gli indici; 1e ¯1per destra e sinistra, ¯⍵e per su e giù.

1,⊢,¯1,-arriva come 1 ⍵ ¯1 ¯⍵, +⍨⍴estende questo array per la lunghezza di ⍵×2, in modo che il finale 2/⍳possa ripetere ciascuno di essi, con un conteggio delle ripetizioni che aumenta ogni secondo elemento:

      (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

poi,

(⌈2÷⍨×⍨),

antepone l'elemento in alto a sinistra della spirale,

×⍨↑

limitare i primi ⍵ 2 elementi di questo elenco di distanze,

+\

esegue la somma cumulativa,

classifica gli indici ( ⍵[i] = ⍵[⍵[i]]), per tradurre la matrice originale con gli indici di ogni elemento, e infine

,⍨⍴

forme come una ⍵×⍵matrice.


Per gli interessati, questa tecnica è discussa a lungo in questo eccellente articolo .
Giona,

9

C, 321 307 295 284 283 282 byte

Grazie sia a @Zachary T sia a @Jonathan Frech per aver giocato a golf un byte!

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

Alloca un array bidimensionale di zero, quindi inizia a riempirlo da qualche parte nel mezzo. Infine, vengono stampati i valori maggiori di zero ma inferiori o uguali al quadrato dell'input.

Provalo online!

formattato:

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

1
È possibile sostituire i,j,k,a,b,m;f(n){n*=n;int**l=calloc(a=m=3*n,4);con i,j,k,a,b,m,**l;f(n){n*=n;l=calloc(a=m=3*n,4);per salvare un byte?
Zacharý,

1
Potrebbe essere possibile sostituire k<=n;con n>k;per salvare un byte.
Jonathan Frech,

6

PHP , 192 byte

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++]);

Provalo online!

Allo stesso modo costruisci una stringa anziché un array

PHP , 217 byte

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

Provalo online!


1
[-1,1][$d&1]->$d&1?:-1
Tito,

@Titus Grazie Non l'ho visto
Jörg Hülsermann,

1
Qui è un altro byte: for(;$k<$a;print join($o)."\n")ksort($o=&$e[+$k++]);. E un altro: "%$l".d. E ancora uno: $x*$l*$a+$y*$l-> ($x*$a+$y)*$l.
Tito,

1
E penso che nella seconda versione è possibile inizializzare $sun carattere di sottolineatura imbottito (o lettera o cifra); quel personaggio verrà sovrascritto.
Tito,

@Titus Grazie e puoi usare il .dtuo approccio per salvare 2 byte
Jörg Hülsermann

6

PHP, 185 176 174 byte

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"
";}

Esegui come pipe -nRo testalo online .

abbattersi

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
}

6

APL (Dyalog Classic) , 32 29 byte

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

Provalo online!

Usi ⎕io←1. Inizia con una matrice 0 per 1 ( ⍪⍬). 2N volte ( ⍣2⍣⍵) aggiunge l'altezza della matrice ( ≢⍵) a ciascuno dei suoi elementi, mette 1 2...heighta destra ( ,⌸) e ruota ( ⌽⍉). Al termine, corregge l'orientamento del risultato ( ⊖∘⌽⍣⍵⌽) e inverte i numeri sottraendoli da N 2 +1 ( 1+×⍨-).


5

Mathematica, 177 byte

(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)&

8
Waaait, non è integrato per questo in Mathematica?
Mr. Xcoder,

5

C ++, 245 228 byte

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<<' ';}}

Provalo online!

La funzione calcola e stampa il valore di ciascun numero della matrice in base alla sua posizione x, y applicando questa logica:

Calcolo dei valori del serpente in base alla posizione

Versione formattata :

#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;
    }
}

5

Python 3 , 249 247 byte

Inizializzo un array 2D e trovo il punto iniziale, che è il centro di n dispari o offset (-1, -1) per n pari, quindi ridimensiono il modello di riempimento / cursore con l'attuale numero di "squilli". Sento che mi manca un trucco per interpretare le indicazioni ma non ho trovato niente di più economico.

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

Provalo online!

-2 grazie a Zachary T!


come hai contato i tuoi byte? contano anche le schede, gli spazi e le nuove righe
Felipe Nardi Batista,

Ho sostituito ogni \ n e \ t con "" e ho preso un len (). Ho appena copiato quanto sopra e lo ho rifatto per essere sicuro di non aver cambiato nulla e di dimenticare di raccontare ma ho ottenuto lo stesso numero. Ho dimenticato qualcosa?
nocturama,

sto contando \te \ncome 1 byte e ricevo ancora 249 byte
Felipe Nardi Batista

e: ^^^ esiste un metodo migliore / più semplice che dovrei usare? sembravano sempre essere usati in modo intercambiabile con me. ^^^ Strano, questo è quello che ottengo in IDLE: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

di solito gli editor di testo ti dicono quanti caratteri sono stati selezionati, quindi CTRL + A e leggi cosa dice
Felipe Nardi Batista,

5

Wolfram Language (Mathematica) , (...) 83 byte

Il byte misurato in UTF8, \[LeftFloor]( ) e \[RightFloor]( ) costa 3 byte ciascuno. Mathematica non ha alcun set di caratteri byte speciali.

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

Provalo online!


Utilizza il modulo chiuso per ciascuno dei 4 casi, quindi prende il massimo con attenzione per ottenere il risultato desiderato.

Restituisce un array 2D di numeri interi. Non sono sicuro che ciò sia consentito e, sebbene sia stato chiesto nei commenti , l'OP non ha risposto.


4

Clojure, 206 byte

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

Immagino che questo sia un inizio decente, costruisce la scheda in sequenza su una mappa hash e poi la suddivide in n x nliste. Quelladefmacro finito per essere piuttosto lungo, ma il codice è ancora più breve con esso che senza. Esiste una sintassi più succinta per descriverla?

La massa di byte calcola il punto iniziale e costruisce la logica di ricerca della velocità successiva v. Forse un nidificato vecsarebbe meglio, ma poi hai due indici e velocità da tenere traccia.



1

Python 165 (o 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)

Questo crea un array intorpidito, quindi lo ruota e aggiunge un lato fino a raggiungere la dimensione corretta. La domanda non specifica se è necessario utilizzare lo stesso punto iniziale per i numeri pari e dispari, in caso contrario è if n%2==0:a=r(r(a))possibile rimuovere la riga , risparmiando 21 byte.


1
questo non è Python, è Python + numpy
solo ASCII il

@ Solo ASCII Esiste un elenco principale di nomi di lingue accettabili da qualche parte? Questo è un pitone perfettamente valido.
user2699

Utilizza una libreria, quindi è necessario includere anche il nome della libreria ... Per quanto riguarda le lingue consentite, è consentita qualsiasi lingua con un'implementazione disponibile pubblicamente che è possibile avviare per l'esecuzione
solo ASCII

@ ASCII-solo dove è scritto? Non l'ho visto fatto con la maggior parte delle risposte di Python.
user2699

Sì, perché la maggior parte di loro non usa numpy ... e lo stdlib non conta come libreria esterna
solo ASCII

0

J , 41 byte

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

formattazione standard

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

Questo approccio si basa su At Play With J Volutes (l'APL di Uriel utilizza una tecnica simile).

È abbastanza inaspettato ed elegante da giustificare una seconda risposta, ho pensato.

In sostanza, non facciamo nulla di procedurale o geometrico. Invece, creiamo aritmeticamente una semplice sequenza che, quando la scansione viene sommata e classificata, fornisce l'ordine corretto del numero a spirale da sinistra a destra, dall'alto verso il basso. Lo modelliamo in una matrice e il gioco è fatto.

Aggiungerò una spiegazione più dettagliata quando il tempo lo consente, ma l'articolo collegato lo spiega in modo approfondito.

Provalo online!


0

Python 3 (Stackless) , 192 188 179 150 byte

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)

Provalo online!

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

I 4 byte salvati dalla rotazione del fasore di 90 gradi vengono eseguiti facilmente senza numeri complessi


0

R , 183 byte

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

Provalo online!

L'output è una matrice di serpenti (o matrice di serpenti, qualunque cosa). Probabilmente non è il metodo più efficiente e probabilmente potrebbe essere giocato a golf, ma ho pensato che valesse la pena mostrarlo. Sono piuttosto orgoglioso di questo in realtà!

Il metodo costruisce la matrice dall'interno verso l'esterno, aggiungendo sempre un numero aggiuntivo di numeri interi pari al numero di colonne nella matrice prima di aggiungere. Il modello che segue è vincolante per colonne o per righe, ma allo stesso tempo inverte alcuni valori in modo che vengano aggiunti nell'ordine corretto.

193 byte

Esatto come sopra, ma finale bè

matrix(b,x)

Provalo online!

che fornisce un output leggermente più pulito, ma non ho visto alcun criterio speciale per l'output, quindi la prima risposta dovrebbe funzionare se non sbaglio.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.