{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "2f5e1fcf-c1b1-49e2-8f5f-8851c4662359",
   "metadata": {
    "editable": true,
    "slideshow": {
     "slide_type": "slide"
    },
    "tags": []
   },
   "source": [
    "# Lösungen Numpy & MatPlotLib"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "0c77fded-7665-41ea-a823-90fc631d9cb7",
   "metadata": {
    "editable": true,
    "slideshow": {
     "slide_type": "skip"
    },
    "tags": []
   },
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "import matplotlib.pyplot as plt"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "089b58c3-dbf7-4436-ae44-a2fda277d939",
   "metadata": {
    "editable": true,
    "slideshow": {
     "slide_type": "slide"
    },
    "tags": []
   },
   "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": 3,
   "id": "f534c21c-afc6-4d61-be54-bf7ffc17947b",
   "metadata": {
    "editable": true,
    "slideshow": {
     "slide_type": "fragment"
    },
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([0., 0., 0., 0., 0., 0.])"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "only_zeros = np.zeros(6)\n",
    "only_zeros"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "8e770dff-f8b2-4222-8487-3a239673cb42",
   "metadata": {
    "editable": true,
    "slideshow": {
     "slide_type": "slide"
    },
    "tags": []
   },
   "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": 4,
   "id": "1154acb7-f10a-4b97-85ec-d8d0e4990531",
   "metadata": {
    "editable": true,
    "slideshow": {
     "slide_type": "fragment"
    },
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([-4. , -1.9,  0.2,  2.3,  4.4,  6.5,  8.6, 10.7, 12.8, 14.9, 17. ])"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "x_scale = np.linspace(-4, 17, num=11)\n",
    "x_scale"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "4efff856-e35c-47b0-ae03-87c94ac5cb31",
   "metadata": {
    "editable": true,
    "slideshow": {
     "slide_type": "slide"
    },
    "tags": []
   },
   "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": 5,
   "id": "0eaac4f3-6635-4be6-9769-103d3f982f01",
   "metadata": {
    "editable": true,
    "slideshow": {
     "slide_type": "subslide"
    },
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 19548 characters]",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "xs = np.linspace(0, 100, num=200)\n",
    "ys = np.sqrt(xs)\n",
    "plt.plot(xs, ys)\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "81980caa-194a-4ed5-9d3a-9121bb2021a1",
   "metadata": {
    "editable": true,
    "slideshow": {
     "slide_type": "slide"
    },
    "tags": []
   },
   "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": 6,
   "id": "670c67ea-973a-46ca-802f-d7e74b47f267",
   "metadata": {
    "editable": true,
    "slideshow": {
     "slide_type": "subslide"
    },
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 26368 characters]",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "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()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "40d39b96-7469-4c7a-9cc2-f837379d4761",
   "metadata": {
    "editable": true,
    "slideshow": {
     "slide_type": "slide"
    },
    "tags": []
   },
   "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": "markdown",
   "id": "1611e66f-2f42-4820-9743-d68bfab86b2c",
   "metadata": {
    "editable": true,
    "slideshow": {
     "slide_type": "subslide"
    },
    "tags": []
   },
   "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": "code",
   "execution_count": 7,
   "id": "aa028122-a194-489c-96bb-843c1de48582",
   "metadata": {
    "editable": true,
    "slideshow": {
     "slide_type": "subslide"
    },
    "tags": []
   },
   "outputs": [],
   "source": [
    "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"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "dfc956c7-803f-4745-afd8-ffbc62800f2d",
   "metadata": {
    "editable": true,
    "slideshow": {
     "slide_type": "subslide"
    },
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1. 3089810780120156248\n",
      "2. 8356396685252565260\n",
      "3. 1921117399837525548\n",
      "4. 14806858147081821235\n",
      "5. 2557599628047639428\n"
     ]
    }
   ],
   "source": [
    "# Cocktailshaker Numbers\n",
    "rng = lcg(\n",
    "        3935559000370003845,\n",
    "        3203021881815356449,\n",
    "        2**64-1, 11742185885288659963\n",
    "    )\n",
    "\n",
    "for i in range(1,6):\n",
    "    print(f\"{i}.\", next(rng))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "1fceb903-350b-4f70-bef0-c71b8aec07ad",
   "metadata": {
    "editable": true,
    "slideshow": {
     "slide_type": "slide"
    },
    "tags": []
   },
   "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": 12,
   "id": "fa2f68b1-ab67-4177-a8bc-5ff461c9c10d",
   "metadata": {
    "editable": true,
    "slideshow": {
     "slide_type": "fragment"
    },
    "tags": []
   },
   "outputs": [],
   "source": [
    "# Given\n",
    "np.random.seed(42) # Setting a fixed start Value for the Generator\n",
    "pcgs: np.array = None\n",
    "pcgs_sorted: np.array = None"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "id": "43aed358-ec09-4c59-a95c-23ca194cc9b0",
   "metadata": {
    "editable": true,
    "slideshow": {
     "slide_type": "subslide"
    },
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 48672 characters]",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "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()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6690543b-7fc9-488e-a93e-b69794454b4d",
   "metadata": {
    "editable": true,
    "slideshow": {
     "slide_type": "slide"
    },
    "tags": []
   },
   "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": 14,
   "id": "de984d20-c338-4cae-acc6-7bf74fa6337e",
   "metadata": {
    "editable": true,
    "slideshow": {
     "slide_type": "fragment"
    },
    "tags": []
   },
   "outputs": [],
   "source": [
    "# Given\n",
    "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": 15,
   "id": "1e8dd05a-2aea-4732-ba49-c3a6c104cbb4",
   "metadata": {
    "editable": true,
    "slideshow": {
     "slide_type": "subslide"
    },
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 26456 characters]",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "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()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "cde352d1-f127-40cb-bc32-96415fa90aee",
   "metadata": {
    "editable": true,
    "slideshow": {
     "slide_type": "slide"
    },
    "tags": []
   },
   "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": 16,
   "id": "fcf4f172-6065-4855-afa1-b745615e10b0",
   "metadata": {
    "editable": true,
    "slideshow": {
     "slide_type": "fragment"
    },
    "tags": []
   },
   "outputs": [],
   "source": [
    "# Given\n",
    "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": 17,
   "id": "66f686f2-3ef8-491e-93cd-5815d8fe535d",
   "metadata": {
    "editable": true,
    "slideshow": {
     "slide_type": "subslide"
    },
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 41856 characters]",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "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()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c061468f-c0ed-4745-8780-49e5e6370612",
   "metadata": {
    "editable": true,
    "slideshow": {
     "slide_type": "slide"
    },
    "tags": []
   },
   "source": [
    "# Extra: The Meme"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "id": "2d3225b3-ae16-4c53-857f-fa20b3134f45",
   "metadata": {
    "editable": true,
    "slideshow": {
     "slide_type": "subslide"
    },
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 24564 characters]",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "data = {\n",
    "    \"Sky\": 0.77,\n",
    "    \"Sunny side of pyramid\": 0.17,\n",
    "    \"Shady side of pyramid\": 0.05\n",
    "}\n",
    "colors = [\"#0095d9\", \"#f5e837\", \"#c4b633\"]\n",
    "plt.pie(data.values(), startangle=-50, colors=colors)\n",
    "plt.legend(data.keys(), bbox_to_anchor=(1, 0, 0.5, 0.6))\n",
    "plt.savefig(\"meme.png\", bbox_inches=\"tight\", transparent=True)"
   ]
  }
 ],
 "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
}
