Iterierte Teilsummen


23

Die Teilsummen einer Liste von ganzen Zahlen [a 1 , a 2 , a 3 , ..., a n ] sind

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

Wir können dann die Liste der Teilsummen [s 1 , s 2 , s 3 , ..., s n ] nehmen und ihre Teilsummen erneut berechnen, um eine neue Liste zu erzeugen, und so weiter.

Verwandte: Iterierte Forward-Differenzen

Eingang:

  • Eine nicht leere Liste von ganzen Zahlen
  • Eine positive Anzahl von Iterationen,

Ausgabe: Gibt die Liste der Ganzzahlen aus, die sich aus der mehrfachen Verwendung der Teilsummen ergibt, oder gibt sie zurück.

Wenigste Bytes gewinnt. Built-Ins sind in Ordnung, auch wenn sie das Problem direkt lösen.

Testfälle:

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

Bestenliste:


Müssen die Argumente in derselben Reihenfolge sein, oder kann die Anzahl der Iterationen vor der Liste der Zahlen stehen?
kirbyfan64sos

@ kirbyfan64sos Entweder bestellen.
Xnor

Antworten:


14

J, 5 Bytes

+/\^:

Versuchen Sie es online auf J.js .

Wie es funktioniert

  • /\ ist ein Adverb (Funktion, die ein linkes Argument annimmt), das sich kumulativ um sein Argument verringert.

  • Also +/\ist das kumulative Summenverb .

  • ^:ist die Machtverbindung ; (f ^: n) ytrifft finsgesamt nmal zu auf y.

  • Der Verb-Konjunktionszug +/\^:bildet ein Adverb, das +/\so oft wiederholt wird, wie im (linken) Argument angegeben.

    x (+/\^:) ywird analysiert als (x (+/\^:)) y, was der Ausführung entspricht (+/\^:x) y.

Vielen Dank an @Zgarb für seine Hilfe bei der Erklärung.


13

Mathematica, 19 Bytes

Gut wenn Einbauten okay sind ...

Accumulate~Nest~##&

Definiert eine Funktion mit derselben Signatur wie die Beispiele in der Challenge. Ich bin mir ziemlich sicher, dank des langen Namens, Accumulatedass dies von den Golfsprachen und der APL-Familie leicht zu übertreffen sein wird. :)

Um den Kommentar von LegionMammal978 für diejenigen zu erläutern, die Mathematica nicht verwenden:

##Stellt eine Folge von Funktionsparametern dar (ähnlich einer Liste, die automatisch "splattet", wo immer sie eingefügt wird, wenn Sie mit diesem Begriff aus einer Sprache Ihrer Wahl vertraut sind). Das ~sind syntaktischer Zucker für Infix Funktionsaufruf, so dass , wenn wir die Funktion mit Parametern aufrufen listund nund alles erweitern, erhalten wir:

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

Das ist genau die Argumentreihenfolge, die von erwartet wird Nest.


Das ist interessant, mit Infix-Notation für 3 Argumente mit SlotSequence...
LegionMammal978

9

Haskell, 26 23 Bytes

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

Dies definiert eine anonyme Funktion, die wie folgt aufgerufen wird:

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

Vielen Dank an @nimi für das Speichern von 3 Bytes.

Erläuterung

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

Sehr schön! Und danke für die Erklärung!
Jake

2
Go pointfree, dann können Sie auch den Namen für die Funktion weglassen: (!!).iterate(scanl1(+)).
nimi

@ nimi Danke! Irgendwie
dachte

9

APL, 9 8 Bytes

{+\⍣⍺⊢⍵}

Dies definiert eine dyadische Funktion, die die Iterationen und Listen als linkes und rechtes Argument akzeptiert.

Vielen Dank an @NBZ für das Golfen ab 1 Byte!

Probieren Sie es online auf TryAPL aus .

Wie es funktioniert

  • und sind die linken und rechten Argumente für die Funktion.

  • +\ ist kumulativ um die Summe zu reduzieren.

  • ⍣⍺wiederholt die vorhergehenden Operatorzeiten .

  • ⊢⍵Wendet die Identitätsfunktion auf an .

    Dies ist eine kürzere Methode zum Parsen des Codes als (+\⍣⍺)⍵anstelle von +\⍣(⍺⍵).

