0

I have a list

s = ["h", "e", "l", "l", "o"]

I try to reverse in place using a recursive function

def reverse_string4(arr, start=0):
    while start < len(arr):
        arr.insert(start, arr.pop())
        reverse_string4(arr, start + 1)

the above goes into an infinite loop, but this one below works

def reverse_string2(arr, start=0):
    if start == len(arr)-1:
        pass
    else:
        arr.insert(start, arr.pop())
        reverse_string2(arr, start + 1)

I am confused when debug start variable increases, then why is not terminating while loop?

5
  • 2
    The while is an infinite loop. There's nothing in the body of the loop that would make the while condition false. Why do you think you need a while loop and recursion? Commented Apr 26, 2021 at 9:39
  • then when start becomes 5 why is not terminating the while loop? Commented Apr 26, 2021 at 9:40
  • Use if instead of while loop because there is no need of while looping in recursion. if start < len(arr): will also work. Commented Apr 26, 2021 at 9:55
  • 1
    start does not become 5. When you recursively call reverse_string2 you create a new run of the function with its own variables and its own start. But in the original run, the start variable that the while-loop is looking at still has the same value, so it still loops. Commented Apr 26, 2021 at 9:57
  • 1
    tldr: a recursive call is not a goto. Commented Apr 26, 2021 at 9:59

1 Answer 1

1

You can easily see what's happening by adding print() statements.

def reverse_string4(arr, start=0):
    print('-> arr %s, start=%i' % (arr, start))
    while start < len(arr):
        print('start %i < len(arr) %i' % (start, len(arr)))
        arr.insert(start, arr.pop())
        print('call reverse_string()')
        reverse_string4(arr, start + 1)
        print('back from call')

Run it with reverse_string4(['h', 'e', 'l', 'l', 'o']):

-> arr ['h', 'e', 'l', 'l', 'o'], start=0
start 0 < len(arr) 5
call reverse_string()
-> arr ['o', 'h', 'e', 'l', 'l'], start=1
start 1 < len(arr) 5
call reverse_string()
-> arr ['o', 'l', 'h', 'e', 'l'], start=2
start 2 < len(arr) 5
call reverse_string()
-> arr ['o', 'l', 'l', 'h', 'e'], start=3
start 3 < len(arr) 5
call reverse_string()
-> arr ['o', 'l', 'l', 'e', 'h'], start=4
start 4 < len(arr) 5
call reverse_string()
-> arr ['o', 'l', 'l', 'e', 'h'], start=5
back from call
start 4 < len(arr) 5
call reverse_string()
-> arr ['o', 'l', 'l', 'e', 'h'], start=5
back from call
start 4 < len(arr) 5
call reverse_string()
-> arr ['o', 'l', 'l', 'e', 'h'], start=5
back from call
start 4 < len(arr) 5
call reverse_string()
-> arr ['o', 'l', 'l', 'e', 'h'], start=5
back from call
start 4 < len(arr) 5
call reverse_string()
-> arr ['o', 'l', 'l', 'e', 'h'], start=5
back from call
start 4 < len(arr) 5
call reverse_string()

See? The while condition is still true, so it stays in the while loop.

The proper fix is to use either a while loop or recursion (and then, probably return the value called by the recursive call).

Sign up to request clarification or add additional context in comments.

3 Comments

Thanks, I notice in debug window that once the start becomes 5, it goes back to 4 and that goes infinite. Then do you mean that while and recursive call should not be used together? This is how I understand it.
That's basically the gist of this, yes. It's not impossible to combine the two but if you are only just learning, probably don't even try. The standard logic is simply if (something): return recursive_call(): else: return base case and the recursion is what takes care of any (implicit) looping.
Thank you, yes I am learning and practise various exersises.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.