Vent moi un serpent numéro!

34

Étant donné un nombre entier d'entrée n, dessiner un serpent de numéro, qui est une grille de mesure se n x ncomposant des nombres à 1travers n^2qui sont enroulés autour de l'autre de la façon suivante:

Entrée n = 3:

7 8 9
6 1 2
5 4 3

Entrée n = 4:

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

Entrée 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

(Inspiré par ce problème de Project Euler.)

C'est , la réponse la plus courte en octets gagne!

Julius
la source
4
Exemple 4:? Ou n'importe quel nombre pair.
TheLethalCoder
1
Peut-on supposer que l'entrée est étrange?
M. Xcoder
1
Connexes
Emigna
2
Dupe possible ?
Shaggy
1
Voir également perlmonks.com/?node_id=487200 avec de nombreuses solutions et liens dans les réponses.
b_jonas

Réponses:

43

MATL , 3 octets

1YL

Essayez-le en ligne!

Explication

Intégré ... ¯ \ _ (ツ) _ / ¯

Luis Mendo
la source
31
Pourquoi ... pourquoi est-ce un construit?
TheLethalCoder
2
Je suppose que cela a quelque chose à voir avec le "Magic Square"?
Urne Magique Octopus
8
@TheLethalCoder Parce que Matlab l'avait et j'ai pensé qu'il serait utile ( ce qui est effectivement le cas )
Luis Mendo
18

C #, 203 202 196 193 178 octets

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

Enregistré un octet grâce à @StefanDelport.
Sauvegardé 22 octets grâce à @FelipeNardiBatista.

Cela fonctionne par l'observation suivante de la façon dont les carrés sont construits:

Image of square where n=5

Comme vous pouvez le constater, chaque bit est ajouté au carré précédent. Pour les nombres égaux, nous allons à droite de l'endroit où nous étions, jusqu'à un niveau inférieur à celui de la place, puis à la fin. Les nombres impairs sont essentiellement l'opposé, nous allons à gauche, jusqu'à un au-dessus de la hauteur actuelle et ensuite jusqu'au bout.

Version complète / formatée:

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
la source
1
++i<=n;peut devenir n>++i, rien d’autre que je peux voir, +1.
LiefdeWen
1
n%2<1?2:1à 2-x%2? Je ne l'ai pas testé en C #, mais en C et Python, cela a fonctionné.
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; ....un peu au golf
Felipe Nardi Batista Le
@ FelipeNardiBatista Awesome n'aurait jamais pensé à ces deux-là! Merci.
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 octets

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

Essayez-le en ligne!

Comment?

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

calcule les différences entre les indices; 1et ¯1pour droite et gauche, ¯⍵et pour monter et descendre.

