Partage
  • Partager sur Facebook
  • Partager sur Twitter

Elements communs dans une liste

    27 octobre 2016 à 11:58:59

    Bonjour à tous !

    Voici mon problème :

    - J'ai une liste L1 constituée d'un nombre connu d'élements

    - J'ai une liste L2 de même longueur que L1 ( longueur n )

    Je dois écrire une fonction python qui renvoie le nombre d'élements communs des deux listes ayant des indices différents. Cette fonction ne doit pas prendre ne compte les éléments communs si ils sont  à la même position.

    J'ai écris ceci :

    def communs(L1,L2):

        r=0

        i=0

        for j in range(n):

           for i in range(n):

              if ( L2[j]==L1[i] and i!= j ):

                 r+=1

        return r

    Mais j'ai un problème quand L1 possède des doublons :par exemple pour L1=[1,1] et L2=[0,1], ma fonction renvoie 1 au lieu de 0...

    Est-ce que quelqu'un a une solution à ce problème ? Merci d'avance !

    • Partager sur Facebook
    • Partager sur Twitter
      27 octobre 2016 à 12:16:13

      tu n'as droit qu'au boucles "for in" ?

      -
      Edité par josmiley 27 octobre 2016 à 12:18:28

      • Partager sur Facebook
      • Partager sur Twitter

      Python c'est bon, mangez-en. 

        27 octobre 2016 à 12:16:47

        Tu dois aussi gérer le cas où tu as plusieurs versions d'une valeur:

        lst1 = [1, 1, 1, 1, 1, 1, 2]
        lst2 = [0, 0, 0, 0, 0, 0, 1]
        
        #commun(lst1, lst2)  # -> 6 (alors que la bonne réponse est 1)


        Sinon tu itères sur n (lignes 4 et 5) alors que celle-ci n'a pas été définie, et l'initialisation de i (ligne 3) est inutile.

        PS: Utilise le bouton </> pour insérer du code sur le forum

        EDIT: Cet exercice n'est pas si simple que ça en fait. Pour ma part, j'ai réussi à trouver une solution assez simple en remplaçant les valeurs déjà inspectées par None (en supposant que None n'est pas un élément possible des séquences). Sans ça, je trouve que c'est un exo assez chaud pour un débutant o_O

        -
        Edité par Olygrim 27 octobre 2016 à 12:53:32

        • Partager sur Facebook
        • Partager sur Twitter
        Précepte: Le mieux est l'ennemi du bien
          27 octobre 2016 à 12:57:45

          @josmiley :


          Oui en effet je ne peux utiliser que for while else elif if et ce genre de chose..

          @Olygrim

          Ah merci,je n'avais pas pris en compte ce problème.. Désolé je suis nouveau sur ce forum, je cherchais justement comment faire du code plus proprement pour mes messages..

          n est une variable fixé dans l'exercice ( en dehors de ma fonction ). Ah oui, cette initialisation ne sert à rien en effet merci !

          [EDIT] :

          En réalité la finalité de cet exercice est de créer le jeu Mastermind, les valeurs de la liste représentent des couleurs, donc None ne peut pas en faire partie.. Je suis également bloqué sur une autre mais elle nécessite que celle-ci fonctionne, je fais donc étape par étape :)

          L'idée serait donc d'inspecter l'élément et après de le remplacer par None, ce qui l'empêcherait d'être à nouveau compté ?  ?



          -
          Edité par Pythonislife 27 octobre 2016 à 13:01:41

          • Partager sur Facebook
          • Partager sur Twitter
            27 octobre 2016 à 13:15:26

            J'ai voulu tester, je suis tombé face au même problème qu'@Olygrim; mais je l'ai pas résolu de la même manière:

            je commence avec un set vide (je l'ai appelé visited par manque de gout)

            on parcourt l1: si un element de l1 est dans l2 ET qu'il n'est pas dans visited, alors le compteur augmente et on ajoute cet element dans visited.. (PS: je fais exprès de ne pas balancer le code histoire que le PO s'amuse)

            Ca permet d'être aussi fonctionnel que la méthode d'@Olygrim, mais en moins dégueu qu'avec des None à tout va :p

            Elle a l'air de marcher pas trop mal.. ^^

            EDIT: je suis entrain de penser @Olygrim, ta méthode, tu modifies la liste que tu es entrain de parcourir du coup? Oo'

            -
            Edité par WexyR 27 octobre 2016 à 13:22:50

            • Partager sur Facebook
            • Partager sur Twitter
            Si je suis tête en l'air, c'est par habitude de viser le sommet
              27 octobre 2016 à 13:41:00

              Oui, je modifie la deuxième liste. J'ai pensé à faire une copie mais j'ai eu la flemme :p.

              Au départ moi aussi je suis parti sur un set mais j'ai trouvé la solution pas très claire. D'ailleurs dans ta solution, tu dis:

              WexyR a écrit:

              si un element de l1 est dans l2 ET qu'il n'est pas dans visited, alors le compteur augmente et on ajoute cet element dans visited..


              Mais quid du nombre d'occurrences. Par exemple, avec ces deux listes:

              lst1 = [1, 2, 1, 2, 2, 1, 0, 0, 1]
              lst2 = [1, 1, 1, 1, 1, 1, 1, 1, 1]


              Ma fonction renvoie 4 (qui est la bonne valeur :)). Que te renvoie la tienne?

              WexyR a écrit:

              mais en moins dégueu qu'avec des None à tout va :p


              Oh le méchant :pirate:
              • Partager sur Facebook
              • Partager sur Twitter
              Précepte: Le mieux est l'ennemi du bien
                27 octobre 2016 à 13:51:16

                Olygrim a écrit:

                lst1 = [1, 1, 1, 1, 1, 1, 2]
                lst2 = [0, 0, 0, 0, 0, 0, 1]
                
                #commun(lst1, lst2)  # -> 6 (alors que la bonne réponse est 1)


                je croyais qu'on devait pas prendre en compte si y'en avait plusieurs occurences du même élément dans l1 ^^ du coup la mienne renvoit 1

                Olygrim a écrit:

                WexyR a écrit:

                mais en moins dégueu qu'avec des None à tout va :p


                Oh le méchant :pirate:

                On va pas se mentir, c'est moche x)

                Bon alors je modifie et je reviens dans 10 min ^^

                EDIT: bon c'est long à expliquer alors je post le code (vous vous en plaindrez à ma flemmardise)

                def commun(l1, l2):
                    visited = set()
                    c = 0
                    for elt1 in l1:
                        for index, elt2 in enumerate(l2):
                            if elt1 == elt2 and index not in visited:
                                c += 1
                                visited.add(index)
                                break
                    return c

                pour faire court mon set ne contient non plus les elements à eviter mais l'index des element à éviter.

                étant donné que faire un in revient à parcourir toute la liste l2, je préfère le faire moi-même, comme ca je récupère l'index.

                Je pense pas perdre trop de temps ni de mémoire en faisant ça, vous en pensez quoi?


                -
                Edité par WexyR 27 octobre 2016 à 14:00:15

                • Partager sur Facebook
                • Partager sur Twitter
                Si je suis tête en l'air, c'est par habitude de viser le sommet
                  27 octobre 2016 à 13:58:52

                  En fait je pense que ma solution n'est pas bonne également si on se place dans le contexte d'un mastermind (qui est au final l'objectif de la fonction). Avec les deux listes précédentes, la fonction devrait renvoyer 0.

                  EDIT: Normalement j'ai réussi à corriger ma fonction (en gardant toujours cette fantastique solution avec les None ;))

                  -
                  Edité par Olygrim 27 octobre 2016 à 14:07:50

                  • Partager sur Facebook
                  • Partager sur Twitter
                  Précepte: Le mieux est l'ennemi du bien
                    27 octobre 2016 à 14:14:44

                    Pythonislife a écrit:

                     Cette fonction ne doit pas prendre ne compte les éléments communs si ils sont  à la même position.

                    oups

                    on a oublié un détail effectivement 

                    • Partager sur Facebook
                    • Partager sur Twitter
                    Si je suis tête en l'air, c'est par habitude de viser le sommet
                      27 octobre 2016 à 14:23:57

                      Ma fonction donne ceci:

                      def common_items(seq1, seq2):
                          common = 0
                          seq2 = list(seq2)
                          for index1, item1 in enumerate(seq1):
                              for index2, item2 in enumerate(seq2):
                                  if item1 == item2:
                                      if item1 == seq2[index1]:
                                          break
                                      elif seq1[index2] != item2:
                                          common += 1
                                          seq2[index2] = None
                                          break
                          return common


                      PS: Ah bah si en fait je fais une copie (ligne 3). J'avais zappé ce détail :lol:

                      -
                      Edité par Olygrim 27 octobre 2016 à 14:28:29

                      • Partager sur Facebook
                      • Partager sur Twitter
                      Précepte: Le mieux est l'ennemi du bien
                        27 octobre 2016 à 14:33:34

                        ah oui pas mal ^^

                        la mienne a un soucis à cause de ça:

                        les éléments reliés par un trait on bien la même valeur et un indice différents. Du coup ça a du mal à marcher.. je vois pas trop comment contourner le problème sans faire un truc du même genre que toi @Olygrim x)

                        je vais continuer de réfléchir mais bon..

                        Je me demandais, en passant par la fonction count, on a pas possibilité de faire un truc bien?

                        • Partager sur Facebook
                        • Partager sur Twitter
                        Si je suis tête en l'air, c'est par habitude de viser le sommet
                          27 octobre 2016 à 14:38:55

                          WexyR a écrit:

                          Je me demandais, en passant par la fonction count, on a pas possibilité de faire un truc bien?

                          Huhu, j'ai eu le même cheminement mais quand j'ai commencé à voir la gueule de la solution j'ai vite lâché l'affaire :lol:.

                          Mais peut-être existe-il une solution toute simple qui nous est passé sous le nez ^^

                          • Partager sur Facebook
                          • Partager sur Twitter
                          Précepte: Le mieux est l'ennemi du bien
                            27 octobre 2016 à 14:43:11

                            Olygrim a écrit:

                            Mais peut-être existe-il une solution toute simple qui nous est passé sous le nez ^^

                            Effectivement, en fait je suis même déçu que tu nous ais pas sorti une solution toute prête de itertools ou collections x)

                            EDIT: j'ai contourné mon problème: je suis tombé sur ta solution... rah! ><'

                            -
                            Edité par WexyR 27 octobre 2016 à 14:49:16

                            • Partager sur Facebook
                            • Partager sur Twitter
                            Si je suis tête en l'air, c'est par habitude de viser le sommet
                              27 octobre 2016 à 14:48:06

                              Il faut que je développe mes compétences algorithmiques (je suis pas super fort là-dessus). C'est pour ça que j'essaie de réfléchir à des algorithmes naïfs mais efficace ^^

                              Mais j'avoue que je n'ai pas eu de *flash* me permettant d'utiliser l'un ou l'autre de ces modules :p

                              -
                              Edité par Olygrim 27 octobre 2016 à 14:48:35

                              • Partager sur Facebook
                              • Partager sur Twitter
                              Précepte: Le mieux est l'ennemi du bien
                                27 octobre 2016 à 23:15:09

                                j'ai une soluce avec des set(), je sais pas si c'est autorisé ...

                                def communs(L1,L2):
                                	L = set(L1+L2)
                                	for a,b in set(zip(L1,L2)):
                                		if a==b: L.remove(a)
                                	return len(set(L1)&set(L2)&L)



                                • Partager sur Facebook
                                • Partager sur Twitter

                                Python c'est bon, mangez-en. 

                                  28 octobre 2016 à 0:04:50

                                  Ton code ne renvoie pas toujours le bon résultat. Par exemple pour les deux listes suivantes:

                                  lst1 = [3, 2, 0, 1, 1]
                                  lst2 = [1, 1, 3, 2, 1]


                                  Il y a 3 valeurs mal placées (le 3, le 2 et le 1) mais ton code renvoie 2. Par contre je ne pourrais absolument pas te dire pourquoi car j'ai pas compris grand chose à ton code :lol:

                                  • Partager sur Facebook
                                  • Partager sur Twitter
                                  Précepte: Le mieux est l'ennemi du bien
                                    28 octobre 2016 à 0:10:07

                                    Une tentative... j'ai regardé les règles du master mind ;)

                                    def necommuns(liste_a,liste_b):
                                    	assert len(liste_a) == len(liste_b)
                                    	
                                    	# On enlève les éléments identiques qui sont à la même position
                                    	# On doit faire cette détection de toute façon pour savoir
                                    	# si le joueur a proposé les bonnes couleurs dans sa ligne
                                    	# de mastermind, donc autant faire d'une pierre deux coups...
                                    	A = []
                                    	B = []
                                    	for n in xrange(len(liste_a)):
                                    		if liste_a[n] == liste_b[n]:
                                    			print "position %d est bonne" % n
                                    		else:
                                    			A.append(liste_a[n])
                                    			B.append(liste_b[n])
                                    	
                                    	print "reste:", A,B
                                    
                                    	# on cherche les éléments communs
                                    	# Note pour le mastermind: 
                                    	# si la combinaison gagnante est 1122 et on propose 2211
                                    	# alors on a 4 éléments corrects mais pas au bon endroit,
                                    	# on doit donc renvoyer 4
                                    	# MAIS si la combi on propose 1112, alors le 2 est bon, 
                                    	# les deux premiers 1 sont bons, et le 3ème 1
                                    	# ne compte pas, on renvoie donc 0!
                                    	
                                    	compte = 0
                                    	for a in A:
                                    		if a in B:
                                    			B.remove(a)
                                    			compte += 1
                                    		
                                    	return compte
                                    
                                    
                                    a = [1,2,3,1,1,3]
                                    b = [1,3,2,2,1,3]
                                    print ">",necommuns(a,b)
                                    
                                    a = [1,1,2,2]
                                    b = [2,2,1,1]
                                    print ">",necommuns(a,b)
                                    
                                    a = [1,1,2,2]
                                    b = [1,1,1,2]
                                    print ">",necommuns(a,b)



                                    • Partager sur Facebook
                                    • Partager sur Twitter
                                      28 octobre 2016 à 9:49:13

                                      Olygrim a écrit:

                                      Ton code ne renvoie pas toujours le bon résultat. Par exemple pour les deux listes suivantes:

                                      lst1 = [3, 2, 0, 1, 1]
                                      lst2 = [1, 1, 3, 2, 1]


                                      Il y a 3 valeurs mal placées (le 3, le 2 et le 1) mais ton code renvoie 2. Par contre je ne pourrais absolument pas te dire pourquoi car j'ai pas compris grand chose à ton code :lol:


                                      c'est pas ce qui est demandé ? ... arf, j'avais pas compris l'énoncé.

                                      Edit:

                                      donc ici on parle de MasterMind ...  ça tombe bien j'en avais codé un : ici

                                      et la fonction qui nous intéresse:

                                      def submit(mastermind,value):
                                          try:
                                              a,b = zip(*[(a,b) for a,b in zip(mastermind,value) if a!=b])
                                              a   = list(a)
                                          except: return 4,0
                                          for i in b:
                                              try: a.remove(i)
                                              except: continue
                                          return 4-len(b),len(b)-len(a) # retourne bien placés, mal placés
                                      



                                      -
                                      Edité par josmiley 28 octobre 2016 à 10:11:00

                                      • Partager sur Facebook
                                      • Partager sur Twitter

                                      Python c'est bon, mangez-en. 

                                        28 octobre 2016 à 10:13:59

                                        Ok, la logique est la même que pour la fonction de Casque Noir:

                                        • Récupérer les éléments qui ne sont pas identiques dans deux listes séparées.
                                        • Itérer sur l'une et supprimer dans l'autre si l'élément est présent.

                                        J'aime beaucoup :)

                                        Voici ma version copitée de celle de Casque Noir ;):

                                        def items_common(seq1, seq2):
                                            assert len(seq1) == len(seq2)
                                        
                                            items_seq1, items_seq2 = [], []
                                            for item1, item2 in zip(seq1, seq2):
                                                if item1 != item2:
                                                    items_seq1.append(item1), items_seq2.append(item2)
                                        
                                            compte = 0
                                            for item1 in items_seq1:
                                                if item1 in items_seq2:
                                                    items_seq2.remove(item1)
                                                    compte += 1
                                            return compte
                                        
                                        • Partager sur Facebook
                                        • Partager sur Twitter
                                        Précepte: Le mieux est l'ennemi du bien
                                          28 octobre 2016 à 11:23:14

                                          Sinon,

                                          • trier les deux listes
                                          • variante de algo classique de fusion/union/intersection de listes ordonnées 

                                          Un truc comme ça

                                          def communs(liste1, liste2):
                                              l1 = liste1[:]   # copies
                                              l2 = liste2[:]
                                              l1.sort()
                                              l2.sort()
                                              i = 0
                                              j = 0
                                              nb = 0
                                              while (i < len(l1) and j < len(l2)):
                                                  if l1[i] < l2[j] :
                                                      i += 1
                                                  elif l1[i] > l2[j] :
                                                      j += 1
                                                  else:
                                                      nb += 1
                                                      i += 1
                                                      j += 1
                                              return nb
                                             


                                          Ca compte ceux qui sont à la même place, mais c'est facile de les soustraire ensuite (d'autant que si c'est le mastermind, on a besoin de les compter de toutes facons)

                                           PS : sur des listes de grande taille, ça doit être optimal ( N log N  dû au tri), mais bon, sur un master mind avec des listes de longueur 4, la methode triviale de comparaison 2 à 2, ça fait jamais que 16 comparaisons.

                                          -
                                          Edité par michelbillaud 28 octobre 2016 à 11:33:49

                                          • Partager sur Facebook
                                          • Partager sur Twitter
                                            28 octobre 2016 à 12:01:20

                                            La difficulté c'est justement de faire un code qui ne prend pas en compte les éléments à la même place. Sinon si c'est juste un décompte, il suffit d'écrire:

                                            from collections import Counter
                                            def decompte(seq1, seq2):
                                                c1, c2 = Counter(seq1), Counter(seq2)
                                                intersec = c1 & c2
                                                print(sum(intersec.values()))

                                            ;)

                                            -
                                            Edité par Olygrim 28 octobre 2016 à 12:01:47

                                            • Partager sur Facebook
                                            • Partager sur Twitter
                                            Précepte: Le mieux est l'ennemi du bien

                                            Elements communs dans une liste

                                            × 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