web-dev-qa-db-fra.com

Fonction avec un nombre variable de boucles For (python)

Mon problème est difficile à expliquer.

Je veux créer une fonction qui contient des boucles imbriquées,
dont le montant est proportionnel à un argument passé à la fonction.

Voici un exemple hypothétique:

Function(2)

... impliquerait ...

for x in range (y):
    for x in range (y):
        do_whatever()

Un autre exemple... 

  Function(6)

... impliquerait ...

for x in range (y):
    for x in range (y):
        for x in range (y):
            for x in range (y):
                for x in range (y):
                    for x in range (y):
                        whatever()

Les variables de la boucle for (y) ne sont PAS réellement utilisées dans le code imbriqué. 

Votre première idée serait peut-être de créer ONE pour la boucle, avec une plage qui correspond à la puissance de l'argument numérique ...
CELA NE PEUT PAS FONCTIONNER car le produit serait énorme. J'ai des cas où il y a 8 boucles imbriquées.
Le produit est trop volumineux pour une plage dans une boucle for.

D'autres arguments doivent être passés à la fonction, mais je peux le gérer moi-même.

Voici le code (Il crée la fractale de flocon de neige)

from turtle import *
length = 800
speed(0)

def Mini(length):
    for x in range (3):
        forward(length)
        right(60)

penup()
setpos(-500, 0)
pendown()   

choice = input("Enter Complexity:")

if choice == 1:
    for x in range (3):
        forward(length)
        left(120)

Elif choice == 2:
    for x in range (3):
        Mini(length/3)
        left(120)

if choice == 3:
    for x in range (6):
        Mini(length/9)
        right(60)
        Mini(length/9)
        left(120)

if choice == 4:
    for y in range (6):
        for x in range (2):
            Mini(length/27)
            right(60)
            Mini(length/27)
            left(120)
        right(180)
        for x in range (2):
            Mini(length/27)
            right(60)
            Mini(length/27)
            left(120)

if choice == 5:
    for a in range (6):
        for z in range (2):
            for y in range (2):
                for x in range (2):
                    Mini(length/81)
                    right(60)
                    Mini(length/81)
                    left(120)
                right(180)
                for x in range (2):
                    Mini(length/81)
                    right(60)
                    Mini(length/81)
                    left(120)
            right(180)
        right(180)

if choice == 6:
    for c in range (6):
        for b in range (2):
            for a in range (2):
                for z in range (2):
                    for y in range (2):
                        for x in range (2):
                            Mini(length/243)
                            right(60)
                            Mini(length/243)
                            left(120)
                        right(180)
                        for x in range (2):
                            Mini(length/243)
                            right(60)
                            Mini(length/243)
                            left(120)
                    right(180)
                right(180)
            right(180)
        right(180)

if choice == 7:
    for a in range (6):
        for b in range(2):
            for c in range (2):
                for d in range (2):
                    for e in range (2):
                        for f in range (2):
                            for y in range (2):
                                for x in range (2):
                                    Mini(length/729)
                                    right(60)
                                    Mini(length/729)
                                    left(120)
                                right(180)
                                for x in range (2):
                                    Mini(length/729)
                                    right(60)
                                    Mini(length/729)
                                    left(120)
                            right(180)
                        right(180)
                    right(180)
                right(180)
            right(180)
        right(180)

J'apprécierais toute aide que vous pourriez me donner,
Cependant, si vous suggérez une méthode différente (telle que la récursion),
s'il vous plaît ne collez pas simplement le code; suggère plutôt des idées qui pourraient me mettre dans la bonne direction.

