Suma w każdym wymiarze

20

Otrzymujesz wielowymiarową tablicę liczb całkowitych. Każdy wymiar ma ustalony rozmiar (aby zawsze był prostokątny, jeśli jest dwuwymiarowy). Twój program powinien obliczyć sumy w każdym wymiarze i dołączyć je jako nowe ostatnie pozycje w tym wymiarze.

Załóżmy, że tablice wejściowe i wyjściowe to A i B, a rozmiar wymiaru i A wynosi n i . B miałby taką samą liczbę wymiarów jak A, a rozmiar wymiaru i wynosiłby n i +1. B j 1 , j 2 , ..., j m jest sumą A k 1 , k 2 , ..., k m gdzie:

  • k i = j i jeśli j i <= n i
  • 0 <k i <= n i jeśli j i = n i +1

Dla danych wejściowych:

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

Twój program (lub funkcja) powinien wypisać:

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

Dane wejściowe zawierają tylko tablicę. Całkowita liczba wymiarów i rozmiar każdego wymiaru nie są podane na wejściu. (Ale możesz pobrać je z tablicy za pomocą własnego kodu.) Możesz używać dowolnych wygodnych formatów list w swoim języku, o ile nie określa bezpośrednio liczby wymiarów ani rozmiarów wymiarów.

Dane wejściowe mają co najmniej 1 wymiar i co najmniej 1 element w tablicy.

To jest golf golfowy. Najkrótszy kod wygrywa.

Przypadki testowe

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
źródło
Czy opublikujesz 16-bajtowe rozwiązanie APL? Jeśli nie, czy mogę?
Dennis
@Dennis Powinieneś to opublikować.
jimmy23013

Odpowiedzi:

9

J, 14 bajtów

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

Stosowanie:

   ]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

Ta funkcja jest równoważna z poniższą, (0|:],+/)^:(#@$)ale używa przysłówka zdefiniowanego przez użytkownika do zapisywania parens.

Objaśnienie drugiego kodu od prawej do lewej:

  • ^:(#@$)powtórz ^:dla liczby #wymiarów $:

    • ],+/konkatenuje ,do argumentu ]z sumą w ostatnim wymiarze+/
    • 0|:obróć wymiary |:, umieszczając pierwszy 0na końcu listy wymiarów
  • Po wykonaniu powyższej procedury odzyskujemy oryginalne dane wejściowe z sumami dla wszystkich wymiarów.

W przypadku mojego starszego rozwiązania sprawdź historię zmian.

Wypróbuj online tutaj.

randomra
źródło
15

Mathematica, 32 20 bajtów

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

Przykład:

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

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

Wyjaśnienie:

Pełna forma {{1, 2, 3}, {4, 5, 6}}to List[List[1, 2, 3], List[4, 5, 6]]. Następnie zamień wszystkie Lists wyrażenia na funkcję ({##,+##}&).

alephalpha
źródło
10

Python 2, 95 bajtów

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

To iteruje każdy wymiar, konkatenując jego sumy za pomocą NumPy.

Natknąłem się na NumPy's r_, co jest całkiem niesamowite do gry w golfa. r_[:n]jest krótszy range(n)i znacznie potężniejszy (np r_[:4, 7, 8, 10:100:10].). Może także wykonywać inne czynności, takie jak konkatenacja wzdłuż dowolnej osi.

Przykładowe użycie:

$ python sum.py
[[1, 2, 3], [4, 5, 6]]
[[ 1  2  3  6]
 [ 4  5  6 15]
 [ 5  7  9 21]]
grc
źródło
7

APL, 16 15 bajtów

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

Dzięki @ user23013 za grę w golfa poza 3 bajtami i ustalenie odpowiedniego formatu wejściowego.

Sprawdź przypadki testowe online za pomocą TryAPL .

Pomysł

Ogólna idea jest taka sama, jak w moim przedłożeniu CJam, dla którego APL pozwala na znacznie krótszą implementację. Składa się tylko z dwóch kroków:

  1. Zsumuj tablicę w jej skrajnym wymiarze.

  2. Powtórz krok 1 dla każdej podtablicy.

Kod

{             } ⍝ 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
źródło
Właśnie wymyśliłem format wejściowy dla twojego oryginalnego kodu: ,⊂(,1)(,1)(,1)(,0)i ,⊂,⊂,⊂,¯1odpowiednio. Możesz więc usunąć inną postać.
jimmy23013
2
@ user23013: Więc mój kod działał! Musisz pokochać język programowania, w którym trudniej jest uzyskać poprawny format wejściowy niż rzeczywisty kod ...
Dennis
6

Pip , 18 15 bajtów

{a-a?fMaAE$+aa}

Jest to anonimowa funkcja, która przyjmuje tablicę jako argument i zwraca wynik. Przykładowe wywołanie przy użyciu -pflagi w celu uzyskania czytelnego wyniku:

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

Pomysł jest zasadniczo taki sam jak APL Dennisa , choć niezależnie pochodzi. Dokładniej:

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

Ta metoda działa, ponieważ +(wraz z wieloma innymi operatorami) działa w elementach na listach w Pipie - funkcja inspirowana językami programowania tablic, takimi jak APL. Więc kiedy masz $+taką listę [[1 2 3] [4 5 6]], wynik jest [5 7 9]zgodny z oczekiwaniami. Używany również w teście list lub skalar: [1 2 3] - [1 2 3]daje [0 0 0], co jest zgodne z prawdą (podobnie jak wszystkie listy oprócz pustej listy).

Poprzednia 18-bajtowa wersja:

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

Zmiany:

  1. Zapisano bajt w teście skalarnym lub listowym - poprzednia metoda polegała na dołączeniu argumentu (na pustym łańcuchu) i sprawdzeniu, czy jest równa jego niepowiązanemu self (działa, ponieważ [1 2 3] != 123);
  2. Wyeliminowano nawiasy. Są one niezbędne w oryginale, ponieważ Mmają niższy priorytet niż ?(choć prawdopodobnie zamierzam to zmienić, szczególnie teraz): bez nich kod byłby analizowany jako (Ja=a?af)M(aAE$+a), co prowadzi do dziwnych komunikatów o błędach. Jednak środkowym argumentem operatora trójskładnikowego może być dowolne wyrażenie o dowolnym priorytecie, niepotrzebne nawiasy. Tak więc, czyniąc listę prawdziwym przypadkiem, mogę zapisać te dwa bajty.
DLosc
źródło
2
To ciekawy język, który tam masz. Operatory pozycyjne są tym, czego brakuje w CJam i Pyth.
Dennis
@Dennis Thanks! Nadal jest to w dużej mierze praca w toku, ale jest kilka zadań, z którymi całkiem dobrze sobie radzi.
DLosc
5

APL (25)

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

Tablice APL mają wbudowane wymiary, więc jest to funkcja, która pobiera tablicę n- wymiarową, a następnie sumuje wzdłuż każdego wymiaru.

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

Wyjaśnienie:

  • N←⍵: zapisz tablicę w N.
  • ⍴⍴N: uzyskać ilość wymiarów Nma. ( podaje wymiary, tzn. ⍴↑(1 2 3)(4 5 6)daje 2 3, więc ⍴⍴podaje wymiary wymiarów).
  • {... }¨⍳: dla każdej liczby od 1 do ⍴⍴N:
    • +/[⍵]N: suma Nwzdłuż wymiaru
    • N,[⍵]←: dołącz wynik do Ntego wymiaru
  • N: w końcu powróć N.
marinus
źródło
Nie mogę sprawić, by działało, jeśli tablica zawiera singletony. Jak nazwałbyś tę funkcję dla trzeciego lub czwartego przypadku testowego?
Dennis
3
@Dennis: musisz przekazać funkcji tablicę wielowymiarową. To, co ↑(1 2 3)(4 5 6)robi, to po prostu zbudowanie 2-wymiarowej tablicy z 2 1-wymiarowych przy użyciu . To nie jest wbudowana notacja i nie uogólnia sposobu myślenia. Kanoniczny sposób konstruowania trzeciej i czwartej tablicy byłby 1 4 1⍴1 1 1 0i 1 1 1 1⍴¯1, ale możliwe jest również zbudowanie ich bez odwoływania się do rozmiarów, np. Trzecia tablica może być również zbudowana ↑⍉⍪(,1)(,1)(,1)(,0), a czwarta może być zbudowana ↑⍪⊂⍪¯1.
marinus
OK, to wszystko wyjaśnia. Moja naiwna implementacja podejścia rekurencyjnego działa dobrze dla tego, co uważałem za tablice (np. f←{0=≡⍵:⍵⋄f¨⍵,+/⍵}⋄f((1 2)(3 4))((5 6)(7 8))), Ale wydaje się, że zagnieżdżone wektory i tablice są różne, a ta pierwsza nie odróżnia skalarów od singletonów ...
Dennis
2
@Dennis golfed: {×≡⍵:∇¨⍵,+/⍵⋄⍵}((1 2)(3 4))((5 6)(7 8)). Poprawiono: {×⍴⍴⍵:∇↓⍵,+/⍵⋄⍵}1 4 1⍴1 1 1 0. Jest teraz krótszy niż Mathematica ...
jimmy23013
3

CJam, 36 bajtów

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

Jest to rekurencyjna funkcja o nazwie, która usuwa tablicę ze stosu i pozostawia jedną w zamian.

Wypróbuj przypadki testowe w interpretatorze CJam .

Pomysł

Niestety, CJam nie ma operatora automagicznego, który pozwala dodawać dowolnie zagnieżdżone tablice, więc musimy go sami zaimplementować. Na szczęście robi to dwóch operatorów infix, :(redukcja) i .(wektoryzacja), które okażą się pomocne w tym zadaniu.

Pierwszym krokiem jest obliczenie liczby wymiarów. Jest to łatwe: przekonwertuj tablicę na reprezentację ciągu i policz liczbę wiodących [ .

Teraz, aby zmniejszyć tablicę o jednym wymiarze, zwykle wystarczy wykonać :+:

[1 2] :+ e# Pushes 3.

W przypadku tablicy dwóch wymiarów +wykonałby konkatenację zamiast dodawania, dlatego musimy ją wektoryzować:

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

Teraz, dla tablicy trzech wymiarów, .+działałby na tablicach dwóch wymiarów i ponownie przeprowadzałby konkatenację. Tym razem musimy wektoryzować .+:

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

W ogólnym przypadku macierz wymiaru D musimy połączyć jeden :, D - 1 . i jeden +.

Oczywiście sumuje to tablicę tylko w jej skrajnym wymiarze. Możemy to rozwiązać, definiując funkcję S, która oblicza wymiar (i nie robi nic, jeśli jest równa zero), wykonuje sumę jak wskazano powyżej i na koniec stosuje się do elementów tablicy.

Kod

{                                }: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
źródło
2

Rubinowy ( 181 139 119 108 bajtów)

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

Zakłada, że ​​dane wejściowe są przekazywane jako JSON.

rr
źródło
W rzeczywistości możesz po prostu napisać funkcję, która akceptuje parsowaną tablicę i zwraca tablicę, i liczy tylko 95 bajtów dla dtej odpowiedzi.
jimmy23013
2

Java, 669 bajtów

nie będę kłamał, jestem z tego dumny: 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;}}

rozszerzony o testy:

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

}

uruchomienie rozszerzonej wersji testowej drukuje to:

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
źródło
erm dla wersji rozszerzonej, wiersz: Array.set (wynik, x, suma (Array.get (arrayA, x), Array.get (arrayB, x ++))); w metodzie _sum (...) powinna była wywołać _sum (...), a nie suma (...). mój zły
Jack Ammo