Zusammen bewerben wir uns +\insgesamt mal um


@AlexA .: Dann wäre das nicht +\⍣⎕⊢⎕akzeptabel? ( Ist wie Python input()).
Marinus

1
@marinus Wird das tatsächlich außerhalb einer REPL gedruckt? Die einzigen Desktop-Interpreten, denen ich später zuweisen müsste .
Dennis

5

Matlab, 41 Bytes

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

Recht einfach. Ich finde es immer noch ziemlich ärgerlich, keine eingebaute Methode zur Erstellung stückweise definierter anonymer Funktionen oder Anker in Rekursionen zu haben.

Ungolfed:

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

5

JavaScript (ES6) 38

Überraschend klein, wenn .map rekursiv verwendet wird

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 Bytes

{y+\/x}

Sehr ähnlich der J-Lösung. +\Führt präzise eine Teilsumme aus und /iteriert , wenn ein monadisches Verb und ein ganzzahliges linkes Argument angegeben sind, eine festgelegte Anzahl von Malen, wie bei einer "for" -Schleife. Der Rest packt es einfach so zusammen, dass es der Reihenfolge der Argumente entspricht.

  {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

Getestet in Kona und OK .

Bearbeiten:

Wenn ich die Argumente umkehren darf, wie @ kirbyfan64sos festgestellt hat, kann ich ganz auf die Funktionsumhüllung verzichten:

+\/

Aufgerufen wie:

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

Dies funktioniert sowohl in k2.8 als auch in k5 einwandfrei. In oK funktioniert es nicht, da dieser Interpreter noch keine Curry-Adverbien (auch als "projizierte Adverbien" bezeichnet) unterstützt und aus weniger eindeutigen Gründen in Kona nicht ordnungsgemäß zu funktionieren scheint.

edit : Seit ein paar Tagen +\/funktioniert die Formulierung auch in OK.


1
Die Argumente können umgekehrt werden , daher denke ich, dass Sie möglicherweise einige Bytes sparen können.
kirbyfan64sos

3 +\/ -3 4 7 -1 15Funktioniert in Kona einwandfrei, kann aber keiner Funktion zugewiesen werden. Seltsam ...
Dennis

Ja, Kona behandelt eindeutig nicht 3+\/-3 4 7 -1 15dasselbe wie +\/[3;-3 4 7 -1 15]- ich frage mich, ob sie das erstere als speziellen syntaktischen Fall behandeln.
JohnE

4

Pyth, 9 Bytes

usM._GvwQ

Probieren Sie es online aus: Demo oder Test Suite

Erläuterung

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 Bytes

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

Das braucht wirklich nicht viel Erklärung. Es ist eine rekursive Funktion, wenn y==0dann nur x ausgegeben wird. Ansonsten dekrementiere y, führe ein Cumsum durch und rekursiere. Wahrscheinlich nicht die bestmögliche Julia-Lösung, ich arbeite noch daran.


4

Labyrinth , 73 Bytes

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

Es ist schon eine Weile her, dass ich im Labyrinth etwas beantwortet habe, und das schien machbar. :)

Das Eingabeformat ist eine flache Liste mit der Anzahl der Iterationen zuerst (und dann der Liste, auf die die Teilsummen angewendet werden sollen). Trennzeichen spielen keine Rolle, solange nach der letzten Ganzzahl kein Zeichen steht. Daher können Sie Folgendes verwenden:

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

Die Ausgabe ist durch Zeilenumbrüche getrennt:

-3
-5
1
14
49

4

R, 75 Bytes

Es ist lang, aber eine andere Einstellung ... die Berechnung der gewünschten Sequenz direkt anstelle von kumulierten Summen:

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

Man beachte, dass die Koeffizienten der Terme von xi für cumsum ^ n (x) Diagonalen des Pascalschen Dreiecks sind. dh

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: um eine funktion zu machen


4

Python 2, 67

Dies verwendet dieselbe Summe wie Anthony Roitman und dieselbe Rekursion wie Morgan Thrapp .

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

