Crie uma matriz piramidal


23

Uma matriz piramidal é uma matriz quadrada em que todos os números aumentam ou diminuem a partir do ponto central, como as duas matrizes abaixo:

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

Dado um número inteiro diferente de zero n, crie uma matriz piramidal onde os números vão de 1para nordem crescente (se n <0) ou ordem decrescente (se n> 0) a partir do centro. Se nfor par, haverá 4 números de centro (veja os exemplos).

Como sempre:

  • Formato opcional de entrada e saída
    • O número de espaços, delimitador etc. é opcional

Casos de teste:

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

10
Por que o caso par é diferente do caso ímpar? Não há razão para que todas as matrizes não possam seguir exatamente o mesmo padrão.
Greg Martin

2
Como a entrada deveria ter o comprimento da parede lateral, nesse caso, há uma diferença entre ímpar e par. Decidi optar pelo valor máximo, mas mantive a diferença ímpar e uniforme lá. Pode parecer estranho e pode não ser uma boa explicação, mas é a explicação para o motivo de haver uma diferença. :-)
Stewie Griffin

2
Podemos assumir -10 < n < 10?
Titus

2
Tudo bem se não parecer um quadrado perfeito, desde que seja um numericamente falando. Se linhas com muitos 10s são maiores que aquelas com poucos 10s, tudo bem ...
Stewie Griffin

Respostas:


5

Geléia , 18 17 bytes

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

Experimente online! ou verifique todos os casos de teste .

Como funciona

|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.

7

EXCEL: 126 bytes

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

Experimente online *

Nota: esta resposta usa a notação R1C1. Se você vai tentar fazer isso sozinho. você precisa ativá-lo nas opções do Excel.

a fórmula dada precisa estar em todas as células presentes além (2,2). Coloque o tamanho desejado da pirâmide em (1,1).

captura de tela rápida da fórmula em ação:
insira a descrição da imagem aqui

Aqui está uma imagem adicional de alguma diversão com formatação condicional!

* Demora muito tempo para atualizar, atualmente.


Isso não lida com os casos negativos ou os casos pares corretamente. Além disso, você pode reduzir o código para =MAX(MIN(MIN(ROW()-1,COLUMN()-1),MIN(((ABS(A1)-1)*2+3)-ROW(),((ABS(A1)-1)*2+3)-COLUMN())),0)92 bytes. No entanto, ele ainda não lida com os casos e a fórmula não pode ser arrastada, pois a referência da célula não está bloqueada.
Gtwebb 22/09

1
Mais golfe mesmos problemas embora. =MEDIAN(MIN(ROW()-1,COLUMN()-1),ABS(A1)*2+1-MAX(ROW(),COLUMN()),0)
Gtwebb 22/09

@ gtwebb obrigado por me dizer. Vou ter que consertar

-1. Isso não funciona. Ele não lida com entrada negativa. Ele não lida nem com entrada. Se você colocar essa fórmula em todas as células aplicáveis, precisará de um Rangeou muito mais do que 126 bytes.
AdmBorkBork 23/09

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]

Criar lista

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

e brinque um pouco com isso.


edit: nova maneira de criar lista + thx Lynn por dois bytes


If n is even, then there will be 4 center numbers
Rod

@ Rod Não, não vai. O que te faz pensar isso?
Pacholik

3
esta é uma das regras
Rod

@Rod Oh. Apenas alguns minutos atrás. Editado.
pacholik 22/09/19

2
Não é novo, não apenas destacou: c
Rod

6

MATL , 26 24 bytes

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

Experimente online! Ou verifique todos os casos de teste (código ligeiramente modificado para servir como suíte de testes).

Explicação

O código primeiro cria a matriz de saída assumindo entrada positiva n. A matriz é inicializada como 1entrada ímpar ou como a matriz vazia para entrada par (isso é criado como uma matriz de identidade com tamanho igual à paridade da entrada). Em seguida, o seguinte é repetido nvezes para entrada par e n-1horas para entrada ímpar: estenda a matriz com um quadro contendo 0e adicione 1a todos os elementos.

Por exemplo, as etapas para entrada nsão:

  • Matriz inicial:

    1
    
  • Estender com moldura:

    0 0 0
    0 1 0
    0 0 0
    
  • Adicionar 1:

    1 1 1
    1 2 1
    1 1 1
    
  • Estender com moldura:

    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
    
  • Adicionar 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
    

Isso fornece a saída correta para entrada positiva. Se a entrada for negativa, a matriz precisará ser modificada adicionando a entrada menos 1e assumindo o valor absoluto:

    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

Você pode assistir a matriz crescendo (código modificado para mostrar etapas intermediárias) em MATL Online! O intérprete ainda é um beta. Se não funcionar, pressione "Executar" novamente ou recarregue a página.

Código comentado

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

