added tut07

This commit is contained in:
2023-12-01 08:35:08 +01:00
parent d613d58be4
commit d147717c39
7 changed files with 352 additions and 0 deletions

View File

@ -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
```

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

View 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")

View 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))

View 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

View 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"