diff --git a/pr 5/coins.py b/pr 5/coins.py new file mode 100644 index 0000000..93bb1ad --- /dev/null +++ b/pr 5/coins.py @@ -0,0 +1,26 @@ +from functools import lru_cache +from timing import timing + + +def count_change_memoized(amount, coins=(1, 2, 5, 10, 20, 50)): + """Münzwechsel-Problem mit LRU-Cache für Performanz-Optimierung.""" + + @lru_cache(maxsize=None) + def helper(n, coin_index): + if n == 0: + return 1 # Betrag exakt gewechselt + if n < 0 or coin_index >= len(coins): + return 0 # Betrag unterschritten oder keine Münzen mehr übrig + + # Möglichkeit 1: Münze verwenden + Möglichkeit 2: Münze überspringen + return helper(n - coins[coin_index], coin_index) + helper( + n, coin_index + 1 + ) + + return helper(amount, 0) + + +# Testen +betrag = 100 +anzahl = timing(count_change_memoized)(betrag) +print(f"Möglichkeiten für {betrag} Cent: {anzahl}") \ No newline at end of file diff --git a/pr 5/run_once.py b/pr 5/run_once.py new file mode 100644 index 0000000..6a15d32 --- /dev/null +++ b/pr 5/run_once.py @@ -0,0 +1,35 @@ +from functools import wraps + + +def run_once(func): + has_run = False + result = None + + @wraps(func) + def wrapper(*args, **kwargs): + nonlocal has_run, result + if not has_run: + result = func(*args, **kwargs) + has_run = True + return result + else: + print( + f"Hinweis: '{func.__name__}' wurde bereits ausgeführt und wird" + " übersprungen." + ) + return result + + return wrapper + + +# Testen der Funktionalität +@run_once +def initialisiere_datenbank(): + print("--> Datenbankverbindung wird aufgebaut...") + return "DB_OK" + + +# Aufrufe testen +print(initialisiere_datenbank()) # Führt die Funktion aus +print(initialisiere_datenbank()) # Wird übersprungen, gibt gemerktes Ergebnis zurück +print(initialisiere_datenbank()) # Wird ebenfalls übersprungen \ No newline at end of file diff --git a/pr 5/stairs.py b/pr 5/stairs.py new file mode 100644 index 0000000..f143f08 --- /dev/null +++ b/pr 5/stairs.py @@ -0,0 +1,42 @@ +from timing import timing + +# Naive rekursive Funktion (ohne Decorator oben drüber, um rekursiven Spam zu vermeiden) +def ways(n): + if n <= 1: + return 1 + return ways(n - 1) + ways(n - 2) + + +# Memoization-Variante mit Dictionary-Cache +def ways_memoized(n, cache=None): + if cache is None: + cache = {} + if n in cache: + return cache[n] + if n <= 1: + return 1 + + cache[n] = ways_memoized(n - 1, cache) + ways_memoized(n - 2, cache) + return cache[n] + + +# Alternativ: Mit functools.lru_cache (Python-Standardweg) +from functools import lru_cache + + +@lru_cache(maxsize=None) +def ways_fast(n): + if n <= 1: + return 1 + return ways_fast(n - 1) + ways_fast(n - 2) + + +# Laufzeitmessung (wie im Hinweis über den äußeren Aufruf) +print("--- Naive Variante ---") +timing(ways)(35) + +print("\n--- Manuelle Memoization ---") +timing(ways_memoized)(35) + +print("\n--- Mit functools.lru_cache ---") +timing(ways_fast)(35) \ No newline at end of file diff --git a/pr 5/timing.py b/pr 5/timing.py new file mode 100644 index 0000000..49ac9ee --- /dev/null +++ b/pr 5/timing.py @@ -0,0 +1,28 @@ +from functools import wraps +import time + + +def timing(func): + """Decorator zur Messung der Ausführungszeit einer Funktion.""" + + @wraps(func) + def wrapper(*args, **kwargs): + start_time = time.perf_counter() + result = func(*args, **kwargs) + end_time = time.perf_counter() + elapsed = end_time - start_time + print(f"[{func.__name__}] Laufzeit: {elapsed:.6f} Sekunden") + return result + + return wrapper + +from timing import timing + + +@timing +def beispiel_funktion(): + """Dies ist eine Testfunktion.""" + pass + + +help(beispiel_funktion) \ No newline at end of file diff --git a/ungerade-zahlen.py b/ungerade-zahlen.py new file mode 100644 index 0000000..aff8aec --- /dev/null +++ b/ungerade-zahlen.py @@ -0,0 +1,9 @@ +def odd(limit): + current = 1 + while current <= limit: + yield current + current += 2 + + +# Testen +print(list(odd(10))) # Ausgabe: [1, 3, 5, 7, 9] \ No newline at end of file