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!


4
Exemple 4:? Ou n'importe quel nombre pair.
TheLethalCoder

1
Peut-on supposer que l'entrée est étrange?
M. Xcoder



1
Voir également perlmonks.com/?node_id=487200 avec de nombreuses solutions et liens dans les réponses.
b_jonas

Réponses:



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

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.


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

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!


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
}

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+×⍨-).


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

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

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!


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.


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.



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.


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!


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


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.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.