Probleme de liste python

Fermé
Poufpaf - Modifié le 27 avril 2022 à 11:02
 Utilisateur anonyme - 2 mai 2022 à 08:09
Bonjour, ce que je cherche à faire est un petir programme permettant de retrouver un mot à partir de lettres dans le mauvais ordre (ex: à partie de "hcta" retrouver "chat" ou tous les autres mots possible). Pour cela, j ai implémenté directement dans le code (pour execution + rapide) une liste de 300000 mots en francais. Ce que mon programme fait, c est à partir d'un (mot dans le mauvais ordre), il retrie la liste des 300000 mots en une sous-liste contenant des mots avec une des lettres contenur dans le (mot dans le mauvais ordre) ensuite il repete l'operation a partir de la sous-liste avec la 2 eme lettre du mot, etc, et ensuite il filltre les mots qui font la bonne taille:
wordstring = """abricot
.......
.......
.......
.......
zython
zythons
zythum
zythums"""

interwordlist = wordstring.splitlines()
wordlistfix = []
for line in interwordlist:
    pureword = str(line.strip())
    wordlistfix.append(pureword)

print(wordlistfix[0:10])


while True:
    badword = str(input("mot à remettre en ordre : "))
    wordlist = wordlistfix
    wordindex = range(int(len(wordlistfix)))
    for lettre in badword:
        selectindex = []
        for index in wordindex:
            word = wordlist[index]
            if lettre in word:
                selectindex.append(index)
                i = word.find(lettre)
                newword = ""
                for n in range(len(word)):
                    if n != i:
                        newword = newword + word[n]
                    else:
                        pass
                wordlist[index] = newword
            else:
                continue
        if len(selectindex) < 1:
            print("aucun mot trouvé")
            break
        else:
            wordindex = selectindex
            continue
    for indexfinal in wordindex:
        if len(wordlistfix[indexfinal]) == len(badword):
            print("  ", wordlistfix[indexfinal])
        else:
            continue


Malgré ce cassage de crâne, le programme renvoie des mots qui n'ont rien avoir comme:
pour "hcat" (qui devrait normallement renvoyer "chat") me renvoie à la place, des mots comme : "lici, licn, loc, obia, oucn, ..... " ce qui ressemble à des morceaux de mots incomplets...

Quelqu'un aurrait il assez de matiere grise pour m'aider à conprendre ce qui ne fonctionne pas dans mon code ? J ai relu plusieurs fois, j ai meme essayé d'appliquer mon code a la main sur papier avec une petite liste, mais je ne comprends vraiment pas ce qui ne joue pas.

Merci d'avance
A voir également:

31 réponses

Phil_1857 Messages postés 1872 Date d'inscription lundi 23 mars 2020 Statut Membre Dernière intervention 28 février 2024 168
Modifié le 27 avril 2022 à 10:50
Bonjour,

Pour que ton code soit plus lisible, affiche-le avec les balises de code, mode d'emploi:

https://codes-sources.commentcamarche.net/faq/11288-les-balises-de-code

Ca doit ressembler à ça, une fois le message validé:
while True:
    badword = str(input("mot à remettre en ordre : "))
    wordlist = wordlistfix


Ceci dit, pour retrouver toutes les anagrammes d'un mot, dans un 1er temps, tu peux faire ça:
import itertools as it

word = input('Mot : ')
anag = set("".join(e) for e in it.permutations(word, len(word)))

for el in anag: print(el)


Et dans un 2eme temps, tu cherches le mot valide
0
interwordlist = wordstring.splitlines()
wordlistfix = []
for line in interwordlist:
    pureword = str(line.strip())
    wordlistfix.append(pureword)

print(wordlistfix[0:10])


