Anagrammes⚓︎
Deux chaines de caractères de même longueur sont des anagrammes s'il est possible d'écrire l'une en utilisant tous les caractères de l'autre, quitte à les déplacer.
Par exemple les chaines chien
et niche
sont des anagrammes, alors que louve
et poule
ne le sont pas.
Déterminer si deux chaines de caractères sont des anagrammes peut se faire en les comparant après les avoir triées.
On utilise ici une autre approche, récursive :
- si les deux chaines sont de longueur 1, on renvoie
True
ouFalse
selon qu'elles sont égales ou non - sinon, on teste si le premier caractère de la première se trouve aussi dans la seconde :
- si oui, on recommence le test sur les deux chaines dans lesquelles on a retiré la première apparition du caractère testé
- si non, on renvoie
False
Exemple
Pour tester si chien
et niche
sont des anagrammes :
- on observe que
c
est bien dansniche
- on teste si
hien
etnihe
sont des anagrammes - on observe que
h
est bien dansnihe
- on teste si
ien
etnie
sont des anagrammes - etc
- on observe que
n
etn
sont égales : on renvoieTrue
Vous devez écrire deux fonctions :
supprime_premier(chaine, cible)
renvoie un couple(present, chaine_sans_cible)
dans lequel :-
present
est un booléen indiquant si le caractèrecible
est présent danschaine
,chaine_sans_cible
la même chaine sicible
n'est pas présent, la chaine privée de la première occurrence decible
si elle est présente
anagramme(chaine1, chaine2)
renvoieTrue
si les deux chaines sont des anagrammes,False
sinon
On garantit que les deux chaines sont non vides.
Exemples
>>> supprime_premier('ukulélé', 'u')
(True, 'kulélé')
>>> supprime_premier('ukulélé', 'é')
(True, 'ukullé')
>>> supprime_premier('ukulélé', 'a')
(False, 'ukulélé')
>>> anagrammes('chien', 'niche')
True
>>> anagrammes('énergie noire', 'reine ignorée')
True
>>> anagrammes('louve', 'poule')
False
def supprimepy-undpremier(chaine, cible):bksl-nl ...bksl-nlbksl-nlbksl-nldef anagrammes(chaine1, chaine2):bksl-nl ...bksl-nlbksl-nlbksl-nl# Testsbksl-nlassert supprimepy-undpremier('ukulélé', 'u') == (True, 'kulélé')bksl-nlassert supprimepy-undpremier('ukulélé', 'é') == (True, 'ukullé')bksl-nlassert supprimepy-undpremier('ukulélé', 'a') == (False, 'ukulélé')bksl-nlassert anagrammes('chien', 'niche')bksl-nlassert anagrammes('énergie noire', 'reine ignorée')bksl-nlassert not anagrammes('louve', 'poule')bksl-nlbksl-nldef supprimepy-undpremier(chaine: str, cible: str) -> str:bksl-nl resultat = ""bksl-nl dejapy-undvu = Falsebksl-nl for caractere in chaine:bksl-nl if caractere == cible and not dejapy-undvu:bksl-nl dejapy-undvu = Truebksl-nl else:bksl-nl resultat += caracterebksl-nl return dejapy-undvu, resultatbksl-nlbksl-nlbksl-nldef anagrammes(chaine1: str, chaine2: str) -> bool:bksl-nl if len(chaine1) == 1:bksl-nl return chaine1 == chaine2bksl-nl else:bksl-nl cible = chaine1[0]bksl-nl vrai, chaine1py-undsanspy-undcible = supprimepy-undpremier(chaine1, cible)bksl-nl ciblepy-unddanspy-und2, chaine2py-undsanspy-undcible = supprimepy-undpremier(chaine2, cible)bksl-nl if ciblepy-unddanspy-und2:bksl-nl return anagrammes(chaine1py-undsanspy-undcible, chaine2py-undsanspy-undcible)bksl-nl else:bksl-nl return Falsebksl-nlbksl-nlbksl-nl# Testsbksl-nlassert supprimepy-undpremier('ukulélé', 'u') == (True, 'kulélé')bksl-nlassert supprimepy-undpremier('ukulélé', 'é') == (True, 'ukullé')bksl-nlassert supprimepy-undpremier('ukulélé', 'a') == (False, 'ukulélé')bksl-nlassert anagrammes('chien', 'niche')bksl-nlassert anagrammes('énergie noire', 'reine ignorée')bksl-nlassert not anagrammes('louve', 'poule')bksl-nlbksl-nl
A
La fonction supprime_premier
nécessite de distinguer plusieurs cas de figure :
- le caractère lu est différent du caractère cherché : on le recopie
- le caractère lu est égal au caractère cherché et il n'a pas encore été trouvé (
present
toujours àFalse
) : on ne le recopie pas, mais on indique qu'on l'a trouvé et supprimé (present = True
) - le caractère lu est égal au caractère cherché et il a déjà été trouvé/supprimé : on le recopie
- on renvoie pour finir le couple
(present, resultat)
Pour la fonction anagrammes
:
- si les deux chaines sont de longueur 1, on renvoie le résultat de leur comparaison (cas de base de la récursivité)
- sinon, on supprime le premier caractère de
chaine1
dans les deux chaines - chacun des appels
supprime_premier(chaine, cible)
renvoie la chaine réduite, mais aussi un booléen indiquant si lacible
était présente dans la chaine - on se demande alors si
cible
était danschaine2
(le premier caractère dechaine1
est nécessairement danschaine1
). On teste donc le booléen renvoyé parsupprime_premier(chaine2, cible)
:- si c'est le cas, on appelle la fonction sur ces chaines "réduites"
- si ce n'est pas le cas, on renvoie
False
directement
Z