So, 3, 2, 1, 14.15 Uhr in Deutschland.
Schönen guten Tag. Herzlich willkommen zur Vorlesung 8.
Das Thema der Vorlesung. Heute ist Rekursion. Wer von
Ihnen hat schon mal was von Rekursion gehört?
Wer von Ihnen hat noch nicht von Rekursion gehört?
So wenige. Werden Sie das heutzutage in der Schule?
Muss wohl, ne? Interessant. Ja, okay,
das könnte die Aufgabe einfacher machen.
Ich habe eben dieses hahaha lustige Video vor der Vorlesung gezeigt
Weil ich werde Rekursionen an der einen oder anderen Stelle motivieren,
indem ich das, was beim Kopfrechnen schwieriger ist,
schwierig ist, auf ein einfacheres Problem zurückführen werde.
Und ich hoffe, dass ich damit also diejenigen,
die von Rekursionen noch nie was gehört haben,
also eine erste Motivation geben kann, für das Thema und denjenigen,
die schon mal was davon gehört haben, so unsere Sicht,
unsere Sichtweise auf das Thema zu verdeutlichen.
Letzte Woche haben wir in der Reihe elementare Kontrollstrukturen,
haben wir sozusagen den metaphorisch gesprochen, den Deckel drauf gemacht,
indem wir uns mit verschiedenen Arten von Schleifenkonstruktionen,
verschiedenen Arten von Wiederholungen
beschäftigt haben
Und heute geht es darum, zu sagen, ach,
eigentlich braucht man das gar nicht. Eigentlich ist es so,
die Schleifenkonstruktion ist also mehr als überflüssige,
mehr als überflüssiges Konstrukt in einer Programmiersprache, namentlich in sogenannten funktionalen Programmiersprachen,
in denen sie zwar die Sequenz finden werden und die Fallunterscheidung,
aber keine Schleifenkonstruktion.
Oder fragt man sich natürlich, als jemand, der,
also von Rekursion noch nichts gehört hat, aha,
das mit den Schleifen war mir dunkel,
so vielleicht gibt es ja Hoffnung, ich brauche das gar nicht verstehen.
Also wenn ich Rekursion verstanden habe,
das ist jetzt eine Alternative, also die mit Rekursion umzugehen,
ist eine Alternative, um Wiederholungen zu vermeiden,
also Schleifenkonstruktion
Bevor ich jetzt, also ich habe jetzt schon hundertmal Rekursionen gesagt,
also bevor ich sage, was das jetzt so eigentlich ist,
sage ich, machen wir mal kurz einen Rückgriff.
Wir kennen ja schon Funktionsaufrufe und nun mal noch so kurz als Wiederholung,
als Einstimmung auf das, was da passiert,
wenn Funktionen aufgerufen werden, sodass der eine Punkt,
der auf dieser Folie gemacht wird, da geht es also um Parameterübergabe,
um Bindung von aktuellen Werten an Namen, an Bezeichnen.
Das gucken wir uns kurz an. Am Beispiel dieser Funktion Even,
also die Prüfung, ob ein übergebener Wert N, ob der ganz zahlig ist.
Das bedeutet der Name jedenfalls an und dann kann man sich diese Funktionsdefinition nochmal anschauen,
haben, man muss also dieses N durch zwei Teilen und dann das wieder mit zwei,
das Ergebnis, mit zwei multipliziert und wenn dann dieselbe Zahl rauskommt,
wie die, die man reingesteckt hat,
dann ist es wohl eine gerade Zahl.
Okay, wir machen uns das am Beispiel, wie die Bindung und die Auswertung stattfindet, hier in diesem Beispiel, klar. Wir übergeben also als aktuellen Parameter 8,
es wird also,
die 8 wird an das N gebunden und dann muss halt noch dieser Ausdruck insgesamt ausgewertet werden und das ist also ziemlich neudeutsch gesprochen,
straightforward, 8. F2 ist 4,
das Ganze wird multipliziert mit zwei, sehen Sie hier,
Auswertung von, wenn diese Auswertung stattgefunden hat,
dann wird noch gefragt, ob 8 gleich 8 ist,
das ist der Fall und dann wird als Ergebnis dieses Ausdrucks,
wird also der Wahrheitswert true, war ja zurückgeliefert.
So, so funktioniert also Aufrufen von Funktionen und so kennen,
also das Worüber wir ja nie gesprochen haben, ist,
dass das Even, also die Realisierung des Even, basiert darauf,
dass also ein etwas größeres Problem in kleinere Teilprobleme, aber andere Probleme zerlegt wird.
So, die anderen Probleme,
mit denen wir es hier zu tun haben,
wir gehen also davon aus, bei unserer Realisierung von Even,
ist das so eine Funktion wie, oder ein Operator,
Schreibweise, da können wir auch als Funktion schreiben,
so eine Funktion wie Division, ganzzahlige Division,
eine Funktion wie das Multiplizieren, das so etwas,
so wahlweise in der Programmiersprache vorhanden ist oder wir uns das selbst geschrieben haben.
Also es gibt eine Funktion, die wird dadurch realisiert,
dass auf primitivere Funktionen zurückgegriffen wird. So,
und das ist so der Stand der Kunst und solche Funktionen
können sie ja heutzutage in Java auch schon schreiben,
tun sie ja auch
In ihren Übungen seit mittlerweile acht Wochen, sechs Wochen,
so minus die zwei Wochen, Carol.
Das ist die, das, davon gehe ich jetzt mal aus,
dass sie das, das ist für sie kein Problem.
So, jetzt. Was ist Rekursion? Was verstehen wir
da drunter? Wie wollen wir diesen Begriff jetzt definieren?
Und dann nehmen wir uns natürlich, also den Duden,
den Informatik-Duden in diesem Fall, was wir da tun,
so die, also Definition von Rekursion geht so, löse ein Gesamtproblem.
Bis jetzt ist es, aha, durch die Aufspaltung in gleichartige, einfachere Teilprobleme.
So, mit der Betonung auf gleichartig und einfacher.
Das gehört dazu. Also nicht wie im Beispiel von Even,
dass man auf ein anderes Problem das zu lösende Problem reduziert,
sondern das Problem durch eine gleichartige, einfachere Version, Teilproblem löst.
Das ist jetzt eine sogenannte Intentionale Definition, intentional bedeutet von
der Struktur her. Wir werden gleich Extensionen, eine extensionale,
also sprich an Beispielen, orientierte Definition uns noch anschauen,
beziehungsweise wir werden uns einfach Beispiele anschauen, die nach dieser intensionalen Grundidee strukturiert sind.
So, jetzt steht was dazu. Gott, der Stellenwert der Rekursion,
das ist jetzt, nachdem wir gerade gelernt haben,
dass unsere Bundesbildungsministerin ist Mathematikerin und da gibt es ja so wenig,
wie ich davon verstehe,
ist das jedenfalls eine andere Art von Wissenschaft als,
sagen wir mal, bei den Juristen.
Da heißt es ja, da verstehe ich auch nichts,
aber so von außen betrachtet zwei Juristen
drei Meinungen
Jetzt kann man bei den Informatikern, ist das eigentlich ähnlich wie bei den Juristen.
Können Sie zwei oder drei Informatiker fragen, was ist denn der stellenwerte Rekursion?
Muss ich mich damit beschäftigen? Und dann werden Sie sicherlich Leute finden,
die sagen, also ohne Rekursion geht gar nicht,
das ist mit eines der, es gibt keinen Superlativ von zentral,
also werden die nicht sagen,
das ist eines der zentralsten Mittel in der Informatik, in der Softwareentwicklung.
Es ist aber auf jeden Fall, also koste es,
was es wolle, einen intellektuellen Gehirnschwalz, den Sie da investieren müssen,
es geht nicht ohne Rekursion in der Softwareentwicklung. Und das hat,
gerade heute kriegt es auch wieder einen etwas,
also ich könnte auch sagen, noch höheren Stellenwert,
in den Zeiten, in denen sie mit,
also sie gehen ja ganz selbstverständlich, vielleicht ohne,
dass sie das wissen, also mit Multikern, Applikationen um,
also in dem Moment, wo parallele Datenverarbeitung gefordert ist,
Parallelisierung von Verarbeitungsschritten.
Da spielt die funktionale Programmierung, also das ausschließliche Um,
der ausschließliche Umgang mit Funktionen in der Programmierung,
spielte eine sehr große Rolle und ein Konstruktionsmittel für Funktionen ist die Rekursion.
Das heißt also, wenn Sie hier den Stellenwert sehen,
ja, kann man so sagen, also ohne Rekursion,
denke ich, ohne ein grundlegendes Verständnis von Rekursion, gibt es keine fortschrittliche Softwareentwicklung.
Ein paar Anwendungsfälle, die wir hier im Rahmen von SE1 auch kennenlernen werden,
sehen Sie hier, insbesondere so in der zweiten Hälfte des Semesters,
werden wir uns mit sogenannten rekursiven Datenstrukturen,
also sowas wie Listen und Bäumen beschäftigen,
aber auch mit Sortieralgorithmen und da ist Rekursu,
da geht es,
also da sind rekursive Algorithmen,
sind da
ganz schön wild
So, jetzt glaube ich zu dem Vorspiel zurück.
Wir stellen uns jetzt mal vor, kopfrechnend ist uns zu schwierig.
Also so eine Aufgabe wie 13 plus 15. Und wenn man dann sieht,
also wie kompliziert also man sich das Leben machen kann,
wenn es um Additionen geht, dann denkt man, oha,
ja, das ist ja in der Tat viel schwieriger, als ich dachte.
Zumal, also das ist auch in dem,
ich habe das heute erst gemerkt,
nach ungefähr 15 Jahren Vortragen dieser Folie,
dass da eine Klammer fehlt, in ihren,
so wie ich das gestern ins Web hoch,
jetzt kommen sie hochgeladen habe, da ist die auch nicht.
Also die fehlt. Bitte tragen sie das doch nach bei Gelegenheit.
Nicht, dass sie sich also in zehn Jahren,
wenn sie wehmütig nochmal durch ihre Unterlagen gehen und sagen,
Mensch, da habe ich auch noch einen Fehler gefunden.
Nee, der ist einer. Ja, den haben sie
gefunden, aber ich weise sie hiermit darauf hin.
So, was steht denn jetzt hier eigentlich
Wie ist die Addition, wie ist die mathematisch definiert?
Was da steht, also in einer Infix-Notation, führen.
Die Addition A, A, B, zurück auf folgendes kleineres Problem.
Bilde den Nachfolger der Summe von A und der zweite Operant ist hier,
des A,
ist der Vorgänger von B. Jetzt könnte ich aber einen Floh husten hören,
so gebannt, wie sie offensichtlich zuhören.
Das lassen wir uns jetzt mal durch den Kopf gehen,
was da steht als Definition. Vielleicht helfen wir uns,
indem wir eine andere Schreibweise uns mal anschauen.
Diese Schreibweise geht so. Also ich will zwei Zahlen,
A und B addieren
Und es gibt einen einfachen Fall. Wenn die zweite Zahl null ist,
dann ist das Ergebnis A. Das ist doch einfach, oder?
A und null, dann ist das Ergebnis A. Okay,
da können wir jetzt mal einen Haken dran machen.
Aber sonst, was ist sonst das Ergebnis?
Wir nehmen das, was ich vorhin mache, das,
was ich vorhin, also in einem komplizierten Satz gesagt habe.
Wir sagen, wenn die zweite Zahl nicht null ist,
also dann ist das Ergebnis mindestens eins plus und dann die
Addition von A mit einem zweiten Parameter B minus eins,
dann ziehen wir von dem B als ab.
Und das machen wir so lange, wie B, ein Wert ungleich null hat. Das heißt,
was wir hier tun, ist genau im Sinne dieser Definition von Rekursion,
die ich am Anfang gesagt habe, wir führen das Problem der Addition,
zweier Zahlen auf ein kleineres Problem zurück und kleineres,
gleichartiges Problem zurück, nämlich wir addieren dann nicht mehr zwei Zahlen,
sondern wir sagen, also die Addition besteht darin,
wir nehmen uns einen Nachfolger von der einen Zahl und addieren dann eine kleinere Zahl dazu.
Also in diesem Fall des B-1. So und das ist jetzt also
der entscheidende Punkt, hier fehlt übrigens noch eine Klammer.
Das heißt, es scheint, also die schließenden Klammern scheinen
beim Malen dieser Folien ausgegangen zu sein.
Das mache ich etwas, was ich extrem ungern tue,
in der Vorlesung an den Folien rummalen. So,
wir führen dieses Problem also auf ein kleineres Zurück und jetzt sehen sie diese,
da war ich stehen geblieben,
wir führen das Problem der Addition auf die Addition selbst
zurück,
aber mit Veränderten
Hier sogar im Wortsinne kleineren Parametern,
aber wir haben uns jetzt auch ein kleineres Problem gemacht,
indem wir sagen, naja,
wir addieren jetzt nicht mehr so eine ganz große Zahl,
sondern eine, die um eins kleiner geworden ist.
Und das ist typisch jetzt für, jetzt kommen zwei weitere Beispiele.
Das ist so eine typische Herangehensweise. Bei einem Finden einer rekursiven Struktur. Die Frage ist,
also die eine mindestens eine der entscheidenden Fragen ist dann dabei,
wie lautet das Abbruchkriterium für die Rekursion?
Und die zweite Frage ist, wie komme ich hin zu dieser Abbruchbedingung?
Und das ist ein Beispiel, das wir hier sehen,
ist, wenn sie jetzt so,
denke ich, auch gleich nachvollziehen können,
wenn ich die Division betrachte und ich kann nicht dividiere,
auf welches kleinere Problem kann ich die Division zurückführen.
Das Problem führe, also Division führe ich auf das Problem Subtraktion zurück.
So, schauen wir uns das in der Definition an.
Ich möchte also zwei Zahlen A und B dividieren und das,
also diese ganzzahlige Division, sondern meine Abbruchbedingungen lautet,
also wenn, ah, kleiner ist als B,
dann ist das Ergebnis null.
Ja, ist ja klar. Kann man sich direkt klar machen,
dreigeteilt durch vier. Wie ist das so? Das ist
auf jeden Fall null. Jedenfalls, was die ganzzahlige Division anbetrifft. So,
jetzt nehme ich mal ein Beispiel sieben geteilt durch drei,
also wo das A nicht kleiner ist als B,
dann sage ich A, das Ergebnis ist auf jeden Fall eins, plus.
Und dann kommt der entscheidende Trick. Hier bewege ich mich in Richtung meines Rekursionsabbruchs,
indem ich sage, ich ziehe von dem A das B ab.
Und das ist jetzt so, wird ihnen,
denke ich, Fred, also auch wieder so,
dem kann man ja beim Programmieren in den Kopf gucken,
beziehungsweise er lässt sie in den Kopf gucken.
Das Finden dieser Art von rekursiver Struktur ist also nicht etwas,
was durch Alkoholkonsum, Drogen, jedweder Art.
Also jedenfalls nicht nach meinem Kenntnisstand gefördert wird.
Das wird durchüben gefördert. Man guckt sich Probleme an,
sieht eine Rekursionsstruktur, wenn nicht, redet man mit jemandem,
der vielleicht schon mal eine rekursive Funktion implementiert hat.
Und dann kriegt man da Übungen drin und die beste Droge in
diesem Zusammenhang nicht nur in diesem Zusammenhang ist ein klarer Kopf.
So, also nicht am Wochenende nachts rekursive Strukturen versuchen zu finden.
Es fällt schwerer. So, jetzt gucken wir uns das,
was ich gerade gesagt habe,
gucken wir uns nochmal mal so vom Ablauf her,
sieben durch drei gucken wir uns an,
wie das so mit der Bindung der Parameter dann aussieht.
So, ich will also,
dass hier sehen Sie die Funktionsdefinition und hier sehen Sie,
wie wir das am Beispiel, wie das so vom Ablauf her funktioniert.
Das Ergebnis wäre also null, wenn sieben kleiner als drei wären,
ist es aber nicht. Also ist das Ergebnis eins plus
und jetzt rekursiver Aufruf von die Wahrheit wieder,
jetzt aber mit den aktuellen Parametern A-B, sieben minus drei und drei.
Der bleibt ja unverändert, der Parameter B. Und das heißt,
das hier ist das Ergebnis, also dieses Funktionsaufruf. Und das,
was eben jetzt vielen so beim ersten Hinschauen so ein klein wenig Unwohlsein
Bei vielen ein klein wenig Unwohlsein hervorruft, ist,
dass wir hier jetzt einfach die Wahrheit nochmal aufrufen und zwar jetzt mit diesen aktuellen Parametern.
Und so geht das dann weiter. Also so,
was man sich so, Mann, sich so gemerkt hat,
ist, also wir sind ja schon bei 1 plus und jetzt kommt also,
die Frage ist vier kleiner als drei, nö, das ist nicht der Fall.
Also ist das Ergebnis dieses Aufrufs von Divide 1 plus,
wieder a-b, von diesen aktuellen Parametern reden wir ja jetzt.
Das ist also vier minus drei, bis mit 1,3.
Und wir landen also bei diesem Ergebnis 1 plus 1 plus ein Aufruf von Divide 1,3.
Also und jetzt kommen wir ganz nah an die Abbruchbedingungen herein.
Ist eins kleiner als drei. Ja, das ist der Fall.
Also ist das Ergebnis null. Und wir haben also diesen Aufruf von Divide,
können wir jetzt, auswerten, ohne einen weiteren rekursiven Abstieg.
Und dann bedeutet das, und das bedeutet,
wir können auch diese Operation ausführen, weil plus können wir,
dann ist das dieses Ergebnis plus, und dann,
wenn der Ausdruck ausgewertet ist, dann kann auch der Gesamtausdruck ausgewertet werden.
Und als Ergebnis kommt zwei raus. Das ist doch die Mathematiker sprechen in diesem Zusammenhang,
gerne auch von einer eleganten Formulierung eines Problems,
so weil sie mit so wenig Mitteln auskommt, um das Problem auszudrücken.
Und insbesondere braucht man nicht das, was,
also Fred hat bei der Diskussion über Schleifenkonstruktion ja auch schon über das One-Off-Problem gesprochen.
Menschen, die die Rekursion beherrschen, das One-Off-Problem im Großen und Ganzen vergessen.
Man muss sich jetzt auch keine Gedanken mehr darüber machen,
also wie oft wird es jetzt durchlaufen?
Man hat eine klare, elegante Formulierung und weiß,
was die Abbruchbedingungen der Rekursion ist. Und man weiß,
mit welchem in Richtung Abbruchbedingungen sich bewegenden Parametern der rekursive Aufruf erfolgen muss.
Das heißt, wenn sie das One-Off-Problem haben,
das hat jeder von uns, fordere ich sie hiermit auf,
also sich rekursive Techniken zu bedienen.
So, letztes Beispiel, da gehen wir auch schon so in Richtung,
also wie schreibt man das dann in Java hin?
Sie sehen hier die Definition, der allseits beliebten, bekannten Fakultätsfunktion.
Wie ist die definiert? Das ist also für N gleich 1,
so wird als Ergebnis null ausgewertet und für ein größer,
Entschuldigung, für endgleich null gibt es eins als Ergebnis und für einen größeren null,
nun, eine Multiplikation von N mit Fakultät von, wir bewegen uns in Richtung Abbruchbedingungen, N minus eins.
So ist die Fakultätsfunktion einfach definiert, dann gucken wir uns das mal,
das habe ich jetzt gerade schon gesagt, also wie das dann,
wie die Auswertungsschritte laufen, also zunächst wird geprüft,
ob N gleich null ist, wenn ja,
dann ist es einfach Abbruchbedingungen, das Ergebnis wird zurückgeliefert,
ansonsten hat man also dieses N und einen rekursiven Aufruf von Fakultät und diese Multiplikation kann natürlich erst ausgeführt werden,
die kann evaluiert werden,
wenn dieser Aufruf hier zurückkehrt
Gucken wir uns jetzt mal an, wie das in Java,
so jetzt nicht so live und direkt mit Blue Jay,
aber wie das so von der Struktur her in Java formuliert werden kann.
Sehen also hier die Bekannten Schlüsselwörter, unter anderem,
also das, was sie auf jeden Fall brauchen,
ist die Fallunterscheidung, weil ist ja klar,
weil die Abbruchbedingungen der Rekursion lässt sich nur durch eine Fallunterscheidung, lässt sie sich feststellen.
Wenn also das Problem einfach lösbar ist, dann kann das einfache Ergebnis zurückgeliefert werden. Ansonsten gibt es halt ein rekursiven Aufruf,
unsere rekursive Funktion hier, Operation heißt Löseproblem,
mit einem veränderten Parameter und verändert ist jetzt, also neutral formuliert,
also Veränderung wäre ja auch, wenn wir das Problem größer machen,
diese Veränderung sollte immer in Richtung des einfachen, einfacheren,
nicht sollte, muss in Richtung, also der Vereinfachung des Problems geben.
So, und wenn dieser Aufruf dann zurückkommt,
und das ist jetzt so ein, dass diese Struktur,
sollten sie sich dann eben einprägen, in dem Moment,
also kann dann erst dann, kann, also dieses Gesamtergebnis, das Ergebnis zurückgeliefert werden, dieses Aufrufs.
So, wie sieht das in Java aus? Die Fakultät,
das steht hier jetzt, ist so ein kleiner,
ein Hauch anders formuliert, als das ist in der,
als es gerade in der grundsätzlichen Struktur beschrieben worden ist,
wo aber ich denke, der Unterschied ist,
also hinreichend klein, wir deklarieren die Funktion Fakultät,
bekommen einen Parameter übergeben, der sollte tunlich größer als Null sein,
was sie mal ausprobieren können, ist hier ein,
das zu implementieren und einen negativen Wert reingeben.
Da kriegen sie dann eine Fehlermeldung,
die sie so möglicherweise noch nicht gesehen haben, einen sogenannten Stack-Overflow,
was das bedeutet, komme ich aber gleich auch noch zu.
So, jetzt nennen wir mal den angenehmen, den positiven Fall an.
Hier wird ein enge Parameter übergeben, Größe mit einem aktuellen
Wert größer Null. Wenn das also ungleich null ist,
dann gehen wir nicht in den einfachen Fall,
sondern eine Multiplikation von dem, was als aktueller Parameter übergeben worden ist,
mit dem rekursiven Aufruf und hier wieder die entscheidende Stelle.
Wir bewegen uns in Richtung Abbruchkriterium der rekursiven Aufrufe,
solange N größer Null ist. So, als Ergebnis wird
dann diese, wenn diese Ausdruck ausgewertet worden ist,
kann eben ein Ergebnis zurückgegeben werden. Jetzt,
dass hier, das muss man, Axel Schmolitzki lassen,
also diese Folie herzustellen, war wahrscheinlich, naja,
ich will nicht hoffen, Blutschweiß und Tränen,
aber auf jeden Fall hat er sie uns sehr liebevoll hinterlassen.
Wie sieht es dann aus? Okay. Mit N gleich
3. Ist N gleich 0? Nein, das ist nicht
der Fall, also bewegen wir uns in den Els-Teil.
Was passiert da? Es gibt einen rekursiven Aufruf mit N
minus 1. Das Ergebnis davon ist zwei. Also sind wir
jetzt an der Stelle, es ist genau dasselbe wie vorher.
Nur, dass der aktuell Parameter jetzt ein um eins dekrementiert worden.
Ist der gleich null? Nein, das ist nicht der
Fall. Also bewegen wir uns in diesem Fall,
wir müssen wiederum einen rekursiven Aufruf machen.
Und jetzt sind wir bei N gleich 1 angekommen.
Wir sind gleich null. Nein, das ist nicht der Fall.
Also bewegen wir uns jetzt in die Richtung Fakultät,
jetzt mit einem Wert von N gleich null.
So, jetzt wird eine Rekursionskette aufgelöst. Wir befinden uns also hier,
Ende ist gleich null und wir können jetzt ein Ergebnis,
also ein in dieser Funktion berechnetes Ergebnis können wir zurückgeben.
Und zwar können wir das an die Stelle zurückgeben,
man könnte jetzt ja mal fragen, was glauben Sie denn,
wohin jetzt der Kontrollfluss zurückkehrt? Und ich hoffe,
Da ist also 105 Prozent von Ihnen Antworten,
da ist doch klar, an die Stelle,
also es geht genau an die Stelle,
beziehungsweise genau hinter die Stelle zurück, von der aus wir aufgerufen worden sind.
Und diese Annahme ist richtig. So, was kommt denn
jetzt hier als Resultat zurück? Hier steht, Result ist gleich eins.
Das wird also zurückgeliefert, und zwar an die Stelle,
und Sie sehen jetzt, was verschwunden ist,
ist jetzt diese Instanz dieser Instanz des Fakultätsaufrufs,
die hat ihr ihre Schuldigkeit getan.
Das Ergebnis ist geliefert. Und wir sind jetzt hier in
diesem Aufruf zurückgekehrt, in dem N gleich eins gewesen ist.
Und wir haben eine Eins aus diesem Aufruf zurückbekommen.
Und jetzt müssen wir nur noch ausrechnen, einmal eins.
Das geht. Das kann man schaffen
Das ist eins. Glück gehabt. So,
jetzt sind wir in diesen Aufruf zurückgekehrt,
wo N gleich, wo Ende den Wert, zwei hatte.
Und NSCar 2, Fakultät von N-1,
wir kriegen von N-minus 1 wurde aufgerufen und wir kriegen als Ergebnis
jetzt eins zurück und wir können jetzt ausrechnen, zweimal eins.
Das ist dasselbe wie einmal zwei. Das ist zwei.
Ich arbeite an einer Karriere als Politiker. So. Einmal zwei
ist jetzt als Resultat dieses Funktionsaufrufs zurückgekehrt. Okay. Und
jetzt sind wir hier und N hatte hier den WR3,
das Ergebnis dieses Aufrufs ist zwei, dreimal,
zwei ist sechs.
Chaka. So ist das
Das Leben kann schön sein. Ja, vor allem sollten wir,
ich sollte nicht, also ich meine, mein Sohn,
als der in der Grundschule war, ich habe mich,
ich habe davon abgesehen, der Grundschullehrerin vorzuschlagen,
sie soll ihm die Grundrechen achten über die Piano-Aktionen beizubringen.
Aber man kann sich das ja im Nachhinein mal so klar machen.
Nicht so, wie das so ist mit dem,
mit den rekursiven Aufrufen, so vermittelt der, vermittelt der Piano-Aktionen.
So, was ich ihnen jetzt gerade gezeigt habe,
ohne den Begriff in den Mund zu nehmen, ist der sogenannte Aufruf-Stack.
Hier sehen Sie ein Beispiel für ein Stack. Auf Deutsch
heißt das den Keller und die Grundidee des Kellers besteht darin,
Kellertür auf, den Müll rein und Kellertür zu.
Und wenn man dann wieder die Kellertür aufmacht, Nächsten Müll rein, Kellertür zu.
Man hat immer nur Zugriff auf das zuletzt in den Keller hinzugefügte Element.
Und so funktioniert auch der Aufrufsdeck für rekursive Funktionen.
Oder es ist eigentlich nicht so funktioniert.
Also so kann man sich vorstellen, dass rekursive Aufrufe funktionieren.
Es wird also hier auf den Aufrufsdeck werden immer neue Instanzen der Funktion Fakultät aufgerufen.
Und wenn man dann anfängt, nämlich dann,
wenn hier kein rekursiver Aufruf mehr erfolgt, wenn man dann fertig ist,
dann wird dieser Stack auch in genau der Reihenfolge aufgeräumt,
in der er aufgebaut worden ist. So,
und das ist so ein ganz fundamentales Prinzip bei der Abarbeitung von Also nicht nur objektorientierten Programme,
ein ganz fundamentales Proprinzip, das so beim Aufrufen von Operationen seien,
dass jetzt Prozeduren oder Funktionen, also mit oder ohne Rückgabe wert,
die werden alle nach dem Prinzip des Aufrufstacks des Calls-Decks,
werden die abgebildet.
So, und es ist also bei jedem,
das habe ich jetzt auch schon mal, also in anderen Worten gesagt,
dass bei jedem neuen Methodenaufruf wird also festgehalten,
wohin muss denn die Operation, die ich jetzt gerade aufrufe,
wohin muss die zurückspringen.
Und das ist stackartig, es gibt immer,
es wird immer genau in der Reihenfolge wieder abgebaut,
in der es auch aufgebaut worden ist. So,
das ist also der Aufrufstack und das ist so ein Modell,
wie man sich so nicht,
sagen wir mal,
man könnte das auch
genau so realisieren
Ob das jetzt tatsächlich so in modernen Programmierumgebungen, Laufzeitumgebung so passiert,
sei mal dahingestellt oder ob das aus Effizienzgründen nicht anders gemacht wird.
Jedenfalls wäre das, also früher wurde das so gemacht.
Theoretisch ist das auch heutzutage noch so. Aber aus Effizienzgründen
ist das möglicherweise auch anders realisiert. So, wir können das
jetzt uns noch so an verschiedenen Stellen können oder mit verschiedenen Beispielen versuchen klarzumachen.
Und wenn sich schon jemand die Liebe gemacht hat,
also das hier mal so hübsch zu animieren,
das ist ja jemand, ist Axel Schmolitzki,
dann denke ich, ist es das auch wert,
das hier mal zu zeigen.
So was hier jetzt berechnet werden soll,
ist also der Ausdruck 23 plus Fakultät von 4.
Wie das auf dem Stack, also das,
was so im Hauptspeicher passiert, wie das tatsächlich aufgebaut wird.
Also tatsächlich immer so mit einer gewissen Abstraktionsebene dazwischen
Sodass Magmal der momentanen Zustand des Decks sein, wo wir also wissen, aha,
wir haben 23 und wir wollen jetzt aufrufen,
Fakultät von 4. Was dann im Hauptspeicher passiert, ist,
dass dann ein Stück Speicher reserviert wird auf dem Stack,
um diese Operation aufzurufen und um sicherzustellen,
dass man seine Rücksprungadresse nicht vergisst.
Und dann ist halt so,
wie wir die Fakultätsfunktion kennengelernt haben, müssen wir dann,
also wir müssen ein Stück Speicher für den Ergebnis,
für das Ergebnis müssen wir festhalten und wir müssen die Rücksprungadresse festhalten,
solange wie wir uns rekursiv aufrufen.
So, und jetzt sind wir ja an der Stelle,
die wir vorhin gesehen haben, so unten rechts auf der Folie.
Wir brauchen jetzt rekursiv nicht weiter abzusteigen,
sondern wir sind genau da angekommen,
wo dieses Abbruchkriterium in Anführungsstrichen zuschlägt
Können wir ein Ergebnis festhalten? Jetzt passen Sie auf.
Hier wird jetzt gleich was passieren. Und da ist das Ergebnis
zurückgeliefert worden. Jetzt wissen wir, wo wir hin zurückspringen müssen,
dass es diese Adresse und wir wissen auch,
also wohin das Ergebnis unseres Aufrufs abgelegt werden muss, nämlich dahin.
Na gut, das ist noch ein Zwischenschritt, ist noch dabei.
Und so wird dieser Stack jetzt sukzessive,
wird er wieder abgebaut, bis wir an der Stelle sind.
Verunglong, klong. 24 bis 23 bis 23 plus 24,
das ist also mehr als 24. Also könnte man jetzt ausrechnen, nicht?
Na gut, 47. So, der Stack ist jetzt komplett
wieder abgebaut. Jetzt kann man was Normales machen. So,
jetzt haben sich das so an ein paar Beispielen gezeigt und jetzt vielleicht noch eine,
ich habe ja die ganze Zeit eigentlich darüber gesprochen,
also wie schön das ist mit der Rekulsion.
Wir gucken uns jetzt noch ein weiteres Problem an,
das sich elegant in rekursiv formulieren lässt, das sind die Fibunacci-Zahlen,
die Fibunacci-Zahlen geben an, also wie schnell sich Kanickel vermehren,
wenn die unendlich lange leben.
Nach wie vielen Generationen hat man, wie viele Kanickel und das geht wahnsinnig schnell.
So, wie sind die definiert, die Fibunacci-Zahlen?
Also wenn die Fibunacci-Zahl der Zahl 1 ist null,
von 2 ist 1 und ansonsten ist es die Fibunacci-Zahl von
N-1 addiert mit der Fibunacci-Zahl
Ja, das ist doch elegant hingeschrieben.
Das kann man nicht anders sagen, wenn man so ein,
wenn man dann ein Gefühl für hat und nicht,
dass ich das behaupten würde, das zu haben.
Aber so, das liest man, denkt, jo,
okay, das kann also ausgerechnet werden.
Jetzt gucken wir uns mal an, wie das,
wozu das führt, wenn wir das so einfach,
so einfach und elegant implementieren.
Wir befinden uns also im Aufruf, Hybonacci von 4 und ja
, ist doch klar. Das resultiert zunächst mal in einem
Aufruf von Fieb von 3. Was ist Fieb von 3?
Das ist doch auch klar. Da muss erst mal
Fieb von 2 ausgerechnet werden und Fieb von 2 bedeutet,
ich muss Fieb von 1 aufrufen. Wir sind immer noch,
also wir steigen jetzt so links ab,
Fieb von 1 kann man ausrechnen,
das ist nämlich genau dieser Fall hier,
solange das Fieb von 2 bedeutete ja,
ich muss das,
also diesen Ausdruck hier auch noch auswerten
So, und fiep von, und dann habe ich den ausgewertet habe,
muss ich ja die andere Seite dieser Addition auch noch ausrechnen.
So, und dann bin ich erst mal hier angekommen,
nämlich auf dieser Seite jetzt, und ja,
das kann man sich jetzt schon, also wozu das führt,
ist, schon bei Fiep von 5 habe ich also 13 rekursive Aufrufe,
und das steigt also echt ganz schön schnell, sie sehen das hier.
So, das ist also, eins, eins,
zwei, drei, vier, fünf, sechs, sieben,
acht, wo sie mal, wie schnell das hochgeht,
da können sie ziemlich schnell, ziemlich viel Rechenzeit,
also verbringen, in einer zwar eleganten Formulierung des Problems,
aber in einer möglicherweise nicht so effizienten,
nicht so effizienten Implementierung
In der Software-Technik, also ein beliebtes Spannungsfeld ist, für einerseits die Formulierung eines Problems und andererseits also die Effizienz, die Performance-Frage, wie gut lässt sich dieses so formulierte Problem auch realisieren. So,
wir gucken uns dann so im Laufe des Semesters noch,
also weitere Anwendungen an, insbesondere ich hatte es schon gesagt,
also Baumstrukturen werden wir uns anschauen,
was das überhaupt in der Softwareentwicklung bedeutet,
also sie haben jetzt schon mal so ansatzweise von der Idee,
haben sie eine Datenstruktur jetzt gehört, der Stack,
der Keller, wir werden uns noch mit Schlangen beschäftigen,
wir werden uns mit Bäumen beschäftigen und ansatzweise auch noch mit Grafen,
mit PH geschrieben, da wird diese Rekursion,
das ist ein Angebot,
keine Drohung,
da werden wir
uns nochmal mit Rekursion beschäftigen
Dann gibt es jetzt, also,
damit hatte ich ja angefangen, wie guckt man so auf,
wie kann man als Softwareentwickler auf Rekursion schauen, so,
und das hier, will ich sagen, der berühmteste lebende Informatiker,
Softwareentwickler, aber doch so eine der,
so ein relativ einflussreicher Schriftsteller, Autor ist, glaube ich,
besser, Autor in der, in der Szene,
und er sagt halt, naja, gut,
so kleine Menge von Problemen ist es sehr einfach,
elegante Lösungen zu produzieren,
und dann gibt es eine etwas größere Frommenge von Problemen,
da kann man also mit Rekursion, also schwer verstehbare Lösungen produzieren,
und für die meisten Probleme, according to his definition of problem,
also findest du sehr komplizierten Lösungen,
und dann sollte man lieber einfach was wegiterieren,
trage ihnen das jetzt einfach so vor,
dass es da eben unterschiedliche Einschätzungen gibt.
Also sie werden sich da im Laufe ihres Studiums,
denke ich, auch ein eigenes Bild machen.
Hier geht es ja nur darum, kurz mal darzustellen,
also es gibt da keine einheitliche Meinung zu dem Thema,
sondern da gibt es also ein Hin und Her wogendes Pro und Contra.
So, wenn ich vom Stack spreche,
dann muss noch eine Bemerkung erlaubt sein,
über einen anderen Bereich des Hauptspeichers, den sie auch schon benutzt haben,
ohne dass wir ihnen verraten haben,
dass das so bereits der Fall ist.
Das ist jetzt aber der Zeitpunkt gekommen, um so den auch mal namentlich hervorzuheben.
Das ist der sogenannte Hieb auf Deutsch, Haufen. Die Art und Weise,
wie der Aufrufsdeck so auf und wieder abgebaut wird,
das haben wir uns am Beispiel des rekursiven Aufrufs,
haben wir uns das mal so ansatzweise angeschaut.
So, das ist also, das geschieht nach einer strikten Ordnung.
Ja, stapelartig. Der Hieb ist von anderer Natur,
der Hieb, der wird von ihnen, also verwendet ihnen,
der wird von ihnen verwendet in dem Moment,
wo sie ein, in dem sie ein neues Objekt schaffen.
Dieses Objekt, der Speicherplatz für diese Objekte,
die sie mit New erzeugen, der wird nicht auf dem Stack reserviert,
sondern auf dem Hieb und der wird genau da aluziieren, wo gerade Platz ist.
So, das kann dann also bei lang laufenden Programmen auch dazu führen,
dass dieser Speicherplatz, so wie man das nennt, fragmentiert ist.
Das kann beim Stack nie passieren,
weil der wird immer brav auf und wieder abgebaut,
in der Reihenfolge, in der Also durch Aufrufe von Operationen vorgegeben ist,
während beim Hieb ist es so, nun,
Sie können da Objekte anlegen und die große Frage ist ja,
wann werden diese Objekte wieder gelöscht?
Wann wird der dafür reservierte Speicherplatz wieder freigegeben?
Und das ist eine andere große Diskussion in der Softwaretechnik.
Oder sagen wir mal, bei der Implementierung von Programmiersprachen in Java
gibt es so etwas wie einen Garbage-Collector. Das heißt,
ein Objekt, das Sie mal angelegt haben,
wird von einem Müllsammler auch wieder freigegeben, in dem Moment,
in dem es niemand mehr referenziert.
Das heißt, da läuft im Hintergrund, läuft eine,
also läuft immer dieser Prozess der Garbage-Collector mit und schaut,
naha, wird dieses Objekt, das da angelegt worden ist,
referenziert das noch jemand
Und wenn das nicht der Fall ist, dann räumt der Garbage-Collector das ab.
Fred ist ja dann auch ein Freund der Programmiersprache C Plus Plus.
NC Plus Plus wurde ganz bewusst die Designentscheidung getroffen.
Speicherplatz, Freigabe ist eine so wichtige Aktivität. Das können wir
keiner Maschine überlassen. Das muss der Programmierer selbst machen.
Deswegen gibt es in C Plus Plus nach meinem Kenntnisstand,
ich breche die Vorlesung ab. Nach meinem Kenntnisstand keinen Garbage-Collector.
Danke. Das ist also immer noch so. Ja,
ich glaube, das bleibt auch so, oder? Das ist,
also kann man jetzt nach so und so vielen x Jahren
10 Plus Plus, wenn die jetzt noch keinen haben,
dann kommt auch keiner mehr.
Und zwar, weil sie das nicht wollen.
Also in Java gibt es das,
sie brauchen sich um ihren Müll nicht zu kümmern,
der wird von Garbage-Collector
wieder eingesammelt
So, jetzt kommen noch so, so auf was
einem alles so passieren kann. In dem Moment,
wo man also dynamisch Speicher anfordert, kann es auch passieren,
dass also dynamisch keinen Speicher mehr da ist.
Dann kriegen sie einen anderen Fehler als den,
den ich gerade genannt habe, nämlich einen sogenannten Out-of-Memory-Error.
So, jetzt noch eine letzte Bemerkung dazu oder sind zu hieb und Stack.
In dem Moment, wo sie zu viele rekursive Aufrufe zum
Beispiel rekursive Aufrufe haben, kann es ihnen passieren,
dass der für sie reservierte Speicherplatz nicht mehr ausreicht.
Und dann kriegen sie vom Laufzeitsystem einen Stack-Overflow-Error.
Und jetzt hoffe ich, können Sie was damit anfangen.
Das können Sie auch gerne mal,
also so die Fibonacci-Funktion ist ja schnell implementiert,
da mal Fieb von 50 aufzurufen oder Fieb von
Da kriegen sie ziemlich schnell einen Stackoverflow produziert. So,
das dürfte schwieriger werden, wenn sie so Objekte aluziieren,
da mal ein Out of Memory Error zu produzieren.
Das dürfte etwas länger dauern. So,
ich bin soweit durch mit dem, was ich sagen wollte.
Und jetzt auf diesen Moment freue ich mich seit sechs bis acht Wochen.
Ich sage jetzt nicht nur schönes Wochenende. Ich sage auch
frohes Fest und guten Rutsch. Das sage ich nicht,
weil sie die nächsten zwei Wochen mittwochs nichts vorhaben,
sondern ich nichts vorhabe.
Jedenfalls nicht mit ihnen. Nächste Woche Mittwoch und übernächste Woche
Mittwoch wird Professor Riebisch. Das Wort in der ersten Hälfte
der Vorlesung
an Sie richten
Ich komme dann nächstes Jahr wieder und freue mich dann darauf,
sie wohlbehalten und nüchtern wieder hier anzutreffen.
Bis dahin sage ich Tschüss. So,
da bin ich wieder, was ist mit meiner Stimme?
Kann man sie hören? Piept nichts? Das ist eine Folie,
die ich normalerweise immer erst am Ende des Semesters auflege,
wo ich am Ende des Semesters sage, oh Gott,
ihr habt ja viel zu wenig getan für SE1. Und ich dachte,
vielleicht ist es sinnvoll, die man in der Mitte des Semesters aufzulegen.
Also ich habe das mal hier irgendwie versucht,
grafisch darzustellen, was wir von euch an Mitarbeiter warten.
Also wir erwarten zum Beispiel, dass ihr in die Vorlesung geht.
Ja, ich glaube, alle, die hier sind,
tun das. Dann solltet ihr auch in die Übung gehen,
sonst kriegt ihr Probleme mit dem Schein. Und darüber hinaus
solltet ihr auch noch ungefähr dreieinhalb Stunden zu Hause arbeiten.
Ja, und jetzt habe ich einfach mal geguckt,
was passiert, wenn man das nicht macht.
Also wenn ihr euch irgendwie sagt, ach nö,
Vorlesungen und Übungen, das Damit komme ich irgendwie durch,
dann fehlen euch ja jede Woche diese dreieinhalb Stunden.
Und wenn ihr das 14 Wochen macht, dann sind das
49 Stunden. Also glaubt 50. Das heißt,
wenn ihr bis jetzt noch nie was gemacht habt,
zu Hause fehlen euch schon 25 Stunden Vorbereitung.
Möglicherweise liegt es daran,
wenn ihr dann irgendwie bestimmte Begriffe nicht zuordnen könnt und nicht wüsst,
was ein formaler Parameter ist oder ein Konstrukt war oder so.
Also nehmt es ruhig ernst. Okay,
manche Leute gehen noch nicht mal die Vorlesung,
denen fehlen dann jetzt schon 35 Stunden und am Ende fehlen denen dann 70.
Also versucht nicht so weit ins Hintertreffen zu kommen mit der Vorbereitung zu Hause.
Gut. Dann wollte ich nochmal einen alten Bekannten rausholen.
Sehr schön. Weil Rekursion ist so
ein Thema
Das kann man mit Carrie wunderbar veranschaulichen. Also hier ist zum Beispiel
ein Problem, das werde ich heute nicht mit euch machen.
Da kann man zum Beispiel das paskalische Dreieck mit Carrie berechnen.
Okay. Nochmal so ein bisschen Wiederholung dem Carrie ja lange nicht gemacht.
Wir haben da nie so explizit drüber gesprochen. Ich habe jetzt
vielleicht auch nochmal so ein bisschen eine kleine formalere Folie zum Thema Kontrollfluss.
Kontrollfluss heißt ja einfach nur, wie bestimmt der Computer eigentlich,
welche Zeile als nächstes ausgeführt wird, so ganz grob gesagt.
Da gibt es einmal die triviale Kontrollstufe Sequenz, die also sagt,
Befehle werden untereinander ausgeführt, also von oben nach unten,
nicht andersrum, nicht gleichzeitig, nicht zufällig.
Das ist irgendwie jedem klar, glaube ich.
Dann haben wir die Fallunterscheidung schon in der ersten Woche kennengelernt.
Ich kann also abhängig von einer Bedingung sagen,
geh entweder in den Block rein oder in den anderen,
den jeweils anderen Block dann bitte überspringen.
Dann haben wir Wiederholungen kennengelernt in der ersten Woche schon die Zählschleife,
dass ich gesagt habe, diese Zeile nicht nur einmal ausführen,
sondern neunmal oder diesen ganzen Block bitte neunmal ausführen
Dann haben wir in der zweiten Woche die bedingte Schleife kennengelernt,
dass er immer wieder einen Block ausführt,
solange er eine bestimmte Bedingung zutrifft.
Und was ich euch auch schon in der ersten Woche gezeigt habe,
man kann, anstatt eine riesige Sequenz von Anweisungen direkt untereinander zu schreiben,
kann man das aufteilen in eigene Befehle.
Ich kann zum Beispiel ein Buffet schreiben, move to wow.
Und wenn ich den irgendwo aufrufe, wird dann zu move to wow gesprungen,
wenn Move to wow durchgelaufen ist, wird wieder zurückgesprungen.
Auch das beeinflusst ja, welche Zeige als nächstes ausgeführt wird. Okay,
und das Thema Rekursion steckt hier im Prinzip schon drin,
nämlich in diesem Punkt, ich habe euch ja nie gesagt,
in einem Befehl darf man nur andere Befehle aufrufen.
Wobei das Kerl, Laufzeit oder das Kerlsystem hat es euch gesagt,
das wurde bis jetzt einmal verboten.
Ab Woche 3 dürft ihr das tatsächlich.
Und das werden wir uns heute mal ein bisschen angucken.
Warum sollte man das tun? Ich habe so ein paar
Rätsel eingebaut in Carrie, wo man tatsächlich Rekursion braucht.
Bei den Paaren ist es einfach in dem Problem so drin,
dass man Rekursion dafür braucht.
Und in manchen ist es, weil Carrie Sprache
ansonsten einfach zu eingeschränkt ist
Also ich habe mal so ein bisschen aus der Luft gegriffen,
so ein Problem, dass ich gesagt habe, ich will,
Kerl steht irgendwo in der Welt, er soll bis zur Wand laufen,
soll sich umdrehen und soll wieder zurücklaufen an die Stelle, von der er kam.
Und er kann diese Stelle nicht auf magische Art und Weise irgendwie erkennen,
also da liegt kein Diamant oder der ist keine Wand oder irgendwas,
sondern er muss sich das irgendwie merken, dass er davon da ursprünglich mal kam.
Okay, also die erste Hälfte des Problems ist super einfach,
Kerl soll bis zur Wand laufen, da wissen wir ja schon,
dafür gibt es diese Wirel-Schleife, dann drehen wir uns um,
tschau, was machen wir dann? Wir wissen jetzt nicht,
ich würde jetzt am liebsten irgendwie sowas sagen,
wie mach bitte eine Schleife, die genauso oft durchläuft,
wie diese Schleife durchgelaufen ist,
das könnte man in Java mit irgendwelchen Variablen machen,
dass wir haben gesagt, ich zähle das einfach vorher einmal mit,
ah, Kerl ist sieben Schritte gegangen,
dann gehe ich jetzt auch sieben Schritte,
das geht aber in Kerlen nicht,
weil wir haben keine Variablen in Carol.
Okay, gut, jetzt gibt es tatsächlich ein Problem,
wo man genau das machen soll, das haben wir also Hier.
Vielleicht zeige ich euch noch mal als Kontrast ein ähnliches Rätsel,
an das ihr euch wahrscheinlich erinnern werdet.
Das ist dieses Rätsel. Das war das irgendwie,
Kerl hat Geburtstag und da wird irgendwie Lampions aufhängen,
das sah ja irgendwie so aus, ihr erinnert euch.
Man nimmt sich aus so einem Lampion, dreht sich nach links,
läuft bis zur Wand, legt ihn ab,
dreht sich um, läuft wieder bis zur Wand.
Hier ist es also kein Problem, weil hier diese Wand ist.
Diese Wand ist unser Benchmark, um zu sagen, alles klar, hier aufhören.
Hier bin ich jetzt wieder da, wo ich ursprünglich mal war.
Diesen Luxus haben wir hier unten nicht,
auch wenn es wieder auf den ersten Blick so aussieht.
Es sieht ja auf den ersten Blick so aus, als wäre hier eine Wand.
Jetzt weiß ich nicht, wie gut man das erkennen kann.
Wahrscheinlich ist das zu klein. Ich kann ja vielleicht mal
einen kleinen Screenshot machen, dass ihr mir wirklich glaubt,
dass da keine Wand ist. Weil das sieht ja
erst mal so aus, als wäre da eine Wand.
Also, es ist in Kerls Welt so,
ich habe das so gebaut, ist ja in so,
kann ich irgendwie diesen blöden Kreis hier wegkriegen?
Nee, ignoriert diesen Kreis, ist egal.
Also Kerls Welt ist in solche Kästchen aufgeteilt und in
der Mitte dieser Kästchen ist so ein Pluszeichen.
Also stellt euch vor, hier sind so,
das ist so die Grenze, dieses Kästchen sozusagen.
Und jedes Kästchen hat ja vier Grenzen. Norden, Süden
, Wessen und Osten. Und Jesus ist jetzt zum Beispiel
so, dass dieser Kasten hat im Norden eine Wand.
Und dieser Kasten hat im Süden eine Wand. Deswegen erscheint
diese Wand recht dick, weil es eigentlich zwei Wände sind,
die direkt aneinandergeklebt sind. Ja, wenn ihr das mal vergleicht,
zum Beispiel mit dem Rand hier oben, ich weiß nicht,
ob ihr das sehen könnt. Diese Wand ist dünner,
weil das sozusagen nur die Nordwand von diesem Kästchen ist.
Hier fehlt sozusagen die Südwand von dem nicht existenten Kästchen darüber.
Also diese Wand ist ziemlich dick, weil es zwei Wände sind.
Und diese Wand hier unten seht ihr, die ist eher dünn.
Das ist quasi die Nordwand von diesem Kästchen.
Aber dieses Kästchen hat keine Südwand. Deswegen wird Kerl,
wenn er hier runtergeht, nicht verstehen,
dass so eine Wand ist und wird einfach durchlaufen
Also das klingt jetzt erstmal nach einem technischen Bug, sage ich mal,
aber ich habe das natürlich schön in die Story eingebaut.
Also auf seiner letzten Party hat Kerrel so gefeiert mit so viel, ja, Substanzen.
Das ist also der ganze Boden komplett durchgeweicht ist.
Also da sind wahrscheinlich die Bierflaschen durch die Gegend geflogen,
ich weiß es nicht. Also der ist so weich,
der Boden, dass er da droht,
den Moment durchzufallen, weil er versucht, da durchgeht.
Also müssen wir das verhindern, dass er da irgendwie durchgeht.
Okay. Tja, wie machen wir das denn jetzt?
Wenn wir nicht erkennen können, dass da eine Wand ist,
wie können wir dann irgendwie dafür sorgen,
dass er aufhört, da irgendwie rumzugehen?
Sonst wechsle ich nochmal kurz auf die Folien zurück.
Und da ist jetzt die erste Idee,
wir beschränken uns jetzt erstmal auf ein sehr kleines Problem.
Wir tun mal so, als wäre die Wohnung von Carol
so schmal oder so flach, was ist der richtige Ausdruck dafür?
Flach, oder? Also das Gegenteil von hoch,
tief, die Wohnung ist so tief oder so flach,
dass die Decke höchstens einen Schritt von ihm weg ist.
Also entweder ist die Decke quasi direkt über ihm oder
nur einen Schritt
weiter weg
Dann wäre das Problem eigentlich relativ einfach. Dann kann ich sagen,
also wenn die Decke direkt über mir ist und mein Ziel ist es,
bis zur Decke zu gehen, mich umzudrehen und wieder zurückzugehen,
dann brauche ich mich ja nur umdrehen.
Mehr muss ich nicht machen. Dann bin ich ja da,
wo ich gestartet bin, weil ich ja nie einen Schritt gegangen bin.
Im anderen Fall kann ich einfach einen Schritt gehen und ich
gehe jetzt davon aus, dass da die Decke ist,
weil ich einfach jetzt das Problem habe, ein bisschen kleiner gemacht habe.
Dann drehe ich mich um und dann gehe ich wieder zurück.
Das ist dieser Fall. Ich tue jetzt mal so,
als würde es nur diese beiden Fälle geben.
Das reicht jetzt natürlich nicht, weil in echt kann die Decke ja
bis zu sieben Schritte, glaube ich, weg sein.
Außer bauen wir jetzt einfach weitere Funktionen dazu, die auf
dieser Funktion aufbauen. Das sieht zum Beispiel so aus.
Also wenn ich sage, ich gehe davon aus,
dass im Worst Case die Decke bis zu zwei Schritte weg ist.
Also sie kann null Schritte, einen Schritt oder zwei Schritte
weg sein, mache ich einfach wieder den Test.
Wenn ich direkt an der Decke bin,
dann brauche ich mich eigentlich nur umdrehen.
Ansonsten gehe ich einen Schritt nach vorne und jetzt weiß ich,
die Decke kann höchstens nur noch einen Schritt von mir
weg sein
Also im schlimmsten Fall waren sie vorher zwei Schritte weg.
Wenn ich jetzt den ersten Schritt gehe, dann kann sie
jetzt ja nur noch höchstens einen Schritt von mir wechseln.
Ich habe das Problem also effektiv kleiner gemacht. Und wenn
diese Reise dann vorbei ist, die höchstens einen Schritt gehen wird,
dann gehe ich wieder den Schritt auf den Rückweg zurück.
Und das Spiel kann ich jetzt immer weiterspielen. Also ich kann sagen,
wenn ich das gelöst habe, quasi für die Problemgröße 2,
dann mache ich eine neue Funktion für die Problemgröße 3.
Ich sage also, wenn ich direkt bei der Wand bin,
brauche ich mich nur umdrehen. Ansonsten mache ich das Problem kleiner,
indem ich den ersten Schritt gehe. Jetzt weiß ich,
die Wand kann nur noch höchstens zwei von mir weg sein,
unter der Voraussetzung, dass sie vorher höchstens drei von mir weg war.
Und wenn diese Funktion zurückkehrt,
hat Kerrit sich ja umgedreht und öst auch schon fast wieder komplett zurückgegangen,
dann muss ich nur noch den Schritt auf den Rückweg gehen.
Also das hier sind quasi immer die Schritte auf dem Hinweg und das
sind immer die Schritte auf dem Rückweg. Und dadurch,
dass die hier so untereinander stehen, in derselben Einrückungsebene und ohne,
dass dazwischen noch irgendwelche IFs geschaltet sind,
kann ich 100% sicher gehen,
dass Carrie für jeden Schritt auf dem Hinweg auch einen Schritt
auf dem Rückweg machen wird
Damit habe ich mir selber eigentlich klar gemacht, dass das
wahrscheinlich funktionieren müsste. Dann mache ich das für Journey 4,
für Journey 5, für Journey 6, für Journey 7,
das habe ich jetzt nicht alles auf Folien gemacht,
aber ich habe es mal programmiert.
Schauen wir uns das mal zusammen an, was ich da gemacht habe.
Ich mache mal Geschwindigkeit auf null, starte das mal.
Okay, das kennen wir, das ist nichts Besonderes, roter Balken.
So, hier ist jetzt die spannende Stelle. Ich will also,
dass Kerre ja maximal sieben Schritte geht,
wenn er vorher schon an der Wand stößt,
kann auch schon vorher aufhören,
dann soll er sich um den und dann soll er wieder zurücklaufen.
Ich würde also erwarten, wenn dieser Befehl komplett durchgelaufen ist,
dass Carol dann diese Bewegung quasi gemacht hat und dann nach Süden guckt.
Gut, schauen wir mal, wie er das macht.
Also, wir gehen in die Journey 7 rein,
wir schauen mal, ob die Reise schon vorbei ist,
ob wir schon bei der Wand angekommen sind, dann wäre es ja einfach.
Sind wir tatsächlich nicht, hier ist er frei. Okay,
gehen wir jetzt aus Elzheim,
jetzt gehen wir den ersten Schritt auf dem Hinweg hin und wir wissen,
irgendwann wird er kontrollflos in dieser Zeile ankommen und
dann werden wir den Schritt wieder zurückgehen
Okay, weil erstmal müssen wir jetzt eine Reise der maximalen Länge sechs antreten.
Machen wir das doch mal. Und das ist hier unten
. Exakt quasi fast derselbe Code. Wir sind noch nicht
da. Okay, gehen wir in den Elsblock,
gehen einen Schritt auf den Hinweg. Und jetzt wissen wir,
die wann kann höchstens nur noch fünf von uns weg sein.
Na gut, da muss man dann wieder in das Els reingehen.
Wir gehen einen Schritt. Jetzt kann die Wand höchstens nur noch vier
von uns weg sein. Dann rufen wir das auf.
Wir sind immer noch nicht da, wir gehen einen Schritt.
Jetzt kann sie nur höchstens drei von uns weg sein.
Ihr seht, ich sage immer fast dasselbe,
nur dass die Zahlen anders sind.
Ich gehe in Sales, ich gehe einen Schritt,
jetzt kann sie nur noch zwei von ihr weg sein.
Ich bin immer noch nicht da, ich gehe einen Schritt,
jetzt kann sie nur noch höchstens einen von mir weg sein.
Ich bin immer noch nicht da, ich gehe einen Schritt.
Und jetzt brauche ich gar nicht mehr prüfen.
Ich habe das ja beschränkt auf höchstens Länge sieben,
also die Wand ist immer spätestens hier.
Deswegen habe ich jetzt hier keinen Hilf mehr eingebaut.
Okay, jetzt drehe ich mich um. Und jetzt gucken wir mal,
dass man diese ganzen Move Forwards auf dem Rückweg auch wieder zurückgeht.
Also gut, das ist das Move Forward,
was quasi zu dem gehört.
Es ist ja irgendwie klar,
dass er das ausführt
Jetzt müssen wir uns anhand des roten Balkens orientieren.
Von wo kamen wir? Wer hatte Journey 1 aufgerufen?
Das war dieser Aufruf. Also müssen wir dieses Mouphobot noch rausführen.
Das ist dieses. Okay, haben wir gemacht.
Dann kamen wir ursprünglich von hier. Das heißt,
wir müssen dieses Mouphobot noch ausführen. Okay, haben wir
gemacht. Dann kamen wir ursprünglich mal von da.
Also man geht jetzt ja einfach wieder durch diese ganzen Funktionen zurück,
führt die jeweiligen Moe Forwards aus, hier genauso.
Hier genauso. Hier genauso. Und dann sind wir fertig. Ja,
ich habe das Problem, also stubenweise immer kleiner und immer
kleiner und immer kleiner gemacht. Und einen einfach durch die Art,
wie diese Welt so ist, habe ich gesagt,
es reicht, wenn ich mich auf Probleme der Größe 7 beschränke.
Wenn ich die immer kleiner und kleiner und kleiner mache,
bin ich irgendwann bei null.
Okay, jetzt kann man sich natürlich fragen, so viel Code?
Ist das wirklich notwendig? Aber habt ihr bis hierhin erstmal Fragen,
dass ich so diese sieben Funktionen geschrieben habe,
die sich in so einer Kette aufrufen und das Problem immer kleiner machen?
Ist das erstmal klar vom Gedanken her
Ich glaube ja. Also dadurch,
dass es auch wirklich immer neue Funktionen sind und man schön sieht,
wie der rote Balken da so durchgeht,
kann man sich das wirklich vorstellen,
wie das am Ende wieder so zurückgerattert quasi.
Okay, und jetzt ist halt der nächste Gedanke,
einmal so ein kleiner Abstraktionsgedanke. Das ist ja blöd,
dass das hier auf eine 7 festgelegt wird.
Theoretisch könnte die Welt ja eigentlich beliebig groß sein oder
zumindest könnte diese Wand vielleicht hier sein.
Man weiß es nicht genau. Und überhaupt diese ganze Kot-Tublizierung,
dass sich hier wirklich so mehrere Bildschirme durchscrollen muss.
Und da ist ja eigentlich fast immer derselbe Tod irgendwie nicht so schön.
Geht das nicht irgendwie einfach? Ist diese Kot-Tublizierung notwendig?
Schauen wir mal, ich glaube, sie ist nicht notwendig.
Also was man erkennt, ist,
ich sage zum Beispiel in Journey 7,
muss ich Journey 6 aufrufen und in Journey 6 muss ich
Journey 5 aufrufen und in Journey 5 muss ich Journey 4 aufrufen.
Aber ansonsten ist der Code immer derselbe.
Wozu schreibe ich dann überhaupt neue Funktionen? Warum nehme ich
nicht nur eine Funktion? Zum Beispiel diese Funktion ja Journey,
wo ich ja so sage, wenn Carol an der Wand angekommen ist,
braucht es sich nur umdrehen.
Ansonsten geht er einen Schritt auf dem Hinweg
Muss dann eine kleinere Reise antreten und gehe dann wieder einen Schritt auf
den Rückweg zurück. Es ist im Prinzip exakt derselbe Quote,
nur dass ich diese Code-Duplizierung nicht habe und das ist jetzt noch noch eine Funktion ist.
Das müssen wir ausprobieren, das ist sonst, glaube ich,
nicht verständlich für Programmieranfänger, dass das funktionieren kann, dass eine Funktion sich selber aufruft.
Da nehme ich nochmal diese Journey 7,
nehme einfach mal diese Zahl hier weg,
nehme diese Zahl hier weg und dann kann ich den ganzen Code,
ich scrolle das jetzt mal ganz bewusst durch, schön langsam,
den brauchen wir jetzt nicht mehr, das kann alles weg, zack.
So, das müssen wir jetzt mal gucken, dass wir das verstehen.
Also wir starten es. So, wir sind jetzt dabei
von außen, zum ersten Mal in diese rekursive Funktion reinzuschwenken.
Das ist an sich noch kein rekursiver Funktionsaufwurf,
ja, also Hango an Lampion, ruft Journey auf,
das kennen wir schon aus Woche 1. Gut,
wir sind noch nicht angekommen, das heißt,
wir müssen einen Schritt gehen uns jetzt selber aufrufen.
Wir hoffen also, dass wir durch dieses Mofoward das Problem
kleiner gemacht haben. Gut. Jeder Aufruf in Kerl
sorgt ja dafür, dass ein neuer roter Balken dazukommt.
Zum Beispiel dieser rote Balken geht hier los,
weil hier der Aufruf ist oder endet hier,
weil hier die aufgerufene Methode endet.
Dieser Aufruf geht hier los, weil hier der Aufruf ist
und weil hier die aufgerufene Methode endet.
Macht euch doch mal kurz zehn Sekunden Gedanken darüber,
wenn ich jetzt einen Step mache, wie der nächste rote Balken aussieht.
Wo fängt er an, der rote Balken und wo endet der rote Balken?
Überlegt euch das einfach mal zehn Sekunden. Gut,
der Cousin hat zehnmal geblinkt, dann müssten das ungefähr zehn Sekunden sein.
Also ich sage folgendes, der rote Balken startet bei der Aufrufstelle,
also in Zeile 30 und wo endet die Funktion, die wir aufrufen?
Journey endet ja hier, müsstet also Batterien 30 enden.
Ich würde jetzt also warten, dass quasi von hier bis hier
ein roter Balken entsteht. Jo, exakt, das ist passiert.
Gut. Jo, wir sind noch nicht angekommen,
wir gehen einen Schritt und rufen uns selber auf.
Seht ihr das jetzt noch ein roter Balken jetzt?
Wir sind noch nicht angekommen, wir gehen einen Schritt und rufen uns selber auf.
Noch ein roter Balken. Jedes Mal, wenn wir uns
selber aufholen, kommt so ein roter Balken dazu.
Also es wächst jetzt quasi dieser Aufrufsdeck,
weil wir uns jedes Mal daran erinnern müssen,
von wo kamen wir denn ursprünglich mal?
So. Und jetzt sind wir an der Wand angekommen.
Jetzt ist also quasi, ja, keine weitere Reise mehr zu Unternehmen.
Ich kann nicht sagen, okay, das ist jetzt ein
triviales Problem, ich muss mich nur noch umdrehen.
Und jetzt muss man uns daran erinnern, von wo kamen
wir denn ursprünglich mal? Wer hat uns denn aufgerufen?
Dazu guckt man sich einfach den roten Balken an.
Wir kamen ursprünglich von hier. Das bedeutet, dieses Moforward
müssen wir noch ausführen. Zack, ausgeführt. Okay,
haben wir da also jetzt auch dieses Journey durch.
Von wo kamen wir ursprünglich? Wir kamen von hier,
also müssen wir dieses Moforward noch ausführen.
Das passiert jetzt die ganze Zeit weiter.
Und jedes Mal baut sich hier einen so einen Stackframe ab.
Und irgendwann sind alle rekursiven Aufrufe abgearbeitet
Und das hat dafür gesorgt,
dass genauso viele Move Howards auf den Rückweg gegangen wurden,
wie sie auf dem Hinweg eben gegangen wurden.
Und jetzt sind wir auch mit dem letzten Journey-Aufruf fertig,
das war jetzt kein rekursiver Aufruf, sondern wir kamen von hier,
dann müssen wir nur noch das Turnleft machen.
Jo. Und dann kann ich das jetzt mal ein bisschen beschleunigen und achte mal darauf,
wie sich hier dieser Aufruf steckt, immer auf- und wieder abbaut,
abhängig davon, wie hoch die Wand ist.
Also je höher die Wand ist, desto größer wird auch der Aufrufsdeck,
so ungefähr bis hier bei der Wand größer.
Und bei diesen Wandgrößen ist er dann eben nicht ganz so groß.
Ist das nicht toll, hier hier immer wieder wächst und widerschrumpft,
auf dem Hinweg wächst, da auf dem Rückweg schrumpft er.
Gut. An dieser Stelle frage ich übrigens gerne, wer hat das verstanden?
Einmal Handtuch. Gut. Das motiviert mich, Kerl,
auch weiterhin für das Thema Rekursion einzusetzen. Gut,
dann wollte ich euch nochmal ganz kurz einen Rätsel zeigen,
was ihr gar nicht als Pflichtaufgabe machen müsst,
aber einfach Es gibt ja immer so ein paar Leute,
die interessiert das, die finden das irgendwie cool.
Ich wollte es euch einfach mal animiert in der Vorlesung zeigen,
wie Carol das Pascal Che Dreieck hinlegt.
Er hat das Pascal Che Dreieck sowieso definiert. Die Ränder
des Pascalischen Dreiecks sind Einsen und jedes, jedes, ja,
jedes andere Element dieses Pascalischen Dreiecks ist die Summe der beiden Zahlen darunter.
Also eins und eins ist zum Beispiel zwei, eins und zwei ist drei,
1 und 3 ist vier, 1 und 4 ist 5,
4 und 5 bis 9 und so weiter.
Und das kann man mit relativ wenig Code, ich glaube,
das passt auf einen Bildschirm, kann man dieses Dreieck legen.
Und ja, vielleicht ist es ja jetzt schon aufgefallen,
es gibt manche Rätsel, da darf Carol mehrere Diamanten auf eine Stelle legen.
Das ist meistens nicht erlaubt. Okay, nur so als kleine Motivation,
dass ihr irgendwie vielleicht ein bisschen Spaß habt,
auch nicht Pflichtaufgaben mit Carol zu lösen.
Gut, dann mache ich Carol jetzt mal dicht,
dann wird er auch, glaube ich, möglicherweise,
wo ich in der letzten Vorlesung nochmal raus,
wir gucken mal.
Mit der vollständigen Induktion, könnt ihr euch auch zu Hause angucken.
Das ist ja hier keine Mathematikvorlesung. Okay, dann starte ich
mal Bluetrain. Genau, und ich wollte einfach nochmal,
dass ihr mal in Bluetrain im Debugger gesehen habt,
wie man ja rekursive Funktionen quasi debuggen kann.
Also machen wir uns mal hier kurz ein neues Exemplar,
dann lassen wir mal den Quote hier schön sichtbar,
machen wir das mal weg, das brauchen wir nicht.
Ich will den Code sehen. Ja, das kann meine
Code, glaube ich, sehen. Dann führe ich das
mal aus. Hier ist die Fakultät. Also ich muss
einen Breakpoint setzen, das vergesse ich immer ganz gerne.
So, machen wir mal die Fakultät von drei,
das haben wir mit den Folien ja auch gemacht.
Hier sehen wir jetzt unseren Aufrufstabel. Also bis jetzt ist nur einmal
diese Funktion Fakultät aktiv. N hat den Wert 3,
weil ich ja gerade das mit dem Wert 3 aufgerufen habe.
Und wir prüfen jetzt, ob 3 gleich 0 ist.
Das ist ja sicherlich nicht der Fall. Und jetzt
habe ich das hier nochmal so in zwei Zwischenschritte aufgeteilt.
Also auf der Vorlesungsfolie war es einfach nur eine Zeile.
Ich habe das hier mal bewusst in zwei Zeilen aufgeteilt.
Werdet ihr gleich sehen, warum. Okay,
also bevor ich jetzt weitermachen kann, muss ich jetzt erstmal sagen,
was ist denn die Fakultät von 2? Weil 3,
minus 1 ist ja 2. Ich rufe mich jetzt also rekrusiv
auf und wir schauen mal, was da passiert.
Es sind jetzt zwei interessante Dinge passiert. Einmal ist jetzt
hier eine zusätzliche Aktivierung oder Instanzsachen auch manchmal dieser Funktion auf
diesen Aufrufsdeck dazugekommen, wo N-Ebenen Wert 2 hat.
Und ihr könnt jetzt sogar beliebig zwischen denen hin und her
sprengen. Also das ist quasi der ursprüngliche Aufruf,
wo Ende einen Wert 3 hatte. Und das ist der
frische Aufruf, wo Ende einen Wert 2 hat.
Okay, 2 ist nicht 0. Das heißt,
wir gehen ins ALS und rufen uns rekrusiv auf.
Jetzt kommt hier noch
eine weitere Instanz
Die Währung und so, wo enden Wert eins hat.
Eins ist immer noch nicht null, wir rufen uns nochmal rekursiv auf mit null.
Jetzt haben wir hier also schon vier Aktivierungen,
das ist die UN3 ist, das ist die UN2 ist,
das ist die UN1 ist.
Und die warten jetzt alle an dieser Stelle,
dass diese rekursiven Aufrufe zurückkehren, weil vorher kann es ja nicht weitergehen.
Okay. Gut, Ende ist null. Ja,
Ende ist null. Das heißt, wir gehen jetzt mal
hier rein und sagen, das Ergebnis soll eins sein.
Das wissen wir. Dafür brauchen wir uns nicht rekursiv aufzurufen.
Gut. Und jetzt geben wir dieses Ergebnis zurück an unseren
Aufrufer. Wenn ich jetzt hier einen roten Balken hätte,
dann würde der rote Balken quasi von hier, nach hier gehen.
Ich kann jetzt also diese eins zurückliefern an diese Stelle,
dann glaube ich, das irgendwie hinkriege.
Also jetzt wissen wir, dieser Ausdruck ist eins,
also stetig hier quasi intempt gleich eins. Ich würde also warten,
dass in die Variante tempt der wird eins reingeschrieben wird.
Hier ist er. Dieses Temp ist also quasi das Zwischenergebnis des rekursiven Aufrufs.
Und das muss ich jetzt noch mit N multiplizieren.
Also weil Temp ist ja quasi Fakultät von Aminus eins,
jetzt muss ich das so mit N multiplizieren.
Haben wir auch eins in diesem Fall,
war einmal eins, ist ja eins.
Und das geben wir jetzt zurück an den Aufrufer.
Das heißt, auch dieser Ausdruck ist eins. Gut,
speichern wir also wieder die einzelne Biople Temp,
multiplizieren das, zweimal eins ist zwei.
Haben wir jetzt also zwei, die war ja auch da reingetan.
Und geben das jetzt an unseren Aufruf zurück.
Das heißt, dieser Ausdruck ist zwei. Okay,
also zwei in die Variante Temp speichern und dann ausrechnen,
was ist denn dreimal zwei? 302 ist sechs. Und
dann wird die sechs an den Aufrufer zurückgerufen und der Aufrufer
sichtlich, hier gibt es jetzt gar keinen Aufrufe mehr.
Das war ich ja quasi selber, der interaktive Blu-Joy-Benutzer.
Gut. Steppen wir das mal. Und da kriege ich jetzt
die sechs als Ergebnis, weil hier quasi Stand Return sechs,
wenn man so will.
Gut. Wer hat das verstanden, einmal Handtor?
Okay, ungefähr genauso viele Leute. Das scheint also
genauso anschaulich zu sein. Das ist doch schön.
Gut. Ja, okay
Jetzt mache ich mal eine kleine Abstimmung. Ihr kennt doch
diese Adventure-Hefte, wo man auswählen kann, wie es weitergeht.
Also ihr könnt jetzt entweder sagen, ich will das Fred,
was über Fimonachi-Zahlen erzählt, rekursiv und iterativ und vielleicht noch besser.
Das wäre die eine Option. Und die andere Option ist,
ich könnte euch zeigen, wenn man hier unten in BlueJay
irgendwas eingibt, dann wird das ja ausgerechnet.
Und man kann sich vorstellen, da steckt ja bestimmt ziemlich viel Magie dahinter.
Also irgendwie muss der Computer verstehen, was diese ganzen Symbole bedeuten.
Das Punkt vor Strichrechnung gilt und so weiter.
Und sowas könnte man auch selber programmieren. Und wenn wir
richtig gut sind, können wir sogar heute noch programmieren,
dass das vielleicht sogar mit Klammern geht.
Also vielleicht irgendwie das mit Klammern was anderes rauskommt.
Ich weiß nicht, ob das in 20 Minuten hinbekommt,
aber man könnte es zumindest mal versuchen.
Wer möchte was über Fimonachi-Zahlen hören? Okay, so zwei,
drei Leute. Wer möchte lieber das mit dem rechnen?
Okay, dann machen wir das. Kann sich niemand beschweren
. Ihr wolltet das ja so. Okay. Gut.
Ich mache dazu vielleicht erstmal wieder mein Lieblingsprogramm auf,
denn mir ist aufgefallen, als ich das letztes Jahr gemacht habe,
Da habe ich so einen riesigen Stapel Quote, den Leuten einfach vorgesetzt.
Oh, falsches Programm. Und irgendwie war das ein bisschen viel auf einmal.
Die Theorie dahinter war nicht so richtig klar, wo ist mein Editor hier?
Und ich wollte das mal schön von den Basis-Bausteinen auf ausbauen,
was wir hier eigentlich machen wollen. So, jetzt mache ich das,
wenn man hier tatsächlich mit Text statt mit Pinseln,
das ist, glaube ich, ein bisschen sinnvoller.
Ich weiß nicht, was ich immer für eine Größe nehme vielleicht, keine Ahnung, 36.
So, und dann irgendwie sowas wie zweimal, dreimal vier,
plus fünfmal, sechs, plus sieben, plus achtmal neun oder so.
Das ist doch ein schönes Beispiel. So,
dann mache ich mal den ein bisschen weniger dick,
vielleicht fünf, und dann nehme ich mal eine andere Farbe,
dann nehmen wir mal blau.
So, ich werde bestimmt keine Methode schreiben können,
die komplett dafür verantwortlich ist und die ganze Logik implementiert und das hier auszurechnen.
Ich mache das Problem mal ein bisschen kleiner,
das hat jetzt erstmal nichts mit Rekursion zu tun,
aber irgendwie bin ich nicht in der richtigen Ebene.
Wie kriege ich jetzt hier meine Ebene richtig hin,
muss ich erstmal
irgendwas anderes auswählen
Das ist blöd, ich bin jetzt noch in der Ebene drin.
Ach, Fenster oder so, wie kriege ich das hin,
dass ich meine Ebenen sehe? Kennt sich jemand mit...
Kennst du jemanden so gut mit Gim, aus,
dass er weiß, wo ich dieses Ebenen-Tool herbekomme?
Das Gimbalex ist an sich in einem eigenen Fenster,
wenn man das in der Ansicht hat, hast du glatte Mittel runter zum Fenster.
Nee, ich glaube, ich habe das irgendwann mal geschlossen,
weil ich dachte, ich brauche es nicht.
Fenster, anblockbare Dialoge, Ebenen. Ah, genau,
seht ihr, und ich will jetzt auf den Hintergrund,
weil sonst kann ich nichts machen auf den Hintergrund.
Dankeschön. So, genau. Also ich will erstmal
eine blaue Funktion schreiben, die nur dafür zuständig ist,
diese Ziffern quasi sinnvoll zu erkennen und mit denen was machen.
So, was kommt als nächstes noch blau, vielleicht grün,
keine Ahnung, dann will ich eine Funktion schreiben,
die diese Multiplikation macht
Ja, im Prinzip ist das hier auch eine Multiplikation eines Faktors.
So. Und dann will ich eine Funktion schreiben,
um die Fahrt mal rot, die Atditionen ausführt.
Und warum habe ich das jetzt in der Reihenfolge gemacht und nicht andersrum,
war ja das Mal stärker bindet als das Plus.
Also ich muss erst gucken, welche Werte haben solche erziffern,
wenn ich das jeweils weiß, für zwei kann ich das multiplizieren.
Und erst wenn ich mehrere solcher Produkte quasi ausgerechnet habe,
kann ich anfangen zu addieren, vorher nicht.
Also ich kann zum Beispiel nicht viele Plus 5 addieren,
das wäre irgendwie Quatsch, weil ich muss ja erst mal die Multiplikationen machen.
Okay, das versuchen wir mal. Gut,
das tue ich mal irgendwie so als, jetzt will ich
das nicht wieder schließen, sonst suche ich es nachher.
Ach ne, ich bin mal optimistisch, ich brauch es heute nicht mehr.
So, das schiebe ich mal nach hier, dass wir es
immer sichtbar haben. Das will ich eigentlich auch nicht haben,
aber das ist mir zu gefährlich, das zu löschen.
So, genau. Vielleicht Fangen wir erst mal mit der Benutzung an.
Ich will also eine Methode in diesem Parser haben, die der Benutzer aufrufen kann.
Deswegen muss die Public sein. Die soll einen Int zurückliefern,
quasi das Ergebnis, ich würde es ja auszeichnen,
also vielleicht kommt, ich glaube, 205 oder so
kommt er raus, ich habe das irgendwann mal ausprobiert.
Und ich nenne es einfach mal so. Das könnt ihr,
also weder das Netz ist ja völlig egal.
Und man tut da irgendeinen Ausdruck rein. Okay. Und
das haben wir noch nicht implementiert, da tun wir mal 42 zurückgeben.
So. Welchen Zustand brauchst du ein Parser? Der Parser muss erst mal,
wenn ich das jetzt in mehrere Methoden aufteile,
eine blaue Methode, eine grüne Methode, eine rote Methode,
die brauchen ja alle irgendwie Zugriff auf diesen String,
diesen String, den ich da reinstecke.
Zwei Kreuz, drei, Kreuz, vier und dann dieses Calls 5.
Also dieser String, der da reingesteckt wird,
den muss ich mir sicherlich irgendwie merken,
sonst werden die anderen Methoden darauf keinen Zugriff haben und ich will die nicht überall immer durchreichen müssen.
Also ich nenne das vielleicht mal hier Input,
keine Ahnung
Dann muss ich das da sicherlich speichern. So. Dann muss ich
mir irgendwie merken, wo bin ich denn gerade in dem String?
Also diese Methoden, das werdet ihr dann später sehen,
die werden immer so im Abwechseln irgendwie aufgerufen.
Ich muss irgendwie wissen, wie weit bin ich
schon fortgeschritten in dem Durchpassen von diesem String?
Bin ich gerade ganz am Anfang oder irgendwo in der Mitte
oder schon fast am Ende oder so?
Dafür brauche ich eine eigene Variable, die nennen wir mal Position.
Und was ich dann immer fürs Debakken sehr nett finde,
ist, wenn man eine Scha-Variable hat,
wo quasi das aktuelle Zeichen drin ist.
Eigentlich braucht man dafür keine eigene Variable.
Ich könnte ja einfach jedes Mal diesen String fragen,
hey, gib mir doch mal das Zeichen an dieser Position.
Aber wir brauchen das an relativ vielen Stellen und in Debaker ist es eben,
wie gesagt, auch nett, wenn man das sieht.
Okay. Dann machen wir mal als nächstes eine Methode.
Ich nenne die mal ganz gerne Move oder Accept oder Advance
, ich nenne sie jetzt einfach mal Advance.
Klingt sehr advanced, aber das heißt einfach nur,
geh doch mal bitte zum nächsten Zeichen.
Mehr heißt es gar nicht. Ich erhöhe einfach mal die Position,
dann sage ich, Ja, eigentlich würde ich jetzt am liebsten sagen,
das Zeichen ist ja sicherlich der Input an der Position, Position.
Aber es könnte jetzt natürlich sein, dass ich irgendwann ganz fertig bin mit dem String.
Ich habe ihn komplett eingelesen. Und dann wurde irgendeine blöde
Acception kommen. Das will ich natürlich auch nicht.
Also ich frage jetzt vielleicht mal ganz kurz ab,
ob es überhaupt noch eine gültige Position ist.
Ich kann ja fragen, ist die Position kleiner als die Länge des Strings?
So macht man das, glaube ich, in Java.
Ups, genau. Also wenn es tatsächlich kleiner ist,
dann ist da noch irgendein Zeichen. Und damit es nicht irgendwie abstürzt oder irgendwas,
sage ich jetzt einfach mal, wenn wir am Ende angekommen sind,
nehme ich mal irgendein Schwachsinnszeichen und tue das da rein.
Das ist höchst die Wagen auch immer ganz nett,
dass man sofort erkennt, wo ich bin.
Also Martin Motto, wenn ich einmal ganz durchgekommen bin,
dahinter kommen dann nur noch Klammeraffen.
Ich könnte da jedes andere Zeichen nehmen. Das ist einfach nur,
falls wir uns gleich vertun beim Programmieren und das nun mal bestimmt,
dann wissen wir, ah, es lag daran,
dass wir schon fertig waren.
Okay, was sind denn jetzt sinnvolle Startwerte dafür? Ich glaube,
am einfachsten ist es, wenn ich sage,
ich fange mal vor dem String an an der Position minus eins
und gehe dann mal zum nächsten Zeichen.
Das heißt, ich gehe also quasi auf das
erste echte Zeichen drauf
Gut. Okay, das sind erstmal so ein paar Vorbereitungen.
Und jetzt würde ich ganz gerne mal mit den elementaren Basis-Bausteinern anfangen.
Klassisch habe ich immer hier oben angefangen,
das sind die Leute mal enorm verwirrt,
weil man dann sozusagen Methoden aufruft, die es noch gar nicht gibt.
Wir fangen jetzt mit dem einfachsten Fahren. Wir programmieren jetzt also,
ich gucke mir an,
welches Zeichen da gerade ist und irgendwie muss ich sagen,
ah, das ist das Zeichen 2,
das hat den Wert 2 oder das ist das Zeichen 3,
das hat den Wert
3. Warum muss man dafür überhaupt was programmieren?
Wenn man mal hier in Blu-Jay reingeht, werdet ihr sehen,
man kann mit solchen Zeichen nicht besonders gut rechnen.
Also wenn ich zum Beispiel sage,
was ist denn 1 plus 2,
wenn es noch Charles hat und ein String besteht dann nochmal aus Charles,
dann kommt dann 99 aus, das ist ja komisch.
Müsste das nicht eigentlich 3 sein? Das liegt einfach daran,
dass diese Charles eine gewisse Unicorse oder Usky-Codes haben.
Also die 1 hat zum Beispiel den Asky-Code 49 oder die 0,
zum Beispiel von der Ask-Code 48, die 9 hat 57.
Also ich muss jetzt erstmal von diesem Unicord
quasi runterkommen auf den Bereich von 0 bis
Okay, machen wir dazu nochmal eine Methode. Ich nenne
die einfach mal. Passfaktor, nenne ich die mal.
Okay. Und dann schaue ich mir doch einfach mal an,
was steht denn gerade in dem aktuellen Zeichen?
Ich switche da einfach mal rüber. Das Switch kennen wir ja schon.
Ich switche da einfach mal rüber. Dann mache ich das mal irgendwie ganz blöd,
dass ich also sage, wenn es der Case null ist,
1, 2, 3, 4, 5, 6,
7, 8, 9, das ist also jetzt sehr explizit,
man könnte das sicherlich geschickter machen mit irgendwelchen Bereichsuntersuchungen mit IF oder so,
aber ich will, dass es möglichst einfach verständlich ist,
dass ihr euch nicht an irgendwelchen Details aufhängt.
Also wenn es einer dieser zehn Fälle ist,
dann mache ich jetzt einfach mal Folgendes, ich sage,
naja, vielleicht tue ich mal hier eine Result-Variable hin,
weil das ein bisschen länger ist, ich weiß noch nicht,
was da für ein sinnvoller Wert ist,
ich mache das jetzt erst mal so,
dann sage ich jetzt, okay, das Ergebnis soll sein,
das, was in der Variable Current drinsteht,
minus der Asri-Code von null,
warum mache ich das
Das schauen wir uns mal hier ganz kurz an, warum das sinnvoll ist.
Was ist denn zum Beispiel sieben minus null? Ja,
ich muss ja mal jeweils 48 drauf addieren für den Aske-Code,
also quasi 55 minus 48. Oh,
das ist sieben als in, das ist ja praktisch.
Oder was ist denn zum Beispiel zwei minus neu?
Ach, das ist zwei, das ist ja genau das,
was ich brauche. Ich gucke mir also einfach nur an,
in diesem Aske-Code, in dem Bereich,
wo die Ziffern sind von 0 bis 9,
wie weit ist die Ziffer denn von der Null weg?
Die Null ist null davon weg, die Eins ist einen davon weg,
zwei davon weg, bitte, bitte, neun davon weg.
Ich gucke mir einfach an, wie weit ist von der Null weg.
Dann kriege ich eine sinnvolle Zahl. Sehr schön. Wenn ich das jetzt gemacht habe,
ja, ich habe mal so diese zwei angeguckt und festgestellt,
okay, ich weiß, was den wer zwei hat,
dann muss ich jetzt ja weitergehen.
Also machen wir dieses Advance. So, haben wir da so quasi abgearbeitet.
Und als ich das gestern mal probe im Play Michator,
habe ich das Break vergessen, das mache ich jetzt nicht.
Okay, was machen wir im anderen Fall? Tja,
da müssen wir uns mal Gedanken machen und würde das
heute auch hinkriegen. Ich schreibe da mal hin,
to do error Handling
Immer sein, dass der Benutzer Unsinn eingibt,
muss man mal gucken, was man da sinnvoll machen kann.
Das lassen wir uns aber aus Zeitgründen erst mal raus.
Okay, und am Ende geben wir das Resulting zurück.
So, was wir jetzt hier programmiert haben, ist diese blaue Funktion quasi.
Ich gehe mal davon aus, dass da ein Zeichen steht,
ich schaue mir den Aske-Code an oder den Unicode,
rechnet es um in einen sinnvollen Int,
gehe einen weiter in dem String nach dem Motto,
ich habe die zwei jetzt abgearbeitet,
brauchen wir uns nicht mehr angucken und dann liefere ich die zwei als Ergebnis zurück.
Wer interessiert sich denn jetzt für die zwei? Also zum Beispiel diese zwei,
diese drei, diese vier, die sind ja deswegen interessant,
weil die multipliziert werden müssen von dieser grünen Funktion.
Ich würde jetzt also als nächstes eine grüne Funktion bauen,
die sagt, hey, lies doch mal diese ganzen Ziffern ein,
solange du solche Sternchen findest und die sollst du dann immer aufmultiplizieren.
Das ist der nächste Schritt, den wir jetzt machen.
Ich schiebe das wieder nach hier,
dass man das irgendwie vielleicht gleichzeitig sehen kann und weiß,
wo wir gerade sind, gedanklich.
Wir sind jetzt also hier bei dieser grünen Funktion quasi.
Das ist die blaue Funktion
Und wir schreiben jetzt die grüne Funktion. Und ich schreibe es
jetzt da drüber, dass es genauso ist wie in der Grafik.
Also nenne ich das mal, ach guck mal,
ich habe den Grabetyp vergessen.
So. Nehmen wir das mal Pass Product. Wenn ich multipliziere,
kommt tatsächlich ein Produkt bei raus. So. Was ist das Erste,
was sozusagen am Anfang eines jeden grünen Balkens steht?
Da drunter steht auch immer ein blauer Balken. Also wenn ich
ein Produkt mir angucke, ist die erste Zutat eine Zahl, ein Faktor.
Also kann ich eigentlich direkt erst mal damit anfangen zu sagen,
hol dir doch mal den ersten Faktor.
Das wäre in unserem Beispiel die zwei. Gut. Haben
uns also die zwei geholt und als nächstes stehen wir jetzt hier.
Wenn wir uns jetzt zum Beispiel,
wenn wir schon so weit gewesen wären,
dass wir uns die vier geholt hätten, würden wir als nächstes hier stehen.
Hier müssten wir jetzt aufhören. Hier müssen wir jetzt auch weitermachen,
weil wir wollen ja Faktoren finden, die wir multiplizieren können.
Also muss ich jetzt sagen, solange das aktuelle Zeichen ein
Sternchen ist, muss ich noch weiter multiplizieren.
Was ich auch gestern vergessen habe, ist,
ich habe mir jetzt dieses Sternchen angeguckt und habe festgestellt,
oh, ein Sternchen, alles klar,
ich muss in die Schleife reingehen,
dann muss ich jetzt hier einen weitergeben.
Weil ich will mir jetzt ja als nächstes,
muss ich jetzt ja hier mit der 3 quasi weitermachen.
Okay, jetzt erwarte ich, dass da wieder ein Faktor steht,
den tue ich mir mal in die Variable B. So,
jetzt habe ich also, wenn ich das zum ersten Mal ausführe,
wird dann A2 drinstehen, in B wird 3 drinstehen.
Jetzt kann ich eigentlich direkt multiplizieren, zweimal 3 ist ja 6,
bauen wir uns einfach mal in die Variable A reintun.
Ich sage jetzt einfach mal A, ist A mal B. Okay. Gut,
dann schauen wir wieder, steht da ein Sternchen,
ja, da steht ein Sternchen,
dann tun wir uns mal die 4 in das B rein
und dann können wir eigentlich auch gleich wieder weiter multiplizieren.
Sechsmal 4 ist 24. Okay. Oh, jetzt ist hier ein Plus.
Jetzt müssen wir aufhören, wir können jetzt nichts mehr machen.
Wir sind ja nur dafür zuständig zu multiplizieren.
Wenn also kein Sternchen mehr hier steht,
dann können wir zurückgehen und sagen, tja,
was geben wir jetzt als Ergebnis zurück?
Wir haben doch so schön gerade multipliziert,
Ist es jetzt sinnvoll, als Ergebnis zurückzugeben.
Wo steht das Ergebnis und wo steht die 24 drin?
In A, genau. Gut. Schauen wir,
wir sind schon fast fertig. Jetzt fehlt nur noch diese
rote Funktion. Welchen Sinn hat die diese rote Funktion?
Wenn ihr euch anguckt, was da drunter steht,
fängt auch immer mit so einem grünen Strich an.
Denn wenn ich Dinge addieren will,
das sind ja alles Produkte, ich will Produkte addieren.
Also ist eigentlich der Aufbau fast genauso wie die Funktion hier unten?
Ich mache jetzt nicht Copy-Paste, weil ich da garantiert irgendwas Falsches mache.
Aber ihr werdet sehen, dass der Code extrem ähnlich ist.
Ich sage also, ich hole mir quasi erstmal das erste Produkt.
Das wäre also quasi hier. Hier wurde eine 24 zurückgeliefert werden.
Und dann muss ich schauen, steht als nächstes ein Plus.
Wenn da ein Plus steht, habe ich ja was zu tun.
Mein Sinn ist es ja, meine Aufgabe ist es ja,
zu addieren. Okay. Was muss ich dann machen?
Dann muss ich mir das nächste Produkt holen.
In diesem Fall wäre das dieses 5 mal 6. Code hole
ich mir das nächste Produkt
Und was muss ich jetzt hören? Jetzt habe ich also
zwei Produkte, einmal 24 und einmal 30.
Was muss ich mit denen tun? Nee, das tun
diese... Ach, ah, hier, danke.
Ah, toll. Sehr gut. Was muss ich jetzt
machen mit den beiden Produkten, die ich habe?
Was ist meine Aufgabe als rote Funktion?
Einfach in den Raum rufen? Adir, richtig. Also
A ist gleich A plus, B. Gut. Ja,
und das wird also dafür sorgen, dass ich,
die erste Addition wird quasi diese sein,
die nächste wird dann diese sein, die nächste wird diese sein.
Und dann wird er irgendwann fragen, welches Zeichen steht denn hier hinter,
dann wird dieser Klammer verkommen und dann werden wir hier rausgehen können.
Dann können wir unser A einfach zurückgeben. Gut. Schauen wir mal,
jetzt haben wir also diese drei Funktionen gebaut, die so aufeinander aufbauen.
Und dann müssen wir das jetzt noch sinnvoll aus dieser Hauptfunktion aufrufen.
Also wir sind ja auf die erste Position gegangen,
dann würde ich sagen,
können wir doch mal dieses Pass Sum auf,
wenn wir uns das Ergebnis einfach mal
eine Variable speichern
So vielleicht. Und das kann man eigentlich auch direkt zurückgeben.
Normalerweise müsste man hier jetzt noch weiter das Error-Handling machen,
das kriege ich jetzt in der Zeit nicht mehr hin.
Könnte ja sein, dass da jemand hinterher noch irgendeinen Quatsch hinschreibt.
Also stellt euch vor, hier hinter würde jetzt ein Ausrufezeichen stehen oder irgendwas anderes.
Das wäre sicherlich nicht so sinnvoll. Und jetzt drücke ich mal auf Compile,
das habe ich ja schon seit einer Viertelstunde nicht mehr gemacht.
Oh. Okay. Zumindest keine Übersetzungsfehler. Dann will ich
das jetzt mal mit euch zusammen kurz debacken.
Damit ihr versteht, was da passiert. Wo tut man
den Haltepunkt hin, tun wir vielleicht mal hierhin. Gut. Okay,
dann mache ich mir doch mal einen neuen Paser und sage direkt daran,
ich brauche dafür keine Zwischenvariable und Pase doch mal und vielleicht jetzt
nicht ganz so kompliziert, zweimal drei, mal vier,
plus fünfmal sechs, das reicht, glaube ich.
So, jetzt nehmen wir also den Zustand unseres Pasers.
Also hier in dem Input steht genau das und was
ich eingegeben habe. Wir sind gerade an Position 0,
da sind wir gerade raufgegangen durch dieses erste Advanced und da
steht eine 2,
das ist korrekt.
Wir sollen jetzt eine Summe passen, dann machen wir das doch mal.
Oh, nein, ich hätte Step Intro drücken müssen.
Verdammt. Okay, abbrechen noch mal von vorne.
Das ist ja blöd. Zweimal, dreimal, vier Plus.
Dann habe ich das dasselbe, ja, ne? Okay,
also das ist der Knopf, den ich drücken will.
Gut. Okay, wir müssen das erste Produkt passen.
Achtet mal darauf, dass jetzt hier ein neues Stackframe dazukommt.
Und um das erste Produkt zu passen,
müssen wir erst mal den ersten Faktor parsen.
Sind wir jetzt hier? Und jetzt switchen wir über dieses Köln,
das Köln ist ja diese zwei, das heißt,
wir werden hier irgendwie landen hoffentlich.
Jetzt sind hier keine Funktionsaufrufe, mehr wir jetzt switchen darüber, genau.
Jetzt müsste in Result also die zwei als Intren stehen,
tut sie auch. Dann ruhen wir das Advanced auf,
da gehe ich jetzt nicht rein. Die Position müsste sich
jetzt um einen erhöhen und hier müsste jetzt das Sternchen stehen.
Genau. Okay, und dann kann das hier zurückgegeben werden.
Gut, wir haben also den ersten Faktor gepasst,
sehr schön
Haben wir das gemacht? Und jetzt gucken,
wer steht jetzt hier ein Sternchen? Ja,
denn wir sind ja gerade hier, wo das Sternchen steht.
Also gehen wir ran in die Schleife, überspringen das Sternchen
und sagen jetzt, dann müssen wir den nächsten Faktor pausen.
Gut. Ach, verdammt, ich bin schon wieder nicht reingegangen.
Aber es ist, glaube ich, nicht so schlimm.
Das habt ihr, glaube ich, verstanden, oder?
Dass wir jetzt den nächsten Faktor. Und wenn wir
so jetzt zwei Faktoren, zwei und drei.
Und wenn ich die multipliziere, haben wir sechs.
Gut, dann schauen wir uns wieder die Schleifenbedingungen an.
Da steht noch ein Sternchen. Deswegen gehen wir dann in
die Schleife rein. Wir gehen wieder einen weiter. Jetzt
sind wir an Position 4, wo die vier steht.
In das Passfaktor springe ich jetzt hier rein.
Das versteht ihr. Haben wir jetzt also diese vier gepasst.
Jetzt kann ich sechs und vier multiplizieren.
Da kommt 24 raus und die gebe ich wieder zurück.
Und jetzt steht da kein Sternchen mehr, sondern ein Plus.
Das heißt, ich kann hier rausgehen und die 24 zurückliefern.
Gut, dann sehe ich jetzt aber, oh,
da steht ja ein Plus, dann überspringe ich mal das Plus.
Und dieses Pass Product. Genau,
das kann ich jetzt eigentlich auch mal überspringen, oder?
Die Details interessieren mich nicht. Was müsst ihr
denn da jetzt rauskommen
Welchen Wert müsste B haben? 30. Richtig, da ist
er, ne? Gut. Dann sehen wir jetzt,
jetzt sind wir hier am Ende angekommen, deswegen steht da der Klammeraffe.
Gut. Nehmen also raus und jetzt können wir die 54 zurückgeben.
Okay. Jetzt ist hier aber noch keine Rekursion drin und
ich habe noch eine Minute, das freut mich total.
Man will ja vielleicht auch geklammerte Ausdrücke. Also ich will ja vielleicht
sowas haben, ich will sowas ausrechnen können, wie,
hatte ich ja schon gesagt, zweimal drei plus vier oder so.
Das kann Bluejay ja auch. Das will ich auch können
. Das heißt also, die Multiplikation funktioniert nicht nur mit
ganz einfachen Ziffern, sondern auch mit geklammerten Ausdrücken.
Ich muss jetzt hier also meine Faktor-Methode so anpassen,
dass ich sage, nicht nur diese zehn Zeichen akzeptiere ich,
sondern ich akzeptiere auch, wenn da eine geschweifte Klammer aufsteht.
Wenn da eine geschweifte Klammer aufsteht, dann sage ich,
alles klar, die brauche ich nicht mehr,
kann ich drüber springen.
Dann rufe ich Past Sum auf,
denn in dieser Klammer kann jetzt ja wieder
irgendeine völlig beliebige Summe drinstehen
Okay. Und anschließend gehe ich mal davon aus,
dass da jetzt wieder eine geschweifte Klammer zukommt,
da müssten wir uns auch wieder Aero-Handling machen, das überspringe ich mal.
Also ich schreibe da jetzt mal hin,
dass quasi jetzt hier die Klammer zu überspringen will.
Und dann breake ich ja auch mal.
Warum ist das denn jetzt Rekursion? Also ich meine,
dieser Funktionsrauf ist keine, ich rufe mich hier nicht selber auf,
hier rufe ich mich nicht selber auf,
hier rufe ich mich auch nicht selber auf,
das und hier rufe ich mich auch nicht selber auf.
Warum ist das denn jetzt Rekursion? Ja, vielleicht noch
mal irgendjemand anders. Ja. Genau, so eine indirekte
Rekursion über drei Stufen. Also ich habe drei Funktionen,
die erste ruft die zweite auf die zweite,
die dritte und die dritte ruft dann wieder die erste auf.
Gut. Was wir jetzt machen,
ist leider ist ja nicht mehr so bezahlt,
ich schiebe den Code jetzt mal hier nach links,
übersetze den mal, okay.
Und das testen wir jetzt mal,
ob das funktioniert
Wie könnte man es nochmal zeigen, dass es funktioniert?
1 plus 2, mal 3 plus 4. Was müsste da
rauskommen? Das muss man sich immer vorher klarmachen.
15? 3 mal 7, 21 müsste da rauskommen,
oder? Ja, das scheint also zu funktionieren,
genau. Ich wollte euch das einfach nur mal zeigen,
weil es sonst immer heißt, Fibonacci und Fakultät und so,
das braucht auch niemand, ja.
Das ist ja irgendwie kein sinnvolles Anwendungsbeispiel für Rekursionen, aber sowas,
solche Rechnungen auszurechnen, was wir vielleicht, ich brauche sowas ständig,
das kann man mit Hilfe von Rekursion und so ein paar Methoden relativ einfach machen.
Jo, das würde ich dann einfach ins Komsi stellen und
dann könnt ihr gerne daran weiter basteln.
Das ist vielleicht auch mit Subtraktion und Division geht.
Okay, bis nächste Woche