Summe in jeder Dimension

20

Sie erhalten ein mehrdimensionales Array von ganzen Zahlen. Jede Bemaßung hat eine feste Größe (so dass sie bei 2D immer rechteckig ist). Ihr Programm sollte die Summen in jeder Dimension berechnen und die Summen als die neuen letzten Elemente in dieser Dimension anhängen.

Angenommen, die Eingabe- und Ausgabearrays sind A und B und die Größe der Dimension i von A ist n i . B hätte die gleiche Anzahl von Dimensionen wie A und die Größe der Dimension i wäre n i +1. B j 1 , j 2 , ..., j m ist die Summe von A k 1 , k 2 , ..., k m wobei:

  • k i = j i wenn j i <= n i
  • 0 <k i <= n i, wenn j i = n i +1

Für die Eingabe:

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

Ihr Programm (oder Ihre Funktion) sollte Folgendes ausgeben:

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

Die Eingabe enthält nur das Array. Die Gesamtanzahl der Dimensionen und die Größe jeder Dimension werden in der Eingabe nicht angegeben. (Sie können sie jedoch über Ihren eigenen Code aus dem Array abrufen.) Sie können beliebige Listenformate in Ihrer Sprache verwenden, sofern darin nicht die Anzahl der Dimensionen oder Dimensionsgrößen direkt angegeben ist.

Die Eingabe hat mindestens eine Dimension und mindestens ein Element im Array.

Das ist Code-Golf. Kürzester Code gewinnt.

Testfälle

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
quelle
Veröffentlichen Sie diese 16-Byte-APL-Lösung? Wenn nicht, kann ich?
Dennis
@ Tennis Du solltest es posten.
Jimmy23013

Antworten:

9

J, 14 Bytes

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

Verwendung:

   ]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

Die Funktion entspricht der folgenden (0|:],+/)^:(#@$), verwendet jedoch ein benutzerdefiniertes Adverb zum Speichern von Parens.

Erklärung für letzteren Code von rechts nach links:

  • ^:(#@$)Wiederholen Sie dies ^:für die Anzahl #der Dimensionen $:

    • ],+/Verketten Sie ,das Argument ]mit der Summe in der letzten Dimension+/
    • 0|:drehen Sie die Dimensionen, |:indem Sie die erste 0an das Ende der Dimensionsliste setzen
  • Nach dem oben beschriebenen Vorgang erhalten wir die ursprüngliche Eingabe mit Summen für alle Dimensionen zurück.

Überprüfen Sie für meine ältere Lösung den Versionsverlauf.

Probieren Sie es hier online aus.

randomra
quelle
15

Mathematica, 32 20 Bytes

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

Beispiel:

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

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

Erläuterung:

