#!/usr/bin/env python3 import random import sys import subprocess import os from fpdf import FPDF class MathExercisesPDF(FPDF): def header(self): self.set_font("Helvetica", "B", 16) self.cell( 0, 10, "Exercices de Multiplication et Division", 0, 1, "C", new_x="LMARGIN", new_y="NEXT", ) self.ln(10) def generate_exercises(min_table, max_table, num_exercises=15): """Génère des exercices de multiplication et division aléatoires mélangés sans doublons""" exercises = [] used_operations = set() # Pour éviter les doublons # Générer le nombre exact d'exercices demandé attempts = 0 max_attempts = num_exercises * 10 # Limite pour éviter une boucle infinie while len(exercises) < num_exercises and attempts < max_attempts: attempts += 1 # Choisir deux nombres aléatoires entre min_table et max_table a = random.randint(min_table, max_table) b = random.randint(min_table, max_table) result = a * b # Choisir aléatoirement le type d'exercice (seulement multiplication ou division) exercise_type = random.choice(["multiplication", "division"]) if exercise_type == "multiplication": # Exercice de multiplication operation_key = f"mult_{a}_{b}" # Clé unique pour cette opération if operation_key not in used_operations: exercise = f"{a} · {b} = ____" exercises.append(exercise) used_operations.add(operation_key) else: # division # Exercice de division divisor = random.choice([a, b]) operation_key = f"div_{result}_{divisor}" # Clé unique pour cette opération if operation_key not in used_operations: exercise = f"{result} : {divisor} = ____" exercises.append(exercise) used_operations.add(operation_key) # Si nous n'avons pas pu générer suffisamment d'exercices uniques, # compléter avec des variations if len(exercises) < num_exercises: remaining = num_exercises - len(exercises) for _ in range(remaining): # Générer des variations avec des nombres légèrement différents a = random.randint(min_table, max_table) b = random.randint(min_table, max_table) result = a * b # Choisir aléatoirement le type d'exercice exercise_type = random.choice(["multiplication", "division"]) if exercise_type == "multiplication": exercise = f"{a} · {b} = ____" else: # division divisor = random.choice([a, b]) exercise = f"{result} : {divisor} = ____" exercises.append(exercise) return exercises def create_math_exercises_pdf(min_table, max_table, num_exercises=15): """Crée un fichier PDF avec des exercices de mathématiques mélangés en 3 colonnes""" pdf = MathExercisesPDF() pdf.add_page() pdf.set_font("Helvetica", "", 12) # Ajouter des informations sur la plage de tables if min_table == max_table: table_info = f"Tables de multiplication et division pour {min_table}" else: table_info = ( f"Tables de multiplication et division de {min_table} à {max_table}" ) pdf.cell(0, 10, table_info, 0, 1, "C", new_x="LMARGIN", new_y="NEXT") pdf.ln(5) # Générer les exercices exercises = generate_exercises(min_table, max_table, num_exercises) # Pas d'en-têtes de colonnes # Répartir les exercices en 3 colonnes num_per_column = (num_exercises + 2) // 3 # Arrondi vers le haut col1_exercises = exercises[:num_per_column] col2_exercises = exercises[num_per_column : num_per_column * 2] col3_exercises = exercises[num_per_column * 2 :] # Ajouter les exercices numérotés de 1 à n dans les colonnes max_rows = max(len(col1_exercises), len(col2_exercises), len(col3_exercises)) for i in range(max_rows): # Colonne 1 if i < len(col1_exercises): exercise_num = i + 1 col1_text = f"{exercise_num}. {col1_exercises[i]}" else: col1_text = "" # Colonne 2 if i < len(col2_exercises): exercise_num = i + 1 + len(col1_exercises) col2_text = f"{exercise_num}. {col2_exercises[i]}" else: col2_text = "" # Colonne 3 if i < len(col3_exercises): exercise_num = i + 1 + len(col1_exercises) + len(col2_exercises) col3_text = f"{exercise_num}. {col3_exercises[i]}" else: col3_text = "" # Ajouter la ligne pdf.cell(60, 10, col1_text, 0, 0, "L", new_x="RIGHT", new_y="TOP") pdf.cell(60, 10, col2_text, 0, 0, "L", new_x="RIGHT", new_y="TOP") pdf.cell(60, 10, col3_text, 0, 1, "L", new_x="LMARGIN", new_y="NEXT") # Sauvegarder le PDF if min_table == max_table: filename = ( f"exercices_mathematiques_table_{min_table}_{num_exercises}_exercices.pdf" ) else: filename = f"exercices_mathematiques_tables_{min_table}_a_{max_table}_{num_exercises}_exercices.pdf" pdf.output(filename) return filename def open_pdf(filename): """Ouvre le fichier PDF avec la commande système appropriée""" try: if sys.platform == "darwin": # macOS subprocess.run(["open", filename], check=True) elif sys.platform == "win32": # Windows os.startfile(filename) else: # Linux et autres subprocess.run(["xdg-open", filename], check=True) return True except (subprocess.CalledProcessError, FileNotFoundError, OSError): return False def main(): """Fonction principale""" # Vérifier les arguments de ligne de commande if len(sys.argv) < 3: print( "Usage: python generate_math_exercises.py [num_exercises] [--open]" ) print("Exemple: python generate_math_exercises.py 4 7 15") print( " python generate_math_exercises.py 4 7 15 --open (pour ouvrir automatiquement le PDF)" ) print( " python generate_math_exercises.py 5 5 10 (pour seulement la table de 5)" ) sys.exit(1) # Vérifier si l'option --open est présente open_after_creation = "--open" in sys.argv if open_after_creation: sys.argv.remove("--open") # Retirer l'option de la liste des arguments try: min_table = int(sys.argv[1]) max_table = int(sys.argv[2]) if min_table < 1 or max_table < 1: raise ValueError("Les tables doivent être supérieures à 0") if min_table > max_table: raise ValueError( "La table minimale doit être inférieure ou égale à la table maximale" ) except ValueError as e: print(f"Erreur: {e}") sys.exit(1) # Nombre d'exercices (par défaut 15) num_exercises = 15 if len(sys.argv) > 3: try: num_exercises = int(sys.argv[3]) if num_exercises < 1: raise ValueError("Le nombre d'exercices doit être supérieur à 0") except ValueError as e: print(f"Erreur: {e}") sys.exit(1) # Créer le PDF try: filename = create_math_exercises_pdf(min_table, max_table, num_exercises) print(f"Fichier PDF '{filename}' créé avec succès !") if min_table == max_table: print(f"- Exercices pour la table de {min_table}") else: print(f"- Exercices pour les tables de {min_table} à {max_table}") print( f"- {num_exercises} exercices MÉLANGÉS générés aléatoirement et numérotés de 1 à {num_exercises}" ) print("- Types d'exercices : multiplications (·) et divisions (:) uniquement") print("- Présentés en 3 colonnes pour économiser l'espace") print("- Aucune opération en double (quand c'est possible)") # Ouvrir le PDF si demandé if open_after_creation: if open_pdf(filename): print("\nPDF ouvert automatiquement avec succès !") else: print( "\nImpossible d'ouvrir automatiquement le PDF. Vous pouvez l'ouvrir manuellement." ) except Exception as e: print(f"Erreur lors de la création du PDF: {e}") sys.exit(1) if __name__ == "__main__": main()