Jumlah parsial berulang


23

The jumlah parsial dari daftar bilangan bulat [a 1 , a 2 , a 3 , ..., a n ] adalah

s 1 = a 1
s 2 = a 1 + a 2
s 3 = a 1 + a 2 + a 3
...
s n = a 1 + a 2 + ... + a n

Kita kemudian dapat mengambil daftar jumlah parsial [s 1 , s 2 , s 3 , ..., s n ] dan menghitung jumlah parsialnya lagi untuk menghasilkan daftar baru, dan seterusnya.

Terkait: Iterasi ke depan perbedaan

Memasukkan:

  • Daftar bilangan bulat yang tidak kosong
  • Sejumlah iterasi positif,

Keluaran: Cetak atau kembalikan daftar bilangan bulat yang dihasilkan dari pengambilan jumlah parsial yang berkali-kali.

Bytes paling sedikit menang. Built-in tidak masalah meskipun mereka langsung menyelesaikan masalah.

Kasus uji:

f([-3, 4, 7, -1, 15], 1) == [-3, 1, 8, 7, 22]
f([-3, 4, 7, -1, 15], 3) == [-3, -5, 1, 14, 49]

Papan peringkat:


Apakah argumen harus dalam urutan yang sama, atau bisakah jumlah iterasi muncul sebelum daftar angka?
kirbyfan64sos

@ kirbyfan64sos Apapun pesanan.
xnor

Jawaban:


14

J, 5 byte

+/\^:

Cobalah online di J.js .

Bagaimana itu bekerja

  • /\ adalah kata keterangan (fungsi yang mengambil argumen kiri) yang secara kumulatif berkurang dengan argumennya.

  • Jadi +/\adalah jumlah kata kerja kumulatif .

  • ^:adalah konjungsi kekuatan ; (f ^: n) yberlaku ftotal nkali untuk y.

  • Kereta kata kerja-konjungsi +/\^:membentuk kata keterangan yang berulang +/\sebanyak yang ditentukan dalam argumen (kiri).

    x (+/\^:) yakan diuraikan sebagai (x (+/\^:)) y, yang setara dengan mengeksekusi (+/\^:x) y.

Terima kasih kepada @Zgarb atas bantuannya dengan penjelasannya.


13

Mathematica, 19 byte

Nah, jika built-in tidak apa-apa ...

Accumulate~Nest~##&

Menentukan fungsi dengan tanda tangan yang sama dengan contoh dalam tantangan. Saya cukup yakin, berkat nama panjang Accumulatebahwa ini akan mudah dikalahkan oleh bahasa golf dan keluarga APL. :)

Untuk menguraikan komentar LegionMammal978 bagi mereka yang tidak Mathematica:

##mewakili urutan parameter fungsi (yang seperti daftar yang secara otomatis "splat" di mana pun ia dimasukkan, jika Anda lebih terbiasa dengan istilah itu dari bahasa pilihan Anda). The ~adalah sintaksis gula untuk fungsi infix doa, jadi jika kita memanggil fungsi dengan parameter listdan ndan memperluas segala sesuatu, kita mendapatkan:

