Skip to content
Snippets Groups Projects
seminar03.ipynb 47.9 KiB
Newer Older
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "![Silly Walk](https://media.giphy.com/media/RzKHvdYC3uds4/giphy.gif)\n",
    "\n",
    "Bitte hier nur weiterlesen, wenn Sie Hilfe benötigen. Versuchen Sie es aber vorher unbedingt erst einmal zu zweit. Das Erfolgserlebnis, die Lösung selber gefunden zu haben, lohnt die Mühe. Und nur so lernen Sie etwas dazu.\n",
    "\n",
    ".\n",
    "\n",
    ".\n",
    "\n",
    ".\n",
    "\n",
    "spoiler\n",
    "\n",
    ".\n",
    "\n",
    ".\n",
    "\n",
    "So sollte der Kopf Ihrer Funktion ausehen (alle notwendigen Informationen dazu stehen im ersten Teil des ersten Satzes der Aufgabe):\n",
    "\n",
    "```python\n",
    "def right_justify(s):\n",
    "```\n",
    "\n",
    ".\n",
    "\n",
    ".\n",
    "\n",
    "Jetzt ein paar Tipps, wie Sie das Problem angehen könnten. Lesen Sie nicht alles auf einmal durch, sondern nur jeweils einen Tipp und versuchen Sie dann erstmal wieder, das Problem zu zweit zu lösen: \n",
    "1. Wieviele Leerzeichen benötigen Sie, um 'monty' rechtsbündig auszugeben? (Falls Sie die Frage nicht beantworten können, lesen Sie sich die Aufgabe nochmal genau durch.)\n",
    "2. Wie können Sie diese Anzahl berechnen? Welche Werte benötigen Sie dafür?\n",
    "3. Das alles können Sie jetzt schon in Ihre Funktion packen.\n",
    "4. Funktioniert das was Sie geschrieben haben auch für andere Werte als 'monty', insbesondere für den Parameter `s` der Funktion?\n",
    "5. Wenn Sie jetzt ausgerechnet haben, wie viele Leerzeichen Sie benötigen, müssen Sie diese noch erzeugen.\n",
    "6. Dafür können Sie den Operator  `*` für Zeichenkettenwiederholung verwenden. \n",
    "7. `' ' * 10` ergibt z.B. 10 Leerzeichen\n",
    "8. Jetzt haben Sie genug Leerzeichen ... aber die müssen ja noch vor die Zeichenkette `s`.\n",
    "9. Sie können Zeichenketten mittels `+` verknüpfen.\n",
    "10. `' ' * 65 + 'monty'` wäre die Zeichenkette, die Sie für 'monty' bräuchten ... aber wie können Sie das allgemein formulieren, so dass es auch für den Parameter `s` (mit beliebiger Länge!) funktioniert?\n",
    "11. Schließlich müssen Sie das Ergebnis noch ausgeben ... nungut, dafür gibt's die `print`-Funktion.\n",
    "12. Alles geschafft? Geben Sie hier ihre fertige Funktion ein:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "def right_justify(s):\n",
    "    # Anzahl Leerzeichen berechnen\n",
    "    anzahl_leerzeichen = \n",
    "    # Zeichenkette erzeugen\n",
    "    ergebnis =\n",
    "    # und ausgeben\n",
    "    print()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Macht ihre Funktion auch wirklich, was sie soll? Ein paar Ideen zum Testen:\n",
    "- Zählen Sie die Leerzeichen bis zum Wort. Das ist schwierig, da Leerzeichen schwer zu sehen sind. Also tauschen Sie doch das Leerzeichen durch ein anderes Zeichen, z.B. einen Punkt aus.\n",
    "- Jetzt sind es bei kurzen Wörtern recht viele Punkte ... als Abhilfe könnten Sie statt in der 70. Spalte alles rechtsbündig in der 10. Spalte ausgeben, also 70 zu 10 ändern. Dann lässt es sich leichter zählen.\n",
    "\n",
    "Wenn Ihre Funktion so richtig funktioniert, dann sollte sie auch mit Leerzeichen und Spalte 70 korrekt funktionieren. Das ist auch Debugging und Testen - es ist wichtig, um Fehler zu finden und hilft Ihnen, mit Ihrem Programm vertrauter zu werden.\n",
    "\n",
    "Abschlussfrage: was passiert, wenn Sie die Funktion mit einer Zeichenkette aufrufen, die länger als 70 Zeichen ist? Probieren Sie es aus:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "right_justify('Abschlussfrage: was passiert, wenn Sie die Funktion mit einer Zeichenkette aufrufen, die länger als 70 Zeichen ist?')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Aufgabe 1+\n",
    "Testen Sie folgendermaßen, ob Sie verstanden haben, wie die Funktion `right_justify` funktioniert: Schreiben Sie eine Funktion `center`, die eine als Argument übergebene Zeichenkette zentriert ausgibt (bei einer angenommen maximalen Spaltenbreite von 70, wie gerade eben):"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Tipp zur Lösung: Mit dem Operator `//` können wir zwei ganze Zahlen so teilen, dass eine ganze Zahl (*integer*) herauskommt. Während `7 / 2` die Fließkommazahl `3.5` ergibt, erhalten wir bei `7 // 2` die ganze Zahl `3` (es wird stets abgerundet).\n",
    "\n",
    "Ein Aufruf der Funktion mit den folgenden Argumenten:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "center('Diese Wörter')\n",
    "center('stehen')\n",
    "center('in')\n",
    "center('der Mitte')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "sollte folgendes Ergebnis liefern:\n",
    "\n",
    "```\n",
    "                             Diese Wörter\n",
    "                                stehen\n",
    "                                  in\n",
    "                              der Mitte\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Aufgabe 2\n",
    "\n",
    "Ein Funktionsobjekt ist ein Wert, den wir einer Variablen zuweisen können oder auch einer Funktion als Argument übergeben können. Zum Beispiel ist `do_twice` eine Funktion, die ein Funktionsobjekt als Argument erwartet und die Funktion dann zweimal aufruft:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "def do_twice(f):\n",
    "    f()\n",
    "    f()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Im Folgenden ein Beispiel, in dem die Funktion `do_twice` genutzt wird, um die Funktion `print_spam` zweimal aufzurufen:\n",
    "\n",
    "```python\n",
    "def print_spam():\n",
    "    print('spam')\n",
    "\n",
    "do_twice(print_spam)\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "(Tipp: Mit der Tastenkombination `SHIFT STRG -` können wir einen Block teilen - also `SHIFT` und `STRG` gleichzeitig gedrückt halten und dann die Minustaste drücken. So können Sie Ihren Code direkt hinter jeder der folgenden Teilaufgaben einfügen.) "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "1. Geben Sie dieses Beispiel in einen Code-Block ein und testen Sie es.\n",
    "2. Ändern Sie `do_twice`, so dass \n",
    "  - es zwei Argumente erwartet: ein Funktionsobjekt und einen Wert und\n",
    "  - die übergebene Funktion zweimal aufruft und ihr den Wert als Argument übergibt.\n",
    "3. Rufen Sie mit der geänderten Funktion `do_twice` die Funktion `print_twice` (die wir weiter vorne definiert hatten) auf und übergeben Sie ein Wort Ihrer Wahl als Argument.\n",
    "4. Definieren Sie eine Funktion `do_four`, die ein Funktionsobjekt und einen Wert erwartet und die übergebene Funktion viermal aufruft und ihr dabei den Wert als Parameter übergibt. Die Funktion `do_four` sollte dabei aus nur zwei Zeilen im Rumpf bestehen, nicht aus vier!\n",
    "\n",
    ".\n",
    "\n",
    ".\n",
    "\n",
    "Die Lösung finden Sie hier: http://thinkpython2.com/code/do_four.py"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Aufgabe 3\n",
    "\n",
    "Lösen Sie die folgende Aufgabe: http://greenteapress.com/thinkpython2/html/thinkpython2004.html#hevea_default261"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Bonusaufgabe\n",
    "\n",
    "Erinnern Sie sich noch an die folgende Aufgabe?\n",
    "\n",
    "1. Finden Sie einen Algorithmus zur Lösung des folgenden Problems:\n",
    "   *Gegeben sei eine positive ganze Zahl `n`. Finden Sie eine Liste\n",
    "   von positiven ganzen Zahlen, so dass das Produkt der Zahlen am\n",
    "   größten unter allen positiven ganzen Zahlen ist, deren Summe\n",
    "   gleich `n` ist.*\n",
    "\n",
    "   Zum Beispiel: \n",
    "   - Für `n = 4` ist die gesuchte Liste `(2,2)`, denn `2 * 2` ist größer als `1 * 1 * 1 * 1`, `2 * 1 * 1` und `3 * 1`.\n",
    "   - Für `n = 5` ist die gesuchte Liste `(2,3)`.\n",
    "\n",
    "2. Wie lautet die Liste für `n = 2001`?\n",
    "3. Erklären Sie, wie Sie \"einen Fuß in die Tür bekommen\" haben.\n",
    "\n",
    "Versuchen Sie es zunächst ohne Hilfe. Wie kann Ihnen Python dabei helfen? \n",
    "\n",
    ".\n",
    "\n",
    ".\n",
    "\n",
    ".\n",
    "\n",
    "Mein \"Fuß in der Tür\" war, dass ich von Hand eine Tabelle mit den Ergebnissen für die ersten `n` Zahlen gebaut habe:\n",
    "\n",
    "|  n | Liste     | Produkt |\n",
    "|----|-----------|---------|\n",
    "|  2 | 1 1       |       1 | \n",
    "|  3 | 1 2       |       3 | \n",
    "|  4 | 2 2       |       4 |\n",
    "|  5 | 2 3       |       6 |"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Ergänzen Sie diese Tabelle von Hand. Dabei kann Ihnen eine Funktion helfen, die für eine gegebene Liste an Zahlen das Produkt und die Summe berechnet:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "def prodsum(zahlen):\n",
    "    prod = 1\n",
    "    summ = 0\n",
    "    for zahl in zahlen:\n",
    "        prod = prod * zahl\n",
    "        summ = summ + zahl\n",
    "    print(\"Produkt =\", prod, \"Summe =\", summ)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Eine Liste von Zahlen können wir erzeugen, indem wir die Zahlen durch Komma getrennt zwischen zwei Klammern schreiben:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "(2,3)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Wir können also `prodsum` so aufrufen:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "prodsum((2,3))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Testen Sie für jedes `n` mehrere Listen, bis Sie sich jeweils sicher sind, die mit dem größten Produkt gefunden zu haben.\n",
    "\n",
    ".\n",
    "\n",
    ".\n",
    "\n",
    ".\n",
    "\n",
    "Ich habe mit Hilfe der Funktion die Tabelle bis `n=15` ergänzt bis ich mir sicher war, dass ich das Prinzip verstanden hatte. \n",
    "\n",
    ".\n",
    "\n",
    ".\n",
    "\n",
    ".\n",
    "\n",
    "Sehen Sie jetzt ein Muster in der Tabelle? Die Produkte bestehen nur aus 3en und ggf. noch 2en oder 4en. Genauer:\n",
    "\n",
    "Beobachtung (\"Fuß in der Tür\"): \n",
    "- Ein Produkt aus möglichst vielen 3en ergibt das beste Ergebnis.\n",
    "- Falls es nicht ganz aufgeht, mit 2 oder 4 auffüllen.\n",
    "\n",
    "Erklärung (warum 3en?):\n",
    "- Ob wir eine 4 oder zwei 2en nehmen, ist egal, da `2+2 = 4 = 2*2`.\n",
    "- Da `2+3=5` aber `2*3=6`, lohnt es sich nicht, größere Zahlen zu nehmen\n",
    "  (ebenso: `3+3=6` aber `3*3=9`) - das Produkt der kleinen Zahlen ist stets größer als ihre Summe\n",
    "\n",
    "Algorithmus:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "def produkt_summe(n):\n",
    "    \"\"\"Berechnet für gegebenes n>2 das Produkt derjenigen Liste von\n",
    "    Zahlen, deren Summe n ergibt und gleichzeitig die größte Liste mit\n",
    "    dieser Eigenschaft ist.\n",
    "    \n",
    "    Vorgehen: wiederholt 3 von n abziehen, bis der Rest kleiner oder \n",
    "    gleich 4 ist. (letzter Schritt klappt, weil 2+2=4=2*2)\n",
    "\n",
    "    \"\"\"\n",
    "    rest = n\n",
    "    prod = 1\n",
    "    zahlen = []\n",
    "    while rest > 4:\n",
    "        rest = rest - 3\n",
    "        prod = prod * 3\n",
    "        zahlen.append(3)\n",
    "    prod = prod * rest\n",
    "    zahlen.append(rest)\n",
    "    \n",
    "    print(\"*\".join([str(z) for z in zahlen]), \"=\", prod)\n",
    "    print(\"+\".join([str(z) for z in zahlen]), \"=\", sum(zahlen))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Testen wir es einmal aus:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "produkt_summe(14)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Das sollte auch die Zahl sein, die Sie für `n=14` oben in Ihrer Tabelle stehen haben. \n",
    "\n",
    "Die Funktion verwendet zwar ein paar Dinge, um eine schöne Ausgabe zu erzeugen, aber die wesentliche Funktionalität in der `while`-Schleife zur Berechnung des Produkts besteht nur aus Konstrukten, die wir schon kennengelernt haben. \n",
    "\n",
    "\n",
    "![I wrote 20 short programs in Python yesterday.  It was wonderful.  Perl, I'm leaving you.\"](https://imgs.xkcd.com/comics/python.png)\n",
    "\n",
