Skip to content
Snippets Groups Projects
seminar09.ipynb 55 KiB
Newer Older
Prof. Dr. Robert Jäschke's avatar
Prof. Dr. Robert Jäschke committed
   "outputs": [],
   "source": [
    "def is_palindrome(word):\n",
    "    i = 0\n",
    "    j = len(word)-1\n",
    "\n",
    "    while i<j:\n",
    "        if word[i] != word[j]:\n",
    "            return False\n",
    "        i = i+1\n",
    "        j = j-1\n",
    "\n",
    "    return True"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Wir könnten das ganze auch auf ein bereits zuvor gelöstes Problem zurückführen und stattdessen schreiben:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "def is_palindrome(word):\n",
Miriam Brauer's avatar
Miriam Brauer committed
    "    return is_reverse(word, word)\n",
    "\n",
    "is_palindrome(\"anna\")"
Michel Schwab's avatar
Michel Schwab committed
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
Miriam Brauer's avatar
Miriam Brauer committed
    "... indem wir `is_reverse` aus [Abschnitt 8.11](seminar08.ipynb#8.11-Debugging) verwenden:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "def is_reverse(word1, word2):\n",
    "    '''Um die kürzere Funktion is_palindrom() aufzurufen eingefügt.'''\n",
    "    if len(word1) != len(word2):\n",
    "        return False\n",
    "    \n",
    "    i = 0\n",
    "    j = len(word2)-1\n",
    "\n",
    "    while j > 0:\n",
    "        if word1[i] != word2[j]:\n",
    "            return False\n",
    "        i = i+1\n",
    "        j = j-1\n",
    "\n",
    "    return True"
Michel Schwab's avatar
Michel Schwab committed
   ]
  },
Prof. Dr. Robert Jäschke's avatar
Prof. Dr. Robert Jäschke committed
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 9.5 Debugging\n",
    "\n",
    "Programme zu testen ist schwierig. Die Funktionen in diesem Abschnitt sind vergleichsweise einfach zu testen, denn wir können die Ergebnisse von Hand überprüfen. Dennoch ist es schwierig bis unmöglich eine Menge von Wörtern zu wählen, mit denen sich alle möglichen Fehler abdecken lassen.\n",
    "\n",
    "Schauen wir uns `has_no_e` als Beispiel an, gibt es zwei offensichtliche Fälle, die wir testen müssen: für Wörter, die ein \"e\" enthalten sollte die Funktion `False` zurückgeben und für Wörter, die kein \"e\" enthalten sollte sie \"True\" zurückgeben. Für beide Fälle fällt es uns leicht, ein Testwort zu finden.\n",
    "\n",
    "Bei jedem der Fälle gibt es jedoch einige nicht so offensichtliche Teilfälle. Unter den Wörtern die ein \"e\" enthalten, sollten wir Wörter testen, die ein \"e\" am Anfang, am Ende und irgendwo in der Mitte enthalten. Wir sollten lange Wörter, kurze Wörter und sehr kurze Wörter, wie zum Beispiel die leere Zeichenkette, testen. Die leere Zeichenkette ist ein Beispiel für einen **Spezialfall** - einer der nicht offensichtlichen Fälle, bei dem sich oft Fehler verstecken.\n",
    "\n",
    "Zusätzlich zu den Testfällen, die wir selber erzeugen, können wir unser Programm auch mit einer Wortliste wie z.B. `top10000de.txt` testen. Indem wir uns die Ausgabe anschauen, finden wir vielleicht Fehler. Aber wir sollten vorsichtig sein: es kann sein, dass wir eine Art von Fehlern finden (Wörter, die nicht enthalten sein sollten, es aber trotzdem sind) aber nicht die andere (Wörter die enthalten sein sollten, es aber nicht sind).\n",
    "\n",
    "Im Allgemeinen kann Testen uns helfen, Fehler zu finden, aber es ist nicht einfach, eine gute Menge von Testfällen zu erzeugen. Und selbst wenn wir das machen, können wir uns nie sicher sein, dass unser Programm korrekt ist. Oder, um es mit den Worten eines legendären Informatikers zu sagen:\n",
    "\n",
    "> Program testing can be used to show the presence of bugs, but \n",
    "> never to show their absence!\n",
    "> \n",
    "> — Edsger W. Dijkstra \n",
    "\n",
    "(Testen kann uns zwar helfen, Bugs zu finden, jedoch nicht, ihre Abwesenheit zu beweisen.)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 9.6 Glossar\n",
    "Legen wir uns eine Liste mit den wichtigsten Begriffen an, die wir im Kapitel 9 gelernt haben:\n",
