Boucle imbriquée cachée vers une fonction récursive en Python

2020-08-02 python recursion nested nested-loops

Bonjour, je vais écrire tout l'état du texte avec le mode supérieur et inférieur un par un et je peux le faire par imbriqué pour mais c'est juste utile pour le texte avec 6 caractères, je vais le convertir en récursif, quelqu'un peut-il aider?

text=['a','b','c','d','e','f']
for i in [0, 1]:
    if i == 1:
        text[0] = text[0].upper()
    else:
        text[0] = text[0].lower()
    for j in [0, 1]:
        if j == 1:
            text[1] = text[1].upper()
        else:
            text[1] = text[1].lower()
        for w in [0, 1]:
            if w == 1:
                text[2] = text[2].upper()
            else:
                text[2] = text[2].lower()
            for q in [0, 1]:
                if q == 1:
                    text[3] = text[3].upper()
                else:
                    text[3] = text[3].lower()
                for z in [0, 1]:
                    if z == 1:
                        text[4] = text[4].upper()
                    else:
                        text[4] = text[4].lower()
                    for g in [0, 1]:
                        if g == 1:
                            text[5] = text[5].upper()
                        else:
                            text[5] = text[5].lower()
                        print(''.join(text))

La sortie est ci-dessous et son correct mais je le ferai avec récursif :

abcdef abcdeF abcdEf abcdEF abcDef abcDeF abcDEf abcDEF abCdef abCdeF abCdEf abCdEF abCDef abCDeF abCDEf abCDEF aBcdef aBcdeF aBcdEf aBcdEF aBcDef aBcDeF aBcDEf aBcDEF aBCdef aBCdeF aBCdEf aBCdEF aBCDef aBCDeF aBCDEf aBCDEF Abcdef AbcdeF AbcdEf AbcdEF AbcDef AbcDeF AbcDEf AbcDEF AbCdef AbCdeF AbCdEf AbCdEF AbCDef AbCDeF AbCDEf AbCDEF ABcdef ABcdeF ABcdEf ABcdEF ABcDef ABcDeF ABcDEf ABcDEF ABCdef ABCdeF ABCdEf ABCdEF ABCDef ABCDeF ABCDEf ABCDEF

Pleas Quelqu'un peut-il aider?

Answers

Je n'utiliserais pas la récursivité en soi, mais plutôt une boucle while:

text=['a','b','c','d','e','f']
remaining_text = text[:]  #copy the array
options = ['']  # we start with an empty string so we can easily append to it
while remaining_text:
    # get the first letter and removes it from the list in one go
    next_letter = remaining_text.pop(0)
    
    # and add one option with lowercase and one with uppercase
    # for every existing option
    options = (
        [option + next_letter.lower() for option in options]
        + [option + next_letter.upper() for option in options]
    )

print(options)

Vous pouvez utiliser la récursivité pour cela, voir ci-dessous. Le principal avantage de l'utilisation d'un générateur récursif de cette manière est que vous ne créez pas de résultats intermédiaires en mémoire ou ne calculez pas les valeurs que vous n'utilisez pas. Si vous avez besoin de calculer beaucoup de permutations, c'est probablement une bonne idée.

def caps_permutations(sequence):
    if len(sequence) == 0:
        raise ValueError()
    elif len(sequence) == 1:
        element = sequence[0]
        yield [element.lower()]
        yield [element.upper()]
    else:
        # Copy to avoid mutating input sequence
        inner_sequence = copy.copy(sequence)
        element = inner_sequence.pop(0)
        for inner_permutation in caps_permutations(inner_sequence):
            yield [element.lower()] + inner_permutation
            yield [element.upper()] + inner_permutation

text=['a','b','c','d','e','f']

for permutation in caps_permutations(text):
    print(permutation)

Production attendue:

['a', 'b', 'c', 'd', 'e', 'f']
['A', 'b', 'c', 'd', 'e', 'f']
['a', 'B', 'c', 'd', 'e', 'f']
['A', 'B', 'c', 'd', 'e', 'f']
['a', 'b', 'C', 'd', 'e', 'f']
['A', 'b', 'C', 'd', 'e', 'f']
...
['A', 'B', 'C', 'D', 'E', 'F']

