Rellene una matriz con sus sumas

23

Reto:

Dada una matriz de entrada cuadrada A , rellene la matriz con una fila y una columna en los cuatro lados.

  • El valor de cada elemento en la fila superior e inferior debe ser la suma de los elementos en cada columna correspondiente.
  • El valor de cada elemento en la columna izquierda y derecha debe ser la suma de los elementos en cada fila correspondiente.
  • El valor de los elementos en la esquina superior izquierda e inferior derecha debe ser la suma de los elementos en diagonal
  • El valor de los elementos en la esquina superior derecha y en la esquina inferior izquierda debe ser la suma de los elementos en el anti-diagonal.

Ejemplo:

A = 
1   5   3
3   2   4
2   5   5

Output:
 8    6   12   12    7
 9    1    5    3    9
 9    3    2    4    9
12    2    5    5   12
 7    6   12   12    8

Explicación:

Los elementos superior izquierdo e inferior derecho son la suma de la diagonal 1 + 2 + 5 = 8 . Los elementos superior derecho e inferior izquierdo son la suma del antia diagonal 2 + 2 + 3 = 7 .

La fila superior e inferior (excepto las esquinas) son la suma de cada una de las columnas en A : 1 + 3 + 2 = 6 , 5 + 2 + 5 = 12 y 3 + 4 + 5 = 12 . Del mismo modo, la columna izquierda y derecha (excepto las esquinas) son la suma de cada una de las filas de A : 1 + 5 + 3 = 9 , 3 + 2 + 4 = 9 y 2 + 5 + 5 = 12 .

Entrada:

  • Una matriz cuadrada no vacía, con enteros no negativos.
  • Formato opcional

Salida:

  • La matriz acolchada como se explicó anteriormente
  • Formato opcional, pero debe ser el mismo que el formato de entrada

Casos de prueba:

Utilice las presentaciones en este desafío si desea convertir el formato de entrada a uno más adecuado (por ejemplo [[1, 5],[0, 2]]).

0
----------------
0 0 0
0 0 0
0 0 0

1 5
0 2
----------------
3 1 7 5
6 1 5 6
2 0 2 2
5 1 7 3

17   24    1    8   15
23    5    7   14   16
 4    6   13   20   22
10   12   19   21    3
11   18   25    2    9 
----------------
65   65   65   65   65   65   65
65   17   24    1    8   15   65
65   23    5    7   14   16   65
65    4    6   13   20   22   65
65   10   12   19   21    3   65
65   11   18   25    2    9   65
65   65   65   65   65   65   65

15    1    2   12
 4   10    9    7
 8    6    5   11
 3   13   14    0
----------------
30   30   30   30   30   30
30   15    1    2   12   30
30    4   10    9    7   30
30    8    6    5   11   30
30    3   13   14    0   30
30   30   30   30   30   30

Este es el , por lo que gana la solución más corta en cada idioma . Las explicaciones son altamente alentadas.

Stewie Griffin
fuente
2
¿Eso es para verificar cuadrados mágicos?
mdahmoune
Simplemente verificar es un poco más fácil, pero de hecho es fácil ver si un cuadrado es mágico de esta manera, sí :-)
Stewie Griffin

Respuestas:

5

Octava , 64 bytes

¡Gracias a Tom Carpenter por guardar 4 bytes y corregir un error que tuve en el código original!

@(a)[b=(t=@trace)(a),c=sum(a),d=t(flip(a));z=sum(a,2),a,z;d,c,b]

Pruébalo en línea!

Explicación:

@(a)                 % Anonymous function that takes the matrix 'a' as input
 [ ... ]             % Concatenate everything inside to a single matrix
  b=(t=@trace)(a),   % Clever trick by Tom Carpenter. Save a function handle 
                     % for 't=trace', and call it with 'a' as input
                     % Save the result in the variable 'b'
  c=sum(a)           % Sum of all columns of 'a'
  d=t(flip(a));      % Save the trace of 'a' flipped as a variable 'd', while 
                     % concatenating [b,c,d] horizontally at the same time, creating the 
                     % first row of the output
  z=sum(a,2)         % The sum of each row of the input, and store it in a variable 'z'
  ,a,z;              % Concatenate it with 'a' and 'z' again, to create the middle part of the output
 d,c,b]              % Add [d,c,b] to complete the bottom row

