Soma em cada dimensão

20

Você recebe uma matriz multidimensional de números inteiros. Cada dimensão tem um tamanho fixo (para que seja sempre retangular se for 2D). Seu programa deve calcular as somas em cada dimensão e anexá-las como os novos últimos itens nessa dimensão.

Suponha que as matrizes de entrada e saída sejam A e B, e o tamanho da dimensão i de A seja n i . B teria o mesmo número de dimensões como A e o tamanho da dimensão i seria n i 1. B j 1 , j 2 , ..., j m é a soma de A k 1 , k 2 , ..., k m onde:

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

Para a entrada:

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

Seu programa (ou função) deve gerar:

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

A entrada contém apenas a matriz. O número total de dimensões e o tamanho de cada dimensão não são fornecidos na entrada. (Mas você pode obtê-los da matriz usando seu próprio código.) Você pode usar qualquer formato de lista conveniente no seu idioma, desde que não especifique diretamente o número de dimensões ou tamanhos de dimensão.

A entrada possui pelo menos 1 dimensão e pelo menos 1 item na matriz.

Isso é código-golfe. O menor código vence.

Casos de teste

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
fonte
Você publicará essa solução de 16 bytes de APL? Se você não quiser, posso?
Dennis
@ Dennis Você deve publicá-lo.
Jimmy23013

Respostas:

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

A função é equivalente ao seguinte, (0|:],+/)^:(#@$)mas usa um advérbio definido pelo usuário para salvar parênteses.

Explicação para o último código da direita para a esquerda:

  • ^:(#@$)repita ^:para o número #de dimensões $:

    • ],+/concatenar ,ao argumento ]com a soma dele na última dimensão+/
    • 0|:gire as dimensões |:colocando a primeira 0no final da lista de dimensões
  • Depois de executar o procedimento acima, retornamos a entrada original com somas em todas as dimensões.

Para minha solução mais antiga, verifique o histórico de revisões.

Experimente online aqui.

randomra
fonte
15

Mathematica, 32 20 bytes

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

Exemplo:

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

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

Explicação:

