Initial commit
This commit is contained in:
284
docs/LETTER_REMOVAL_FEATURE.md
Normal file
284
docs/LETTER_REMOVAL_FEATURE.md
Normal file
@@ -0,0 +1,284 @@
|
||||
# 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`
|
||||
Reference in New Issue
Block a user