mirror of
https://github.com/DavidGailleton/42-Piscine_Python.git
synced 2026-04-28 16:14:35 +02:00
Compare commits
2 Commits
271d310f9b
...
1cf669e6f8
| Author | SHA1 | Date | |
|---|---|---|---|
| 1cf669e6f8 | |||
| 1dfeee81e3 |
@@ -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()
|
|
||||||
@@ -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:
|
try:
|
||||||
return sorted(artifacts, key=lambda artifact: artifact["power"])
|
return sorted(artifacts, key=lambda artifact: artifact["power"])
|
||||||
except KeyError as err:
|
except KeyError as err:
|
||||||
@@ -6,7 +9,9 @@ def artifact_sorter(artifacts: list[dict]) -> list[dict]:
|
|||||||
return artifacts
|
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:
|
try:
|
||||||
return list(filter(lambda x: x["power"] >= min_power, mages))
|
return list(filter(lambda x: x["power"] >= min_power, mages))
|
||||||
except KeyError as err:
|
except KeyError as err:
|
||||||
@@ -18,7 +23,7 @@ def spell_transformer(spells: list[str]) -> list[str]:
|
|||||||
return list(map(lambda x: "* " + x + " *", spells))
|
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:
|
try:
|
||||||
max_power = max(mages, key=lambda mage: mage["power"])
|
max_power = max(mages, key=lambda mage: mage["power"])
|
||||||
min_power = min(mages, key=lambda mage: mage["power"])
|
min_power = min(mages, key=lambda mage: mage["power"])
|
||||||
|
|||||||
@@ -1,22 +1,22 @@
|
|||||||
from typing import Callable
|
from typing import Any, Callable
|
||||||
|
|
||||||
|
|
||||||
def spell_combiner(spell1: Callable, spell2: Callable) -> 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 (spell1(*args), spell2(*args))
|
||||||
|
|
||||||
return combiner
|
return combiner
|
||||||
|
|
||||||
|
|
||||||
def power_amplifier(base_spell: Callable, multiplier: int) -> Callable:
|
def power_amplifier(base_spell: Callable, multiplier: int) -> Callable:
|
||||||
def multiplie(*args):
|
def multiply(*args: Any) -> Any:
|
||||||
return base_spell(*args) * multiplier
|
return base_spell(*args) * multiplier
|
||||||
|
|
||||||
return multiplie
|
return multiply
|
||||||
|
|
||||||
|
|
||||||
def conditional_caster(condition: Callable, spell: Callable) -> Callable:
|
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):
|
if condition(*args, **kwargs):
|
||||||
return spell(args[0])
|
return spell(args[0])
|
||||||
else:
|
else:
|
||||||
@@ -26,7 +26,7 @@ def conditional_caster(condition: Callable, spell: Callable) -> Callable:
|
|||||||
|
|
||||||
|
|
||||||
def spell_sequence(spells: list[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 [res(*args, **kwargs) for res in spells]
|
||||||
|
|
||||||
return sequence
|
return sequence
|
||||||
@@ -56,7 +56,7 @@ def main() -> None:
|
|||||||
|
|
||||||
print("\n=== power_amplifier ===")
|
print("\n=== power_amplifier ===")
|
||||||
amplifier = power_amplifier(pow_2, 4)
|
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 ===")
|
print("\n=== conditional_caster ===")
|
||||||
caster = conditional_caster(isinstance, fireball)
|
caster = conditional_caster(isinstance, fireball)
|
||||||
|
|||||||
@@ -34,7 +34,6 @@ def memory_vault() -> dict[str, Callable]:
|
|||||||
storage = {}
|
storage = {}
|
||||||
|
|
||||||
def store(to_store: dict[str, str]) -> None:
|
def store(to_store: dict[str, str]) -> None:
|
||||||
nonlocal storage
|
|
||||||
for data in to_store:
|
for data in to_store:
|
||||||
storage[data] = to_store[data]
|
storage[data] = to_store[data]
|
||||||
|
|
||||||
@@ -47,7 +46,7 @@ def memory_vault() -> dict[str, Callable]:
|
|||||||
return {"store": store, "recall": recall}
|
return {"store": store, "recall": recall}
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main() -> None:
|
||||||
print("===mage_counter===\n")
|
print("===mage_counter===\n")
|
||||||
count = mage_counter()
|
count = mage_counter()
|
||||||
print(f"1 : {count()}")
|
print(f"1 : {count()}")
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
from functools import lru_cache, reduce, partial, singledispatch
|
from functools import lru_cache, reduce, partial, singledispatch
|
||||||
import operator as op
|
import operator as op
|
||||||
import re
|
|
||||||
from typing import Callable, Any
|
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:
|
def memoized_fibonacci(n: int) -> int:
|
||||||
if n < 2:
|
if n < 2:
|
||||||
return n
|
return n
|
||||||
@@ -35,7 +35,7 @@ def memoized_fibonacci(n: int) -> int:
|
|||||||
|
|
||||||
def spell_dispatcher() -> Callable:
|
def spell_dispatcher() -> Callable:
|
||||||
@singledispatch
|
@singledispatch
|
||||||
def basic(arg: Any) -> str:
|
def basic(arg: Any) -> Any:
|
||||||
return arg
|
return arg
|
||||||
|
|
||||||
@basic.register(int)
|
@basic.register(int)
|
||||||
@@ -47,7 +47,7 @@ def spell_dispatcher() -> Callable:
|
|||||||
return f"apply {arg}"
|
return f"apply {arg}"
|
||||||
|
|
||||||
@basic.register(list)
|
@basic.register(list)
|
||||||
def basic_list(arg: list) -> str:
|
def basic_list(arg: list[Any]) -> str:
|
||||||
res = ""
|
res = ""
|
||||||
for cast in arg:
|
for cast in arg:
|
||||||
res += f"cast {cast}\n"
|
res += f"cast {cast}\n"
|
||||||
|
|||||||
+67
-11
@@ -5,43 +5,99 @@ from functools import wraps
|
|||||||
|
|
||||||
def spell_timer(func: Callable) -> Callable:
|
def spell_timer(func: Callable) -> Callable:
|
||||||
@wraps(func)
|
@wraps(func)
|
||||||
def print_time(*args, **kwargs) -> Any:
|
def print_time(*args: Any, **kwargs: Any) -> Any:
|
||||||
print(f"Casting {func.__name__}")
|
print(f"Casting {func.__name__}")
|
||||||
start = time.time()
|
start = time.time()
|
||||||
res = func(args, kwargs)
|
res = func(*args, **kwargs)
|
||||||
print(f"Spell completed int {time.time() - start} seconds")
|
print(f"Spell completed int {(time.time() - start):.3f} seconds")
|
||||||
return res
|
return res
|
||||||
|
|
||||||
return print_time
|
return print_time
|
||||||
|
|
||||||
|
|
||||||
def power_validator(min_power: int) -> Callable:
|
def power_validator(min_power: int) -> Callable:
|
||||||
def check_power(power: int, func: Callable) -> str | Any:
|
def check_power(func: Callable) -> str | Any:
|
||||||
|
@wraps(func)
|
||||||
|
def fn(*args: Any) -> str | Any:
|
||||||
try:
|
try:
|
||||||
if power < min_power:
|
if args[2] < min_power:
|
||||||
return "Insufficient power for this spell"
|
return "Insufficient power for this spell"
|
||||||
return func()
|
return func(*args)
|
||||||
except Exception:
|
except Exception as err:
|
||||||
|
print(err)
|
||||||
return "invalid input"
|
return "invalid input"
|
||||||
|
|
||||||
|
return fn
|
||||||
|
|
||||||
return check_power
|
return check_power
|
||||||
|
|
||||||
|
|
||||||
def retry_spell(max_attempts: int) -> Callable:
|
def retry_spell(max_attempts: int) -> Callable:
|
||||||
def try_spell(func: Callable) -> str | Any:
|
def try_spell(func: Callable) -> str | Any:
|
||||||
|
@wraps(func)
|
||||||
|
def fn(*args: Any) -> Any:
|
||||||
for i in range(max_attempts):
|
for i in range(max_attempts):
|
||||||
try:
|
try:
|
||||||
return func()
|
return func(*args)
|
||||||
except Exception:
|
except Exception:
|
||||||
print(f"Spell failed, retrying... ({i + 1}/{max_attempts})")
|
print(
|
||||||
|
f"Spell failed, retrying... ({i + 1}/{max_attempts})"
|
||||||
|
)
|
||||||
continue
|
continue
|
||||||
return f"Spell casting failed after {max_attempts} attempts"
|
return f"Spell casting failed after {max_attempts} attempts"
|
||||||
|
|
||||||
|
return fn
|
||||||
|
|
||||||
return try_spell
|
return try_spell
|
||||||
|
|
||||||
|
|
||||||
class MageGuild:
|
class MageGuild:
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def validate_mage_name(name: str) -> bool: ...
|
def validate_mage_name(name: str) -> bool:
|
||||||
|
return len(name) >= 3 and all(x.isalpha() or x.isspace() for x in name)
|
||||||
|
|
||||||
def cast_spell(self, spell_name: str, power: int) -> str: ...
|
@power_validator(10)
|
||||||
|
def cast_spell(self, spell_name: str, power: int) -> str:
|
||||||
|
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!"
|
||||||
|
|
||||||
|
@retry_spell(3)
|
||||||
|
def make_exception(exception: Exception) -> None:
|
||||||
|
raise exception
|
||||||
|
|
||||||
|
guild = MageGuild()
|
||||||
|
|
||||||
|
print("===spell_timer===\n")
|
||||||
|
print(f"Result: {fireball()}")
|
||||||
|
|
||||||
|
print("\n===power_validator===\n")
|
||||||
|
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")
|
||||||
|
print(f"Invalid: {make_exception(Exception())}")
|
||||||
|
|
||||||
|
print("\n======MageGuild======\n")
|
||||||
|
print("\n===validate_mage_name===\n")
|
||||||
|
print(f"Less than 3 chars: {MageGuild.validate_mage_name('op')}")
|
||||||
|
print(f"Special char: {MageGuild.validate_mage_name('ope!')}")
|
||||||
|
print(
|
||||||
|
"valid: "
|
||||||
|
f"{MageGuild.validate_mage_name('Bonjour a tous c est vendredi')}"
|
||||||
|
)
|
||||||
|
|
||||||
|
print("\n===cast_spell===\n")
|
||||||
|
print(f"Valid: {guild.cast_spell('Lightning', 15)}")
|
||||||
|
print(f"Invalid: {guild.cast_spell('Lightning', 5)}")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
|
|||||||
Reference in New Issue
Block a user