Le blog: Web, Python, Django, Javascript ...

Python Quizz: L'homme qui parle en anagrammes

Voici le retour du Python quizz après une longue absence. Je vous propose aujourd'hui de réaliser à l'aide d'une fonction Python, un détecteur d'anagramme en référence à 'The man who talks in anagrams' un sketch des Monty Python.

Comment réaliser en quelques lignes de Python, une fonction qui retourne vrai si 2 chaînes sont des anagrammes?

>>> is_anagram('Hamrag', 'Graham')
True

Si vous avez besoin d'exemples pour les tests, voici le texte du sketch

Mise à jour: Voici une proposition de solution

Je dois avouer que pour moi aussi la tentation a été grande d'utiliser un set.

Le set en Python est un dictionnaire sans valeurs dans lequel on ne stocke que les clés.
C'est une table de hashage avec un lot de méthodes bien pratiques pour des opérations sur des ensembles (union, intersection, ...)
Un outil parfois méconnu de la librairie Python mais qui peut se révéler très utile.

Tout comme une clé d'un dictionnaire, chaque valeur stockée dans un set doit être unique.

>>> set('AAABBCC')
set(['A', 'C', 'B'])


set(l1.lower()) == set(l2.lower()) permet donc de vérifier que deux mots ont les même lettres mais pas qu'elles sont des anagrammes. Deux anagrammes doivent bien comporter le même nombre d'occurences d'une lettre. C'est simplement un renversement des lettres d'un mot. aspirine est l'anagramme de parisien mais pas celui de parisienne.

En utilisant un set, on perd l'information sur le nombre d'occurences des lettres et on ne peut donc pas détecter correctement si 2 chaînes sont des anagrammes.

La réponse de cgravier me parait tout à fait valide mais on peut faire un peu plus court en supprimant la conversion en list et le if final qui sont inutiles.

L'utilisation de la fonction sorted me paraît très pertinente. Fonctionnant avec le même principe que la méthode sort de la list, elle permet de trier n'inporte quel type de séquence. Inutile donc de convertir en list puisqu'une chaîne est déjà une séquence.

Voici donc ma proposition:

def is_anagram(m1, m2) :
    return sorted(m1.lower()) == sorted(m2.lower())

Merci pour vos propositions et à bientôt.


Comments rss
Posted by cgravier on Monday 21 February 2011 à 16:30
Ca fait un moment que je souhaite me mettre au python (en dehors du bricolage de script sous zope/plone), ces quizz sont l'occasion :-)

def is_anagram(m1, m2) :
s1 = sorted(list(m1.lower()))
s2 = sorted(list(m2.lower()))
if (s1 == s2):
return True
else:
return False

Posted by Fabien C. on Monday 21 February 2011 à 17:05
De la facilité de traiter les ensembles en python:

def is_anagram(l1, l2):
return set(l1.lower()) == set(l2.lower())

Posted by cgravier on Wednesday 23 February 2011 à 15:50
plus simple ca va être difficile :) merci

Posted by Fabien C. on Friday 25 February 2011 à 11:03
Effectivement j'ai été un peu vite en besogne, la solution finale reste courte, c'est beau le Python :)

Name: Email: URL: Comment: If you enter anything in this field your comment will be treated as spam: Captcha: captcha