added tut07
This commit is contained in:
@ -0,0 +1,169 @@
|
|||||||
|
# Tutorium 07 - 01.12.2023
|
||||||
|
|
||||||
|
## Execrise 06
|
||||||
|
|
||||||
|
- Korrektur wieder am Samstag
|
||||||
|
|
||||||
|
### Problematik ChatGPT und Plagiate
|
||||||
|
|
||||||
|
- ChatGPT ist ein tolles Tool, warum?
|
||||||
|
- Manchmal liefert es andere Lösungen zu Problemen
|
||||||
|
- Grundverständnis bei neuen Problemen
|
||||||
|
- integriert in die IDE (z.B. Github Copilot):
|
||||||
|
- schneller Code schreiben
|
||||||
|
<details>
|
||||||
|
<summary>Wie viele Zeilen Code schreibt ein Entwickler durchschnittlich am Tag?</summary>
|
||||||
|
10 bis 50 Codezeilen
|
||||||
|
</details>
|
||||||
|
- Leichtsinnsfehler ausbessern
|
||||||
|
- Kurz: Es nimmt einen repetetive Arbeit ab
|
||||||
|
|
||||||
|
#### Die Problematik?
|
||||||
|
|
||||||
|
- Ein EidP soll das Grundverständnis von Programmieren vermittelt werden
|
||||||
|
- Denkweise
|
||||||
|
- Konzepte in der theoretischen Informatik
|
||||||
|
- Konzepte in Programmiersprachen
|
||||||
|
- Übung
|
||||||
|
- Um ChatGPT sinnvoll zu nutzen müsst ihr diese Grundverständnis bereits besitzen
|
||||||
|
- Auch Studierende mit Vorwissen profitieren davon die Übung sinnvoll zu bearbeiten
|
||||||
|
- Wenn Ihr für die Aufgaben ChatGPT verwendet, dann habt ihr nicht genug Vorwissen
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>Studienleistung WS2022</summary>
|
||||||
|
<img src="./img/ws2022-studienleistung.png" width=833 height=auto>
|
||||||
|
</details>
|
||||||
|
<details>
|
||||||
|
<summary>Notenverteilung WS2022</summary>
|
||||||
|
<img src="./img/ws2022-notenverteilung.png" width=833 height=auto>
|
||||||
|
</details>
|
||||||
|
|
||||||
|
|
||||||
|
#### Also, macht eure Aufgaben selber!
|
||||||
|
|
||||||
|
----
|
||||||
|
|
||||||
|
## Wichtiges/Hilfreiches für Exercise-07
|
||||||
|
|
||||||
|
### Rekursion
|
||||||
|
|
||||||
|
- Rekursion in Python sind Funktionen die sich selbst aufrufen
|
||||||
|
```python
|
||||||
|
def fac(n: int) -> int:
|
||||||
|
if n <= 1: # Abbruchbedingung, kein Rekursiver Aufruf mehr!
|
||||||
|
return 1
|
||||||
|
return n * fac(n - 1) # Rekursiver Aufruf
|
||||||
|
```
|
||||||
|
- Eine Rekursion braucht eine **Abbruchbedingung**
|
||||||
|
- primitive Rekursionen können auch einfach iterative gelöst werden
|
||||||
|
```python
|
||||||
|
def fac2(n: int) -> int:
|
||||||
|
fac = 1
|
||||||
|
for i in range(1, n + 1):
|
||||||
|
fac *= i
|
||||||
|
return fac
|
||||||
|
```
|
||||||
|
- Eine Rekursion kann mehrere Rekursionspfade haben! (Kaskadenförmige Rekursion), welche auch primitiv berechenbar sind!
|
||||||
|
```python
|
||||||
|
def fib(n: int) -> int:
|
||||||
|
if n in {0, 1}: # Abbruchbedingung
|
||||||
|
return n
|
||||||
|
return fib(n - 1) + fib(n - 2) # mehrere Rekursionsaufrufe
|
||||||
|
```
|
||||||
|
- Wie Funktioniert das?
|
||||||
|
- Es wird ein Rekursionsbaum aufgebaut
|
||||||
|
- Wenn dieser Fertig ist wird berechnet
|
||||||
|
- Z.b. `fac`:
|
||||||
|
```
|
||||||
|
fac(5)
|
||||||
|
5 * fac(4)
|
||||||
|
5 * 4 * fac(3)
|
||||||
|
5 * 4 * 3 * fac(2)
|
||||||
|
5 * 4 * 3 * 2 * fac(1)
|
||||||
|
5 * 4 * 3 * 2 * 1
|
||||||
|
120
|
||||||
|
```
|
||||||
|
|
||||||
|
```
|
||||||
|
fib(4)
|
||||||
|
fib(3) + fib(2)
|
||||||
|
(fib(2) + fib(1)) + (fib(0) + fib(1))
|
||||||
|
((fib(0) + fib(1)) + fib(1)) + (fib(0) + fib(1))
|
||||||
|
((0 + 1) + 1) + (0 + 1)
|
||||||
|
3
|
||||||
|
```
|
||||||
|
- Gibt es Rekursionen die nicht iterative berechenbar sind?
|
||||||
|
- $\mu$-Rekursionen oder partiell Rekursionen
|
||||||
|
- erste partiell rekursive Funktion von Wilhelm Ackermann 1926, die "Ackermannfunktion"
|
||||||
|
$\alpha(0, m) = m + 1$
|
||||||
|
$\alpha(n, 0) = \alpha(n - 1, 1)$
|
||||||
|
$\alpha(n, m) = \alpha(n, \alpha(n, m - 1))$
|
||||||
|
|
||||||
|
```python
|
||||||
|
def ack(n: int, m: int) -> int:
|
||||||
|
match (n, m):
|
||||||
|
case (0, _):
|
||||||
|
return m + 1
|
||||||
|
case (_, 0):
|
||||||
|
return ack(n - 1, 1)
|
||||||
|
case _:
|
||||||
|
return ack(n - 1, ack(n, m - 1))
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Tipp:
|
||||||
|
|
||||||
|
Man kann alles rekursiv Aufbauen mit Operatoren (`+, -, *, /, %, //, &&, and, ...`), also auch Listen oder Strings
|
||||||
|
|
||||||
|
```python
|
||||||
|
def all_fac(max: int) -> list[(int, int)]:
|
||||||
|
if max == 0: # Abbruchbedingung
|
||||||
|
return [(0, 1)]
|
||||||
|
return [(max, fac(max))] + all_fac(max - 1) # Rekursion
|
||||||
|
|
||||||
|
def all_fac_str(min: int, max: int) -> str:
|
||||||
|
if min >= max: # Abbruchbedingung
|
||||||
|
return f"{fac(min)}"
|
||||||
|
return f"{fac(min)} " + all_fac_str(min + 1, max) # Rekursion
|
||||||
|
|
||||||
|
def fib_str(n: int) -> str:
|
||||||
|
if n in {0, 1}: # Abbruchbedingung
|
||||||
|
return str(n)
|
||||||
|
return f"({fib_str(n - 1)} + {fib_str(n - 2)})" # Rekursion
|
||||||
|
```
|
||||||
|
|
||||||
|
### Rekursion in Bäumen
|
||||||
|
|
||||||
|
- Drei möglichkeiten einen Baum *abzulaufen*
|
||||||
|
- **Pre-Order**: Knoten, links, rechts
|
||||||
|
```python
|
||||||
|
def preorder[T](tree: BTree[T]):
|
||||||
|
match tree:
|
||||||
|
case Node(value, left, right):
|
||||||
|
print(value)
|
||||||
|
preorder(left)
|
||||||
|
preorder(right)
|
||||||
|
case _:
|
||||||
|
return
|
||||||
|
```
|
||||||
|
- **Post-Order**: links, rechts, Knoten
|
||||||
|
```python
|
||||||
|
def postorder[T](tree: BTree[T]):
|
||||||
|
match tree:
|
||||||
|
case Node(value, left, right):
|
||||||
|
postorder(left)
|
||||||
|
postorder(right)
|
||||||
|
print(value)
|
||||||
|
case _:
|
||||||
|
return
|
||||||
|
```
|
||||||
|
- **In-Order**: links, Knoten, rechts
|
||||||
|
```python
|
||||||
|
def inorder[T](tree: BTree[T]):
|
||||||
|
match tree:
|
||||||
|
case Node(value, left, right):
|
||||||
|
inorder(left)
|
||||||
|
print(value)
|
||||||
|
inorder(right)
|
||||||
|
case _:
|
||||||
|
return
|
||||||
|
```
|
BIN
Tutorium/tut07/img/ws2022-notenverteilung.png
Normal file
BIN
Tutorium/tut07/img/ws2022-notenverteilung.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 12 KiB |
BIN
Tutorium/tut07/img/ws2022-studienleistung.png
Normal file
BIN
Tutorium/tut07/img/ws2022-studienleistung.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 10 KiB |
57
Tutorium/tut07/src/solutions-exercise-06/mastermind.py
Normal file
57
Tutorium/tut07/src/solutions-exercise-06/mastermind.py
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
import random
|
||||||
|
|
||||||
|
|
||||||
|
def remove_char(string: str, c: str) -> str:
|
||||||
|
for i, s in enumerate(string):
|
||||||
|
if s == c:
|
||||||
|
return string[:i] + string[i + 1:]
|
||||||
|
return string
|
||||||
|
|
||||||
|
|
||||||
|
def perfect_chars(inp: str, sol: str) -> str:
|
||||||
|
chars = ""
|
||||||
|
for c, s in zip(inp, sol):
|
||||||
|
if c == s:
|
||||||
|
chars = chars + c
|
||||||
|
return chars
|
||||||
|
|
||||||
|
|
||||||
|
def correct_chars(inp: str, sol: str) -> str:
|
||||||
|
res = ""
|
||||||
|
for c in inp:
|
||||||
|
if c in sol:
|
||||||
|
res += c
|
||||||
|
sol = remove_char(sol, c)
|
||||||
|
return res
|
||||||
|
|
||||||
|
|
||||||
|
def compare(inp: str, sol: str) -> tuple[int, int]:
|
||||||
|
perfect = len(perfect_chars(inp, sol))
|
||||||
|
correct = len(correct_chars(inp, sol))
|
||||||
|
return perfect, correct - perfect
|
||||||
|
|
||||||
|
|
||||||
|
def compare_alt(inp: str, sol: str) -> tuple[int, int]:
|
||||||
|
perfect = perfect_chars(inp, sol)
|
||||||
|
for c in perfect:
|
||||||
|
sol = remove_char(sol, c)
|
||||||
|
inp = remove_char(inp, c)
|
||||||
|
correct = correct_chars(inp, sol)
|
||||||
|
return len(perfect), len(correct)
|
||||||
|
|
||||||
|
|
||||||
|
def game(length: int, symbols: str):
|
||||||
|
solution = "".join(random.choices(symbols, k=length))
|
||||||
|
print("Länge:", length, "Zeichen:", symbols)
|
||||||
|
result = (0, 0)
|
||||||
|
while result != (length, 0):
|
||||||
|
c = input()
|
||||||
|
if len(c) != length:
|
||||||
|
print("Try again!")
|
||||||
|
continue
|
||||||
|
result = compare(c, solution)
|
||||||
|
print("Antwort:", result[0] * "X" + result[1] * "-")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
game(5, "ABCDE")
|
35
Tutorium/tut07/src/solutions-exercise-06/typevars.py
Normal file
35
Tutorium/tut07/src/solutions-exercise-06/typevars.py
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
from typing import Optional
|
||||||
|
|
||||||
|
|
||||||
|
def head[T](xs: list[T]) -> Optional[T]:
|
||||||
|
if not xs:
|
||||||
|
return None
|
||||||
|
return xs[0]
|
||||||
|
|
||||||
|
|
||||||
|
def tail[T](xs: list[T]) -> Optional[list[T]]:
|
||||||
|
if not xs:
|
||||||
|
return None
|
||||||
|
return xs[1:]
|
||||||
|
|
||||||
|
|
||||||
|
def concat[T](xss: list[list[T]]) -> list[T]:
|
||||||
|
outer = list()
|
||||||
|
for xs in xss:
|
||||||
|
outer += xs
|
||||||
|
return outer
|
||||||
|
|
||||||
|
|
||||||
|
def zip[T, U](xs: list[T], ys: list[U]) -> list[tuple[T, U]]:
|
||||||
|
out = list()
|
||||||
|
for i, x in enumerate(xs):
|
||||||
|
if i >= len(ys):
|
||||||
|
return out
|
||||||
|
else:
|
||||||
|
out += [(x, ys[i])]
|
||||||
|
return out
|
||||||
|
|
||||||
|
|
||||||
|
def assoc[T, U, V](t: tuple[tuple[T, U], V]) -> tuple[T, tuple[U, V]]:
|
||||||
|
(x, y), z = t
|
||||||
|
return (x, (y, z))
|
36
Tutorium/tut07/src/trees.py
Normal file
36
Tutorium/tut07/src/trees.py
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
@dataclass
|
||||||
|
class Node[T]:
|
||||||
|
value: T
|
||||||
|
left: Optional['Node[T]'] = None
|
||||||
|
right: Optional['Node[T]'] = None
|
||||||
|
|
||||||
|
type BTree[T] = Node[T] | None
|
||||||
|
|
||||||
|
def preorder[T](tree: BTree[T]):
|
||||||
|
match tree:
|
||||||
|
case Node(value, left, right):
|
||||||
|
print(value)
|
||||||
|
preorder(left)
|
||||||
|
preorder(right)
|
||||||
|
case _:
|
||||||
|
return
|
||||||
|
|
||||||
|
|
||||||
|
def postorder[T](tree: BTree[T]):
|
||||||
|
match tree:
|
||||||
|
case Node(value, left, right):
|
||||||
|
postorder(left)
|
||||||
|
postorder(right)
|
||||||
|
print(value)
|
||||||
|
case _:
|
||||||
|
return
|
||||||
|
|
||||||
|
|
||||||
|
def inorder[T](tree: BTree[T]):
|
||||||
|
match tree:
|
||||||
|
case Node(value, left, right):
|
||||||
|
inorder(left)
|
||||||
|
print(value)
|
||||||
|
inorder(right)
|
||||||
|
case _:
|
||||||
|
return
|
55
Tutorium/tut07/src/tutorium_07.py
Normal file
55
Tutorium/tut07/src/tutorium_07.py
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
def fibonacci(n: int) -> int:
|
||||||
|
if n in {0, 1}: # Abbruchbedingung
|
||||||
|
return n
|
||||||
|
return fibonacci(n - 1) + fibonacci(n - 2) # mehrere Rekursionsaufrufe
|
||||||
|
|
||||||
|
|
||||||
|
def fac(n: int) -> int:
|
||||||
|
if n <= 0: # Abbruchbedingung, kein Rekursiver Aufruf mehr!
|
||||||
|
return 1
|
||||||
|
return n * fac(n - 1) # Rekursiver Aufruf
|
||||||
|
|
||||||
|
|
||||||
|
def fac2(n: int) -> int:
|
||||||
|
num = 1
|
||||||
|
for i in range(1, n + 1):
|
||||||
|
num *= i
|
||||||
|
return num
|
||||||
|
|
||||||
|
|
||||||
|
def ack(n: int, m: int) -> int:
|
||||||
|
match (n, m):
|
||||||
|
case (0, _):
|
||||||
|
return m + 1
|
||||||
|
case (_, 0):
|
||||||
|
return ack(n - 1, 1)
|
||||||
|
case _:
|
||||||
|
return ack(n - 1, ack(n, m - 1))
|
||||||
|
|
||||||
|
|
||||||
|
def all_fac(max: int) -> list[(int, int)]:
|
||||||
|
if max == 0: # Abbruchbedingung
|
||||||
|
return [(0, 1)]
|
||||||
|
return [(max, fac(max))] + all_fac(max - 1) # Rekursion
|
||||||
|
|
||||||
|
|
||||||
|
def all_fac_str(min: int, max: int) -> str:
|
||||||
|
if min >= max: # Abbruchbedingung
|
||||||
|
return f"{fac(min)}"
|
||||||
|
return f"{fac(min)} " + all_fac_str(min + 1, max) # Rekursion
|
||||||
|
|
||||||
|
|
||||||
|
def fib_str(n: int) -> str:
|
||||||
|
if n in {0, 1}:
|
||||||
|
return str(n)
|
||||||
|
return f"({fib_str(n - 1)} + {fib_str(n - 2)})"
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
assert [fibonacci(n) for n in range(15)] == [0, 1, 1, 2,
|
||||||
|
3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377]
|
||||||
|
assert [fac(n) for n in range(11)] == [1, 1, 2, 6, 24,
|
||||||
|
120, 720, 5040, 40320, 362880, 3628800]
|
||||||
|
assert [fac(n) for n in range(10)] == [fac2(n) for n in range(10)]
|
||||||
|
assert list(reversed(all_fac(10))) == [(n, fac(n)) for n in range(11)]
|
||||||
|
assert all_fac_str(0, 10) == "1 1 2 6 24 120 720 5040 40320 362880 3628800"
|
Reference in New Issue
Block a user