diff --git a/10/data_generator.py b/10/data_generator.py deleted file mode 100644 index 64389f8..0000000 --- a/10/data_generator.py +++ /dev/null @@ -1,222 +0,0 @@ -""" -FuncMage Chronicles - Data Generator Helper -Generates test data for all exercises to help learners test their -implementations -""" - -import random -from typing import List, Dict, Any - - -class FuncMageDataGenerator: - """Generate test data for FuncMage Chronicles exercises.""" - - # Fantasy-themed data pools - MAGE_NAMES = [ - "Alex", - "Jordan", - "Riley", - "Casey", - "Morgan", - "Sage", - "River", - "Phoenix", - "Ember", - "Storm", - "Luna", - "Nova", - "Zara", - "Kai", - "Rowan", - "Ash"] - - ELEMENTS = [ - "fire", - "ice", - "lightning", - "earth", - "wind", - "water", - "light", - "shadow"] - - SPELL_NAMES = [ - "fireball", "heal", "shield", "lightning", "freeze", "earthquake", - "tornado", "tsunami", "flash", "darkness", "meteor", "blizzard" - ] - - ARTIFACT_NAMES = [ - "Crystal Orb", - "Fire Staff", - "Ice Wand", - "Lightning Rod", - "Earth Shield", - "Wind Cloak", - "Water Chalice", - "Shadow Blade", - "Light Prism", - "Storm Crown"] - - ARTIFACT_TYPES = ["weapon", "focus", "armor", "accessory", "relic"] - - ENCHANTMENT_TYPES = [ - "Flaming", - "Frozen", - "Shocking", - "Earthen", - "Windy", - "Flowing", - "Radiant", - "Dark"] - - @classmethod - def generate_mages(cls, count: int = 5) -> List[Dict[str, Any]]: - """Generate a list of mages with random attributes.""" - mages = [] - for _ in range(count): - mage = { - 'name': random.choice(cls.MAGE_NAMES), - 'power': random.randint(50, 100), - 'element': random.choice(cls.ELEMENTS) - } - mages.append(mage) - return mages - - @classmethod - def generate_artifacts(cls, count: int = 5) -> List[Dict[str, Any]]: - """Generate a list of magical artifacts.""" - artifacts = [] - for _ in range(count): - artifact = { - 'name': random.choice(cls.ARTIFACT_NAMES), - 'power': random.randint(60, 120), - 'type': random.choice(cls.ARTIFACT_TYPES) - } - artifacts.append(artifact) - return artifacts - - @classmethod - def generate_spells(cls, count: int = 6) -> List[str]: - """Generate a list of spell names.""" - return random.sample(cls.SPELL_NAMES, min(count, len(cls.SPELL_NAMES))) - - @classmethod - def generate_spell_powers(cls, count: int = 5) -> List[int]: - """Generate a list of spell power values.""" - return [random.randint(10, 50) for _ in range(count)] - - @classmethod - def generate_enchantment_items(cls, count: int = 5) -> List[str]: - """Generate a list of items to be enchanted.""" - items = [ - "Sword", - "Shield", - "Staff", - "Wand", - "Armor", - "Ring", - "Amulet", - "Cloak"] - return random.sample(items, min(count, len(items))) - - @classmethod - def print_exercise_data(cls, exercise_num: int): - """Print formatted test data for a specific exercise.""" - print(f"=== Exercise {exercise_num} Test Data ===") - - if exercise_num == 0: - print("# Lambda Sanctum Test Data") - print("artifacts =", cls.generate_artifacts(4)) - print("mages =", cls.generate_mages(5)) - print("spells =", cls.generate_spells(4)) - - elif exercise_num == 1: - print("# Higher Realm Test Data") - print("# Use these in your test functions:") - print("test_values =", [random.randint(5, 25) for _ in range(3)]) - print("test_targets =", ["Dragon", "Goblin", "Wizard", "Knight"]) - - elif exercise_num == 2: - print("# Memory Depths Test Data") - print( - "initial_powers =", [ - random.randint( - 20, 80) for _ in range(3)]) - print( - "power_additions =", [ - random.randint( - 5, 20) for _ in range(5)]) - print( - "enchantment_types =", - random.sample( - cls.ENCHANTMENT_TYPES, - 3)) - print("items_to_enchant =", cls.generate_enchantment_items(4)) - - elif exercise_num == 3: - print("# Ancient Library Test Data") - print("spell_powers =", cls.generate_spell_powers(6)) - print("operations = ['add', 'multiply', 'max', 'min']") - print( - "fibonacci_tests =", [ - random.randint( - 8, 20) for _ in range(3)]) - - elif exercise_num == 4: - print("# Master's Tower Test Data") - print("test_powers =", [random.randint(5, 30) for _ in range(4)]) - print("spell_names =", random.sample(cls.SPELL_NAMES, 4)) - print("mage_names =", random.sample(cls.MAGE_NAMES, 6)) - print("invalid_names = ['Jo', 'A', 'Alex123', 'Test@Name']") - - print() - - -def main(): - """Interactive data generator for FuncMage Chronicles.""" - print("🧙‍♀️ FuncMage Chronicles - Data Generator Helper 🧙‍♂️") - print("=" * 50) - print() - - while True: - print("Choose an option:") - print("0. Generate data for Exercise 0 (Lambda Sanctum)") - print("1. Generate data for Exercise 1 (Higher Realm)") - print("2. Generate data for Exercise 2 (Memory Depths)") - print("3. Generate data for Exercise 3 (Ancient Library)") - print("4. Generate data for Exercise 4 (Master's Tower)") - print("5. Generate data for ALL exercises") - print("6. Generate custom mage data") - print("7. Generate custom artifact data") - print("q. Quit") - print() - - choice = input("Enter your choice: ").strip().lower() - - if choice == 'q': - print("May your functions be pure and your closures be strong! 🌟") - break - elif choice in ['0', '1', '2', '3', '4']: - FuncMageDataGenerator.print_exercise_data(int(choice)) - elif choice == '5': - for i in range(5): - FuncMageDataGenerator.print_exercise_data(i) - elif choice == '6': - count = int( - input("How many mages to generate? (default 5): ") or 5) - print("mages =", FuncMageDataGenerator.generate_mages(count)) - print() - elif choice == '7': - count = int( - input("How many artifacts to generate? (default 5): ") or 5) - print( - "artifacts =", - FuncMageDataGenerator.generate_artifacts(count)) - print() - else: - print("Invalid choice. Please try again.") - print() - - -if __name__ == "__main__": - main() diff --git a/10/ex0/lambda_spells.py b/10/ex0/lambda_spells.py index 5d98fa9..12a73ca 100644 --- a/10/ex0/lambda_spells.py +++ b/10/ex0/lambda_spells.py @@ -1,4 +1,7 @@ -def artifact_sorter(artifacts: list[dict]) -> list[dict]: +from typing import Any + + +def artifact_sorter(artifacts: list[dict[Any, Any]]) -> list[dict[Any, Any]]: try: return sorted(artifacts, key=lambda artifact: artifact["power"]) except KeyError as err: @@ -6,7 +9,9 @@ def artifact_sorter(artifacts: list[dict]) -> list[dict]: return artifacts -def power_filter(mages: list[dict], min_power: int) -> list[dict]: +def power_filter( + mages: list[dict[Any, Any]], min_power: int +) -> list[dict[Any, Any]]: try: return list(filter(lambda x: x["power"] >= min_power, mages)) except KeyError as err: @@ -18,7 +23,7 @@ def spell_transformer(spells: list[str]) -> list[str]: return list(map(lambda x: "* " + x + " *", spells)) -def mage_stats(mages: list[dict]) -> dict: +def mage_stats(mages: list[dict[Any, Any]]) -> dict[str, int | float]: try: max_power = max(mages, key=lambda mage: mage["power"]) min_power = min(mages, key=lambda mage: mage["power"]) diff --git a/10/ex1/higher_magic.py b/10/ex1/higher_magic.py index f5323e3..822a368 100644 --- a/10/ex1/higher_magic.py +++ b/10/ex1/higher_magic.py @@ -1,22 +1,22 @@ -from typing import Callable +from typing import Any, Callable def spell_combiner(spell1: Callable, spell2: Callable) -> Callable: - def combiner(*args): + def combiner(*args: Any) -> tuple[Any, Any]: return (spell1(*args), spell2(*args)) return combiner def power_amplifier(base_spell: Callable, multiplier: int) -> Callable: - def multiplie(*args): + def multiply(*args: Any) -> Any: return base_spell(*args) * multiplier - return multiplie + return multiply def conditional_caster(condition: Callable, spell: Callable) -> Callable: - def cond_res(*args, **kwargs): + def cond_res(*args: Any, **kwargs: Any) -> Any: if condition(*args, **kwargs): return spell(args[0]) else: @@ -26,7 +26,7 @@ def conditional_caster(condition: Callable, spell: Callable) -> Callable: def spell_sequence(spells: list[Callable]) -> Callable: - def sequence(*args, **kwargs): + def sequence(*args: Any, **kwargs: Any) -> list[Any]: return [res(*args, **kwargs) for res in spells] return sequence @@ -56,7 +56,7 @@ def main() -> None: print("\n=== power_amplifier ===") amplifier = power_amplifier(pow_2, 4) - print(f"multiplie 5 pow_2 by 4: {amplifier(5)}") + print(f"multiply 5 pow_2 by 4: {amplifier(5)}") print("\n=== conditional_caster ===") caster = conditional_caster(isinstance, fireball) diff --git a/10/ex2/scope_mysteries.py b/10/ex2/scope_mysteries.py index 4388e68..d91ec3d 100644 --- a/10/ex2/scope_mysteries.py +++ b/10/ex2/scope_mysteries.py @@ -34,7 +34,6 @@ def memory_vault() -> dict[str, Callable]: storage = {} def store(to_store: dict[str, str]) -> None: - nonlocal storage for data in to_store: storage[data] = to_store[data] @@ -47,7 +46,7 @@ def memory_vault() -> dict[str, Callable]: return {"store": store, "recall": recall} -def main(): +def main() -> None: print("===mage_counter===\n") count = mage_counter() print(f"1 : {count()}") diff --git a/10/ex3/functools_artifacts.py b/10/ex3/functools_artifacts.py index f818d1e..5079d7f 100644 --- a/10/ex3/functools_artifacts.py +++ b/10/ex3/functools_artifacts.py @@ -1,6 +1,5 @@ from functools import lru_cache, reduce, partial, singledispatch import operator as op -import re from typing import Callable, Any @@ -27,6 +26,7 @@ def partial_enchanter(base_enchantment: Callable) -> dict[str, Callable]: } +@lru_cache def memoized_fibonacci(n: int) -> int: if n < 2: return n @@ -35,7 +35,7 @@ def memoized_fibonacci(n: int) -> int: def spell_dispatcher() -> Callable: @singledispatch - def basic(arg: Any) -> str: + def basic(arg: Any) -> Any: return arg @basic.register(int) @@ -47,7 +47,7 @@ def spell_dispatcher() -> Callable: return f"apply {arg}" @basic.register(list) - def basic_list(arg: list) -> str: + def basic_list(arg: list[Any]) -> str: res = "" for cast in arg: res += f"cast {cast}\n" diff --git a/10/ex4/decorator_mastery.py b/10/ex4/decorator_mastery.py index 6390f19..c47e7ba 100644 --- a/10/ex4/decorator_mastery.py +++ b/10/ex4/decorator_mastery.py @@ -5,7 +5,7 @@ from functools import wraps def spell_timer(func: Callable) -> Callable: @wraps(func) - def print_time(*args, **kwargs) -> Any: + def print_time(*args: Any, **kwargs: Any) -> Any: print(f"Casting {func.__name__}") start = time.time() res = func(*args, **kwargs) @@ -16,26 +16,37 @@ def spell_timer(func: Callable) -> Callable: def power_validator(min_power: int) -> Callable: - def check_power(power: int, func: Callable) -> str | Any: - try: - if power < min_power: - return "Insufficient power for this spell" - return func() - except Exception: - return "invalid input" + def check_power(func: Callable) -> str | Any: + @wraps(func) + def fn(*args: Any) -> str | Any: + try: + if args[2] < min_power: + return "Insufficient power for this spell" + return func(*args) + except Exception as err: + print(err) + return "invalid input" + + return fn return check_power def retry_spell(max_attempts: int) -> Callable: def try_spell(func: Callable) -> str | Any: - for i in range(max_attempts): - try: - return func() - except Exception: - print(f"Spell failed, retrying... ({i + 1}/{max_attempts})") - continue - return f"Spell casting failed after {max_attempts} attempts" + @wraps(func) + def fn(*args: Any) -> Any: + for i in range(max_attempts): + try: + return func(*args) + except Exception: + print( + f"Spell failed, retrying... ({i + 1}/{max_attempts})" + ) + continue + return f"Spell casting failed after {max_attempts} attempts" + + return fn return try_spell @@ -45,34 +56,34 @@ class MageGuild: def validate_mage_name(name: str) -> bool: return len(name) >= 3 and all(x.isalpha() or x.isspace() for x in name) + @power_validator(10) def cast_spell(self, spell_name: str, power: int) -> str: - def cast() -> str: - return f"Successfully cast {spell_name} with {power} power" - - validator = power_validator(10) - return validator(power, cast) + return f"Successfully cast {spell_name} with {power} power" def main() -> None: + import time + + @spell_timer def fireball() -> str: + time.sleep(0.5) return "Fireball cast!" - def make_exception() -> None: - raise Exception + @retry_spell(3) + def make_exception(exception: Exception) -> None: + raise exception + + guild = MageGuild() print("===spell_timer===\n") - timer = spell_timer(fireball) - print(f"Result: {timer()}") + print(f"Result: {fireball()}") print("\n===power_validator===\n") - validator = power_validator(10) - print(f"Valid: {validator(15, fireball)}") - print(f"Invalid: {validator(5, fireball)}") + print(f"Valid: {guild.cast_spell('meteorite de caca', 15)}") + print(f"INvalid: {guild.cast_spell('meteorite de caca', 5)}") print("\n===retry_spell===\n") - retry = retry_spell(3) - print(f"Valid: {retry(fireball)}") - print(f"Invalid: {retry(make_exception)}") + print(f"Invalid: {make_exception(Exception())}") print("\n======MageGuild======\n") print("\n===validate_mage_name===\n") @@ -84,7 +95,6 @@ def main() -> None: ) print("\n===cast_spell===\n") - guild = MageGuild() print(f"Valid: {guild.cast_spell('Lightning', 15)}") print(f"Invalid: {guild.cast_spell('Lightning', 5)}")