Créer une matrice pyramidale

23

Une matrice pyramidale est une matrice carrée où tous les nombres augmentent ou diminuent à partir du point central, comme les deux matrices ci-dessous:

1  1  1  1  1
1  2  2  2  1
1  2  3  2  1
1  2  2  2  1
1  1  1  1  1

Ou:

3  3  3  3  3
3  2  2  2  3
3  2  1  2  3
3  2  2  2  3
3  3  3  3  3

Etant donné un nombre entier non nul n, créer une matrice pyramidale où le nombre va de 1à , nsoit dans l' ordre croissant (si n <0), ou un ordre décroissant (si n> 0) à partir du centre. Si nc'est pair, alors il y aura 4 nombres centraux (voir les exemples).

Comme toujours:

  • Format d'entrée et de sortie en option
    • Le nombre d'espaces, délimiteur, etc. est facultatif

Cas de test:

1
1

-1
1

5
1  1  1  1  1  1  1  1  1
1  2  2  2  2  2  2  2  1
1  2  3  3  3  3  3  2  1
1  2  3  4  4  4  3  2  1
1  2  3  4  5  4  3  2  1
1  2  3  4  4  4  3  2  1
1  2  3  3  3  3  3  2  1
1  2  2  2  2  2  2  2  1
1  1  1  1  1  1  1  1  1

-5
5  5  5  5  5  5  5  5  5
5  4  4  4  4  4  4  4  5
5  4  3  3  3  3  3  4  5
5  4  3  2  2  2  3  4  5
5  4  3  2  1  2  3  4  5
5  4  3  2  2  2  3  4  5
5  4  3  3  3  3  3  4  5
5  4  4  4  4  4  4  4  5
5  5  5  5  5  5  5  5  5

2
1  1  1  1
1  2  2  1
1  2  2  1
1  1  1  1

-2
2  2  2  2
2  1  1  2
2  1  1  2
2  2  2  2

-4
4  4  4  4  4  4  4  4
4  3  3  3  3  3  3  4
4  3  2  2  2  2  3  4
4  3  2  1  1  2  3  4
4  3  2  1  1  2  3  4
4  3  2  2  2  2  3  4
4  3  3  3  3  3  3  4
4  4  4  4  4  4  4  4
Stewie Griffin
la source
10
Pourquoi le cas pair est-il différent du cas impair? Il n'y a aucune raison pour que les matrices ne suivent pas toutes exactement le même modèle.
Greg Martin
2
Parce que l'entrée était censée être la longueur de la paroi latérale, auquel cas il y a une différence entre impair et pair. J'ai décidé d'aller à la place pour la valeur maximale, mais j'ai conservé la différence impaire et paire. Cela peut sembler étrange et peut-être pas une bonne explication, mais c'est l'explication de la raison pour laquelle il y a une différence. :-)
Stewie Griffin
2
Pouvons-nous supposer -10 < n < 10?
Titus
2
Ce n'est pas grave s'il ne ressemble pas à un carré parfait, tant qu'il s'agit d'un carré numérique. Si les rangées avec plusieurs 10 sont plus larges que celles avec peu de 10, alors ça va ...
Stewie Griffin

Réponses:

5

Gelée , 18 17 octets

|1ŒḄfR«þ`
AÇạẋ¡CG

Essayez-le en ligne! ou vérifiez tous les cas de test .

Comment ça marche

|1ŒḄfR«þ`  Helper link. Argument: k (positive integer)