Vejo que você reutilizou o código da pergunta sobre animação. Impressionante! O engraçado é que esse código também venceria nessa questão, mesmo que seja mais longo que a sua outra versão;).
Magic Octopus Urn

1
@carusocomputing Sim, é semelhante: duplicata, visor, pause 1 segundo, saída clara :-)
Luis Mendo

Além disso, não sei por que, mas qualquer entrada acima de 14 para às 14. Cancele isso, é uma limitação do console on-line "Operação esgotada".
Magic Octopus Urn

@carusocomputing O erro diz "tempo limite de operação". Acho que leva muito tempo para o intérprete. Tente reduzir a pausa para dizer .2segundos
Luis Mendo

@carusocomputing Sim, esse é o tempo limite do intérprete online. No momento, limitamos os trabalhos a 30 segundos. Como Luis sugere, você pode diminuir o tempo de pausa
Suever 22/09

3

Python 2.7: 123 122 120 bytes

probs ainda podem salvar alguns bytes ...

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)para salvar 1 byte

edit2: (i+1)*(n>0)or-n-ipara salvar 2 bytes


3

Haskell, 119 113 110 104 102 101 bytes

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]

Retorna a matriz como uma lista de listas de números inteiros, por exemplo: f 2->[[1,1,1,1],[1,2,2,1],[1,2,2,1],[1,1,1,1]] .

Como funciona:

            [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

2

Perl, 175 bytes

Inclui 1 bytes para -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;

;

(Existe uma nova linha à direita que eu não sei mostrar com a remarcação, mas você precisa dela).

Necessidades -p, bem como -M5.010ou -Epara executar:

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

Porra, isso é muito longo ... Vou tentar outras abordagens quando tiver algum tempo.


Por que você usa eval?
Titus

@Titus Como y///não interpola, use aspas duplas para interpolar $we $k, em seguida, evalpara executar y///.
Dada

2

Python 2, 109 bytes

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]

2

J, 29 26 bytes

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

Uso

   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

Explicação

O i.verbo intervalo gera [0, 1, ..., n-1]positivo ne [n-1, n-2, ..., 0]negativo, o nque é útil aqui.

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

2

Mathematica, 78 bytes

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

Explicação

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

Faça a matriz inicial: 1x1 se ímpar, 2x2 se for par.

Range[Abs@#-1]

Gere uma lista de 1 a abs (entrada) - 1.

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

Preencher a matriz inicial usando a lista mencionada acima.

... +1~Min~-#

Adicione 1 ou entrada, o que for menor.

Abs

Aplique valor absoluto a toda a matriz.


1

PHP, 177 157 bytes

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

correr com php -r '<code>

circula pelas linhas e colunas, imprime os valores dependendo da distância do centro.

  • $n=abs($z)+1: O +1 Salva algumas +1e -1em expressões posteriores
  • os loops vão de -$n+1(pré-incremento na condição!) a$n-1 ( -abs($z)a abs($z))
  • linha / coluna 0 (e para ímpar $n: 1) são ignoradas
    ( $n&1é verdade para colunas pares aqui! Lembre-se do +1?)
  • A impressão para $ z positivo também se beneficia do +1.

1

Haskell, 191 183 173 169 168 168 bytes

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

Uso:

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]

Obrigado a nimi por 2 10 20 24 bytes!


1
negateé (0-)
nimi

1
Você pode mudar fpara [id!id,tail!init]!!mod n 2e, em seguida, em linha-lo em ge usar a 1<2guarda para vincular um resultado intermediário do ramo: g n| ... |q<-r<$>a n=([id!id,tail!init]!!mod n 2)q$a n. Você não precisa de um nome para a função principal.
nimi

1
Oh, você pode in-line a, também (e voltar para a 1<2guarda): 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
Última para hoje: m=map, em !: ...(++).m ye 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 bytes

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

lé o tamanho da matriz. O n<0?-n-j:j+1parece estranho, mas eu não consigo encontrar nada melhor.


1

Vim, 152 143 bytes

Tenho certeza de que isso poderia ser mais praticado, principalmente nas últimas duas linhas, mas meu cérebro está frito.

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":"")

Experimente online!

Aqui está no formato xxd com caracteres não imprimíveis:

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":"")

Explicação

Ele constrói a pirâmide do centro para fora, cercando o número do centro com xes:

x x x
x 5 x
x x x

Em seguida, substitui xes pelo número seguinte e o envolve xnovamente com 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

...e assim por diante. Para números pares, ele faz a mesma coisa, mas começa com uma base 2x2.

Aqui está o código "ungolfed". É um tanto pouco convencional que eu "grave" uma macro digitando-a em um buffer (daí todos os <C-v>) e excluindo-a em um registro, que é a melhor maneira que encontrei para compor uma macro sem realmente executar as teclas digitadas.

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

0

PHP, 215 bytes

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

0

R, 112 bytes

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

Precisa de número inteiro nna área de trabalho, caso contrário, execute n=scan()por 8 bytes extras.

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
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.