Prof. Dr. Robert Jäschke's avatar
Prof. Dr. Robert Jäschke committed
    "\n",
    "- Dateiobjekt:\n",
    "- Zurückführen auf ein vorher gelöstes Problem:\n",
Miriam Brauer's avatar
Miriam Brauer committed
    "- Spezialfall: ein nicht offensichtlicher Fall, in dem sich oft Fehler verstecken.\n",
Prof. Dr. Robert Jäschke's avatar
Prof. Dr. Robert Jäschke committed
    "\n",
    "Ergänzen Sie die Liste in eigenen Worten. Das ist eine gute Erinnerungs- und Übungsmöglichkeit."
Prof. Dr. Robert Jäschke's avatar
Prof. Dr. Robert Jäschke committed
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
Miriam Brauer's avatar
Miriam Brauer committed
    "### 9.7 Übung\n",
    "\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Aufgabe 7\n",
Prof. Dr. Robert Jäschke's avatar
Prof. Dr. Robert Jäschke committed
    "\n",
Miriam Brauer's avatar
Miriam Brauer committed
    "Hier ist ein weiteres [Car Talk Rätsel](http://www.cartalk.com/content/puzzlers):\n",
Prof. Dr. Robert Jäschke's avatar
Prof. Dr. Robert Jäschke committed
    "\n",
Miriam Brauer's avatar
Miriam Brauer committed
    "> Als ich letztens auf der Autobahn gefahren bin ist mir auf meinem Kilometerzähler etwas aufgefallen. Wie die meisten Kilometerzähler hat er sechs Stellen für die ganzen Kilometer. Wenn also mein Auto 300000 Kilometer gefahren wäre, dann würde ich 3-0-0-0-0-0 sehen. Was ich sah, war sehr interessant. Mir ist aufgefallen, dass die letzten vier Ziffern ein Palindrom gebildet haben, d.h. rückwärts gelesen ergeben sie die gleiche Zahlenfolge wie vorwärts. Beispielswiese ist 5-4-4-5 ein Palindrom. Mein Kilometerzähler könnte also beispielsweise 3-1-5-4-4-5 angezeigt haben. \n",
Prof. Dr. Robert Jäschke's avatar
Prof. Dr. Robert Jäschke committed
    ">\n",
    "> Einen Kilometer später ergaben die letzten 5 Ziffern ein Palindrom. Mein Kilometerzähler könnte also beispielsweise 3-6-5-4-5-6 anzeigen. Nach einem weiteren Kilometer ergaben die mittleren 4 der 6 Ziffern ein Palindrom. Bis du bereit? Noch einen Kilometer weiter ergaben alle 6 Ziffern ein Palindrom!\n",
    ">\n",
    "> Die Frage ist: was zeigte der Kilometerzähler an, als ich das erste mal darauf schaute?\n",
    "\n",
Miriam Brauer's avatar
Miriam Brauer committed
    "Schreiben Sie ein Python-Programm, welches alle Zahlen mit sechs Ziffern durchtestet und alle Nummern mit dieser Eigenschaft ausgibt."
Prof. Dr. Robert Jäschke's avatar
Prof. Dr. Robert Jäschke committed
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Implementieren Sie hier das Programm\n"
   ]
  },