Accumulate~Nest~##
Nest[Accumulate, ##]
Nest[Accumulate, list, n]

Yang terjadi justru urutan argumen yang diharapkan oleh Nest.


Itu menarik, menggunakan notasi infiks untuk 3 argumen menggunakan SlotSequence...
LegionMammal978

9

Haskell, 26 23 byte

(!!).iterate(scanl1(+))

Ini mendefinisikan fungsi anonim, dipanggil sebagai berikut:

> let f = (!!).iterate(scanl1(+)) in f [-3,4,7,-1,15] 3
[-3,-5,1,14,49]

Terima kasih kepada @nimi karena telah menghemat 3 byte.

Penjelasan

(!!).                    -- Index by second argument from
     iterate(         )  -- the infinite list obtained by iterating
             scanl1(+)   -- the partial sums function (left scan by +) to first argument

Sangat bagus! Dan terima kasih atas penjelasannya!
Jake

2
Go pointfree, maka Anda bahkan dapat menghilangkan nama untuk fungsi: (!!).iterate(scanl1(+)).
nimi

@nimi, terima kasih! Entah bagaimana saya beralasan komposisi itu tidak akan menguntungkan saya di sini ...
Zgarb

9

APL, 9 8 byte

{+\⍣⍺⊢⍵}

Ini mendefinisikan fungsi diad yang menerima iterasi dan daftar sebagai argumen kiri dan kanan.

Terima kasih kepada @NBZ untuk bermain golf 1 byte!

Cobalah online di TryAPL .

Bagaimana itu bekerja

  • dan argumen kiri dan kanan untuk fungsi.

  • +\ kumulatif dikurangi dengan jumlah.

  • ⍣⍺mengulangi waktu operator sebelumnya .

  • ⊢⍵menerapkan fungsi identitas .

    Ini adalah cara yang lebih pendek dari parsing kode sebagai (+\⍣⍺)⍵bukan +\⍣(⍺⍵).

Dalam hubungannya, kami menerapkan +\total kali untuk


@AlexA .: Maka tidak akan +\⍣⎕⊢⎕bisa diterima? ( seperti Python input()).
marinus

1
@marinus Apakah itu benar-benar mencetak di luar REPL? Satu-satunya juru bahasa desktop yang saya miliki akan membutuhkan penugasan setelahnya.
Dennis

5

Matlab, 41 byte

function f(l,n);for i=1:n;l=cumsum(l);end

Cukup mudah. Saya masih berpikir itu cukup menjengkelkan karena tidak memiliki cara untuk membuat fungsi anonim yang didefinisikan secara terpisah, atau jangkar dalam rekursi.

Tidak Disatukan:

function f(l,n);
for i=1:n;
    l=cumsum(l);
end

5

JavaScript (ES6) 38

Mengejutkan menggunakan .map secara rekursif

f=(l,n,t=0)=>n?f(l.map(x=>t+=x),n-1):l

function test()
{
  var n, v, i = I.value
  v = i.match(/\-?\d+/g).map(x=>+x)
  n = v.pop()
  console.log(v,n)
  O.innerHTML = I.value + ' -> ' + f(v,n) + '\n' + O.innerHTML;
}

test()
<input id=I value='[-3, 4, 7, -1, 15], 3'><button onclick="test()">-></button>
<pre id=O></pre>


5

K, 7 3 byte

{y+\/x}

Sangat mirip dengan solusi J. +\tepat melakukan jumlah parsial, dan ketika /diberikan dengan kata kerja monadik dan argumen integer kiri itu mengulangi beberapa kali, seperti loop "for". Sisanya hanya membungkusnya dengan rapi agar sesuai dengan urutan argumen.

  {y+\/x}[-3 4 7 -1 15;1]
-3 1 8 7 22
  {y+\/x}[-3 4 7 -1 15;3]
-3 -5 1 14 49

Diuji dalam Kona dan oK .

Edit:

Jika saya diizinkan untuk membalikkan argumen, seperti yang ditentukan @ kirbyfan64sos, saya dapat membuang fungsi pembungkus seluruhnya:

+\/

Dipanggil seperti:

+\/[3;-3 4 7 -1 15]

Ini berfungsi baik di k2.8 dan k5. Ini tidak berfungsi di OK karena penerjemah itu belum mendukung adverbia curried (alias "diproyeksikan"), dan itu tampaknya tidak bekerja dengan baik di Kona karena alasan yang kurang jelas.

sunting : Sampai beberapa hari yang lalu, +\/formulasi juga berfungsi di oK.


1
Argumen dapat dibalik , jadi saya pikir Anda mungkin dapat mencukur beberapa byte.
kirbyfan64sos

3 +\/ -3 4 7 -1 15berfungsi dengan baik di Kona, tetapi Anda tidak dapat menetapkannya ke suatu fungsi. Aneh ...
Dennis

Ya, Kona jelas tidak memperlakukan 3+\/-3 4 7 -1 15sama seperti +\/[3;-3 4 7 -1 15]- membuat saya bertanya-tanya apakah mereka menangani yang pertama sebagai kasus sintaksis khusus.
JohnE

4

Pyth, 9 byte

usM._GvwQ

Cobalah online: Demonstrasi atau Test Suite

Penjelasan

usM._GvwQ  implicit: Q = input list
      vw   input number
u       Q  repeat the following instruction ^ times to G = Q
   ._G        sequence of prefixes of G
 sM           sum them up

4

Julia, 29 byte

f(x,y)=y>0?f(cumsum(x),y-1):x

Ini benar-benar tidak perlu banyak penjelasan. Ini adalah fungsi rekursif, jika y==0kemudian hanya keluaran x. Jika tidak, kurangi y, lakukan cumsum, dan rekursi. Mungkin bukan solusi Julia yang paling golf, saya masih mengusahakannya.


4

Labirin , 73 byte

;?
,"
;
#
#;}=
;  #
"#;(
_  ;={()"
#;; ( { "
  ; { !\(@
+=( =
" " "
":{:"

Sudah lama sejak saya menjawab sesuatu di Labyrinth, dan ini sepertinya bisa dilakukan. :)

Format input adalah daftar datar dengan jumlah iterasi pertama (dan kemudian daftar untuk menerapkan jumlah parsial). Pembatas tidak masalah semua, selama tidak ada karakter setelah integer terakhir, sehingga Anda dapat menggunakan sesuatu yang dapat dibaca seperti:

3 | -3, 4, 7, -1, 15

Output dipisahkan oleh baris baru:

-3
-5
1
14
49

4

R, 75 byte

Ini panjang tapi berbeda ... menghitung urutan yang diinginkan secara langsung daripada jumlah kumulatif:

function(x,n)sapply(1:length(x),function(i)sum(x[1:i]*choose(i:1+n-2,n-1)))

Memperhatikan bahwa koefisien syarat xi untuk kumsum ^ n (x) adalah diagonal segitiga Pascal. yaitu

cumsum^3(x) = choose(2,2) * x1, choose(3,2) * x1 + choose(2,2) *x2, choose(4,2) * x1 + choose(3,2) * x2 + choose(2,2) * x3, ....

edit: untuk membuat fungsi


4

Python 2, 67

Ini menggunakan penjumlahan yang sama dengan Anthony Roitman , dan rekursi yang sama dengan Morgan Thrapp .

f=lambda l,n:f([sum(l[:i+1])for i in range(len(l))],n-1)if n else l

Saya mengembangkan solusi ini sebelum saya melihat solusi mereka, dan kemudian sepertinya lebih mudah untuk mempostingnya sebagai jawaban daripada komentar untuk salah satu atau keduanya.


4

Python, 113 93 89 76 byte

def f(l,n):
 for i in[0]*n:l=[sum(l[:j+1])for j in range(len(l))];
 print(l)

Ini berfungsi untuk kedua kasus uji. Terima kasih kepada Status, Morgan Thrapp, dan Ruth Franklin yang telah membantu saya mengubah program menjadi 93, 89, dan 76 byte.


1
Anda dapat memotong sejumlah byte dengan mengubah loop kedua menjadi pemahaman daftar. Yaitu k=[sum(l[:j+1])for j in range(len(l))],. Kemudian dengan ;k=lmenempelkan pada ujung itu Anda bisa mendorong semua ini ke satu baris dengan for iloop.
Status

1
Anda dapat memindahkannya k=[sum(l[:j+1])for j in range(len(l))];l=kke baris yang sama dengan for loop untuk menyimpan 2 byte dan menghapus spasi di antara argumen f untuk menyimpan byte lainnya.
Morgan Thrapp

Karena Anda tidak menggunakan nilai i, Anda dapat menggantinya for i in range(n)dengan for i in[0]*n(karena yang Anda pedulikan hanyalah panjangnya, bukan elemen dari daftar). Dan saya pikir Anda bisa melakukannya tanpa menggunakan daftar tambahan k, hanya memodifikasi argumen l.
Ruth Franklin

4

Gol> <> 0.3.10 , 22 byte

SI
C>rFlMF:}+
NRl<C}<;

Bilangan bulat pertama dianggap sebagai nomor iterasi dan sisanya merupakan daftar. Daftar akhir dikeluarkan baris-baru yang dikeluarkan.

Bahasanya masih sangat muda dan tidak stabil, tetapi karena saya cukup mengatur operator ini saya pikir itu akan baik-baik saja.

Penjelasan

SI            Read integer, moving down on EOF (first line runs as loop)
r             Reverse stack, putting iteration number on top

[outer loop]
F             Do #(iterations) times

[inner loop]
lMF           Do #(length of stack - 1) times
:             Duplicate top of stack
}             Rotate stack rightward (top goes to bottom)
+             Add the top two elements of the stack
C             Continue inner loop, moving down from F when loop is over

}             Rotate once more
C             Continue outer loop, moving down from F when loop is over