Ich habe diese Lösung entwickelt, bevor ich ihre gesehen habe, und dann schien es einfacher, sie als Antwort zu veröffentlichen, anstatt sie einem oder beiden zu kommentieren.


4

Python, 113 93 89 76 Bytes

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

Es funktioniert für beide Testfälle. Dank an Status, Morgan Thrapp und Ruth Franklin, die mir geholfen haben, das Programm auf 93, 89 bzw. 76 Bytes herunterzuspielen.


1
Sie können eine Anzahl von Bytes ausschneiden, indem Sie die zweite Schleife in ein Listenverständnis umwandeln. Das heißt, k=[sum(l[:j+1])for j in range(len(l))]. Dann mit ;k=langeheftet am Ende, können Sie dies alles auf eine Linie mit der for iSchleife schieben .
Status

1
Sie können die k=[sum(l[:j+1])for j in range(len(l))];l=kin dieselbe Zeile wie die for-Schleife verschieben, um 2 Byte zu speichern, und das Leerzeichen zwischen den Argumenten von f entfernen, um ein weiteres Byte zu speichern.
Morgan Thrapp

Wie Sie den Wert nicht verwenden i, können Sie ersetzen for i in range(n)mit for i in[0]*n(weil alle kümmern uns um die Länge nicht die Elemente der Liste). Und ich denke, Sie können es tun, ohne die Hilfsliste zu verwenden kund nur das Argument zu ändern l.
Ruth Franklin

4

Gol> <> 0,3,10 , 22 Bytes

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

Die erste Ganzzahl ist die Iterationsnummer und der Rest bildet die Liste. Die endgültige Liste wird zeilenweise getrennt ausgegeben.

Die Sprache ist noch recht jung und instabil, aber da ich ziemlich auf diese Operatoren eingestellt bin, dachte ich, es wäre okay.

Erläuterung

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

