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

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

Python Discussion :

nombre variable de boucles


Sujet :

Python

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

    Informations forums :
    Inscription : Janvier 2007
    Messages : 1 418
    Points : 1 658
    Points
    1 658
    Par défaut fumigation et japonaiserie
    tytamos, j'ai lu de façon plus approfondie ton tuto après avoir écrit mes messages un peu rapidement cette nuit. Y a pas à dire, il est complet et bien fait.
    Mais il y a quelque chose qui me chiffone dans tout ce perfectionnement.
    Je ne suis pas sûr qu'un progamme qui crée une imbrication de boucles en s'attachant à prévoir tous les cas possible comme entrées soit absolument utile. En effet, un tel programme est nécessairement destiné à servir au sein d'un programme qui l'englobe à titre de module. Si j'en avais le besoin, je préfèrerais personnellement fignoler une insertion d'un tel "module" dans un programme en l'adaptant exactement à mon programme englobant, et dans ce cas le formalisme des entrées et soties du module ne me conviendrait peut ètre pas exctement.
    Ainsi pour utiliser un tel programme, si on veut par exemple utiliser le deuxième indice à s'incrémenter, il faudra extraire par x = boucles.C[-2] puis utiliser cette valeur dans le programme englobant. Je préfèrerais dans ce cas personnellement aller mettre les instructions du programme général au sein même des instructions de boucles(), en les entrelardant en quelque sorte. Ça permet de mettre un peu de mathématique dans l'algorithme, au lieu de se reposer entièrement sur les capacités de Python pour faire des tâches. C'est pour ça que j'écris "programme général" et non plus "programme englobant" dans mon optique.
    Ceci dit, avec les programmes tels que je les donne il faut aussi préléver tel ou tel indice de la même manière que je viens de dire. Je crois.....
    Je ne suis pas sûr que tout ce que je viens de raconter soit très clair ni même pertinent. Il faudrait que je vois ce qui se passe en prenant un cas concret au lieu de blablater.


    En contraste à ces considérations peut être un peu fumeuses, j'ai réécrit mon dernier programme dans le sens d'un dépouillement à la japonaise:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    bornesup = []
    n = 1
    while 1:
        try:
            v = input('Entrer une borne superieure (RIEN pour arreter les entrees) : ')
            bornesup.insert(0,v)
            n = n*v
        except:
            break
    print 'bornesup =',bornesup,'n=',n
     
    li = [ 0 for i in bornesup ]
    for x in xrange(n):
        for (k,born) in enumerate(bornesup):
            c = x%born
            li[-k-1] = c
            if c:
                break
            x = x/born
        print li

  2. #22
    Expert éminent
    Avatar de tyrtamos
    Homme Profil pro
    Retraité
    Inscrit en
    Décembre 2007
    Messages
    4 462
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2007
    Messages : 4 462
    Points : 9 249
    Points
    9 249
    Billets dans le blog
    6
    Par défaut
    En fait, quand je commence à travailler sur un sujet qui me semble de portée générale, j'essaie de le développer pour pouvoir m'en resservir plus tard. Et les tutos que je fais sont d'abord pour moi: c'est une mémoire de solutions qui marchent! De ce fait, je reconnais que j'en ai fait plus que ce qui était strictement nécessaire pour répondre au problème posé.

    Ce faisant, dans les 2 solutions que j'ai données, c'est la seconde qui a ma préférence: celle qui est basée sur une classe. Car une fois cette classe mise au point, et insérée dans un module "Boucles" par exemple, l'utilisation en devient extrêmement simple:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    import Boucles
     
    boucles = Boucles.Boucles([5,3,4])
    while boucles.encore():
        #...
        # print boucles.C
        #...
    Une fois qu'on a compris comment incrémenter rapidement ces compteurs hiérarchisés, on pense à d'autres utilisations.

    Ainsi, comme on peut fixer le nombre de boucles pendant le déroulement du programme, on peut aussi, par exemple, s'en servir pour compter en binaire sur un nombre quelconque de digits. Par exemple avec 4 digits:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    B = [2,2,2,2]
    boucles = Boucles(B)
     
    while boucles.encore():
        print "".join([str(x) for x in boucles.C])
    Ce qui affiche:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
     
    0000
    0001
    0010
    0011
    0100
    0101
    0110
    0111
    1000
    1001
    1010
    1011
    1100
    1101
    1110
    1111
    Et avec B = [8,8,8,8], donc sur 4 digits aussi, on peut compter en octal:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
     
    0000
    0001
    0002
    0003
    0004
    0005
    0006
    0007
    0010
    0011
    0012
    ...
    ...
    7774
    7775
    7776
    7777
    Tyrtamos
    Un expert est une personne qui a fait toutes les erreurs qui peuvent être faites, dans un domaine étroit... (Niels Bohr)
    Mes recettes python: http://www.jpvweb.com

  3. #23
    Expert éminent
    Avatar de tyrtamos
    Homme Profil pro
    Retraité
    Inscrit en
    Décembre 2007
    Messages
    4 462
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2007
    Messages : 4 462
    Points : 9 249
    Points
    9 249
    Billets dans le blog
    6
    Par défaut
    Bon, puisque personne n'a osé proposer la solution suivante, je vais quand même la donner au moins pour mémoire:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    B = [5,3,4]
    ch = ""
    for i in range(0,len(B)): ch += "    "*i + "for i" + str(i) + " in range(" + str(B[i]) + "):\n"
    ch += "    "*len(B) + "print "
    for i in range(0,len(B)): ch += "i" + str(i) + ", "
    ch = ch[:-2] + "\n"
    exec(ch)
    la chaine "ch" construite est:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    for i0 in range(5):
        for i1 in range(3):
            for i2 in range(4):
                print i0, i1, i2
    Et le résultat de son exécution par exec(ch) donne bien:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    0 0 0
    0 0 1
    0 0 2
    0 0 3
    0 1 0
    ...
    4 2 0
    4 2 1
    4 2 2
    4 2 3
    Il faut, bien entendu, remplacer le print par les instructions voulues.

    Ce n'est pas une solution terrible, et elle a plein de défauts, mais... c'est probablement la plus courte, et peut-être même la plus rapide

    Tyrtamos
    Un expert est une personne qui a fait toutes les erreurs qui peuvent être faites, dans un domaine étroit... (Niels Bohr)
    Mes recettes python: http://www.jpvweb.com

  4. #24
    Membre éclairé
    Homme Profil pro
    heu...
    Inscrit en
    Octobre 2007
    Messages
    648
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : heu...

    Informations forums :
    Inscription : Octobre 2007
    Messages : 648
    Points : 773
    Points
    773
    Par défaut
    Tiens, c'est drôle, cette nuit j'me suis repenché sur un vieux module que je voulais améliorer (et qui au vu de vos code, peux encore être largement raccourcis...), m'enfin plus on est de fou , plus on rit comme on dit

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    import random
     
    class CIter(object):
        __slots__=('idx',)
        randrange=random.randrange
        def __init__(self,clock=False,*args):
            self.idx=()
            for x in args:
                self.idx+=(CIter.Compound(x if not clock else x-1,self.idx[-1] if self.idx!=() else None))
            self.idx[-1](-1)
        def next(self):
            self.idx[-1].next()
        def random(self):
            return tuple(x.random() for x in self.idx)
        def __call__(self):
            self.next()
            a=tuple(x() for x in self.idx)
            return a if None!=a[0] else None
     
        class Compound(object):
            __slots__=('limit','val','parent')
            def __init__(self,val,parent=None):
                self.limit=val
                self.val=0
                self.parent=parent
            def next(self):
                if self.val+1>self.limit:
                    if self.parent is not None:
                        self.val=0
                        self.parent.next()
                    else: self.val=None
                else: self.val+=1
            def reset(self): self.val=0
            def random(self):
                return CIter.randrange(self.limit+1)
            def __call__(self,val=None):
                if val is None:return self.val
                elif val> self.limit:
                    self.limit=self.val=val
                else: self.val=val
     
    if __name__=='__main__':
        a=CIter(False,10,10)
        while 1:
            b=a()
            if b is None: break
            else: print(b)
        #for x in range(20): print(a.random())
     
        #Et façon 'horloge'
        print('\n\n')
        a=CIter(True,10,10)
        while 1:
            b=a()
            if b is None: break
            else: print(b)
     
    #-------------
    #Execution
    #-------------
    (0, 0)
    (0, 1)
    (0, 2)
    (1, 0)
    (1, 1)
    (1, 2)
    (2, 0)
    (2, 1)
    (2, 2)
     
     
    (0, 0)
    (0, 1)
    (1, 0)
    (1, 1)

  5. #25
    Membre éclairé
    Homme Profil pro
    heu...
    Inscrit en
    Octobre 2007
    Messages
    648
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : heu...

    Informations forums :
    Inscription : Octobre 2007
    Messages : 648
    Points : 773
    Points
    773
    Par défaut
    Je sais que le post commence à se faire vieux, mais je me suis encore repenché sur ce problème...

    La dernière soluce de tyrtamos est sans égale en termes de vitesse, (et même en terme d'utilisation mémoire à partir de python 2.6 ou 3.0 (les range produisant des generators)). Ceci dit, je trouve pas hyper élégant de devoir taper les instructions de la dernières boucle dans du texte, m'enfin, c'est du pure chipotage, les résultats sont là...

    voici un generator de generators qui nous retourne une liste d'index, un paramètre étant une liste de longueurs est passé a ce generator de generator lors de sa création:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    def genBox(lens):
        def gen(x,parent=None,y=0):
            while 1:
                if y<x:
                    yield y
                    y+=1
                elif parent is not None:
                    parent.next()
                    y=0
                else:
                    raise StopIteration
        genBox=[gen(lens[0])]
        for x in range(1,len(lens)):
            genBox[-1].next()
            genBox.append(gen(lens[x],genBox[-1]))
        while 1:
            genBox[-1].next()
            yield tuple([x.gi_frame.f_locals['y'] for x in genBox])
    code de test:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    foo=[['a','b','c'],['d','e','f']]
    for x in genBox([len(y) for y in foo]):
        print [foo[y][x[y]] for y in range(len(foo))]
    et le resultat:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    >>> 
    ['a', 'd']
    ['a', 'e']
    ['a', 'f']
    ['b', 'd']
    ['b', 'e']
    ['b', 'f']
    ['c', 'd']
    ['c', 'e']
    ['c', 'f']
    >>>
    Voilà, elle ne vaut toujours pas celle de Tyrtamos, mais je la trouvais assez sympa en terme de consomation mémoire pour être postée...

Discussions similaires

  1. Boucles imbriquées de nombre variable
    Par CondensationdeCauchy dans le forum Débuter
    Réponses: 1
    Dernier message: 04/04/2015, 19h46
  2. Boucle While avec nombre variable de conditions
    Par jazzybluesy dans le forum Macros et VBA Excel
    Réponses: 2
    Dernier message: 22/09/2012, 19h05
  3. Pb de Boucles "Pour" (nombre variable)
    Par Isima dans le forum Algorithmes et structures de données
    Réponses: 4
    Dernier message: 28/05/2008, 10h53
  4. Boucles imbriquées en nombre variable
    Par lebelge dans le forum Fortran
    Réponses: 5
    Dernier message: 05/07/2007, 14h58
  5. Procédure avec un nombre variable d'arguments
    Par charly dans le forum Langage
    Réponses: 15
    Dernier message: 21/06/2002, 11h08

Partager

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