Une anagramme d'un mot est un mot s'écrivant avec les mêmes lettres que le mot initial.
Exemples :
- Marie et aimer.
- Léna et élan.
- ironique et onirique.
- baignade et badinage.
- estival et vitales.
Ici, nous ne demandons pas que les mots envisagés soient des mots du dictionnaire. Ainsi 'abc' et 'bca' sont deux anagrammes.
Écrire une fonction python récursive :
Entrée | un mot (type str). |
---|---|
Sortie | la liste de ses anagrammes. |
- définition récursive
- un premier code
- traceur
- version itérateur
- Si le mot n'a qu'une seule lettre, la liste de ses anagrammes ne contient qu'un seul élément : le mot lui-même. On peut même définir le cas de base sur une chaîne vide : la liste des anagrammes est alors constituée de l'unique chaîne vide.
- Regardons le cas d'un mot de trois lettres 'abc'. On peut définir la liste de ses anagrammes en fonction de la liste des anagrammes du mot 'bc'. La liste des anagrammes de 'bc' est ['bc', 'cb']. Pour constituer la liste des anagrammes de 'abc', il suffit de placer la lettre 'a' dans toutes les positions possibles des anagrammes de 'bc'. On obtient la liste ['abc', 'bac', 'bca', 'acb', 'cab', 'cba']. De la même façon, on obtiendra la liste de toutes les anagrammes du mot 'dabc' en glissant la lettre 'd' dans toutes les positions possibles de toutes les anagrammes de 'abc'.
def listeAnagramme(mot) :
if mot == '' : return ['']
else :
liste = []
for anagr in listeAnagramme(mot[1:]) :
for k in range(len(mot)) :
liste.append(anagr[:k] + mot[0] + anagr[k:])
return liste
print(listeAnagramme('abc'))
Pour ceux qui apprécient la concision python :
def listeAnagramme(mot) :
if mot == '' : return ['']
return [anagr[:k] + mot[0] + anagr[k:] for anagr in listeAnagramme(mot[1:]) for k in range(len(mot))]
print(listeAnagramme('abc'))
En fait, cette version a le défaut de donner plusieurs fois certaines anagrammes quand le mot initial contient plusieurs lettres identiques. On peut régler ce problème comme suit :
def listeAnagrammeavecRepet(mot) :
if mot == '' : return ['']
return [anagr[:k] + mot[0] + anagr[k:] for anagr in listeAnagrammeavecRepet(mot[1:]) for k in range(len(mot))]
def listeAnagrammeSansDoublon(mot) :
return list(set(listeAnagrammeavecRepet(mot)))
print(listeAnagrammeSansDoublon('aba'))
Décomposons un peu avec des traces :
def trace(f):
decale = 0
def g(mot):
nonlocal decale
print('| ' * decale + '|--', f.__name__, '(', mot ,') ' )
decale += 1
valeur = f(mot)
print('| ' * decale , f.__name__, '(', mot,') =', repr(valeur) )
decale -= 1
return valeur
return g
def listeAnagramme(mot) :
if mot == '' : return ['']
else :
liste = []
for anagr in listeAnagramme(mot[1:]) :
for k in range(len(mot)) :
liste.append(anagr[:k] + mot[0] + anagr[k:])
return liste
listeAnagramme = trace(listeAnagramme)
listeAnagramme('abc')
On obtient :
|-- listeAnagramme ( abc ) | |-- listeAnagramme ( bc ) | | |-- listeAnagramme ( c ) | | | |-- listeAnagramme ( ) | | | | listeAnagramme ( ) = [''] | | | listeAnagramme ( c ) = ['c'] | | listeAnagramme ( bc ) = ['bc', 'cb'] | listeAnagramme ( abc ) = ['abc', 'bac', 'bca', 'acb', 'cab', 'cba']
def anagramme(mot) :
if mot == '' :
yield ''
else :
yield from [anagr[:k] + mot[0] + anagr[k:] for anagr in anagramme(mot[1:]) for k in range(len(mot))]
for x in anagramme('abc') :
print(x)
Vous pourrez trouver des explications sur yield
sur
cette page.