Miriam Brauer's avatar
Miriam Brauer committed
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "\n",
    "![Spoiler Alert](https://imgs.xkcd.com/comics/spoiler_alert.png)\n",
    "([Spoiler Alert](https://xkcd.com/109/), Randall Munroe)\n",
    "\n",
    "\n",
    "1. Es sollte schnell klar werden, dass wir mehrere Funktionen brauchen, die ineinander greifen. Insgesamt werden 3 Funktionen benötigt. Überlegen Sie welche Funktionen benötigt werden und schreiben Sie eventuell schoneinmal die Funktionskopf. \n",
    "2. Wir brauchen auf jedenfall eine Funktion, die testet ob eine Zahl ein Palindrom ist. Verwandeln Sie die eingegebene Zahl in einen `string` dann können Sie die einzeilige version von is_palindrom aus [Abschnitt 8.13](seminar08.ipynb#8.13-Übung) wiederverwenden.\n",
    "3. Testen Sie diese Funktion. Behalten Sie auf jeden Fall im Kopf, dass die Funktion im Lauf der Entwicklung unter Umständen angepasst werden muss. \n",
    "4. Sobald `palindrom` funktioniert, schreiben wir eine Funktion, die für einzelne Zahlen prüft, ob die Bedingungen des Rätsels erfüllt sind. Diese Funktion ist schwierig zu testen, da Sie quasi im Kopf durchrechnen müssten, was das Ergebnis ist. Kontrollieren Sie ob Sie die Angaben des Rätsels richtig übernommen haben und geben Sie der Funktion ggf. einen Vertrauensvorschuss.\n",
    "5. Die Funktion ruft `palindrom` mit verschiedenen Werten auf, die aus der Zahl errechnet werden, die eingegeben wird. Beim erneuten Lesen der Aufgabenstellung sollte auffallen, dass wir die eingegebene Zahl auf verschiedene Längen kürzen müssen.\n",
    "6.  Am besten funktiert das, wenn Sie Start- und Endwerte mit übergeben und diese dann auch an palindrom weitergeben. Hier müssen wir `palindrom` anpassen, indem wir mehr Werte übergeben und den `string` mit dem Klammernoperator entsprechend kürzen. \n",
    "7. Insgesamt müssen 4 Zahlen überprüft werden, dabei kann abgebrochen werden, sobald einer der Tests `False` zurückgibt. Zuerst wird palindrom mit i, 2 und 6 aufgerufen, dann mit i+1, 1 und 6. Schreiben Sie die anderen beiden Tests selber und ergänzen Sie wie notwendig die `return`-Anweißungen. *Hinweiß: Sie können die Funktion mit 199999 und 111111 testen, ersteres gibt `True` letzteres `False` zurück.*  \n",
    "8. Wenn diese Tests das gewüschte Ergebnis liefern, nehmen Sie an, dass die Funktion richtig funktioniert und schreiben Sie die letzte Funktion die wir benötigen. Sie iteriert durch alle möglichen Zählerstände und gibt alle aus, die die Bedingung des Rätsels erfüllen. Überlegen Sie was der kleinstmögliche Zählerstand ist. Überlegen Sie auch was der größtmögliche Zählerstand ist.\n",
    "9. Erstellen Sie eine Variable mit dem kleinstmöglichen Zählerstand und eine Schleife, deren Abbruchbedingung der größtmögliche Zählerstand ist.\n",
    "10. In dieser Schleife prüfen Sie den momentanen Wert des Zählers in `check()` und wenn die Funktion `True` zurückliefert, drucken sie den Wert des Zählers aus. Wenn Sie eine `while`-Schleife verwenden, vergessen Sie nicht den Wert des Zählers zu inkrementieren. \n",
    "\n",
    "*Hinweiß: 198888 und 199999 sollten als Lösungen rauskommen*\n",
    "\n",
    "Eine weitere Lösung finden Sie [hier](http://thinkpython2.com/code/cartalk2.py)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "def palindrom(i, start, end):\n",
    "    s=str(i)[start:end]\n",
    "    return s[::-1]==s\n",
    "    \n",
    "\n",
    "    \n",
    "def check(i):\n",
    "    if palindrom(i, 2,6):\n",
    "        if palindrom(i+1, 1, 6):\n",
    "            if palindrom(i+2,1,5):\n",
    "                if palindrom(i+3,0,6):\n",
    "                    return True\n",
    "    return False            \n",
    "\n",
    "\n",
    "\n",
    "\n",
    "\n",
    "def check_all():\n",
    "    i = 100000\n",
    "    print(\"Hier die Zählerstände die Lösungen sind: \\n\")\n",
    "    while i <= 999999:\n",
    "        if check(i):\n",
    "            print(i)\n",
    "        i = i + 1\n",
    "\n",
    "        \n",
    "check_all()"
   ]
  },
