Skip to content
Snippets Groups Projects
seminar10.ipynb 116 KiB
Newer Older
  • Learn to ignore specific revisions
  •    ]
      },
      {
       "cell_type": "markdown",
       "metadata": {},
       "source": [
        "Hier sehen wir, wie die Funktion verwendet werden kann und wie sie wirkt:"
       ]
      },
      {
       "cell_type": "code",
       "execution_count": null,
       "metadata": {},
       "outputs": [],
       "source": [
        "letters = ['a', 'b', 'c']\n",
        "delete_head(letters)\n",
        "letters"
       ]
      },
      {
       "cell_type": "markdown",
       "metadata": {},
       "source": [
        "Der Parameter `t` und die Variable `letters` sind Aliase für das selbe Objekt. Das Stapeldiagramm beim Aufruf von `delete_head` sieht folgendermaßen aus:\n",
        "\n",
        "![Stapeldiagramm delete_head](https://amor.cms.hu-berlin.de/~jaeschkr/teaching/spp/stapeldiagramm_delete_head.svg)\n",
        "\n",
        "Die zwei Blöcke `__main__` und `delete_head` teilen sich die Liste, daher zeigen zwei Pfeile auf sie.\n",
        "\n",
        "Es ist wichtig, dass wir zwischen Operationen unterscheiden, die Listen *verändern* und jenen, die neue Listen *erzeugen*. Beispielsweise verändert die Methode `append` eine Liste, aber der Operator `+` erzeugt eine neue Liste.\n",
        "\n",
        "Nachfolgend ein Beispiel zu `append`:"
       ]
      },
      {
       "cell_type": "code",
       "execution_count": null,
       "metadata": {},
       "outputs": [],
       "source": [
        "t1 = [1, 2]\n",
        "t2 = t1.append(3)\n",
        "print(t1)\n",
        "print(t2)"
       ]
      },
      {
       "cell_type": "markdown",
       "metadata": {},
       "source": [
        "Der Rückgabewert von `append` ist `None`.\n",
        "\n",
        "Nachfolgend ein Beispiel für den Operator `+`:"
       ]
      },
      {
       "cell_type": "code",
       "execution_count": null,
       "metadata": {},
       "outputs": [],
       "source": [
        "t3 = t1 + [4]\n",
        "print(t1)\n",
        "print(t3)"
       ]
      },
      {
       "cell_type": "markdown",
       "metadata": {},
       "source": [
        "Das Ergebnis des Operators ist eine neue Liste; die Ursprungsliste ist unverändert.\n",
        "\n",
        "Dieser Unterschied ist wichtig, wenn wir Funktionen schreiben die Listen verändern. Beispielsweise entfernt die folgende Funktion *nicht* das erste Element einer Liste: "
       ]
      },
      {
       "cell_type": "code",
       "execution_count": null,
       "metadata": {},
       "outputs": [],
       "source": [
        "def bad_delete_head(t):\n",
        "    t = t[1:]              # FALSCH!"
       ]
      },
      {
       "cell_type": "markdown",
       "metadata": {},
       "source": [
        "Der Segmentoperator erzeugt eine neue Liste und die Zuweisung sorgt dafür, dass `t` auf die neue Liste verweist, aber das verändert nicht die Ursprungsliste:"
       ]
      },
      {
       "cell_type": "code",
       "execution_count": null,
       "metadata": {},
       "outputs": [],
       "source": [
        "t4 = [1, 2, 3]\n",
        "bad_delete_head(t4)\n",
        "t4"
       ]
      },
      {
       "cell_type": "markdown",
       "metadata": {},
       "source": [
        "Am Anfang von `bad_delete_head` verweisen `t` und `t4` auf die gleiche Liste. Am Ende verweist `t` auf eine neue Liste, aber `t4` verweist immer noch auf die ursprüngliche, unveränderte Liste.\n",
        "\n",
        "Eine Alternative ist, eine Funktion zu schreiben, die eine neue Liste erzeugt und zurückgibt. Beispielsweise gibt `tail` alle bis auf das erste Element einer Liste zurück:"
       ]
      },
      {
       "cell_type": "code",
       "execution_count": null,
       "metadata": {},
       "outputs": [],
       "source": [
        "def tail(t):\n",
        "    return t[1:]"
       ]
      },
      {
       "cell_type": "markdown",
       "metadata": {},
       "source": [
        "Diese Funktion verändert die Ursprungsliste nicht! Folgendermaßen kann die Funktion verwendet werden:"
       ]
      },
      {
       "cell_type": "code",
       "execution_count": null,
       "metadata": {},
       "outputs": [],
       "source": [
        "letters = ['a', 'b', 'c']\n",
        "rest = tail(letters)\n",
        "rest"
       ]
      },
      {
       "cell_type": "markdown",
       "metadata": {},
       "source": [
    
        "## Debugging\n",
    
        "\n",
        "Unvorsichtige Verwendung von Listen (und anderen veränderbaren Objekten) kann langwieriges Debuggen verursachen. Einige übliche Fehler und Wege, sie zu vermeiden:\n",
        "\n",
    
        "### Die meisten Listenmethoden verändern das Argument und geben `None` zurück.\n",
    
        "\n",
        "Das ist das Gegenteil zum Verhalten der Methoden für Zeichenketten, die eine neue Zeichenkette zurückgeben und die ursprüngliche Zeichenkette unverändert lassen.\n",
        "\n",
        "Wenn Sie gewohnt sind, Code für Zeichenketten so zu schreiben:\n",
        "   \n",
        "```python\n",
        "word = word.strip()\n",
        "```\n",
        "   \n",
    
        "Dann ist es verlockend, folgenden Code für Listen zu schreiben:\n",
    
        "   \n",
        "```python\n",
        "t = t.sort()      # FALSCH!\n",
        "```\n",
        "   \n",
        "Weil `sort` keinen Wert (also `None`) zurückliefert, wird die nächste Operation, die wir mit `t` durchführen würden wahrscheinlich fehlschlagen. \n",
        "   \n",
        "Bevor wir Methoden und Operatoren für Listen verwenden, sollten wir aufmerksam die Dokumentation lesen und mit etwas Beispielcode testen.\n",
        "   \n",
    
        "### Sich für ein Idiom entscheiden und dann dabei bleiben.\n",
    
        "\n",
        "Ein Teil des Problems mit Listen ist, dass es zu viele Möglichkeiten gibt, mit Ihnen umzugehen. Beispielsweise können wir zum Entfernen eines Elements `pop`, `remove`, `del` oder sogar den Segmentoperator verwenden. \n",
        "   \n",
        "Um ein Element hinzuzufügen, können wir die Methode `append` oder den Operator `+` verwenden. Angenommen, `t` ist eine Liste und `x` ist ein Listenelement, dann sind die folgenden Varianten korrekt:"
       ]
      },
      {
       "cell_type": "code",
       "execution_count": null,
       "metadata": {},
       "outputs": [],
       "source": [
        "t = ['a', 'b', 'c']\n",
        "x = 'n'\n",
        "\n",
        "t.append(x)\n",
        "print(t)\n",
        "\n",
        "t = t + [x]\n",
        "print(t)\n",
        "\n",
        "t += [x]\n",
        "print(t)"
       ]
      },
      {
       "cell_type": "markdown",
       "metadata": {},
       "source": [
        "und die folgenden sind falsch:"
       ]
      },
      {
       "cell_type": "code",
       "execution_count": null,
       "metadata": {},
       "outputs": [],
       "source": [
        "t.append([x])          # FALSCH!\n",
        "print(t)\n",
        "\n",
        "t = t.append(x)        # FALSCH!\n",
        "print(t)\n",
        "\n",
    
        "t + [x]                # FALSCH!\n",
    
        "print(t)\n",
        "\n",
        "t = t + x              # FLASCH!\n",
        "print(t)"
       ]
      },
      {
       "cell_type": "markdown",
       "metadata": {},
       "source": [
        "Probieren Sie diese Beispiele (einzeln!) aus und stellen Sie sicher, dass Sie wirklich verstanden haben, was sie tun. Beachten Sie, dass nur das letzte Beispiel einen Laufzeitfehler (*runtime error*) verursacht. Die anderen drei Varianten sind erlaubt, aber sie tun das Falsche.\n",
        "   \n",
    
        "### Kopien erzeugen, um Aliasing zu vermeiden.\n",
    
        "\n",
        "Wenn Sie eine Methode wie z.B. `sort` verwenden wollen, die das Argument verändert, aber Sie benötigen auch die Ursprungsliste, dann können Sie eine Kopie erzeugen:"
       ]
      },
      {
       "cell_type": "code",
       "execution_count": null,
       "metadata": {},
       "outputs": [],
       "source": [
        "t = [3, 1, 2]\n",
        "t2 = t[:]\n",
        "t2.sort()\n",
        "print(t)\n",
        "print(t2)"
       ]
      },
      {
       "cell_type": "markdown",
       "metadata": {},
       "source": [
        "In diesem Beispiel könnten Sie auch die eingebaute Funktion `sorted` verwenden, die eine neue, sortierte Liste zurückgibt, ohne die Ursprungsliste zu verändern: "
       ]
      },
      {
       "cell_type": "code",
       "execution_count": null,
       "metadata": {},
       "outputs": [],
       "source": [
        "t2 = sorted(t)\n",
        "print(t)\n",
        "print(t2)"
       ]
      },
      {
       "cell_type": "markdown",
       "metadata": {},
       "source": [
    
        "## Glossar\n",
    
        "\n",
        "Legen wir uns eine Liste mit den wichtigsten Begriffen an, die wir im Kapitel 10 gelernt haben:\n",
        "\n",
        "- Liste: eine Folge von Werten\n",
        "- Element:\n",
        "- verschachtelte Liste: \n",
        "- Akkumulator:\n",
        "- erweiterte Zuweisung\n",
        "- Reducer:\n",
        "- Mapper:\n",
        "- Filter:\n",
        "- Objekt:\n",
        "- äquivalent:\n",
        "- identisch:\n",
        "- Referenz:\n",
        "- Aliasing:\n",
        "- Trennzeichen:\n",
        "\n",
        "Ergänzen Sie die Liste in eigenen Worten. Das ist eine gute Erinnerungs- und Übungsmöglichkeit."
       ]
      },
      {
       "cell_type": "markdown",
       "metadata": {},
       "source": [
    
        "## Übung\n",
    
        "\n",
        "Sie finden die Lösungen für die Aufgaben hier: http://thinkpython2.com/code/list_exercises.py\n",
        "\n",
    
        "### Aufgabe 1\n",
        "Schreiben Sie eine Funktion `nested_sum`, die eine Liste von Listen von ganzen Zahlen erwartet und die Werte der einzelnen Elemente aufaddiert und das Ergebnis zurückgibt. Beispielsweise sollte die Funktion für die Liste `t = [[1, 2], [3], [4, 5, 6]]` den Wert `21` zurückgeben.\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",
        "Wie immer schreiben wir zuerst den Kopf der Funktion mit den nötigen Parametern und eine `return`-Anweisung mit einem Platzhalter.\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",
        "In diesem Notebook wird eine Funktion vorgestellt, mit der Sie die Summe einer einzelnen Liste berechnen können. Schauen Sie nach, wie diese Funktion heißt und überlegen Sie, wie Sie diese Funktion hier verwenden können.\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",
        "Um die Funktion nutzen zu können, die die Summe einer einzelnen Liste berechnet, müssen Sie auf die einzelnen Elemente der Liste von Listen zugreifen. Dafür verwenden Sie eine `for`- Schleife.\n",
        "    \n",
        "  </div>       \n",
        "</details>   \n",
        "   \n",
        "  \n",
        "<details>\n",
        "    <summary type=\"button\" class=\"btn btn-primary\">4. Hinweis</summary>\n",
        "  <div class=\"alert alert-info\" role=\"alert\">\n",
        "      \n",
        "Sie brauchen eine Variable, in der Sie die Summen der untergeordneten Listen zusammenaddieren und speichern können.\n",
        "      \n",
        "  </div>       \n",
        "</details>  \n",
        "  \n",
        "  \n",
        "\n",
        "<details>\n",
        "    <summary type=\"button\" class=\"btn btn-primary\">5. Hinweis</summary>\n",
        "  <div class=\"alert alert-info\" role=\"alert\">\n",
        "      \n",
        "Sie müssen die Variable ausserhalb der `for`-Schleife implementieren. Setzen Sie innerhalb der `for``-Schleife diese Variable immer gleich des aktuellen Wertes plus der Summe der aktuellen Subliste. Am Ende geben Sie diese Zahl aus. \n",
        "      \n",
        "    </div>       \n",
        "</details>  "
    
       ]
      },
      {
       "cell_type": "code",
       "execution_count": null,
       "metadata": {},
       "outputs": [],
       "source": [
    
        "def nested_sum(t):\n",
    
    Prof. Dr. Robert Jäschke's avatar
    Prof. Dr. Robert Jäschke committed
        "    # Implementieren Sie hier die Funktion\n",
        "    "
    
       ]
      },
      {
       "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"
       ]
      },
      {
       "cell_type": "code",
       "execution_count": null,
       "metadata": {},
       "outputs": [],
       "source": [
        "def nested_sum(t):\n",
        "    total=0\n",
        "    for element in t:\n",
        "        total = total+ sum(element)\n",
        "    return total\n",
        "        \n",
        "        \n",
        "t = [[1, 2], [3], [4, 5, 6]]\n",
        "nested_sum(t)"
       ]
      },
      {
       "cell_type": "markdown",
       "metadata": {},
       "source": [
        "### Aufgabe 2  \n",
        "\n",
        "Schreiben Sie eine Funktion `cumsum`, die eine Liste von Zahlen erwartet und die kumulative Summe zurückgibt, d.h. eine neue Liste, in der das *i*-te Element die Summe der ersten *i + 1* Elemente der Original-Liste enthält. Beispielsweise sollte die Funktion für die Liste `t = [1, 2, 3]` die Liste `[1, 3, 6]` zurückgeben.\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",
        "Wie immer schreiben wir zuerst den Kopf der Funktion mit den nötigen Parametern und eine `return`-Anweisung mit einem Platzhalter.\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",
        "Da wir eine neue Liste ausgeben wollen, müssen wir eine neue (zunächst leere) Liste erstellen. Ebenso brauchen wir eine Variable, die die aktuelle Summe speichern kann. \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",
        "Wir müssen die alte Liste in einer 'for'-Schleife durchlaufen. Was sind die zwei Schritte, die innerhalb der Schleife vorgenommen werden müssen?\n",
        "      \n",
        "  </div>       \n",
        "</details>   \n",
        "   \n",
        "  \n",
        "<details>\n",
        "    <summary type=\"button\" class=\"btn btn-primary\">4. Hinweis</summary>\n",
        "  <div class=\"alert alert-info\" role=\"alert\">\n",
        "      \n",
        "Zunächst muss die neue Summe berechnet werden. Anschließend muss dieses Ergebnis an die (neue) Ergebnisliste angehängt werden.\n",
        "      \n",
        "  </div>       \n",
        "</details>  \n",
        "  \n",
        "  \n",
        "\n",
        "<details>\n",
        "    <summary type=\"button\" class=\"btn btn-primary\">5. Hinweis</summary>\n",
        "  <div class=\"alert alert-info\" role=\"alert\">\n",
        "\n",
        "Denken Sie daran, dass die 'return'-Anweisung am Ende die neue Liste zurückgeben muss.\n",
        "      \n",
        "   </div>       \n",
        "</details>  "
    
       ]
      },
      {
       "cell_type": "code",
       "execution_count": null,
       "metadata": {},
       "outputs": [],
       "source": [
        "def cumsum(t):\n",
        "    # Implementieren Sie hier die Funktion"
       ]
      },
      {
       "cell_type": "markdown",
       "metadata": {},
       "source": [
        "Testen Sie die Funktion mit verschiedenen Listen als Eingabe.\n",
        "\n",
    
        "Welche Liste müssten Sie der Funktion `cumsum` übergeben, um als Ergebnis die Liste `[1, 1, 2, 3, 5, 8, 13, 21, 34, 55]` der ersten zehn Fibonacci-Zahlen zu erhalten?\n",
        "\n",
        "<details>\n",
        "    <summary type=\"button\" class=\"btn btn-success\">Lösung für die Liste</summary>\n",
        "  <div class=\"alert alert-success\" role=\"alert\">\n",
        "      Die korrekte Liste ist: [1,0,1,1,2,3,5,8, 13, 21]\n",
        "  </div>       \n",
        "</details> "
       ]
      },
      {
       "cell_type": "code",
       "execution_count": null,
       "metadata": {},
       "outputs": [],
       "source": [
        "#Testen Sie hier verschiedene Listen, bis Sie das korrekte Ergebnis erhalten."
    
       ]
      },
      {
       "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"
       ]
      },
      {
       "cell_type": "code",
       "execution_count": null,
       "metadata": {},
       "outputs": [],
       "source": [
        "def cumsum(t):\n",
        "    total = 0\n",
        "    result = []\n",
        "    for element in t:\n",
        "        total += element\n",
        "        result.append(total)\n",
        "    return result\n",
        "\n",
        "t = [1, 2, 3] \n",
        "cumsum(t)"
       ]
      },
      {
       "cell_type": "markdown",
       "metadata": {},
       "source": [
        "### Aufgabe 3\n",
    
        "Schreiben Sie eine Funktion `middle`, die eine Liste als Argument erwartet und eine neue Liste zurückgibt, die alle Elemente bis auf das erste und letzte der Ausgangsliste enthält. Beispielsweise sollte die Funktion für die Liste `t = [1,2,3,4]` die Liste `[2,3]` zurückgeben:\n",
        "\n",
        "```python\n",
        "t = [1,2,3,4]\n",
        "middle(t)\n",
        "```\n",
    
        "sollte `[2,3]` ergeben.    \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",
        "Wie immer schreiben wir zuerst den Kopf der Funktion mit den nötigen Parametern und eine `return`-Anweisung mit einem Platzhalter.\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 wollen den 'Segment' Operator verwenden, um die Teilliste auszuwählen. Schauen Sie sich nochmal an, wie dieser verwendet wird.\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",
        "Zunächst wollen wir dafür sorgen, dass die Liste ab dem zweiten Element zurückgegeben wird. Welchen Index hat das erste Element der Liste, welchen das zweite? Testen Sie ob Ihre Funktion korrekt die Liste ab dem 2. Element zurückgibt.\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",
        "In Notebook 8 haben Sie gelernt, wie Sie von hinten auf Zeichenketten zugreifen können, ohne ihre Länge zu kennen. Das funktioniert analog für Listen. Schauen Sie nochmal in Notebook 8 nach, wenn Sie sich nicht mehr sicher sind (nutzen Sie gegebenenfalls `str`+`f`und suchen Sie nach `rückwärts` um die entsprechende Stelle zu finden). Achten Sie dabei darauf, wie die Segmente ausgegeben werden. Probieren Sie verschiedene Indices bis es richtig funktioniert.\n",
        "    \n",
        "  </div>       \n",
        "</details>  "
    
       ]
      },
      {
       "cell_type": "code",
       "execution_count": null,
       "metadata": {},
       "outputs": [],
       "source": [
        "def middle(t):\n",
        "    # Implementieren Sie hier die Funktion"
       ]
      },
      {
       "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"
       ]
      },
      {
       "cell_type": "code",
       "execution_count": null,
       "metadata": {},
       "outputs": [],
       "source": [
        "def middle(t):\n",
        "    return t[1:-1]\n",
        "    \n",
        "t=[1,2,3,4]\n",
        "middle(t)\n"
       ]
      },
      {
       "cell_type": "markdown",
       "metadata": {},
       "source": [
        "### Aufgabe 4\n",
    
        "Schreiben Sie eine Funktion `chop`, die eine Liste als Argument erwartet, das erste und letzte Element entfernt und `None` zurückgibt. Beispielsweise sollte\n",
        "\n",
        "```python\n",
        "t = [1,2,3,4]\n",
        "chop(t)\n",
        "t\n",
        "```\n",
    
        "`[2,3]` ergeben.\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",
        "Zunächst mag es scheinen, als sei diese Funktion dasselbe wie `middle`, aber wenn Sie ihre ursprüngliche Liste ausgeben lassen, nachdem Sie `middle` angewendet haben, dann ist die Liste unverändert. Im Gegensatz dazu verändern wir mit `chop` die ursprüngliche Liste.\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",
        "Schauen Sie in diesem Notebook nach, wie Sie Elemente anhand ihres Indexes löschen können.     \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",
        "Wir benötigen 2 Zeilen, eine für jeden Index, den wir entfernen wollen. Testen Sie ob Sie den richtigen Index entfernt haben indem Sie die Funktion testen und verändern Sie gegebenenfalls den Index bis Sie das richtige Ergebnis erhalten.      \n",
        "  </div>       \n",
        "</details>   "
    
       ]
      },
      {
       "cell_type": "code",
       "execution_count": null,
       "metadata": {},
       "outputs": [],
       "source": [
        "def chop(t):\n",
        "    # Implementieren Sie hier die Funktion"
       ]
      },
      {
       "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"
       ]
      },
      {
       "cell_type": "code",
       "execution_count": null,
       "metadata": {},
       "outputs": [],
       "source": [
        "def chop (t):\n",
        "    del t[0]\n",
        "    del t[-1]\n",
        "\n",
        "t=[1,2,3,4]\n",
        "chop (t)\n",
        "t"
       ]
      },
      {
       "cell_type": "markdown",
       "metadata": {},
       "source": [
        "### Aufgabe 5\n",
    
        "Schreiben Sie eine Funktion `is_sorted`, die eine Liste als Argument erwartet und `True` zurückgibt, falls die Liste in aufsteigender Reihenfolge sortiert ist und ansonsten `False`. Also zum Beispiel:\n",
        "\n",
        "```python\n",
        ">>> is_sorted([1, 2, 2])\n",
        "True\n",
        ">>> is_sorted(['b', 'a'])\n",
        "False\n",
    
        "```\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",
        "Wir müssen die eingegebene Liste mit der sortierten Version derselben vergleichen. Sind Sie gleich, gibt der Vergleichsoperator `True` zurück, ansonsten `False`.\n",
        "      \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",
        "In diesem Notebook haben Sie eine eingebaute Funktion kennengelernt, die eine gegebene Liste sortiert. Schauen Sie nach, wie diese Funktion aussieht und wenden Sie diese auf die eingegebene Liste an.\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",
        "Mit `==`können Sie zwei Listen in einer Zeile vergleichen. Das Ergebnis des Vergleichs ist ein `boolscher`-Wert, also `True` oder `False`. Daher können Sie die ganze Funktion in einer Zeile implementieren. \n",
        "      \n",
        "  </div>       \n",
        "</details> "
    
       ]
      },
      {
       "cell_type": "code",
       "execution_count": null,
       "metadata": {},
       "outputs": [],
       "source": [
        "def is_sorted(t):\n",
        "    # Implementieren Sie hier die Funktion"
       ]
      },
      {
       "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"
       ]
      },
      {
       "cell_type": "code",
       "execution_count": null,
       "metadata": {},
       "outputs": [],
       "source": [
        "def is_sorted(t):\n",
        "    return t == sorted(t)\n",
        "\n",
        "print(is_sorted([1, 2, 2]))\n",
        "print(is_sorted(['b', 'a']))\n"
       ]
      },
      {
       "cell_type": "markdown",
       "metadata": {},
       "source": [
        "### Aufgabe 6\n",
        "\n",
        "Zwei Wörter bilden ein *Anagramm*, wenn wir die Buchstaben des einen Wortes so anordnen können, dass sich das andere Wort ergibt. (Beispielsweise bilden *LAGER* und *REGAL* ein Anagramm.) Schreiben Sie eine Funktion `is_anagram`, die zwei Zeichenketten erwartet und `True` zurückgibt, falls sie ein Anagramm bilden (sonst `False`). \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",
        "Ein Anagramm liegt dann vor, wenn die Zeichen in einer Zeichenkette und die Zeichen in einer anderen Zeichenkette genau die gleichen sind. Wie können Sie das überprüfen?\n",
        "      \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",
        "Zeichenketten und Listen verhalten sich sehr ähnlich. Sie können die `sorted`-Funktion auf Zeichenketten anwenden und erhalten eine sortierte Liste von Zeichen in einer Zeichenkette. Bilden zwei Zeichenketten ein Anagramm sind die sortierten Listen gleich. Gehen Sie analog zu `is_sorted()` vor um zu prüfen, ob die Zeichenketten gleich sind.\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",
        "Wenn Sie sich im englischsprachigen Raum bewegen, sind sie nun fertig, da Sie Groß- und Kleinschreibung ignorieren können. Wenn wir für die deutsche Sprache akurate Ergebnisse erhalten wollen, müssen wir sicherstellen, dass die Zeichenketten nur Kleinbuchstaben enthält, da sonst zum Beispiel 'Lager' und 'Regal' nicht gleich sind. Wie können wir sicherstellen, dass dies der Fall ist? (D.h. gegebenenfalls Großbuchstaben umwandeln?)\n",
        "\n",
        "  </div>       \n",
        "</details>  \n",
        "\n",
        "\n",
        "<details>\n",
        "    <summary type=\"button\" class=\"btn btn-primary\">4. Hinweis</summary>\n",
        "  <div class=\"alert alert-info\" role=\"alert\">\n",
        "\n",
        "Verwenden Sie die Zeichenkettenmethode `lower()` um die Zeichenkette umzuwandeln. Vergessen Sie nicht, die aktualisierten Zeichenketten zu speichern. Testen Sie Ihre Funktion mit Groß- und Kleinbuchstaben.\n",
        "  </div>       \n",
        "</details>"
    
       ]
      },
      {
       "cell_type": "code",
       "execution_count": null,
       "metadata": {},
       "outputs": [],
       "source": [
        "def is_anagram(v, w):\n",
        "    # Implementieren Sie hier die Funktion"
       ]
      },
      {
       "cell_type": "markdown",
       "metadata": {},
       "source": [
    
        "Zusatzaufgabe: Suchen Sie in der Wortliste aus dem [9. Kapitel](notebooks_seminar09.ipynb) nach Anagrammen."
    
       ]
      },
      {
       "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"
       ]
      },
      {
       "cell_type": "code",
       "execution_count": null,
       "metadata": {},
       "outputs": [],
       "source": [
        "def is_anagram(v, w):\n",
        "    # Implementieren Sie hier die Funktion\n",
        "    v=v.lower()\n",
        "    w=w.lower()\n",
        "    return sorted (v) == sorted (w)\n",
        "    \n",
        "is_anagram('Lager','Regal')"
       ]
      },
      {
       "cell_type": "markdown",
       "metadata": {},
       "source": [
        "### Aufgabe 7\n",
        "Schreiben Sie eine Funktion `has_duplicates`, die eine Liste als Argument erwartet und `True` zurückgibt, falls ein Element der Liste mehr als einmal in der Liste enthalten ist. Die Funktion soll die Ursprungsliste nicht verändern.\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",
        "Als Basis soll die Funktion `False` zurückgeben, nur wenn zwei gleiche Elemente gefunden werden, wird stattdessen `True` zurückgegeben. Schreiben Sie die beiden möglichen Rückgaben. Wo genau diese stehen müssen, überlegen wir uns im Laufe der Entwicklung der Funktion.\n",
        "      \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",
        "Wenn wir schauen wollen, ob sich Elemente in einer Liste wiederholen, ist es sinnvoll, die Liste zu sortieren. Wenn die Liste sortiert ist, stehe gleiche Elemente nebeneinander, statt an beliebigen -- unabhängigen -- Stellen in der Liste. Lassen Sie sich die sortierte Liste in einer 'print'-Anweisung innerhalb der Funktion ausgeben und geben Sie gleichzeitig die Originalliste aus um sicher zu gehen, dass Sie die Originalliste nicht verändern.\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",
        "Um in einer sortierten Liste zu überprüfen, ob es Duplikate gibt, müssen wir lediglich für jeden Index schauen, ob der benachbarte Index das gleiche Element enthält. Da Sie jeden Index ansteuern, müssen Sie immer nur einen Nachbarn überprüfen, je nachdem, welchen Sie auswählen, müssen Sie den Start und End Index gegebenenfalls anpassen. Hier schauen wir uns immer den rechten Nachbarn (also den mit dem nächstgrößeren Index) an. \n",
        "\n",
        "  </div>       \n",
        "</details>  \n",
        "\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 durchlaufen die Liste mit einer `for`-Schleife. Nutzen Sie die `len`-Funktion um die Länge der Liste zu ermitteln und zu schauen, wie oft die `for`-Schleife durchlaufen werden muss. Achten Sie dabei auf den Index um sogenannte `off by one` Fehler zu vermeiden. \n",
        "  </div>       \n",
        "</details>\n",
        "\n",
        "\n",
        "<details>\n",
        "    <summary type=\"button\" class=\"btn btn-primary\">5. Hinweis</summary>\n",
        "  <div class=\"alert alert-info\" role=\"alert\">\n",
        "      \n",
        "In diesem Fall wollen wir in der `for`-Schleife 2 Elemente der Liste vergleichen, daher können wir die Liste nicht einfach Element für Element durchlaufen, sondern benötigen einen Index. Schreiben Sie die Schleife und lassen Sie sich jeweils den Index ausgeben, um zu testen, dass alle benötigten Werte angenommen werden\n",
        "  </div>      \n",
        "</details>\n",
        "\n",
        "\n",
        "<details>\n",
        "    <summary type=\"button\" class=\"btn btn-primary\">6. Hinweis</summary>\n",
        "  <div class=\"alert alert-info\" role=\"alert\">\n",
        "      \n",
        "In der Schleife müssen Sie das Element mit dem Index i mit dem Element mit dem Index i+1 vergleichen. Sind diese gleich, kann die Funktion abbrechen und `True` zurückgeben. Wird die Schleife durchlaufen, ohne das zwei Elemente gleich sind, wird die Schleife verlassen und Sie geben `False` zurück\n",
        "    \n",
        "  </div>       \n",
        "</details>\n",
        "\n",
        "\n"
    
       ]
      },
      {
       "cell_type": "code",
       "execution_count": null,
       "metadata": {},
       "outputs": [],
       "source": [
        "def has_duplicates(t):\n",
        "    # Implementieren Sie hier die Funktion"
       ]
      },
      {
       "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"
       ]
      },
      {
       "cell_type": "code",
       "execution_count": null,
       "metadata": {},
       "outputs": [],
       "source": [
        "def has_dublicates(t):\n",
        "    '''Takes list or string\n",
        "    Returns True if dublicates exist, otherwise returns False'''\n",
        "    \n",
        "    t=sorted(t)\n",
        "    \n",
        "    for i in range (len(t)-1):\n",
        "        if t[i] == t[i+1]:\n",
        "            return True\n",
        "    return False\n",
        "\n",
        "\n",
        "\n",
        "t=['h','a', 'l', 'l', 'o']\n",
        "print (has_dublicates(t))\n",
        "t"
       ]
      },
      {
       "cell_type": "markdown",
       "metadata": {},
       "source": [
        "### Aufgabe 8\n",
    
        "In dieser Aufgabe geht es um das sogenannte \"Geburtstags-Paradoxon\" über das Sie mehr in [Wikipedia](http://en.wikipedia.org/wiki/Birthday_paradox) lesen können.\n",
        "\n",
    
        "Wenn 23 Studierende in Ihrem Kurs sind, wie hoch ist dann die Wahrscheinlichkeit, dass zwei davon am gleichen Tag Geburtstag haben? Sie können diese Wahrscheinlichkeit schätzen, indem Sie zufällig 23 Geburtstage auswürfeln und prüfen, ob mindestens zwei davon identisch sind.\n",
        "\n",
        "<details>\n",
        "    <summary type=\"button\" class=\"btn btn-info\">Hinweis</summary>\n",
        "  <div class=\"alert alert-info\" role=\"alert\">\n",
        "\n",
        "Sie können zufällige Geburtstage mit Hilfe der Funktion `randint` aus dem <a href= \"https://docs.python.org/3/library/random.html\">Modul `random`</a> erzeugen.\n",
        "      \n",
        "  </div>       \n",
        "</details> \n",
        "\n",
        "Die Originallösung aus dem Buch finden Sie [hier](http://thinkpython2.com/code/birthday.py), es folgen wie gewohnt Lösungsschritte mit denen Sie versuchen können, die Aufgabe selbstständig zu lösen.\n",
        "\n",
        "<details>\n",
        "    <summary type=\"button\" class=\"btn btn-primary\">1. Hinweis</summary>\n",
        "  <div class=\"alert alert-info\" role=\"alert\">\n",
        "\n",
        "In Essenz besteht diese Aufgabe aus 2 Teilen. Zum einen müssen wir eine Funktion schreiben, die eine gegebene Anzahl an Geburtstagen auswürfelt. Zum anderen brauchen wir eine Funktion, die prüft, ob zwei davon identisch sind. Und da eine einzelne Simulation keine guten Daten zu der Wahrscheinlichkeit des Datensets liefert, sollten wir eine Funktion schreiben, die diesen Test wiederholt durchführt und dann das Ergebnis zurückgibt.      \n",
        "      \n",
        "  </div>       \n",
        "</details>   \n",
        "\n",
        "Erstellen der Geburtstagsliste:\n",
        "  \n",
        "<details>\n",
        "    <summary type=\"button\" class=\"btn btn-primary\">2. Hinweis</summary>\n",
        "  <div class=\"alert alert-info\" role=\"alert\">\n",
        "\n",