Jumlahkan di setiap dimensi

20

Anda diberi array multi-dimensi bilangan bulat. Setiap dimensi memiliki ukuran tetap (sehingga akan selalu persegi panjang jika 2D). Program Anda harus menghitung jumlah di setiap dimensi dan menambahkan jumlahnya sebagai item terakhir baru di dimensi itu.

Asumsikan array input dan output adalah A dan B, dan ukuran dimensi i dari A adalah n i . B akan memiliki jumlah dimensi yang sama dengan A dan ukuran dimensi i menjadi n i +1. B j 1 , j 2 , ..., j m adalah jumlah dari A k 1 , k 2 , ..., k m di mana:

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

Untuk input:

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

Program Anda (atau fungsi) harus menampilkan:

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

Input hanya berisi array. Jumlah total dimensi dan ukuran setiap dimensi tidak diberikan dalam input. (Tapi Anda bisa mendapatkannya dari array dengan kode Anda sendiri.) Anda dapat menggunakan format daftar yang mudah digunakan dalam bahasa Anda, asalkan tidak menentukan jumlah dimensi atau ukuran dimensi secara langsung.

Input memiliki setidaknya 1 dimensi, dan memiliki setidaknya 1 item dalam array.

Ini adalah kode-golf. Kode terpendek menang.

Uji kasus

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
sumber
Apakah Anda akan memposting solusi APL 16 byte itu? Jika tidak, bisakah saya?
Dennis
@ Dennis Anda harus mempostingnya.
jimmy23013

Jawaban:

9

J, 14 byte

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

Pemakaian:

   ]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

Fungsi ini setara dengan yang berikut ini (0|:],+/)^:(#@$)tetapi menggunakan kata keterangan yang ditentukan pengguna untuk menyimpan parens.

Penjelasan untuk kode yang terakhir dari kanan ke kiri:

  • ^:(#@$)ulangi ^:untuk jumlah #dimensi $:

    • ],+/menggabungkan ,argumen ]dengan jumlah itu pada dimensi terakhir+/
    • 0|:putar dimensi |:dengan meletakkan yang pertama 0ke akhir daftar dimensi
  • Setelah melakukan prosedur di atas, kami mendapatkan kembali input asli dengan jumlah pada semua dimensi.

Untuk solusi lama saya periksa riwayat revisi.

Cobalah online di sini.

randomra
sumber
15

Mathematica, 32 20 byte

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

Contoh:

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

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

Penjelasan:

Bentuk lengkap {{1, 2, 3}, {4, 5, 6}}is List[List[1, 2, 3], List[4, 5, 6]]. Kemudian ganti semua Lists dalam ekspresi dengan fungsi ({##,+##}&).

alephalpha
sumber
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

Ini berulang setiap dimensi, menggabungkan jumlah menggunakan NumPy.

Saya menemukan NumPy r_, yang cukup bagus untuk bermain golf. r_[:n]lebih pendek dari range(n)dan jauh lebih kuat (mis r_[:4, 7, 8, 10:100:10].). Itu juga dapat melakukan hal-hal lain seperti penggabungan sepanjang sumbu arbitrer.

Contoh penggunaan:

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

APL, 16 15 byte

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

Terima kasih kepada @ user23013 untuk bermain golf 3 byte dan mencari tahu format input yang tepat.

Verifikasi kasus uji online dengan TryAPL .

Ide

Gagasan umum adalah sama seperti dalam pengajuan CJam saya, yang mana APL memungkinkan implementasi yang jauh lebih pendek. Ini hanya terdiri dari dua langkah:

  1. Jumlah array di dimensi terluarnya.

  2. Ulangi langkah 1 untuk setiap subarray.

Kode

{             } ⍝ 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
sumber
Baru tahu format input untuk kode asli Anda: ,⊂(,1)(,1)(,1)(,0)dan ,⊂,⊂,⊂,¯1masing - masing. Jadi, Anda dapat menghapus karakter lain.
jimmy23013
2
@ user23013: Jadi kode saya berhasil! Anda harus menyukai bahasa pemrograman di mana format input lebih sulit untuk diperbaiki daripada kode yang sebenarnya ...
Dennis
6

Pip , 18 15 byte

{a-a?fMaAE$+aa}

Ini adalah fungsi anonim, yang mengambil array sebagai argumen dan mengembalikan hasilnya. Contoh doa, menggunakan -pbendera untuk mendapatkan hasil yang dapat dibaca:

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

Idenya pada dasarnya sama dengan APL Dennis , meskipun diturunkan secara independen. Lebih spesifik:

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

Metode ini berfungsi karena +(bersama dengan banyak operator lain) fungsi item-bijaksana pada daftar di Pip - fitur yang terinspirasi oleh bahasa pemrograman array seperti APL. Jadi ketika Anda $+daftar suka [[1 2 3] [4 5 6]], hasilnya [5 7 9]seperti yang diinginkan. Juga digunakan dalam tes daftar-atau-skalar: [1 2 3] - [1 2 3]memberi [0 0 0], yang benar (seperti semua daftar kecuali daftar kosong).

Versi 18-byte sebelumnya:

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

Perubahan:

  1. Menyimpan byte pada tes skalar-atau-daftar - metode sebelumnya adalah untuk bergabung dengan argumen (pada string kosong) dan menguji apakah sama dengan dirinya yang tidak bergabung (berfungsi karena [1 2 3] != 123);
  2. Menghilangkan tanda kurung. Mereka diperlukan dalam yang asli karena Mlebih diutamakan daripada ?(meskipun saya mungkin akan mengubah itu, terutama sekarang): tanpa mereka, kode akan diurai sebagai (Ja=a?af)M(aAE$+a), mengarah ke pesan kesalahan aneh. Namun, argumen tengah operator ternary dapat setiap ekspresi diutamakan apapun, tidak ada tanda kurung diperlukan. Jadi dengan membuat daftar kasus kebenaran, saya dapat menyimpan dua byte itu.
DLosc
sumber
2
Itu bahasa yang menarik yang Anda dapatkan di sana. Operator itemwise adalah apa yang hilang dalam CJam dan Pyth.
Dennis
@Dennis Terima kasih! Ini masih banyak pekerjaan yang sedang berjalan, tetapi ada beberapa tugas yang cukup baik.
DLosc
5

APL (25)

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

Array APL memiliki dimensi bawaan, jadi ini adalah fungsi yang mengambil larik n- dimensi dan kemudian menjumlahkan di sepanjang setiap dimensi.

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

Penjelasan:

  • N←⍵: simpan array di N.
  • ⍴⍴N: dapatkan jumlah dimensi yang Ndimilikinya. (Berikan dimensi, yaitu ⍴↑(1 2 3)(4 5 6)memberi 2 3, sehingga ⍴⍴memberikan dimensi dari dimensi.)
  • {... }¨⍳: untuk setiap nomor dari 1 hingga ⍴⍴N:
    • +/[⍵]N: jumlah Nsepanjang dimensi
    • N,[⍵]←: gabungkan hasilnya ke Ndalam dimensi itu
  • N: akhirnya, kembali N.
marinus
sumber
Sepertinya saya tidak bisa membuat ini berfungsi jika array berisi lajang. Bagaimana Anda memanggil fungsi ini untuk test case ketiga atau keempat?
Dennis
3
@ Dennis: Anda harus melewati fungsi array multidimensi. Apa yang ↑(1 2 3)(4 5 6)dilakukan adalah hanya membangun array 2 dimensi dari 2 yang menggunakan 1 dimensi . Ini bukan notasi bawaan dan tidak menggeneralisasi cara Anda berpikir. Cara kanonik untuk membangun array ke-3 dan ke-4 adalah 1 4 1⍴1 1 1 0dan 1 1 1 1⍴¯1, tetapi juga memungkinkan untuk membangunnya tanpa merujuk pada ukuran, mis., Array ketiga juga dapat dibangun dengan ↑⍉⍪(,1)(,1)(,1)(,0), yang keempat dapat dibangun dengan ↑⍪⊂⍪¯1.
marinus
Oke, itu menjelaskan semuanya. Implementasi naif saya dari pendekatan rekursif bekerja dengan baik untuk apa yang saya pikir array (misalnya f←{0=≡⍵:⍵⋄f¨⍵,+/⍵}⋄f((1 2)(3 4))((5 6)(7 8))), tetapi tampaknya vektor bersarang dan array berbeda dan yang pertama tidak membedakan skalar dari singleton ...
Dennis
2
@Dennis golfed: {×≡⍵:∇¨⍵,+/⍵⋄⍵}((1 2)(3 4))((5 6)(7 8)). Tetap: {×⍴⍴⍵:∇↓⍵,+/⍵⋄⍵}1 4 1⍴1 1 1 0. Ini lebih pendek dari Mathematica sekarang ...
jimmy23013
3

CJam, 36 byte

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

Ini adalah fungsi bernama rekursif yang memunculkan array dari tumpukan dan mengembalikannya.

Coba kasus uji dalam juru bahasa CJam .

Ide

Sayangnya, CJam tidak memiliki beberapa operator otomatis yang memungkinkan untuk menambahkan array bersarang secara sewenang-wenang, jadi kami harus mengimplementasikannya sendiri. Untungnya, ia melakukan itu dua operator infiks, :(mengurangi) dan .(vectorize), yang akan terbukti bermanfaat untuk tugas ini.

Langkah pertama adalah menghitung jumlah dimensi. Ini mudah: Konversi array menjadi representasi stringnya dan hitung jumlah leading [ 's.

Sekarang, untuk mengurangi array satu dimensi, Anda biasanya hanya menjalankan :+:

[1 2] :+ e# Pushes 3.

Untuk array dua dimensi, +akan melakukan penggabungan bukannya penambahan, jadi kita harus mengubahnya:

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

Sekarang, untuk array tiga dimensi, .+akan beroperasi pada array dua dimensi dan melakukan, sekali lagi, penggabungan. Kali ini, kita harus membuat vektor .+:

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

Untuk kasus umum, array dimensi D , kita harus menghubungkan satu :, D - 1 . dan satu +.

Tentu saja, ini hanya menjumlahkan array hanya di dimensi terluarnya. Kita dapat menyelesaikan ini dengan mendefinisikan fungsi S yang menghitung dimensi (dan tidak melakukan apa-apa jika itu nol), melakukan penjumlahan seperti yang ditunjukkan di atas dan, akhirnya, berlaku sendiri untuk elemen-elemen array.

Kode

{                                }: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
sumber
2

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

Mengasumsikan input dilewatkan sebagai JSON.

rr-
sumber
Dan sebenarnya Anda hanya bisa menulis fungsi menerima array yang diuraikan dan mengembalikan array, dan hanya menghitung 95 byte ddalam jawaban ini.
jimmy23013
2

Java, 669 byte

tidak akan berbohong, saya cukup bangga pada diri saya untuk yang satu ini: hal

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

diperluas dengan pengujian:

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

}

menjalankan versi pengujian yang diperluas mencetak ini:

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
sumber
erm untuk versi yang diperluas, baris: Array.set (hasil, x, jumlah (Array.get (arrayA, x), Array.get (arrayB, x ++))); dalam metode _sum (...) seharusnya disebut _sum (...), bukan jumlah (...). salahku
Jack Ammo