while True:
    badword = str(input("mot à remettre en ordre : "))
    wordlist = wordlistfix
    wordindex = range(int(len(wordlistfix)))
    for lettre in badword:
        selectindex = []
        for index in wordindex:
            word = wordlist[index]
            if lettre in word:
                selectindex.append(index)
                i = word.find(lettre)
                newword = ""
                for n in range(len(word)):
                    if n != i:
                        newword = newword + word[n]
                    else:
                        pass
                wordlist[index] = newword
            else:
                continue
        if len(selectindex) < 1:
            print("aucun mot trouvé")
            break
        else:
            wordindex = selectindex
            continue
    for indexfinal in wordindex:
        if len(wordlistfix[indexfinal]) == len(badword):
            print("  ", wordlistfix[indexfinal])
        else:
            continue


Voila, normallement le code devrait s afficher correctement. Sinon, à propos de l'idée que vous m avez proposée, de re hercher tous les anagrames d'un mot, ce n'est pas possible, car par exemple pour un mot de 25 lettres comme "anticonstitutionnellement" il faudrait essayer 25! Possibilité ce qui fait environ 1,55*10²⁵, aucun ordinateur ne serait assez puissant pour essayer toutes les possibilités en un temps raisonnable. C'est pour cela que j'utioise ma methode de selectionner les mots du dictionnaire qui contiennent les meme lettres que le mot dans le mauvais ordre, ce qui a un temps de calcul non-exponentiel en tout cas, donc assez rapide peu importe la longueur du mot.
0
Phil_1857 Messages postés 1872 Date d'inscription lundi 23 mars 2020 Statut Membre Dernière intervention 28 février 2024 168
27 avril 2022 à 11:52
Hello,

Comme tu peux le constater toi même, tu n'as pas appliqué les balises de code
Tu vois quand même bien que ça ne ressemble pas du tout à ce que je te montre dans ma réponse ...

Sinon, as-tu testé mon bout de code tout simple ?
0
J'ai corrigé les balises en vous les envoyant dans un nouveau message, dans commentaires de votre 1ère réponse, j ai egallement répondu à votre bout de code
0
Phil_1857 Messages postés 1872 Date d'inscription lundi 23 mars 2020 Statut Membre Dernière intervention 28 février 2024 168
Modifié le 27 avril 2022 à 12:04
Pour les anagrammes, c'est vrai que j'utilisais ça pour des mots courts
10 lettres maxi, 300000 combinaisons en 10 secondes...
sachant qu'avec set(), j'élimine quand même les doublons
0
C'est vrai qu'en éliminant les doublons on pourrait passer repidement de 10 à 9 ou à 8 caracteres, mais pour de longs mots, 25 ou 22 caracteres sans compter les doublons resterait impissible à calculer. Je sûr que ma methode est la plus rapide possible, mais je n'ai peut être pas fait le code le plus compact. Ma methode reviendrait au meme que de vérifier pour chaque mot du dictionnaire, si il contient les memes lettres que {les lettres mal rangées} ou pas.
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
Phil_1857 Messages postés 1872 Date d'inscription lundi 23 mars 2020 Statut Membre Dernière intervention 28 février 2024 168
Modifié le 27 avril 2022 à 12:15
par contre j'ai testé ton code avec juste ces mots la:
wordstring = """abricot
chat
zython
zythons
zythum
zythums"""


et bizarrement, ça donne ça:


même pas un message d'info ...
0
Je pense que tu as dû mal insérer la fin de la boucle, il y a surement une erreur de tabulation, car la tu reviens au debut de la boucle while sans avoir affiché le message de print, donc le message de print est surement en dehors de la boucle alors qu'il devrait etre dedans. Je pense que ça doit etre ça, est tu sur d'avoir bien copié les tabulations ?
0
Ou alors c'est qu'il y a queslque chose qui ne va justement pas dans le code. Quand j ai essayé pour "chat" avec la liste complete, ça me donnait plein de bouts de mots
0
['a', 'à', 'abaissa', 'abaissable', 'abaissables', 'abaissai', 'abaissaient', 'abaissais', 'abaissait', 'abaissâmes']
mot à remettre en ordre : hcat
anes
eais
eait
eant
eât
eée
eés
èes
eeur
eiez
eons
evai
evan
evâ
roma
moai
moan
moâ
moen
niar
rone
taai
taas
taé
taer
taes
taez
urue
vaî
b̂ai
b̂an
b̂â
b̂en
boai
boas
boé
boer
boes
boez
bêi
bên
bê̂
bioi
bios
blne
blni
boui
boun
boû