Die vollständige Form von {{1, 2, 3}, {4, 5, 6}}ist List[List[1, 2, 3], List[4, 5, 6]]. Ersetzen Sie dann alle Lists im Ausdruck durch die Funktion ({##,+##}&).

Alephalpha
quelle
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

Dies durchläuft jede Dimension und verknüpft ihre Summen mit NumPy.

Ich bin über NumPy's gestolpert r_, was zum Golfen ziemlich genial ist. r_[:n]ist kürzer als range(n)und viel mächtiger (zB r_[:4, 7, 8, 10:100:10]). Es kann auch andere Dinge tun, wie die Verkettung entlang einer beliebigen Achse.

Anwendungsbeispiel:

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

APL, 16-15 Bytes

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

Vielen Dank an @ user23013 für das Golfen mit 3 Bytes und das Herausfinden des richtigen Eingabeformats.

Überprüfen Sie die Testfälle online mit TryAPL .

Idee

Die allgemeine Idee ist dieselbe wie in meiner CJam-Einreichung, für die APL eine viel kürzere Implementierung zulässt. Es besteht aus nur zwei Schritten:

  1. Summieren Sie das Array über seine äußerste Dimension.

  2. Wiederholen Sie Schritt 1 für jedes Subarray.

Code

{             } ⍝ 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
quelle
Heraus nur das Eingabeformat für Ihren ursprünglichen Code: ,⊂(,1)(,1)(,1)(,0)und ,⊂,⊂,⊂,¯1jeweils. So können Sie ein anderes Zeichen entfernen.
Jimmy23013
2
@ user23013: Also mein Code hat funktioniert! Sie müssen eine Programmiersprache lieben, in der das Eingabeformat schwieriger zu finden ist als der eigentliche Code ...
Dennis
6

Pip , 18-15 Bytes

{a-a?fMaAE$+aa}

Dies ist eine anonyme Funktion, die das Array als Argument verwendet und das Ergebnis zurückgibt. Beispielaufruf unter Verwendung des -pFlags, um eine lesbare Ausgabe zu erhalten:

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

Die Idee ist im Grunde die gleiche wie bei Dennis 'APL , obwohl sie unabhängig abgeleitet wurde. Genauer:

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

Diese Methode funktioniert, weil +(zusammen mit vielen anderen Operatoren) Listen in Pip elementweise bearbeitet werden - eine Funktion, die von Array-Programmiersprachen wie APL inspiriert ist. Wenn Sie also $+eine Liste mögen [[1 2 3] [4 5 6]], ist das Ergebnis [5 7 9]wie gewünscht. Wird auch im Listen- oder Skalartest verwendet : [1 2 3] - [1 2 3]gives [0 0 0], was wahr ist (wie alle Listen mit Ausnahme der leeren Liste).

Vorherige 18-Byte-Version:

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

Änderungen:

  1. Beim Skalar- oder Listentest wurde ein Byte gespeichert. Die vorherige Methode bestand darin, das Argument (in einer leeren Zeichenfolge) zu verknüpfen und zu testen, ob es dem nicht verknüpften Selbst entspricht (funktioniert, weil [1 2 3] != 123).
  2. Beseitigte die Klammern. Sie sind im Original notwendig, weil sie Meine niedrigere Priorität haben als ?(obwohl ich das wahrscheinlich gerade jetzt ändern werde): Ohne sie würde der Code als analysiert (Ja=a?af)M(aAE$+a), was zu bizarren Fehlermeldungen führen würde. Das mittlere Argument eines ternären Operators kann jedoch ein beliebiger Ausdruck beliebiger Priorität sein, ohne dass Klammern erforderlich sind. Indem ich die Liste zum Wahrheitsgehalt mache, kann ich diese beiden Bytes retten.
DLosc
quelle
2
Das ist eine interessante Sprache, die Sie dort haben. Itemweise Operatoren fehlen in CJam und Pyth.
Dennis
@ Tennis Danke! Es ist noch sehr viel in Arbeit, aber es gibt einige Aufgaben, mit denen es ziemlich gut klappt.
DLosc,
5

APL (25)

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

In APL-Arrays sind Dimensionen integriert. Dies ist also eine Funktion, die ein n- dimensionales Array annimmt und dann entlang jeder Dimension summiert.

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

Erläuterung:

  • N←⍵: Speichern Sie das Array in N.
  • ⍴⍴N: bekommen die Menge der Dimensionen Nhat. ( Gibt die Dimensionen, also ⍴↑(1 2 3)(4 5 6)gibt 2 3, so ⍴⍴die Abmessungen der Abmessungen gibt.)
  • {... }¨⍳: für jede Zahl von 1 bis ⍴⍴N:
    • +/[⍵]N: Summe Nentlang der Dimension
    • N,[⍵]←: Füge das Ergebnis Nin diese Dimension ein
  • N: endlich zurück N.
Marinus
quelle
Ich kann nicht scheinen, diese Arbeit zu machen, wenn das Array Singletons enthält. Wie würden Sie diese Funktion für den dritten oder vierten Testfall aufrufen?
Dennis
3
@Dennis: Sie müssen der Funktion ein mehrdimensionales Array übergeben. Was das ↑(1 2 3)(4 5 6)tut, ist einfach ein 2-dimensionales Array aus 2 1-dimensionalen zu konstruieren . Es ist keine eingebaute Notation und verallgemeinert nicht die Art und Weise, wie Sie vielleicht denken. Die kanonische Art und Weise, die 3. und 4. Anordnung zu konstruieren, wäre 1 4 1⍴1 1 1 0und 1 1 1 1⍴¯1, es ist jedoch auch möglich, sie ohne Bezugnahme auf die Größen zu konstruieren, z. B. kann die dritte Anordnung auch mit konstruiert werden ↑⍉⍪(,1)(,1)(,1)(,0), die vierte kann mit konstruiert werden ↑⍪⊂⍪¯1.
Marinus
OK, das erklärt alles. Meine naive Implementierung eines rekursiven Ansatzes funktioniert gut für Arrays (zB f←{0=≡⍵:⍵⋄f¨⍵,+/⍵}⋄f((1 2)(3 4))((5 6)(7 8))), aber es scheint, dass verschachtelte Vektoren und Arrays unterschiedlich sind und ersteres Skalare nicht von Singletons unterscheidet ...
Dennis
2
@ Dennis golfed: {×≡⍵:∇¨⍵,+/⍵⋄⍵}((1 2)(3 4))((5 6)(7 8)). Behoben: {×⍴⍴⍵:∇↓⍵,+/⍵⋄⍵}1 4 1⍴1 1 1 0. Es ist jetzt kürzer als Mathematica ...
Jimmy23013
3

CJam, 36 Bytes

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

Dies ist eine rekursiv benannte Funktion, die ein Array aus dem Stapel entfernt und ein Array zurückgibt.

Probieren Sie die Testfälle im CJam-Interpreter aus .

Idee

Leider gibt es in CJam keinen automagischen Operator, mit dem beliebig verschachtelte Arrays hinzugefügt werden können. Deshalb müssen wir ihn selbst implementieren. Glücklicherweise erweisen sich zwei Infix-Operatoren :(Reduzieren) und .(Vektorisieren) als hilfreich für diese Aufgabe.

In Schritt eins wird die Anzahl der Dimensionen berechnet. Dies ist ganz einfach: Konvertieren Sie das Array in seine Zeichenfolgendarstellung und zählen Sie die Anzahl der führenden [ 's.

Um ein Array einer Dimension zu verkleinern, führen Sie normalerweise Folgendes aus :+:

[1 2] :+ e# Pushes 3.

+Würde für ein Array mit zwei Dimensionen eine Verkettung anstelle einer Addition durchgeführt, müssen wir sie vektorisieren:

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

.+Würde nun für ein Array mit drei Dimensionen ein Array mit zwei Dimensionen bearbeiten und erneut eine Verkettung durchführen. Dieses Mal müssen wir vektorisieren .+:

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

Für den allgemeinen Fall, ein Array der Dimension D , müssen wir eins :, D - 1 . und eins verketten +.

Dies summiert das Array natürlich nur über seine äußerste Dimension. Wir können dies lösen, indem wir eine Funktion S definieren , die die Dimension berechnet (und nichts tut, wenn sie Null ist), die Summe wie oben angegeben ausführt und sich schließlich auf die Elemente des Arrays anwendet.

Code

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

Angenommen, die Eingabe wird als JSON übergeben.

rr-
quelle
Tatsächlich können Sie einfach eine Funktion schreiben, die ein geparstes Array akzeptiert und ein Array zurückgibt, und din dieser Antwort nur die 95 Bytes zählen .
Jimmy23013
2

Java, 669 Bytes

Ich werde nicht lügen, ich bin ziemlich stolz auf mich: 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;}}

erweitert mit Testing:

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

}

Das Ausführen der erweiterten Testversion gibt Folgendes aus:

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
quelle
erm für die erweiterte Version die Zeile: Array.set (result, x, sum (Array.get (arrayA, x), Array.get (arrayB, x ++))); in der _sum (...) Methode sollte _sum (...) aufgerufen haben, nicht sum (...). mein böser
Jack Ammo