Somme parziali iterate


23

Le somme parziali di un elenco di numeri interi [a 1 , a 2 , a 3 , ..., a n ] sono

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

Possiamo quindi prendere la lista delle somme parziali [s 1 , s 2 , s 3 , ..., s n ] e calcolare nuovamente le sue somme parziali per produrre un nuovo elenco e così via.

Correlati: differenze in avanti iterate

Ingresso:

  • Un elenco non vuoto di numeri interi
  • Un numero positivo di iterazioni,

Output: stampa o restituisce l'elenco di numeri interi risultanti dall'assunzione delle somme parziali più volte.

Vince il minor numero di byte. Gli incorporati sono OK anche se risolvono il problema.

Casi test:

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

Classifica:


Gli argomenti devono essere nello stesso ordine o il numero di iterazioni può precedere l'elenco dei numeri?
kirbyfan64sos,

@ kirbyfan64sos In entrambi i casi.
xnor

Risposte:


14

J, 5 byte

+/\^:

Provalo in rete su J.js .

Come funziona

  • /\ è un avverbio (funzione che accetta un argomento sinistro) che si riduce cumulativamente dal suo argomento.

  • Quindi +/\è il verbo somma cumulativa .

  • ^:è la congiunzione di potere ; (f ^: n) ysi applica fun totale di nvolte a y.

  • Il treno verbo-congiunzione +/\^:forma un avverbio che si ripete +/\tante volte quanto specificato nel suo argomento (a sinistra).

    x (+/\^:) yviene analizzato come (x (+/\^:)) y, che equivale all'esecuzione (+/\^:x) y.

Grazie a @Zgarb per il suo aiuto con la spiegazione.


13

Mathematica, 19 byte

Bene, se i built-in vanno bene ...

Accumulate~Nest~##&

Definisce una funzione con la stessa firma degli esempi nella sfida. Sono abbastanza sicuro, grazie al nome lungo Accumulateche questo sarà facilmente battuto dalle lingue del golf e dalla famiglia APL. :)

Per approfondire il commento di LegionMammal978 per coloro che non sono Mathematica:

##rappresenta una sequenza dei parametri della funzione (che è come un elenco che "si splatisce automaticamente" ovunque sia inserito, se hai più familiarità con quel termine dalla lingua che preferisci). L' ~sono zucchero sintattico per la funzione infisso invocazione, quindi se chiamiamo la funzione con parametri liste ned espandere tutto, si ottiene:

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

Che sembra essere esattamente l'ordine degli argomenti previsto da Nest.


È interessante, usare la notazione SlotSequence
infissa

9

Haskell, 26 23 byte

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

Questo definisce una funzione anonima, invocata come segue:

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

Grazie a @nimi per aver salvato 3 byte.

Spiegazione

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

Molto bella! E grazie per la spiegazione!
Jake,

2
Go pointfree, allora si può anche omettere il nome per la funzione: (!!).iterate(scanl1(+)).
nimi,

@nimi Grazie! In qualche modo ho pensato che la composizione non avrebbe funzionato a mio vantaggio qui ...
Zgarb

9

APL, 9 8 byte

{+\⍣⍺⊢⍵}

Questo definisce una funzione diadica che accetta le iterazioni e l'elenco come argomenti sinistro e destro.

Grazie a @NBZ per giocare a golf a 1 byte!

Provalo online su TryAPL .

Come funziona

  • e sono gli argomenti destro e sinistro della funzione.

  • +\ è cumulativo ridurre di somma.

  • ⍣⍺ripete i precedenti tempi dell'operatore .

  • ⊢⍵applica la funzione identità a .

    Questo è un modo più breve di analizzare il codice come (+\⍣⍺)⍵anziché +\⍣(⍺⍵).

Insieme, applichiamo +\un totale di volte a


@AlexA .: Quindi non +\⍣⎕⊢⎕sarebbe accettabile? ( è come Python input()).
Marin

1
@marinus Viene effettivamente stampato all'esterno di una REPL? Gli unici interpreti desktop che dovrei richiedere in seguito.
Dennis,

5

Matlab, 41 byte

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

Abbastanza semplice. Continuo a pensare che sia abbastanza fastidioso non avere un modo per creare funzioni anonime definite a tratti, o ancore nelle ricorsioni.

Ungolfed:

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

5

JavaScript (ES6) 38

Sorprendentemente piccolo usando .map in modo ricorsivo

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}

