4

I am new at python and very bad at thinking in a recursive way. This code gives me an IndexError: string index out of range. And I have no idea how to correct it.

def get_permutations(sequence):

    def permutationhelp(sequence,chosen):

        if sequence=="":
            print(chosen)

        else:

            for i in range(len(sequence)):
                c= sequence[i]
                chosen +=c
                sequence=sequence[i+1:]
                permutationhelp(sequence,chosen)
                sequence=c+sequence
                chosen=chosen[:-1]

    def permutation(sequence):
        permutationhelp(sequence,"")


    return permutation(sequence)

Example:

get_permutations('abc')
['abc', 'acb', 'bac', 'bca', 'cab', 'cba']

The Traceback is this:

Traceback (most recent call last):
  File "soRecursivePermutations.py", line 25, in <module>
    get_permutations('abc')
  File "soRecursivePermutations.py", line 23, in get_permutations
    return permutation(sequence)
  File "soRecursivePermutations.py", line 20, in permutation
    permutationhelp(sequence,"")
  File "soRecursivePermutations.py", line 12, in permutationhelp
    c= sequence[i]
IndexError: string index out of range
quamrana
  • 37,849
  • 12
  • 53
  • 71
Em Rul
  • 57
  • 5
  • 1
    Please update your question with the way you call the function, the input data and expected output data, and the full text of the error trace that you are seeing. – quamrana Mar 14 '19 at 15:35
  • Another thing that would be helpful for us, is if you could provide what you expect to happen? I.e. What should be the result when you call `get_permutations()`. – Aaron N. Brock Mar 14 '19 at 15:39

5 Answers5

2

Should strongly consider to use:

import itertools

for p in itertools.permutations("abc"):
    print(''.join(p))
# abc
# acb
# bac
# bca
# cab
# cba

Or if you want to store in list:

perm = [''.join(p) for p in itertools.permutations('abc')]
Vlad
  • 8,225
  • 5
  • 33
  • 45
  • 1
    I believe OP is trying to learn the *recursive* way of doing this. Do you have an answer for that? – Austin Mar 14 '19 at 15:54
  • 1
    thanks, but I am new. And I am trying to understand the way how recursion work and how I can think recursive. I don't want to import itertools – Em Rul Mar 14 '19 at 15:56
  • This is correct, but the OP appears to want a recursive solution – Magnus Mar 14 '19 at 15:57
2

The reason for your Traceback is here:

sequence=sequence[i+1:]
permutationhelp(sequence,chosen)
sequence=c+sequence

The first line leaves sequence with just the end of the string. and the third line only adds one character back onto sequence, so sequence gets shorter as you go through the loop.

However, this is probably the program you were looking for:

# https://stackoverflow.com/a/53088155/4834
def remove_at(i, s):
    return s[:i] + s[i + 1:]

def permutationhelp(sequence, chosen, collect):
    if sequence == "":
        collect.append(chosen)
    else:
        for i,c in enumerate(sequence):
            permutationhelp(remove_at(i, sequence), chosen + c, collect)

def get_permutations(sequence):
    collect = []
    permutationhelp(sequence, "", collect)
    return collect

print(get_permutations('abc'))

Output:

['abc', 'acb', 'bac', 'bca', 'cab', 'cba']
quamrana
  • 37,849
  • 12
  • 53
  • 71
1

@quamrana has given the good explain. Here I think the following codes is more helpful for OP to understand his error and the recursive algorithm.

def get_permutations(sequence):
    def permutationhelp(sequence, chosen):
        if sequence == "":
            print(chosen)
        else:
            for i in range(len(sequence)):
                c = sequence[i]
                chosen += c
                sequence = sequence[:i] + sequence[i+1:]
                permutationhelp(sequence,chosen)
                sequence = sequence[:i] + c + sequence[i:]
                chosen = chosen[:-1]

    def permutation(sequence):
        permutationhelp(sequence,"")

    return permutation(sequence)

testcase

>>> get_permutations('abc')
abc
acb
bac
bca
cab
cba
Fogmoon
  • 569
  • 5
  • 16
0

I think you may want to approach it differently. From following your code, I think you just want to reduce the list and print out the result to the console when you run out of sequence, but I am not seeing any logic for actual permutation. Forgive me if it's there and I missed it.

Here is how I think about it. Start with first element "a", keep an index "i" to pass it into your helper function then swap with a list that doesn't include "a" so in this case it would be "b and c." Then concat that with your "i" index char, and also unswap list one with that same char again. This would print out "abc and acb."

Then I would increment the "i" and call your helper again. So now your element is "b" and swap list is "a and c" and produce "bac" and "bca". Then increment and repeat again, which produce "cab" and "cba". You can have your recursion base case as i being same as len(sequence). Hopefully, I didn't lose you anywhere. I didn't code it because I figured you are trying to learn by doing. Good Luck!

Pyrogrammer
  • 173
  • 1
  • 12
0

I had to copy it to find out the issue, the exception clearly says that you were trying to access an index that is longer than the provided array.

I edited few things in your solution.

  1. I stopped the "chosen" variable reliance in the recursion

  2. I made it return a list of the results.

    def get_permutations(sequence):
    
     def permutationhelp(sequence):
       if len(sequence) == 1:
        return sequence
    result = []
    for i in range(len(sequence)):
        c = sequence[i]
        remaining = sequence[:i] + sequence[i+1:]
        for perm in permutationhelp(remaining):
            result.append(c + perm)
    
    return result
    
    def permutation(sequence):
      result = permutationhelp(sequence)
      print(result)
    
    
    return permutation(sequence)
    
    get_permutations('abc')
    

result:

['abc', 'acb', 'bac', 'bca', 'cab', 'cba']
Ramy M. Mousa
  • 5,727
  • 3
  • 34
  • 45