lRN           Print stack as (num + newline)
;             Halt

Untuk melihat mengapa ini berhasil, mari kita coba contoh kecil [5 2 1]:

[5 2 1] -- : --> [5 2 1 1] -- } -->  [1 5 2 1]  -- + --> [1 5 3]
[1 5 3] -- : --> [1 5 3 3] -- } -->  [3 1 5 3]  -- + --> [3 1 8]

-- } --> [8 3 1]

3

Python, 52 byte

f=lambda l,n:n*l and f(f(l[:-1],1)+[sum(l)],n-1)or l

Fungsi rekursif yang berulang pada daftar ldan jumlah iterasi n. Mari kita jabarkan.

Pertama, mari kita pertimbangkan fungsi rekursif gyang mengulangi jumlah parsial sekali saja.

g=lambda l:l and g(l[:-1])+[sum(l)]

Untuk daftar kosong l, ini mengembalikan ldirinya sendiri, daftar kosong. Jika tidak, entri terakhir dari jumlah parsial ladalah jumlah keseluruhan l, yang ditambahkan ke hasil rekursif untuk semua kecuali elemen terakhir l.

Sekarang, mari kita lihat fungsi fyang berlaku guntuk niterasi.

f=lambda l,n:n and f(g(l),n-1)or l

Ketika nadalah 0, ini mengembalikan daftar lberubah, dan sebaliknya, berlaku gsekali, kemudian memanggil frekursif dengan satu lebih sedikit iterasi yang tersisa.