Molto simile alla soluzione J. +\esegue precisamente una somma parziale e quando /viene fornito con un verbo monadico e un argomento intero sinistro, scorre un determinato numero di volte, come un ciclo "for". Il resto lo sta semplicemente avvolgendo ordinatamente per adattarsi all'ordine degli argomenti.

  {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

Testato a Kona e oK .

Modificare:

Se mi è permesso invertire gli argomenti, come determinato da @ kirbyfan64sos, posso fare a meno della funzione che avvolge interamente:

+\/

Invocato come:

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

Funziona correttamente sia in k2.8 che in k5. Non funziona in oK poiché l'interprete non supporta ancora gli avverbi curry (ovvero "proiettati") e non sembra funzionare correttamente in Kona per ragioni meno chiare.

modifica : fino a pochi giorni fa, la +\/formulazione funziona anche in oK.


1
Gli argomenti possono essere invertiti , quindi penso che potresti essere in grado di radere qualche byte.
Kirbyfan64sos,

3 +\/ -3 4 7 -1 15funziona bene in Kona, ma non puoi assegnarlo a una funzione. Strano ...
Dennis il

Sì, Kona chiaramente non sta trattando 3+\/-3 4 7 -1 15lo stesso di +\/[3;-3 4 7 -1 15]- mi chiedo se trattano il primo come un caso sintattico speciale.
Giovanni,

4

Pyth, 9 byte

usM._GvwQ

Provalo online: Dimostrazione o Test Suite

Spiegazione

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

Questo in realtà non ha bisogno di molte spiegazioni. È una funzione ricorsiva, se y==0poi emette solo x. Altrimenti decrementa y, esegui un cumsum e ricorri. Probabilmente non è la soluzione Julia più giocosa possibile, ci sto ancora lavorando.


4

Labyrinth , 73 byte

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

È passato un po 'di tempo da quando ho risposto a qualcosa in Labyrinth, e questo sembrava fattibile. :)

Il formato di input è un elenco semplice con prima il numero di iterazioni (e quindi l'elenco a cui applicare le somme parziali). I delimitatori non contano tutto, purché non ci siano caratteri dopo l'ultimo numero intero, quindi puoi usare qualcosa di leggibile come:

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

L'output è separato da una nuova riga:

-3
-5
1
14
49

4

R, 75 byte

È lungo ma un approccio diverso ... calcolando direttamente la sequenza desiderata anziché le somme cumulative:

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

Notando che i coefficienti dei termini di xi per cumsum ^ n (x) sono diagonali del triangolo di Pascal. vale a dire

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, ....

modifica: per creare una funzione


4

Python 2, 67

Questo utilizza la stessa sommatoria di Anthony Roitman e la stessa ricorsione di Morgan Thrapp .

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

Ho sviluppato questa soluzione prima di vedere la loro, e poi mi è sembrato più semplice pubblicarla come risposta piuttosto che come commento a uno o entrambi.


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)

Funziona con entrambi i casi di test. Grazie a Status, Morgan Thrapp e Ruth Franklin per avermi aiutato a golf il programma fino a 93, 89 e 76 byte rispettivamente.


1
È possibile ritagliare un numero di byte modificando il secondo ciclo in una comprensione dell'elenco. Cioè, k=[sum(l[:j+1])for j in range(len(l))]. Quindi con la ;k=lvirata all'estremità puoi spingere tutto su una linea con il for icappio.
Stato

1
È possibile spostare il k=[sum(l[:j+1])for j in range(len(l))];l=ksimbolo sulla stessa riga del ciclo for per salvare 2 byte e rimuovere lo spazio tra gli argomenti di f per salvare un altro byte.
Morgan Thrapp,

Poiché non usi il valore di i, puoi sostituirlo for i in range(n)con for i in[0]*n(perché tutto ciò che ti interessa è la lunghezza e non gli elementi dell'elenco). E penso che tu possa farlo senza usare la lista ausiliaria k, modificando semplicemente l'argomento l.
Ruth Franklin,

4

Gol> <> 0.3.10 , 22 byte

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

Il primo numero intero è considerato il numero di iterazione e il resto costituisce l'elenco. L'elenco finale viene generato separato da una nuova riga.

La lingua è ancora piuttosto giovane e instabile, ma dal momento che sono abbastanza impostato su questi operatori ho pensato che sarebbe andato tutto bene.

Spiegazione

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

Per capire perché funziona, proviamo un piccolo esempio [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

Una funzione ricorsiva che ricorre sia nell'elenco lche nel numero di iterazioni n. Analizziamolo.

Innanzitutto, consideriamo una funzione ricorsiva gche ha ripetuto la somma parziale solo una volta.

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

Per un elenco vuoto l, questo restituisce lse stesso, l'elenco vuoto. In caso contrario, l'ultima voce delle somme parziali di lè la somma complessiva di l, che viene aggiunta al risultato ricorsivo per tutti tranne l'ultimo elemento di l.

Ora diamo un'occhiata a una funzione fche si applica galle niterazioni.

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

Quando nè 0, questo restituisce la lista linvariata e, in caso contrario, si applica guna volta, quindi chiama fricorsivamente con una iterazione in meno rimanente.

Ora diamo un'occhiata al codice reale, che combina le due ricorsioni in un'unica funzione. L'idea è di trattare g(l)il caso speciale f(l,1).

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

Abbiamo preso f(g(l),n-1)dalla definizione precedente, espanso g(l)in g(l[:-1])+[sum(l)]e poi sostituito g(_)con f(_,1)per limitare le chiamate ricorsive a f.

Per il caso di base, vogliamo tornare logni volta n==0o l==[]. Uniamo questi notando che uno dei due n*lè la lista vuota, che è Falsy. Quindi, ricerchiamo ogni volta che n*lnon è vuoto, e ritorniamo laltrimenti.

Anche se ci sono due chiamate ricorsive a f, questo non provoca un esponenziale esplodere la definizione ricorsiva dei numeri di Fibonacci, ma rimane quadratico.


3

C ++ (61 + 17 = 78 byte)

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

Caso di prova:

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

Ciò richiede una leggera libertà con le specifiche: utilizza un array in stile C, passando i puntatori all'inizio e alla fine dell'array. Internamente, come puoi vedere, è solo un wrapper estremamente sottile std::partial_sumnella libreria standard. Invece di restituire effettivamente il valore risultante, modifica semplicemente l'array che viene passato.

Se non ci dispiace spingere le definizioni delle cose al limite (e, probabilmente, un po 'oltre) possiamo definire una "funzione" in un'espressione 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 << " ";
}

Questo riduce la definizione della funzione (oggetto simile) a questo pezzo:

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

... per 40 byte (+17 per il #include).


Wau, non mi aspettavo che STL avesse un conto per contare somme parziali.
Zereges,

1
@Zereges: nessuno si aspetta l'inquisizione spagnola .... oh, aspetta, stiamo facendo C ++, non Python. Mie scuse.
Jerry Coffin,


2

Haskell, 52 47 byte

Il primo "tentativo" di codice in assoluto, e sono un principiante di Haskell, quindi i commenti sono benvenuti! Nella domanda non era chiaro quale sia il formato necessario della chiamata di funzione o se fosse stato preso da un argomento al programma, quindi ho usato il punto esclamativo come identificatore di funzione per salvare un paio di spazi.

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

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

Benvenuti nel codice golf! Di solito è più breve abbinare il motivo che usare le protezioni, come 0!a=a i!a=....
xnor

Grazie @xnor - In precedenza avevo usato 'xs' durante la creazione del codice iniziale e dovevo averlo perso quando ho modificato il codice nel post. Modificato.
Jake,

Per sum(take j a), puoi evitare le parentesi facendo sum$take j a, usando l'alta precedenza di $.
xnor

Grazie per l'aiuto! Ero, per qualche motivo, sotto l'impressione che $avrebbe avuto la precedenza sulla sintassi (e provavo a valutare il resto della linea così com'è). Certo, non avrebbe nemmeno senso.
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>;

e

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

Utilizza pratiche non ortodosse ( v=>t+=v), ma questo è PPCG. Notare anche il vincolo di profondità dello stack.


2

Python 3, 73

Probabilmente potrebbe essere ulteriormente abbattuto.

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

Questa versione usa intorpidimento, che sembra un po 'barare, ma eccolo qui:

Python 3 (con 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 (include) = 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;}

Ungolfed, con 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 << " ";
}

Si basa sull'ordine di valutazione. Non sono sicuro che sia UB o meno, ma funziona Dipende dal compilatore, quindi l'ho cambiato.


Invece di contare jda 0 a n, conto nalla rovescia fino a 0. Fornisce 97 byte dal mio conteggio.
Jerry Coffin,

@JerryCoffin Grazie ..
Zereges,


1

Burlesque, 10 byte

{q++pa}jE!

non è molto efficiente in generale, ma fa il trucco.

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

Come lambda senza nome che modifica il suo input, richiedendo ccome un contenitore ad accesso casuale simile vector<int>.

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


1

Gelatina , 3 byte

SƤ¡

Provalo online!

Questo è il mio metodo (di Mr Xcoder ).

Gelatina , 3 byte

+\¡

Provalo online!

Questa è una caotica moneta la soluzione .

Metodo n. 1

SƤ¡ - Programma completo, diadico.

  ¡- Applicare ripetutamente, N volte.
 Ƥ - Mappa il link precedente sui prefissi dell'elenco.
S - Somma.
     - Uscita implicita

Metodo n. 2

+ \ ¡- Programma completo, diadico.

  ¡- Applicare ripetutamente, N volte.
 \ - Riduzione cumulativa di:
+ - Aggiunta.

0

Axiom 213 47 byte

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

ungolf e qualche esempio

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