Um zu sehen, warum dies funktioniert, versuchen wir ein kleines Beispiel [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 Bytes

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

Eine rekursive Funktion, die sowohl in der Liste lals auch in der Anzahl der Iterationen rekursiv ist n. Lassen Sie es uns aufschlüsseln.

Betrachten wir zunächst eine rekursive Funktion g, bei der die Teilsumme nur einmal durchlaufen wurde.

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

Bei einer leeren Liste lgibt dies sich lselbst zurück, die leere Liste. Ansonsten ist der letzte Eintrag der Teilsummen von ldie Gesamtsumme von l, die an das rekursive Ergebnis für alle bis auf das letzte Element von angehängt wirdl .

Betrachten wir nun eine Funktion f, die gfür nIterationen gilt.

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

Wenn dies der Fall nist 0, wird die Liste lunverändert zurückgegeben. Andernfalls wird sie geinmal angewendet und anschließend frekursiv mit einer verbleibenden Iteration weniger aufgerufen.

Betrachten wir nun noch einmal den eigentlichen Code, der die beiden Rekursionen zu einer einzigen Funktion kombiniert. Die Idee ist, g(l)als Sonderfall zu behandeln f(l,1).

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

Wir haben f(g(l),n-1)von der vorherigen Definition erweitert g(l)in g(l[:-1])+[sum(l)], und dann ersetzt g(_)mit f(_,1)auf , um die rekursive Anrufe beschränkt f.

Für den Basisfall möchten wir zurückkehren, lwann immer n==0oder l==[]. Wir kombinieren diese, indem wir feststellen, dass eine der beiden n*lListen die leere Liste ist, die Falsy ist. Wir greifen also immer dann zu, wenn n*les nicht leer ist, und kehren lansonsten zurück.

Obwohl es zwei rekursive Aufrufe gibt, fführt dies nicht zu einer exponentiellen Explosion der rekursiven Definition der Fibonacci-Zahlen, sondern bleibt quadratisch.


3

C ++ (61 + 17 = 78 Byte)

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

Testfall:

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

Dies lässt sich leicht mit der Spezifikation vereinbaren: Es wird ein Array im C-Stil verwendet, das Zeiger an den Anfang und das Ende des Arrays übergibt. Intern ist es, wie Sie sehen, nur eine extrem dünne Hüllestd::partial_sum in der Standardbibliothek. Anstatt den resultierenden Wert tatsächlich zurückzugeben, wird lediglich das übergebene Array geändert.

Wenn es uns nichts ausmacht, Definitionen von Dingen an ihre Grenzen zu treiben (und vielleicht sogar darüber hinaus), können wir eine "Funktion" in einem Lambda-Ausdruck definieren:

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

Dies reduziert die Definition der Funktion (-ähnliches Objekt) auf dieses Stück:

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

... für 40 Bytes (+17 für die #include).


Wau, ich hatte nicht erwartet, dass STL einen Algorithmus zum Zählen von Teilsummen hat.
Zereges

1
@Zereges: Niemand erwartet den spanischen Inquisit ... Oh, warte, wir machen C ++, nicht Python. Entschuldigen Sie.
Jerry Coffin


2

Haskell, 52 47 Bytes

Der erste Code-Golf-Versuch, und ich bin ein absoluter Haskell-Anfänger. Kommentare sind daher sehr willkommen! Bei der Frage nach dem erforderlichen Format des Funktionsaufrufs oder ob es sich um ein Argument für das Programm handelt, war nicht klar, weshalb ich das Ausrufezeichen als Funktionskennung verwendete, um einige Leerzeichen zu speichern.

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

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

Willkommen beim Code Golf! Normalerweise ist das Anpassen von Mustern kürzer als das Verwenden von Schutzvorrichtungen 0!a=a i!a=....
20.

Danke @xnor - Ich hatte zuvor 'xs' beim Erstellen des ursprünglichen Codes verwendet und musste es verpasst haben, als ich den Code im Beitrag geändert habe. Bearbeitet
Jake,

Für sum(take j a)Sie können Pars , indem Sie vermeiden sum$take j a, mit der hohen Priorität von $.
20.

Danke für deine Hilfe! Aus irgendeinem Grund hatte ich den Eindruck, dass $dies Vorrang vor der Syntax haben würde (und ich versuchte, den Rest der Zeile so zu bewerten, wie er ist). Das würde natürlich keinen Sinn ergeben.
Jake,

2

R, 41 Bytes

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

2

C #, 52 + 85 = 148 137 Bytes

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

und

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

Es werden unorthodoxe Praktiken verwendet ( v=>t+=v), dies ist jedoch PPCG. Beachten Sie auch die Einschränkung der Stapeltiefe.


2

Python 3, 73

Könnte wohl etwas weiter unten golfen werden.

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

Diese Version benutzt Numpy, was sich ein bisschen wie Schummeln anfühlt, aber hier ist es:

Python 3 (mit Zahl), 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 (Einschluss) = 111 Bytes

#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, mit Testfall

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

Verlässt sich auf die Reihenfolge der Bewertung. Ich bin mir nicht sicher, ob es UB ist oder nicht, aber es funktioniert. Es ist vom Compiler abhängig, also habe ich es geändert.


Anstatt jvon 0 bis n hoch zu zählen, zählen nSie bis 0 herunter. Gibt 97 Bytes durch meine Zählung.
Jerry Coffin

@ JerryCoffin Danke ..
Zereges


1

Burlesque, 10 Bytes

{q++pa}jE!

Es ist im Allgemeinen nicht sehr effizient, aber es macht den Trick.

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 Bytes

Als unbenanntes Lambda modifiziert es seine Eingabe und benötigt cso einen Random-Access-Container wie vector<int>.

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


1

Gelee , 3 Bytes

SƤ¡

Probieren Sie es online!

Dies ist meine ( Mr Xcoders ) Methode.

Gelee , 3 Bytes

+\¡

Probieren Sie es online!

Dies ist die Lösung von caird coinheringaahing .

Methode 1

Vollständiges Programm, dyadisch.

  ¡- N-mal wiederholt anwenden.
 Ƥ - Ordnen Sie den vorhergehenden Link den Präfixen der Liste zu.
S - Summe.
     - Implizit ausgeben

Methode # 2

+ \ ¡- Volles Programm, dyadisch.

  ¡- N-mal wiederholt anwenden.
 \ - kumulativ reduziert um:
+ - Ergänzung.

0

Axiom 213 47 Bytes

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

ungolf und ein beispiel

 (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
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.