Sekarang, mari kita lihat kembali kode yang sebenarnya, yang menggabungkan dua rekursi menjadi satu fungsi. Idenya adalah untuk memperlakukan g(l)sebagai kasus khusus f(l,1).

f=lambda l,n:n*l and f(f(l[:-1],1)+[sum(l)],n-1)or l

Kami mengambil f(g(l),n-1)dari definisi sebelumnya, diperluas g(l)menjadi g(l[:-1])+[sum(l)], dan kemudian diganti g(_)dengan f(_,1)untuk membatasi panggilan rekursif f.

Untuk kasus dasar, kami ingin kembali lkapanpun n==0atau l==[]. Kami menggabungkan ini dengan mencatat bahwa salah satu n*ldari daftar tersebut menjadi daftar kosong, yaitu Falsy. Jadi, kami berulang setiap kali n*ltidak kosong, dan mengembalikan lsebaliknya.

Meskipun ada dua panggilan rekursif f, ini tidak menyebabkan ledakan eksponensial definisi rekursif dari angka-angka Fibonacci, tetapi tetap kuadratik.


3

C ++ (61 + 17 = 78 byte)

#include<numeric>
void f(int*a,int*e,int n){for(;n--;)std::partial_sum(a,e,a);}

Kasus cobaan:

#include <iostream>
#include <iterator>

int main() {
    int a[] { -3, 4, 7, -1, 15 };
    f(a, std::end(a), 3);
    for (auto i : a)
        std::cout << i << " ";
}

Ini membutuhkan sedikit kebebasan dengan spesifikasi: ia menggunakan larik C-style, melewati pointer ke awal dan akhir larik. Secara internal, seperti yang Anda lihat, itu hanya pembungkus yang sangat tipis std::partial_sumdi dalam perpustakaan standar. Alih-alih benar-benar mengembalikan nilai yang dihasilkan, itu hanya mengubah array yang diteruskan.

Jika kita tidak keberatan mendorong definisi hal-hal ke batas (dan, bisa dibilang, sedikit di luar) kita dapat mendefinisikan "fungsi" dalam ekspresi lambda:

#include<numeric>
#include <iostream>
#include <iterator>

int main() {
    int a[] { -3, 4, 7, -1, 15 };
    int *e = std::end(a);
    int n=3;

    auto f=[&]{for(;n--;)std::partial_sum(a,e,a);};

    f();
    for (auto i : a)
        std::cout << i << " ";
}

Ini mengurangi definisi fungsi (-seperti objek) untuk bagian ini:

[&]{for(;n--;)std::partial_sum(a,e,a);};

