Files
anagram-generator/docs/LETTER_REMOVAL_FEATURE.md
2025-11-06 22:34:21 +01:00

285 lines
8.1 KiB
Markdown

# 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 <NOMBRE>
```
Autorise le retrait jusqu'à `<NOMBRE>` 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<R: Rng, S: PronounceabilityScorer> AnagramGenerator<R, S> {
// Point d'entrée selon la stratégie
fn try_generate_one(...) -> Option<Anagram>
// Génération sans retrait (comportement original)
fn try_generate_without_removal(...) -> Option<Anagram>
// Génération avec retrait adaptatif
fn try_generate_with_removal(...) -> Option<Anagram>
// Essai avec un nombre spécifique de retraits
fn try_with_specific_removals(...) -> Option<Anagram>
}
```
## 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<usize>,
}
```
## 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`