From 35c42f0a50ba7e89c8987f981c2b380856b3fe39 Mon Sep 17 00:00:00 2001 From: schwabmi <michel.j.schwab@gmail.com> Date: Thu, 14 Jan 2021 11:24:19 +0100 Subject: [PATCH] updated MB updates --- notebooks/seminar06.ipynb | 513 ++++++++++++++++++++++++++++++++------ 1 file changed, 436 insertions(+), 77 deletions(-) diff --git a/notebooks/seminar06.ipynb b/notebooks/seminar06.ipynb index 1808c43..2a86841 100644 --- a/notebooks/seminar06.ipynb +++ b/notebooks/seminar06.ipynb @@ -4,19 +4,29 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# Seminar Problemorientierte Programmierung\n", - "\n", - "## 6 Ertragreiche Funktionen\n", + "# 6 Ertragreiche Funktionen\n", "[Chapter 6: Fruitful function](http://greenteapress.com/thinkpython2/html/thinkpython2007.html)\n", "\n", - "\n", "Viele Python-Funktionen die wir bis jetzt genutzt haben, wie z.B. die Mathematik-Funktionen aus dem `math`-Modul, erzeugen Rückgabewerte (*return values*). Aber die meisten Funktionen die wir selber geschrieben haben sind \"leer\": sie bewirken etwas, beispielsweise die Ausgabe eines Wertes (mit Hilfe der `print`-Funktion) oder die Bewegung einer Schildkröte, aber sie haben keinen Rückgabewert. In diesem Kapitel werden wir lernen, wie wir \"ertragreiche Funktionen\", also solche mit Rückgabewert, schreiben können.\n", "\n", "\n", "\n", - "([Random Number](https://xkcd.com/221/), Randall Munroe)\n", - "\n", - "### Ihre Lernziele:\n", + "([Random Number](https://xkcd.com/221/), Randall Munroe). [Erklärung der Comics](https://www.explainxkcd.com/wiki/index.php/221:_Random_Number) falls Sie mehr erfahren wollen.\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "<h1>Inhaltsverzeichnis<span class=\"tocSkip\"></span></h1>\n", + "<div class=\"toc\"><ul class=\"toc-item\"><li><span><a href=\"#Ihre-Lernziele:\" data-toc-modified-id=\"Ihre-Lernziele:-1\"><span class=\"toc-item-num\">1 </span>Ihre Lernziele:</a></span></li><li><span><a href=\"#Exkurs:-Was-mir-an-Python-gefällt\" data-toc-modified-id=\"Exkurs:-Was-mir-an-Python-gefällt-2\"><span class=\"toc-item-num\">2 </span>Exkurs: Was mir an Python gefällt</a></span></li><li><span><a href=\"#Rückgabewerte\" data-toc-modified-id=\"Rückgabewerte-3\"><span class=\"toc-item-num\">3 </span>Rückgabewerte</a></span></li><li><span><a href=\"#Schrittweise-Entwicklung\" data-toc-modified-id=\"Schrittweise-Entwicklung-4\"><span class=\"toc-item-num\">4 </span>Schrittweise Entwicklung</a></span></li><li><span><a href=\"#Komposition\" data-toc-modified-id=\"Komposition-5\"><span class=\"toc-item-num\">5 </span>Komposition</a></span></li><li><span><a href=\"#Boolesche-Funktionen\" data-toc-modified-id=\"Boolesche-Funktionen-6\"><span class=\"toc-item-num\">6 </span>Boolesche Funktionen</a></span></li><li><span><a href=\"#Noch-mehr-Rekursion\" data-toc-modified-id=\"Noch-mehr-Rekursion-7\"><span class=\"toc-item-num\">7 </span>Noch mehr Rekursion</a></span></li><li><span><a href=\"#Vertrauensvorschuss\" data-toc-modified-id=\"Vertrauensvorschuss-8\"><span class=\"toc-item-num\">8 </span>Vertrauensvorschuss</a></span></li><li><span><a href=\"#Ein-weiteres-Beispiel\" data-toc-modified-id=\"Ein-weiteres-Beispiel-9\"><span class=\"toc-item-num\">9 </span>Ein weiteres Beispiel</a></span></li><li><span><a href=\"#Typen-prüfen\" data-toc-modified-id=\"Typen-prüfen-10\"><span class=\"toc-item-num\">10 </span>Typen prüfen</a></span></li><li><span><a href=\"#Debugging\" data-toc-modified-id=\"Debugging-11\"><span class=\"toc-item-num\">11 </span>Debugging</a></span></li><li><span><a href=\"#Glossar\" data-toc-modified-id=\"Glossar-12\"><span class=\"toc-item-num\">12 </span>Glossar</a></span></li><li><span><a href=\"#Übung\" data-toc-modified-id=\"Übung-13\"><span class=\"toc-item-num\">13 </span>Übung</a></span><ul class=\"toc-item\"><li><span><a href=\"#Aufgabe-1\" data-toc-modified-id=\"Aufgabe-1-13.1\"><span class=\"toc-item-num\">13.1 </span>Aufgabe 1</a></span></li><li><span><a href=\"#Aufgabe-2\" data-toc-modified-id=\"Aufgabe-2-13.2\"><span class=\"toc-item-num\">13.2 </span>Aufgabe 2</a></span></li><li><span><a href=\"#Aufgabe-3\" data-toc-modified-id=\"Aufgabe-3-13.3\"><span class=\"toc-item-num\">13.3 </span>Aufgabe 3</a></span></li><li><span><a href=\"#Aufgabe-4\" data-toc-modified-id=\"Aufgabe-4-13.4\"><span class=\"toc-item-num\">13.4 </span>Aufgabe 4</a></span></li><li><span><a href=\"#Aufgabe-5\" data-toc-modified-id=\"Aufgabe-5-13.5\"><span class=\"toc-item-num\">13.5 </span>Aufgabe 5</a></span></li></ul></li></ul></div>" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Ihre Lernziele:\n", "Beschreiben Sie in 2-3 Stichpunkten kurz was Sie im Seminar heute lernen wollen. Klicken Sie dazu doppelt auf diesen Text und bearbeiten Sie dann den Text:\n", "\n", " - \n", @@ -63,7 +73,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "### 6.1 Rückgabewerte\n", + "## Rückgabewerte\n", "\n", "Der Aufruf einer Funktion erzeugt einen Rückgabewert, den wir üblicherweise einer Variable zuweisen oder als Teil eines Ausdrucks verwenden:\n", "\n", @@ -74,7 +84,7 @@ "\n", "Die (meisten) Funktionen, die wir bisher geschrieben haben sind \"leer\" - sie haben keinen Rückgabewert. Präziser ausgedrückt ist ihr Rückgabewert `None` (also nichts).\n", "\n", - "In diesem Kapitel schreiben wir (endlich) ertragreiche Funktionen. Das erste Beispiel ist die Funktion `kreisflaeche`, die die Fläche eines Kreises für einen gegebenen Radius berechnet:" + "In diesem Kapitel schreiben wir (endlich) ertragreiche Funktionen. Damit haben wir bereits kurz in [Seminar 3](notebooks_seminar03.ipynb) angefangen und lernen jetzt genauer, wie das funktioniert. Das erste Beispiel ist die Funktion `kreisflaeche`, die die Fläche eines Kreises für einen gegebenen Radius berechnet:" ] }, { @@ -190,7 +200,55 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Schreiben Sie eine Funktion `compare`, die zwei Parameter `x` und `y` erwartet und `1` für `x > y`, `0` für `x == y` und `-1` für `x < y` zurückliefert:" + "Schreiben Sie eine Funktion `compare`, die zwei Parameter `x` und `y` erwartet und `1` für `x > y`, `0` für `x == y` und `-1` für `x < y` zurückliefert:\n", + "\n", + "\n", + "\n", + "<details>\n", + " <summary type=\"button\" class=\"btn btn-primary\">1. Hinweis</summary>\n", + " <div class=\"alert alert-info\" role=\"alert\">\n", + " \n", + "Schauen Sie sich den Aufgabentext genau an und formulieren Sie den Kopf der Funktion. Wie soll die Funktion heißen und welche Parameter müssen Sie der Funktion übergeben? Stellen Sie sicher, dass Sie die Definition mit `def` starten, die Parameter in Klammern setzten und am Ende der Zeile einen Doppelpunkt setzen. \n", + " \n", + " </div> \n", + "</details>\n", + "\n", + "<details>\n", + " <summary type=\"button\" class=\"btn btn-primary\">2. Hinweis</summary>\n", + " <div class=\"alert alert-info\" role=\"alert\">\n", + " \n", + "Wenn Sie 3 verschiedene Werte zurückgeben wollen, wie viele Bedingungen müssen Sie dann prüfen? Sie können `elif` verwenden um nach der ersten `if` Bedingung weitere einzufügen. \n", + " \n", + " </div> \n", + "</details>\n", + "\n", + "\n", + "<details>\n", + " <summary type=\"button\" class=\"btn btn-primary\">3. Hinweis</summary>\n", + " <div class=\"alert alert-info\" role=\"alert\">\n", + " \n", + "Die Prüfung braucht insgesamt 3 Zweige, die erste Bedingung ist: `if x>y:`. Wie müssen die anderen Bedingungen formuliert werden?\n", + " \n", + " </div> \n", + "</details>\n", + "\n", + "<details>\n", + " <summary type=\"button\" class=\"btn btn-primary\">4. Hinweis</summary>\n", + " <div class=\"alert alert-info\" role=\"alert\">\n", + " \n", + "Stellen Sie sicher, dass jede Eingabe zu einem Ergebnis führt. Prüfen Sie Ihre Funktion mit verschiedenen Werten für `x` und `y`.\n", + " \n", + " </div> \n", + "</details>\n", + "\n", + "<details>\n", + " <summary type=\"button\" class=\"btn btn-primary\">5. Hinweis</summary>\n", + " <div class=\"alert alert-info\" role=\"alert\">\n", + " \n", + "Falls die Rückgabe nicht funktioniert, prüfen Sie zunächst folgendes: Haben Sie alles richtig geschrieben? Haben Sie alle nötigen Doppelpunkte und Klammern gesetzt? Haben Sie alles korrekt eingerückt? Enthält jeder der Zweige eine `return` Anweisung?\n", + " \n", + " </div> \n", + "</details>" ] }, { @@ -206,7 +264,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "### 6.2 Schrittweise Entwicklung\n", + "## Schrittweise Entwicklung\n", "\n", "Wenn Sie größere Funktionen schreiben, kann es sein, dass Sie mehr Zeit mit der Fehlersuche (Debugging) verbringen.\n", "\n", @@ -344,7 +402,50 @@ "2. Nutzen Sie Variablen, um Zwischenwerte zu speichern, so dass Sie diese mit `print` ausgeben und überprüfen können.\n", "3. Sobald das Programm funktioniert, sollten Sie Teile des Hilfscodes entfernen und gegebenenfalls mehrere Anweisungen zu einer Verbundanweisung zusammenfügen, aber nur, wenn sich dadurch die Lesbarkeit des Programms nicht verschlechtert.\n", "\n", - "**Übung:** Nutzen Sie das Prinzip der schrittweisen Entwicklung, um eine Funktion `hypothenuse` zu schreiben, die die Länge der Hypothenuse eines rechtwinkligen Dreiecks zurückgibt, wenn die Längen der beiden Katheden gegeben sind. Dokumentieren Sie jeden Entwicklungsschritt hier im Notebook (d.h., erzeugen Sie eine Kopie der Funktion, bevor Sie den nächsten Entwicklungsschritt durchführen)." + "**Übung:** Nutzen Sie das Prinzip der schrittweisen Entwicklung, um eine Funktion `hypothenuse` zu schreiben, die die Länge der Hypothenuse eines [rechtwinkligen Dreiecks](https://de.wikipedia.org/wiki/Rechtwinkliges_Dreieck) zurückgibt, wenn die Längen der beiden Katheden gegeben sind. Dokumentieren Sie jeden Entwicklungsschritt hier im Notebook (d.h., erzeugen Sie eine Kopie der Funktion, bevor Sie den nächsten Entwicklungsschritt durchführen).\n", + "\n", + "<details>\n", + " <summary type=\"button\" class=\"btn btn-primary\">1. Hinweis</summary>\n", + " <div class=\"alert alert-info\" role=\"alert\">\n", + " \n", + " Wie immer fangen wir damit an, den Kopf der Funktion zu schreiben. Denken Sie darüber nach, welche Parameter laut Aufgabenstellung benötigt werden. Da wir eine Funktion mit Rückgabewert schreiben möchten, muss in Ihrem Code eine `return`-Anweisung auftauchen. Welchen Wert möchten Sie zurückgeben? Fügen Sie den entsprechenden Platzhalter ein. \n", + " </div> \n", + "</details> \n", + " \n", + " \n", + "<details>\n", + " <summary type=\"button\" class=\"btn btn-primary\">2. Hinweis</summary>\n", + " <div class=\"alert alert-info\" role=\"alert\">\n", + " \n", + "Wir können die Hypothenuse mit dem Satz des Pythagoras berechnen. Suchen Sie die Formel heraus und berechnen Sie das erste Zwischenergebnis.\n", + " \n", + " </div> \n", + "</details> \n", + " \n", + "<details>\n", + " <summary type=\"button\" class=\"btn btn-primary\">3. Hinweis</summary>\n", + " <div class=\"alert alert-info\" role=\"alert\">\n", + "\n", + "Berechnen Sie zuerst $c^2$, indem Sie $a^2$ und $b^2$ addieren und schreiben Sie eine `print`-Anweisung, die das Zwischenergebnis ausgibt. Führen Sie die Funktion mit Werten aus, bei denen Sie das Ergebnis überprüfen können. Wie funktionieren Potenzen nochmal in Python? Das haben Sie bereits gelernt. \n", + " \n", + " </div> \n", + "</details>\n", + "\n", + "<details>\n", + " <summary type=\"button\" class=\"btn btn-primary\">4. Hinweis</summary>\n", + " <div class=\"alert alert-info\" role=\"alert\">\n", + " \n", + "Die Funktion `math.sqrt()` berechnet die Quadratwurzel. Verwenden Sie diese Funktion, um die Wurzel von $c^2$ zu erhalten. Das Ergebnis ist die Länge der Seite c (der Hypothenuse). Vergessen Sie nicht, das `math` Modul zu importieren. Überprüfen Sie, ob Sie das richtige Ergebnis für c erhalten.\n", + " \n", + " </div> \n", + "</details>\n", + "<details>\n", + " <summary type=\"button\" class=\"btn btn-primary\">5. Hinweis</summary>\n", + " <div class=\"alert alert-info\" role=\"alert\">\n", + " \n", + "Jetzt sollte die Funktion korrekt funktionieren. Tauschen Sie den Rückgabewertplatzhalter mit dem korrekten Rückgabewert und entfernen Sie alle `print`-Anweisungen oder kommentieren Sie diese aus.\n", + " </div> \n", + "</details>" ] }, { @@ -353,7 +454,7 @@ "metadata": {}, "outputs": [], "source": [ - "# beginnen Sie hier mit der Entwicklung der Funktion" + "# Beginnen Sie hier mit der Entwicklung der Funktion." ] }, { @@ -369,7 +470,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "### 6.3 Komposition\n", + "## Komposition\n", "\n", "Wie Sie mittlerweile wissen sollten, können wir eine Funktion innerhalb einer anderen aufrufen. Als Beispiel werden wir eine Funktion schreiben, die zwei Punkte erwartet - den Mittelpunkt eines Kreises und einen Punkt auf dem Kreisumfang - und uns daraus die Fläche des Kreises berechnet.\n", "\n", @@ -448,7 +549,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "### 6.4 Boolesche Funktionen\n", + "## Boolesche Funktionen\n", "\n", "Funktionen können Boolesche Werte zurückliefern. Das ist praktkisch, um komplizierte Tests in einer Funktion zu verstecken. Zum Beispiel: " ] @@ -566,7 +667,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "### 6.5 Noch mehr Rekursion\n", + "## Noch mehr Rekursion\n", "\n", "Wir haben bisher nur eine kleine Teilmenge von Python kennengelernt aber vielleicht interessiert es Sie zu wissen, dass diese Teilmenge eine *komplette* Programmiersprache darstellt. Das heißt, alles was berechnet werden kann, können wir mit den bisher erlernten Anweisungen und Funktionen ausdrücken! Jedes jemals geschriebene Programm könnten wir umschreiben, so dass es nur mit den Sprachmerkmalen auskommt, die wir bis jetzt gelernt haben (gut, wir bräuchten noch ein paar Anweisungen, um Geräte wie z.B. die Maus, Festplatten, etc. zu kontrollieren).\n", "\n", @@ -576,6 +677,7 @@ "\n", "Um einen Idee davon zu bekommen, was wir mit den Werkzeugen, die wir bisher kennengelernt haben, schon erreichen können, wollen wir einige rekursiv definierte mathematische Funktionen implementieren. Eine rekursive Definition ist ähnlich einer [zirkulären Definition](https://en.wikipedia.org/wiki/Circular_definition) (*circular definition* - leider konnte ich dafür keinen deutschen Begriff finden) in dem Sinne, dass die Definition eine Referenz auf das, was definiert wird, enthält. Eine richtig zirkuläre Definition ist nicht sehr nützlich:\n", "\n", + "\n", "**vorpal:** Ein Adjektiv welches genutzt wird, um etwas zu beschreiben, was vorpal ist.\n", "\n", "Wenn Sie so eine Definition in einem Wörterbuch sehen, sind Sie vermutlich verärgert. Andererseits, wenn wir uns die Definition der Fakultätsfunktion heraussuchen (die mit dem Symbol ! bezeichnet wird), finden wir vermutlich etwas in der Art:\n", @@ -670,13 +772,13 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "### 6.6 Vertrauensvorschuss\n", + "## Vertrauensvorschuss\n", "\n", "Dem Kontrollfluss zu folgen ist eine Möglichkeit, Programme zu lesen, aber das kann ganz schön aufwendig sein. Eine Alternative ist, dem Code einen \"Vertrauensvorschuss\" zu geben. Wenn wir einen Funktionsaufruf sehen, können wir, statt dem Kontrollfluss zu folgen, einfach *annehmen*, dass die Funktion richtig arbeitet und das korrekte Ergebnis zurückliefert.\n", "\n", "Tatsächlich praktizieren wir das bisher schon mit den eingebauten Funktionen. Wenn wir `math.cos` oder `print` aufrufen, schauen wir uns den Rumpf dieser Funktionen nicht an. Wir gehen einfach davon aus, dass sie funktionieren, weil die Leute, die sie geschrieben haben, gute Programmierer/innen sind. (Zumindest nehmen wir das vielleicht an ;-) )\n", "\n", - "Das gleiche gilt, wenn wir eine unserer eigenen Funktionen aufrufen. Beispielsweise haben wir in [Abschnitt 6.4](#6.4-Boolesche-Funktionen) eine Funktion `ist_teilbar` geschrieben, die bestimmt, ob eine Zahl durch eine andere teilbar ist. Sobald wir uns davon überzeugt haben, dass diese Funktion korrekt arbeitet - durch Verstehen des Codes und Testen - können wir die Funktion nutzen, ohne uns den Rumpf noch einmal anzuschauen.\n", + "Das gleiche gilt, wenn wir eine unserer eigenen Funktionen aufrufen. Beispielsweise haben wir in [Abschnitt 6](#6-Boolesche-Funktionen) eine Funktion `ist_teilbar` geschrieben, die bestimmt, ob eine Zahl durch eine andere teilbar ist. Sobald wir uns davon überzeugt haben, dass diese Funktion korrekt arbeitet - durch Verstehen des Codes und Testen - können wir die Funktion nutzen, ohne uns den Rumpf noch einmal anzuschauen.\n", "\n", "Das gleiche gilt für rekursive Programme. Wenn wir auf einen rekursiven Funktionsaufruf treffen, können wir, anstatt dem Kontrollfluss zu folgen, annehmen, dass der rekursive Aufruf funktioniert (also den richtigen Wert zurückliefert) und uns selbst beispielsweise fragen \"Angenommen, ich kann die Fakultät von $n-1$ berechnen, kann ich dann die Fakultät von $n$ berechnen?\" Das funktioniert offensichtlich - indem wir mit $n$ multiplizieren.\n", "\n", @@ -687,7 +789,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "### 6.7 Ein weiteres Beispiel\n", + "## Ein weiteres Beispiel\n", "\n", "Neben der Fakultät ist ein weiteres übliches Beispiel für eine rekursiv definierte mathematische Funktion die [Fibonacci-Folge](https://de.wikipedia.org/wiki/Fibonacci-Folge):\n", "\n", @@ -734,7 +836,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "### 6.8 Typen prüfen\n", + "## Typen prüfen\n", "\n", "Was passiert, wenn wir `fakultaet` mit dem Wert `1.5` als Argument aufrufen?" ] @@ -822,14 +924,14 @@ "\n", "Dieses Programm demonstriert ein Entwurfsmuster, welches manchmal **Wächter** (*guardian*) genannt wird. Die ersten beiden Verzweigungen agieren als Wächter, die den darauffolgenden Code vor Werten beschützen, die Fehler hervorrufen könnten. Die Wächter ermöglichen uns, die Korrektheit des Codes zu beweisen.\n", "\n", - "Im [Abschnitt 11.4](seminar11.ipynb#reverse-lookup) werden wir eine flexiblere Alternative kennenlernen, um eine Fehlermeldung auszugeben: Ausnahmebehandlung." + "Im [Notebook 11 Abschnitt 4](seminar11.ipynb#reverse-lookup) werden wir eine flexiblere Alternative kennenlernen, um eine Fehlermeldung auszugeben: Ausnahmebehandlung." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "### 6.9 Debugging\n", + "## Debugging\n", "\n", "Ein großes Programm in kleinere Funktionen zu zerlegen erzeugt ganz natürliche Kontrollpunkte. Wenn eine Funktion nicht funktioniert, gibt es drei Möglichkeiten, die wir in Betracht ziehen sollten:\n", "\n", @@ -839,7 +941,7 @@ "\n", "Um die erste Möglichkeit auszuschließen, können wir `print`-Anweisungen am Anfang der Funktion einfügen und die Werte der Parameter (und vielleicht deren Typ) ausgeben. Oder wir können Code einfügen, der die Vorbedingungen explizit prüft (wie wir es bei `fakultaet` gerade eben gemacht haben).\n", "\n", - "Wenn die Parameter gut aussehen, dann können wir eine `print`-Anweisung vor jeder `return`-Anweisung einfügen und den Rückgabewert anzeigen. Falls möglich, prüfen wir den Wert von Hand. Wir können auch in Betracht ziehen, die Funktion mit Werten aufzurufen, die uns das überprüfen des Ergebnisses erleichtern (wie in [Abschnitt 6.2](#6.2-Schrittweise-Entwicklung)). \n", + "Wenn die Parameter gut aussehen, dann können wir eine `print`-Anweisung vor jeder `return`-Anweisung einfügen und den Rückgabewert anzeigen. Falls möglich, prüfen wir den Wert von Hand. Wir können auch in Betracht ziehen, die Funktion mit Werten aufzurufen, die uns das überprüfen des Ergebnisses erleichtern (wie in [Abschnitt 4](#4-Schrittweise-Entwicklung)). \n", "\n", "Wenn die Funktion richtig arbeitet (oder es zumindest danach aussieht), sollten wir uns die Stelle anschauen, an der die Funktion aufgerufen wird und sicherstellen, dass der Rückgabewert richtig bzw. überhaupt verwendet wird.\n", "\n", @@ -890,14 +992,14 @@ "\n", "\n", "\n", - "([Debugging](https://xkcd.com/1722/), Randall Munroe)" + "([Debugging](https://xkcd.com/1722/), Randall Munroe) [Erklärung des Comics](https://www.explainxkcd.com/wiki/index.php/1722:_Debugging) falls Sie mehr lernen wollen." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "### 6.10 Glossar\n", + "## Glossar\n", "\n", "Legen wir uns eine Liste mit den wichtigsten Begriffen an, die wir im Kapitel 6 gelernt haben:\n", "\n", @@ -914,9 +1016,9 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "### 6.11 Übung\n", + "## Übung\n", "\n", - "#### Aufgabe 1\n", + "### Aufgabe 1\n", "\n", "Zeichnen Sie (mit Bleistift und Papier) ein Stapeldiagramm für das folgende Programm wenn bei der Ausführung die Zeile `x = x + 1` in der Funktion `a` erreicht wurde. Was gibt das Programm aus?\n" ] @@ -950,7 +1052,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "#### Aufgabe 2\n", + "### Aufgabe 2\n", "\n", "Die [Ackermannfunktion](https://de.wikipedia.org/wiki/Ackermannfunktion), $A(m, n)$ ist folgendermaßen definiert:\n", "\n", @@ -963,7 +1065,96 @@ "\\end{cases}\n", "\\end{equation}\n", "\n", - "Schreiben Sie eine Funktion `ack` die die Ackermannfunktion berechnet. Berechnen Sie mit ihrer Funktion `ack(3,4)`, was 125 ergeben sollte. Was passiert für größere Werte von `m` und `n`? " + "Schreiben Sie eine Funktion `ack` die die Ackermannfunktion berechnet. Berechnen Sie mit ihrer Funktion `ack(3,4)`, was 125 ergeben sollte. Was passiert für größere Werte von `m` und `n`?\n", + "\n", + "In den folgenden Hinweisen werden wir die Funktion schrittweise entwickeln. Versuchen Sie, die Aufgabe in Partnerarbeit zu lösen und verwenden Sie so wenige Hinweise wie möglich.\n", + "\n", + "\n", + "<details>\n", + " <summary type=\"button\" class=\"btn btn-primary\">1. Hinweis</summary>\n", + " <div class=\"alert alert-info\" role=\"alert\">\n", + "\n", + "Schreiben Sie zuerst den Kopf der Funktion und überlegen Sie sich, wieviele Zweige Ihre Funktion benötigt. Schreiben Sie die entsprechende Anzahl an `if`-Bedingungen (bzw. `elif`-Bedingungen) und `return`-Anweisungen. Keine Sorge, Sie müssen sich an dieser Stelle noch keine Gedanken machen, wie die `if`-Bedingungen aussehen werden.\n", + " </div> \n", + "</details> \n", + " \n", + " \n", + "<details>\n", + " <summary type=\"button\" class=\"btn btn-primary\">2. Hinweis</summary>\n", + " <div class=\"alert alert-info\" role=\"alert\">\n", + "\n", + "Im nächsten Schritt werden wir die korrekten `if`-Bedinungen schreiben. Die geschweifte Klammer in der mathematischen Notation unterscheidet die unterschiedlichen Fälle, die bei bestimmten Bedingungen eintreten. Die Bedingungen stehen hinter dem Schlüsselwort \"falls\". Übersetzen Sie diese Formel in Python. Fügen Sie in jedem Zweig eine `print`-Anweisung ein, die den Zweig eindeutig identifiziert. Wir werden diese Hilfsanweisung später löschen. Testen Sie jetzt, ob Ihre Funktion für verschiedene Eingabewerte den korrekten Zweig ansteuert. Testen Sie auch die Möglichkeiten `m=0` und `n=0`. Im nächsten Hinweis (2.5) finden Sie die verschiedenen `if`-Bedingungen.\n", + " </div> \n", + "</details> \n", + " \n", + "\n", + "<details>\n", + " <summary type=\"button\" class=\"btn btn-primary\">2.5. Hinweis</summary>\n", + " <div class=\"alert alert-info\" role=\"alert\">\n", + "\n", + "Die `if`-Bedingungen sind: `if m==0:`für den Basisfall, `elif n==0 and m>0:` und `elif m>0 and n>0:`\n", + " \n", + " </div> \n", + "</details> \n", + " \n", + "<details>\n", + " <summary type=\"button\" class=\"btn btn-primary\">3. Hinweis</summary>\n", + " <div class=\"alert alert-info\" role=\"alert\">\n", + "\n", + "Im nächsten Schritt werden wir den korrekten Rückgabewert für den Basisfall eingeben. Anschließend testen Sie Ihre Funktion mit einem Aufruf des Basisfalls. Schauen Sie sich an, wie die Anweisung für die Berechnung des Basisfalls lauten muss. Sie können die korrekte Anweisung in Hinweis 3.5 nachlesen, wenn Sie sich unsicher sind oder Ihr Code nicht korrekt funktioniert.\n", + " \n", + " </div> \n", + "</details>\n", + "\n", + "<details>\n", + " <summary type=\"button\" class=\"btn btn-primary\">3.5. Hinweis</summary>\n", + " <div class=\"alert alert-info\" role=\"alert\">\n", + "\n", + "Die Rückgabe im Basisfall muss `return n+1` lauten. \n", + " \n", + " </div> \n", + "</details>\n", + "\n", + "<details>\n", + " <summary type=\"button\" class=\"btn btn-primary\">4. Hinweis</summary>\n", + " <div class=\"alert alert-info\" role=\"alert\">\n", + " \n", + "Anschließened beschäftigen wir mit der Bedingung `n==0`. Schauen Sie sich auch hier wieder die Formel an und versuchen Sie herauszufinden, welche Werte Sie beim rekursiven Aufruf übergeben müssen. In 4.5 können Sie den korrekten Aufruf nachlesen, wenn Sie dabei Hilfe brauchen. \n", + " \n", + " </div> \n", + "</details>\n", + "\n", + "<details>\n", + " <summary type=\"button\" class=\"btn btn-primary\">4.5. Hinweis</summary>\n", + " <div class=\"alert alert-info\" role=\"alert\">\n", + " \n", + "Die korrekte Anweisung lautet: `return ack (m-1,1)` \n", + " </div> \n", + "</details>\n", + "\n", + "<details>\n", + " <summary type=\"button\" class=\"btn btn-primary\">5. Hinweis</summary>\n", + " <div class=\"alert alert-info\" role=\"alert\">\n", + " \n", + "Der letzte Zweig wird aufgerufen, wenn sowohl m als auch n größer als Null sind. Schauen Sie sich genau an, wie die Funktion dabei definiert ist. Dabei fällt auf, dass die Funktion sich selbst im Funktionsaufruf rekursiv aufruft. Schreiben Sie diesen Funktionsaufruf und achten Sie auf die richtige Klammersetzung. Wenn Sie Hilfe brauchen, können Sie sich den korrekten Aufruf in 5.5 anschauen, versuchen Sie es aber zunächst einmal selber und testen Sie, ob bei Ihrem Aufruf das korrekte Ergebnis erscheint. \n", + " </div> \n", + "</details>\n", + "\n", + "<details>\n", + " <summary type=\"button\" class=\"btn btn-primary\">5.5 Hinweis</summary>\n", + " <div class=\"alert alert-info\" role=\"alert\">\n", + " \n", + "Die korrekte `return`-Anweisung lautet: `return ack (m-1, ack(m, n-1))` \n", + " </div> \n", + "</details>\n", + "\n", + "<details>\n", + " <summary type=\"button\" class=\"btn btn-primary\">5. Hinweis</summary>\n", + " <div class=\"alert alert-info\" role=\"alert\">\n", + " \n", + "Jetzt funktioniert Ihr Code wie gewünscht. An dieser Stelle ist es sinnvoll, Wächter und einen Doc-String einzubauen. Überlegen Sie dabei, für welche Zahlenbereiche die Funktion definiert ist und stellen Sie sicher, dass ihr Code das zu Beginn überprüft. Schreiben Sie auch einen Doc-String, der beschreibt, welche Eingaben die Funktion akzeptiert und was Sie als Ergebnis ausgibt.\n", + " </div> \n", + "</details>\n" ] }, { @@ -987,13 +1178,7 @@ "\n", "(Quelle: Jason Eppink, Flickr)\n", "\n", - "1. Wie muss die Grundstruktur der Funktion aussehen, was ist der Kopf, was sind die Parameter?\n", - "2. Wie ist die Funktion aufgebaut, wie viele Zweige hat sie? Schreiben Sie die leeren Zweige mit `return`-Anweisungen auf.\n", - "3. Was sind die Bedingungen für die einzelnen Zweige, übergeben Sie diese den verschiedenen `if`-Anweisungen. \n", - "4. Was wird im Basisfall $m=0$ zurückgegeben? Schreiben Sie die `return`-Anweisung für diesen Zweig.\n", - "5. Was passiert wenn n gleich null ist? Mit welchen Werten wird ack aufgerufen? Geben Sie den neuen Aufruf hinter der `return`-Anweisung ein.\n", - "6. Was passiert im letzten Zweig? Hier wird es ein wenig kompliziert, aber im Prinzip müssen sie den Ausdruck aus der Formel oben nur hinter der `return`-Anweisung abschreiben\n", - "7. Vielleicht wollen Sie jetzt noch Wächter einbauen oder eine `Doc-String` schreiben, die dem Nutzer klar sagt, für welche Zahlen `ack` definiert ist. \n" + "Es folgt der Code, der Mithilfe der Hinweise entwickelt wurde. Wenn Ihr Code etwas anders aussieht, ist das selbstverständlich okay, solange er das korrekte Ergebnis berechnet.\n" ] }, { @@ -1003,6 +1188,11 @@ "outputs": [], "source": [ "def ack(m,n):\n", + " \n", + " '''Die Funktion erwartet 2 positive ganze Zahlen m und n und berechnet daraus die Ackermannfunktion.\n", + " Werden ungültige Werte eingegeben, ist der Rückgabewert None und ein Fehler wird ausgegeben, anderfalls wird\n", + " das Ergebnis zurückgegeben.'''\n", + " \n", " if m<0 or n<0:\n", " print(\"Funktion nicht definiert\")\n", " return None\n", @@ -1024,7 +1214,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "#### Aufgabe 3\n", + "### Aufgabe 3\n", "\n", "Ein [Palindrom](https://de.wikipedia.org/wiki/Palindrom) ist ein Wort, welches vorwärts und rückwärts gelesen gleich ist. Beispielsweise \"neben\" oder \"hangnah\" (wenn wir Großschreibung ignorieren, gibt es auch Substantive, z.B. \"Reliefpfeiler\" oder \"Anna\"). Rekursiv definiert, ist ein Wort ein Palindrom, wenn der erste und letzte Buchstabe identisch sind und der Mittelteil ein Palindrom ist.\n", "\n", @@ -1051,10 +1241,9 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Wir werden in [Kapitel 8](seminar08.ipynb) sehen, wie sie funktionieren.\n", + "Wir werden in [Seminar 8](seminar08.ipynb) sehen, wie sie funktionieren.\n", "\n", - "1. Testen Sie diese Funktionen. Was passiert, wenn Sie `middle` mit einer Zeichenkette mit nur zwei Zeichen aufrufen? Oder mit nur einem Zeichen? Was passiert mit der leeren Zeichenkette, geschrieben '', die keine Zeichen enthält?\n", - "2. Schreiben Sie eine Funktion `ist_palindrom`, die eine Zeichenkette als Argument erwartet und `True` zurückliefert, wenn die Zeichenkette ein Palindrom ist und ansonsten `False`. (Erinnern Sie sich daran, dass Sie mit der eingebauten Funktion `len` die Länge einer Zeichenkette ermitteln können.)\n" + "1. Testen Sie diese Funktionen. Was passiert, wenn Sie `middle` mit einer Zeichenkette mit nur zwei Zeichen aufrufen? Oder mit nur einem Zeichen? Was passiert mit der leeren Zeichenkette, geschrieben `''`, die keine Zeichen enthält?" ] }, { @@ -1066,6 +1255,94 @@ "# Testen Sie hier die Funktionen first, last und middle " ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "2. Schreiben Sie eine Funktion `ist_palindrom`, die eine Zeichenkette als Argument erwartet und `True` zurückliefert, wenn die Zeichenkette ein Palindrom ist und ansonsten `False`. (Erinnern Sie sich daran, dass Sie mit der eingebauten Funktion `len` die Länge einer Zeichenkette ermitteln können.) \n", + "\n", + "Wie gehabt, folgen jetzt einige Hinweise, versuchen Sie zunächst die Aufgaben in Partnerarbeit zu lösen und verwenden Sie so wenige von den Hinweisen wie möglich, das ist die beste Übung:\n", + "\n", + "\n", + "<details>\n", + " <summary type=\"button\" class=\"btn btn-primary\">1. Hinweis</summary>\n", + " <div class=\"alert alert-info\" role=\"alert\">\n", + "\n", + "Wir werden uns die Funktionen `first, last` und `middle` zu nutze machen um die Funktion zu schreiben.\n", + " \n", + " </div> \n", + "</details> \n", + " \n", + " \n", + "<details>\n", + " <summary type=\"button\" class=\"btn btn-primary\">2. Hinweis</summary>\n", + " <div class=\"alert alert-info\" role=\"alert\">\n", + "\n", + "Schreiben Sie zunächst den Kopf der Funktion. welche Zustände muss die Funktion zurückgeben? Schreiben Sie auch die entsprechenden Rückgabeeingaben, machen Sie sich (noch) keinen Kopf darüber, wie sie entscheiden, welcher Wert zurückgegeben wird. Wenn Sie die Funktion jetzt testen wird immer der erste Rückgabewert, den Sie eingegeben haben zurückgegeben. \n", + " </div> \n", + "</details> \n", + " \n", + " \n", + " \n", + "<details>\n", + " <summary type=\"button\" class=\"btn btn-primary\">3. Hinweis</summary>\n", + " <div class=\"alert alert-info\" role=\"alert\">\n", + "\n", + "Wenn wir automatisch ein Palindrom testen wollen, vergleichen wir immer den ersten mit dem letzen Buchstaben, diese müssen gleich sein. Das bedeutet, das der hier geschriebene Test bei Palindromen mit unterschiedlich gesetzen Leerzeichen kein Palindrom findet. \n", + " </div> \n", + "</details>\n", + "\n", + "<details>\n", + " <summary type=\"button\" class=\"btn btn-primary\">4. Hinweis</summary>\n", + " <div class=\"alert alert-info\" role=\"alert\">\n", + "\n", + " Wir werden die Funktion rekursiv implementieren, wir müssen uns also den Basisfall eines Palindroms überlegen. Wie könnte dieser Basisfall aussehen? \n", + " </div> \n", + "</details>\n", + "\n", + "<details>\n", + " <summary type=\"button\" class=\"btn btn-primary\">5. Hinweis</summary>\n", + " <div class=\"alert alert-info\" role=\"alert\">\n", + " \n", + "Der Basisfall für ein Palindrom ist eine Zeichenkette mit nur einem oder keinem Zeichen ist immer ein Palindrom. Für diesen Wert gibt die Funktion den Wert `True` zurück. Verwenden Sie die Funktion `len` um die Länge der Zeichenkette zu testen und schreiben Sie die entsprechende `if`-Bedingung.\n", + " \n", + " </div> \n", + "</details>\n", + "\n", + "<details>\n", + " <summary type=\"button\" class=\"btn btn-primary\">6. Hinweis</summary>\n", + " <div class=\"alert alert-info\" role=\"alert\">\n", + " \n", + "Was muss die Abbruchbedingung sein, wenn die Funktion `False` zurückgeben soll?\n", + " </div> \n", + "</details>\n", + "\n", + "<details>\n", + " <summary type=\"button\" class=\"btn btn-primary\">7. Hinweis</summary>\n", + " <div class=\"alert alert-info\" role=\"alert\">\n", + "\n", + "Verwenden Sie einen Test auf Ungleichheit. Da in einem Palindrom der erste und letzte Buchstabe gleich sein müssen, geben Sie `False` zurück, wenn der Rückgabewert von `first` und `last` nicht gleich ist. \n", + " \n", + " </div> \n", + "</details>\n", + "\n", + "<details>\n", + " <summary type=\"button\" class=\"btn btn-primary\">8. Hinweis</summary>\n", + " <div class=\"alert alert-info\" role=\"alert\">\n", + " \n", + "Abschließend müssen die noch den Rekursiven Funktionsaufruf schreiben. Überlegen Sie, wie Sie die Funktion mit dem zweiten bis vorletzten Buchstaben aufrufen können. \n", + " \n", + " </div> \n", + "</details>\n", + "<details>\n", + " <summary type=\"button\" class=\"btn btn-primary\">9. Hinweis</summary>\n", + " <div class=\"alert alert-info\" role=\"alert\">\n", + " \n", + "Der rekursive Funktionsaufruf muss `ist_palindrom(middle(s))` lauten\n", + " </div> \n", + "</details>\n" + ] + }, { "cell_type": "code", "execution_count": null, @@ -1082,17 +1359,7 @@ "\n", "<a data-flickr-embed=\"true\" href=\"https://www.flickr.com/photos/jasoneppink/4964471335\" title=\"Spoiler Alert\"><img src=\"https://farm5.staticflickr.com/4110/4964471335_1f86a923f3_n.jpg\" width=\"320\" height=\"213\" alt=\"Spoiler Alert\"></a><script async src=\"//embedr.flickr.com/assets/client-code.js\" charset=\"utf-8\"></script>\n", "\n", - "(Quelle: Jason Eppink, Flickr)\n", - "\n", - "1. Verwenden Sie die Funktionen first, last und middle.\n", - "2. Überlegen Sie wann ein Palindrom ein Palindrom ist und wie sie das einfach testen können.\n", - "3. Wenn Sie von außen nach innen immer Zeichenpaare vergleichen und diese Stimmen miteinander überein, dann haben Sie ein Palindrom.\n", - "4. Wir wollen das ganze rekursiv implementieren, was ist dabei der Basisfall? \n", - "5. Eine Zeichenkette mit einem oder keinem Zeichen ist immer ein Palindrom und damit der Basisfall und einer der Zweige in denen die Funktion abbricht und einen Wert- nämlich `True`zurückgibt. Wir können die Länge der Zeichenkette mit der `len` Funktion testen.\n", - "6. Wann sonst bricht die Funktion ab, gibt aber `False` zurück?\n", - "7. Wenn das erste und letzte Zeichen, der momentanen Zeichenkette nicht übereinstimmen\n", - "8. Wir rufen `ist_palindrom` rekursiv mit `middle` auf um die Zeichenkette ohne den ersten und letzten Buchstaben zu erhalten, damit wird die Zeichenkette immer kürzer und bricht entweder ab, weil sie zu kurz ist- dann ist es ein Palindrom- oder weil das erste und letzte Zeichen nicht übereinstimmen - dann ist es kein Palindrom \n", - "\n" + "(Quelle: Jason Eppink, Flickr)\n" ] }, { @@ -1115,13 +1382,81 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "\n", + " \n", "\n", "([Farrar, Straus and Giroux](http://time.com/3771063/mark-saltveit-world-palindrome-championship/))\n", "\n", - "#### Aufgabe 4\n", + "### Aufgabe 4\n", + "\n", + "Eine Zahl $a$ ist eine Potenz von $b$, wenn $a$ durch $b$ teilbar ist und $a/b$ eine Potenz von $b$ ist. (Beispielsweise ist 27 eine Potenz von 3, denn 27 ist durch 3 teilbar und 9 ist eine Potenz von 3.) Schreiben Sie eine Funktion `ist_potenz` die Parameter `a` und `b` erwartet und `True` zurückgibt, wenn `a` eine Potenz von `b` ist (ansonsten `False`). \n", + "<details>\n", + " <summary type=\"button\" class=\"btn btn-info\">Hinweis</summary>\n", + " <div class=\"alert alert-info\" role=\"alert\">\n", + "\n", + "Überlegen Sie sich, was der Basisfall ist und wie Sie diesen behandeln.\n", + " \n", + " </div> \n", + "</details>\n", + "\n", + "Es folgen wie immer Hinweise zum Lösen der Aufgabe. Versuchen Sie zunächst, die Aufgabe in Partnerarbeit zu lösen, so lernen Sie immer am besten. \n", + "\n", + "\n", + "<details>\n", + " <summary type=\"button\" class=\"btn btn-primary\">1. Hinweis</summary>\n", + " <div class=\"alert alert-info\" role=\"alert\">\n", + "\n", + "Schreiben Sie zunächst wie üblich den Kopf der Funktion inklusive der Parameter und schreiben Sie auch bereits die `return`-Anweisungen für die möglichen Ergebnisse der Funktion. Wir kümmern uns anschließend darum, wie diese Werte jeweils erreicht werden.\n", + " \n", + " </div> \n", + "</details> \n", + " \n", + " \n", + "<details>\n", + " <summary type=\"button\" class=\"btn btn-primary\">2. Hinweis</summary>\n", + " <div class=\"alert alert-info\" role=\"alert\">\n", + "\n", + "Wir müssen uns die beiden Basisfälle überlegen. Diese sind die Fälle, bei denen die Funktion `True` zurückgibt. Die Basisfälle sind `a==b` und `b==1`. Machen Sie sich klar, warum diese Fälle die Basisfälle sind.\n", + " </div> \n", + "</details> \n", + " \n", + " \n", + " \n", + "<details>\n", + " <summary type=\"button\" class=\"btn btn-primary\">3. Hinweis</summary>\n", + " <div class=\"alert alert-info\" role=\"alert\">\n", + "\n", + "Überlegen Sie nun, wie Sie testen können, ob eine Zahl die Potenz einer anderen Zahl ist. Verwenden Sie den `modulo` Operator.\n", + "\n", + " \n", + " </div> \n", + "</details>\n", + "\n", + "<details>\n", + " <summary type=\"button\" class=\"btn btn-primary\">4. Hinweis</summary>\n", + " <div class=\"alert alert-info\" role=\"alert\">\n", "\n", - "Eine Zahl $a$ ist eine Potenz von $b$, wenn $a$ durch $b$ teilbar ist und $a/b$ eine Potenz von $b$ ist. (Beispielsweise ist 27 eine Potenz von 3, denn 27 ist durch 3 teilbar und 9 ist eine Potenz von 3.) Schreiben Sie eine Funktion `ist_potenz` die Parameter `a` und `b` erwartet und `True` zurückgibt, wenn `a` eine Potenz von `b` ist (ansonsten `False`). Hinweis: Überlegen Sie sich, was der Basisfall ist und wie Sie diesen behandeln." + "Damit eine Zahl eine Potenz einer anderen Zahl sein kann, muss Sie restlos durch die andere Zahl teilbar sein. Implementieren Sie die Verzweigung und schreiben Sie den Zweig, der `False` zurück gibt. Das ist der Zweig, der ausgeführt wird, wenn alle anderen Bedingungen nicht erfüllt werden.\n", + "\n", + " </div> \n", + "</details>\n", + "\n", + "<details>\n", + " <summary type=\"button\" class=\"btn btn-primary\">5. Hinweis</summary>\n", + " <div class=\"alert alert-info\" role=\"alert\">\n", + " \n", + "Wenn sich $a$ restlos durch $b$ teilen lässt, muss sich in diesem Zweig die Funktion mit einer `return`-Anweisung rekursiv aufrufen. Überlegen Sie sich, welche Werte für $a$ und $b$ übergeben werden müssen.\n", + " \n", + " </div> \n", + "</details>\n", + "\n", + "<details>\n", + " <summary type=\"button\" class=\"btn btn-primary\">6. Hinweis</summary>\n", + " <div class=\"alert alert-info\" role=\"alert\">\n", + " \n", + "Für $a$ müssen Sie $a/b$ übergeben, da Sie ja prüfen müssen, ob $a/b$ auch restlos durch $b$ teilbar ist. Für $b$ müssen Sie daher wieder $b$ übergeben.\n", + "\n", + " </div> \n", + "</details>" ] }, { @@ -1140,17 +1475,7 @@ "\n", "<a data-flickr-embed=\"true\" href=\"https://www.flickr.com/photos/jasoneppink/4964471335\" title=\"Spoiler Alert\"><img src=\"https://farm5.staticflickr.com/4110/4964471335_1f86a923f3_n.jpg\" width=\"320\" height=\"213\" alt=\"Spoiler Alert\"></a><script async src=\"//embedr.flickr.com/assets/client-code.js\" charset=\"utf-8\"></script>\n", "\n", - "(Quelle: Jason Eppink, Flickr)\n", - "\n", - "1. Schreiben Sie erst den Kopf der Funktion inklusive Parametern\n", - "2. Bevor Sie den Rest der Funktion implementieren, müssen Sie sich den Basisfall überlegen.\n", - "3. Der Basisfall ist b=1 -- und darausfolgend auch a=b\n", - "4. Was ist die Ausgabe, wenn der Basisfall erreicht wird?\n", - "5. Was müssen Sie überprüfen um herauszufinden ob $a$ eine Potenz von $b$ ist?\n", - "6. Wenn $a$ nicht restlos durch $b$ teilbar ist, kann $a$ keine Potenz von $b$ sein. Implementieren Sie diese Aussage\n", - "7. Wie und wo muss die Funktion sich selber aufrufen?\n", - "8. Die Funktion muss sich !mit `return`-Anweisung! selber aufrufen wenn a%b==0 gilt\n", - "9. Dabei wird $a/b$ für $a$ übergeben." + "(Quelle: Jason Eppink, Flickr)" ] }, { @@ -1173,13 +1498,55 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "#### Aufgabe 5\n", + "### Aufgabe 5\n", "\n", "Der [größte gemeinsame Teiler](https://de.wikipedia.org/wiki/Gr%C3%B6%C3%9Fter_gemeinsamer_Teiler) (ggT) von $a$ und $b$ ist die größte Zahl die beide Zahlen ($a$ und $b$) ohne Rest teilt.\n", "\n", "Eine Möglichkeit den ggT zweier Zahlen zu berechnen, beruht auf der Beobachtung, dass, wenn $r$ der Rest der Division von $a$ durch $b$ ist, dann $ggT(a,b) = ggT(b,r)$ gilt. Als Basisfall können wir $ggT(a,0)=a$ nutzen.\n", "\n", - "Schreiben Sie eine Funktion `ggt`, die zwei Parameter `a` und `b` erwartet und den größten gemeinsamen Teiler zurückgibt." + "Schreiben Sie eine Funktion `ggt`, die zwei Parameter `a` und `b` erwartet und den größten gemeinsamen Teiler zurückgibt. Bedenken Sie, dass wir für die Berechnung anders vorgehen als bei der Verwendung des Euklidischen Algorithmus. Nutzen Sie die Hinweise, wenn Sie Hilfe benötigen. \n", + "\n", + "\n", + "\n", + "<details>\n", + " <summary type=\"button\" class=\"btn btn-primary\">1. Hinweis</summary>\n", + " <div class=\"alert alert-info\" role=\"alert\">\n", + "\n", + "Schreiben Sie zunächst den Kopf der Funktion und die `return`-Anweisung. Lassen Sie die Funktion zuerst einen Platzhalter zurückgeben, wir werden uns in späteren Schritten damit beschäftigen, das korrekte Ergebnis auszugeben.\n", + " \n", + " </div> \n", + "</details> \n", + " \n", + " \n", + "<details>\n", + " <summary type=\"button\" class=\"btn btn-primary\">2. Hinweis</summary>\n", + " <div class=\"alert alert-info\" role=\"alert\">\n", + "\n", + "Wie lautet der Basisfall? Schreiben Sie die `if`-Anweisung, die prüft, ob der Basisfall wahr ist. Passen Sie die `return`-Anweisung so an, dass das für den Basisfall passende Ergebnis zurückgegeben wird. Testen Sie, ob dies funktioniert, indem Sie die Funktion mit dem Basisfall aufrufen und sich das Ergebnis anschauen.\n", + "\n", + " </div> \n", + "</details> \n", + " \n", + " \n", + " \n", + "<details>\n", + " <summary type=\"button\" class=\"btn btn-primary\">3. Hinweis</summary>\n", + " <div class=\"alert alert-info\" role=\"alert\">\n", + "\n", + "Da wir eine rekursive Funktion implementieren wollen, müssen wir uns überlegen, wie wir den rekursiven Aufruf gestalten können. Schauen Sie sich die Aufgabenstellung an und überlegen Sie, welche Argumente Sie dem Aufruf übergeben. \n", + "\n", + " </div> \n", + "</details>\n", + "\n", + "<details>\n", + " <summary type=\"button\" class=\"btn btn-primary\">4. Hinweis</summary>\n", + " <div class=\"alert alert-info\" role=\"alert\">\n", + "\n", + "\n", + "Wir wollen für b den Rest aus der Divison von a und b übergeben. Berechnen Sie den Wert. Sie können direkt die Berechnung übergeben oder das Ergebnis in einer Variablen speichern und diese Variable übergeben. Für a übergeben wir b aus diesem Funktionsaufruf.\n", + " \n", + " </div> \n", + "</details>" ] }, { @@ -1195,16 +1562,9 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "\n", "<a data-flickr-embed=\"true\" href=\"https://www.flickr.com/photos/jasoneppink/4964471335\" title=\"Spoiler Alert\"><img src=\"https://farm5.staticflickr.com/4110/4964471335_1f86a923f3_n.jpg\" width=\"320\" height=\"213\" alt=\"Spoiler Alert\"></a><script async src=\"//embedr.flickr.com/assets/client-code.js\" charset=\"utf-8\"></script>\n", "\n", - "(Quelle: Jason Eppink, Flickr)\n", - "\n", - "1. Wie muss der Kopf der Funktion aussehen, welche Parameter werden übergeben?\n", - "2. Was müssen wir für den Basisfall überprüfen? Schreiben Sie die passende `if`-Bedingung\n", - "3. Was wird im Basisfall zurück gegeben? Schreiben Sie die `return`-Anweisung\n", - "4. Wie können Sie den Rest der Division von $a/b$ berechnen?\n", - "5. Rufen Sie die Funktion rekursiv auf, übergeben Sie dabei die passenden Varibablen und vergessen Sie die `return`-Anweisung dabei nicht." + "(Quelle: Jason Eppink, Flickr)" ] }, { @@ -1220,8 +1580,7 @@ " return ggt(b,r)\n", " \n", " \n", - "ggt (175,25)\n", - " \n" + "ggt (175,25)" ] }, { -- GitLab