|1         Take the bitwise OR with 1. This increments k if it is even.
  ŒḄ       Bounce; yield [1, 2, ..., k | 1, ..., 2, 1].
    fR     Filter range; remove elements not in [1, ..., k] from the array.
           This results in [1, 2, ..., k, ..., 2, 1] if k is odd and in
           [1, 2, ..., k, k, ..., 2, 1] if k is even.
        `  Pass the last return value as left and right argument to:
      «þ     Minimum table; take the minimum of each pair of elements in the
             generated array, returning a 2D array.


AÇạẋ¡CG      Main link. Argument: n

A            Take the absolute value of n.
 Ç           Call the helper link on the result.
     C       Complement; yield 1 - n.
    ¡        Conditional application:
   ẋ           If repeating the return value of Ç 1 - n times results in a non-
               empty array, i.e., if n < 1:
  ạ              Take the absolute differences of the generated integers and 1 - n.
      G      Grid; join columns by spaces, rows by linefeeds.
Dennis
la source
7

EXCEL: 126 octets

=MAX(MIN(MIN(CELL("row",RC)-1,CELL("col",RC)-1),MIN(((ABS(R1C1)-1)*2+3)-CELL("row",RC),((ABS(R1C1)-1)*2+3)-CELL("col",RC))),0)

Essayez-le en ligne *

Remarque: cette réponse utilise la notation R1C1. Si vous allez l'essayer vous-même. vous devez l'activer dans les options Excel.

la formule donnée doit être dans chaque cellule présente au-delà (2,2). Mettez votre taille de pyramide souhaitée dans (1,1).

capture d'écran rapide de la formule en action:
entrez la description de l'image ici

Voici une image supplémentaire de plaisir avec un formatage conditionnel!

* La mise à jour prend actuellement beaucoup de temps.


la source
Cela ne gère pas correctement les cas négatifs ou les cas pairs. Vous pouvez également raccourcir le code =MAX(MIN(MIN(ROW()-1,COLUMN()-1),MIN(((ABS(A1)-1)*2+3)-ROW(),((ABS(A1)-1)*2+3)-COLUMN())),0)qui est de 92 octets. Cependant, il ne gère toujours pas les cas et la formule ne peut pas être glissée car la référence de cellule n'est pas verrouillée.
gtwebb
1
Plus de golf même problèmes cependant. =MEDIAN(MIN(ROW()-1,COLUMN()-1),ABS(A1)*2+1-MAX(ROW(),COLUMN()),0)
gtwebb
@gtwebb merci de me l'avoir dit. Je vais devoir réparer
-1. Ça ne marche pas. Il ne gère pas les entrées négatives. Il ne gère même pas l'entrée. Si vous mettez cette formule dans chaque cellule applicable, vous avez besoin d'un Rangeou de beaucoup plus de 126 octets.
AdmBorkBork
7

Python 2, 109 99 98

n=input()
r=range(1,abs(n)+1)
l=r+r[~n|-2::-1]
for j in l:print[abs((n<0)*~-n+min(i,j))for i in l]

Créer une liste

l = [1,2,3,4,5,4,3,2,1]

et jouer avec un peu.


edit: nouvelle façon de créer une liste + thx Lynn pour deux octets

pacholik
la source
If n is even, then there will be 4 center numbers
Rod
@Rod Non, il n'y en aura pas. Qu'est-ce qui vous fait penser cela?
pacholik
3
c'est l'une des règles
Rod
@Rod Oh. Il y a quelques minutes. Édité.
pacholik
2
Ce n'est pas nouveau, mais pas mis en évidence: c
Rod
6

MATL , 26 24 octets

oXyG|to-:"TTYaQ]G0<?G+q|

Essayez-le en ligne! Ou vérifiez tous les cas de test (code légèrement modifié pour servir de suite de tests).

Explication

Le code construit d'abord le tableau de sortie en supposant une entrée positive n. Le tableau est initialisé comme 1pour une entrée impaire ou comme un tableau vide pour une entrée paire (il est créé comme une matrice d'identité avec une taille égale à la parité de l'entrée). Ensuite, les temps suivants sont répétés npour les entrées paires et les n-1temps pour les entrées impaires: étendez le tableau avec un cadre contenant 0et ajoutez 1à tous les éléments.

Par exemple, les étapes de saisie nsont les suivantes:

  • Tableau initial:

    1
    
  • Étendre avec le cadre:

    0 0 0
    0 1 0
    0 0 0
    
  • Ajouter 1:

    1 1 1
    1 2 1
    1 1 1
    
  • Étendre avec le cadre:

    0 0 0 0 0
    0 1 1 1 0
    0 1 2 1 0
    0 1 1 1 0
    0 0 0 0 0
    
  • Ajouter 1:

    1 1 1 1 1
    1 2 2 2 1
    1 2 3 2 1
    1 2 2 2 1
    1 1 1 1 1
    

Cela donne la sortie correcte pour une entrée positive. Si l'entrée est négative, le tableau doit être modifié en ajoutant l'entrée moins 1et en prenant la valeur absolue:

    3 3 3 3 3
    3 2 2 2 3
    3 2 1 2 3
    3 2 2 2 3
    3 3 3 3 3

Vous pouvez regarder le tableau grandir (code modifié pour afficher les étapes intermédiaires) sur MATL Online! L'interprète est toujours en version bêta. Si cela ne fonctionne pas, appuyez à nouveau sur "Exécuter" ou rechargez la page.

Code commenté

o        % Take input implicitly and push 0 if even or 1 if odd
Xy       % Identity matrix of that size. Gives either 1 or empty array
G|       % Absolute value of input
to-      % Subtract 1 if odd
:"       % For loop: repeat that many times
  TTYa   %   Add a frame of zeros in the two dimensions
  Q      %   Add 1 to all elements
]        % End for
G        % Push input again
0>       % is it negative?
?        % If so
  G      %   Push input again
  +      %   Add
  q      %   Subtract 1
  |      %   Absolute value
         % End if implicitly
         % Display implicitly
Luis Mendo
la source
Je vois que vous avez réutilisé le code de la question d'animation. Impressionnant! Le plus drôle, c'est que ce code gagnerait toujours à cette question, même s'il est plus long que votre autre version;).
Magic Octopus Urn
1
@carusocomputing Oui, c'est similaire: duplication, affichage, pause 1 seconde, sortie claire :-)
Luis Mendo
Aussi, je ne sais pas pourquoi, mais toute entrée au-dessus de 14 s'arrête à 14. Annulez cela, c'est une limitation de la console en ligne "Operation timed out".
Magic Octopus Urn
@carusocomputing L'erreur indique "timeout d'opération". Je suppose que cela prend trop de temps pour l'interprète. Essayez de réduire la pause pour dire les .2secondes
Luis Mendo
@carusocomputing Oui, c'est le délai d'attente sur l'interpréteur en ligne. Nous limitons actuellement les travaux à 30 secondes. Comme le suggère Luis, vous pouvez réduire le temps de pause
Suever
3

Python 2.7: 123 122 120 octets

les probs peuvent encore économiser quelques octets ...

from numpy import*
n=input()
N=abs(n)
e=N*2-N%2
a=ones([e,e])
for i in range(N):a[i:e-i,i:e-i]=(i+1)*(n>0)or-n-i
print a

edit1: N=abs(n)pour économiser 1 octet

edit2: (i+1)*(n>0)or-n-ipour économiser 2 octets

Aaron
la source
3

Haskell, 119 113 110 104 102 101 octets

f x|(h,t)<-splitAt(mod x 2)$[x,x-1..1]++[1.. -x]=foldl(\m n->(n#)<$>(n<$m)#m)[[y]|y<-h]t
x#y=x:y++[x]

Renvoie la matrice sous la forme d'une liste de listes d'entiers, par exemple: f 2-> [[1,1,1,1],[1,2,2,1],[1,2,2,1],[1,1,1,1]].

Comment ça marche:

            [x,x-1..1]++[1.. -x]      -- make list from x down to 1 followed by
                                      -- 1 to (-x). One of the sublists will be
                                      -- empty. The resulting list contains the
                                      -- numbers of the pyramid from inside to out.
   (h,t)<-splitAt(mod x 2)            -- bind h to the first element if x is odd
                                      -- or to the empty list if x is even
                                      -- bind t to the rest (tail or full list)

foldl (     ) [[y]|y<-h] t            -- fold the following function into t with a
                                      -- starting value of [] if x is even or
                                      -- [[h]] if x is odd

   \m n ->                            -- the current matrix m with the next number
                                      -- n is transformed into a new matrix:

               (n#)<$>(n<$m)#m        -- prepend and append a n to 
                                      -- m prepended and append by a line of n's

x#y=x:y++[x]                          -- helper function to prepend and append an
                                      -- element x to a list y
nimi
la source
2

Perl, 175 octets

Comprend 1 octet pour -p .

($t,$v,$w)=($_,(abs)x2);$k=$_.$k for 1..$v;map{$r.=$_ for(@v=1..$_-1),$_ x(2*$v---$w%2),reverse@v;$r.=$/}1..$v;$_=$r.~~reverse$r;eval"y/1-$w/$k/"if$t<0;$w%2&&s/

.*//||s;

;

(Il y a un retour à la ligne que je ne sais pas comment montrer avec la démarque, mais vous en avez besoin).

Besoins -painsi que -M5.010ou -Eà exécuter:

perl -pE '($t,$v,$w)=($_,(abs)x2);$k=$_.$k for 1..$v;map{$r.=$_ for(@v=1..$_-1),$_ x(2*$v---$w%2),reverse@v;$r.=$/}1..$v;$_=$r.~~reverse$r;eval"y/1-$w/$k/"if$t<0;$w%2&&s/

.*//||s;

;
' <<< 5

Merde, c'est trop long ... J'essaierai d'autres approches quand j'aurai du temps.

Dada
la source
Pourquoi utilisez-vous eval?
Titus
@Titus Parce que y///n'interpole pas, il en est de même d'utiliser les guillemets doubles pour interpoler $wet $k, puis evalpour exécuter y///.
Dada
2

Python 2, 109 octets

n=input()
a=abs(n)
s=a*2-a%2
r=range(s)
for y in r:print[(min,max)[n<0](x+1,s-x,y+1,s-y)-(n<0)*s/2for x in r]
Lynn
la source
2

J, 29 26 octets

1+**[:<./~**i.,2&|1&}.i.@-

Usage

   f =: 1+**[:<./~**i.,2&|1&}.i.@-
   f 1
1
   f _1
1
   f 2
1 1 1 1
1 2 2 1
1 2 2 1
1 1 1 1
   f _2
2 2 2 2
2 1 1 2
2 1 1 2
2 2 2 2
   f 3
1 1 1 1 1
1 2 2 2 1
1 2 3 2 1
1 2 2 2 1
1 1 1 1 1
   f _3
3 3 3 3 3
3 2 2 2 3
3 2 1 2 3
3 2 2 2 3
3 3 3 3 3

Explication

Le i.verbe de plage renvoie [0, 1, ..., n-1]pour positif net [n-1, n-2, ..., 0]pour négatif nqui est utile ici.

1+**[:<./~**i.,2&|1&}.i.@-  Input: integer n
                         -  Negate n
                      i.@   Creates range for -n
               2&|          Take n modulo 2, returns 0 or 1
                  1&}.      If n is odd, drop the first value from the range for -n
                            Else do nothing and pass it unmodified
              ,             Append it to
            i.              The range for n
          *                 Get the sign of n
           *                Multiply elementwise with the joined ranges
    [:<./~                  Form a table of the minimum values of the range
  *                         Get the sign of n
   *                        Multiply elementwise with the joined ranges
1+                          Add 1 to each and return
miles
la source
2

Mathematica, 78 octets

Abs[Fold[ArrayPad[#,1,#2]&,Table[0,#,#]&@Mod[#,2,1],Range[Abs@#-1]]+1~Min~-#]&

Explication

Table[0,#,#]&@Mod[#,2,1]

Faire la matrice initiale: 1x1 si impair, 2x2 si pair.

Range[Abs@#-1]

Générez une liste de 1 à abs (entrée) - 1.

Fold[ArrayPad[#,1,#2]&, ..., ...]

Remplissez le tableau initial à l'aide de la liste susmentionnée.

... +1~Min~-#

Ajoutez 1 ou -entrée, la valeur la plus petite étant retenue.

Abs

Appliquez une valeur absolue à la matrice entière.

JungHwan Min
la source
1

PHP, 177 157 octets

for($y=-$n=abs($z=$argv[1])+1;++$y<$n;)if($y&&($n&1||$y-1)){for($x=-$n;++$x<$n;)if($x&&($n&1||$x-1)){$v=max(abs($x),abs($y));echo$z<0?$v:$n-$v," ";}echo"
";}

courir avec php -r '<code>

boucle à travers les lignes et les colonnes, imprime les valeurs en fonction de leur distance au centre.

  • $n=abs($z)+1: Le +1sauve quelques+1-1 expressions et dans des expressions ultérieures
  • les boucles vont de -$n+1(pré-incrémentation de la condition!) à $n-1(-abs($z) àabs($z) )
  • la ligne / colonne 0 (et pour impair $n: 1) sont ignorées
    ($n&1 c'est vrai pour les colonnes paires ici!+1 ?)
  • L'impression pour $ z positif bénéficie également du +1.
Titus
la source
1

Haskell, 191 183 173 169 168 octets

r=reverse;m=map
x!y=(((++)<*>(x.r)).).zipWith(++).m y
g n|n<0=m(m$abs.((n-1)+)).g$abs n|1<2=[id!id,tail!init]!!mod n 2=<<m r$r$m(\x->(x<$[1..x])++[x+1..n])[1..n]
g.(0-)

Usage:

mapM_ print $ (g.(0-)) 3

[1,1,1,1,1]
[1,2,2,2,1]
[1,2,3,2,1]
[1,2,2,2,1]
[1,1,1,1,1]

Merci à nimi pour 2 10 20 24 octets!

BlackCap
la source
1
negateest (0-)
nimi
1
Vous pouvez changer fà [id!id,tail!init]!!mod n 2, puis en ligne dans get utiliser le 1<2garde pour lier un résultat intermédiaire de la branche: g n| ... |q<-r<$>a n=([id!id,tail!init]!!mod n 2)q$a n. Vous n'avez pas besoin d'un nom pour la fonction principale.
nimi
1
Oh, vous pouvez inline aaussi (et retourner à la 1<2garde): g n| ... |1<2=[id!id,tail!init]!!mod n 2=<<map r$r$(\x->(x<$[1..x])++[x+1..n])<$>[1..n].
nimi
1
Dernier pour aujourd'hui: m=mapen !: ...(++).m yet g: g n|n<0=m(m(abs.((n-1)+)))$g$abs n|1<2=[id!id,tail!init]!!mod n 2=<<m r$r$m(\x->(x<$[1..x])++[x+1..n])[1..n].
nimi
1

JavaScript (ES6), 107 octets

(n,l=Math.abs(n+n-n%2))=>[...Array(l--)].map((_,i,a)=>a.map((_,j)=>(j=Math.min(i,l-i,j,l-j),n<0?-n-j:j+1)))

lest la taille du tableau. Le n<0?-n-j:j+1semble bizarre , mais je ne peux pas trouver mieux.

Neil
la source
1

Vim, 152 143 octets

Je suis sûr que cela pourrait être joué davantage, en particulier ces deux dernières lignes, mais mon cerveau est frit.

D:let@z=@-/abs(@-)
a"nywYp:s/\d/x/g<C-v>
YggP:%s/.*/x \0 x<C-v>
:%s/x\+/\=@n-@z/g<C-v>
<Esc>v0"qda<C-r>=@z<0?1:@-*@z
<Esc>@=@-%2?"":"YPJYp"
@=@-*@z-1.(@-*@z>1?"@q":"")

Essayez-le en ligne!

Le voici au format xxd avec des caractères non imprimables:

0000000: 443a 6c65 7440 7a3d 402d 2f61 6273 2840  D:let@z=@-/abs(@
0000010: 2d29 0a61 226e 7977 5970 3a73 2f5c 642f  -).a"nywYp:s/\d/
0000020: 782f 6716 0a59 6767 503a 2573 2f2e 2a2f  x/g..YggP:%s/.*/
0000030: 7820 5c30 2078 160a 3a25 732f 785c 2b2f  x \0 x..:%s/x\+/
0000040: 5c3d 406e 2d40 7a2f 6716 0a1b 7630 2271  \=@n-@z/g...v0"q
0000050: 6461 123d 407a 3c30 3f31 3a40 2d2a 407a  da.=@z<0?1:@-*@z
0000060: 0a1b 403d 402d 2532 3f22 223a 2259 504a  ..@=@-%2?"":"YPJ
0000070: 5970 220a 403d 402d 2a40 7a2d 312e 2840  Yp".@=@-*@z-1.(@
0000080: 2d2a 407a 3e31 3f22 4071 223a 2222 29    -*@z>1?"@q":"")

Explication

Il construit la pyramide du centre vers l'extérieur, entourant le numéro du centre avec xes:

x x x
x 5 x
x x x

Ensuite, il remplace l' xes par le numéro suivant et l'entoure à xnouveau d'es:

x x x x x
x 4 4 4 x
x 4 5 4 x
x 4 4 4 x
x x x x x

...etc. Pour les nombres pairs, il fait la même chose mais commence par une base 2x2.

Voici le code "non golfé". C'est quelque peu inhabituel dans la mesure où j'enregistre une macro en la tapant dans un tampon (d'où tous les <C-v>s) puis en la supprimant dans un registre, ce qui est le meilleur moyen que j'ai trouvé pour composer une macro sans réellement exécuter les frappes.

D:let@z=@-/abs(@-)<CR>       " Delete the input (into @-) and set @z to -1 if @- is negative; otherwise 1
a                            " Enter insert mode to compose the macro
  "nyw                         " Copy the number under the cursor to @n
  Yp                           " Copy this line and paste it below
  :s/\d/x/g<C-v><CR>           " Replace digits in the copy with 'x'
  YggP                         " Copy this line and paste it at the top of the buffer
  :%s/.*/x \0 x<C-v><CR>       " Add an 'x' before and after each line
  :%s/x\+/\=@n-@z/g<C-v><CR>   " Replace all 'x'es (and 'xx'es etc.) with the next number
<Esc>v0"qd                   " Done composing macro; delete it into @q (buffer is now empty)
a<C-r>=@z<0?1:@-*@z          " Append the center number (1 or abs(@-)) to the buffer
<Esc>@=@-%2?"":"YPJYp"       " If the input is even, make a 2x2 square
@=@-*@z-1.(@-*@z>1?"@q":"")  " Execute the macro abs(@-)-1 times if it's > 1
Jordan
la source
0

PHP, 215 octets

for($i=0;$i<$m=($r=($s=abs($n=$argv[1]))*2-$s%2)**2;){$i%$r?:print"\n";$l=min(($x=$i%$r+1)<$s?$x:$x=$r-$x+1,($z=1+floor($i++/$r))<$s?$z:$z=$r-$z+1);$o=($n>0)?$l:$s+1-$l;echo str_pad(" ",1+strlen($s)-strlen($o)).$o;}
Jörg Hülsermann
la source
0

R, 112 octets

k=abs(n);l=2*k;m=diag(l);for(i in 1:k){m[i:(l+1-i),i:(l+1-i)]=i};if(n%%2==1){m=m[-k,-k]};if(n<0){m=abs(m-1+n)};m

Nécessite un entier ndans l'espace de travail, sinon exécutez n=scan()pour 8 octets supplémentaires.

k=abs(n)
l=2*k
m=diag(l)                    # Initialize quadratic 2*|n| matrix
for(i in 1:k){
    m[i:(l+1-i),i:(l+1-i)]=i # Assign values to matrix elements according
                             # to their index
}
if(n%%2==1){
   m=m[-k,-k]                # If n is odd, delete middle row and column
}
if(n<0){
    m=abs(m-1+n)             # If n < 0, flip values
}
m                            # Print matrix
Coup de tête
la source