Anagrammes¶
Un écrit ou un récit ? un vélo volé... acheter un hectare, suivre la trace sur la carte... avec l'esprit ou les tripes ?
Ceci est un programme permettant de lister (presque tout) les anagrammes du Français à partir d'un dictionnaire donné (c'est-à-dire une liste de mots)...
Chargement et dépoussiérage du dictionnaire¶
#fichier = 'liste_mots_mix.txt' #295088 mots - http://www.lexique.org/listes/liste_mots.php
fichier = 'liste_francais.txt' # 22740 mots
with open(fichier, encoding="ISO-8859-1") as f:
dictionnaire = f.readlines()
len(dictionnaire)
Sont retirés, entre autre, les noms propres (majuscule), les mots avec une apostrophe ou un tiret...
import re
sacdemots = set()
for ligne in dictionnaire:
if not re.search( r"[#()'0-9\.\-A-Z!]", ligne) :
mot = ligne.strip(' \r\n')
if len(mot)>2 :
sacdemots.add( mot )
liste_mots = list( sacdemots )
print( len( liste_mots ) )
print( ', '.join( liste_mots[:10] ) + ', ...etc' )
Recheche des anagrammes¶
La liste des anagrammes est créée en triant, pour chaque mot, ses lettres par ordre alphabétique.
liste_anagrammes = [ ''.join( sorted( mot ) ).strip() for mot in liste_mots ]
print( ', '.join( liste_anagrammes[:10] ) + ', ...etc' )
Les anagrammes sont ensuite triés, en conservant le mot correspondant attaché avec (zip
).
Z = sorted( zip(liste_anagrammes, liste_mots ), key=lambda x:x[0] )
print( Z[:10] )
et enfin le coeur du problème, les mots ayant le même anagramme sont cherchés de proche en proche:
multi = []
A = Z[0]
same = False
for B in Z[1:]:
if A[0] == B[0] and same == False:
same = True
famille = [A[1], B[1]]
elif A[0] == B[0] and same == True:
famille.append( B[1] )
elif A[0] != B[0] and same == True:
multi.append(famille)
same = False
A = B
len( multi )
print( sorted( multi, key=lambda x:len(x[0]) )[:10] )
Résultats¶
Les mots ayant le plus d'anagrammes possible :
print( sorted( multi, key=lambda x:len(x), reverse=True)[:20] )
Les anagrammes des mots les plus longs:
print( sorted( multi, key=lambda x:len(x[0]), reverse=True )[:20] )
Et la liste de tous les anagrammes:
S = sorted( multi, key=lambda x:len(x[0]) )
Sa = [ '/'.join(u) for u in S ]
print( '; '.join( Sa ) )
Remarques:¶
- le résultat dépend beaucoup du dictionnaire utilisé. Il existe beaucoup de mots non courant, permettant de former beaucoup plus d'anagrammes... plutôt incomprehensibles.
- Comment faire pour autoriser une ou deux lettres de différence ? Ou en travaillant sur la phonétique plutôt que l'orthographe exacte ?