IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Python Discussion :

Fonctionr sort() ne fonctionne pas ?


Sujet :

Python

  1. #1
    Membre du Club
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    56
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Janvier 2007
    Messages : 56
    Points : 43
    Points
    43
    Par défaut Fonctionr sort() ne fonctionne pas ?
    Bonjour à tous,

    Je ne comprend pas pourquoi cela ne fonctionne pas ?
    Je lis un fichier txt contenant une série de prénoms (format str).
    J'ajoute les lignes dans une liste.
    Et, enfin, j'essaie de trier la liste avec la fonction liste.sort()...
    Quand j'affiche la liste pour vérifier je constate que la liste n'es pas triée... et je ne comprend pas pourquoi cela ne fonctionne pas !

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
     
    #!/usr/bin/env python
    # -*- coding: utf-8 -*-
    #
    # Problem 22 - Project Euler
    #
    # Using names.txt (right click and 'Save Link/Target As...'),
    # a 46K text file containing over five-thousand first names, begin by
    # sorting it into alphabetical order. Then working out the alphabetical
    # value for each name, multiply this value by its alphabetical position
    # in the list to obtain a name score.
    #
    # For example, when the list is sorted into alphabetical order,
    # COLIN, which is worth 3 + 15 + 12 + 9 + 14 = 53, is the 938th name
    # in the list. So, COLIN would obtain a score of 938 × 53 = 49714.
    #
    # What is the total of all the name scores in the file?
    #
    import time
     
    def exo_22_project_Euler(fichier_txt):
     
        a = []
     
        f = open(fichier_txt, 'r')
        for ligne in f:
            a.append(ligne)
        f.close()
     
        a.sort()
     
        return a
     
    def main():
        s = time.time()
     
        print exo_22_project_Euler('names.txt')
     
        e = time.time()-s
        print "\nRésultat fourni en %f secondes." % (e)
     
        return 0
     
    if __name__ == '__main__': main()
    En vous remerciant d'avance,
    a+
    EricStib

  2. #2
    Membre extrêmement actif
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    1 418
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 1 418
    Points : 1 658
    Points
    1 658
    Par défaut
    Est-ce qu'il y a bien plusieurs lignes dans ton fichier_txt ?
    Si a ne contient qu'un élément quand tu lui appliques sort() ........

    Donnes nous un aperçu du contenu de fichier_txt, stp, obtenu en faisant

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    f = open(fichier_txt, 'r')
    u = f.readlines()
    f.close()
    print u
    Donne nous aussi l'affichage de la liste que tu obtiens en résultat stp.

    PS: un essai de ton code sur un fichier de plusieurs lignes contenant un mot par ligne m'a affiché une liste qui est bien triée

  3. #3
    Membre du Club
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    56
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Janvier 2007
    Messages : 56
    Points : 43
    Points
    43
    Par défaut
    Bonjour,

    Le fichier texte se trouve ici: http://projecteuler.net/project/names.txt
    Il ne contient qu'une seule ligne mais puisque je le met dans une liste, pourquoi la fonction sort() ne fonctionne pas ?

    J'ai mis l'écran obtenu en file attach, je ne savais pas comment le faire apparaitre ici.

    a+
    Images attachées Images attachées  

  4. #4
    Membre du Club
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    56
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Janvier 2007
    Messages : 56
    Points : 43
    Points
    43
    Par défaut
    J'ai trouvé quelque chose avec les expressions régulières (tirés d'en livre)... cela à l'air de scinder ma ligne en mot mais je ne comprend pas encore comment cela fonctionne et je ne sais pas si je suis vraiment tiré d'affaire pour mon algo mais, en utilisant le code ci-dessous, j'arrive à trier ma liste !!

    Maintenant, je vais essayer de comprendre le code du bouquin car je ne connais encore rien sur les expressions régulières

    Encore merci et a+,

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
     
    import re
     
    def exo_22_project_Euler(fichier_txt):
        alphabet = {'A':1, 'B':2, 'C':3, 'D':4, 'E':5, 'F':6, 'G':7, 'H':8,
                    'I':9, 'J':10, 'K':11, 'L':12, 'M':13, 'N':14, 'O':15,
                    'P':16, 'Q':17, 'R':18, 'S':19, 'T':20, 'U':21,
                    'V':22, 'W':23, 'X':24, 'Y':25, 'Z':26}
     
        a = []
        position = 1
        total = 0
        re_mot = re.compile(r'[\w"-]+')
     
        f = open(fichier_txt, 'r')
        for ligne in f:
            for mot in re_mot.finditer(ligne):
                a.append(mot.group(0))
        f.close()
     
        a.sort()

  5. #5
    Membre extrêmement actif
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    1 418
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 1 418
    Points : 1 658
    Points
    1 658
    Par défaut
    Puisque le fichier ne contient qu'une seule ligne,
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
            for ligne in f:
                a.append(ligne)
    ne travaille qu'une fois.
    En sortie de "boucle", a ne contient qu'un élément qui est une chaine de caractères.
    Nous, nous voyons des mots dans cette chaine, entourés de " " et séparés par des virgules. Mais ces éléments-mots de la chaine n'existent pas pour sort(): elle ne cherche qu'à trier les éléments de la liste a... et il n'y en a qu'un.

  6. #6
    Membre extrêmement actif
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    1 418
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 1 418
    Points : 1 658
    Points
    1 658
    Par défaut
    Les expressions régulières sont un sujet très intéressant, un vrai régal, mais elles sont inutiles pour ce niveau de problème.
    Ce que nous identifions comme mots dans la chaine de caractères ont le bon goût d'être séparés par des virgules et entourés de " ". En fait , il faut se dire que les mots sont séparés par des chaines de 3 caractères "," , ce sera plus parlant pour un programme. Et il faut chercher une liste qui découpe une chaine en fonction d'un séparateur. Il faut regarder ici:
    http://www.python.org/doc/2.5/lib/ge....html#letter-s
    à string,
    methods
    Une page à bien connaître à mon avis.

  7. #7
    Futur Membre du Club
    Profil pro
    Inscrit en
    Janvier 2009
    Messages
    12
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2009
    Messages : 12
    Points : 8
    Points
    8
    Par défaut
    moi je sais, moi je sais!!!!
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    fch=open("fichier","r")
    fichier=fch.readlines()
    fch.close()
    fichier.replace("'","")
    fichier.split(',')
    for i in fichier:
     print i
    j'ai bon ?

  8. #8
    Membre extrêmement actif
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    1 418
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 1 418
    Points : 1 658
    Points
    1 658
    Par défaut
    maori,
    je te conseillerais 2 choses:
    - chaque fois qu'on utilise une fonction, il faut à mon avis se poser 2 questions pour bien savoir où on en est:
    'Sur quel type d'objet cette fonction s'applique-t-elle ?'
    'Modifie-t-elle l'objet auquel on l'applique ou renvoie-t-elle un objet ? Si elle renvoie un objet, quel est son type ?'
    - faire tourner les codes


    En faisant tourner ton code j'obtiens le message d'erreur suivant:
    fichier.replace("'","")
    AttributeError: 'list' object has no attribute 'replace'
    readlines() est une méthode de fichier qui produit une liste
    replace() est une méthode de string, elle ne peut donc pas être appliquée à ce que produit readlines()

    readlines() est de toute façon inadaptée au problème puisque readlines() scinde le contenu d'un fichier en lignes et place les lignes obtenues dans une liste. Or le fichier de départ en question n'a qu'une ligne. Inutile d'avoir 10 doigts si on a un piano à une seule touche.

    En réalité il est inexact de parler de lignes dans un fichier car une ligne est une notion visuelle et il n'y a rien de visuel dans un fichier numérique constitué de bits, il n'y a que des caractères qui se suivent à la la queue leu leu.
    Dire qu'un fichier comporte des lignes, c'est un raccourci pour signifier qu'il y a des caractères '\n' dans la succession de caractères constituant le fichier et que ces '\n' provoqueront des retours à la ligne si on fait afficher d'un coup le contenu du fichier placé dans une chaine obtenue par f.read() ,
    ou constitueront des repères permettant aux fonctions readlines() et splitlines() de fractionner la succession de caractères en portions qui seront appelées des lignes et seront stockées dans une liste.

    Soit dit en passant, d'après ce que j'ai constaté, et si j'ai bien compris les choses, '\n' est une REPRÉSENTATION qui traduit un retour à la ligne ( ou retour chariot, ou EOL, je ne sais pas quel est le terme correct) mais cette représentation ne signifie pas qu'il y a 2 caractères écrits à tel endroit dans un fichier. D'après ce que j'ai constaté , je conclus qu'un EOL concret est une SUCCESSION DE BITS de longueur identique à celle des caractères alphanumériques et autres connus, mais que cette succession n'est celle d'aucun des caractères connus par ailleurs ni d'aucune combinaison de plusieurs caractères.
    Cela veut dire que pour enlever le EOL au bout d'un objet-ligne représenté par ln, il faut prendre ln[0:-1] et non pas ln[0:-2]



    Comme readlines() est inutile et qu'on veut appliquer des méthodes de string au contenu du fichier, il faut donc le lire par read() qui produit une chaine de caractères ch.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    f = open("names","r")
    ch = f.read()
    Pour séparer ensuite les mots, replace() me semble inutile:
    il faut se dire que les mots sont séparés par des chaines de 3 caractères "," , ce sera plus parlant pour un programme.
    Mais ch contient y compris le '\n' de la fin. Il faut faire attention à le laisser aussi de coté dans la phase d'obtention des mots à partir de ch.

    Le fichier tel qu'il est fourni permet d'utiliser read(). Dans le cas d'un fichier "avec des lignes", on appliquerait split() à chacune des lignes obtenues après usage de readlines() ou read().splitlines().
    readlines() conserve les retours à la ligne '\n'
    splitlines() ne les conserve pas.
    Mais si on y tient , readlines() et read().splitlines(True) produisent la même liste des lignes comportant les retours à la ligne '\n' à leurs extrémités.



    EricStib,
    ton code ne marche pas. Il m'a donné comme résultat: None.
    La regex r'[\w"-]+' n'est pas du tout adaptée.
    [\w"-] c'est l'ensemble [a-zA-Z0-9_"-]
    Le + signifie qu'une chaine qui matche avec cette regex contient 1 ou plusieurs caractères successifs pris dans cet ensemble. On ne voit pas le rapport avec le séparateur "'" dans le fichier Euler.

    «For each match, the iterator re.finditer() returns a match object.»
    Cela signifie que re.finditer() fournit des MatchObjects: un MatchObject pour chaque match détecté dans une chaine.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    import re
    bla = '[\w"-]+'
    ch = 'jgb"vkn IYt&^5iO'
    for m in re.finditer(bla,ch):
        print m
        print type(m)
    <_sre.SRE_Match object at 0x013397C8>
    <type '_sre.SRE_Match'>
    <_sre.SRE_Match object at 0x01339790>
    <type '_sre.SRE_Match'>
    <_sre.SRE_Match object at 0x013397C8>
    <type '_sre.SRE_Match'>
    Pour tirer quelque chose de re.finditer() il faut appliquer aux MatchObjects qu'il produit une méthode de MatchObject, par exemple group() qui donne l'identité de la sous-chaine ayant matché.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    import re
    bla = '[\w"-]+'
    ch = 'jgb"vkn IYt&^5iO'
    for m in re.finditer(bla,ch):
        print m.group()
    jgb"vkn
    IYt
    5iO

  9. #9
    Membre du Club
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    56
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Janvier 2007
    Messages : 56
    Points : 43
    Points
    43
    Par défaut
    Bonjour,
    Alors, j'en suis revenu à des choses plus simples
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    data = f.read().split(',')
    J'ai utilisé cette manière de scindé ma ligne en mot (en me servant des virgules comme séparateurs)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    for (ligne, prenom) in enumerate(sorted(data)):
    C'est sur cette ligne que j'ai passé le plus de temps, j'utilisais range() mais cela me donnait une erreur... j'ai mis du temps à découvrir enumerate
    Par contre, je faisais quand j'ai vu qu'il y avait moyen de condensé avec sorted()

    Dans ma première version de code je m'étais fait un dictionnaire mais, par après, j'ai découvert ceci:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    for c in range(len(prenom)):
                total += string.ascii_uppercase.find(prenom[c])+1
    Ce qui me fait dire:
    Python est très simple d'utilisation... mais on gagne beaucoup à lire la doc !!
    Mon code complet ci-dessous (il fonctionne)
    Merci beaucoup pour l'aide,
    a+
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
     
    #!/usr/bin/env python
    # -*- coding: utf-8 -*-
     
    import time
    import string
     
    def exo_22_project_Euler(fichier_txt):
     
        total, total_general = 0, 0
     
        f = open(fichier_txt, 'r')
        data = f.read().split(',')
        f.close()
     
        # pour tout les prénoms repris dans la liste
        for (ligne, prenom) in enumerate(sorted(data)):
            total = 0
            for c in range(len(prenom)):
                total += string.ascii_uppercase.find(prenom[c])+1
            total_general += total * (ligne+1)
     
        return total_general
     
     
    def main():
        s = time.time()
     
        print exo_22_project_Euler('names.txt')
     
        e = time.time()-s
        print "\nRésultat fourni en %f secondes." % (e)
     
        return 0
     
    if __name__ == '__main__': main()

  10. #10
    Membre expérimenté
    Homme Profil pro
    Inscrit en
    Mars 2007
    Messages
    941
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Mars 2007
    Messages : 941
    Points : 1 384
    Points
    1 384
    Par défaut
    Quelques améliorations:

    D'abord, la boucle interne peut être simplifiée:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
            for c in range(len(prenom)):
                total += string.ascii_uppercase.find(prenom[c])+1
     
    Est équivalent à:
     
            for c in prenom:
                total += string.ascii_uppercase.find(c)+1
    Ensuite, Il vaut mieux utiliser time.clock(), qui est plus précis que time.time(), pour mesurer le temps d'exécution.

    Finalement, le fait de faire une recherche (find) dans une liste (string.ascii_uppercase) à chaque itération n'est pas optimal; on a la fonction ord qui renvoie directement le code du caractère. Mais cela crée un autre problème: le fichier contient chaque prénom entre guillemets; ton code fonctionnait malgré cela car find retourne -1 si le caractère recherché (ici: ") n'est pas trouvé, auquel tu additionnes 1 ce qui fait que le résultat n'en souffre pas. Mais avec ord cela pose problème, et il faut donc les retirer (avec la méthode strip ci-dessous).

    Au final le code complet donne ceci:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    #!/usr/bin/env python
    # -*- coding: utf-8 -*-
     
    import time
     
    def exo_22_project_Euler(fichier_txt):
     
        total_general = 0     # inutile d'initialiser total ici; il l'est plus bas
     
        f = open(fichier_txt, 'r')
        data = [p.strip('"') for p in f.read().split(',')]
        f.close()
     
        OFFSET = ord('A')-1
        # pour tous les prénoms repris dans la liste
        for ligne, prenom in enumerate(sorted(data)):
            total = 0
            for c in prenom:
                total += ord(c) - OFFSET
            total_general += total * (ligne+1)
     
        return total_general
     
     
    def main():
        s = time.clock()
     
        print exo_22_project_Euler('names.txt')
     
        e = time.clock()-s
        print "\nRésultat fourni en %f secondes." % (e)
     
        return 0
     
    if __name__ == '__main__': main()
    Il est environ 2 fois plus rapide que ton code, de par l'utilisation de ord.

  11. #11
    Membre extrêmement actif
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    1 418
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 1 418
    Points : 1 658
    Points
    1 658
    Par défaut
    Python est très simple d'utilisation... mais on gagne beaucoup à lire la doc !!
    Ça c'est ben vrai !

    Il y a un autre aphorisme auquel je suis arrivé à force de réfléchir sur des problèmes:

    Quand on croit en avoir fini avec un code, on peut encore le simplifier, car Python est très très très agile.
    Or il y a encore des choses un tantinet optimisables dans ton code.

    Ce qui me surprend le plus est que ça ne semble pas te gêner d'avoir une liste data qui est ['"MARY"', '"PATRICIA"', '"LINDA"', '"BARBARA"', '"ELIZABETH"', etc...
    alors que ce qui nous intéresse ce sont les PRÉNOMS, pas les "PRÉNOMS" !!!

    il faut se dire que les mots sont séparés par des chaines de 3 caractères "," , ce sera plus parlant pour un programme.
    En splitant avec "," , je veux dire avec '","' on obtient directement une liste
    ['"MARY', 'PATRICIA', 'LINDA', 'BARBARA', 'ELIZABETH', etc...
    Mais attention au premier et au dernier éléments de la liste !!


    ------------------------------------

    Ensuite dans la boucle for (ligne, prenom) in enumerate(sorted(data)): , le coup du find() qui vaut -1 pour les caractères " et AUSSI le '\n' du dernier élément de la liste avant tri ("ALONSO"\n) (y avais tu vraiment pensé ?), et qui compense le +1 nécessaire quand il s'agit des ABCDetc, c'est assez malin.

    Mais, en restant dans le cadre de ton algo, je propose les améliorations suivantes:

    - créer ALPHABET = '"ABCDEFGHIJKLMNOPQRSTUVWXYZ'
    On évite d'importer un module, on n'a pas besoin d'ajouter +1 à ALPHABET.find(prenom[c]) pour les lettres et ALPHABET.find('"') produit directement 0.

    -
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    for c in range(len(prenom)):
        total += ALPHABET.find(prenom[c])
    # se remplace avantageusement par
    for c in prenom:
        total += ALPHABET.find(c)
    - pour éviter d'ajouter +1 dans le calcul de total_general, il suffit aussi d'ajouter un élément bidon en tête de liste data pour décaler les prenoms sur leur "bon" indice; et comme l'insert sera en indice 0, il pésera 0 quelle que soit son écriture. Mais attention que l'insert commence par " pour ne pas fausser le triage !


    Ce qui donne, avec ta liste:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
        data.insert(0,'"AAAAA"')
        for (ligne, prenom) in enumerate(sorted(data)):
            total = 0
            for c in prenom:
                total += alphabet.find(c)
            total_general += total * ligne
    Mais il reste un problème: il y a '"ALONSO"\n' dans la liste data parce que la fin du fichier était ..."DARELL","BRODERICK","ALONSO"\n'. Cette fois le '\n' va produire un find() égal à -1. Il faut donc éliminer le dernier caractère de data avant tri.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
        f = open(fichier_txt, 'r')
        data = f.read()[0:-1].split(',')
        f.close()
        data.insert(0,'"AAAAA"')
        for (ligne, prenom) in enumerate(sorted(data)):
            total = 0
            for c in prenom:
                total += alphabet.find(c)
            total_general += total * ligne


    --------------------------------------

    Pour ne pas travailler stérilement sur les " au début et à la fin de chaque prenom (il y a plus de 5000 prenoms)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    # soit
    for c in prenom[1:-1]:
        total += ALPHABET.find(c)
    # soit
    data = [ item[1:-1] for item in data ] avant de commencer la boucle
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
        f = open(fichier_txt, 'r')
        data = [ item[1:-1] for item in  f.read()[0:-1].split(',')]
        data.insert(0,'AAAAA')
        f.close()
        for (ligne, prenom) in enumerate(sorted(data)):
            total = 0
            for c in prenom:
                total += alphabet.find(c)
            total_general += total * ligne


    M'enfin, je préfère personnellement

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
        f = open(fichier_txt, 'r')
        data = f.read()[1:-2].split('","')
        data.insert(0,'AAAAA')
        f.close()
        for (ligne, prenom) in enumerate(sorted(data)):
            total = 0
            for c in prenom:
                total += alphabet.find(c)
            total_general += total * ligne

    EDIT:
    En fait, il y a d'autres solutions encore que je n'ai pas regardées en détail. Il y en a une que je testerai quand j'aurai le temps parce qu'elle doit aller très très vite (depuis que dividee m'a convaincu que les dictionnaires sont rapides , j'y pense un peu plus) mais elle fait sortir du cadre de l'énoncé Euler qui demande à créer d'abord la liste des prénoms. Je ne crois pas que ce soit nécessaire (cette liste...)

  12. #12
    Membre extrêmement actif
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    1 418
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 1 418
    Points : 1 658
    Points
    1 658
    Par défaut
    Dans ton code, dividee
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    #Il faut corriger
    data = [p.strip('"') for p in f.read().split(',')]
    #en
    data = [p.strip('"') for p in f.read()[0:-1].split(',')]
    #pour avoir le bon résultat.
    Le problème est la fin du fichier:
    ..."DARELL","BRODERICK","ALONSO"\n'
    dont ni strip('"') ni split(',') ne retire le retour chariot '\n'.
    C'est casse-gueule ces trucs , n'est ce pas ?

    C'est pour ça que li = f.read().splitlines() ou f.readlines() sont quand même des écritures bien pratiques, ça vire tous les '\n' sans qu'on ait à se poser de questions. Mais après, s'il n'y a qu'un élément dans la liste il ne faut pas se planter, la chaine est li[0] , pas la liste li.



    Pour le coup de ord() , bien vu dividee !.
    Je me doutais bien qu'il existait une fonction de ce genre en vertu de l'aphorisme "il y a toujours plus simple" , mais j'ai eu la flemme de chercher.
    En mettant ord() dans mon code, ça booste.
    Voici une série de résultats avec les code dans l'ordre (j'ai la flemme de faire des mesures avec Timer):
    code stib
    code eyquem
    code dividee
    code eyquem modifié dividee

    871198282 Résultat fourni en 0.301000 secondes.
    871198282 Résultat fourni en 0.190000 secondes.
    871198282 Résultat fourni en 0.130000 secondes.
    871198282 Résultat fourni en 0.110000 secondes.
    >>>
    871198282 Résultat fourni en 0.291000 secondes.
    871198282 Résultat fourni en 0.180000 secondes.
    871198282 Résultat fourni en 0.130000 secondes.
    871198282 Résultat fourni en 0.110000 secondes.
    >>>
    871198282 Résultat fourni en 0.290000 secondes.
    871198282 Résultat fourni en 0.181000 secondes.
    871198282 Résultat fourni en 0.130000 secondes.
    871198282 Résultat fourni en 0.100000 secondes.
    >>>
    871198282 Résultat fourni en 0.301000 secondes.
    871198282 Résultat fourni en 0.170000 secondes.
    871198282 Résultat fourni en 0.120000 secondes.
    871198282 Résultat fourni en 0.100000 secondes.
    >>>
    871198282 Résultat fourni en 0.300000 secondes.
    871198282 Résultat fourni en 0.171000 secondes.
    871198282 Résultat fourni en 0.120000 secondes.
    871198282 Résultat fourni en 0.110000 secondes.
    Et maintenant....

    ...il faut trouver encoe plus simple.... ça doit pouvoir se faire !

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    #!/usr/bin/env python
    # -*- coding: utf-8 -*-
    import string
    import time
    alphabet = '"ABCDEFGHIJKLMNOPQRSTUVWXYZ'
     
    def exo_22_project_Euler11(fichier_txt):  #stib
     
        total_general = 0
     
        f = open(fichier_txt, 'r')
        data = f.read().split(',')
        f.close()
     
        # pour tout les prénoms repris dans la liste
        for (ligne, prenom) in enumerate(sorted(data)):
            total = 0
            for c in range(len(prenom)):
                total += string.ascii_uppercase.find(prenom[c])+1
            total_general += total * (ligne+1)
     
        return total_general
     
     
    def exo_22_project_Euler2(fichier_txt): # eyquem
        total_general = 0
        f = open(fichier_txt, 'r')
        data = f.read()[1:-2].split('","')
        data.insert(0,'AAAAA')
        f.close()
        for (ligne, prenom) in enumerate(sorted(data)):
            total = 0
            for c in prenom:
                total += alphabet.find(c)
            total_general += total * ligne
     
        return total_general
     
     
    def exo_22_project_Euler3(fichier_txt): # dividee
     
        total_general = 0     # inutile d'initialiser total ici; il l'est plus bas
     
        f = open(fichier_txt, 'r')
        data = [p.strip('"') for p in f.read()[0:-1].split(',')]
        f.close()
     
        OFFSET = ord('A')-1
        # pour tous les prénoms repris dans la liste
        for ligne, prenom in enumerate(sorted(data)):
            total = 0
            for c in prenom:
                total += ord(c) - OFFSET
            total_general += total * (ligne+1)
     
        return total_general
     
     
     
    def exo_22_project_Euler4(fichier_txt): # eyquem modifié dividee
        total_general = 0
        f = open(fichier_txt, 'r')
        data = f.read()[1:-2].split('","')
        data.insert(0,'AAAAA')
        f.close()
        for (ligne, prenom) in enumerate(sorted(data)):
            total = 0
            for c in prenom:
                total += ord(c)-64
            total_general += total * ligne
     
        return total_general
     
     
    def main():
        s = time.time()
        print exo_22_project_Euler11('naames'),
        print "Résultat fourni en %f secondes." % (time.time()-s)
     
        s = time.time()
        print exo_22_project_Euler2('naames'),
        print "Résultat fourni en %f secondes." % (time.time()-s)
     
        s = time.time()
        print exo_22_project_Euler3('naames'),
        print "Résultat fourni en %f secondes." % (time.time()-s)
     
        s = time.time()
        print exo_22_project_Euler4('naames'),
        print "Résultat fourni en %f secondes." % (time.time()-s)
     
        return 0
     
    if __name__ == '__main__': main()

  13. #13
    Membre expérimenté
    Homme Profil pro
    Inscrit en
    Mars 2007
    Messages
    941
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Mars 2007
    Messages : 941
    Points : 1 384
    Points
    1 384
    Par défaut
    Euh... Dans le fichier names.txt que j'ai téléchargé, il n'y a pas de \n à la fin.

  14. #14
    Membre extrêmement actif
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    1 418
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 1 418
    Points : 1 658
    Points
    1 658
    Par défaut
    .....ah..euh..beh....,...euh.... tiens oui c'est vrai ça: il n'y a pas de retour '\n' dans le fichier téléchargeable.
    Mes excuses dividee, ton code n'était donc pas à corriger.

    Je ne sais pas comment je me suis débrouillé pour en mettre un dans mon fichier mais ça ne peut être que moi parce qu'en réalité le fichier 'naames' que j'ai utilisé était au départ une copie d'un fichier ouvrable avec Python, dans lequel j'ai fait un copier-coller de la liste des prénoms. J'ai dû taper sur Enter par mégarde avant de refermer le fichier.
    En effet, en fonction du type d'un fichier, j'arrive à le faire ouvrir par un programme Python, ou non. Jusqu'à présent, je faisais un copier-coller dans un fichier d'un type ouvrable (avec un logo Windows) pour ne pas me casser la tête.
    Les fichiers de type Rich Text Document (avec un logo representant un calepin, avec des spirales dans le haut, des lignes bleues au milieu et un A rouge en bas a droite) ne sont pas ouvrables par exemple.
    Mais je viens de voir que le fichier 'names' téléchargé du site http://projecteuler.net est de type Text Document et que je peux le faire lire par un programme Python en utilisant le nom 'names.txt'
    J'ai des notions encore trop sommaires sur les types de fichier, il va falloir que je potasse ça aussi.

    -----------------

    Pour ce qui est du problème lui-même, on améliore la vitesse si on remplace l'utilisation de ord() par un dictionnaire
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    p = {}
    for i,lettre in enumerate(',ABCDEFGHIJKLMNOPQRSTUVWXYZ'):
            p[lettre] = i
    Enfin bon, c'est pas énorme comme accélération.


    En fait j'ai trouvé une autre manière de procéder légèrement différente pour résoudre le problème posé, et selon le détail du code dans lequel on l'écrit, le temps d'exécution tombe entre 0,10 et 0,08 seconde. Ce n'est pas une question de dictionnaire, c'est une question d'algorithme traduisant une idée de principe, et l'exécution valide l'idée puisque ça va plus vite.
    Je vais faire un tour sur le site http://projecteuler.net pour situer si ma solution se tient bien par rapport aux autres.

  15. #15
    Membre expérimenté
    Homme Profil pro
    Inscrit en
    Mars 2007
    Messages
    941
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Mars 2007
    Messages : 941
    Points : 1 384
    Points
    1 384
    Par défaut
    Citation Envoyé par eyquem Voir le message
    En effet, en fonction du type d'un fichier, j'arrive à le faire ouvrir par un programme Python, ou non.
    Tous les types de fichiers sont lisibles par Python. D'après ce que tu décris, il me semble que tu as l'option "Masquer les extensions des fichiers dont le type est connu" activée dans Windows. Je conseille à tout le monde de la désactiver (elle se trouve dans les options de dossier, onglet affichage), sinon tu ne vois pas le vrai nom des fichiers, mais une version tronquée.

    Citation Envoyé par eyquem Voir le message
    En fait j'ai trouvé une autre manière de procéder légèrement différente pour résoudre le problème posé, et selon le détail du code dans lequel on l'écrit, le temps d'exécution tombe entre 0,10 et 0,08 seconde. Ce n'est pas une question de dictionnaire, c'est une question d'algorithme traduisant une idée de principe, et l'exécution valide l'idée puisque ça va plus vite.
    Je vais faire un tour sur le site http://projecteuler.net pour situer si ma solution se tient bien par rapport aux autres.
    Si la réponse est bonne, et que le code est plus rapide, ça se tient. Je ne sais pas si tu trouveras l'info que tu cherches sur le site; le but est de trouver une réponse à une question précise, quelle que soit la méthode; on n'envoie pas son code source, il faut juste donner la bonne réponse. Il n'y a donc pas de classement des meilleurs solutions ou ce genre de choses.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Quick Sort ne fonctionne pas
    Par thierryler dans le forum Collection et Stream
    Réponses: 42
    Dernier message: 31/07/2014, 14h38
  2. sort by ne fonctionne pas avec des subtables
    Par ekremyilmaz dans le forum JSF
    Réponses: 1
    Dernier message: 27/07/2010, 13h17
  3. Collections.sort ne fonctionne pas
    Par lex13 dans le forum Collection et Stream
    Réponses: 7
    Dernier message: 12/07/2007, 11h13
  4. Un Hint sur un PopupMenu ne fonctionne pas !!??
    Par momox dans le forum C++Builder
    Réponses: 6
    Dernier message: 26/05/2003, 16h48
  5. ca ne fonctionne pas (generateur auto-incrémentant)
    Par tripper.dim dans le forum SQL
    Réponses: 7
    Dernier message: 26/11/2002, 00h10

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo