Somma in ogni dimensione


20

Ti viene data una matrice multidimensionale di numeri interi. Ogni dimensione ha una dimensione fissa (in modo che sia sempre rettangolare se è 2D). Il tuo programma dovrebbe calcolare le somme in ogni dimensione e aggiungere le somme come i nuovi ultimi elementi in quella dimensione.

Supponiamo che gli array di input e output siano A e B e che la dimensione della dimensione i di A sia n i . B avrebbe lo stesso numero di dimensioni come A e la dimensione di dimensione i sarebbe n i +1. B j 1 , j 2 , ..., j m è la somma di A k 1 , k 2 , ..., k m dove:

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

Per l'input:

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

Il tuo programma (o funzione) dovrebbe generare:

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

L'input contiene solo l'array. Il numero totale di dimensioni e le dimensioni di ciascuna dimensione non sono indicati nell'input. (Ma è possibile ottenerli dall'array con il proprio codice.) È possibile utilizzare qualsiasi formato elenco conveniente nella propria lingua, purché non specifichi direttamente il numero di dimensioni o dimensioni.

L'input ha almeno 1 dimensione e almeno 1 elemento nell'array.

Questo è code-golf. Il codice più corto vince.

Casi test

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

Pubblicherai quella soluzione APL a 16 byte? Se non lo farai, posso?
Dennis,

@Dennis Dovresti pubblicarlo.
jimmy23013,

Risposte:


9

J, 14 byte

#@$(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 funzione è equivalente alla seguente (0|:],+/)^:(#@$)ma utilizza un avverbio definito dall'utente per salvare i genitori.

Spiegazione per quest'ultimo codice da destra a sinistra:

  • ^:(#@$)ripetere ^:per il numero #di dimensioni $:

    • ],+/concatenare ,l'argomento ]con la somma dell'ultima dimensione+/
    • 0|:ruota le dimensioni |:mettendo il primo 0alla fine dell'elenco dimensioni
  • Dopo aver eseguito la procedura sopra riportata, si ripristina l'input originale con somme su tutte le dimensioni.

Per la mia soluzione precedente, controlla la cronologia delle revisioni.

Provalo online qui.


15

Mathematica, 32 20 byte

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

Esempio:

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

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

Spiegazione:

La forma completa di {{1, 2, 3}, {4, 5, 6}}è List[List[1, 2, 3], List[4, 5, 6]]. Quindi sostituire tutte le Lists nell'espressione con la funzione ({##,+##}&).


10

Python 2, 95 byte

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

Questo scorre su ogni dimensione, concatenandone le somme usando NumPy.

Mi sono imbattuto in NumPy r_, il che è fantastico per il golf. r_[:n]è più breve di range(n)e molto più potente (ad es r_[:4, 7, 8, 10:100:10].). Può anche fare altre cose come la concatenazione lungo un asse arbitrario.

Esempio di utilizzo:

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

7

APL, 16 15 byte

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

Grazie a @ user23013 per giocare a golf da 3 byte e capire il formato di input corretto.

Verifica i casi di test online con TryAPL .

Idea

L'idea generale è la stessa della mia presentazione CJam, per la quale APL consente un'implementazione molto più breve. Si compone di solo due passaggi:

  1. Somma l'array attraverso la sua dimensione più esterna.

  2. Ripetere il passaggio 1 per ciascun subarray.

Codice

{             } ⍝ 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 ⍵.

Ho appena capito il formato di input per il tuo codice originale: ,⊂(,1)(,1)(,1)(,0)e ,⊂,⊂,⊂,¯1rispettivamente. Quindi puoi rimuovere un altro personaggio.
jimmy23013,

2
@ user23013: Quindi il mio codice ha funzionato! Devi amare un linguaggio di programmazione in cui il formato di input è più difficile da ottenere rispetto al codice reale ...
Dennis

6

Pip , 18 15 byte

{a-a?fMaAE$+aa}

Questa è una funzione anonima, che accetta l'array come argomento e restituisce il risultato. Invocazione di esempio, utilizzando il -pflag per ottenere un output leggibile:

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

L'idea è sostanzialmente la stessa di dell'APL di Dennis , sebbene derivata in modo indipendente. Più specificamente:

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

Questo metodo funziona perché +(insieme a molti altri operatori) funziona in base agli elenchi in Pip - una funzionalità ispirata ai linguaggi di programmazione di array come APL. Quindi, quando ti $+piace un elenco [[1 2 3] [4 5 6]], il risultato è [5 7 9]come desiderato. Utilizzato anche nel test elenco-o-scalare: [1 2 3] - [1 2 3][0 0 0], che è vero (come lo sono tutte le liste tranne la lista vuota).

Versione precedente a 18 byte:

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

I cambiamenti:

  1. Salvataggio di un byte nel test scalare-o-elenco - il metodo precedente era di unire l'argomento (su stringa vuota) e testare se uguale al suo sé non unito (funziona perché [1 2 3] != 123);
  2. Eliminate le parentesi. Sono necessari nell'originale perché hanno Muna precedenza inferiore rispetto a ?(anche se probabilmente lo cambierò, soprattutto ora): senza di essi, il codice analizzerebbe come (Ja=a?af)M(aAE$+a), portando a bizzarri messaggi di errore. Tuttavia, l'argomento centrale di un operatore ternario può essere qualsiasi espressione di qualunque precedenza, senza bisogno di parentesi. Quindi, facendo della lista il caso vero, posso salvare quei due byte.

