Partage
  • Partager sur Facebook
  • Partager sur Twitter

[Exercice] des chiffres et des lettres

Le mot le plus long

    25 août 2011 à 12:57:55

    Bonjour,

    J'essaie de faire cet exo mais je bloque (débutant inside). Le code "fonctionne", par contre je ne vois pas comment je pourrais faire pour chercher n-1 lettre si il n'y a pas de mots avec n lettres. Je pensais faire une permutations de self.letters, le tirage, en virant la dernière lettre puis l'avant dernière, etc, mais je ne vois pas comment le mettre proprement dans mon usine à gaz. J'ai regardé vos codes, mais je ne les comprends pas tous (trop de fonctions python que je ne connais pas), et je ne vois pas où vous gérez ça. Une coupure de courant avant de poster ce message m'a fait me replonger dans vos codes (itertools.combination()) et j'ai trouvé. :D

    J'ai essayé de le faire en POO pour m'entrainer à la POO et essayer d'en comprendre le fonctionnement. (vous allez me dire que ça sert à rien sur cet exo et que je l'ai mal fait en plus) Si vous pouvez me donner des corrections/conseils...

    C'est en python3, le code met dans les 13s à s’exécuter.

    # -*- coding:utf-8 -*-
    # Algo pour trouver le mot le plus long à partir de 9 letttres.
    # Inspiré du jeu télé "Des chiffres et des lettres"
    
    from random import randrange
    from string import ascii_lowercase
    from itertools import combinations
    
    class Dico(object):
        """La classe pour contenir le dictionnaire des mots"""
        def __init__(self):
            self.dico = []
    
        def remplissage_dico(self):
            # ouverture du fichier
            self.f = open("chiffres_lettres_dico.txt", "r")
    
            # boucle pour remplir le dictionnaire
            temp_dico = []
    
            word = self.f.readline()    #pour sauter la première ligne
            letter = 'a'    #pour gérer les listes en fonction de la première lettre
    
            while 1:
                word = self.f.readline()
                if word:
                    first_letter = word[0]
    
                    if first_letter != letter:
                        self.dico.append(temp_dico)
                        temp_dico = []
                        letter = first_letter
                    else:
                        temp_dico.append(word[:-1])
                        #[:-1] pour virer les caractères de fin de ligne
                else:
                    self.dico.append(temp_dico)
                    break
    
            # fermeture du fichier
            self.f.close()
    
            return self.dico
    
    
    class PlusLong(object):
        """Classse permettant de trouver le mot le plus long"""
        def __init__(self, letters, dico):
            # on tranforme letters en liste et on trie
            self.letters = list(letters)
            self.letters.sort()
            self.dico = dico
            self.mot_trouve = []    #liste des mots trouvés
    
        def cherche(self):
            """cherche le mot le plus long"""
            z = len(self.letters)
    
            # tant qu'on ne trouve pas de mots et qu'on est >= 3 lettres
            while not self.mot_trouve and z>=3:
    
                # on essaie les combinaisons possibles de lettres
                for m in combinations(self.letters, z):
                    c = self.compare(m)
                z -= 1
    
            print("Les mots les plus longs que l'on peut former avec {} sont : {}"
                  .format(self.letters, self.mot_trouve))
    
        def compare(self, chaine):
            """""Compare la chaine avec le dico"""
            for letter in chaine:
                # on choisi le dico commencant par letter
                first_letter_dico = self.dico[ascii_lowercase.index(letter)]
    
                for mot in first_letter_dico:
                    # on vire le trait d'union s'il y en a un
                    mot = mot.replace("-", "")
                    # si le mot du dico a la même longueur
                    # que celui recherché on continue
                    if len(mot) == len(chaine):
                        # on transforme mot en liste et on trie
                        mot_trie = list(mot)
                        mot_trie.sort()
                        i = 0
                        t = True
    
                        while i<len(mot):
                            if mot_trie[i] != chaine[i]:
                                t = False
                            i+=1
    
                        # si t est toujours vrai on ajoute le mot
                        if t:
                            self.mot_trouve.append(mot)
    
    
    class Application(object):
        """Corps de l'application"""
        def __init__(self, nb):
            self.letters = ''
            self.nb = nb    # nombre de lettres
            self.choix = self.choix_voy_cons()
            self.dico = Dico().remplissage_dico()
            self.mot_le_plus_long = PlusLong(self.letters, self.dico).cherche()
    
    
        def choix_voy_cons(self):
            consonnes = 'bcdfghjklmnpqrstvwxz'
            voyelles = 'aeiouy'
            compt_voy = 0    #pour compter les voyelles
    
            for i in range(0, self.nb):
    
                while 1:
                    # vérifie s'il y a au moins 2 voyelles
                    if i >= self.nb-2 and compt_voy < 2:
                        self.letters += voyelles[randrange(0,5)]
                        print("Le nombre de voyelles n'a pas été atteint, la \
    voyelle {} a été ajoutée.".format(self.letters[-1]))
                        compt_voy += 1
                        break
    
                    l = input('(c)onsonne ou (v)oyelle ? ')
                    # [:-1] pour échapper le \r, je ne sais pas pourquoi il est là
                    # on choisi une lettre au pif
                    if l[:-1] == 'c':
                        self.letters += consonnes[randrange(0, 19)]
                        break
                    elif l[:-1] == 'v':
                        self.letters += voyelles[randrange(0,5)]
                        compt_voy +=1
                        break
                    else:    #si la lettre n'est pas c ou v
                        print("J'ai dis c ou v")
    
    
    if __name__ == '__main__':
    
        import time
        debut = time.clock()
        test = Application(9)
        fin = time.clock()
        print("Éxécution en {:5.4f}s".format(fin-debut))
    
        #print(test.letters)
    
        #test de vitesse de chargement de Dico()
        #import time
        #debut = time.clock()
        #dico = Dico()
        #fin = time.clock()
        #print("Le fichier dictionnaire se charge en {:5.4f}s".format(fin-debut))
    


    edit: petite modif + commentaires
    Pourquoi il me met des mots en double ?
    • Partager sur Facebook
    • Partager sur Twitter
      28 août 2011 à 1:10:51

      Je pense que l'on peut allégé le dico, car la plupart des mots font plus de 9 lettres. (+ de 50% des mots). Je comprend bien que ce n'est pas la vitesse qui compte mais l'algo.

      Sinon, l'exercice est intéressant, tout comme les idées d'ailleurs. :)
      • Partager sur Facebook
      • Partager sur Twitter

      🍊 - Étudiant - Codeur en C | Zeste de Savoir apprenez avec une communauté | Articles  - ♡ Copying is an act of love.

        29 août 2011 à 15:51:46

        J'ai rajouter la limite de nombre de lettres pour le remplissage du dico

        Python3:
        # -*- coding:utf-8 -*-
        # Algo pour trouver le mot le plus long à partir de n letttres.
        
        from random import randrange
        from string import ascii_lowercase
        from itertools import combinations
        
        class Dico(object):
            """La classe pour contenir le dictionnaire des mots"""
            def __init__(self, nb):
                self.dico = []
                self.nb = nb    # nombre de lettres
        
            def remplissage_dico(self):
                # ouverture du fichier
                self.f = open("chiffres_lettres_dico.txt", "r")
        
                # boucle pour remplir le dictionnaire
                temp_dico = []
        
                word = self.f.readline()    #pour sauter la première ligne
                letter = 'a'    #pour gérer les listes en fonction de la première lettre
        
                while 1:
                    word = self.f.readline()
                    if word:
                        first_letter = word[0]
        
                        if first_letter != letter:
                            self.dico.append(temp_dico)
                            temp_dico = []
                            letter = first_letter
                        else:
                        #on ne garde que les mots de longueurs<= à ceux que l'on cherche
                            if len(word[:-1])<=self.nb:
                                temp_dico.append(word[:-1])
                                #[:-1] pour virer les caractères de fin de ligne
                    else:
                        self.dico.append(temp_dico)
                        break
        
                # fermeture du fichier
                self.f.close()
        
                return self.dico
        
        
        class PlusLong(object):
            """Classse permettant de trouver le mot le plus long"""
            def __init__(self, letters, dico):
                # on tranforme letters en liste et on trie
                self.letters = list(letters)
                self.letters.sort()
                self.dico = dico
                self.mot_trouve = []    #liste des mots trouvés
        
            def cherche(self):
                """cherche le mot le plus long"""
                z = len(self.letters)
        
                # tant qu'on ne trouve pas de mots et qu'on est >= 3 lettres
                while not self.mot_trouve and z>=3:
        
                    # on essaie les combinaisons possibles de lettres
                    for m in combinations(self.letters, z):
                        c = self.compare(m)
                    z -= 1
        
                print("Les mots les plus longs que l'on peut former avec {} sont : {}"
                      .format(self.letters, self.mot_trouve))
        
            def compare(self, chaine):
                """""Compare la chaine avec le dico"""
                for letter in chaine:
                    # on choisi le dico commencant par letter
                    first_letter_dico = self.dico[ascii_lowercase.index(letter)]
        
                    for mot in first_letter_dico:
                        # on vire le trait d'union s'il y en a un
                        mot = mot.replace("-", "")
                        # si le mot du dico a la même longueur
                        # que celui recherché on continue
                        if len(mot) == len(chaine):
                            # on transforme mot en liste et on trie
                            mot_trie = list(mot)
                            mot_trie.sort()
                            i = 0
                            t = True
        
                            while i<len(mot):
                                if mot_trie[i] != chaine[i]:
                                    t = False
                                i+=1
        
                            # si t est toujours vrai on ajoute le mot
                            if t:
                                self.mot_trouve.append(mot)
        
        
        class Application(object):
            """Corps de l'application"""
            def __init__(self, nb):
                self.letters = ''
                self.nb = nb    # nombre de lettres
                self.choix = self.choix_voy_cons()
                self.dico = Dico(self.nb).remplissage_dico()
                self.mot_le_plus_long = PlusLong(self.letters, self.dico).cherche()
        
        
            def choix_voy_cons(self):
                consonnes = 'bcdfghjklmnpqrstvwxz'
                voyelles = 'aeiouy'
                compt_voy = 0    #pour compter les voyelles
        
                for i in range(0, self.nb):
        
                    while 1:
                        # vérifie s'il y a au moins 2 voyelles
                        if i >= self.nb-2 and compt_voy < 2:
                            self.letters += voyelles[randrange(0,5)]
                            print("Le nombre de voyelles n'a pas été atteint, la \
        voyelle {} a été ajoutée.".format(self.letters[-1]))
                            compt_voy += 1
                            break
        
                        l = input('(c)onsonne ou (v)oyelle ? ')
                        # [:-1] pour échapper le \r, je ne sais pas pourquoi il est là
                        # on choisi une lettre au pif
                        if l[:-1] == 'c':
                            self.letters += consonnes[randrange(0, 19)]
                            break
                        elif l[:-1] == 'v':
                            self.letters += voyelles[randrange(0,5)]
                            compt_voy +=1
                            break
                        else:    #si la lettre n'est pas c ou v
                            print("J'ai dis c ou v")
        
        
        if __name__ == '__main__':
        
            import time
            debut = time.clock()
            test = Application(9)
            fin = time.clock()
            print("Éxécution en {:5.4f}s".format(fin-debut))
        
        • Partager sur Facebook
        • Partager sur Twitter
          29 août 2011 à 18:45:17

          Citation : carrion crow

          J'ai rajouter la limite de nombre de lettres pour le remplissage du dico


          Quel est le gain constaté ?

          Sinon, tu as lu les posts précédents ? Il y a eu une discussion plutôt intéressante.
          • Partager sur Facebook
          • Partager sur Twitter
            30 juin 2012 à 17:09:05

            Ce sujet commence à dater un peu, mais j'ai fait ça et c'est plutôt rapide je trouve (y'a ptetre une erreur ?) :

            #coding: utf8
            
            import random
            import time
            
            VOYELLES = ["a", "e", "i", "o", "u", "y"]
            CONSONNES = ["b", "c", "d", "f", "g", "h", "j", "k", "l", "m", "n", "p", "q", "r", "s", "t", "v", "w", "x", "z"]
            
            def tirage_lettres_comme_tv(VOYELLES):
            	nb_lettre = 0
            	nb_voyelle = 0
            	liste_lettre = []
            	while nb_lettre < 9:
            		choix = raw_input("Consonne ou voyelle ? c ou v (minimum 2 voyelles)").lower()
            		while choix != "c" and choix != "v":
            			choix = raw_input("On a dit v ou c").lower()
            		if choix == "c" and nb_lettre >= 7 and nb_voyelle < 2:
            			while choix == "c":
            				choix = raw_input("IL FAUT MINIMUM 2 VOYELLES. Vous n'avez plus le choix : demandez une voyelle.").lower()
            		if choix == "c":
            			lettre = random.choice(CONSONNES)
            		else:
            			lettre = random.choice(VOYELLES)
            			nb_voyelle += 1
            		liste_lettre.append(lettre)
            		print "lettre tirée : ", lettre	
            		nb_lettre += 1
            	return liste_lettre
            
            
            def demander_tirage():
            	tirage = raw_input('entrez votre tirage').lower()
            	return tirage		
            
            def creation_dictionnaire_ordonne():
            	with open("dictionnaire.txt", "r") as fichier_dico:
            		dict_ord_len = {}
            		for longueur in range(26):
            			dict_ord_len[longueur+1] = []
            		while True:
            			mot = fichier_dico.readline()
            			if mot == '':
            				break
            			mot = mot.strip('\n')
            			if '-' in mot:
            				mot = mot.replace('-','')
            			dict_ord_len[len(mot)].append(mot)
            		fichier_dico.close()
            		return dict_ord_len
            		
            		
            def trouver_mot_plus_long(longueur_max_mot, dico, tirage):
            	longueur_mot = longueur_max_mot
            	solution= []
            	set_tirage = set(tirage)
            	while longueur_mot > 0:
            		for mot in dico[longueur_mot]:
            			if set(mot).issubset(set_tirage) :
            				tirage_test = list(tirage)
            				try:
            					for lettre in mot:
            						tirage_test.remove(lettre)
            				except: 
            					continue
            				solution.append(mot)
            		if solution != []:
            			return solution
            		longueur_mot -= 1
            
            t_pre_dico = time.time()
            dict_ord_len = creation_dictionnaire_ordonne()
            time_post_dico = time.time()-t_pre_dico
            print 'Le dico a mis ' + str(time_post_dico) +' sc a se charger'
            on_joue = True
            while on_joue:
            	tirage = demander_tirage()
            	t = time.time()	
            	solution = trouver_mot_plus_long(len(tirage), dict_ord_len, tirage)
            	time_post_solution = time.time()-t
            	print 'Le script a mis ' + str(time_post_solution) +' sc pour trouver la solution'
            	print solution	
            	rejouer = raw_input('Rejouer ? Oui/Non')
            	if rejouer == "non":
            		on_joue = False
            


            Chez moi : 0.6 sc pour charger le dico
            ~0.15 sc pour trouver la meilleure combine de 5 lettres
            ~0.25sc pour trouver la meilleure combine de 10 lettres
            ~0.5 sc pour trouver la meilleure combine de 17 lettres
            • Partager sur Facebook
            • Partager sur Twitter

            [Exercice] des chiffres et des lettres

            × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
            × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
            • Editeur
            • Markdown