Prof. Dr. Robert Jäschke's avatar
Prof. Dr. Robert Jäschke committed
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Aufgabe 8\n",
Prof. Dr. Robert Jäschke's avatar
Prof. Dr. Robert Jäschke committed
    "\n",
    "Und noch ein [Car Talk Rätsel](http://www.cartalk.com/content/puzzlers) welches sich mit Suche lösen lässt:\n",
    "\n",
    "> Letztens hat mich meine Mutter besucht und uns ist aufgefallen, dass die zwei Ziffern, die mein Alter angegeben rückwärts gelesen ihrem Alter entsprachen. Wir haben uns gefragt, wie oft das über die Jahre schon passiert ist, aber wir wurden abgelenkt und haben keine Antwort gefunden.\n",
    "> Als ich nach Hause kam ist mir aufgefallen, dass die Ziffern unserer Alter sich bisher sechs mal umkehren ließen. Mir fiel auch auf, dass es in ein paar Jahren nochmal passieren würde, wenn es uns bis dahin gut geht. Und wenn wir richtig viel Glück haben, würde es danach noch einmal passieren. Anders gesagt: es könnte acht mal insgesamt passieren. Die Frage ist also, wie alt ich gerade bin?\n",
    "\n",
    "Schreiben Sie ein Programm, welches nach einer Lösung für dieses Rätsel sucht. Hinweis: Sie könnten die Zeichenketten-Methode [zfill](http://python-reference.readthedocs.io/en/latest/docs/str/zfill.html) nützlich finden. Lösung: http://thinkpython2.com/code/cartalk3.py"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Implementieren Sie hier ihr Programm\n",
    "\n"
   ]
  },
