Suma en cada dimensión

20

Te dan una matriz multidimensional de enteros. Cada dimensión tiene un tamaño fijo (para que siempre sea rectangular si es 2D). Su programa debe calcular las sumas en cada dimensión y agregar las sumas como los últimos últimos elementos en esa dimensión.

Suponga que las matrices de entrada y salida son A y B, y el tamaño de la dimensión i de A es n i . B tendría el mismo número de dimensiones que A y el tamaño de la dimensión i sería n i +1. B j 1 , j 2 , ..., j m es la suma de A k 1 , k 2 , ..., k m donde:

  • k i = j i si j i <= n i
  • 0 <k i <= n i si j i = n i +1

Para la entrada:

[[1 2 3]
 [4 5 6]]

Su programa (o función) debería generar:

[[1 2 3 6]
 [4 5 6 15]
 [5 7 9 21]]

La entrada contiene solo la matriz. El número total de dimensiones y el tamaño de cada dimensión no se dan en la entrada. (Pero puede obtenerlos de la matriz mediante su propio código). Puede usar cualquier formato de lista conveniente en su idioma, siempre que no especifique el número de dimensiones o tamaños de dimensión directamente.

La entrada tiene al menos 1 dimensión y tiene al menos 1 elemento en la matriz.

Este es el código de golf. El código más corto gana.

Casos de prueba

Input:
[5 2 3]
Output:
[5 2 3 10]

Input:
[[1 2 3] [4 5 6]]
Outputs:
[[1 2 3 6] [4 5 6 15] [5 7 9 21]]

Input:
[[[1] [1] [1] [0]]]
Output:
[[[1 1] [1 1] [1 1] [0 0] [3 3]] [[1 1] [1 1] [1 1] [0 0] [3 3]]]

Input:
[[[[-1]]]]
Output:
[[[[-1 -1] [-1 -1]] [[-1 -1] [-1 -1]]] [[[-1 -1] [-1 -1]] [[-1 -1] [-1 -1]]]]
jimmy23013
fuente
¿Publicará esa solución APL de 16 bytes? Si no quieres, ¿puedo?
Dennis
@ Dennis Deberías publicarlo.
jimmy23013

Respuestas:

9

J, 14 bytes

#@$(0|:],+/^:)

Uso:

   ]a=.i.2 3
0 1 2
3 4 5

   (#@$(0|:],+/^:)) a    NB. parens are optional
0 1 2  3
3 4 5 12
3 5 7 15

La función es equivalente a la siguiente, (0|:],+/)^:(#@$)pero utiliza un adverbio definido por el usuario para salvar a los padres.

Explicación del último código de derecha a izquierda:

  • ^:(#@$)repita ^:para el número #de dimensiones $:

    • ],+/concatenar ,al argumento ]con la suma del mismo en la última dimensión+/
    • 0|:rotar dimensiones |:colocando el primero 0al final de la lista de dimensiones
  • Después de realizar el procedimiento anterior, recuperamos la entrada original con sumas en todas las dimensiones.

Para mi solución anterior, verifique el historial de revisiones.

Pruébelo en línea aquí.

randomra
fuente
15

Mathematica, 32 20 bytes

#/.List->({##,+##}&)&

Ejemplo:

In[1]:= #/.List->({##,+##}&)&[{{1, 2, 3}, {4, 5, 6}}]

Out[1]= {{1, 2, 3, 6}, {4, 5, 6, 15}, {5, 7, 9, 21}}

Explicación:

La forma completa de {{1, 2, 3}, {4, 5, 6}}es List[List[1, 2, 3], List[4, 5, 6]]. Luego reemplace todas las Lists en la expresión con la función ({##,+##}&).

alephalpha
fuente
10

Python 2, 95 bytes

from numpy import*
a=copy(input())
for d in r_[:a.ndim]:a=r_[`d`,a,sum(a,d,keepdims=1)]
print a

Esto itera sobre cada dimensión, concatenando sus sumas usando NumPy.

Me encontré con NumPy's r_, que es bastante impresionante para jugar al golf. r_[:n]es más corto range(n)y mucho más poderoso (p r_[:4, 7, 8, 10:100:10]. ej .). También puede hacer otras cosas como la concatenación a lo largo de un eje arbitrario.

Ejemplo de uso:

$ python sum.py
[[1, 2, 3], [4, 5, 6]]
[[ 1  2  3  6]
 [ 4  5  6 15]
 [ 5  7  9 21]]
grc
fuente
7

APL, 16 15 bytes

{×≡⍵:∇¨⍵,+/⍵⋄⍵}

Gracias a @ user23013 por jugar 3 bytes y descubrir el formato de entrada adecuado.

Verifique los casos de prueba en línea con TryAPL .

Idea

La idea general es la misma que en mi presentación de CJam, para la cual APL permite una implementación mucho más corta. Consta de solo dos pasos:

  1. Suma la matriz en su dimensión más externa.

  2. Repita el paso 1 para cada submatriz.

Código

{             } ⍝ Define a monadic function with argument ⍵ and reference ∇.
 ×≡⍵:           ⍝ If the depth of ⍵ is positive:
     ∇          ⍝   Apply this function...
      ¨         ⍝   to each element of...
       ⍵,       ⍝   the concatenation of ⍵...
         +/⍵    ⍝   and the sum across ⍵.
            ⋄⍵  ⍝  Else, return ⍵.
Dennis
fuente
Acabo de descubrir el formato de entrada para su código original: ,⊂(,1)(,1)(,1)(,0)y ,⊂,⊂,⊂,¯1respectivamente. Entonces puedes eliminar otro personaje.
jimmy23013
2
@ user23013: ¡Entonces mi código funcionó! Tienes que amar un lenguaje de programación donde el formato de entrada es más difícil de entender que el código real ...
Dennis
6

Pip , 18 15 bytes

{a-a?fMaAE$+aa}

Esta es una función anónima, que toma la matriz como argumento y devuelve el resultado. Invocación de muestra, utilizando el -pindicador para obtener una salida legible:

C:\> pip.py -pe "( {a-a?fMaAE$+aa} [[1 2 3] [4 5 6]] )"
[[1;2;3;6];[4;5;6;15];[5;7;9;21]]

La idea es básicamente la misma que la APL de Dennis , aunque derivada de forma independiente. Más específicamente:

{             }  Define a lambda function with parameter a
 a-a?            Shortest way I could find to test whether the argument is a list
                 or scalar: subtracting a number from itself gives 0 (falsy);
                 subtracting a list from itself gives a list of zeros (truthy!)
     fM          If truthy, it's a list, so map the same function (f) recursively to:
       aAE         Argument, with appended element...
          $+a      ...sum of argument (fold on +)
             a   If falsy, it's a scalar, so just return it

Este método funciona porque +(junto con muchos otros operadores) funciona por elementos en las listas de Pip, una característica inspirada en lenguajes de programación de matriz como APL. Entonces, cuando le $+gusta una lista [[1 2 3] [4 5 6]], el resultado es el [5 7 9]deseado. También se usa en la prueba de lista o escalar: [1 2 3] - [1 2 3]da [0 0 0], lo cual es verdadero (como lo son todas las listas excepto la lista vacía).

Versión anterior de 18 bytes:

{Ja=a?a(fMaAE$+a)}

Cambios:

  1. Guardado un byte en la prueba de escalar o lista: el método anterior era unir el argumento (en una cadena vacía) y probar si es igual a su yo no unido (funciona porque [1 2 3] != 123);
  2. Eliminado los paréntesis. Son necesarios en el original porque Mtienen una precedencia menor que ?(aunque probablemente voy a cambiar eso, especialmente ahora): sin ellos, el código se analizaría como (Ja=a?af)M(aAE$+a), lo que llevaría a mensajes de error extraños. Sin embargo, el argumento central de un operador ternario puede ser cualquier expresión de cualquier precedencia, sin paréntesis. Entonces, al hacer que la lista sea el caso verdadero, puedo guardar esos dos bytes.
DLosc
fuente
2
Ese es un lenguaje interesante que tienes allí. Los operadores de artículo son lo que falta en CJam y Pyth.
Dennis
@ Dennis Gracias! Todavía es un trabajo en progreso, pero hay algunas tareas con las que funciona bastante bien.
DLosc
5

APL (25)

{N⊣{N,[⍵]←+/[⍵]N}¨⍳⍴⍴N←⍵}

Las matrices de APL tienen dimensiones incorporadas, por lo que esta es una función que toma una matriz n- dimensional y luego suma a lo largo de cada dimensión.

      {N⊣{N,[⍵]←+/[⍵]N}¨⍳⍴⍴N←⍵} ↑(1 2 3)(4 5 6)
1 2 3  6
4 5 6 15
5 7 9 21

Explicación:

  • N←⍵: almacena la matriz en N.
  • ⍴⍴N: obtener la cantidad de dimensiones que Ntiene. ( da las dimensiones, es decir, ⍴↑(1 2 3)(4 5 6)da 2 3, así ⍴⍴da las dimensiones de las dimensiones).
  • {... }¨⍳: para cada número del 1 al ⍴⍴N:
    • +/[⍵]N: suma a lo Nlargo de la dimensión
    • N,[⍵]←: une el resultado a Nesa dimensión
  • N: finalmente, vuelve N.
marinus
fuente
Parece que no puedo hacer que esto funcione si la matriz contiene singletons. ¿Cómo llamaría a esta función para el tercer o cuarto caso de prueba?
Dennis
3
@Dennis: debe pasar la función a una matriz multidimensional. Lo que ↑(1 2 3)(4 5 6)está haciendo es simplemente construir una matriz bidimensional a partir de 2 unidades unidimensionales usando . No es una notación incorporada y no generaliza la forma en que podría pensar. La forma canónica de construir las matrices tercera y cuarta sería 1 4 1⍴1 1 1 0y 1 1 1 1⍴¯1, pero también es posible construirlas sin hacer referencia a los tamaños, por ejemplo, la tercera matriz también se puede construir con ↑⍉⍪(,1)(,1)(,1)(,0)la cuarta con la que se puede construir ↑⍪⊂⍪¯1.
Marinus
OK, eso lo explica todo. Mi implementación ingenua de un enfoque recursivo funciona bien para lo que pensé que eran matrices (por ejemplo f←{0=≡⍵:⍵⋄f¨⍵,+/⍵}⋄f((1 2)(3 4))((5 6)(7 8))), pero parece que los vectores y matrices anidados son diferentes y el primero no diferencia escalares de singletons ...
Dennis
2
@Dennis golfed: {×≡⍵:∇¨⍵,+/⍵⋄⍵}((1 2)(3 4))((5 6)(7 8)). Fijo: {×⍴⍴⍵:∇↓⍵,+/⍵⋄⍵}1 4 1⍴1 1 1 0. Ahora es más corto que Mathematica ...
jimmy23013
3

CJam, 36 bytes

{_`{'[<}#:D{_":"D'.e]'++~a+{S}%}&}:S

Esta es una función recursiva con nombre que saca una matriz de la pila y deja una a cambio.

Pruebe los casos de prueba en el intérprete de CJam .

Idea

Lamentablemente, CJam no tiene algún operador automático que permita agregar matrices anidadas arbitrariamente, por lo que debemos implementarlo nosotros mismos. Afortunadamente, hace que dos operadores infijos, :(reducir) y .(vectorizar), sean útiles para esta tarea.

El primer paso es calcular el número de dimensiones. Esto es fácil: convierta la matriz en su representación de cadena y cuente el número de [ 's iniciales.

Ahora, para reducir una matriz de una dimensión, generalmente solo ejecuta :+:

[1 2] :+ e# Pushes 3.

Para una matriz de dos dimensiones, +realizaríamos la concatenación en lugar de la suma, por lo que tenemos que vectorizarla:

[[1 2][3 4]] :.+ Pushes [4 6].

Ahora, para una matriz de tres dimensiones, .+operaría en matrices de dos dimensiones y realizaría, una vez más, concatenación. Esta vez, tenemos que vectorizar .+:

[[[1 2][3 4]][[5 6][7 8]]] :..+ e# Pushes [[[6 8] [10 12]]].

Para el caso general, una matriz de dimensión D , tenemos que encadenar uno :, D - 1 . y uno +.

Por supuesto, esto solo suma la matriz solo en su dimensión más externa. Podemos resolver esto definiendo una función S que calcule la dimensión (y no haga nada si es cero), realiza la suma como se indicó anteriormente y, finalmente, se aplica a los elementos de la matriz.

Código

{                                }:S e# Define S:
 _`                                  e#   Push a string representation of a the array.
   {'[<}#                            e#   Find the index of the first non-bracket.
         :D                          e#   Save it in D.
           {                   }&    e#   If D is positive:
            _                        e#     Push a copy of the array.
             ":"D'.e]                e#     Pad ":" with "."s to a string of length D.
                     '++~            e#     Add a "+" to the string and evaluate.
                         a+          e#     Wrap the result in a array and concatenate.
                           {S}%      e#     Apply S to the elements of the array.
Dennis
fuente
2

Rubí ( 181 139 119 108 bytes)

def d a;a.push a[0].to_s['[']?a.map{|x|d x}.transpose.map{|x|x.reduce:+}:a.reduce(:+)end
p d eval ARGF.read

Asume que la entrada se pasa como JSON.

rr-
fuente
Y, de hecho, puede escribir una función que acepte una matriz analizada y devuelva una matriz, y solo cuente los 95 bytes den esta respuesta.
jimmy23013
2

Java, 669 bytes

no voy a mentir, estoy bastante orgulloso de mí mismo por este: p

import java.lang.reflect.Array;enum S{D;<A>A s(A a){int l=Array.getLength(a),x=0;Class t=a.getClass();Class c=t.getComponentType();A r=(A)Array.newInstance(c,l+1);System.arraycopy(a,0,r,0,l);if(t==int[].class)for(;x<l;)((int[])r)[l]=((int[])r)[l]+((int[])r)[x++];else{for(;x<l;)Array.set(r,x,S.this.s(Array.get(r,x++)));Object o=Array.get(r,0);for(;--x>0;)o=s(o,Array.get(r,x));Array.set(r,l,o);}return r;}<A>A s(A a,A b){int l=Array.getLength(a),x=0;Class t=a.getClass();A r=(A)Array.newInstance(t.getComponentType(),l);if(int[].class==t)for(;x<l;)((int[])r)[x]=((int[])a)[x]+((int[])b)[x++];else for(;x<l;)Array.set(r,x,s(Array.get(a,x),Array.get(b,x++)));return r;}}

ampliado con pruebas:

import java.lang.reflect.Array;
import java.util.Arrays;

public enum SumOf{
    Dimensions;

    <A>A sum(A array){ //call this method to solve the challenge
        int length=Array.getLength(array),x=0;
        Class arrayType=array.getClass();
        Class componentType=arrayType.getComponentType();
        //grow the array to include the sum element
        A result=(A)Array.newInstance(componentType,length+1);
        System.arraycopy(array,0,result,0,length);
        if(arrayType==int[].class) //one-dimensional array needs to be handled separately
            for(;x<length;) //find the sum
                ((int[])result)[length]=((int[])result)[length]+((int[])result)[x++];        
        else{ //multi-dimensional array
            for(;x<length;) //find the sum for each element in this dimension's array
                Array.set(result,x,sum(Array.get(result,x++)));
            //find the total sum for this dimension's array
            Object s=Array.get(result,0);
            for(;--x>0;)
                s=_sum(s,Array.get(result,x)); //add the 2 elements together
            Array.set(result,length,s);
        }
        return result;
    }

    <A>A _sum(A arrayA,A arrayB){ //this method is used by the previous method
        int length=Array.getLength(arrayA),x=0;
        Class arrayType=arrayA.getClass();
        A result=(A)Array.newInstance(arrayType.getComponentType(),length);
        if(int[].class==arrayType) //one-dimensional array needs to be handled separately
            for(;x<length;) //find the sum of both arrays
                ((int[])result)[x]=((int[])arrayA)[x]+((int[])arrayB)[x++];
        else
            for(;x<length;) //find the sum of both arrays
                Array.set(result,x,sum(Array.get(arrayA,x),Array.get(arrayB,x++)));
            return result;
        }

    static int[] intArray( int firstElement, int...array ) {
        if( array == null ) array = new int[0];
        array = Arrays.copyOf( array, array.length + 1 );
        System.arraycopy( array, 0, array, 1, array.length - 1 );
        array[0] = firstElement;
        return array;
    }

    static <E> E[] arrayArray( E firstElement, E...array ) {
        if( array == null ) array = (E[]) Array.newInstance( firstElement.getClass(), 0 );
        array = Arrays.copyOf( array, array.length + 1 );
        System.arraycopy( array, 0, array, 1, array.length - 1 );
        array[0] = firstElement;
        return array;
    }

    static void printIntArray( int[]array ){
        System.out.print("[ ");
        for( int x = 0; x < array.length; x++ )
            System.out.print( array[x] + " " );
        System.out.print("] ");
    }

    static < A > void printArray( A array ) {
        if( array.getClass() == int[].class ){
            printIntArray( (int[]) array );
        }
        else {
            System.out.print("[ ");
            int length = Array.getLength( array );
            for( int x = 0; x < length; x++ )
                printArray( Array.get( array, x ) );
            System.out.print("] ");
        }
    }

    public static void main(String[]s){
        int[] test01 = intArray( 5, 2, 3 );
        System.out.print("Input: ");
        printArray( test01 );
        System.out.print("\nOutput: ");
        printArray( SumOf.Dimensions.sum( test01 ) );
        System.out.println();

        int[][] test02 = arrayArray( intArray( 1, 2, 3 ), intArray( 4, 5, 6 ) );
        System.out.print("\nInput: ");
        printArray( test02 );
        System.out.print("\nOutput: ");
        printArray( SumOf.Dimensions.sum( test02 ) );
        System.out.println();

        int[][][] test03 = arrayArray( arrayArray( intArray( 1 ), intArray( 1 ), intArray( 1 ), intArray( 0 ) ) );
        System.out.print("\nInput: ");
        printArray( test03 );
        System.out.print("\nOutput: ");
        printArray( SumOf.Dimensions.sum( test03 ) );
        System.out.println();

        int[][][][] test04 = arrayArray( arrayArray( arrayArray( intArray( -1 ) ) ) );
        System.out.print("\nInput: ");
        printArray( test04 );
        System.out.print("\nOutput: ");
        printArray( SumOf.Dimensions.sum( test04 ) );
        System.out.println();

        int[][][] test05 = arrayArray( arrayArray( intArray( 1, 2, 3 ), intArray( 4, 5, 6 ), intArray( 7, 8, 9 ) ), arrayArray( intArray( 11, 12, 13 ), intArray( 14, 15, 16 ), intArray( 17, 18, 19 ) ), arrayArray( intArray( 21, 22, 23 ), intArray( 24, 25, 26 ), intArray( 27, 28, 29 ) ) );
        System.out.print("\nInput: ");
        printArray( test05 );
        System.out.print("\nOutput: ");
        printArray( SumOf.Dimensions.sum( test05 ) );
        System.out.println();
    }

}

ejecutar la versión de prueba ampliada imprime esto:

Input: [ 5 2 3 ] 
Output: [ 5 2 3 10 ] 

Input: [ [ 1 2 3 ] [ 4 5 6 ] ] 
Output: [ [ 1 2 3 6 ] [ 4 5 6 15 ] [ 5 7 9 21 ] ] 

Input: [ [ [ 1 ] [ 1 ] [ 1 ] [ 0 ] ] ] 
Output: [ [ [ 1 1 ] [ 1 1 ] [ 1 1 ] [ 0 0 ] [ 3 3 ] ] [ [ 1 1 ] [ 1 1 ] [ 1 1 ] [ 0 0 ] [ 3 3 ] ] ] 

Input: [ [ [ [ -1 ] ] ] ] 
Output: [ [ [ [ -1 -1 ] [ -1 -1 ] ] [ [ -1 -1 ] [ -1 -1 ] ] ] [ [ [ -1 -1 ] [ -1 -1 ] ] [ [ -1 -1 ] [ -1 -1 ] ] ] ] 

Input: [ [ [ 1 2 3 ] [ 4 5 6 ] [ 7 8 9 ] ] [ [ 11 12 13 ] [ 14 15 16 ] [ 17 18 19 ] ] [ [ 21 22 23 ] [ 24 25 26 ] [ 27 28 29 ] ] ] 
Output: [ [ [ 1 2 3 6 ] [ 4 5 6 15 ] [ 7 8 9 24 ] [ 12 15 18 45 ] ] [ [ 11 12 13 36 ] [ 14 15 16 45 ] [ 17 18 19 54 ] [ 42 45 48 135 ] ] [ [ 21 22 23 66 ] [ 24 25 26 75 ] [ 27 28 29 84 ] [ 72 75 78 225 ] ] [ [ 33 36 39 108 ] [ 42 45 48 135 ] [ 51 54 57 162 ] [ 126 135 144 405 ] ] ] 
Jack munición
fuente
erm para la versión expandida, la línea: Array.set (result, x, sum (Array.get (arrayA, x), Array.get (arrayB, x ++))); en el método _sum (...) debería haber llamado _sum (...), no sum (...). my bad
Jack Ammo