Voici ce que j'obtiens en lançant mon code ????‍♂️
0
Phil_1857 Messages postés 1872 Date d'inscription lundi 23 mars 2020 Statut Membre Dernière intervention 28 février 2024 168
Modifié le 27 avril 2022 à 13:51
J'ai les tabulations puisque j'ai copié/collé ton code
résultat avec ta nouvelle liste:


Au fait len(wordlistfix) est forcément un integer donc pas besoin de int(len(...
input saisi par défaut une string, donc pas besoin de badword = str(input(
    badword = input("\nmot à remettre en ordre : (Q = quitter) : ")
    if(badword in 'Qq'): break


"tu reviens au debut de la boucle while sans avoir affiché le message de print"

Ok mais on ne print que si ces 2 conditions sont vraies:
        if len(selectindex) < 1:
            print("aucun mot trouvé")

        if len(wordlistfix[indexfinal]) == len(badword):
            print("  ", wordlistfix[indexfinal])


Si on ne tombe dans aucun de ces 2 cas, on ne sort rien ...
0
Alors c est le probleme du code, moi avec la lite de mots complete, ca m a fiche plein de bouts de mots, mais pas ceux qui devraient s'afficher
0
Phil_1857 Messages postés 1872 Date d'inscription lundi 23 mars 2020 Statut Membre Dernière intervention 28 février 2024 168
27 avril 2022 à 13:53
relis mon message de 13h44, je l'ai modifié pendant que tu répondais, donc tu n'as surement pas tout vu ...
0
Oui, majs normallement on est forcement dans un cas ou dans l'autre, car soit la liste est vide (len(...)<1:), soit la liste n'est pas vide (else:) et dans ce cas la boucle for continue pour la lettre suivante. Je pense que je vais repenser mon code, et au lieu de faire (pour chaque lettre de badword, lettre est il dans {wordlist[indexlist]} ) je vais plutot faire l'inverse, c est a dire: vérifier si pour chaque mot de la liste, le mot contient il chaque lettre de badword), en gros je vais essayer de refaire un code mais en inversant les 2 premiere boucles for. Je pense que avec cette methode ce serait plus simple car il n'y aura pas besoin de mettre à jour wordindex pour chaque lettre. Je réessaie ce soir, et si je réussis, je partage le code, si ça vous interresse..

Merci des conseils, j'avais effectivement pu penser à une break pour sortir de la loupe, mais l'avantage de rester dans la boucle while, c'est que on peut utiliser le code plusieurs fois, sans avoir à regénérer wordlistfix à chaque fois, car la liste est quand meme assez longue (300000 mots).

Je vous redis si j'atteints quelque chose ce soir
0
Phil_1857 Messages postés 1872 Date d'inscription lundi 23 mars 2020 Statut Membre Dernière intervention 28 février 2024 168
Modifié le 27 avril 2022 à 17:34
Ben non, wordlistfix est initialisée une seule fois avant le while

En faisant comme ça, ca marche:

wordstring = """abricot
chat
chatte
zythons
zythum
zythums"""

wordlistfix = wordstring.splitlines()
print(wordlistfix)

while(True):
    mixed_word = input("\nmot à remettre en ordre (Q)uitter : ")
    if(mixed_word in ['q','Q']): break
    longueur = 0

    for word in wordlistfix:
        if(len(word) == len(mixed_word)):
            for lettre in mixed_word:
                if(lettre in word): longueur += 1

            if(len(word) == longueur):
                print('\nTrouvé : {}'.format(word))
                break
            else:
                longueur = 0

    if(longueur == 0): print('\nRien trouvé !')




0
Phil_1857 Messages postés 1872 Date d'inscription lundi 23 mars 2020 Statut Membre Dernière intervention 28 février 2024 168
Modifié le 29 avril 2022 à 09:35
Bonjour Pafpouf,

Alors où en es tu ?

As-tu testé mon code ?
0
Rebonjour, oui, klmerci beaucoup, c est en effet la méthode que je voulais avec laquelle je voulais refaire mon code, en testant pour chaque mot le nb de lettre, et il marche effectivement bien, il n'y a pas de problemes avec les doublons. Je suis en train de le perfectionner en ajoutant des options comme ignorer les accents, ou choisir le nombre de lettres minimum à utiliser. Je me pose maintenant si il existe de meme, un algorithme simple permettant de faire la meme chose avec des phrases, (les lettres de toute la phrase sont melangées), mais sans pour autant avoi recour au bruteforce, ni faire de liste de phrases, mais uniquement en utilisant la liste de mots francais. Ce problème là me parrait déjà plus compliqué ètant donné qu'avec une phrase comprenant beaucoup de caracteres et/ou beaucoup de mots, on peut avoir des milliers de possibilites de phrases. Mais deja il faudrait trouver un algo permettant de toutes les trouver sans faire de bruteforce (ou alors une bruteforce dont le temps de calcul ne serait pas exponentiel en fonction de la longueur de la phrase ou du nombre de mots dans la phrase).

Sinon, merci beaucoup pour vos conseils, je me complique parfois trop la vie en utilisant python.
0
Phil_1857 Messages postés 1872 Date d'inscription lundi 23 mars 2020 Statut Membre Dernière intervention 28 février 2024 168
Modifié le 29 avril 2022 à 18:32
Hé oui, mon code est très simple et très court, et il fait le job demandé

Tu remarqueras que, lorsque je boucle sur les mots de wordlistfix, je commence par tester si le mot mélangé

a la même longueur que le mot de wordlistfix, sinon, ce n'est pas la peine d'analyser plus loin

C'est bien la 1ere chose à faire ...
0
yg_be Messages postés 23530 Date d'inscription lundi 9 juin 2008 Statut Contributeur Dernière intervention 22 avril 2025 1 578
29 avril 2022 à 19:34
La première chose à faire, c'est une fois pour toutes, de trier les mots du dictionnaire, de façon à pouvoir faire une recherche dichotomique.
0
Ah oui, j'allais oublier, la seule chose qui ne fo ctionne pas dans le code que vous m'avez envoyé, c'est la mise à 0 de la variable longueur. Par chance, votre code fonctionne pour la liste que vous avez utilisée car "chat" et le seul mot pour lequel la variable longueur a été utilisée, vu que "chat" est le seul mot de votre liste qui contient le meme nombre de caractères que "hcat". Mais si vous aviez mis un autre mot de d'autres mots valables pour "hcat", imaginons que dans votre liste vous auriez mis le mot "cath", votre code ne l'aurait pas trouvé, car votre variable longueur n'aurait pas été remise à 0, car vous n'avez pas mis (longueur = 0) au bon endroit. J'ai juste corrigé ça en insérant (longueur = 0) à l'interieur de la premiere boucle for, mais à l'extérieur de la 2ème. Et la votre algorithme devient juste. Sinon merci, votre méthode en utilisant la variable longeur est astucieuse, j'y avais pas pensé.
0
yg_be Messages postés 23530 Date d'inscription lundi 9 juin 2008 Statut Contributeur Dernière intervention 22 avril 2025 Ambassadeur 1 578
Modifié le 29 avril 2022 à 19:42
Moi je ferais ainsi:
1) associer à chaque mot du dictionnaire une clé, chaine de caractères avec les lettres du mot, triées par ordre alphabétique
2) stocker cela dans une base de données sqlite, ou dans une structure dans un fichier, triée par la clé

Quand tu dois retrouver un mot à partir de lettres dans le mauvais ordre, tu fais une recherche, puisque tu connais la clé exacte à chercher.
0
yg_be Messages postés 23530 Date d'inscription lundi 9 juin 2008 Statut Contributeur Dernière intervention 22 avril 2025 1 578
29 avril 2022 à 20:16
exemple:
import sqlite3
wordstring = """abricot
chat
chatte
zythons
zythum
zythums"""
def trielettres (m):
    return "".join(sorted(m))
conn = sqlite3.connect('dico.db')
curs=conn.cursor()
# sql="CREATE TABLE dico(mot text, cle text)"
# curs.execute(sql)
# sql="CREATE INDEX i_cle ON dico(cle)"
# curs.execute(sql)
wordlistfix = wordstring.splitlines()
sql="DELETE FROM dico"
curs.execute(sql)
for word in wordlistfix:
    sql="INSERT INTO dico (mot,cle) VALUES('" + word + "','"+ trielettres(word) +"')"
    curs.execute(sql)
conn.commit()
while(True):
    mixed_word = input("\nmot à remettre en ordre (Q)uitter : ")
    if(mixed_word in ['q','Q']): break
    sql="SELECT mot FROM dico WHERE cle='" + trielettres(mixed_word) + "'"
    curs.execute(sql)
    recs=curs.fetchall()
    for rec in recs:
        print(rec[0])
0
J'ai enfin réussi à faire un code qui fonctionne parfaitement pour les mots de toutes longueurs:

zython
zythons
zythum
zythums"""

def dellettre(string, lettre):
    newword = ""
    ind = string.find(lettre)
    for index in range(len(string)):
        if index != ind:
            newword = newword + string[index]
    return(newword)

interwordlist = wordstring.splitlines()
wordlistfix = []
for line in interwordlist:
    pureword = str(line.strip())
    wordlistfix.append(pureword)

while(True):
    badword = input("mot à remettre en ordre : ")
    selectword = []
    for word in wordlistfix:
        if(len(word) == len(badword)):
            piece = word
            longueur = 0
            for lettre in badword:
                if lettre in piece:
                    longueur = longueur + 1
                    piece = dellettre(piece, lettre)
                else:
                    break
            if longueur == len(badword):
                selectword.append(word)
        else:
            pass
    for mot in selectword:
        print(mot)


Voici un exemple de son fonctionnement :

mot à remettre en ordre : ogrnaes
onagres
oranges
organes
rageons
rongeas
songera

Donc il fonctionne bien, il me donne bien toutes les olutions possibles, il fonctionne aussi avec les longs mots comme "hermaphrodite", "hippopotame", "thermodynamique".

Tout marche trés bien, mais il subsiste tout de même 1 seul, le seul et ultime problème : dés qu'il s'agit de mot comportant des accents, comme "è", "é", "à", "î", ô, â, ï,.... alors le code ne retourne rien, mème pour les mots très simple. Donc là, je me pose la question de savoir si c est encore un erreur dans le code, ce qui me parrait bizarre car ça fonctionne parfaitement pour tous les mots, même long, qui m'ont pas de lettre avec des accent. Ou alors, est-ce peut etre un problème d'encodage ou un problème lié à l'interprêtation des accents par python.

Pourtant, lorsque je fais :
string = éléphant
print(string.find("é"))

celà me renvoie pourtant bien =>0, donc .find detecte bien les accents. L'erreur est donc ailleur, mais je ne sais pas où...

Svp auriez vous une idée ?
0
Phil_1857 Messages postés 1872 Date d'inscription lundi 23 mars 2020 Statut Membre Dernière intervention 28 février 2024 168
Modifié le 30 avril 2022 à 10:03
Bonjour patpouf,

Encore plus court et plus concis:

dico = ['abricot', 'chat', 'oranges', 'onagres', 'organes', 'rageons', 'zython']
print(dico)

while(True):
    mixed_word = input("\nmot à remettre en ordre (Q)uitter : ")
    if(mixed_word in ['q','Q']): break

    mixed_word_a = ''.join(sorted(mixed_word))

    found = False
    for word in dico:
        word_a = ''.join(sorted(word))
        if(word_a == mixed_word_a):
            found = True
            print('Trouvé : ', word)

    if(not found): print(mixed_word,'non trouvé ...')


0