2
È una lingua interessante che ci sei arrivato. Gli operatori Itemwise mancano in CJam e Pyth.
Dennis,

@Dennis Grazie! È ancora un lavoro in corso, ma ci sono alcune attività che fa abbastanza bene.
DLosc,

5

APL (25)

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

Le matrici di APL hanno dimensioni incorporate, quindi questa è una funzione che accetta una matrice n- dimensionale e quindi somma lungo ogni dimensione.

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

Spiegazione:

  • N←⍵: archivia l'array in N.
  • ⍴⍴N: ottenere la quantità di dimensioni Nha. ( indica le dimensioni, ovvero ⍴↑(1 2 3)(4 5 6)indica 2 3, quindi ⍴⍴indica le dimensioni delle dimensioni.)
  • {... }¨⍳: per ogni numero da 1 a⍴⍴N :
    • +/[⍵]N: somma Nlungo la dimensione
    • N,[⍵]←: unisce il risultato a Nin quella dimensione
  • N: finalmente, ritorna N.

Non riesco a farlo funzionare se l'array contiene singleton. Come chiamereste questa funzione per il terzo o il quarto caso di test?
Dennis,

3
@Dennis: devi passare la funzione in un array multidimensionale. Quello che ↑(1 2 3)(4 5 6)sta facendo è semplicemente costruire un array 2-dimensionale da 2 quelli 1-dimensionali usando . Non è una notazione incorporata e non generalizza il modo in cui potresti pensare. Il modo canonico di costruire il 3o e il 4o array sarebbe 1 4 1⍴1 1 1 0e 1 1 1 1⍴¯1, ma è anche possibile costruirli senza fare riferimento alle dimensioni, ad esempio, il terzo array può anche essere costruito con ↑⍉⍪(,1)(,1)(,1)(,0), il quarto può essere costruito con ↑⍪⊂⍪¯1.
Marinus

OK, questo spiega tutto. La mia ingenua implementazione di un approccio ricorsivo funziona bene per ciò che pensavo fossero array (ad esempio f←{0=≡⍵:⍵⋄f¨⍵,+/⍵}⋄f((1 2)(3 4))((5 6)(7 8))), ma sembra che i vettori e gli array nidificati siano diversi e il primo non differenzi gli scalari dai singleton ...
Dennis

2
@Dennis golfed: {×≡⍵:∇¨⍵,+/⍵⋄⍵}((1 2)(3 4))((5 6)(7 8)). Fisso: {×⍴⍴⍵:∇↓⍵,+/⍵⋄⍵}1 4 1⍴1 1 1 0. Ora è più corto di Mathematica ...
jimmy23013,

3

CJam, 36 byte

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

Questa è una funzione denominata ricorsiva che estrae un array dallo stack e ne lascia uno in cambio.

Prova i casi di test nell'interprete CJam .

Idea

Purtroppo, CJam non ha un operatore automagico che consente di aggiungere array nidificati in modo arbitrario, quindi dobbiamo implementarlo da soli. Fortunatamente, due operatori infix, :(ridurre) e .(vettorializzare), si dimostreranno utili per questo compito.

Il primo passo è il calcolo del numero di dimensioni. Questo è facile: converti l'array nella sua rappresentazione di stringa e conta il numero di [ 's iniziali.

Ora, per ridurre un array di una dimensione, di solito basta eseguire :+:

[1 2] :+ e# Pushes 3.

Per una matrice di due dimensioni, +eseguirà la concatenazione anziché l'aggiunta, quindi dobbiamo vettorializzarla:

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

Ora, per un array di tre dimensioni, .+opererebbe su array di due dimensioni ed eseguirà, ancora una volta, la concatenazione. Questa volta, dobbiamo vettorializzare .+:

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

Per il caso generale, una matrice di dimensione D , dobbiamo concatenare una :, D - 1 . e una +.

Naturalmente, questo somma solo l'array solo attraverso la sua dimensione più estrema. Possiamo risolverlo definendo una funzione S che calcola la dimensione (e non fa nulla se è zero), esegue la somma come indicato sopra e, infine, si applica agli elementi dell'array.

Codice

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

2

Rubino ( 181 139 119 108 byte)

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

Presuppone che l'input sia passato come JSON.


E infatti puoi semplicemente scrivere una funzione che accetta una matrice analizzata e restituisce una matrice, e contare solo i 95 byte per dquesta risposta.
jimmy23013,

2

Java, 669 byte

non mentirò, sono abbastanza orgoglioso di me stesso per questo: 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;}}

ampliato con i test:

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

}

l'esecuzione della versione di prova estesa stampa questo:

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

erm per la versione espansa, la riga: Array.set (risultato, x, sum (Array.get (arrayA, x), Array.get (arrayB, x ++))); nel metodo _sum (...) avrebbe dovuto chiamare _sum (...), non sum (...). mio cattivo
Jack Ammo
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.