Tenga en cuenta que escribí esto mucho después de publicar el desafío.

Stewie Griffin
fuente
4

Jalea , 27 bytes

,UŒDḢ$S$€,Ṛ$j€SW€jSẋ¥€2$j"$

Pruébalo en línea!

Erik el Outgolfer
fuente
2
Quiero saber cómo funciona esto, por favor.
Camarada SparklePony
@ComradeSparklePony No sé si tengo tiempo para escribir una explicación en este momento, lo siento.
Erik the Outgolfer
Está bien, no te preocupes.
Camarada SparklePony
4

MATL , 27 26 bytes

,!tXswyv]GXds5L(PGPXds5L(P

Pruébalo en línea! O verificar todos los casos de prueba .

Explicación

,        % Do the following twice
  !      %   Tranpose. Takes input implititly in the first iteration
  t      %   Duplicate
  Xs     %   Row vector with the sum of each column
  wy     %   Push a copy to the bottom of the stack
  v      %   Concatenate stack vertically. This attaches the sum of
         %   each row (first iteration) and column (second), leaving 
         %   the matrix with the correct orientation (transposed twice)
]        % End
G        % Push input again
Xds      % Column vector with the diagonal of the matrix. Sum of vector
5L(      % Write that into first and last entries of the result matrix
         % matrix; that is, its upper-left and lower-right corners
P        % Flip result matrix vertically
GP       % Push input matrix vertically flipped
Xds      % Diagonal, sum. Since the input has been vertically flipped,
         % this gives the sum of the anti-diagonal of the input.
5L(      % Write that into the upper-left and lower-right corners of
         % the verticallly flipped version of the result matrix
P        % Flip vertically again, to restore initial orientation
         % Implicitly display
Luis Mendo
fuente
Por supuesto, MATL está diseñado para trabajar con matrices a diferencia de Jelly. > _>
Erik the Outgolfer
@EriktheOutgolfer ¡Pero tu respuesta tiene más euros!
Luis Mendo
3
Sí, tiene euros dólares y yenes ... desafortunadamente ese no es el criterio ganador aquí. D:
Erik the Outgolfer
3

APL (Dyalog) , 37 bytes

(d,+⌿,d∘⌽)⍪(+/,⊢,+/)⍪d∘⌽,+⌿,d←+/1 1∘⍉

Pruébalo en línea!

1 1∘⍉ diagonal (iluminado, colapsar ambos ejes en uno)

d← almacenar esa función como d y aplicarla al argumento

+⌿ anteponer las sumas de la columna

d∘⌽, anteponer d aplicado al argumento invertido

()⍪ Apila lo siguiente en la parte superior:

+/,⊢,+/ sumas de fila, el argumento no modificado, sumas de fila

()⍪ Apila lo siguiente en la parte superior:

d,+⌿,d∘⌽ aplicado al argumento, sumas de columnas, d aplicado al argumento invertido

Adán
fuente
3

Jalea , 26 bytes

ŒDµḊṖѵ€1¦ŒḌU
S;;S
Ç€Zµ⁺ÑÑ

Pruébalo en línea!

Parece sorprendentemente diferente de la solución de Erik .

Finalmente logré entender cómo ¦funciona (depurando el código de Jelly, jajaja). Lástima que requiera una para trabajar Çen mi caso.

Explicación

El código usa tres enlaces. El primer enlace auxiliar rellena un vector con su suma en ambos extremos, el segundo enlace auxiliar fija dos esquinas de la matriz y el enlace principal los llama apropiadamente.

Ç€Zµ⁺ÑÑ    Main link. Argument: M (matrix)
Ç            Call the first helper link (pad row with sums)...
 €           ...on each row of the matrix.
  Z          Transpose, so that the second invocation uses the columns.
   µ         Begin a new monadic chain.
    ⁺        Repeat the previous chain (everything up to here).
     ÑÑ      Call the second helper link twice on the whole matrix.

S;;S    First helper link. Argument: v (1-dimensional list)
S         Sum the argument list.
 ;        Append the argument list to the sum.
  ;       Append...
   S      ...the sum of the argument list.

ŒDµḊṖѵ€1¦ŒḌU    Second helper link. Argument: M (matrix)
ŒD                 Get the diagonals of the matrix, starting with the main diagonal.
  µ                Begin a new monadic chain.
      µ€           Perform the following actions on each diagonal...
        1¦         ...and keep the result for the first item (main diagonal):
   Ḋ                 Remove the first item (incorrect top corner).
    Ṗ                Remove the last item (incorrect bottom corner).
     Ñ               Call the first helper link on the diagonal to pad it with its sum.
          ŒḌ       Convert the diagonals back to the matrix.
            U      Reverse each row, so that consecutive calls fix the other corners.
PurkkaKoodari
fuente
3

Python 3 , 155 bytes

Esta es la sugerencia de @LeakyNun, que ahorra 54 bytes . Luego lo jugué un poco.

def f(m):l=len(m);r=range(l);s=sum;b=[s(m[i][i]for i in r)];c=[s(m[i][l+~i]for i in r)];d=[*map(s,zip(*m))];return[b+d+c,*[[s(a),*a,s(a)]for a in m],c+d+b]

Pruébalo en línea!

Solución inicial: Python 3 , 216 bytes

def f(m):l=len(m);r,s=range(l),sum;a,b,c,d=s(m[i][i]for i in r),s(m[i][l-i-1]for i in r),[s(m[i][j]for j in r)for i in r],[s(m[i][j]for i in r)for j in r];print([[a]+d+[b]]+[[c[i]]+m[i]+[c[i]]for i in r]+[[b]+d+[a]])

Pruébalo en línea!

Sr. Xcoder
fuente
162 bytes
Leaky Nun
@LeakyNun Gracias. Estaba actualizando con ~ 190 bytes, esto es mucho más corto: P
Mr. Xcoder
2

Python 2 , 268 250 184 174 bytes

10 gracias a Stewie Griffin

from numpy import *
a,c,v,s=sum,trace,vstack,matrix(input())
l,r,d,e=a(s,0),a(s,1),c(s),c(fliplr(s))
print hstack((v(([[d]],r,[[e]])),v((l,s,l)),v(([[e]],r,[[d]])))).tolist()

Pruébalo en línea!

Algunas explicaciones La entrada se carga como una matriz. Primero, el código calcula la suma de cada columna y cada fila usando numpy.sum. Luego calcula la suma de la diagonal por numpy.trace. Después de esto, obtiene la otra diagonal haciendo un giro de izquierda a derecha en la matriz. Finalmente, usa numpy.vstack y numpy.hstack para unir las piezas.

mdahmoune
fuente
@StewieGriffin Ok, acabo de actualizar el código :)
mdahmoune
1
Creo que esto funciona para 174 tio.run/…
Stewie Griffin
2

R, 129 bytes

pryr::f(t(matrix(c(d<-sum(diag(m)),c<-colSums(m),a<-sum(diag(m[(n<-nrow(m)):1,])),t(matrix(c(r<-rowSums(m),m,r),n)),a,c,d),n+2)))

Una función anónima que toma una matriz cuadrada como entrada. Publicaré una explicación si hay interés.

rturnbull
fuente
2

PHP , 211 bytes

<?foreach($_GET as$l=>$r){$y=0;foreach($r as$k=>$c){$y+=$c;$x[$k]+=$c;$l-$k?:$d+=$c;($z=count($_GET))-1-$k-$l?:$h+=$c;}$o[]=[-1=>$y]+$r+[$z=>$y];}$o[]=[-1=>$h]+$x+[$z=>$d];print_r([-1=>[-1=>$d]+$x+[$z=>$h]]+$o);

Pruébalo en línea!

Expandido

foreach($_GET as$l=>$r){
  $y=0; # sum for a row
  foreach($r as$k=>$c){
    $y+=$c; # add to sum for a row
    $x[$k]+=$c; # add to sum for a column and store in array
    $l-$k?:$d+=$c; # make the diagonal sum left to right
    ($z=count($_GET))-1-$k-$l?:$h+=$c; # make the diagonal sum right to left
  }
  $o[]=[-1=>$y]+$r+[$z=>$y]; # add to result array the actual row with sum of both sides
}
$o[]=[-1=>$h]+$x+[$z=>$d]; # add to result array the last array
print_r([-1=>[-1=>$d]+$x+[$z=>$h]]+$o); #output after adding the first array to the result array
Jörg Hülsermann
fuente
2

Python 3 , 125 bytes

from numpy import*
f=lambda m,t=trace,s=sum:c_[r_[t(m),s(m,1),t(m[::-1])],c_[s(m,0),m.T,s(m,0)].T,r_[t(m[::-1]),s(m,1),t(m)]]

Pruébalo en línea!

Ligeramente incólume:

import numpy as np

def f_expanded(m):
    return np.c_[np.r_[np.trace(m), np.sum(m, 1), np.trace(m[::-1])],
                 np.c_[np.sum(m, 0), m.T, np.sum(m, 0)].T,
                 np.r_[np.trace(m[::-1]), np.sum(m, 1), np.trace(m)]]

Esta toma de entrada formateada como una matriz numpy, a continuación, utiliza los np.c_e np.r_indexación de herramientas para construir una nueva matriz de una sola vez. np.tracey np.sumse usan para calcular las sumas a lo largo de las diagonales y en cualquier otro lugar, respectivamente. Tse usa para tomar la transposición antes y después de concatenar las sumas porque es más corta que hacer que todas las matrices sean bidimensionales y se usen np.r_. m[::-1]guarda bytes en comparación con rot90(m)o fliplr(m)para encontrar la traza para la segunda diagonal.

EFT
fuente
¡Buena respuesta! Bienvenido al sitio :)
DJMcMayhem
1

JavaScript (ES6), 170 bytes

(a,m=g=>a.map((_,i)=>g(i)),s=x=>eval(x.join`+`))=>[[d=s(m(i=>a[i][i])),...c=m(i=>s(m(j=>a[j][i]))),g=s(m(i=>a[i][a.length-i-1]))],...a.map(b=>[r=s(b),...b,r]),[g,...c,d]]

La entrada y salida es una matriz 2D de números.

Explicado

(a,                             // input matrix: a
    m=g=>a.map((_,i)=>g(i)),    // helper func m: map by index
    s=x=>eval(x.join`+`)        // helper func s: array sum
) =>
[
    [
        d = s(m(i=>a[i][i])),           // diagonal sum: d
        ...c=m(i=>s(m(j=>a[j][i]))),    // column sums: c
        g = s(m(i=>a[i][a.length-i-1])) // antidiagonal sum: g
    ],
    ...a.map(b=>[r = s(b), ...b, r]),   // all rows with row sums on each end
    [g, ...c, d]                        // same as top row, with corners flipped
]

Fragmento de prueba

La entrada / salida ha sido formateada con nuevas líneas y pestañas.

f=
(a,m=g=>a.map((_,i)=>g(i)),s=x=>eval(x.join`+`))=>[[d=s(m(i=>a[i][i])),...c=m(i=>s(m(j=>a[j][i]))),g=s(m(i=>a[i][a.length-i-1]))],...a.map(b=>[r=s(b),...b,r]),[g,...c,d]]

let tests=[[[0]],[[1,5],[0,2]],[[17,24,1,8,15],[23,5,7,14,16],[4,6,13,20,22],[10,12,19,21,3],[11,18,25,2,9]],[[15,1,2,12],[4,10,9,7],[8,6,5,11],[3,13,14,0]]];
<select id=S oninput="I.value=S.selectedIndex?tests[S.value-1].map(s=>s.join`\t`).join`\n`:''"><option>Tests<option>1<option>2<option>3<option>4</select> <button onclick="O.innerHTML=I.value.trim()?f(I.value.split`\n`.map(s=>s.trim().split(/\s+/g))).map(s=>s.join`\t`).join`\n`:''">Run</button><br><textarea rows=6 cols=50 id=I></textarea><pre id=O>

Justin Mariner
fuente
0

LOGOTIPO , 198 bytes

to g :v[:h reduce "+ :v]
op(se :h :v :h)
end
to f :s[:a reduce "+ map[item # ?]:s][:b reduce "+ map[item # reverse ?]:s][:c apply "map se "sum :s]
op `[[,:a ,@:c ,:b],@[map "g :s][,:b ,@:c ,:a]]
end

La función ftoma una matriz como una lista 2D, luego genera la matriz resultante. gEs la función auxiliar.

usuario202729
fuente