{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "40366dea-bec8-4128-b8e9-a7c10536a613",
   "metadata": {
    "nbgrader": {
     "grade": false,
     "grade_id": "cell-44b468fb46efb002",
     "locked": true,
     "schema_version": 3,
     "solution": false,
     "task": false
    }
   },
   "source": [
    "# 4. Programmierübung: NumPy\n",
    "\n",
    "<div style=\"display:flex;\">\n",
    "    <div style=\"text-align: left\">\n",
    "        Willkommen zur vierten Programmierübung Einführung in Python 3.\n",
    "    </div>\n",
    "    <img style=\"float: right; margin: 0px 15px 15px 0px\" src=\"https://www.python.org/static/img/python-logo-large.c36dccadd999.png?1576869008\" width=\"100\" />\n",
    "</div>\n",
    "\n",
    "Wenn Sie Fragen oder Verbesserungsvorschläge zum Inhalt oder Struktur der Notebooks haben, dann können sie eine E-Mail an Phil Keier ([p.keier@hbk-bs.de](mailto:p.keier@hbk-bs.de?subject=[SigSys]%20Feedback%20Programmierübung&amp)) oder Martin Le ([martin.le@tu-bs.de](mailto:martin.le@tu-bs.de?subject=[SigSys]%20Feedback%20Programmierübung&amp)) schreiben.\n",
    "\n",
    "Link zu einem Python Spickzettel: [hier](https://s3.amazonaws.com/assets.datacamp.com/blog_assets/PythonForDataScience.pdf)\n",
    "\n",
    "Der Großteil des Python-Tutorials stammt aus der Veranstaltung _Deep Learning Lab_ und von [www.python-kurs.eu](https://www.python-kurs.eu/python3_kurs.php) und wurde für _Signale und Systeme_, sowie _Einführung in die Programmierung für Nicht Informatiker_ angepasst.\n",
    "\n",
    "---"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "4d4eed4c-36ff-4643-bbc8-6c5440f73065",
   "metadata": {
    "nbgrader": {
     "grade": false,
     "grade_id": "cell-5ac025a1f69e3f31",
     "locked": true,
     "schema_version": 3,
     "solution": false,
     "task": false
    }
   },
   "source": [
    "# Was ist NumPy\n",
    "\n",
    "NumPy steht für *Numerical Python*, ist OpenSource und wird mittlerweile von nahezu jedem Python Entwickeler verwendet. Dabei ist das Core Feature von NumPy seine effiziente Implementierung eines n-dimensionales Arrays in C, welches in Python verwendet werden kann. Hinzu kommt eine Hülle an Funktionen wie effiziente Zufallsalgorithmen und mathematische Funktionen aus den unterschiedlichten Bereichen der Statistik und numerischen Berechnung, welche alle für NumPy Arrays optimiert sind. Im Folgenden wollen wir den Umgang mit NumPy Arrays lernen. \n",
    "\n",
    "__Für dieses Notebook schauen Sie bitte in die [NumPy Docs](https://numpy.org/doc/stable/reference/index.html)!!!__ Dort sind alle Funktionen beschrieben die wir hier bearbeiten und noch mehr!\n",
    "\n",
    "---"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ee26bbc0-d6a6-4721-b371-5cade59879ea",
   "metadata": {
    "nbgrader": {
     "grade": false,
     "grade_id": "cell-d2be4b14819d46e9",
     "locked": true,
     "schema_version": 3,
     "solution": false,
     "task": false
    }
   },
   "source": [
    "# Was ist Matplotlib\n",
    "\n",
    "Matplotlib ist eine Python Bibliothek zum (interaktiven) Visualisieren von Daten. Die Bibliothek integriert sich gut mit anderen viel benutzten Python Bibliotheken wie NumPy. Der Vorteil der Kombination mit Jupyter besteht in der direkten Ausgabe eines Plots auf dem Bildschirm.\n",
    "\n",
    "__Nutzen Sie für diese Aufgabe gerne die [Matplotlib Reference](https://matplotlib.org/stable/users/index.html)__\n",
    "\n",
    "---"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "8f6a28a6-9ef0-4f80-9432-80375cf3876b",
   "metadata": {
    "nbgrader": {
     "grade": false,
     "grade_id": "cell-b8d545ee5d6cabe7",
     "locked": true,
     "schema_version": 3,
     "solution": false,
     "task": false
    }
   },
   "source": [
    "Das gesamte Internet importiert NumPy mit dem Kürzel `np` & das pyplot Objekt mit `plt`.\n",
    "\n",
    "Um uns diesen ungeschriebenen Gesetz anzuschließen importieren wir in nächster Zelle NumPy als np:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "20dc6e2f-9b96-4f0c-85a8-8763e6722ce8",
   "metadata": {
    "nbgrader": {
     "grade": false,
     "grade_id": "cell-3d1fe74859052932",
     "locked": true,
     "schema_version": 3,
     "solution": false,
     "task": false
    }
   },
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "import matplotlib.pyplot as plt"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "57f719db-3269-49e2-acd2-a676911c0470",
   "metadata": {
    "nbgrader": {
     "grade": false,
     "grade_id": "cell-39e898b8ebe45728",
     "locked": true,
     "schema_version": 3,
     "solution": false,
     "task": false
    }
   },
   "source": [
    "---"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9e008318-4d2a-4244-ac91-63d7b8806491",
   "metadata": {
    "nbgrader": {
     "grade": false,
     "grade_id": "cell-b910cff04746aa1d",
     "locked": true,
     "schema_version": 3,
     "solution": false,
     "task": false
    }
   },
   "source": [
    "# Was ist ein Array?\n",
    "\n",
    "Ein Array ist eine kontinuierliche Datenstruktur. Dabei werden die Daten in Reihe im Arbeitsspeicher hinterlegt, vergleichbar mit der Python Liste.\n",
    "\n",
    "## Erstellen von Arrays\n",
    "\n",
    "Alle folgenden Beispiele finden Sie im [Beginners Guide](https://numpy.org/doc/stable/user/absolute_beginners.html).\n",
    "\n",
    "Für unser erstes Beispiel erstellen wir aus einer Python Liste ein [NumPy Array](https://numpy.org/doc/stable/reference/arrays.html)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "b44876d4-2376-4651-b489-9708a02f86bd",
   "metadata": {
    "nbgrader": {
     "grade": false,
     "grade_id": "cell-1adaa95f01483572",
     "locked": true,
     "schema_version": 3,
     "solution": false,
     "task": false
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([1, 2, 3, 4, 5])"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arr = np.array([1,2,3,4,5])\n",
    "arr"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a08e52ec-5148-4304-93da-064369cab9f8",
   "metadata": {
    "nbgrader": {
     "grade": false,
     "grade_id": "cell-ea5067ebbb1c99bc",
     "locked": true,
     "schema_version": 3,
     "solution": false,
     "task": false
    }
   },
   "source": [
    "Der Zugriff auf Elemente des Arrays erfolgt analog zu Pythons Liste:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "68679f58-495f-483e-a394-0cb3016dd488",
   "metadata": {
    "nbgrader": {
     "grade": false,
     "grade_id": "cell-cb73ac88e9fa5d93",
     "locked": true,
     "schema_version": 3,
     "solution": false,
     "task": false
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "np.int64(5)"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arr[4]"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "3f9f7d47-b9d6-47b2-85e3-bdb015cc72d8",
   "metadata": {
    "nbgrader": {
     "grade": false,
     "grade_id": "cell-ec0a814ecfda8547",
     "locked": true,
     "schema_version": 3,
     "solution": false,
     "task": false
    }
   },
   "source": [
    "NumPy Arrays sind n-dimensional, heißt Arrays in NumPy können aus geschachtelten Listen bestehen. Beispiel für ein 2-Dimensionales Array:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "04452b0d-ca06-4dd8-9b6a-47aa00b38011",
   "metadata": {
    "nbgrader": {
     "grade": false,
     "grade_id": "cell-ff72c8352626ac82",
     "locked": true,
     "schema_version": 3,
     "solution": false,
     "task": false
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[1, 2, 3, 4, 5],\n",
       "       [6, 7, 8, 9, 8],\n",
       "       [7, 6, 5, 4, 3]])"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arr = np.array(\n",
    "    [\n",
    "        [1,2,3,4,5],\n",
    "        [6,7,8,9,8],\n",
    "        [7,6,5,4,3],\n",
    "    ])\n",
    "arr"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a4d10e8e-6856-4f14-a18c-b4d0d4cfee96",
   "metadata": {
    "nbgrader": {
     "grade": false,
     "grade_id": "cell-413fcd639649e39a",
     "locked": true,
     "schema_version": 3,
     "solution": false,
     "task": false
    }
   },
   "source": [
    "Diese Datenstruktur wird Allgemein auch Matrix gennant. Der Zugriff auf ein Element einer Matrix folgt nach dem Prinzip \"Spalte->Reihe\". Die erste Spalte ist demnach:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "9539a428-4cb1-426e-9ff0-bb10f9e5dd75",
   "metadata": {
    "nbgrader": {
     "grade": false,
     "grade_id": "cell-c7a59ce293c8e402",
     "locked": true,
     "schema_version": 3,
     "solution": false,
     "task": false
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([1, 2, 3, 4, 5])"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arr[0]"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "eb7b82f2-c8ba-4336-b3f9-505d89010e3b",
   "metadata": {
    "nbgrader": {
     "grade": false,
     "grade_id": "cell-fb0cf79581b45e5e",
     "locked": true,
     "schema_version": 3,
     "solution": false,
     "task": false
    }
   },
   "source": [
    "Der Zugriff auf ein einzelnes Element erfolgt dann Analog:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "c940ad92-43b4-4783-be50-687b2be51541",
   "metadata": {
    "nbgrader": {
     "grade": false,
     "grade_id": "cell-2f107dba2b747fbb",
     "locked": true,
     "schema_version": 3,
     "solution": false,
     "task": false
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "np.int64(5)"
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arr[0][4]"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "37cd7d69-9a6f-4136-95bc-3470ea512f45",
   "metadata": {
    "nbgrader": {
     "grade": false,
     "grade_id": "cell-617d777cf3216789",
     "locked": true,
     "schema_version": 3,
     "solution": false,
     "task": false
    }
   },
   "source": [
    "Oder mit NumPys eigener Syntax `arr[<spalte>, <reihe>]`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "id": "630ba433-c2e5-4faf-980a-ae34e57d470a",
   "metadata": {
    "nbgrader": {
     "grade": false,
     "grade_id": "cell-3e1e7323c57088ad",
     "locked": true,
     "schema_version": 3,
     "solution": false,
     "task": false
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "np.int64(5)"
      ]
     },
     "execution_count": 13,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arr[0, 4]"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "2b1ad36a-eeec-410f-82f1-768bb134accd",
   "metadata": {
    "nbgrader": {
     "grade": false,
     "grade_id": "cell-62701cdd045c7c4c",
     "locked": true,
     "schema_version": 3,
     "solution": false,
     "task": false
    }
   },
   "source": [
    "## Platzreservierung\n",
    "\n",
    "Falls bekannt ist, wie viele Elemente ein Array im späteren Programmverlauf haben soll, bietet einem NumPy die Möglichkeit diesen Platz im Speicher gewissermaßen zu reservieren.\n",
    "Hierfür gibt es einige Funktionen.\n",
    "\n",
    "### Ones\n",
    "\n",
    "1 Dimensionales NumPy Array der Größe 10 mit 1 gefüllt:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "id": "1da0eee9-4aa6-4a2e-91ab-7f9110ba5961",
   "metadata": {
    "nbgrader": {
     "grade": false,
     "grade_id": "cell-d3aeedf2a30a9b30",
     "locked": true,
     "schema_version": 3,
     "solution": false,
     "task": false
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([1., 1., 1., 1., 1., 1., 1., 1., 1., 1.])"
      ]
     },
     "execution_count": 14,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.ones(10)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "dec9de1d-0415-4ce1-8182-cdf5f50cb8cd",
   "metadata": {
    "nbgrader": {
     "grade": false,
     "grade_id": "cell-6e683d4afe40b7ff",
     "locked": true,
     "schema_version": 3,
     "solution": false,
     "task": false
    }
   },
   "source": [
    "### Zeros\n",
    "\n",
    "Analog dazu mit 0 gefüllt:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "id": "22b81912-0f2b-4ea6-b085-938e8f835daa",
   "metadata": {
    "nbgrader": {
     "grade": false,
     "grade_id": "cell-450f40270416767a",
     "locked": true,
     "schema_version": 3,
     "solution": false,
     "task": false
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([0., 0., 0., 0., 0., 0., 0., 0., 0., 0.])"
      ]
     },
     "execution_count": 15,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.zeros(10)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "794bfa8c-2c62-4d13-b2cf-65165b9f66d8",
   "metadata": {
    "nbgrader": {
     "grade": false,
     "grade_id": "cell-ef1e55c1165e2de5",
     "locked": true,
     "schema_version": 3,
     "solution": false,
     "task": false
    }
   },
   "source": [
    "### Empty\n",
    "\n",
    "Analog mit zufälligen Werten (bzw. Werte, die bereits an der Speicherstelle waren, meistens 0):"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "id": "5bede573-fda6-4065-bc05-2238cdcd7dc5",
   "metadata": {
    "nbgrader": {
     "grade": false,
     "grade_id": "cell-896e48c096be9062",
     "locked": true,
     "schema_version": 3,
     "solution": false,
     "task": false
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([0., 0., 0., 0., 0., 0., 0., 0., 0., 0.])"
      ]
     },
     "execution_count": 16,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.empty(10)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f8543f2c-37a1-45c7-9e6f-387126d2e0c4",
   "metadata": {
    "nbgrader": {
     "grade": false,
     "grade_id": "cell-947ed3289815694d",
     "locked": true,
     "schema_version": 3,
     "solution": false,
     "task": false
    }
   },
   "source": [
    "### Arange\n",
    "\n",
    "Analog dazu die `arange` Funktion (die Paramter sind die selben wie bei der Python `range` Funktion):"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "id": "57a83964-bf61-4db8-8358-d415d92e49bb",
   "metadata": {
    "nbgrader": {
     "grade": false,
     "grade_id": "cell-5329dd48e6129b33",
     "locked": true,
     "schema_version": 3,
     "solution": false,
     "task": false
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])"
      ]
     },
     "execution_count": 17,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.arange(10)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "14461c48-a442-41d8-a9dc-bd411beb6b14",
   "metadata": {
    "nbgrader": {
     "grade": false,
     "grade_id": "cell-299417e99c41e05f",
     "locked": true,
     "schema_version": 3,
     "solution": false,
     "task": false
    }
   },
   "source": [
    "### Linspace\n",
    "\n",
    "Um später mit Matplotlib besser arbeiten zu können hat Numpy die [linspace](https://numpy.org/doc/stable/reference/generated/numpy.linspace.html#numpy-linspace) Funktion. Welche die Werte von einem Start und End Punkt Linear berechnet, zusätzlich kann noch die Anzahl der Elemete mit dem `num` Parameter angegeben werden:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "id": "1defeafc-b02a-4e84-a1d3-30878fc69071",
   "metadata": {
    "nbgrader": {
     "grade": false,
     "grade_id": "cell-036bdec449f35dc5",
     "locked": true,
     "schema_version": 3,
     "solution": false,
     "task": false
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([ 0. ,  2.5,  5. ,  7.5, 10. ])"
      ]
     },
     "execution_count": 18,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.linspace(0,10, num=5)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "id": "72416872-9e66-4ff8-88ad-9244b6e67827",
   "metadata": {
    "nbgrader": {
     "grade": false,
     "grade_id": "cell-9ac9d3f215fc0237",
     "locked": true,
     "schema_version": 3,
     "solution": false,
     "task": false
    },
    "scrolled": true
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([ 400.        ,  466.66666667,  533.33333333,  600.        ,\n",
       "        666.66666667,  733.33333333,  800.        ,  866.66666667,\n",
       "        933.33333333, 1000.        ])"
      ]
     },
     "execution_count": 19,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.linspace(400, 1000, num=10)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "53cd285e-fe83-4c8b-9ac5-ee65db57107d",
   "metadata": {
    "nbgrader": {
     "grade": false,
     "grade_id": "cell-522faf35a6c76300",
     "locked": true,
     "schema_version": 3,
     "solution": false,
     "task": false
    }
   },
   "source": [
    "## Aufgabe\n",
    "\n",
    "*1 Punkt*\n",
    "\n",
    "Erstellen Sie ein NumPy Array, welches 6 Nullen reserviert und speichern Sie das Array in der Variablen `only_zeros`. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "id": "8f64d227-64cc-4b26-b076-b9ea3db3d798",
   "metadata": {
    "nbgrader": {
     "grade": false,
     "grade_id": "cell-176f6befb5f45c58",
     "locked": false,
     "schema_version": 3,
     "solution": true,
     "task": false
    }
   },
   "outputs": [],
   "source": [
    "only_zeros = None\n",
    "# BEGIN SOLUTION\n",
    "only_zeros = np.zeros(6)\n",
    "# END SOLUTION"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "id": "ca435e4c-e686-4e64-b796-6f6884708ce3",
   "metadata": {
    "nbgrader": {
     "grade": true,
     "grade_id": "cell-8ad1e3a41d459d55",
     "locked": true,
     "points": 1,
     "schema_version": 3,
     "solution": false,
     "task": false
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[0. 0. 0. 0. 0. 0.]\n"
     ]
    }
   ],
   "source": [
    "print(only_zeros)\n",
    "\n",
    "# Check i length is correct\n",
    "assert len(only_zeros) == 6\n",
    "\n",
    "# Check if every element contains a zero\n",
    "for el in only_zeros:\n",
    "    assert el == 0"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "07012ea7-35b0-4e24-83d4-5732853761bd",
   "metadata": {
    "nbgrader": {
     "grade": false,
     "grade_id": "cell-0108e88f3110e70f",
     "locked": true,
     "schema_version": 3,
     "solution": false,
     "task": false
    }
   },
   "source": [
    "## Aufgabe\n",
    "\n",
    "*1 Punkt*\n",
    "\n",
    "Erstellen Sie ein NumPy Array mit 11 Elementen mittels `linspace`. Dabei soll der Startwert = -4 und der Endwert = 17 sein. Speichern Sie das Ergbniss in der Variablen `x_scale`. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "id": "41f68397-24db-44d8-a2cf-4e7aec431b57",
   "metadata": {
    "nbgrader": {
     "grade": false,
     "grade_id": "cell-3231ee937ba8ab7a",
     "locked": false,
     "schema_version": 3,
     "solution": true,
     "task": false
    }
   },
   "outputs": [],
   "source": [
    "x_scale = None\n",
    "# BEGIN SOLUTION\n",
    "x_scale = np.linspace(-4, 17, num=11)\n",
    "# END SOLUTION"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "id": "2439440f-f8f6-4ee1-ae2b-3bca19992675",
   "metadata": {
    "nbgrader": {
     "grade": true,
     "grade_id": "cell-e5d66ef7599f7b91",
     "locked": true,
     "points": 1,
     "schema_version": 3,
     "solution": false,
     "task": false
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[-4.  -1.9  0.2  2.3  4.4  6.5  8.6 10.7 12.8 14.9 17. ]\n"
     ]
    }
   ],
   "source": [
    "# Hier werden ihre Lösungen getestet\n",
    "print(x_scale)\n",
    "\n",
    "# Check if length is correct\n",
    "assert len(x_scale) == 11\n",
    "### BEGIN HIDDEN TESTS\n",
    "s = np.linspace(-4, 17, num=11)\n",
    "### END HIDDEN TESTS\n",
    "\n",
    "# Test if elements are correct\n",
    "for el1, el2 in zip(x_scale, s):\n",
    "    assert el1 == el2"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "dfdb02ea-44b4-4368-9b46-235ca1dca667",
   "metadata": {
    "nbgrader": {
     "grade": false,
     "grade_id": "cell-5d8e19cc802e33a4",
     "locked": true,
     "schema_version": 3,
     "solution": false,
     "task": false
    }
   },
   "source": [
    "---"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9276ba6e-30a0-4803-ace7-14147cd214ee",
   "metadata": {
    "nbgrader": {
     "grade": false,
     "grade_id": "cell-30de8243b097dfdc",
     "locked": true,
     "schema_version": 3,
     "solution": false,
     "task": false
    }
   },
   "source": [
    "# First plot\n",
    "\n",
    "Wie dem [Getting Started](https://matplotlib.org/stable/users/getting_started/index.html#getting-started) Beispiel zu entnehmen, wollen wir einmal die Sinus Funktion plotten.\n",
    "\n",
    "Dazu brauchen wir zwei Attribute:\n",
    "1. Die x-Skala - Dies kann die Länge eines Datensets sein, oder ein allgemeiner Linespace. Auf jeden Fall eine Liste bzw. Array.\n",
    "2. Die y-Skala - Im Allgemeinen die Werte eines zu plottenden Datensets. Auf jeden Fall auch eine Liste bzw. Array.\n",
    "\n",
    "Plotten wir im Folgenden die Sinus Funktion. Eine der schönen Eigenschaften der Sinus Funktion ist, dass diese sich nach dem Intervall $[0...2\\pi]$ wiederholt. Daher enthält die x-Skala einen linespace von $[0...2\\pi]$. Als Wert für $\\pi$ wird die NumPy Konstante [np.pi](https://numpy.org/doc/stable/reference/constants.html#numpy.pi) verwendet.\n",
    "\n",
    "Auf der y-Skala plotten wir im folgenden das zuvor berechnete Array mit den Sinus Werten. Die Hierfür verwendete Funktion ist [np.sin](https://numpy.org/doc/stable/reference/generated/numpy.sin.html). \n",
    "\n",
    "Das `plt` Objekt hat mehrere Funktionen die in einer bestimmten Reihenfolge aufgerufen werden müssen. Dabei können zuerst mehrere plots mit [plt.plot](https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot.plot.html) definiert werden. Zum Schluss wird zur Ausgabe [plt.show](https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot.show.html) aufgerufen."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "63f7bd92-7a44-4fe0-b03e-d13b1374be1c",
   "metadata": {
    "nbgrader": {
     "grade": false,
     "grade_id": "cell-2eaf77b2d04abff1",
     "locked": true,
     "schema_version": 3,
     "solution": false,
     "task": false
    }
   },
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 30716 characters]",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "x = np.linspace(0, 2*np.pi, num=200) # Definiere einen linearen Bereich von 0 bis 2pi\n",
    "y = np.sin(x) # Berechne den Sinus mit den Werten von x\n",
    "\n",
    "plt.plot(x, y) # Setze für die X-Achse x und für die Y-Achse y\n",
    "plt.show() # Zeige den Plot"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9dc5f266-8956-431d-aa8e-cb33afc8fc34",
   "metadata": {
    "nbgrader": {
     "grade": false,
     "grade_id": "cell-1dd3b7172bc39b59",
     "locked": true,
     "schema_version": 3,
     "solution": false,
     "task": false
    }
   },
   "source": [
    "# Zwei Funktionen \n",
    "\n",
    "Wie bereits zuvor erwähnt lässt sich `plt.plot` mehr als einmal aufrufen. Wollen wir im folgenden den Kosinus mittels [np.cos](https://numpy.org/doc/stable/reference/generated/numpy.cos.html) dazu plotten. Dafür werden die Werte aus dem bereits definierten x wiederverwendet. Die Variabelen `y1 = np.sin(x)` & `y2 = np.cos(x)` enthälten die jeweiligen y werte. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "7f63b65d-875d-4ee2-998b-fc6f39935ab0",
   "metadata": {
    "nbgrader": {
     "grade": false,
     "grade_id": "cell-2e9cc2ce95f1e20e",
     "locked": true,
     "schema_version": 3,
     "solution": false,
     "task": false
    }
   },
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 43060 characters]",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "y1 = np.sin(x) # Sinus Werte mittels x berechnen\n",
    "y2 = np.cos(x) # Kosinus Werte mittels x berechnen\n",
    "\n",
    "plt.plot(x, y1) # Plotte den Sinus\n",
    "plt.plot(x, y2) # Plotte den Kosinus\n",
    "\n",
    "plt.show() # Zeige das Diagramm"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c1e5749a-8f46-41ae-817a-19e5103a9a7a",
   "metadata": {
    "nbgrader": {
     "grade": false,
     "grade_id": "cell-d1d50ca1d203ac29",
     "locked": true,
     "schema_version": 3,
     "solution": false,
     "task": false
    }
   },
   "source": [
    "## Aufgabe - Erster eigener Plot Square Root\n",
    "\n",
    "Analog zu voheriger Erklärung plotten Sie im folgenden die Funktion Square Root, Mathematisch definiert als $f(x) = \\sqrt x; \\quad x \\geq 0$.\n",
    "\n",
    "Gehen Sie dabei wie folgt vor:\n",
    "1. Definieren Sie einen **geeigneten** [Linespace](https://numpy.org/doc/stable/reference/generated/numpy.linspace.html#numpy-linspace) für die Zahlenraum 0...100. (Tipp: Achten Sie auf die Definition! Die Wurzel ist nur für positive Zahlen definiert.)\n",
    "2. Berechnen Sie mittels der Funktion [np.sqrt](https://numpy.org/doc/stable/reference/generated/numpy.sqrt.html#numpy.sqrt) die Werte für die Wurzel.\n",
    "3. Plotten Sie das Ergebnis"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 36,
   "id": "c36ff699-9c30-448c-9d97-0a75e00888fd",
   "metadata": {
    "nbgrader": {
     "grade": true,
     "grade_id": "cell-bae73642cf0a866a",
     "locked": false,
     "points": 3,
     "schema_version": 3,
     "solution": true,
     "task": false
    }
   },
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 19556 characters]",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# BEGIN SOLUTION\n",
    "xs = np.linspace(0, 100, num=200)\n",
    "ys = np.sqrt(xs)\n",
    "plt.plot(xs, ys)\n",
    "plt.show()\n",
    "# END SOLUTION"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a98f7855-0bca-4769-aaf5-fa27f0404b23",
   "metadata": {
    "nbgrader": {
     "grade": false,
     "grade_id": "cell-998243908406c7d4",
     "locked": true,
     "schema_version": 3,
     "solution": false,
     "task": false
    }
   },
   "source": [
    "# Styling\n",
    "\n",
    "Da bei mehreren Plots der Überblick schnell verloren geht, beschäftigen wir uns im folgenden mit dem Styling. Dabei gehen wir im Schnelldurchlauf durch alle Parameter.\n",
    "\n",
    "Die Grundlage für alle folgenden Plots werden in der nächsten Zelle gesetzt."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 37,
   "id": "dd074404-20be-450e-a187-d992c9d804cf",
   "metadata": {
    "nbgrader": {
     "grade": false,
     "grade_id": "cell-a86ddac229c0bbbb",
     "locked": true,
     "schema_version": 3,
     "solution": false,
     "task": false
    }
   },
   "outputs": [],
   "source": [
    "x = np.linspace(0, 2*np.pi, num=200)\n",
    "s = np.sin(x)\n",
    "c = np.cos(x)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "7e541a27-5fb0-48a5-98a6-175842a59f31",
   "metadata": {
    "nbgrader": {
     "grade": false,
     "grade_id": "cell-e27c575962048d7b",
     "locked": true,
     "schema_version": 3,
     "solution": false,
     "task": false
    }
   },
   "source": [
    "## Farbe ändern\n",
    "\n",
    "Die Standard Farbe für den ersten Plot ist immer Blau. Um die Farbe zu verändern wird `plt.plot` der Parameter `color` übergeben. Dieser erwartet einen String. Für eine genauere Erläuterung, lesen Sie die Dokumentation zu [Specifying color](https://matplotlib.org/stable/users/explain/colors/colors.html). Für dieses Notebook werden die Beispiele mit den \"Single Character Shorthands\" (Aus der Dokumentation zu entnehmen) ausgestattet.\n",
    "\n",
    "Plotten wir den Sinus nun in Rot:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 38,
   "id": "01d03aa6-22c3-4843-8cf0-33155b78740e",
   "metadata": {
    "nbgrader": {
     "grade": false,
     "grade_id": "cell-1ec79feac73af81f",
     "locked": true,
     "schema_version": 3,
     "solution": false,
     "task": false
    }
   },
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 27324 characters]",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "plt.plot(x, s, color='r') # Plot mit der Farbe Rot\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e229b04c-8688-4457-982c-7a3f27c4254c",
   "metadata": {
    "nbgrader": {
     "grade": false,
     "grade_id": "cell-6d559d4604922bd9",
     "locked": true,
     "schema_version": 3,
     "solution": false,
     "task": false
    }
   },
   "source": [
    "## Titel für den Plot setzen\n",
    "\n",
    "Dafür wird [plt.title](https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot.title.html) der Paramter als String übergeben:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 39,
   "id": "ca46e07c-2f69-40cb-b58b-5278e13a048e",
   "metadata": {
    "nbgrader": {
     "grade": false,
     "grade_id": "cell-106786a4fca81b67",
     "locked": true,
     "schema_version": 3,
     "solution": false,
     "task": false
    }
   },
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 32904 characters]",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "plt.plot(x, s)\n",
    "plt.title(\"Sinus Plot\") # Titel Setzen\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6d0a0200-ac39-467c-a3e8-66e6a3ba3818",
   "metadata": {
    "nbgrader": {
     "grade": false,
     "grade_id": "cell-8d7bed3592e18530",
     "locked": true,
     "schema_version": 3,
     "solution": false,
     "task": false
    }
   },
   "source": [
    "## Legende und Labels\n",
    "\n",
    "Um eine Legende anzuzeigen, muss vor `plt.show` die Funktion [plt.legend](https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot.legend.html) aufgerufen werden. Damit dies Wirkung zeigt, muss jeder Plot mit dem Parameter `label` (als String) ausgezeichnet werden. Plotten wir im Folgenden den Sinus und Kosinus mit entsprechenden Labels."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 40,
   "id": "4d58a327-a11e-408b-a998-ef03c7cfaf87",
   "metadata": {
    "nbgrader": {
     "grade": false,
     "grade_id": "cell-b1d037b9a275622c",
     "locked": true,
     "schema_version": 3,
     "solution": false,
     "task": false
    }
   },
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 45860 characters]",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "plt.plot(x, s, label=\"Sinus\") # Plotte Sinus mit label Sinus\n",
    "plt.plot(x, c, label=\"Kosinus\") # Plotte Kosinus mit label Kosinus\n",
    "plt.legend() # Füge die Legende ein\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "fb03ce2f-5639-402a-9b32-0b351113b5d6",
   "metadata": {
    "nbgrader": {
     "grade": false,
     "grade_id": "cell-63bbc82ff5e6892a",
     "locked": true,
     "schema_version": 3,
     "solution": false,
     "task": false
    }
   },
   "source": [
    "## Linestyle\n",
    "\n",
    "Die letze wichtige Eigenschaft ist das Setzen eines Linestyles. Dazu wird `plt.plot` der Parameter `linestyle` als String übergeben. Entnehmen Sie die verschiedenen Linestyles bitte der Dokumentation zu [Linestyles](https://matplotlib.org/stable/gallery/lines_bars_and_markers/linestyles.html).\n",
    "\n",
    "Sinus als `dashed` line:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 47,
   "id": "90be449a-1d18-416f-b22b-782081d1b007",
   "metadata": {
    "nbgrader": {
     "grade": false,
     "grade_id": "cell-402e40ea2ceafc35",
     "locked": true,
     "schema_version": 3,
     "solution": false,
     "task": false
    }
   },
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 29272 characters]",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "plt.plot(x, s, linestyle=\"dashed\")\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b465a6e5-06ab-4fc0-8238-f4f05593a9d1",
   "metadata": {
    "nbgrader": {
     "grade": false,
     "grade_id": "cell-88e04ff7645c08cd",
     "locked": true,
     "schema_version": 3,
     "solution": false,
     "task": false
    }
   },
   "source": [
    "## Aufgabe - Multiplot\n",
    "\n",
    "*8 Punkte*\n",
    "\n",
    "In der nächsten Aufgabe wollen wir gleich zwei Funktionen plotten. $f(x) = \\sqrt x; x \\geq 0$ und $g(x) = x^2$.\n",
    "\n",
    "Gehen Sie dabei wie folgt vor:\n",
    "1. Definieren Sie einen geeigneten [Linespace](https://numpy.org/doc/stable/reference/generated/numpy.linspace.html#numpy-linspace) für die Zahlenraum 0...3. (Tipp: Achten Sie auf die Definition! Die Wurzel ist nur für positive Zahlen definiert.)\n",
    "2. Berechnen Sie mittels der Funktion [np.sqrt](https://numpy.org/doc/stable/reference/generated/numpy.sqrt.html#numpy.sqrt) die Werte für die Wurzel.\n",
    "3. Berechnen Sie mittels der Funktion [np.square](https://numpy.org/doc/stable/reference/generated/numpy.square.html#numpy-square) die Werte für die Quadratzahlen\n",
    "4. Geben Sie den beiden Plots die Farben Grün & Rot. Nutzen Sie gerne die [Color Shorthands](https://matplotlib.org/stable/users/explain/colors/colors.html) aus der Dokumentation.\n",
    "5. Plotten Sie die Square Funktion mit dem Linestyle `dashdot`, wie der Dokumentation zu entnehmen [Linestyles](https://matplotlib.org/stable/gallery/lines_bars_and_markers/linestyles.html)\n",
    "6. Geben Sie den beiden Plots angemessene Labels.\n",
    "7. Fügen Sie die Legende hinzu.\n",
    "8. Plotten Sie das Ergebnis."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 48,
   "id": "41c07973-1717-48f1-94a5-c6930b0089ec",
   "metadata": {
    "nbgrader": {
     "grade": true,
     "grade_id": "cell-6bb6ab1d60fffde5",
     "locked": false,
     "points": 8,
     "schema_version": 3,
     "solution": true,
     "task": false
    }
   },
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 26372 characters]",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# BEGIN SOLUTION\n",
    "xt = np.linspace(0, 3, num=200)\n",
    "sqrt = np.sqrt(xt)\n",
    "square = np.square(xt)\n",
    "\n",
    "plt.plot(xt, sqrt, color='r', label=\"Square Root\")\n",
    "plt.plot(xt, square, color='g', label=\"Square Function\", linestyle=\"dashdot\")\n",
    "plt.legend()\n",
    "plt.show()\n",
    "# END SOLUTION"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d33d372a-ed48-4a31-a1fc-4b325e910d27",
   "metadata": {
    "nbgrader": {
     "grade": false,
     "grade_id": "cell-6d0019ce99d7aacb",
     "locked": true,
     "schema_version": 3,
     "solution": false,
     "task": false
    }
   },
   "source": [
    "---"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "7dd33f6a-1e5d-4c8f-8778-7820d13fa357",
   "metadata": {
    "nbgrader": {
     "grade": false,
     "grade_id": "cell-c7e6f6e837a94d41",
     "locked": true,
     "schema_version": 3,
     "solution": false,
     "task": false
    }
   },
   "source": [
    "# Warum Zufall?\n",
    "\n",
    "Für statistische Analysen jeglicher Art ist es wichtig seine Werkzeuge zu verstehen. Da nicht immer direkt ein Dataset vorliegt, oder dieses zurzeit noch im Erstellungsprozess ist, gibt es die Möglichkeit, die mathematischen und programmatischen Werzeuge zuvor an nachvollziebaren Zufallsdaten zu testen. Dabei wollen wir in dieser Übung lernen, was Zufall ist, wie Zufallsgeneratoren funktionieren und wie der Zufall auf bestimmte Art manipuliert werden kann.\n",
    "\n",
    "---"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6536feb0-7612-4bad-b797-3960ed3c832c",
   "metadata": {
    "nbgrader": {
     "grade": false,
     "grade_id": "cell-f387eeef09033ea3",
     "locked": true,
     "schema_version": 3,
     "solution": false,
     "task": false
    }
   },
   "source": [
    "# Was ist Zufall?\n",
    "\n",
    "Für Zufall gibt es viele Definitionen. Aber was genau ist Zufall? Das Würfeln eines Würfels zum Beispiel ist nicht zufällig. Jeder Würfelwurf kann vorhergesagt werden, vorausgesetzt, alle erforderlichen Daten sind vorhanden. Auch das Wetter ist nicht zufällig. Alle Ereignisse lassen sich vorhersagen, wenn genügend Daten vorhanden sind, das Problem ist nur, dass es nie genug Daten gibt. \n",
    "\n",
    "Jedes andere Beispiel kann mit der gleichen Argumentation als \"zufällig\" widerlegt werden. Daher werden diese Phänomene als pseudo-zufällig bezeichnet. \n",
    "\n",
    "Aber das nur am Rande. In der Physik gibt es ein Phänomen, das völlig unvorhersehbar ist. Wenn ein einzelnes Photon auf einen halbtransparenten Spiegel geschossen wird, kann __nie__ vorhergesagt werden, auf welchen der beiden Detektoren das Photon treffen wird. Diese Form der wirklich echten Zufalls wird von der Firma [ID Quntique](https://www.idquantique.com/random-number-generation/overview/) genutzt und verkauft Geräte, die das zuvor erklärte Quantenphänomen nutzen.\n",
    "\n",
    "Aber genug von der echten Koinzidenz und zurück zum Pseudo-Zufall und wie Computer damit umgehen.\n",
    "\n",
    "---"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "73c86ab1-9f06-4dc5-861b-6558e8315bb3",
   "metadata": {
    "nbgrader": {
     "grade": false,
     "grade_id": "cell-fde25777024719e0",
     "locked": true,
     "schema_version": 3,
     "solution": false,
     "task": false
    }
   },
   "source": [
    "# Pseudo Randomness\n",
    "\n",
    "Zufallszahlen in Computern werden über Formeln berechnet. Einer dieser Generatoren ist der _Linear Congruent Generator (LCG)_, dessen mathematische Grundlage leicht verdaulich ist.\n",
    "\n",
    "$$ X_{n+1} = (aX_n + c) \\;mod\\; m; \\quad n \\geq 0 $$\n",
    "\n",
    "Wenn $ c = 0 $ dann nennt man den Generator auch _Multiplicative Congruent Generator (MCG)_.\n",
    "\n",
    "Die Werte haben folgenden Nutzen in der Funktion:\n",
    "\n",
    "- $X_n$ ist der Startwert oder seed\n",
    "- $X_{n+1}$ ist der Folgewert der im nächsten Schritt für $X_n$ eingesetzt wird\n",
    "- $a$ ist der Vorfaktor vom Startwert. Dieser wird skaliert, deshalb wird er Skalar gennant\n",
    "- $c$ ist das hinzuaddierte Offset\n",
    "- $m$ ist der Restklassenring oder auch Modulus genannt"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "39b18b10-a831-4fbe-a50b-d8177108bca1",
   "metadata": {
    "nbgrader": {
     "grade": false,
     "grade_id": "cell-a1c6ad2b24a97f6b",
     "locked": true,
     "schema_version": 3,
     "solution": false,
     "task": false
    }
   },
   "source": [
    "## Aufgabe\n",
    "\n",
    "*6 Punkte*\n",
    "\n",
    "Schreibe einen _Linear Congruent Generator_ mit dem funktionsnamen `lcg`.\n",
    "\n",
    "- Nutze die oben gegebene Definition\n",
    "- Prüfe auch, das Werte nicht verwendet werden dürfen (Bsp. $n \\geq 0$)\n",
    "- `lcg` muss ein unendlicher Generator sein"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "id": "224134b7-6ab5-4438-ad46-6cb77261680c",
   "metadata": {
    "nbgrader": {
     "grade": false,
     "grade_id": "cell-d5c7ad13eb813b34",
     "locked": false,
     "schema_version": 3,
     "solution": true,
     "task": false
    }
   },
   "outputs": [],
   "source": [
    "# BEGIN SOLUTION\n",
    "def lcg(seed: int, scalar: int, modulus: int, offset: int) -> int:\n",
    "    ''' \n",
    "    Linear Congruential Generators\n",
    "\n",
    "    X(n+1) = (a X(n) + c) mod m; n >= 0\n",
    "\n",
    "    m > 0; \n",
    "    0 <= a < m;\n",
    "    c > 0; a > 0\n",
    "\n",
    "    '''\n",
    "    assert modulus > 0, \"Modulus must be greater than 0\"\n",
    "    assert 0 <= scalar and scalar < modulus, \"Scalar must be in range 0 <= a < m\"\n",
    "\n",
    "    while seed > 1:\n",
    "        seed = (scalar*seed+offset) % modulus\n",
    "        assert seed >= 0\n",
    "        yield seed\n",
    "# END SOLUTION"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 36,
   "id": "853a70eb-7dd1-43b5-af99-ed1b3126846c",
   "metadata": {
    "nbgrader": {
     "grade": true,
     "grade_id": "cell-35fbf31fbee439df",
     "locked": true,
     "points": 6,
     "schema_version": 3,
     "solution": false,
     "task": false
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Lcg using Cocktailshaker Numbers: 3089810780120156248\n",
      "Correct should be: 3089810780120156248\n",
      "\n",
      "Lcg using Cocktailshaker Numbers: 8356396685252565260\n",
      "Correct should be: 8356396685252565260\n",
      "\n",
      "Lcg using Cocktailshaker Numbers: 1921117399837525548\n",
      "Correct should be: 1921117399837525548\n",
      "\n",
      "Lcg using Cocktailshaker Numbers: 14806858147081821235\n",
      "Correct should be: 14806858147081821235\n",
      "\n",
      "Lcg using Cocktailshaker Numbers: 2557599628047639428\n",
      "Correct should be: 2557599628047639428\n",
      "\n",
      "Lcg using Cocktailshaker Numbers: 16453652254840064460\n",
      "Correct should be: 16453652254840064460\n",
      "\n",
      "Lcg using Cocktailshaker Numbers: 15995401842808378843\n",
      "Correct should be: 15995401842808378843\n",
      "\n",
      "Lcg using Cocktailshaker Numbers: 681272290641816305\n",
      "Correct should be: 681272290641816305\n",
      "\n",
      "Lcg using Cocktailshaker Numbers: 10955466795170118648\n",
      "Correct should be: 10955466795170118648\n",
      "\n",
      "Lcg using Cocktailshaker Numbers: 13714992071537968180\n",
      "Correct should be: 13714992071537968180\n",
      "\n"
     ]
    }
   ],
   "source": [
    "# Hier werden ihre Lösungen getestet ...\n",
    "\n",
    "# Check if lcg is a properly defined\n",
    "assert 'lcg' in dir()\n",
    "\n",
    "# Check if lcg is a generator\n",
    "import types\n",
    "assert isinstance(lcg(1,1,1,1), types.GeneratorType) # 1 Punkt\n",
    "\n",
    "# Using Cocktailshaker numbers :)\n",
    "s = lcg(3935559000370003845, 3203021881815356449, 2**64-1, 11742185885288659963)\n",
    "### BEGIN HIDDEN TESTS\n",
    "def lcg_test(seed: int, scalar: int, modulus: int, offset: int) -> int:\n",
    "    assert modulus > 0, \"Modulus must be greater than 0\"\n",
    "    assert 0 <= scalar and scalar < modulus, \"Scalar must be in range 0 <= a < m\"\n",
    "\n",
    "    while seed > 1:\n",
    "        seed = (scalar*seed+offset) % modulus\n",
    "        assert seed >= 0\n",
    "        yield seed\n",
    "\n",
    "t = lcg_test(3935559000370003845, 3203021881815356449, 2**64-1, 11742185885288659963)\n",
    "### END HIDDEN TESTS\n",
    "\n",
    "# Check if Generator works\n",
    "for _ in range(10):\n",
    "    stud = next(s)\n",
    "    instructor = next(t)\n",
    "    print(\"Lcg using Cocktailshaker Numbers:\", stud)\n",
    "    print(\"Correct should be:\", instructor, end='\\n\\n')\n",
    "    assert stud == instructor\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "8e516bd4-c203-4b11-9880-31eabba13c2e",
   "metadata": {
    "nbgrader": {
     "grade": false,
     "grade_id": "cell-88eadd4386332f26",
     "locked": true,
     "schema_version": 3,
     "solution": false,
     "task": false
    }
   },
   "source": [
    "---\n",
    "\n",
    "# A Family of Better Random Number Generators\n",
    "\n",
    "<div style=\"display: flex; justify-content: center;\">\n",
    "    <figure style=\"margin-top: 30px;\">\n",
    "        <img src=\"https://www.cs.hmc.edu/~oneill/images/melissa1.jpg\" width=\"300\">\n",
    "        <figcaption>\n",
    "            <p style=\"text-align:center; font-size: 20px;\">\n",
    "                <strong>Melissa E. O’Neill</strong>\n",
    "            </p>\n",
    "        </figcaption>\n",
    "    </figure>\n",
    "    <div style=\"margin-left: 40px; max-width: 60%; word-wrap:break-word;\">\n",
    "        <br/>\n",
    "            <p><i>Linear Congruent Generators</i> zeichnen sich durch ihre Stabilität und Geschwindigkeit als Hervorragende Zufallsgeneratoren. Doch 2014 gelang Melissa E. O'Neil ein neuer Durchbruch in der Konzeption von Pseudozufallsgeneratoren. Das Problem mit existierenden Zufallsgeneratoren ist entweder ihre Stabilität (Wie vorhersehbar die Zufallszahlen sind) oder ihre Geschwindigkeit (Wie lange der Zufallsgenerator braucht um die nächste Zufallszahl zu errechnen).</p>\n",
    "            <p>Ihr Durchbruch gelang, indem Sie die Vorteile eines <i>Linear Congruent Generators</i> mit dem eines <i>XorShift Generators</i> verband. Dadurch erreichte Sie nicht nur eine Normalverteilung in den generierten Zufallszahlen (und eine damit einhergende Stabilität), Sie hatte auch eine Family von schnellen einfachen Algorithmen entwickelt. Diese nennen sich <i>PCG - Permuted Congruential Generator</i>.</p>\n",
    "            <p>Die Implementierungsdetails lassen wir im nächsten Schritt aus, da diese nicht einfach in Python umzusetzen sind. Auf der Webseite <a href=\"https://www.pcg-random.org\" >pcg-random.org</a> lassen sich Implemtierungen für C & C++ finden. Als weiterführende Literatur ist <a href=\"https://www.pcg-random.org/pdf/hmc-cs-2014-0905.pdf\" >PCG: A Family of Simple Fast Space-Efficient Statistically Good Algorithms for Random Number Generation - Melissa E. O’Neill</a> als Literatur angegeben.</p>\n",
    "    </div>\n",
    "</div>\n",
    "\n",
    "Zum Glück hat _Numpy_ eine Implementierung des _PCG_. Diese findet sich unter [Numpy PCG64](https://numpy.org/doc/stable/reference/random/index.html)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "81959fe2-2f2f-4f57-9360-4e96dc0674ba",
   "metadata": {
    "nbgrader": {
     "grade": false,
     "grade_id": "cell-3cfb52b705a8d147",
     "locked": true,
     "schema_version": 3,
     "solution": false,
     "task": false
    }
   },
   "source": [
    "## Aufgabe\n",
    "\n",
    "*6 Punkte*\n",
    "\n",
    "Plote die Zufallszahlen eines _Permuted Congruent Generators_ mittels NumPy & MatPlotLib.\n",
    "\n",
    "- Gegeben ist der Anfangszustand des Generators.\n",
    "- Nutze die Dokumentation und rufe den `default_rng` aus dem `numpy.random` Modul, **20** mal auf speichere die Werte in der variablen `pcgs`. *(Tipp: Nutze ein NumPy Array)*\n",
    "- Sortiere im nächsten Schritt die in `pcgs` gespeicherten Werte und speichere diese in `pcgs_sorted`\n",
    "- Plotte sinnvoll beide Array. Gestalte den Plot angemessen."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 46,
   "id": "a2fbf6d5-9460-48bc-8183-b2afb9c5c186",
   "metadata": {
    "nbgrader": {
     "grade": true,
     "grade_id": "cell-9e88f0a0a4a77c47",
     "locked": false,
     "points": 3,
     "schema_version": 3,
     "solution": true,
     "task": false
    }
   },
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 51284 characters]",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "np.random.seed(42) # Setting a fixed start Value for the Generator\n",
    "pcgs: np.array = None\n",
    "pcgs_sorted: np.array = None\n",
    "\n",
    "# BEGIN SOLUTION\n",
    "gen = np.random.default_rng()\n",
    "pcgs = np.array([gen.random() for _ in range(20)])\n",
    "pcgs_sorted = np.sort(pcgs)\n",
    "\n",
    "# Plot\n",
    "plt.plot(np.arange(len(pcgs_sorted)), pcgs, color='r', label='PCGs')\n",
    "plt.plot(np.arange(len(pcgs_sorted)), pcgs_sorted, color='g', label='Sortierte PCGs')\n",
    "plt.title(\"PCG Random Numbers\")\n",
    "plt.legend()\n",
    "plt.show()\n",
    "# END SOLUTION"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 52,
   "id": "91d763ff-71ac-4940-9cf8-54ca7ea6b8ca",
   "metadata": {
    "nbgrader": {
     "grade": true,
     "grade_id": "cell-69197dfdc3015ec5",
     "locked": true,
     "points": 3,
     "schema_version": 3,
     "solution": false,
     "task": false
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "PCGs [0.83138478 0.46249136 0.44121926 0.42622691 0.42466013 0.3974171\n",
      " 0.98723244 0.5836077  0.7404793  0.53513345 0.7691253  0.52569606\n",
      " 0.87456503 0.78567245 0.44853762 0.95138405 0.65358711 0.33559832\n",
      " 0.19727424 0.39672796]\n",
      "Sorted PCGs [0.19727424 0.33559832 0.39672796 0.3974171  0.42466013 0.42622691\n",
      " 0.44121926 0.44853762 0.46249136 0.52569606 0.53513345 0.5836077\n",
      " 0.65358711 0.7404793  0.7691253  0.78567245 0.83138478 0.87456503\n",
      " 0.95138405 0.98723244]\n"
     ]
    }
   ],
   "source": [
    "# Hier werden ihre Lösungen getestet ...\n",
    "print(\"PCGs\", pcgs)\n",
    "print(\"Sorted PCGs\", pcgs_sorted)\n",
    "### BEGIN HIDDEN TESTS\n",
    "np.random.seed(42)\n",
    "test_gen = np.random.default_rng()\n",
    "test_pcgs = np.array([gen.random() for _ in range(20)])\n",
    "test_pcgs_sorted = np.sort(pcgs)\n",
    "### END HIDDEN TESTS\n",
    "\n",
    "# Check if pcgs are correctly generated\n",
    "assert test_pcgs.all() == pcgs.all()\n",
    "\n",
    "# Check if pcgs are correctly sorted\n",
    "assert test_pcgs_sorted.all() == pcgs_sorted.all()\n",
    "\n",
    "# Plot is manually checked"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9283cd7a-b8a6-4090-84c3-da70e61b2d2e",
   "metadata": {
    "nbgrader": {
     "grade": false,
     "grade_id": "cell-486bea96505ad0a6",
     "locked": true,
     "schema_version": 3,
     "solution": false,
     "task": false
    }
   },
   "source": [
    "---\n",
    "\n",
    "# Plot Types\n",
    "\n",
    "Im folgenden Kapitel beschäftigen wir uns mit verschiedensten Plot Typen."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "8fe0a0f7-a836-4279-bc7c-e993004f97aa",
   "metadata": {
    "nbgrader": {
     "grade": false,
     "grade_id": "cell-79e43d78c9874975",
     "locked": true,
     "schema_version": 3,
     "solution": false,
     "task": false
    }
   },
   "source": [
    "## Line Plots\n",
    "\n",
    "Line Plots haben wir im voherigen Kapitel bereits kennengelernt. Diese können mittels `plt.plot` augerufen werden.\n",
    "\n",
    "Beispiel Sinus:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 49,
   "id": "19b25d9b-0ee5-4eff-b290-8513f7948f50",
   "metadata": {
    "nbgrader": {
     "grade": false,
     "grade_id": "cell-b48b1eec8fe65537",
     "locked": true,
     "schema_version": 3,
     "solution": false,
     "task": false
    }
   },
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 30716 characters]",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "x = np.linspace(0, 2*np.pi, num=200)\n",
    "y = np.sin(x) \n",
    "\n",
    "plt.plot(x, y) \n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "10d13d03-03f5-44c4-a62b-b68bf8dcaaf9",
   "metadata": {
    "nbgrader": {
     "grade": false,
     "grade_id": "cell-d81b654168ec4bc8",
     "locked": true,
     "schema_version": 3,
     "solution": false,
     "task": false
    }
   },
   "source": [
    "## Bar Charts\n",
    "\n",
    "Beliebt sind Barcharts. Dazu werden aber mehrere Parameter benötigt, da einfache mathematische Funktionen bei dieser Art Plot keinen Sinn ergeben.\n",
    "\n",
    "Konsultieren wir dafür folgendes Beispiel:\n",
    "\n",
    "Wir wollen wissen wie viele Kinder an einer Grundschule in jeder Klassenstufe sind.\n",
    "Dazu benötigen wir 2 Listen.\n",
    "1. Die Klassenstufen\n",
    "2. Die Anzahl an Kinder in der Klassenstufe"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 52,
   "id": "06b54439-c88c-438a-9870-896280151491",
   "metadata": {
    "nbgrader": {
     "grade": false,
     "grade_id": "cell-3767e976a92e292a",
     "locked": true,
     "schema_version": 3,
     "solution": false,
     "task": false
    }
   },
   "outputs": [],
   "source": [
    "classes = [\"1. Klasse\", \"2. Klasse\", \"3. Klasse\", \"4. Klasse\"]\n",
    "kids = [42, 30, 26, 45]"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "55022635-12f7-4666-991b-e802ce67c9a5",
   "metadata": {
    "nbgrader": {
     "grade": false,
     "grade_id": "cell-a702a6b994c5809e",
     "locked": true,
     "schema_version": 3,
     "solution": false,
     "task": false
    }
   },
   "source": [
    "Plotten wir die Werte nun als Bar Chart mit der Funktion `plt.bar`:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 54,
   "id": "d73faeb6-2b83-495f-b246-2e4b4c6ff784",
   "metadata": {
    "nbgrader": {
     "grade": false,
     "grade_id": "cell-8c604c68ae96c752",
     "locked": true,
     "schema_version": 3,
     "solution": false,
     "task": false
    }
   },
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 10040 characters]",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "plt.bar(classes, kids)\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a641132d-cf1a-4e92-bdc3-55f5425b9388",
   "metadata": {
    "nbgrader": {
     "grade": false,
     "grade_id": "cell-c2444cb0f1af6626",
     "locked": true,
     "schema_version": 3,
     "solution": false,
     "task": false
    }
   },
   "source": [
    "### Bessere Datenrepresentation\n",
    "\n",
    "Da die Daten aus `classes` & `kids` miteinander eine Verbindung teilen wäre, die Repräsentation mittels Dictionary die klügere Wahl, um keine Fehler in den Plot zu bringen.\n",
    "\n",
    "Mittels der `.keys` & `.values` Funktion auf dem Dictionary lassen sich dann die Daten gezielt plotten.\n",
    "\n",
    "Schauen Sie sich daher folgendes Beispiel an:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 55,
   "id": "d21c9c59-2b84-4e87-a2f2-1388070b2419",
   "metadata": {
    "nbgrader": {
     "grade": false,
     "grade_id": "cell-1777b8fcd5bd30c4",
     "locked": true,
     "schema_version": 3,
     "solution": false,
     "task": false
    }
   },
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 10040 characters]",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# Definiere ein Dictionary welches die Anzahl der Schüler ihrer Klasse zuweist \n",
    "school = { \n",
    "    \"1. Klasse\": 42,\n",
    "    \"2. Klasse\": 30,\n",
    "    \"3. Klasse\": 26,\n",
    "    \"4. Klasse\": 45,\n",
    "}\n",
    "\n",
    "plt.bar(school.keys(), school.values()) # Plotte mit den Werten des Dictionarys\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a921963b-94df-4c6a-81f7-c3a3fb09b7c0",
   "metadata": {
    "nbgrader": {
     "grade": false,
     "grade_id": "cell-d2c659803a58f15e",
     "locked": true,
     "schema_version": 3,
     "solution": false,
     "task": false
    }
   },
   "source": [
    "### Styling\n",
    "\n",
    "Bar plots können auch gestyled werden. Hierzu wird dem Parameter `color` eine Liste mit farbwerten übergeben:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 57,
   "id": "00e9f1c6-5ccd-4ea3-bcec-b2265602917f",
   "metadata": {
    "nbgrader": {
     "grade": false,
     "grade_id": "cell-a3604899d50585d2",
     "locked": true,
     "schema_version": 3,
     "solution": false,
     "task": false
    }
   },
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 10188 characters]",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "school = { \n",
    "    \"1. Klasse\": 42,\n",
    "    \"2. Klasse\": 30,\n",
    "    \"3. Klasse\": 26,\n",
    "    \"4. Klasse\": 45,\n",
    "}\n",
    "\n",
    "bar_colors = [\"red\", \"blue\", \"green\", \"yellow\"] # Farben definieren\n",
    "\n",
    "plt.bar(school.keys(), school.values(), color=bar_colors) # Farben übergeben\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a74afec9-34fd-4cfb-bcd3-db6be64ef35f",
   "metadata": {
    "nbgrader": {
     "grade": false,
     "grade_id": "cell-964f579ce46a2882",
     "locked": true,
     "schema_version": 3,
     "solution": false,
     "task": false
    }
   },
   "source": [
    "### Y-Label\n",
    "\n",
    "Mit `plt.ylabel` (als String) lässt sich die y-Achse beschriften:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 60,
   "id": "e9f4c9a3-e39c-4eb8-95fd-77a3b40fa249",
   "metadata": {
    "nbgrader": {
     "grade": false,
     "grade_id": "cell-21cee3bf50f011e1",
     "locked": true,
     "schema_version": 3,
     "solution": false,
     "task": false
    }
   },
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 13000 characters]",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "school = { \n",
    "    \"1. Klasse\": 42,\n",
    "    \"2. Klasse\": 30,\n",
    "    \"3. Klasse\": 26,\n",
    "    \"4. Klasse\": 45,\n",
    "}\n",
    "\n",
    "bar_colors = [\"red\", \"blue\", \"green\", \"yellow\"]\n",
    "\n",
    "plt.bar(school.keys(), school.values(), color=bar_colors)\n",
    "\n",
    "plt.ylabel(\"Anzahl Kinder\") # Beschriften der Y-Achse\n",
    "\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9d90f3b3-adc9-498e-9dbe-13e0c577b886",
   "metadata": {
    "nbgrader": {
     "grade": false,
     "grade_id": "cell-32dabb34444f6190",
     "locked": true,
     "schema_version": 3,
     "solution": false,
     "task": false
    }
   },
   "source": [
    "### X-Label\n",
    "\n",
    "Analog dazu die Beschriftung der X-Achse mit `plt.xlabel`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 61,
   "id": "2644cc38-238e-4cec-b951-3ff88b80011e",
   "metadata": {
    "nbgrader": {
     "grade": false,
     "grade_id": "cell-3737280b071f9d91",
     "locked": true,
     "schema_version": 3,
     "solution": false,
     "task": false
    }
   },
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 15616 characters]",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "school = { \n",
    "    \"1. Klasse\": 42,\n",
    "    \"2. Klasse\": 30,\n",
    "    \"3. Klasse\": 26,\n",
    "    \"4. Klasse\": 45,\n",
    "}\n",
    "\n",
    "bar_colors = [\"red\", \"blue\", \"green\", \"yellow\"]\n",
    "\n",
    "plt.bar(school.keys(), school.values(), color=bar_colors)\n",
    "\n",
    "plt.ylabel(\"Anzahl Kinder\") # Beschriften der Y-Achse\n",
    "plt.xlabel(\"Klassenstufen\") # Beschriften der X-Achse\n",
    "\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "16e05c9d-80ef-47b8-a17f-df7a96398ab5",
   "metadata": {
    "nbgrader": {
     "grade": false,
     "grade_id": "cell-230328a26793cddb",
     "locked": true,
     "schema_version": 3,
     "solution": false,
     "task": false
    }
   },
   "source": [
    "### Aufgabe\n",
    "\n",
    "*5 Punkte*\n",
    "\n",
    "Ihnen ist ein Datenset `sec_school` einer Hauptschule gegeben, welches die Klassenstufen von 5 bis 9 auf die Anzahl ihrer Schüler im Jahrgang mappt. \n",
    "\n",
    "Definieren Sie einen Barplot. Gehen Sie dabei wie folgt vor:\n",
    "1. Definieren Sie ein geeignetes Farbschema zur Darstellung der Daten.\n",
    "2. Extrahieren Sie die Schlüssel und Werte aus dem Datenset und übergeben Sie diese zusammen mit den Farbwerten an die Funktion `plt.bar`.\n",
    "3. Setzen Sie geeignete Werte für die X & Y-Achse.\n",
    "4. Setzen Sie einen geeigneten Titel für den Plot.\n",
    "5. Plotten Sie den Werte"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 64,
   "id": "0608b1ea-6275-47c7-82a8-fed86e5e5973",
   "metadata": {
    "nbgrader": {
     "grade": false,
     "grade_id": "cell-b954e989a8bbc2fa",
     "locked": true,
     "schema_version": 3,
     "solution": false,
     "task": false
    }
   },
   "outputs": [],
   "source": [
    "sec_school = {\n",
    "    '5. Klasse': 29,\n",
    "    '6. Klasse': 35,\n",
    "    '7. Klasse': 25,\n",
    "    '8. Klasse': 28,\n",
    "    '9. Klasse': 31\n",
    "}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 65,
   "id": "ae63d6f9-cd8c-4603-9a15-7ee336d905e9",
   "metadata": {
    "nbgrader": {
     "grade": true,
     "grade_id": "cell-8caba57a6ad34b87",
     "locked": false,
     "points": 5,
     "schema_version": 3,
     "solution": true,
     "task": false
    }
   },
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 26476 characters]",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# BEGIN SOLUTION\n",
    "colors = [\"red\", \"blue\", \"green\", \"yellow\", \"pink\"]\n",
    "plt.bar(sec_school.keys(), sec_school.values(), color=colors)\n",
    "plt.xlabel(\"Klassenstufe\")\n",
    "plt.ylabel(\"Anzahl Kinder\")\n",
    "plt.title(\"Verteilung Kinder einer Hauptschule pro Klassenstufe\")\n",
    "plt.show()\n",
    "# END SOLUTION"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "bf9e917c-6949-4bb1-8184-270747e8cb4e",
   "metadata": {
    "nbgrader": {
     "grade": false,
     "grade_id": "cell-42bf44a09515d0fd",
     "locked": true,
     "schema_version": 3,
     "solution": false,
     "task": false
    }
   },
   "source": [
    "## Horizontales Bar Chart\n",
    "\n",
    "Analog zum Barchart erzeugt `plt.barh` einen Horizontales Barchart.\n",
    "\n",
    "Beispiel:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 87,
   "id": "146615f7-1315-41a3-a690-73c98ee465e3",
   "metadata": {
    "nbgrader": {
     "grade": false,
     "grade_id": "cell-54166820b406e29e",
     "locked": true,
     "schema_version": 3,
     "solution": false,
     "task": false
    }
   },
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 18240 characters]",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "school = { \n",
    "    \"1. Klasse\": 42,\n",
    "    \"2. Klasse\": 30,\n",
    "    \"3. Klasse\": 26,\n",
    "    \"4. Klasse\": 45,\n",
    "}\n",
    "\n",
    "plt.barh(list(school.keys()), list(school.values()), color=\"maroon\") # barh statt bar\n",
    "\n",
    "plt.xlabel(\"Anzahl Kinder\") \n",
    "plt.ylabel(\"Klassenstufen\") \n",
    "\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "df9117c3-0ca8-4e0d-8779-9b8826044a3a",
   "metadata": {
    "nbgrader": {
     "grade": false,
     "grade_id": "cell-3adde3f53176bcb0",
     "locked": true,
     "schema_version": 3,
     "solution": false,
     "task": false
    }
   },
   "source": [
    "## Pie Chart\n",
    "\n",
    "Kommen wir als nächstes zu der besten, tollsten und schönsten Darstellung von Daten.\n",
    "\n",
    "![](https://flowingdata.com/wp-content/uploads/2014/12/Pie-Pyramid-620x311.png)\n",
    "\n",
    "Kuchendiagramme können mittels `plt.pie` erstellt werden. Nehmen wir dazu wieder das Beispiel aus voherigem Kapitel. Dabei verlangt das Pie Chart nur die Werte (`school.values`) des Datensets:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 94,
   "id": "bb311d1b-978d-41f8-9648-874b4a862bc5",
   "metadata": {
    "nbgrader": {
     "grade": false,
     "grade_id": "cell-46cde6d166912ad0",
     "locked": true,
     "schema_version": 3,
     "solution": false,
     "task": false
    }
   },
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 20872 characters]",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "school = { \n",
    "    \"1. Klasse\": 42,\n",
    "    \"2. Klasse\": 30,\n",
    "    \"3. Klasse\": 26,\n",
    "    \"4. Klasse\": 45,\n",
    "}\n",
    "\n",
    "plt.pie(school.values()) # Pie Chart\n",
    "\n",
    "plt.title(\"Klassenverteilung einer Grundschule\")\n",
    "\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "76e19a82-7aa7-416d-beae-667b77497cf3",
   "metadata": {
    "nbgrader": {
     "grade": false,
     "grade_id": "cell-aec08dc408437049",
     "locked": true,
     "schema_version": 3,
     "solution": false,
     "task": false
    }
   },
   "source": [
    "## Styling\n",
    "\n",
    "Alle Parameter wie `title`, `color`, `xlabel`, `ylabel`, etc. lassen sich auch für das Pie Chart setzen. Die Beschriftung der einzelnen Stücke jedoch Funktioniert etwas anders.\n",
    "\n",
    "Dazu wird der Parameter `label` mit den dazugehörigen Werten ausgestattet:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 95,
   "id": "09124a3e-1f76-4f32-8638-19e7efc234b0",
   "metadata": {
    "nbgrader": {
     "grade": false,
     "grade_id": "cell-c742155fd484b71b",
     "locked": true,
     "schema_version": 3,
     "solution": false,
     "task": false
    }
   },
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 27684 characters]",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "school = { \n",
    "    \"1. Klasse\": 42,\n",
    "    \"2. Klasse\": 30,\n",
    "    \"3. Klasse\": 26,\n",
    "    \"4. Klasse\": 45,\n",
    "}\n",
    "\n",
    "plt.pie(school.values(), labels=school.keys()) # Setzen der Labels\n",
    "\n",
    "plt.title(\"Klassenverteilung einer Grundschule\")\n",
    "\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d3e68330-6319-4a87-acda-91abd4f98900",
   "metadata": {
    "nbgrader": {
     "grade": false,
     "grade_id": "cell-5336af155ef45527",
     "locked": true,
     "schema_version": 3,
     "solution": false,
     "task": false
    }
   },
   "source": [
    "Zum Setzen von Prozentwerten wird der Parameter `autopct` verwendet. Dieser nutzt einen Format String oder eine Funktion zum Definieren der Werte. Schaue dazu für mehr in die Dokumentation für [autpct](https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot.pie.html#matplotlib-pyplot-pie), eine Dokumentation zu Formatstrings findest du [hier](https://www.geeksforgeeks.org/format-specifiers-in-c/).\n",
    "\n",
    "Beispiel für Prozentwerte:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 96,
   "id": "974a71d0-552c-45d4-bb01-88edd6be608c",
   "metadata": {
    "nbgrader": {
     "grade": false,
     "grade_id": "cell-183044afa87a0492",
     "locked": true,
     "schema_version": 3,
     "solution": false,
     "task": false
    }
   },
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 32612 characters]",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "school = { \n",
    "    \"1. Klasse\": 42,\n",
    "    \"2. Klasse\": 30,\n",
    "    \"3. Klasse\": 26,\n",
    "    \"4. Klasse\": 45,\n",
    "}\n",
    "\n",
    "plt.pie(school.values(), labels=school.keys(), autopct='%1.1f%%') # Setzen von Prozentwerten\n",
    "\n",
    "plt.title(\"Klassenverteilung einer Grundschule\")\n",
    "\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a0a13fc0-3ae1-4ab5-a488-8c5247cf74c5",
   "metadata": {
    "nbgrader": {
     "grade": false,
     "grade_id": "cell-430a11a7f58f4fa5",
     "locked": true,
     "schema_version": 3,
     "solution": false,
     "task": false
    }
   },
   "source": [
    "Pie Charts haben auch einen Parameter `shadow`. Dieser ist Standardmässig `False`. Setzt man den Wert auf `True` sieht man einen Schatten:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 98,
   "id": "62971d68-8cdd-48c4-8f60-209bffe64e84",
   "metadata": {
    "nbgrader": {
     "grade": false,
     "grade_id": "cell-408e63a1464d64ea",
     "locked": true,
     "schema_version": 3,
     "solution": false,
     "task": false
    }
   },
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 38156 characters]",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "school = { \n",
    "    \"1. Klasse\": 42,\n",
    "    \"2. Klasse\": 30,\n",
    "    \"3. Klasse\": 26,\n",
    "    \"4. Klasse\": 45,\n",
    "}\n",
    "\n",
    "plt.pie(school.values(), labels=school.keys(), autopct='%1.1f%%', shadow=True) # Zeige einen Schatten\n",
    "\n",
    "plt.title(\"Klassenverteilung einer Grundschule\")\n",
    "\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "59e8be26-c070-4205-8260-f4597074ec6f",
   "metadata": {
    "nbgrader": {
     "grade": false,
     "grade_id": "cell-376fc818f2a3d818",
     "locked": true,
     "schema_version": 3,
     "solution": false,
     "task": false
    }
   },
   "source": [
    "Zum Herausnehmen von Kuchenstücken gibt es den Parameter `explode`. Dieser erwartet eine Liste mit Fließkommazahlen die zwischen 0.0 - Standardwert und 1.0 - absoluter Explode liegen.\n",
    "\n",
    "Beispiel Klasse 3 ist vom Ursprung 20% entfernt:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 99,
   "id": "bf1ea228-1547-4c1d-975e-d7f49111486c",
   "metadata": {
    "nbgrader": {
     "grade": false,
     "grade_id": "cell-e3921561732c3895",
     "locked": true,
     "schema_version": 3,
     "solution": false,
     "task": false
    }
   },
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 33908 characters]",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "school = { \n",
    "    \"1. Klasse\": 42,\n",
    "    \"2. Klasse\": 30,\n",
    "    \"3. Klasse\": 26,\n",
    "    \"4. Klasse\": 45,\n",
    "}\n",
    "\n",
    "plt.pie(school.values(), labels=school.keys(), autopct='%1.1f%%', explode=[0, 0, 0.2, 0]) # Zeige einen Schatten\n",
    "\n",
    "plt.title(\"Klassenverteilung einer Grundschule\")\n",
    "\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "cbe9aba9-529d-4d4c-87fa-ff46e3a24e5b",
   "metadata": {
    "nbgrader": {
     "grade": false,
     "grade_id": "cell-ed3d080835960776",
     "locked": true,
     "schema_version": 3,
     "solution": false,
     "task": false
    }
   },
   "source": [
    "## Aufgabe\n",
    "\n",
    "*5 Punkte*\n",
    "\n",
    "Ihnen ist ein Datenset `sec_school` einer Hauptschule gegeben, welches die Klassenstufen von 5 bis 9 auf die Anzahl ihrer Schüler im Jahrgang mappt. \n",
    "\n",
    "Definieren Sie einen Pieplot. Gehen Sie dabei wie folgt vor:\n",
    "1. Definieren Sie ein geeignetes Farbschema zur Darstellung der Daten.\n",
    "2. Extrahieren Sie die Schlüssel und Werte aus dem Datenset und übergeben Sie diese zusammen mit den Farbwerten an die Funktion `plt.pie`. (Nutzen Sie zum Anzeigen der Prozentwerte autopct='%1.1f%%')\n",
    "3. Lassen Sie die 6. Klasse 25% und die 9. Klasse 40% explodieren.\n",
    "4. Setzen Sie einen geeigneten Titel für den Plot.\n",
    "5. Plotten Sie den Werte."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 104,
   "id": "5a2e4c2b-051d-4e9d-ae93-0e6fe4b25003",
   "metadata": {
    "nbgrader": {
     "grade": false,
     "grade_id": "cell-bf48088c515caf5c",
     "locked": true,
     "schema_version": 3,
     "solution": false,
     "task": false
    }
   },
   "outputs": [],
   "source": [
    "sec_school = {\n",
    "    '5. Klasse': 29,\n",
    "    '6. Klasse': 35,\n",
    "    '7. Klasse': 25,\n",
    "    '8. Klasse': 28,\n",
    "    '9. Klasse': 31\n",
    "}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 105,
   "id": "fdebbc40-17eb-48e5-89fa-f8d12ec65688",
   "metadata": {
    "nbgrader": {
     "grade": true,
     "grade_id": "cell-d201bd3e919fcf1c",
     "locked": false,
     "points": 5,
     "schema_version": 3,
     "solution": true,
     "task": false
    }
   },
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 41876 characters]",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# BEGIN SOLUTION\n",
    "plt.pie(\n",
    "    sec_school.values(),\n",
    "    labels=sec_school.keys(),\n",
    "    autopct='%1.1f%%',\n",
    "    explode=[0, 0.25, 0, 0, 0.4]\n",
    ")\n",
    "\n",
    "plt.title(\"Klassenverteilung einer Grundschule\")\n",
    "\n",
    "plt.show()\n",
    "# END SOLUTION"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.12.7"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