... untuk 40 byte (+17 untuk #include).


Wau, saya tidak berharap STL memiliki banyak untuk menghitung jumlah parsial.
Zereges

1
@ Zona: Tidak ada yang mengharapkan Inkuisisi Spanyol .... oh, tunggu, kami sedang melakukan C ++, bukan Python. Permintaan maaf saya.
Jerry Coffin


2

Haskell, 52 47 byte

Kode 'usaha' golf pertama, dan saya sangat pemula di Haskell, jadi komentar dengan senang hati disambut! Tidak jelas dalam pertanyaan mengenai format panggilan fungsi yang diperlukan, atau apakah itu diambil oleh argumen ke program, jadi saya menggunakan tanda seru sebagai pengidentifikasi fungsi untuk menghemat beberapa ruang.

0!a=a
i!a=(i-1)![sum$take j a|j<-[1..length a]]

Penggunaan (GHCi):

$ ghci partialsums.hs
GHCi, version 7.6.3: http://www.haskell.org/ghc/  :? for help
Loading package ghc-prim ... linking ... done.
Loading package integer-gmp ... linking ... done.
Loading package base ... linking ... done.
[1 of 1] Compiling Main             ( partialsums.hs, interpreted )
Ok, modules loaded: Main.
*Main> 1![-3, 4 ,7 ,-1 ,15]
[-3,1,8,7,22]
*Main> 3![-3, 4 ,7 ,-1 ,15]
[-3,-5,1,14,49]

Selamat datang di kode golf! Biasanya lebih pendek untuk mencocokkan pola daripada menggunakan penjaga, seperti 0!a=a i!a=....
xnor

Terima kasih @xnor - Saya sebelumnya menggunakan 'xs' ketika membangun kode awal dan pasti melewatkannya ketika saya memodifikasi kode dalam posting. Diedit.
Jake

Sebab sum(take j a), Anda dapat menghindari parens dengan melakukan sum$take j a, menggunakan prioritas tinggi $.
xnor

Terima kasih untuk bantuannya! Saya, untuk beberapa alasan, di bawah kesan yang $akan diutamakan daripada sintaks (dan mencoba untuk mengevaluasi sisa baris seperti yang ada). Tentu saja, itu bahkan tidak masuk akal.
Jake

2

R, 41 byte

function(x,n){for(i in 1:n)x=cumsum(x);x}

2

C #, 52 + 85 = 148 137 byte

using E=System.Collections.Generic.IEnumerable<int>;

dan

E I(E s,int i){int t=0;return i<1?s:I(System.Linq.Enumerable.Select(s,v=>t+=v),i-1);}

Ini menggunakan praktik yang tidak lazim ( v=>t+=v), tetapi ini adalah PPCG. Perhatikan juga batasan kedalaman tumpukan.


2

Python 3, 73

Mungkin bisa bermain golf sedikit lebih jauh.

def f(n,i):
 p=0;c=[]
 for m in n:p+=m;c+=[p]
 f(c,i-1)if i else print(n)

Versi ini menggunakan numpy, yang terasa sedikit seperti curang, tetapi ini dia:

Python 3 (dengan numpy), 72

from numpy import*
def f(n,i):
 if i:c=cumsum(n);f(c,i-1)
 else:print(n)

2

C ++ 14, 102 103 94 + 17 (termasuk) = 111 byte

#include<vector>
auto f(std::vector<int>a,int n){for(;n--;)for(int i=0;i<a.size()-1;++i)a[i+1]+=a[i];return a;}

Tidak disatukan, dengan test case

#include <vector>
#include <iostream>

auto f(std::vector<int> a, int n)
{
    for (; n--;)
        for (int i = 0; i < a.size() - 1; ++i)
            a[i + 1] += a[i];
    return a;
}


int main()
{
    auto t = f({-3, 4, 7, -1, 15}, 3);
    for (int i : t)
        std::cout << i << " ";
}

Bergantung pada urutan evaluasi. Tidak yakin apakah itu UB atau tidak, tetapi berfungsi Ini bergantung pada kompiler, jadi saya mengubahnya.


Alih-alih menghitung jdari 0 hingga n, hitung nmundur menjadi 0. Memberikan 97 byte menurut hitungan saya.
Jerry Coffin

@JerryCoffin Terima kasih ..
Zereges


1

Burlesque, 10 byte

{q++pa}jE!

itu tidak terlalu efisien secara umum tetapi itu berhasil.

blsq ) {-3 4 7 -1 15} 1 {q++pa}jE!
{-3 1 8 7 22}
blsq ) {-3 4 7 -1 15} 3 {q++pa}jE!
{-3 -5 1 14 49}

1

C ++ 14, 67 byte

Sebagai lambda tanpa nama memodifikasi inputnya, diperlukan csebagai wadah akses-acak seperti vector<int>.

[](auto&c,int n){while(n--)for(int i=0;i++<c.size();c[i]+=c[i-1]);}



0

Aksioma 213 47 byte

m(a,b)==(for i in 1..b repeat a:=scan(+,a,0);a)

ungolf dan beberapa contoh

 (3) -> [m([-3,4,7,-1,15],1), m([-3,4,7,-1,15],3)]
    Compiling function l with type List Integer -> List Integer
    Compiling function m with type (List Integer,Integer) -> List
       Integer

    (3)  [[- 3,1,8,7,22],[- 3,- 5,1,14,49]]
                                                       Type: List List Integer
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.