Annonce

Réduire
Aucune annonce.

[Python] Mini analyse fréquentielle

Réduire
X
 
  • Filtre
  • Heure
  • Afficher
Tout nettoyer
nouveaux messages

  • [Python] Mini analyse fréquentielle

    Bonjour,

    suite au petit exercice de Fred (cf. http://hackademics.fr/showthread.php...e-caract%E8res) j'ai réalisé un petit script renvoyant le nombre d'occurrences de chaque caractères dans un texte entré.
    C'est très sommaire, pas très pratique pour une véritable utilisation d'analyse fréquentielle mais bon

    Code:
    import os
    
    phrase = raw_input("Entrez votre texte : ")
    mon_dico = dict()
    for lettre in phrase:
        if lettre in mon_dico:
            continue
        else:
            mon_dico[lettre] = phrase.count(lettre)
    
    print(str(mon_dico))
    os.system("pause")
    En espérant que ça serve à certains ^^
    Mon blog : http://rootsheep.info

  • #2
    Coucou Sadik,

    Pour l'algorithmie rien à redire.
    Par contre au niveau de ta syntaxe, deux-trois petites choses peuvent être améliorer.

    Code:
    import os
    
    ...
    
    os.system("pause")
    Pas besoin d'importer une bibliothèque pour bloquer la console.
    Tu peux faire ça :

    Code:
    # Python 2
    raw_input()
    
    # Python 3
    input()
    Ensuite, je recommande d'utiliser la version 3 de Python.
    Et d'indiquer la version (même pour Windows).

    Code:
    # Python 2
    #!/usr/bin/python
    
    # Python 3
    #!/usr/bin/python3
    Au niveau de ta boucle, plutôt que d'indiquer "continue" tu peux simplement écrire :
    Code:
    for lettre in phrase:
        if lettre not in mon_dico:
            mon_dico[lettre] = phrase.count(lettre)
    Et pour l'affichage, tu n'as pas besoin de concaténer une chaîne de caractère avec un dico. Pas besoin d'utiliser str().
    Code:
    print(mon_dico)
    Conclusion :
    Code:
    #!/usr/bin/python
    
    phrase = raw_input("Entrez votre texte : ")
    mon_dico = dict()
    for lettre in phrase:
        if lettre not in mon_dico:
            mon_dico[lettre] = phrase.count(lettre)
    raw_input(mon_dico)
    Petite subtilité, au lieu d'indiquer print() puis raw_input() pour la pause.
    Je concatène les deux opérations !

    Autre proposition en Python 3 et plus concaténé :
    Code:
    #!/usr/bin/python3
    
    mon_dico = {}
    for x in input("Entrez votre texte : "):
    	mon_dico[x] = mon_dico[x]+1 if x in mon_dico else 1
    input(mon_dico)
    Si t'as des questions, n'hésites pas.
    ~ Yarflam ~

    ❉ L'Univers se dirige vers son ultime perfection ❉

    Commentaire


    • #3
      Pour l'algorithmie rien à redire.
      Tu es sûr ? (voir ci-dessous le code)

      Code:
      mon_dico[lettre] = phrase.count(lettre)
      Algorithmiquement parlant, c'est la cata... la méthode count part du début de la chaîne pour recompter et tester le caractère, il y a pas plus lent niveau algorithmique, cependant ce qui sauve c'est que count est en CPython, du coup ça doit être assez efficace, comparé à du pure python

      Maintenant pour être clair, l'essentiel pour mes cours, c'est de voir du code fonctionnel concernant les réponses, la syntaxe est ma seule priorité, et pour cela toutes les informations de yarflam sont tout à fait justifiées et correctes

      Pour information

      Voici les résultats sur une boucle de 10 000 fois

      La fonction de sadik executée en 2.1021710000000002
      La fonction de yarflam executée en 2.9584689999999996
      On comprend bien que count est extrêmement efficace, c'est une fonction C, du coup python seul ne peut rien faire, même si algorithmiquement le code de Yarflam est plus efficace, c'est immérité, mais tous les moyens sont bons comme on dit.

      Le pire c'est qu'il peut encore améliorer en dégageant les doublons de lettre avec la fonction set

      Code:
      def sadikBetter(phrase):
          mon_dico = dict()
          for lettre in set(phrase):
              mon_dico[lettre] = phrase.count(lettre)
          return mon_dico
      La fonction de sadik executée en 2.052838
      La fonction de sadikBetter executée en 1.494132
      La fonction de yarflam executée en 2.911221
      Il va deux fois plus vite, c'est triste... mais c'est la vie !

      Il faut se méfier de ces fonctions C qui souvent tronque les résultats. Maintenant je dis pas, sur un bouquin, peut-être que c'est une toute autre histoire, mais dans ce cas, c'est le meilleur résultat à part la mienne bien sûr

      La fonction de sadik executée en 2.034414
      La fonction de sadikBetter executée en 1.4753309999999997
      La fonction de yarflam executée en 2.86655
      La fonction de fred executée en 1.1223999999999998
      Dernière modification par fred, 23 août 2014, 18h31.

      Commentaire


      • #4
        Re: [Python] Mini analyse fréquentielle

        On peut pas lutter
        Mon blog : http://rootsheep.info

        Commentaire


        • #5
          Faut savoir qu'avec du C++, on va guère plus vite, j'arrive à 0.896 seconde, ce qui rend ma fonction extrêmement efficace, et elle est builtin, ce qui veut dire que cette fonction est déjà connue dans la librairie standard, à vous de là trouver. J'ai déjà quelqu'un qui l'avait trouvé et m'avait envoyé son résultat en MP.

          Bref voici l'implémentation en C++

          Code:
          #include <iostream>
          #include <map>
          #include <string>
          
          std::map <char, int> Counter(std::string str);
          void display(std::map <char, int> d);
          
          int main(void)
          {
          
              std::string texte = "Cet enseignement d’exploration vise à renforcer l’attractivité de la voie littéraire, en montrant aux élèves l’intérêt, l’utilité sociale et la diversité des débouchés d’une formation humaniste au sens large et moderne du terme.\
          On cherche pour cela à :\
          - faire percevoir la variété des études littéraires et des champs professionnels qui s’y rattachent, afin d’éclairer un futur choix d’orientation pour l’élève ;\
          - mettre en œuvre un enseignement fondé sur le croisement et la complémentarité de plusieurs approches disciplinaires ;\
          - faire expérimenter des situations concrètes d’activité ou de recherche en relation avec les disciplines littéraires ;\
          - faire prendre conscience que les études littéraires sont, aujourd’hui plus que jamais, au cœur de la formation de l’homme et du citoyen.\
          L’enseignement d’exploration « littérature et société » a un programme spécifique, structuré autour des Lettres et de l’histoire-géographie. Il est présenté sous forme de domaines d’exploration qui ont été choisis en raison de :\
          - l’ouverture qu’ils constituent pour des élèves sortant de collège ;\
          - les compétences qu’ils permettent de développer et l’éclairage qu’ils apportent sur les formations et les débouchés possibles en liaison avec ces compétences ;\
          - la collaboration fructueuse qu’ils permettent d’engager entre les différentes disciplines du champ littéraire.";
          
              std::map <char, int> result = Counter(texte);
              display(result);
          
              return 0;
          }
          
          std::map <char, int> Counter(std::string str)
          {
              std::map<char,int> res;
              std::string::iterator it;
          
              for (it=str.begin(); it!=str.end(); ++it)
              {
                  if (res.count(*it) > 0)
                      res[*it] += 1;
                  else
                      res[*it] = 1;
              }
          
              return res;
          }
          
          void display(std::map <char, int> d)
          {
              std::map<char, int>::iterator it;
          
              for (it=d.begin(); it!=d.end(); ++it)
                  std::cout << it->first << " -> " << it->second << std::endl;
          }
          Rien de tel que d'implémenter son propre dictionnaire, je divise presque par 2 mon temps

          Code:
          #include <iostream>
          #include <vector>
          #include <string>
          
          struct paire
          {
              char letter;
              int n;
          };
          
          int add(char myLetter, std::vector <paire> &v);
          void create(char myLetter, std::vector <paire> &v);
          std::vector <paire> Counter(std::string str);
          void display(std::vector <paire> v);
          
          int main(void)
          {
              std::vector <paire> res;
          
              std::string texte = "Cet enseignement d’exploration vise à renforcer l’attractivité de la voie littéraire, en montrant aux élèves l’intérêt, l’utilité sociale et la diversité des débouchés d’une formation humaniste au sens large et moderne du terme.\
          On cherche pour cela à :\
          - faire percevoir la variété des études littéraires et des champs professionnels qui s’y rattachent, afin d’éclairer un futur choix d’orientation pour l’élève ;\
          - mettre en œuvre un enseignement fondé sur le croisement et la complémentarité de plusieurs approches disciplinaires ;\
          - faire expérimenter des situations concrètes d’activité ou de recherche en relation avec les disciplines littéraires ;\
          - faire prendre conscience que les études littéraires sont, aujourd’hui plus que jamais, au cœur de la formation de l’homme et du citoyen.\
          L’enseignement d’exploration « littérature et société » a un programme spécifique, structuré autour des Lettres et de l’histoire-géographie. Il est présenté sous forme de domaines d’exploration qui ont été choisis en raison de :\
          - l’ouverture qu’ils constituent pour des élèves sortant de collège ;\
          - les compétences qu’ils permettent de développer et l’éclairage qu’ils apportent sur les formations et les débouchés possibles en liaison avec ces compétences ;\
          - la collaboration fructueuse qu’ils permettent d’engager entre les différentes disciplines du champ littéraire.";
          
              res = Counter(texte);
              display(res);
          
              return 0;
          }
          
          int add(char myLetter, std::vector <paire> &v)
          {
              std::vector <paire>::iterator it;
              paire p;
          
              for (it=v.begin(); it!=v.end(); it++)
              {
                  p = *it;
                  if (p.letter == myLetter)
                  {
                      p.n += 1;
                      *it = p;
                      return 1;
                  }
              }
          
              return 0;
          }
          
          void create(char myLetter, std::vector <paire> &v)
          {
              paire p;
              p.letter = myLetter;
              p.n = 1;
          
              v.push_back(p);
          }
          
          std::vector <paire> Counter(std::string str)
          {
              std::string::iterator it;
              std::vector <paire> myVector;
          
              for (it=str.begin(); it!=str.end(); it++)
              {
                  if (!add(*it, myVector))
                      create(*it, myVector);
              }
          
              return myVector;
          }
          
          void display(std::vector <paire> v)
          {
              std::vector <paire>::iterator it;
              paire p;
          
              for (it=v.begin(); it!=v.end(); it++)
              {
                  p = *it;
                  std::cout << p.letter << " -> " << p.n << std::endl;
              }
          }
          Je suis à 0.562s, nettement mieux !
          Dernière modification par fred, 25 août 2014, 09h59.

          Commentaire


          • #6
            Voilà ma version en C :

            #include <stdio.h>
            #include <locale.h>
            #include <wchar.h>
            #include <stdlib.h>
            #include <string.h>

            int main(int argc, char *argv[]){

            setlocale(LC_ALL, "");

            int occu[256];
            int cpt;
            for (cpt=0;cpt<256;cpt++){
            occu[cpt]=0;
            }
            wchar_t phrase[strlen(argv[1])+1];
            mbstowcs(phrase,argv[1], strlen(argv[1])+1);
            wprintf(L"\n%ls",phrase);

            int i;
            for(i=0;i<wcslen(phrase) ;i++){
            occu[phrase[i]]++;
            }
            for(i=0;i<256 ;i++)
            if(occu[i]>0)
            wprintf(L"\n %lc : %d",i,occu[i]);
            return 0;
            }

            Commentaire


            • #7
              Peux-tu le rendre exécutable dans le corps du programme, comme je l'ai proposé dans ma version C++ ? Ensuite il aurait été préférable d'avoir une fonction retournant (mot clé return) la liste des lettres et le nombre d'occurrences, sinon ça serait trop simple.

              Le but étant de pouvoir réutiliser cette fonction dans n'importe quelle autre programme créé

              Commentaire


              • #8
                Peux-tu le rendre exécutable dans le corps du programme
                je ne vois pas trop ce que tu entends par executable.
                Ceci dit j'ai quand même essayé de faire une deuxième mouture en séparant le main et la fonction et où la chaine est écrite en dur comme dans ton code.
                Dis moi si c'est mieux

                Code:
                #include <stdio.h>
                #include <locale.h>
                #include <wchar.h>
                #include <stdlib.h>
                #include <string.h>
                
                
                int * occurrenceLettres(const wchar_t *phrase,int * occu);
                
                int main(int argc, char *argv[]){
                	setlocale(LC_ALL, "");
                
                	int occu[256];
                	int cpt;
                	for (cpt=0;cpt<256;cpt++){
                		occu[cpt]=0;
                	}
                	wchar_t * texte = L"Cet enseignement d’exploration vise à renforcer l’attractivité de la voie littéraire, en montrant aux élèves l’intérêt, l’utilité sociale et la diversité des débouchés d’une formation humaniste au sens large et moderne du terme.\
                On cherche pour cela à :\
                - faire percevoir la variété des études littéraires et des champs professionnels qui s’y rattachent, afin d’éclairer un futur choix d’orientation pour l’élève ;\
                - mettre en œuvre un enseignement fondé sur le croisement et la complémentarité de plusieurs approches disciplinaires ;\
                - faire expérimenter des situations concrètes d’activité ou de recherche en relation avec les disciplines littéraires ;\
                - faire prendre conscience que les études littéraires sont, aujourd’hui plus que jamais, au cœur de la formation de l’homme et du citoyen.\
                L’enseignement d’exploration « littérature et société » a un programme spécifique, structuré autour des Lettres et de l’histoire-géographie. Il est présenté sous forme de domaines d’exploration qui ont été choisis en raison de :\
                - l’ouverture qu’ils constituent pour des élèves sortant de collège ;\
                - les compétences qu’ils permettent de développer et l’éclairage qu’ils apportent sur les formations et les débouchés possibles en liaison avec ces compétences ;\
                - la collaboration fructueuse qu’ils permettent d’engager entre les différentes disciplines du champ littéraire.";
                
                	occurrenceLettres(texte,occu);
                	int i;
                	for(i=0;i<256 ;i++){
                		if(occu[i]>0)wprintf(L"\n %lc : %d\n",i,occu[i]);
                	}
                	return 0;
                }
                
                int * occurrenceLettres(const wchar_t * phrase,int* occu){
                	int i;
                	for(i=0;i<wcslen(phrase) ;i++){
                		occu[phrase[i]]++;
                	}
                	return occu;
                }

                Commentaire


                • #9
                  Ah j'ai une erreur lors de l'exécution

                  Code:
                  Erreur de segmentation (core dumped)

                  Commentaire


                  • #10
                    j'ai eu cette erreur a cause des apostrophes qui ont pour code une valeur supérieure à 255.
                    Solution : ajouter le fameux % 256
                    int * occurrenceLettres(const wchar_t * phrase,int* occu){
                    int i;
                    for(i=0;i<wcslen(phrase) ;i++){
                    occu[phrase[i]%256]++;
                    }
                    return occu;
                    }

                    Commentaire

                    Chargement...
                    X