Sir-Sorg
Sir-Sorg

Reputation: 315

Covert Nested Loop to Recursive Function in Python

Hello I will Write All State of text with upper and lower mode one by one and i can do it by nested for but its just useful for text with 6 charector i will convert it to Recursive can anyone help?

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))

The Output is in Below and its Correct but I will do it with Recursive :

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 Can Anyone Help?

Upvotes: 0

Views: 160

Answers (5)

Aguy
Aguy

Reputation: 8059

Since you asked specifically for recursion, this is one way to do this:

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))

Upvotes: 0

phipsgabler
phipsgabler

Reputation: 20960

When designing recursive functions on data structures, you basically invent an induction principle. So there's two ingredients you need:

  1. What is the base case? This is the result when you can't break down your input anymore.
  2. What is the inductive case? This is what you do to a complex input, assuming its parts have already been handled.

With a bit of experience, you usually know immediately what the cases are, structurally. For lists, it's almost always (the empty list) and (operating on the the first element, given the recursive result(s) on the rest of the elements).

To translate it to the concrete problem:

  1. We know that the result for an empty string is the empty string.
  2. If we have a nonempty string, we take all possible combinations for the first letter (uppercase and lowercase). Then we assume we already know all results for the rest of the string, and simply form the product with the first-letter results.

In 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 ''  

An elegant working on general iterable inputs and withouth intermediate allocation would be nice as well, though, but I haven't found a short, readable one.

Upvotes: 0

Thierry Lathuille
Thierry Lathuille

Reputation: 24242

You could also do it using itertools.product.

One way to do it is to generate all possible products of True and False repeated for the number of characters in text, and use that to put each individual character in lowercase or uppercase.

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)

Output:

['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']

Or by making the product of 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)

Upvotes: 0

Kvothe
Kvothe

Reputation: 396

You can use recursion for this, see below. The main benefit of using a recursing generator in this way is that you don't build up intermediate results in memory or calculate values you don't end up using. If you need to calculate a lot of permutations that is probably a good idea.

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)

Expected output:

['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']

Upvotes: 0

Ruben Helsloot
Ruben Helsloot

Reputation: 13129

I wouldn't use recursion per se, but use a while loop instead:

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)

Upvotes: 1

Related Questions