Partage
  • Partager sur Facebook
  • Partager sur Twitter

Problème d'algorithme avec Python

Sujet résolu
    2 janvier 2011 à 13:13:23

    Bonjour. J'ai un problème que je ne parviens pas résoudre malgré mes recherches.
    J'ai une image de 3x3 pixels représentées dans mon code par un tableau de 0 ou de 1 suivant que le pixel est blanc ou noir.

    J'ai une fonction inverser qui prend en paramètre une image et une position et qui inverse la couleur du pixel à cette position et des quatre pixels autour de lui (en forme de + donc) et qui renvoie l'image ainsi modifiée.
    D'après mes tests, cette fonction fonctionne parfaitement.

    Je souhaite ensuite chercher toutes les images possibles de 3x3 pixels en inversant d'une telle manière les pixels.

    Voici la fonction que j'ai écrit :
    def tab( image , n, m):
            global listeImages
            if not(image in listeImages):
                    listeImages.append(image)
                    for x in range(n):
                            for y in range(m):
                                    tab( inverser(image, x, y), n, m)
    

    Elle prend en paramètre une fonction et sa taille, puis vérifie si cette image a déjà été rencontrée. Si non, on la rajoute dans la liste des images déjà croisées puis on teste toutes les images constructibles à partir de celle-ci. Visiblement, c'est cette fonction qui ne fonctionne pas puisque je n'ai pas le résultat attendu.

    Voici le code dans son intégralité :
    listeImages = []
    
    
    def inverser(tableau, x, y):
            tableau[y][x] = -tableau[y][x] +1
            if y > 0:
                    tableau[y-1][x] = -tableau[y-1][x] +1
            if x > 0:
                    tableau[y][x-1] = - tableau[y][x-1] +1
            if x < (len(tableau[0]) -1):
                    tableau[y][x+1] = -tableau[y][x+1] + 1
            if y < (len(tableau) -1):
                    tableau[y+1][x] = -tableau[y+1][x] + 1
            return tableau
    
    def tab( image , n, m):
            global listeImages
            if not(image in listeImages):
                    listeImages.append(image)
                    for x in range(n):
                            for y in range(m):
                                    tab( inverser(image, x, y), n, m)
    if __name__ == '__main__':
            tab([[0,0,0],[0,0,0],[0,0,0]], 3, 3)
            print listeImages
    


    Ce code ne produit pas la sortie attendue mais :
    [[[1, 0, 1], [0, 1, 0], [1, 0, 1]]]


    Je ne comprends pas comment le programme produit cette sortie.

    Merci
    • Partager sur Facebook
    • Partager sur Twitter
      2 janvier 2011 à 13:47:48

      Tu lui demandes d’afficher listeImages (dernière ligne de ton code)... Alors il le fait, il t’affiche un tableau de tableaux avec la notation qu’il connaît pour le faire : un tableau, pour lui, ça se note [valeur1, ..., valeurn]... ;)
      • Partager sur Facebook
      • Partager sur Twitter
      Anonyme
        2 janvier 2011 à 14:01:31

        Pour savoir combien d'images différentes de n couleurs maximum il est possible de faire avec un cadre de x pixels, il suffit d'une instruction ; n puissance de x. ;)
        • Partager sur Facebook
        • Partager sur Twitter
          2 janvier 2011 à 14:03:53

          Donc <math>\(2^9\)</math>, en l’occurrence... ;)
          • Partager sur Facebook
          • Partager sur Twitter
            2 janvier 2011 à 14:15:08

            Ici, les images suivent une règle très précise lorsqu'on les dessine, ce qui fait qu'on a un nombre d'image inférieur à 2^9.
            La problème est que la liste d'image ne contient que un tableau alors qu'elle devrait en contenir plus ([[0,0,0],[0,0,0][0,0,0]] par exemple. Il m'affiche bien un tableau mais qui ne comprends qu'un seul élément, alors qu'il devrait en contenir plusieurs. Je ne comprends toujours pas où est mon erreur :S
            • Partager sur Facebook
            • Partager sur Twitter
            Anonyme
              2 janvier 2011 à 15:31:59

              Ok, autant pour moi, je n'avais pas bien lu.

              Alors ton problème vient du fait qu'en python tout est référence à objet. C'est à dire que la liste 'listeImages' contient la liste 'image' et quand tu modifie cette dernière avec la fonction 'inverser()' c'est belle et bien toujours l'objet 'image' que tu modifie. En gros tu ne copie pas une nouvelle liste mais tu traite toujours le même objet.

              À la place de listeImage.append(image) essaye listeImage.append([[pix for pix in row] for row in image])

              [edit] Par contre, len(listeImages) == 2**9 soit 512. ;)
              • Partager sur Facebook
              • Partager sur Twitter
                2 janvier 2011 à 23:15:25

                Merci beaucoup, décidément j'aurai du mal à me faire à ce comportement de python que je ne trouve pas logique...
                • Partager sur Facebook
                • Partager sur Twitter
                Anonyme
                  3 janvier 2011 à 0:08:01

                  Je ne sais pas si c'est illogique mais c'est ainsi. ^^

                  Il ne faut jamais oublier que l'on ne passe pas un objet à une fonction mais sa référence. Et vient s'ajouter à ce concepte, le fait qu'il y a deux sortes d'objets ; les non-modifiables (int, float, str, bytes, etc. ) et les modifiables comme les listes.

                  Petit exemple pour comprendre :
                  >>> def f(obj, x):
                  ...     "Ajoute <x> à <obj> (<x> doit être du même type que <obj>)."
                  ...     # on affiche l'id de <obj> avant traitement :
                  ...     print(id(obj))
                  ...     obj += x # ajout de <x> à <obj>
                  ...     # affichage de l'id de <obj> après traitement :
                  ...     print(id(obj))
                  ...     # enfin on retourne l'objet modifié :
                  ...     return obj
                  ... 
                  >>> ls = [1, 'deux', 2.1, b"\x123"]
                  >>> id(ls)
                  33572984
                  >>> f(ls, ['hello'])
                  33572984
                  33572984
                  [1, 'deux', 2.1, b'\x123', 'hello']
                  >>> ls
                  [1, 'deux', 2.1, b'\x123', 'hello']
                  >>> nb = 5
                  >>> id(nb)
                  505408936
                  >>> id(5)
                  505408936
                  >>> f(nb, 3)
                  505408936
                  505408984
                  8
                  >>> id(8)
                  505408984
                  


                  Petit plus : l'id d'un objet avec Cpython correspond aussi à l'emplacement de l'objet dans la memoire. ;)
                  • Partager sur Facebook
                  • Partager sur Twitter
                    3 janvier 2011 à 13:11:53

                    C'est pas illogique, c'est un choix. Par exemple, ça permet de créer une fonction qui traite une liste en agissant directement dessus, plutôt que sur une copie (par exemple, pour gagner de la place en mémoire).
                    • Partager sur Facebook
                    • Partager sur Twitter
                      4 janvier 2011 à 22:32:54

                      Je me suis mal exprimé : je ne trouve pas que ce soit une mauvaise chose, c'est juste un choix. J'ai juste plus l'habitude de souvent passer par des copies, d'utiliser des références si je souhaite modifier l'objet passé en paramètre ou const si je ne le modifierai pas et que je n'ai pas besoin d'en faire une copie. C'est juste une autre habitude mais maintenant je fais pas gaffe et j'oublie qu'un choix différent à était fait par les développeurs de python.

                      Merci beaucoup pour votre aide :)
                      • Partager sur Facebook
                      • Partager sur Twitter

                      Problème d'algorithme avec Python

                      × 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