(L'algorithme est pour une assignation en maths spécialisé)


spécifications:
Python 2.7.1
Tortue
TOURNER AU RALENTI
Windows 7

28
Anti Earth

Ce problème peut être résolu par la récursivité. Je suis juste en train d'écrire un algorithme ici, car je crois que cela peut être un problème général. 

function Recurse (y, number) 
   if (number > 1)
      Recurse ( y, number - 1 )
   else
      for x in range (y)
      whatever()
19
Ozair Kafray

Je ne comprends pas pourquoi vous ne pouvez pas utiliser le produit des limites et faire

for x in range(y exp n)

où n est le nombre de boucles ... Vous dites que y exp n sera énorme, mais je suis sûr que python peut le gérer.

Cependant, cela étant dit, qu'en est-il d'une sorte d'algorithme récursif?

def loop_rec(y, n):
    if n >= 1:
        for x in range(y):
            loop_rec(y, n - 1)
    else:
       whatever()
22
Robert Martin

cela peut être fait sans récursion en utilisant itertools.product

import itertools
def function(n):
    for x in itertools.product(range(n),repeat=n):
        whatever()
13
Dan D.

La récursivité sera votre meilleur pari. Considérez ce que cela devrait faire dans le cas de base et dans le cas récursif.

Code laissé à la demande.

5
outis

Voici. Laissez les plages être vos plages, opérez sur le résultat lorsque vous en avez besoin.

ranges=((1,4),(0,3),(3,6))
from operator import mul
operations=reduce(mul,(p[1]-p[0] for p in ranges))-1
result=[i[0] for i in ranges]
pos=len(ranges)-1
increments=0
print result
while increments < operations:
    if result[pos]==ranges[pos][1]-1:
        result[pos]=ranges[pos][0]
        pos-=1
    else:
        result[pos]+=1
        increments+=1
        pos=len(ranges)-1 #increment the innermost loop
        print result

[1, 0, 3]
[1, 0, 4]
[1, 0, 5]
[1, 1, 3]
[1, 1, 4]
[1, 1, 5]
[1, 2, 3]
[1, 2, 4]
[1, 2, 5]
[2, 0, 3]
[2, 0, 4]
[2, 0, 5]
[2, 1, 3]
[2, 1, 4]
[2, 1, 5]
[2, 2, 3]
[2, 2, 4]
[2, 2, 5]
[3, 0, 3]
[3, 0, 4]
[3, 0, 5]
[3, 1, 3]
[3, 1, 4]
[3, 1, 5]
[3, 2, 3]
[3, 2, 4]
[3, 2, 5]
[1, 0, 4]

Tester avec ce qui suit donnerait le même résultat:

for x in range(*ranges[0]):
    for y in range(*ranges[1]):
        for z in range(*ranges[2]):
            print [x,y,z]
3
robert king

Avez-vous envisagé de xrange?

for x in xrange(y ** n):
    whatever()

Et si vous dépassez la limite, même xrange, vous pouvez utiliser itertool

import itertools
for x in itertools.product(xrange(y), repeat=n):
   whatever()

(la réponse précédente dans l'outil de traitement utilisé incorrectement n pour la plage au lieu de y)

1
MatthieuW

Ma réponse est en retard, mais supposons que vous vouliez faire plusieurs boucles, par exemple. imprimer une plage plusieurs fois. Alors la version correcte de cette récursion est:

def loop_rec(y, number):
   if (number > 1):
      loop_rec( y, number - 1 )
      for i in range(y): 
         print(i, end=' ')        
   else:      
      for i in range(y):
         print(i, end=' ')

loop_rec(4,3)

Cela créera trois boucles for avec la plage (4)

Si vous voulez jouer avec la plage dynamique, voici quelques variantes:

def loop_rec(y, number):
if (number > 1):
    loop_rec( y+1, number - 1 )
    for i in range(y): 
        print(i, end=' ')
    print(' ;')
else:      
    for i in range(y):
        print(i, end=' ')
    print(';')

loop_rec(6,4)

qui imprimera:

0 1 2 3 4 5 6 7 8 ;
0 1 2 3 4 5 6 7  ;
0 1 2 3 4 5 6  ;
0 1 2 3 4 5  ;

ou

def loop_rec(y, number):
if (number > 1):
    loop_rec( y-1, number - 1 )
    for i in range(y): 
        print(i, end=' ')
    print(' ;')
else:      
    for i in range(y):
        print(i, end=' ')
    print(';')
loop_rec(6,4)

qui produira:

0 1 2 ;
0 1 2 3  ;
0 1 2 3 4  ;
0 1 2 3 4 5  ;

Une meilleure variante qui utilise une seule boucle for (moins de frappe) est la suivante:

def loop_rec(y, number):
    if (number >= 1):
        loop_rec( y+1, number - 1 )
        for i in range(y): 
            print(i, end=' ')
        print('')
    else:      
        return

loop_rec(1,5)

affichera:

0 1 2 3 4 
0 1 2 3 
0 1 2 
0 1 
0 
0
youth4ever