1,⊢,¯1,-vient comme 1 ⍵ ¯1 ¯⍵, +⍨⍴étend ce tableau à la longueur de ⍵×2, de sorte que le final 2/⍳puisse répéter chacun d'eux, avec un nombre de répétitions augmentant chaque élément sur deux:

      (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

puis,

(⌈2÷⍨×⍨),

préfixe l'élément en haut à gauche de la spirale,

×⍨↑

limiter les ⍵ 2 premiers éléments de cette liste de distances,

+\

effectue la somme cumulée,

gradue les indices ( ⍵[i] = ⍵[⍵[i]]), pour traduire la matrice d'origine avec les indices de chaque élément, et enfin

,⍨⍴

formes comme une ⍵×⍵matrice.

Uriel
la source
Pour les personnes intéressées, cette technique est longuement discutée dans cet excellent article .
Jonah
9

C, 321 307 295 284 283 282 octets

Merci à @Zachary T et @Jonathan Frech pour le golf d'un octet!

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

Alloue un tableau bidimensionnel de zéros, puis commence à le remplir quelque part au milieu. Enfin, les valeurs supérieures à zéro mais inférieures ou égales au carré de l'entrée sont imprimées.

Essayez-le en ligne!

Formaté:

#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
la source
1
Est-il possible de remplacer i,j,k,a,b,m;f(n){n*=n;int**l=calloc(a=m=3*n,4);par i,j,k,a,b,m,**l;f(n){n*=n;l=calloc(a=m=3*n,4);pour sauvegarder un octet?
Zacharý
1
Vous pourrez peut-être remplacer k<=n;par n>k;pour sauvegarder un octet.
Jonathan Frech
6

PHP , 192 octets

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

Essayez-le en ligne!

De la même manière construire une chaîne au lieu d'un tableau

PHP , 217 octets

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

Essayez-le en ligne!

Jörg Hülsermann
la source
1
[-1,1][$d&1]->$d&1?:-1
Titus
@Titus Merci, je ne l'ai pas vu
Jörg Hülsermann le
1
Voici un octet: for(;$k<$a;print join($o)."\n")ksort($o=&$e[+$k++]);. Et l'autre: "%$l".d. Et un de plus: $x*$l*$a+$y*$l-> ($x*$a+$y)*$l.
Tite
1
Et je pense que dans la deuxième version, vous pouvez initialiser $sun trait de soulignement (ou une lettre ou un chiffre) renforcé; ce personnage sera écrasé.
Tite
@ Titus Merci et vous pouvez utiliser .dvotre propre approche pour économiser 2 octets
Jörg Hülsermann
6

PHP, 185 176 174 octets

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

Exécutez en tant que pipe -nRou testez-le en ligne .

panne

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
la source
6

APL (Dyalog Classic) , 32 à 29 octets

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

Essayez-le en ligne!

Utilisations ⎕io←1. Commence avec une matrice 0 par 1 ( ⍪⍬). 2N fois ( ⍣2⍣⍵) ajoute la hauteur de la matrice ( ≢⍵) à chacun de ses éléments, la met 1 2...heightà sa droite ( ,⌸) et effectue une rotation ( ⌽⍉). Lorsque cela est terminé, corrige l'orientation du résultat ( ⊖∘⌽⍣⍵⌽) et inverse les nombres en les soustrayant de N 2 +1 ( 1+×⍨-).

ngn
la source
5

Mathematica, 177 octets

(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
la source
8
Waaait, pas intégré pour cela dans Mathematica?
M. Xcoder
5

C ++, 245 228 octets

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

Essayez-le en ligne!

La fonction calcule et affiche la valeur de chaque nombre de la matrice en fonction de sa position x, y en appliquant cette logique:

Snake values calculation depending on position

Version formatée :

#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
la source
5

Python 3 , 249 247 octets

J'initialise un tableau 2D et trouve le point de départ, qui est le centre de n impair ou d'offset (-1, -1) pour n pair, puis redimensionne le motif de remplissage / curseur avec le numéro actuel de l'anneau. Je sens qu'il me manque un truc pour interpréter les instructions, mais je n'ai rien trouvé de moins cher.

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

Essayez-le en ligne!

-2 grâce à Zachary T!

nocturama
la source
comment avez-vous compté vos octets? les onglets, les espaces et les nouvelles lignes comptent également
Felipe Nardi Batista Le
J'ai remplacé chaque \ n et \ t par "" et ai pris un len (). Je viens de copier ce qui précède et de le refaire pour m'assurer de ne rien changer et d'oublier de raconter mais j'ai le même numéro. Ai-je manqué quelque chose?
nocturama
Je compte \tet en \ntant que 1 octet et obtient toujours 249 octets
Felipe Nardi Batista
e: ^^^ Y a-t-il une méthode meilleure / plus simple que je devrais utiliser? . ils semblaient toujours être utilisés indifféremment pour me ^^^ étrange, ce que je reçois en 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
généralement les éditeurs de texte vous disent combien de caractères sont sélectionnés, donc CTRL + A et lisez ce qui est écrit
Felipe Nardi Batista
5

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

Octet mesuré en UTF8, \[LeftFloor]( ) et \[RightFloor]( ) coûtent 3 octets chacun. Mathematica n'a pas de jeu de caractères octet particulier.

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

Essayez-le en ligne!


Utilise le formulaire fermé pour chacun des 4 cas, puis utilise soigneusement le maximum pour obtenir le résultat souhaité.

Retourne un tableau 2D d'entiers. Je ne sais pas si cela est autorisé, et bien que cela ait été demandé dans les commentaires , le PO n'a pas répondu.

utilisateur202729
la source
4

Clojure, 206 octets

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

Je suppose que c’est un bon début, construit le tableau en séquence en une carte de hachage puis le partitionne en n x nlistes. Cettedefmacro fini par être assez long, mais le code est toujours plus court avec lui que sans. Existe-t-il une syntaxe plus succincte pour la décrire?

De nombreux octets calculent le point de départ et construisent la logique de recherche de la vitesse suivante v. Un niché vecserait peut-être préférable, mais dans ce cas, vous avez deux index et deux vitesses à suivre.

NikoNyrh
la source
3

J , 41 octets

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

Essayez-le en ligne!

Fait la même chose que la soumission APL de ngn mais commence par une matrice 1 par 1 et se répète 2 × N − 2 fois.

FrownyFrog
la source
Pouvez-vous améliorer mon approche alternative (maintenant à égalité à 41 ans) pour vous battre? Jusqu'à présent, j'ai déjà fait de mon mieux, mais je pense qu'au moins quelques octets supplémentaires pourraient être supprimés.
Jonah le
1

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

Cela crée un tableau numpy, puis le fait pivoter et ajoute un côté jusqu'à atteindre la taille correcte. La question ne précisait pas si le même point de départ devait être utilisé pour les nombres pairs et les nombres impairs. Si ce n'est pas le cas, la ligne if n%2==0:a=r(r(a))peut être supprimée, ce qui permet d'économiser 21 octets.

utilisateur2699
la source
1
ce n'est pas Python, c'est Python + numpy
ASCII uniquement
@ ASCII uniquement Y at-il une liste principale de noms de langues acceptables quelque part? Ceci est parfaitement valide python.
user2699
Il utilise une bibliothèque, vous devez donc inclure le nom de la bibliothèque ... ainsi que pour les langues autorisées, toute langue avec une implémentation publique disponible que vous pouvez exécuter est autorisée
ASCII uniquement
@ ASCII seulement où est-ce écrit? Je ne l'ai pas vu faire avec la plupart des réponses python.
user2699
Oui, car la plupart d'entre eux n'utilisent pas numpy ... et stdlib ne compte pas comme une bibliothèque externe
ASCII uniquement
0

J , 41 octets

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

mise en forme standard

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

Cette approche est basée sur At Play With J Volutes (l’APL d’Uriel utilise une technique similaire).

C'est assez inattendu et élégant pour justifier une 2e réponse, pensai-je.

Essentiellement, nous ne faisons rien de procédural ni même de géométrique. Au lieu de cela, nous créons de manière arithmétique une séquence simple qui, une fois numérisée et numérisée, donne le bon ordre du nombre en spirale de gauche à droite, de haut en bas. Nous formons ensuite cela dans une matrice et sommes faits.

J'ajouterai une explication plus détaillée si le temps le permet, mais l'article lié l'explique en profondeur.

Essayez-le en ligne!

Jonas
la source
0

Python 3 (sans pile) , 192 188 179 150 octets

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)

Essayez-le en ligne!

L'algorithme consiste ici à former un phaseur pour chaque coordonnée dans la grille, puis à le faire pivoter de 90 degrés dans le sens des aiguilles d'une montre jusqu'à ce que le phaseur soit situé entre les diagonales supérieures. Une formule simple peut être utilisée pour calculer la valeur en fonction des coordonnées et du nombre de rotations dans le sens des aiguilles d'une montre:

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

4 octets enregistrés car la rotation du phaseur à 90 degrés se fait facilement sans nombres complexes

SmileAndNod
la source
0

R , 183 octets

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

Essayez-le en ligne!

Le résultat est un serpent à matrice (ou une matrice de serpent, peu importe). Ce n'est probablement pas la méthode la plus efficace, et il pourrait probablement être joué au golf, mais j'ai pensé que ça valait la peine de le montrer. Je suis plutôt fier de ça en fait!

La méthode construit la matrice de l'intérieur vers l'extérieur en ajoutant toujours un nombre supplémentaire d'entiers égal au nombre de colonnes de la matrice avant l'ajout. Le modèle qui suit est soit une liaison par colonnes ou par lignes, tout en inversant certaines valeurs afin qu’elles soient ajoutées dans le bon ordre.

193 octets

Exactement comme ci-dessus, mais final best

matrix(b,x)

Essayez-le en ligne!

ce qui donne une sortie légèrement plus propre, mais je n'ai pas vu de critères spéciaux pour la sortie, donc la première réponse devrait fonctionner si je ne me trompe pas.

Sumner18
la source