A forma completa de {{1, 2, 3}, {4, 5, 6}}é List[List[1, 2, 3], List[4, 5, 6]]. Em seguida, substitua todas as Lists na expressão com a função ({##,+##}&).

alefalpha
fonte
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

Isso itera sobre cada dimensão, concatenando suas somas usando NumPy.

Tropecei no NumPy's r_, o que é incrível para o golfe. r_[:n]é mais curto range(n)e muito mais poderoso (por exemplo r_[:4, 7, 8, 10:100:10]). Também pode fazer outras coisas, como concatenação ao longo de um eixo arbitrário.

Exemplo de uso:

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

APL, 16 15 bytes

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

Obrigado a @ user23013 por obter 3 bytes de golfe e descobrir o formato de entrada adequado.

Verifique os casos de teste online com o TryAPL .

Idéia

A idéia geral é a mesma da minha submissão ao CJam, para a qual o APL permite uma implementação muito mais curta. Consiste em apenas duas etapas:

  1. Soma a matriz em sua dimensão mais extrema.

  2. Repita a etapa 1 para cada sub-matriz.

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
fonte
Acabei de descobrir o formato de entrada para o seu código original: ,⊂(,1)(,1)(,1)(,0)e ,⊂,⊂,⊂,¯1respectivamente. Então você pode remover outro personagem.
Jimmy23013
2
@ user23013: Então meu código funcionou! Você tem que amar uma linguagem de programação, onde o formato de entrada é mais difícil de acertar do que o código real ...
Dennis
6

Pip , 18 15 bytes

{a-a?fMaAE$+aa}

Essa é uma função anônima, que pega a matriz como argumento e retorna o resultado. Chamada de amostra, usando o -psinalizador para obter saída legível:

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

A idéia é basicamente a mesma do APL de Dennis , embora derivada de forma independente. Mais especificamente:

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

Esse método funciona porque +(junto com muitos outros operadores) funciona item-a-item nas listas do Pip - um recurso inspirado em linguagens de programação de array como APL. Então, quando você $+gosta de uma lista [[1 2 3] [4 5 6]], o resultado é [5 7 9]o desejado. Também usado no teste de lista ou escalar: [1 2 3] - [1 2 3]give [0 0 0], que é verdadeiro (como todas as listas, exceto a lista vazia).

Versão anterior de 18 bytes:

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

Alterar:

  1. Salva um byte no teste escalar-ou-lista - o método anterior era ingressar no argumento (na cadeia vazia) e testar se era igual ao seu não-unido (funciona porque [1 2 3] != 123);
  2. Eliminado os parênteses. Eles são necessários no original porque Mtêm precedência mais baixa do que ?(embora eu provavelmente mude isso, especialmente agora): sem eles, o código seria analisado como (Ja=a?af)M(aAE$+a), levando a mensagens de erro bizarras. No entanto, o argumento do meio de um operador ternário pode ser qualquer expressão de qualquer precedência, sem necessidade de parênteses. Portanto, tornando a lista o caso mais verdadeiro, posso salvar esses dois bytes.
DLosc
fonte
2
Essa é uma linguagem interessante que você chegou lá. Os operadores item a item são o que está faltando no CJam e Pyth.
Dennis
@Dennis Thanks! Ainda é um trabalho em andamento, mas há algumas tarefas com as quais ele se sai muito bem.
DLosc
5

APL (25)

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

As matrizes da APL possuem dimensões internas, portanto, essa é uma função que pega uma matriz n- dimensional e depois soma ao longo de cada dimensão.

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

Explicação:

  • N←⍵: armazena a matriz em N.
  • ⍴⍴N: obtenha a quantidade de dimensões que Npossui. ( fornece as dimensões, ou seja, ⍴↑(1 2 3)(4 5 6)fornece 2 3, ⍴⍴fornece as dimensões das dimensões.)
  • {... }¨⍳: para cada número de 1 a ⍴⍴N:
    • +/[⍵]N: soma Nao longo da dimensão
    • N,[⍵]←: junte o resultado Nnessa dimensão
  • N: finalmente, volte N.
marinus
fonte
Não consigo fazer isso funcionar se a matriz contiver singletons. Como você chamaria essa função para o terceiro ou quarto caso de teste?
Dennis
3
@ Dennis: você precisa passar a função em um array multidimensional. O que ↑(1 2 3)(4 5 6)está fazendo é simplesmente construir uma matriz bidimensional a partir de duas matrizes unidimensionais usando . Não é uma notação incorporada e não generaliza a maneira como você pensa. A maneira canônica de construir as 3ª e 4ª matrizes seria 1 4 1⍴1 1 1 0e 1 1 1 1⍴¯1, mas também é possível construí-las sem se referir aos tamanhos, por exemplo, a terceira matriz também pode ser construída com ↑⍉⍪(,1)(,1)(,1)(,0)a quarta, com a quarta ↑⍪⊂⍪¯1.
Marinus 22/05
OK, isso explica tudo. Minha implementação ingênua de uma abordagem recursiva funciona bem para o que eu achava que eram matrizes (por exemplo f←{0=≡⍵:⍵⋄f¨⍵,+/⍵}⋄f((1 2)(3 4))((5 6)(7 8))), mas parece que os vetores e matrizes aninhadas são diferentes e os primeiros não faz escalares diferenciar de singletons ...
Dennis
2
@ Dennis Golfed: {×≡⍵:∇¨⍵,+/⍵⋄⍵}((1 2)(3 4))((5 6)(7 8)). Fixo: {×⍴⍴⍵:∇↓⍵,+/⍵⋄⍵}1 4 1⍴1 1 1 0. Agora é mais curto que o Mathematica ...
jimmy23013 #
3

CJam, 36 bytes

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

Essa é uma função nomeada recursiva que exibe uma matriz da pilha e deixa uma em retorno.

Experimente os casos de teste no intérprete CJam .

Idéia

Infelizmente, o CJam não possui um operador auto-mágico que permita adicionar matrizes aninhadas arbitrariamente; portanto, temos que implementá-lo nós mesmos. Felizmente, isso faz com que dois operadores de infixo, :(reduzam) e .(vectorizem), serão úteis para esta tarefa.

O primeiro passo é calcular o número de dimensões. Isso é fácil: converta a matriz em sua representação de string e conte o número de [ 's iniciais.

Agora, para reduzir uma matriz de uma dimensão, você normalmente apenas executa :+:

[1 2] :+ e# Pushes 3.

Para uma matriz de duas dimensões, +seria realizada concatenação em vez de adição, portanto, temos que vetorizá-la:

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

Agora, para uma matriz de três dimensões, .+operaria em matrizes de duas dimensões e executaria, mais uma vez, concatenação. Desta vez, temos que vetorizar .+:

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

Para o caso geral, uma matriz de dimensão D , temos que encadear uma :, D - 1 . e uma +.

Obviamente, isso apenas soma o array apenas em sua dimensão mais extrema. Podemos resolver isso definindo uma função S que calcula a dimensão (e não faz nada se for zero), executa a soma conforme indicado acima e, finalmente, aplica-se aos elementos da 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
fonte
2

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

Assume que a entrada é passada como JSON.

rr-
fonte
E, de fato, você pode simplesmente escrever uma função que aceite uma matriz analisada e retorna uma matriz e conte apenas os 95 bytes ddesta resposta.
Jimmy23013
2

Java, 669 bytes

não vou mentir, tenho muito orgulho de mim por esse: 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;}}

expandido com testes:

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

}

executar a versão de teste expandida imprime isto:

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 Ammo
fonte
erm para a versão expandida, a linha: Array.set (result, x, sum (Array.get (arrayA, x), Array.get (arrayB, x ++))); no método _sum (...) deveria ter chamado _sum (...), não soma (...). meu mau
Jack Ammo