# Fonctionnalité de retrait de lettres ## Vue d'ensemble La fonctionnalité de retrait de lettres permet de générer des anagrammes plus prononçables en supprimant stratégiquement certaines lettres du mot source. Cette approche est particulièrement utile pour créer des pseudonymes à partir de mots difficiles à prononcer. ## Motivation Certains mots contiennent des combinaisons de lettres qui rendent difficile la création d'anagrammes prononçables : - Mots avec peu ou pas de voyelles (ex: "rhythm", "strength") - Mots avec de nombreuses consonnes consécutives - Mots longs avec une distribution difficile de lettres Le retrait stratégique de lettres permet d'augmenter considérablement le taux de réussite et la qualité des pseudonymes générés. ## Utilisation ### Option CLI ```bash -r, --remove-letters ``` Autorise le retrait jusqu'à `` lettres pour maximiser la prononçabilité. ### Exemples #### Mot difficile sans voyelles ```bash # Sans retrait : aucun résultat avec score ≥ 60 cargo run -- --word bcdfghjkl --count 5 --min-score 60 # Résultat: No anagrams generated. # Avec retrait : résultats possibles cargo run -- --word bcdfghjkl --count 5 --min-score 40 --remove-letters 5 ``` #### Mot avec consonnes consécutives ```bash # Sans retrait cargo run -- --word strength --count 10 --min-score 60 # Résultat: No anagrams generated. # Avec retrait de 2 lettres cargo run -- --word strength --count 10 --min-score 60 --remove-letters 2 # Résultats: thsetr, rtethg, trgent, hgestn, etc. ``` ## Algorithme ### Stratégie adaptative L'algorithme utilise une stratégie `LetterRemovalStrategy::Adaptive` qui : 1. **Explore différentes configurations** : Teste 0, 1, 2, ..., N retraits de lettres 2. **Sélection aléatoire** : Choisit aléatoirement quelles lettres retirer 3. **Critères de sélection** : - Priorise le **score de prononçabilité** le plus élevé - À score égal, préfère les **mots plus longs** (moins de retraits) ### Pseudo-code ``` pour chaque tentative de génération: meilleur_anagramme = None pour nombre_retraits de 0 à max_removals: lettres_gardées = sélection_aléatoire(source, taille - nombre_retraits) anagramme_candidat = mélanger(lettres_gardées) score = évaluer_prononçabilité(anagramme_candidat) si score >= score_minimum: si meilleur_anagramme == None ou score > meilleur_score: meilleur_anagramme = anagramme_candidat sinon si score == meilleur_score et len(candidat) > len(meilleur): meilleur_anagramme = anagramme_candidat retourner meilleur_anagramme ``` ### Limites - **Longueur minimale** : Au moins 1 lettre doit rester - **Limite de retrait** : `min(max_removals, len(mot) - 2)` - **Pas de retrait excessif** : Garde au moins 2 caractères pour maintenir un sens ## Architecture logicielle ### Enum `LetterRemovalStrategy` ```rust pub enum LetterRemovalStrategy { /// No letters will be removed None, /// Remove up to N letters to maximize pronounceability Adaptive { max_removals: usize }, } ``` ### Configuration ```rust // Par défaut : pas de retrait let config = GenerationConfig::default(); assert_eq!(config.letter_removal, LetterRemovalStrategy::None); // Avec retrait let config = GenerationConfig::default() .allow_removing_letters(3); // Ou explicitement let config = GenerationConfig::default() .with_letter_removal(LetterRemovalStrategy::Adaptive { max_removals: 3 }); ``` ### Méthodes du générateur ```rust impl AnagramGenerator { // Point d'entrée selon la stratégie fn try_generate_one(...) -> Option // Génération sans retrait (comportement original) fn try_generate_without_removal(...) -> Option // Génération avec retrait adaptatif fn try_generate_with_removal(...) -> Option // Essai avec un nombre spécifique de retraits fn try_with_specific_removals(...) -> Option } ``` ## Tests ### Couverture des tests 10 tests dédiés dans [tests/letter_removal_tests.rs](tests/letter_removal_tests.rs) : 1. **Configuration** : - `test_letter_removal_disabled_by_default` - `test_letter_removal_can_be_enabled` - `test_config_builder_with_letter_removal` - `test_letter_removal_strategy_with_method` 2. **Comportement** : - `test_generation_without_removal_produces_same_length` - `test_generation_with_removal_may_produce_shorter_words` - `test_letter_removal_respects_max_removals` - `test_letter_removal_maintains_min_word_length` 3. **Efficacité** : - `test_letter_removal_improves_pronounceability` - `test_letter_removal_with_good_word` ### Exécuter les tests ```bash # Tous les tests cargo test # Tests spécifiques au retrait de lettres cargo test --test letter_removal_tests # Un test particulier cargo test test_letter_removal_improves_pronounceability ``` ## Performance ### Impact sur le temps d'exécution Le retrait de lettres ajoute une complexité computationnelle : - **Sans retrait** : O(1) par tentative (un seul shuffle) - **Avec retrait (N max)** : O(N) par tentative (N+1 shuffles) ### Optimisations 1. **Early exit** : Si un score parfait est atteint avec 0 retrait, arrêt immédiat 2. **Limite adaptative** : Ne teste pas plus de retraits que nécessaire 3. **Sélection intelligente** : Préfère les mots plus longs à score égal ### Recommandations - **Petites valeurs** : Utilisez `--remove-letters 2-3` pour la plupart des cas - **Valeurs moyennes** : `--remove-letters 4-5` pour des mots très difficiles - **Augmentez les tentatives** : Combinez avec `--max-attempts 5000+` pour des mots problématiques ## Cas d'usage ### 1. Génération de pseudonymes courts ```bash cargo run -- --word "christopher" --count 10 --min-score 70 --remove-letters 5 # Génère des pseudonymes de 8-13 lettres prononçables ``` ### 2. Mots techniques ou étrangers ```bash cargo run -- --word "krzyzewski" --count 5 --min-score 50 --remove-letters 4 # Adapte des mots difficiles en pseudonymes prononçables ``` ### 3. Amélioration du taux de réussite ```bash # Faible taux de réussite sans retrait cargo run -- --word "complexity" --count 20 --min-score 75 # Meilleur taux avec retrait cargo run -- --word "complexity" --count 20 --min-score 75 --remove-letters 3 ``` ### 4. Création de noms de marque ```bash cargo run -- --word "innovative" --count 15 --min-score 80 --remove-letters 2 # Génère des noms courts et mémorables ``` ## Principes SOLID respectés ### Single Responsibility Principle - `LetterRemovalStrategy` : Définit la stratégie - Méthodes séparées pour chaque comportement ### Open/Closed Principle - Extensible : Nouvelles stratégies peuvent être ajoutées - Fermé : Code existant non modifié ### Liskov Substitution Principle - Toute stratégie respecte le contrat - Comportement prévisible ### Dependency Inversion Principle - Configuration injectable - Pas de dépendance hard-codée ## Limitations actuelles 1. **Sélection aléatoire** : Les lettres à retirer sont choisies aléatoirement - Amélioration possible : Cibler les consonnes problématiques 2. **Pas de cache** : Recalcule à chaque tentative - Amélioration possible : Mémoriser les scores calculés 3. **Pas de heuristiques phonétiques** : Ne considère pas la structure phonétique - Amélioration possible : Retirer préférentiellement certaines consonnes ## Extensions possibles ### Stratégies avancées ```rust pub enum LetterRemovalStrategy { None, Adaptive { max_removals: usize }, // Nouvelles stratégies possibles : TargetedConsonants { max_removals: usize }, PreserveVowels { min_vowels: usize }, PhoneticOptimization { target_score: u32 }, } ``` ### Configuration fine ```rust pub struct AdaptiveRemovalConfig { pub max_removals: usize, pub prefer_consonant_removal: bool, pub preserve_starting_letter: bool, pub target_length: Option, } ``` ## Références - Code source : [src/generator.rs](src/generator.rs) - Tests : [tests/letter_removal_tests.rs](tests/letter_removal_tests.rs) - Documentation API : `cargo doc --open`