Partage
  • Partager sur Facebook
  • Partager sur Twitter

Poker

Identifier une main, comparer deux mains

    17 juillet 2011 à 1:36:45

    Moi perso j'y vais plus doucement car, au moins candide et Yoch montrent du code (et pas que sur le forum python.) :-°

    Alors après comme dis Josmiley, les goûts et les codeurs.
    Mais perso, je préfère largement voir des gens qui se mouillent, quitte à prendre des remarques...

    On voit plus souvent l'inverse. (Zerda ?) :-°
    • Partager sur Facebook
    • Partager sur Twitter
    Zeste de Savoir, le site qui en a dans le citron !
      17 juillet 2011 à 9:53:15

      @ fred1599:
      Tu me juge quelque peu sévèrement. Je rappelle que je suis encore au stade "débutant" en Python, donc je n'ai forcément pas encore de bonnes pratiques "pythoniques".

      L'ennui est que lorsque l'on débute dans un langage (particulièrement si on sait déjà coder par ailleurs), on essaie dans la mesure du possible de coller au style/philosophie de ce langage, pour produire du code idiomatique. On cherche alors à s'inspirer d'anciennes habitudes, de codes existants lus sur internet ou la doc, etc. Le mix entre anciennes pratiques (inadaptées) / mauvais exemples suivis / connaissance incomplète du nouveau langage / etc. peut conduire à des aberrations, comme par exemple une démarche algorithmique lourde, du code repoussant, etc.

      C'est un fait : on voit souvent du code illisible chez les débutants qui pensent être passé au niveau "supérieur" (et ce, dans maints langages). Peut-être est ce dû à un mauvais exemple ? Peut-être aussi cherchent-ils à connaitre les limites du langage ? ou autre (que sais-je) ?

      Sinon, il y a plusieurs manière d'évaluer du beau code, et cela dépends beaucoup de son emploi. Un code destiné à servir et être maintenu doit être plus simple, plus commenté, même au prix d'une plus grande longueur. Un code de TP n'a pas les mêmes contraintes, il sert surtout à apprendre pour soi, et on peut alors se permettre plus de liberté, à mon sens.

      Citation : fred1599

      chercher zen of python sur google ou en faisant
      Mais c'est des recommandations qui peuvent être faites dans tous les autres langages.


      Merci pour l'info. :)
      <chicaneur> "There should be one-- and preferably only one --obvious way to do it.". C'est très rare qu'il n'y ait qu'un moyen de le faire. Et je ne vois pas en quoi c'est préférable. </chicaneur>

      Citation : fred1599

      Si tu veux des performances, faut retourner au C ou C++ car il n'y a aucune chance de pouvoir faire mieux en python, même pour un codeur C++ pitoyable.


      Non, tu ne m'a pas compris : je parle des perfs de mon code Python, qui sont assez pitoyables par rapport à ce qu'on pourrait faire en s'appliquant. Car oui, je me suis appliqué sur des points de syntaxe et de concision, et ça a complétement tué le coté algo, ce que j'ai déploré.
      <hs> Et puis détrompe toi, un codeur même relativement bon en C/C++ peut faire infiniment moins bien qu'un très bon code Python, tu n'as qu'a faire un tour sur les forums de project Euler pour t'en assurer. </hs>
      • Partager sur Facebook
      • Partager sur Twitter
      Anonyme
        17 juillet 2011 à 10:26:45

        Citation

        Tu me juge quelque peu sévèrement. Je rappelle que je suis encore au stade "débutant" en Python, donc je n'ai forcément pas encore de bonnes pratiques "pythoniques".



        Attention ce n'est pas un jugement, et si je devais juger je dirais que tu as les bonnes pratiques, mais tu ne les appliquent pas ;) Mais je ne me permettrais pas un jugement juste une constatation.

        Citation

        L'ennui est que lorsque l'on débute dans un langage (particulièrement si on sait déjà coder par ailleurs), on essaie dans la mesure du possible de coller au style/philosophie de ce langage, pour produire du code idiomatique. On cherche alors à s'inspirer d'anciennes habitudes, de codes existants lus sur internet ou la doc, etc. Le mix entre anciennes pratiques (inadaptées) / mauvais exemples suivis / connaissance incomplète du nouveau langage / etc. peut conduire à des aberrations, comme par exemple une démarche algorithmique lourde, du code repoussant, etc.



        Encore une fois, tu mets cela sur le compte du débutant, tu maîtrises mieux que moi python, tu as des connaissances nettement plus avancées en C/C++ et ton expérience dans tous ces langages font que tes codes au contraire doivent être clairs et compréhensifs. Ce n'est pas une question de pouvoir mais de vouloir.

        Ne me dis pas qu'on peut faire compliqué et pas simple?

        Citation

        Sinon, il y a plusieurs manière d'évaluer du beau code, et cela dépends beaucoup de son emploi. Un code destiné à servir et être maintenu doit être plus simple, plus commenté, même au prix d'une plus grande longueur. Un code de TP n'a pas les mêmes contraintes, il sert surtout à apprendre pour soi, et on peut alors se permettre plus de liberté, à mon sens.



        On est d'accord c'est un code personnel qui reste pédagogique que pour celui qui le conçoit et non pour ceux qui le lisent.

        Citation

        Merci pour l'info. :)
        <chicaneur> "There should be one-- and preferably only one --obvious way to do it.". C'est très rare qu'il n'y ait qu'un moyen de le faire. Et je ne vois pas en quoi c'est préférable. </chicaneur>



        C'est en effet un des abus du concepteur python, je suis d'accord, cependant d'autres conseils (pas tous) sont eux applicables dans la conception d'un code.

        Citation

        Non, tu ne m'a pas compris : je parle des perfs de mon code Python, qui sont assez pitoyables par rapport à ce qu'on pourrait faire en s'appliquant. Car oui, je me suis appliqué sur des points de syntaxe et de concision, et ça a complétement tué le coté algo, ce que j'ai déploré.
        <hs>



        En fait si j'avais bien compris :)

        Beaucoup de fois on a pu démontrer que malgré un très bon algorithme on arrive pas à la hauteur de l'utilisation des fonctions standards python.

        Citation

        Et puis détrompe toi, un codeur même relativement bon en C/C++ peut faire infiniment moins bien qu'un très bon code Python, tu n'as qu'a faire un tour sur les forums de project Euler pour t'en assurer.



        En étant pitoyable en C/C++ j'ai toujours fait mieux niveau perf que mes fonctions python, maintenant encore une fois tu es plus expérimenté que moi et je veux bien te croire.

        Citation : josmiley

        perso je trouve le code de Candide trop long, alors que celui de yoch est certe maladroit mais plus dans ma vision des choses.
        comme quoi, les goûts et les codeurs ...



        Plus long, oui! Mais en quoi son code est moins lisible? Il utilise vraiment la simplicité dans son code, peut-être aussi pour garder je pense un caractère pédagogique.

        • Partager sur Facebook
        • Partager sur Twitter
          17 juillet 2011 à 11:58:14

          Citation : fred1599


          Plus long, oui! Mais en quoi son code est moins lisible? Il utilise vraiment la simplicité dans son code, peut-être aussi pour garder je pense un caractère pédagogique.



          j'ai jamais dit qu'il n'était pas lisible ... je dis juste trop long en fonction de ce qu'il est sensé faire, à mon goût.
          Mais c'est sûr qu'en lisant juste le nom des fonctions le code se comprend aisément.
          Personnellement je préfère les codes courts, même s'il faut les décortiquer un peu, et chercher l'astuce utilisée pour grapiller des lignes.(ben oui j'aime bien le byte-crunching :p )

          quelques modifs de la class Main qui permettent de ne pas surcharger les opérateurs de comparaison:

          Image utilisateur
          #!/usr/bin/env python
          # -*- coding: utf-8 -*-
          from pygame import *
          font.init()
          
          scr = display.set_mode((600,123))
          font = font.Font(None,16)
          
          class Main(list,object):
              
              tile_set = image.load('cards.png')
              force = {(1,1,1,1,1):'0_CARTE',
                       (2,1,1,1):'1_PAIRE',
                       (2,2,1):'2_DEUX PAIRES',
                       (3,1,1):'3_BRELAN',
                       (3,2):'6_FULL',
                       (4,1):'7_CARRE'}
                       
              def __init__(self,cartes):
                  valeur,couleur = zip(*cartes)
                  self.extend(sorted(cartes,key=lambda (v,_):(valeur.count(v),v,_),reverse=1)) # tri les cartes
                  nom = Main.force[tuple(sorted([valeur.count(v)for v in set(valeur)],reverse=1))] # donne le nom de la main
                  if nom == '0_CARTE': # gestion des cas particuliers
                      estCouleur = len(set(couleur)) == 1 # teste si c'est une couleur
                      estHauteur5 = sorted(valeur) == [2,3,4,5,14] # teste si c'est une suite à hauteur 5
                      estSuite = (max(valeur)-min(valeur) == 4) or estHauteur5 # teste si c'est une suite
                      if estCouleur: nom = '8_QUINTE FLUSH' if estSuite else '5_COULEUR'
                      elif estSuite: nom = '4_SUITE'
                      if estHauteur5: self.append(self.pop(0)) # retification du tri si l'AS vaut 1
                  self.insert(0,nom)
          
              @property
              def name(self):
                  return self[0][2:]
              
              def __repr__(self):
                  # retourne le nom de la Main
                  return self.name
              
              def get_images(self):
                  # retourne une liste des images des cartes de la main
                  return [Main.tile_set.subsurface(((v-1)*79,c*123,79,123))for v,c in self[1:]]
          
          # *************************************************************************************
          
          test=[
              [(8,0),(7,0),(6,0),(5,0),(4,0)],
              [(14,0),(13,0),(12,0),(11,0),(10,0)],
              [(4,2),(3,2),(14,2),(5,2),(2,2)],
              [(13,2),(13,0),(13,3),(13,1),(3,2)], 
              [(14,2),(14,0),(14,3),(14,1),(3,1)],
              [(13,2),(13,0),(13,3),(3,3),(3,2)],
              [(13,1),(10,1),(8,1),(4,1),(3,1)],
              [(8,3),(7,2),(6,2),(5,1),(4,1)],
              [(13,2),(13,1),(13,3),(12,2),(5,3)],
              [(13,2),(13,3),(12,3),(8,3),(8,1)],
              [(8,3),(8,1),(13,2),(12,2),(5,3)],
              [(10,3),(10,1),(13,2),(12,2),(5,3)],
              [(13,2),(12,2),(8,0),(6,1),(5,3)]
              ]
          
          test = [Main(m) for m in test]
          for m in sorted(test):
              pos = 0,0
              for img in m.get_images(): pos = scr.blit(img,pos).topright
              scr.blit(font.render(m.name,1,(255,255,255)),pos)
              display.flip()
          
              while event.wait().type != MOUSEBUTTONUP: pass
              scr.fill(0)
          
          • Partager sur Facebook
          • Partager sur Twitter
            17 juillet 2011 à 13:04:41

            Citation : fred1599

            Encore une fois, tu mets cela sur le compte du débutant, tu maîtrises mieux que moi python, tu as des connaissances nettement plus avancées en C/C++ et ton expérience dans tous ces langages font que tes codes au contraire doivent être clairs et compréhensifs. Ce n'est pas une question de pouvoir mais de vouloir.

            Ne me dis pas qu'on peut faire compliqué et pas simple?


            Sincèrement, je pense avoir beaucoup moins d’expérience que toi en Python. J'essaie de compenser en me servant de mon expérience avec d'autres langages (pas nécessairement une "bonne idée", je dirais plutôt un cheminement quasi-automatique), et en me servant des diverses documentations/exemples à ma disposition.

            Effectivement, je pourrais très facilement écrire de façon plus simple/claire, mais j'ai une crainte (assez forte): c'est de passer en quelque sorte à coté du langage. Donc j'essaie avec mon maigre bagage d'utiliser toute l'expressivité que le langage met à ma disposition, et je me retrouve avec un code plutôt infect :-° (ou non :) ).

            Fondamentalement, je me range aujourd’hui plutôt du coté de la clarté que du coté de la concision poussée à l’extrême dans les langages que je maitrise (en C par exemple, on se retrouve vite à faire des suppositions sur le comportement du compilateur, etc.). Mais cela reflète tout un cheminement, certaines expériences (dev à plusieurs, etc.), que je ne peux que difficilement transcrire dans un contexte tout nouveau comme Python. Car oui, il y a (et y aura) toujours un sacrifice à faire quelque part: sacrifier la concision à la performance, sacrifier l'expressivité à la lisibilité, sacrifier la simplicité à la ré-usabilité, etc., et cela implique des choix qui ne seront pas nécessairement les mêmes selon le langage utilisé et l'objectif visé.
            • Partager sur Facebook
            • Partager sur Twitter
            Anonyme
              17 juillet 2011 à 14:22:59

              j'ai jamais dit qu'il n'était pas lisible ...
              


              Je me suis mal exprimé, je voulais clairement dire, long mais lisible!

              Citation

              Sincèrement, je pense avoir beaucoup moins d’expérience que toi en Python. J'essaie de compenser en me servant de mon expérience avec d'autres langages (pas nécessairement une "bonne idée", je dirais plutôt un cheminement quasi-automatique), et en me servant des diverses documentations/exemples à ma disposition.



              Peut-être (ou non :) ) écrire du on-liner aussi facilement est pour moi preuve d'expérience dans le langage. Je n'ai rien contre ton code, seulement si on reste dans un caractère pédagogique (TP ou exercice), il est préférable que ton code soit lisible par tous. Ce que je regrette c'est surtout un manque de commentaires sur des points assez pointus comme tes on-liners par exemple.

              En C (voir C++, mais beaucoup plus rare) tu vas souvent réinventer la roue, alors que python va te proposer une pléthore de fonctions pour contourner ou éviter le plus possible un nombre incalculable de lignes de code.

              En outre programmeur n'est pas mon métier je n'ai juste qu'une vue externe de l'iceberg, une vue dont je me suis fais des bases (bonnes ou mauvaises) seul et peut-être maladroitement.

              yoch, je lis souvent tes codes C qui sont pour moi très souvent formateur, et j'étais surpris étant un vrai débutant en C et C++ de comprendre tes codes et d'avoir des difficultés dans la lecture d'un code python fait par le même codeur, car niveau algorithme en ce qui me concerne tu es un modèle :)

              • Partager sur Facebook
              • Partager sur Twitter
                17 juillet 2011 à 14:48:28

                Citation : fred1599

                En outre programmeur n'est pas mon métier je n'ai juste qu'une vue externe de l'iceberg, une vue dont je me suis fais des bases (bonnes ou mauvaises) seul et peut-être maladroitement.


                Ce n'est pas mon métier non plus :) . Une simple passion...

                Citation : fred1599

                yoch, je lis souvent tes codes C qui sont pour moi très souvent formateur, et j'étais surpris étant un vrai débutant en C et C++ de comprendre tes codes et d'avoir des difficultés dans la lecture d'un code python fait par le même codeur, car niveau algorithme en ce qui me concerne tu es un modèle :)


                Merci pour le compliment. Cela prouve justement que l’expérience dans un langage donné compte pour beaucoup, s'il fallait le prouver. ;)
                ________

                Bon, pour revenir au sujet initial (avant que candide ne nous tire les oreilles ^^ ), voici mon dernier code remanié, avec un poil plus de commentaires, et un petit hack de rien du tout [ligne 32] qui me permet d'améliorer mes perfs. Pour une plus grande clarté, j'ai remplacé value par fig (pas trouvé l'équivalent anglais) :

                from collections import namedtuple
                
                Card = namedtuple('Card', 'color fig')
                
                CardsValues = { f:v for f,v in zip('23456789TJQKA',range(2,15)) }
                HandName = {1:'Card', 2:'Pair', 3:'TwoPairs', 4:'Three', 5:'Straight', 6:'Flush', 7:'Full', 8:'Four', 9:'StraightFlush', 10:'RoyalFlush'}
                Levels = {(1,1,1,1,1):1, (2,1,1,1):2, (2,2,1):3, (3,1,1):4, (3,2):7, (4,1):8}
                
                class PokerHand:
                
                    def __init__(self, cards):
                        figures,colors = zip(*[(c.fig,c.color) for c in cards])
                        # teste si c'est une couleur
                        flush = len(set(colors)) == 1
                        # teste si c'est une suite
                        values = sorted([CardsValues[fig] for fig in set(figures)])
                        straight = (len(values)==5) and (values[0]+4 == values[4])
                        # calcule le nombre d'occurences de chaque figure
                        nvals=dict().fromkeys(figures, 0)
                        for f in figures:
                            nvals[f]+=1
                        # determine la force de la main
                        if straight and flush:
                            self.level = (10 if values[4]==CardsValues['A'] else 9) 
                        elif flush:
                            self.level = 6
                        elif straight:
                            self.level = 5
                        else:
                            self.level = Levels[tuple(sorted(nvals.values(), reverse=True))]
                        # trie les cartes pour une comparaison eventuelle
                        self.cards = sorted(cards, key=lambda c: CardsValues[c.fig]+(15*nvals[c.fig]), reverse=True)
                
                    def name(self):
                        return HandName[self.level]
                
                    def __lt__(self, other):
                        if self.level != other.level:
                            return self.level < other.level
                        else:
                            return [CardsValues[c.fig] for c in self.cards] < [CardsValues[c.fig] for c in other.cards]
                
                    def __gt__(self, other):
                        if self.level != other.level:
                            return self.level > other.level
                        else:
                            return [CardsValues[c.fig] for c in self.cards] > [CardsValues[c.fig] for c in other.cards]
                
                    def __eq__(self, other):
                        if self.level != other.level:
                            return False
                        else:
                            return [CardsValues[c.fig] for c in self.cards] == [CardsValues[c.fig] for c in other.cards]
                
                    def __repr__(self):
                        return ' '.join([c.color + c.fig for c in self.cards])
                


                PS: Question bête, pourquoi certains ici disent 'on-liner' ? Il me semble que l'on dit 'one-liner', non ? Quelque chose m'a échappé ?
                • Partager sur Facebook
                • Partager sur Twitter
                Anonyme
                  17 juillet 2011 à 15:31:11

                  Citation

                  Question bête, pourquoi certains ici disent 'on-liner' ? Il me semble que l'on dit 'one-liner', non ? Quelque chose m'a échappé ?



                  C'est bien one je te rassure ;)

                  Citation

                  voici mon dernier code remanié, avec un poil plus de commentaires, et un petit hack de rien du tout [ligne 32] qui me permet d'améliorer mes perfs. Pour une plus grande clarté, j'ai remplacé value par fig (pas trouvé l'équivalent anglais) :



                  C'est déjà nettement mieux car avec les commentaires on comprend tout de suite où tu veux en venir.

                  Je vais analyser ton code

                  Voilà une amélioration avec la fonction count() qui normalement devrait être plus rapide

                  nvals=dict().fromkeys(figures, 0)
                          for f in figures:
                              nvals[f]+=1
                  


                  On pourrait faire

                  nvals = {}
                  for i in set(figures):
                      nvals[i] = figures.count(i)
                  


                  non?

                  Tu pourrais donner un exemple d'initialisation de ta classe, qui je pense doit être en rapport avec ton tuple nommé?
                  • Partager sur Facebook
                  • Partager sur Twitter
                    17 juillet 2011 à 17:38:20

                    Citation : fred1599

                    Voilà une amélioration avec la fonction count() qui normalement devrait être plus rapide

                    nvals=dict().fromkeys(figures, 0)
                            for f in figures:
                                nvals[f]+=1
                    



                    On pourrait faire

                    nvals = {}
                    for i in set(figures):
                        nvals[i] = figures.count(i)
                    



                    non?


                    Non, ce n'est pas plus rapide, à cause du coût de count(), cf. ce post ci-dessus (en plus du temps pour construire le set, enfin bon, on pourrait garder le set utilisé un peu plus haut). En revanche, ça pourrait permettre d'économiser des lignes :p , comme ceci :
                    nvals = { k:figures.count(k) for k in set(figures) }
                    


                    Citation : fred1599

                    Tu pourrais donner un exemple d'initialisation de ta classe, qui je pense doit être en rapport avec ton tuple nommé?



                    On peut soit initialiser un tuple nommé en nommant expressément les champs du tuple (l'ordre ne compte alors pas), soit implicitement en passant les paramètres au constructeur dans le bon ordre. Cf. ici et (construction implicite).

                    L'emploi d'un tuple nommé est ici purement cosmétique, afin de pouvoir écrire c.fig et c.color, au lieu de c[0] et c[1]...
                    • Partager sur Facebook
                    • Partager sur Twitter
                    Anonyme
                      17 juillet 2011 à 20:57:40

                      Citation

                      Non, ce n'est pas plus rapide, à cause du coût de count(), cf. ce post ci-dessus (en plus du temps pour construire le set, enfin bon, on pourrait garder le set utilisé un peu plus haut). En revanche, ça pourrait permettre d'économiser des lignes :p , comme ceci :



                      count est plus rapide qu'un compteur, ça doit être la fonction set qui doit être plus lente, donc fromkeys en effet est adapté.

                      nvals = dict.fromkeys(figure, 0)
                      for k in nvals:
                          nvals[k] = figure.count(k)
                      


                      Sinon j'ai mieux encore, je pense que tu vas apprécier :)

                      from collections import Counter
                      nvals = Counter(figure)
                      
                      • Partager sur Facebook
                      • Partager sur Twitter
                        17 juillet 2011 à 21:23:01

                        j'ai réduit la taille de l' __init__, bien sûr c'est illisible ...

                        #!/usr/bin/env python
                        # -*- coding: utf-8 -*-
                        
                        class Main(list,object):
                            
                            valeur = ('','AS','2','3','4','5','6','7','8','9','10','VALET','DAME','ROI','AS')
                            couleur = ('TREFLE','CARREAU','COEUR','PIQUE')
                            force = {(1,1,1,1,1):'0_CARTE',(1,1,1,2):'1_PAIRE',(1,2,2):'2_DEUX PAIRES',
                                     (1,1,3):'3_BRELAN',(2,3):'6_FULL',(1,4):'7_CARRE'}
                                     
                            def __init__(self,cartes):
                                valeur,couleur = zip(*sorted(cartes))
                                if valeur == (2,3,4,5,14): valeur = (1,2,3,4,5)
                                estSuite = (valeur[4]-valeur[0] == 4)
                                if len(set(couleur)) == 1: self.append('8_QUINTE FLUSH' if estSuite else '5_COULEUR')
                                else: self.append('4_SUITE' if estSuite else Main.force[tuple(sorted([valeur.count(v)for v in set(valeur)]))])
                                self.hand = sorted(cartes,key=lambda (v,c):(valeur.count(v),v,c),reverse=1)
                                self.extend(zip(*self.hand)[0])
                                self.name = self[0][2:]
                                self.alpha_hand = [(Main.valeur[v],Main.couleur[c]) for v,c in self.hand]
                        
                        # *************************************************************************************
                        
                        test=[
                            [(8,0),(7,0),(6,0),(5,0),(4,0)],
                            [(14,0),(13,0),(12,0),(11,0),(10,0)],
                            [(4,2),(3,2),(14,2),(5,2),(2,2)],
                            [(13,2),(13,0),(13,3),(13,1),(3,2)], 
                            [(14,2),(14,0),(14,3),(14,1),(3,1)],
                            [(13,2),(13,0),(13,3),(3,3),(3,2)],
                            [(13,1),(10,1),(8,1),(4,1),(3,1)],
                            [(8,3),(7,2),(6,2),(5,1),(4,1)],
                            [(13,2),(13,1),(13,3),(12,2),(5,3)],
                            [(13,2),(13,3),(12,3),(8,3),(8,1)],
                            [(8,3),(8,1),(13,2),(12,2),(5,3)],
                            [(10,3),(10,1),(13,2),(12,2),(5,3)],
                            [(13,2),(12,2),(8,0),(6,1),(5,3)]
                            ]
                        
                        test = [Main(m) for m in test]
                        for m in sorted(test):
                            print m.alpha_hand,' : '+m.name
                        

                        [('ROI', 'COEUR'), ('DAME', 'COEUR'), ('8', 'TREFLE'), ('6', 'CARREAU'), ('5', 'PIQUE')]  : CARTE
                        [('8', 'PIQUE'), ('8', 'CARREAU'), ('ROI', 'COEUR'), ('DAME', 'COEUR'), ('5', 'PIQUE')]  : PAIRE
                        [('10', 'PIQUE'), ('10', 'CARREAU'), ('ROI', 'COEUR'), ('DAME', 'COEUR'), ('5', 'PIQUE')]  : PAIRE
                        [('ROI', 'PIQUE'), ('ROI', 'COEUR'), ('8', 'PIQUE'), ('8', 'CARREAU'), ('DAME', 'PIQUE')]  : DEUX PAIRES
                        [('ROI', 'PIQUE'), ('ROI', 'COEUR'), ('ROI', 'CARREAU'), ('DAME', 'COEUR'), ('5', 'PIQUE')]  : BRELAN
                        [('8', 'PIQUE'), ('7', 'COEUR'), ('6', 'COEUR'), ('5', 'CARREAU'), ('4', 'CARREAU')]  : SUITE
                        [('ROI', 'CARREAU'), ('10', 'CARREAU'), ('8', 'CARREAU'), ('4', 'CARREAU'), ('3', 'CARREAU')]  : COULEUR
                        [('ROI', 'PIQUE'), ('ROI', 'COEUR'), ('ROI', 'TREFLE'), ('3', 'PIQUE'), ('3', 'COEUR')]  : FULL
                        [('ROI', 'PIQUE'), ('ROI', 'COEUR'), ('ROI', 'CARREAU'), ('ROI', 'TREFLE'), ('3', 'COEUR')]  : CARRE
                        [('AS', 'PIQUE'), ('AS', 'COEUR'), ('AS', 'CARREAU'), ('AS', 'TREFLE'), ('3', 'CARREAU')]  : CARRE
                        [('5', 'COEUR'), ('4', 'COEUR'), ('3', 'COEUR'), ('2', 'COEUR'), ('AS', 'COEUR')]  : QUINTE FLUSH
                        [('8', 'TREFLE'), ('7', 'TREFLE'), ('6', 'TREFLE'), ('5', 'TREFLE'), ('4', 'TREFLE')]  : QUINTE FLUSH
                        [('AS', 'TREFLE'), ('ROI', 'TREFLE'), ('DAME', 'TREFLE'), ('VALET', 'TREFLE'), ('10', 'TREFLE')]  : QUINTE FLUSH

                        • Partager sur Facebook
                        • Partager sur Twitter
                          17 juillet 2011 à 21:46:01

                          Citation : fred1599

                          Sinon j'ai mieux encore, je pense que tu vas apprécier :)

                          from collections import Counter
                          nvals = Counter(figure)
                          


                          Pile ce que je cherchais, merci ! :D

                          EDIT:
                          Après mesure des perfs, il s’avère que cette solution est terriblement peu performante dans le cas présent, dommage...

                          Je suppose toutefois qu'elle sera nettement plus efficace qu'une solution à base de count() sur de gros iterables.

                          L’implémentation proposée dans les sources de python 3.2 ressemble à ceci (effectivement performant, mais pas plus que ma première methode, légèrement moins on dirait) :
                          nvals = {}
                          for f in figures:
                              nvals[f] = nvals.get(f,0)+1
                          


                          En revanche, une compréhension ne fonctionne pas correctement ici (renvoie un seul élément de chaque figure), sans doute parce que get() ne renvoie pas la valeur attendue pendant la construction du dictionnaire :
                          nvals = { f:nvals.get(f,0)+1 for f in figures }
                          


                          EDIT2:
                          Je viens de relire attentivement le post de fred1599 :

                          Citation

                          count est plus rapide qu'un compteur


                          Je ne crois pas. D’où tiens tu cela ?

                          Citation

                          ça doit être la fonction set qui doit être plus lente, donc fromkeys en effet est adapté.


                          Ça va moins vite que sans le count() chez moi.

                          EDIT3:
                          Encore une methode équivalente à Counter(), inspirée de la doc :

                          from collections import defaultdict
                          
                          nvals = defaultdict(int)
                          for f in figures:
                              nvals[f] += 1
                          


                          Si f ne se trouve pas dans le dictionnaire, le constructeur par défaut int() est appelé, soit 0.
                          • Partager sur Facebook
                          • Partager sur Twitter
                          Anonyme
                            19 juillet 2011 à 18:17:55

                            Citation

                            Je ne crois pas. D’où tiens tu cela ?



                            Cette méthode fait partie de la lib standard et donc elle est optimisée.

                            Je ne comprend pas pourquoi c'est plus lent, il y a un blème là :o

                            Contrairement à une simple incrémentation.

                            J'arrive pas à trouver la source de la méthode.

                            Citation

                            Encore une methode équivalente à Counter(), inspirée de la doc :



                            Oui je l'avais vu aussi ;)

                            • Partager sur Facebook
                            • Partager sur Twitter
                              19 juillet 2011 à 18:27:36

                              Citation : fred1599

                              Citation

                              Je ne crois pas. D’où tiens tu cela ?



                              Cette méthode fait partie de la lib standard et donc elle est optimisée.

                              Je ne comprend pas pourquoi c'est plus lent, il y a un blème là :o


                              Optimisée, c'est clair, mais cette fonction est tout de même en O(N), c'est à dire que l'on doit impérativement parcourir tout l'iterable pour compter les objets. Donc si tu appelle count() sur chaque objet, la complexité devient quadratique O(N^2), comme l'a justement fait remarquer candide.

                              Ici, ça n'a pas une grande influence, parce qu'il n'y a que 5 cartes, mais si tu en avais 10000, tu aurais eu des écarts astronomiques...

                              EDIT : et puis count() n'est pas une methode, c'est une fonction.
                              • Partager sur Facebook
                              • Partager sur Twitter
                              Anonyme
                                19 juillet 2011 à 18:34:58

                                Citation

                                EDIT : et puis count() n'est pas une methode, c'est une fonction.



                                count() est appliqué sur un objet, c'est donc une méthode, si je ne me trompe pas.

                                Pour le reste je veux bien vous croire je n'y comprend rien aux complexités, donc je dis amen
                                • Partager sur Facebook
                                • Partager sur Twitter
                                  19 juillet 2011 à 18:38:49

                                  Citation : fred1599

                                  count() est appliqué sur un objet, c'est donc une méthode, si je ne me trompe pas.


                                  Non.

                                  Une methode, c'est une fonction appartenant à un objet : objet.methode()

                                  Une fonction peut très bien être appelée sur un objet : fonction(objet)
                                  • Partager sur Facebook
                                  • Partager sur Twitter
                                  Anonyme
                                    19 juillet 2011 à 18:43:33

                                    liste = [1, 1, 5, 9, 3, 1]
                                    print(liste.count(1))
                                    


                                    Edit : Et je rajoute une référence

                                    Citation

                                    The list data type has some more methods. Here are all of the methods of list objects:



                                    La méthode count() est dans la liste

                                    ;)
                                    • Partager sur Facebook
                                    • Partager sur Twitter
                                      19 juillet 2011 à 18:57:57

                                      dans cet exercice on s'en tape d'utiliser count() ou une autre méthode pour gratter des millisecondes? non?
                                      • Partager sur Facebook
                                      • Partager sur Twitter
                                        19 juillet 2011 à 19:40:33

                                        Citation : fred1599

                                        liste = [1, 1, 5, 9, 3, 1]
                                        print(liste.count(1))
                                        

                                        Désolé, je pensais que count() faisait partie des fonctions built-in (comme min() et max()). :honte:

                                        Citation : josmiley

                                        dans cet exercice on s'en tape d'utiliser count() ou une autre méthode pour gratter des millisecondes? non?


                                        Oui, on s'en fout pas mal. La discussion avait un caractère plus global (car l'exo est fait pour s'entrainer, mais aussi pour réfléchir, comparer les diverses approches, etc.).
                                        • Partager sur Facebook
                                        • Partager sur Twitter
                                        Anonyme
                                          29 mai 2013 à 18:13:07



                                          Voilà je reviens un peu tard sur le topic mais je dois me former un peu sur le python pour un boulot ( je suis plus JAVA :p ) et j'ai réalisé quelques un des tp pour 

                                          prendre la main. Je n'ai pas tout résolu le problème du poker mais j'ai crée deux classes Cartes et JeuCartes qui permettent respectivement de créer un type carte

                                          et de générer un jeu de 52 cartes et deux mains aléatoires.

                                          Voici la classe Cartes :

                                          '''
                                          Created on 29 mai 2013
                                          
                                          @author: jaillet-jb
                                          '''
                                          
                                          class Cartes(object):
                                              '''
                                              Une cartes a une couleur "string"
                                              Une cartes a une valeur "string"
                                              '''
                                          
                                          
                                              def __init__(self, couleur, valeur):
                                                  if couleur != "co" and couleur != "p" and couleur != "ca" and couleur !="t" :
                                                      print(couleur)
                                                      print("Couleur incorrecte")
                                                  else :
                                                      self.couleur = couleur
                                                  if valeur not in "1023456789rvd" :
                                                      print("Valeur incorrecte.")
                                                  else :    
                                                      if valeur in "1023456789" :
                                                          a = int(valeur)
                                                          if a > 10 or a == 0:
                                                              print("Valeur incorrecte")
                                                          else :
                                                              self.valeur = valeur
                                                      else :
                                                          self.valeur = valeur
                                                      
                                              def _get_couleur(self):
                                                  return self.couleur
                                              
                                              def _get_valeur(self):
                                                  return self.valeur
                                              
                                              def _set_couleur(self,couleur):
                                                  self.couleur = couleur
                                                  
                                              def _set_valeur(self,valeur):
                                                  self.valeur = valeur
                                                  
                                              def ordreCartes(self,carte):
                                                  '''
                                                  Renvoie 0 si les cartes sont egales
                                                  Renvoie 1 si la premiere carte est plus grande
                                                  Renvoie 2 si la deuxieme carte est plus grande
                                                  '''
                                                  if self.valeur == carte.valeur :
                                                      print("Les deux cartes ont la meme valeur !")
                                                      return 0
                                                  elif self.valeur in "rvd" and carte.valeur not in "rvd" :
                                                      self.afficherCarte()
                                                      print("l'emporte sur ")
                                                      carte.afficherCarte()
                                                      return 1
                                                  elif self.valeur not in "rvd" and carte.valeur in "rvd" :
                                                      self.afficherCarte()
                                                      print("est battue par le")
                                                      carte.afficherCarte()
                                                      return 2
                                                  elif self.valeur not in "rvd" and carte.valeur not in "rvd" :
                                                      a = int(self.valeur)
                                                      b = int(carte.valeur)
                                                      if a < b :
                                                          self.afficherCarte()
                                                          print("est battue par le")
                                                          carte.afficherCarte()
                                                          return 2
                                                      else :
                                                          self.afficherCarte()
                                                          print("l'emporte sur ")
                                                          carte.afficherCarte()
                                                          return 1
                                                  else :
                                                      if self.valeur == "v" :
                                                          self.afficherCarte()
                                                          print("est battue par le")
                                                          carte.afficherCarte()
                                                          return 2
                                                      elif carte.valeur == "v" :
                                                          self.afficherCarte()
                                                          print("l'emporte sur ")
                                                          carte.afficherCarte()
                                                          return 1
                                                      elif self.valeur == "r" :
                                                          self.afficherCarte()
                                                          print("l'emporte sur ")
                                                          carte.afficherCarte()
                                                          return 1
                                                      else :
                                                          self.afficherCarte()
                                                          print("est battue par le")
                                                          carte.afficherCarte()
                                                          return 2
                                                      
                                                      
                                              def afficherCarte(self) :
                                                  a = " "
                                                  c = " "
                                                  if self.couleur == "ca" :
                                                      a = "Carreau"
                                                  elif self.couleur == "co" :
                                                      a = "Coeur"
                                                  elif self.couleur == "p" :
                                                      a = "Pique"
                                                  else :
                                                      a = "Trefle"
                                                  
                                                  if self.valeur == "v" :
                                                      c = "Valet"
                                                  elif self.valeur == "d" :
                                                      c = "Dame"
                                                  elif self.valeur == "r" :
                                                      c = "Roi"
                                                  elif self.valeur == "1" :
                                                      c = "As"
                                                  else :
                                                      c = self.valeur
                                                  
                                                  print(" "+ c +" de " + a +". ")
                                           


                                          La classe JeuCartes :

                                          '''
                                          Created on 29 mai 2013
                                          
                                          @author: jaillet-jb
                                          '''
                                          from classe.Cartes import Cartes
                                          import random
                                          
                                          class JeuCartes(object):
                                              
                                              def __init__(self):
                                                  self.jeu = {}
                                                  self.mainun = {}
                                                  self.maindeux = {}
                                                  k = 0
                                                  couleur = ["ca","co","t","p"]
                                                  valeur = ["1","2","3","4","5","6","7","8","9","10","v","d","r"]
                                                  for i in valeur :
                                                      for j in couleur :
                                                          a = str(k)
                                                          cartes = Cartes(j,i)
                                                          self.jeu[a] = cartes
                                                          k += 1
                                                  
                                              def afficherJeu(self):
                                                  i = 0
                                                  while i < len(self.jeu) :
                                                      i = str(i)
                                                      self.jeu[i].afficherCarte()
                                                      i = int(i)
                                                      i += 1
                                              def afficherMain(self):
                                                  i = 0
                                                  print("Premiere main : ")
                                                  while i < len(self.mainun) :
                                                      i = str(i)
                                                      self.mainun[i].afficherCarte()
                                                      i = int(i)
                                                      i += 1
                                                  i = 0
                                                  print("Deuxieme main : ")
                                                  while i < len(self.mainun) :
                                                      i = str(i)
                                                      self.maindeux[i].afficherCarte()
                                                      i = int(i)
                                                      i += 1
                                                  
                                              def genererMain(self):
                                                  jeutemp = {}
                                                  jeutemp = self.jeu
                                                  i = 0
                                                  while i < 5 :
                                                      k = random.randrange(52)
                                                      k = str(k)
                                                      if k in jeutemp.keys() :
                                                          self.mainun[str(i)] = jeutemp[k]
                                                          del jeutemp[k]
                                                          i += 1
                                                  i = 0
                                                  while i < 5 : 
                                                      k = random.randrange(52)
                                                      k = str(k)
                                                      if k in jeutemp.keys() :
                                                          self.maindeux[str(i)] = jeutemp[k]
                                                          del jeutemp[k]
                                                          i += 1



                                          Et enfin un exemple d'appel :

                                          '''
                                          Created on 29 mai 2013
                                          
                                          @author: jaillet-jb
                                          '''
                                          from classe.Cartes import Cartes
                                          from classe.JeuCartes import JeuCartes
                                          
                                          j = JeuCartes()
                                          j.genererMain()
                                          j.afficherMain()

                                          Une fois le jeu de cartes créer, vous appelez le méthode genererMain() autant de fois que vous voulez pour générer des mains aléatoires ( sans problème de doublons

                                          evidemment :p )

                                          Exemple de compilation :

                                          Premiere main :
                                           10 de Pique.
                                           Valet de Carreau.
                                           3 de Coeur.
                                           9 de Coeur.
                                           2 de Coeur.
                                          Deuxieme main :
                                           4 de Trefle.
                                           Valet de Coeur.
                                           4 de Coeur.
                                           3 de Pique.
                                           4 de Carreau.

                                          Voilà, c'est plus pour donner un p'tit truc pour ensuite faire grandir la classe ( nombre de main générer, jeux de cartes différents ) ou pour tester vos code

                                          de poker sur des mains générées aléatoirement.

                                          Cordialement

                                          Besta

                                          -
                                          Edité par Anonyme 29 mai 2013 à 18:18:43

                                          • Partager sur Facebook
                                          • Partager sur Twitter

                                          Poker

                                          × 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