CDS401-Mathematics-I/Code/comination.ipynb
2025-04-17 13:17:21 +02:00

236 lines
9.4 KiB
Plaintext

{
"cells": [
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "e15757ea0cf743dc9af162093423cb6e",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"VBox(children=(HBox(children=(Dropdown(description='Regel:', options=('Kombination', 'Permutation', 'Fakultät'…"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"import matplotlib.pyplot as plt\n",
"import numpy as np\n",
"import ipywidgets as widgets\n",
"from IPython.display import display, Math, clear_output\n",
"\n",
"# Interaktives Lern-Tool für Kombinatorik-Regeln\n",
"# Dies ist ein Jupyter-Notebook-Style Code für interaktive Widgets.\n",
"# Bitte in einer Umgebung ausführen, die Widgets unterstützt (z.B. JupyterLab/Notebook).\n",
"\n",
"# Funktionen zur Berechnung\n",
"def combination(n, k):\n",
" from math import comb\n",
" return comb(n, k)\n",
"\n",
"def permutation(n, k):\n",
" from math import perm\n",
" return perm(n, k)\n",
"\n",
"def factorial(n):\n",
" from math import factorial\n",
" return factorial(n)\n",
"\n",
"def binomial_coefficient(n, k):\n",
" from math import comb\n",
" return comb(n, k)\n",
"\n",
"def variation(n, k):\n",
" from math import perm\n",
" return perm(n, k)\n",
"\n",
"def multiset_combination(n, k):\n",
" from math import comb\n",
" return comb(n + k - 1, k)\n",
"\n",
"# Funktion, um den Entscheidungsbaum zu zeichnen (nur für Kombinationen und Permutationen)\n",
"def draw_tree(n, k, is_perm):\n",
" plt.figure(figsize=(8, 6))\n",
" ax = plt.gca()\n",
" ax.clear()\n",
" ax.set_title(\"Entscheidungsbaum\", fontsize=14)\n",
" ax.axis('off')\n",
"\n",
" if k == 1:\n",
" x_start = 0.5\n",
" y_start = 0.9\n",
" plt.text(x_start, y_start, f\"Start\\n(n={n})\", ha='center', va='center')\n",
" for i in range(n):\n",
" x = 0.1 + i*(0.8/(n-1)) if n > 1 else 0.5\n",
" y = 0.6\n",
" plt.plot([x_start, x], [y_start-0.05, y], 'k-')\n",
" plt.text(x, y, f\"Wahl {i+1}\", ha='center', va='center')\n",
"\n",
" elif k == 2:\n",
" x_start = 0.5\n",
" y_start = 0.9\n",
" plt.text(x_start, y_start, f\"Start\\n(n={n})\", ha='center', va='center')\n",
" child_coords = []\n",
" for i in range(n):\n",
" x = 0.1 + i*(0.8/(n-1)) if n > 1 else 0.5\n",
" y = 0.7\n",
" plt.plot([x_start, x], [y_start-0.05, y], 'k-')\n",
" plt.text(x, y, f\"W1={i+1}\", ha='center', va='center')\n",
" child_coords.append((x, y))\n",
" for (ix, iy) in child_coords:\n",
" branch_count = (n-1) if is_perm else (n)\n",
" for j in range(branch_count):\n",
" x2 = ix - 0.08 + j*(0.16/(branch_count-1)) if branch_count > 1 else ix\n",
" y2 = 0.45\n",
" plt.plot([ix, x2], [iy-0.05, y2], 'k-')\n",
" plt.text(x2, y2, f\"W2={j+1}\", ha='center', va='center', fontsize=8)\n",
" elif k == 3:\n",
" x_start = 0.5\n",
" y_start = 0.95\n",
" plt.text(x_start, y_start, f\"Start\\n(n={n})\", ha='center', va='center')\n",
" layer1 = []\n",
" for i in range(n):\n",
" x = 0.1 + i*(0.8/(n-1)) if n > 1 else 0.5\n",
" y = 0.8\n",
" plt.plot([x_start, x], [y_start-0.03, y], 'k-')\n",
" plt.text(x, y, f\"W1={i+1}\", ha='center', va='center', fontsize=9)\n",
" layer1.append((x, y))\n",
" layer2 = []\n",
" for (ix, iy) in layer1:\n",
" branch_count = (n-1) if is_perm else n\n",
" for j in range(branch_count):\n",
" x2 = ix - 0.05 + j*(0.1/(branch_count-1)) if branch_count > 1 else ix\n",
" y2 = 0.6\n",
" plt.plot([ix, x2], [iy-0.03, y2], 'k-')\n",
" plt.text(x2, y2, f\"W2={j+1}\", ha='center', va='center', fontsize=7)\n",
" layer2.append((x2, y2))\n",
" for (ix2, iy2) in layer2:\n",
" branch_count = (n-2) if is_perm else n\n",
" for j in range(branch_count):\n",
" x3 = ix2 - 0.02 + j*(0.04/(branch_count-1)) if branch_count > 1 else ix2\n",
" y3 = 0.4\n",
" plt.plot([ix2, x3], [iy2-0.03, y3], 'k-')\n",
" plt.text(x3, y3, f\"W3={j+1}\", ha='center', va='center', fontsize=6)\n",
" else:\n",
" plt.text(0.5, 0.5, \"Baumdiagramm für k>3 ist zu groß.\\nBitte k <= 3 für Baum\", ha='center', va='center', fontsize=12)\n",
"\n",
" plt.tight_layout()\n",
" plt.show()\n",
"\n",
"# Widgets erstellen\n",
"dropdown_rule = widgets.Dropdown(\n",
" options=['Kombination', 'Permutation', 'Fakultät', 'Binomialkoeffizient', 'Variation', 'Mehrfachkombination'],\n",
" value='Kombination',\n",
" description='Regel:',\n",
" style={'description_width': 'initial'}\n",
")\n",
"\n",
"input_n = widgets.IntText(value=5, description='n:', style={'description_width': 'initial'})\n",
"input_k = widgets.IntText(value=2, description='k:', style={'description_width': 'initial'})\n",
"input_k.layout.visibility = 'visible' # Standardmäßig sichtbar\n",
"\n",
"output_area = widgets.Output()\n",
"\n",
"# Button zum Berechnen\n",
"button = widgets.Button(description='Berechnen & Visualisieren')\n",
"\n",
"# Callback-Funktion\n",
"def on_button_click(b):\n",
" with output_area:\n",
" clear_output()\n",
" rule = dropdown_rule.value\n",
" n = input_n.value\n",
" k = input_k.value if rule in ['Kombination', 'Permutation', 'Binomialkoeffizient', 'Variation', 'Mehrfachkombination'] else None\n",
"\n",
" try:\n",
" if rule == 'Kombination':\n",
" if k > n:\n",
" print(\"k darf nicht größer als n sein.\")\n",
" return\n",
" res = combination(n, k)\n",
" display(Math(r\"C(n,k) = \\binom{{{}}}{{{}}} = {}\".format(n, k, res)))\n",
" draw_tree(n, k, is_perm=False)\n",
" elif rule == 'Permutation':\n",
" if k > n:\n",
" print(\"k darf nicht größer als n sein.\")\n",
" return\n",
" res = permutation(n, k)\n",
" display(Math(r\"P(n,k) = {} = {}\".format(res, res)))\n",
" draw_tree(n, k, is_perm=True)\n",
" elif rule == 'Fakultät':\n",
" res = factorial(n)\n",
" display(Math(r\"n! = {} = {}\".format(res, res)))\n",
" elif rule == 'Binomialkoeffizient':\n",
" if k > n:\n",
" print(\"k darf nicht größer als n sein.\")\n",
" return\n",
" res = binomial_coefficient(n, k)\n",
" display(Math(r\"\\binom{{{}}}{{{}}} = {}\".format(n, k, res)))\n",
" elif rule == 'Variation':\n",
" if k > n:\n",
" print(\"k darf nicht größer als n sein.\")\n",
" return\n",
" res = variation(n, k)\n",
" display(Math(r\"V(n,k) = P(n,k) = {} = {}\".format(res, res)))\n",
" elif rule == 'Mehrfachkombination':\n",
" res = multiset_combination(n, k)\n",
" display(Math(r\"\\binom{{n+k-1}}{{k}} = {} = {}\".format(res, res)))\n",
" else:\n",
" print(\"Unbekannte Regel.\")\n",
" except Exception as e:\n",
" print(f\"Fehler: {e}\")\n",
"\n",
"# Event verknüpfen\n",
"button.on_click(on_button_click)\n",
"\n",
"# Anpassung der sichtbaren Eingabefelder basierend auf der gewählten Regel\n",
"def on_rule_change(change):\n",
" rule = change['new']\n",
" if rule in ['Kombination', 'Permutation', 'Binomialkoeffizient', 'Variation', 'Mehrfachkombination']:\n",
" input_k.layout.visibility = 'visible'\n",
" else:\n",
" input_k.layout.visibility = 'hidden'\n",
"\n",
"dropdown_rule.observe(on_rule_change, names='value')\n",
"\n",
"# Anzeige\n",
"controls = widgets.VBox([\n",
" widgets.HBox([dropdown_rule]),\n",
" widgets.HBox([input_n, input_k]),\n",
" button,\n",
" output_area\n",
"])\n",
"display(controls)\n"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"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": 2
}