diff --git a/10/data_generator.py b/10/data_generator.py new file mode 100644 index 0000000..64389f8 --- /dev/null +++ b/10/data_generator.py @@ -0,0 +1,222 @@ +""" +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 3901310..5d98fa9 100644 --- a/10/ex0/lambda_spells.py +++ b/10/ex0/lambda_spells.py @@ -1,14 +1,73 @@ def artifact_sorter(artifacts: list[dict]) -> list[dict]: - return sorted(artifacts, key=lambda artifact: artifact["power"]) + try: + return sorted(artifacts, key=lambda artifact: artifact["power"]) + except KeyError as err: + print(err) + return artifacts def power_filter(mages: list[dict], min_power: int) -> list[dict]: - return list(filter(lambda x: x["power"] >= min_power, mages)) + try: + return list(filter(lambda x: x["power"] >= min_power, mages)) + except KeyError as err: + print(err) + return mages def spell_transformer(spells: list[str]) -> list[str]: - pass + return list(map(lambda x: "* " + x + " *", spells)) def mage_stats(mages: list[dict]) -> dict: - pass + try: + max_power = max(mages, key=lambda mage: mage["power"]) + min_power = min(mages, key=lambda mage: mage["power"]) + avg_power = sum(map(lambda mage: mage["power"], mages)) / len(mages) + return { + "max_power": max_power["power"], + "min_power": min_power["power"], + "avg_power": round(avg_power, 2), + } + except Exception: + return { + "max_power": 0, + "min_power": 0, + "avg_power": 0, + } + + +def main() -> None: + try: + artifacts = [ + {"power": 30}, + {"power": 10}, + {"power": 300}, + {"power": 400}, + {"power": 200}, + {"power": 3}, + {"power": 10}, + ] + str_list = [ + "Hello", + "World", + "Lorem", + "ipsum", + ] + + print("=== artifact_sorter ===") + print(f"Sorted artifacts: {artifact_sorter(artifacts)}") + + print("\n=== power_filter ===") + print(f"Filtered artifacts: {power_filter(artifacts, 100)}") + + print("\n=== spell_transformer ===") + print(f"Transformed str: {spell_transformer(str_list)}") + + print("\n=== mage_stats ===") + print(f"Get power info: {mage_stats(artifacts)}") + except Exception as err: + print(err) + + +if __name__ == "__main__": + main() diff --git a/10/ex1/higher_magic.py b/10/ex1/higher_magic.py new file mode 100644 index 0000000..3bbd423 --- /dev/null +++ b/10/ex1/higher_magic.py @@ -0,0 +1,69 @@ +from typing import Callable + + +def spell_combiner(spell1: Callable, spell2: Callable) -> Callable: + def combiner(*args): + return (spell1(*args), spell2(*args)) + + return combiner + + +def power_amplifier(base_spell: Callable, multiplier: int) -> Callable: + def multiplie(*args): + return base_spell(*args) * multiplier + + return multiplie + + +def conditional_caster(condition: Callable, spell: Callable) -> Callable: + def cond_res(*args, **kwargs): + if condition(*args, **kwargs): + return spell(args[0]) + else: + return "Spell fizzled" + + return cond_res + + +def spell_sequence(spells: list[Callable]) -> Callable: + def sequence(*args, **kwargs): + return [res(*args, **kwargs) for res in spells] + + return sequence + + +def fireball(target: str) -> str: + return f"Fireball hits {target}" + + +def heal(target: str) -> str: + return f"Heals {target}" + + +def pow_2(nb: int) -> int: + return nb * nb + + +def main() -> None: + try: + print("=== spell_combiner ===") + combiner = spell_combiner(fireball, heal) + print(f"Combine fireball and heal: {combiner('dragon')}") + + print("\n=== power_amplifier ===") + amplifier = power_amplifier(pow_2, 4) + print(f"multiplie 5 pow_2 by 4: {amplifier(5)}") + + print("\n=== conditional_caster ===") + caster = conditional_caster(isinstance, fireball) + print(f"Valid: {caster('dragon', str)}") + print(f"Invalid: {caster(2, str)}") + + print("\n=== spell_sequence ===") + sequencer = spell_sequence([fireball, heal, isinstance]) + except Exception as err: + print(err) + + +if __name__ == "__main__": + main()