Prof. Dr. Robert Jäschke's avatar
Prof. Dr. Robert Jäschke committed
    "([Python](https://xkcd.com/353/), Randall Munroe)\n",
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
Prof. Dr. Robert Jäschke's avatar
Prof. Dr. Robert Jäschke committed
    "![Speichern](https://amor.cms.hu-berlin.de/~jaeschkr/teaching/spp/floppy.png) Speichern Sie dieses Notebook, so dass Ihre Änderungen nicht verlorengehen (nicht auf einem Pool-Rechner). Rufen Sie dazu im Menü \"File\" den Punkt \"Download as\"->\"Notebook\" auf und nutzen Sie beispielsweise einen USB-Stick, E-Mail, Google Drive, Dropbox oder Ihre [HU-Box](https://box.hu-berlin.de/).  "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "![Smiley](https://upload.wikimedia.org/wikipedia/commons/thumb/3/33/Smiling_smiley_yellow_simple.svg/240px-Smiling_smiley_yellow_simple.svg.png)\n",
    "\n",
    "Herzlichen Glückwunsch! Sie haben das 3. Kapitel geschafft. Weiter geht es in [5: Bedingungen und Rekursion](seminar05.ipynb)."
   ]
  }
 ],
 "metadata": {
  "language_info": {
   "name": "python",
   "pygments_lexer": "ipython3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}