Aufsummieren mal anders

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
duodiscus
User
Beiträge: 97
Registriert: Sonntag 6. April 2014, 16:10

Hallo zusammen,
wenn ich eine Summe von Werten bilden wollte, habe ich dieses bisher immer mit einer Schleife gelöst:

Code: Alles auswählen

def summe(n):
    summe=0
    for i in range(n):

        summe = summe + i+1
        
    print(summe)
Wie könnte ich denn eine Aufsummierung der Zahlen rekursiv angehen? Also das sich die Funktion immer wieder selbst aufruft und die Werte bis n aufsummiert? Kann mir da jemand was zu sagen? Vielen Dank!
duodiscus
User
Beiträge: 97
Registriert: Sonntag 6. April 2014, 16:10

Habe es schon.

Code: Alles auswählen


return n + SummeRek(n-1)
Benutzeravatar
snafu
User
Beiträge: 6741
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Wohl eher so:

Code: Alles auswählen

def gib_summe(n):
    return n + gib_summe(n - 1) if n > 1 else n
Denn ohne eine Abbruchbedingung wird die rekursive Aufrufkette niemals beendet. Außer natürlich, wenn der Stack voll ist. Wobei die Abbruchbedingung keinesfalls nur ein notwendiges Übel ist, sondern vielmehr einen essentiellen Bestandteil für die dahinter stehende Logik darstellt.

Und falls man mal was ganz Verrücktes machen möchte:

Code: Alles auswählen

def gib_summe(n):
    return sum(range(n + 1))
Oder auch total crazy:

Code: Alles auswählen

def gib_summe(n):
    return (n**2 + n) / 2
BlackJack

Und wieder eine Hausaufgabenlösung für duodiscus. Hihihi. :-)
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

In Scala mit Endrekursion

Code: Alles auswählen

package Summen

import scala.annotation.tailrec

object Summe {

  def main(args: Array[String]) {
    println("Summe von 5 ist " + sum(5))
  }

  def sum(limit: Int) = {

    @tailrec
    def sumAcc(acc: Int, rest: Int): Int =
      if (rest == 0) acc
      else sumAcc(acc + rest, rest - 1)

    sumAcc(0, math.abs(limit))
  }

}
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
BlackJack

Vielleicht noch die *vernünftige* Lösung für diese Aufgabe, die weder iterativ noch rekursiv ist:

Code: Alles auswählen

def gib_summe(n):
    return n * (n + 1) / 2
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

BlackJack hat geschrieben:Vielleicht noch die *vernünftige* Lösung für diese Aufgabe, die weder iterativ noch rekursiv ist:
Ach komm... der kleine Gauß wäre doch auch nie darauf gekommen, wenn seine REPL nicht aus Schiefer gewesen wäre :twisted:
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Hier noch mal der rekursive Ansatz in Clojure (Wieso gibt es da kein Syntax-Highlighting? Nicht mal irgend ein Lisp / Scheme finde ich da :-( )

Code: Alles auswählen

(defn sum [n]
  (loop [acc 0 rest n]
    (if (zero? rest)
      acc
      (recur (+ acc rest) (dec rest)))))
Dabei fiel mir ein, dass wir den über ``reduce`` "vergessen" haben, also auch den mal in Clojure:

Code: Alles auswählen

(defn sum [n]
  (reduce + (range 1 (+ n 1))))
Zuletzt geändert von Hyperion am Dienstag 27. Mai 2014, 19:12, insgesamt 1-mal geändert.
Grund: Code auf Clojure gestellt - es klappt ja auch hier :-D
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
BlackJack

@Hyperion: Lisp und Scheme kann man manuell angeben. Aber wie man sieht, sind die nicht besonders.
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Danke für den Tipp... ja, bringt jetzt nicht so viel :-D

Verwendet das Board hier Geshi? Dafür gibts ne Implementierung: Link
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
BlackJack

@Hyperion: Jup, das Board verwendet Geshi.
Benutzeravatar
snafu
User
Beiträge: 6741
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Steht ja nur unter jedem Codeblock rechts unten... :roll: :twisted: :wink:
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

snafu hat geschrieben:Steht ja nur unter jedem Codeblock rechts unten... :roll: :twisted: :wink:
Ja hab ich die Zeit und Muße alles zu lesen... :oops:

Auf uu.de gibt's Clojure Highlighting bereits - Pygments sei dank :-)

Edit: Hier auch! s.o.
@BlackJack: Man kann auch "clojure" von Hand angeben - da geht vermutlich also so ziemlich alles von Geshi :-)
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
BlackJack

Dann will ich auch mal etwas Rekursives beisteuern. Langweiliges JavaScript:

Code: Alles auswählen

var sum = function (n) { return (n > 0) ? n + sum(n - 1) : 0; };
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Dann mache ich mal mit:

Code: Alles auswählen

sum = lambda n: (lambda f, x: f(f, x))(lambda f, x: x + f(f, x - 1) if x > 0 else 0, n)
Das Leben ist wie ein Tennisball.
DasIch
User
Beiträge: 2718
Registriert: Montag 19. Mai 2008, 04:21
Wohnort: Berlin

Wirklich elegant lässt sich sowas doch nur in Opal implementieren:

Sum.sign

Code: Alles auswählen

SIGNATURE Sum

IMPORT Nat ONLY nat
       Seq ONLY seq


FUN sum : seq[nat] -> nat
Sum.impl

Code: Alles auswählen

IMPLEMENTATION Sum

IMPORT Nat COMPLETELY
       Seq COMPLETELY
       SeqReduce COMPLETELY


DEF sum(ns) == (+, 0) \ ns
BlackJack

Iterativ in 6510-Assembler:

Code: Alles auswählen

!zone
; In:   A = n
; Out:  A/X = sum from 1 to n
;       Y = 0
; Uses: A, X, Y, r1
sum:
        ldx #0
        tay
        cpy #0
        beq .exit
        stx r1
-
        clc
        tya
        adc r1
        sta r1
        bcc +
        inx
+
        dey
        bne -

        lda r1
.exit:
        rts
Antworten