Vous pouvez également le faire en utilisant itertools.product .

Une façon de le faire est de générer tous les produits possibles de True et False répétés pour le nombre de caractères dans le text , et de l'utiliser pour mettre chaque caractère individuel en minuscules ou en majuscules.

from itertools import product

text = 'abcdef'

out = []
for capitalized in product([False, True], repeat=len(text)):
    out.append(''.join([char.upper() if upper else char for char, upper in zip(text, capitalized)]))

print(out)

Production:

['abcdef', 'abcdeF', 'abcdEf', 'abcdEF', 'abcDef', 'abcDeF', 'abcDEf', 'abcDEF', 'abCdef', 'abCdeF', 'abCdEf', 'abCdEF', 'abCDef', 'abCDeF', 'abCDEf', 'abCDEF', 'aBcdef', 'aBcdeF', 'aBcdEf', 'aBcdEF', 'aBcDef', 'aBcDeF', 'aBcDEf', 'aBcDEF', 'aBCdef', 'aBCdeF', 'aBCdEf', 'aBCdEF', 'aBCDef', 'aBCDeF', 'aBCDEf', 'aBCDEF', 'Abcdef', 'AbcdeF', 'AbcdEf', 'AbcdEF', 'AbcDef', 'AbcDeF', 'AbcDEf', 'AbcDEF', 'AbCdef', 'AbCdeF', 'AbCdEf', 'AbCdEF', 'AbCDef', 'AbCDeF', 'AbCDEf', 'AbCDEF', 'ABcdef', 'ABcdeF', 'ABcdEf', 'ABcdEF', 'ABcDef', 'ABcDeF', 'ABcDEf', 'ABcDEF', 'ABCdef', 'ABCdeF', 'ABCdEf', 'ABCdEF', 'ABCDef', 'ABCDeF', 'ABCDEf', 'ABCDEF']

Ou en faisant le produit de tuples (char, char.upper()) :

from itertools import product

text = 'abcdef'

out = []
for chars in product(*((c, c.upper()) for c in text)):
    out.append(''.join(chars))
    
print(out)

Puisque vous avez spécifiquement demandé la récursivité, voici une façon de le faire:

def alloptions(textlist):
    if len(textlist) == 0:
        return ['']
    return [y + x for y in [textlist[0].lower(), textlist[0].upper()] for x in alloptions(textlist[1:])]

text=['a','b','c','d','e','f']
print(alloptions(text))

Lors de la conception de fonctions récursives sur des structures de données, vous inventez essentiellement un principe d'induction. Il y a donc deux ingrédients dont vous avez besoin:

  1. Quel est le cas de base? C'est le résultat lorsque vous ne pouvez plus décomposer votre entrée.
  2. Quel est le cas inductif? C'est ce que vous faites à une entrée complexe, en supposant que ses parties ont déjà été traitées .

Avec un peu d'expérience, vous savez généralement immédiatement quels sont les cas, structurellement. Pour les listes, c'est presque toujours (la liste vide) et (opérant sur le premier élément, étant donné le ou les résultats récursifs sur le reste des éléments).

Pour le traduire en problème concret:

  1. Nous savons que le résultat pour une chaîne vide est la chaîne vide.
  2. Si nous avons une chaîne non vide, nous prenons toutes les combinaisons possibles pour la première lettre (majuscules et minuscules). Ensuite, nous supposons que nous connaissons déjà tous les résultats pour le reste de la chaîne, et formons simplement le produit avec les résultats en première lettre.

Dans du code:

def upper_lower(chars): 
    if len(chars) > 0: 
        first, *rest = chars 
        for combo in upper_lower(rest): 
            yield first.lower() + combo 
            yield first.upper() + combo 
    else: 
        yield ''  

Un travail élégant sur des entrées itérables générales et sans allocation intermédiaire serait également bien, mais je n'en ai pas trouvé une courte et lisible.

Related