Miriam Brauer's avatar
Miriam Brauer committed
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "\n",
    "![Spoiler Alert](https://imgs.xkcd.com/comics/spoiler_alert.png)\n",
    "([Spoiler Alert](https://xkcd.com/109/), Randall Munroe)\n",
    "\n",
    "1. Auch dies ist wieder ein Problem für das wir mehrere Funktionen schreiben müssen. Überlegen Sie  zunächst in welche Bestandteile sie das Problem aufteilen können.\n",
    "2. Wir brauchen insgesammt 4 Funktionen, diese sind stärker miteinander verbunden als in der vorherigen Aufgabe, wir versuchen dennoch Sie nach und nach zu schreiben.\n",
    "3. Wir schreiben zunächst eine Funktion, die testet ob sich das Alter herumdrehen lässt. Sie brauchen 2 Strings der gleichen Länge, dafür können Sie `zfill(2)` verwenden. Orientieren Sie sich an `palindrom` aus der vorherigen Aufgabe.\n",
    "4. Die Funktion `are_reversed()` wird in 2 weiteren Funktionen dieser Aufgabe verwenden, die sich einigen Code teilen. Schreiben Sie also zunächst eine der Funktionen, duplizieren Sie sie dann und passen Sie sie entsprechen an.\n",
    "5. In der ersten Funktion wird gezählt, wie oft sich für einen gegebenen Altersunterschied das Alter der Mutter und der Tochter umdrehen lässt. \n",
    "6. Erstellen Sie eine Variable die das Alter der Tochter simuliert. Initialisieren Sie diese mit 0. Erstellen Sie eine Variable die zählt wie oft sich das Alter umdrehen lässt.\n",
    "7. Da Sie jedes mögliche Alter für den gegebenen Abstand testen wollen erstellen Sie ein Schleife. Da Sie das Alter der Mutter als Abbruchbedingung nehmen wollen und wir die entsprechende Variable erst in der Schleife initialisieren verwenden Sie eine Schleife die erst abbricht, wenn in der Schleife eine Bedingung erfüllt wird. (*`While True`*)\n",
    "8. Das Alter der Mutter ergibt sich aus dem Alter der Tochter und der Differenz. Erstellen Sie die Variable entsprechend. \n",
    "9. Rufen Sie `are_reversed()` mit mother und daughter auf. Wird `True` zurückgegeben, muss count inkrementiert werden.\n",
    "10. Testen Sie das Alter der Mutter. Ist es größer als 100 brechen Sie die Schleife mit einer `break`-Anweißung ab.\n",
    "11. Vergessen Sie nicht vor Abschluss des Schleifendurchlaufs die Variable `daughter` zu inkrementieren.\n",
    "12. Nach Verlassen der Schleife geben Sie mit der `return`-Anweißung den Zähler zurück. \n",
    "13. Kopieren Sie die Funktion und geben Sie ihr einen neuen Namen. Weitere Änderungen der Funktion führen wir an gegebener Stelle durch. \n",
    "14. Schreiben Sie nun zunächst eine allgemeine Funktion. Diese wird nach und nach den Altersabstand zwischen Mutter und Tocher erhöhen und prüfen ob die Bedingung des Rätsels erfüllt ist. Da wir den Altersabstand an die anderen Funktionen weiterreichen, erstellen Sie hier die benötigte Variable. Legen Sie einen sinnvollen Mindestabstand fest. \n",
    "15. Schreiben Sie eine Schleife die den Altersabstand graduell vergrößert. Wählen Sie einen sinnvollen Maximalabstand als Abbruchbedingung.\n",
    "16. In der Schleife wird `num_instances()`aufgerufen und der Rückgabewert einer Variablen zugewießen. Diese Variable wird dann geprüft um zu schauen ob dieser Altersabstand die Bedingung des Rätsels erfüllt. Was ist diese Bedinung?\n",
    "17. Ist die Bedinung erfüllt wird `list_instance` mit dieser Differenz aufgerufen. Diese Funktion prüft das Alter analog zu `num_instances()` und gibt das Alter aus, das die Lösung des Rätsels dastellt. Wir brauchen hierbei `print`-Anweißungen, eine für den Kopf der Tablle und eine die das Alter ausdruckt, wenn sich das Alter von Mutter und Tochter genau x mal bisher umdrehen ließ. \n",
    "\n",
    "*Hinweiß: Vergessen Sie nicht, diff in der Schleife zu inkrementieren!*\n",
    "\n",
    "\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "def are_reversed(i,j):\n",
    "    i= str(i).zfill(2)\n",
    "    j= str(j).zfill(2)\n",
    "    if i==j[::-1]:\n",
    "        return True\n",
    "    \n",
    "\n",
    "def num_instances(diff):\n",
    "    daughter = 0\n",
    "    count = 0\n",
    "    while True:\n",
    "        mother = daughter + diff\n",
    "        if are_reversed(daughter, mother):\n",
    "            count = count + 1\n",
    "        if mother > 100:\n",
    "            break\n",
    "        daughter = daughter + 1\n",
    "    return count\n",
    "\n",
    "\n",
    "def list_instance(diff):\n",
    "    daughter=0\n",
    "    count=0\n",
    "    print(\"daughter mother\")\n",
    "    while True:\n",
    "        mother= daughter+diff\n",
    "        if are_reversed(daughter, mother):\n",
    "            count=count+1\n",
    "            if count==6:\n",
    "                print(daughter,\"     \",mother)\n",
    "        if mother > 100:\n",
    "            return\n",
    "        daughter=daughter+1\n",
    "\n",
    "\n",
    "def check_ages():\n",
    "    diff = 13\n",
    "    while diff < 70:\n",
    "        n = num_instances(diff)\n",
    "        if n == 8:\n",
    "            list_instance(diff)\n",
    "        diff = diff + 1 \n",
    "\n",
    "check_ages()\n"
   ]
  },
Prof. Dr. Robert Jäschke's avatar
Prof. Dr. Robert Jäschke committed
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "![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). Klicken Sie dazu oben links auf das Disketten-Icon 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": [
Prof. Dr. Robert Jäschke's avatar
Prof. Dr. Robert Jäschke committed
    "![Smiley](https://upload.wikimedia.org/wikipedia/commons/thumb/7/79/Face-smile.svg/48px-Face-smile.svg.png)\n",
Prof. Dr. Robert Jäschke's avatar
Prof. Dr. Robert Jäschke committed
    "\n",
Prof. Dr. Robert Jäschke's avatar
Prof. Dr. Robert Jäschke committed
    "Herzlichen Glückwunsch! Sie haben das 9. Kapitel geschafft. Weiter geht es in [10: Listen](seminar10.ipynb)."
Prof. Dr. Robert Jäschke's avatar
Prof. Dr. Robert Jäschke committed
   ]
  }
 ],
 "metadata": {
  "language_info": {
   "name": "python",
   "pygments_lexer": "ipython3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}