Why is the recursion not working as expected when the start and end values are fine?
Question:
I am trying to use recursion to create the following effect:
FORWARD
ORWARD
RWARD
WARD
ARD
RD
D
But the python code below is producing some unexpected results:
def forward(string,start,end):
if start>end:
return
start+=1
print(string, start, end)
return forward(string[start:end+1],start,end)
forward("FORWARD",0,6)
The output of the above code is:
FORWARD 0 6
FORWARD 1 6
ORWARD 2 6
WARD 3 6
D 4 6
5 6
6 6
I have also printed the start and end values and there seems to be no problem with them. What am I missing?
Answers:
The problem is that you pass only a part of the string. In the next iteration, you pass en even greater start value, which makes the string even smaller.
If you want the string to become smaller by 1 character, slice it only by one character, not start
characters.
Passing end+1
as part of the slice might be problematic. You can leave that part empty, if you want the substring until the end.
Also, since the method does not return anything (return type is None
basically), you don’t need the return statement.
forward(string[1:],start,end)
Another option would be to leave the string intact and print only a part of it:
print(string[start:], start, end)
forward(string,start,end)
It looks like you are at a point where you want to learn how to debug small programs and use a decent IDE with debugging capabilities, such as PyCharm. They offer a free community edition.
One way to fix this is to pass the entire string in the recursive call, only incrementing the start value by one.
def forward(string,start,end):
if start>end:
return
print(string[start:end+1], start, end)
return forward(string,start+1,end)
When taking or removing substrings from the beginning or ending of a string python slice notation should look simple and clear, e.g.
def forward(string):
if string:
print(string)
forward(string[1:])
if __name__ == '__main__':
forward('forward')
string[n:]
skips the first n characters and returns the remaining characters. string[:-n]
returns everything but the last n characters. string[-n:]
returns just the last n characters. Of course there are many more variations but getting a little bit of expertise and comfort with the slice concepts will go a long way toward producing clear python string manipulation code.
The problem is that reduce the string by the number which start
is meaning, you don’t make the string one character smaller each time. Try this instead:
def forward(string):
print(string)
if len(string) == 1:
return
forward(string[1:])
forward("FORWARD")
What is the output/return of each iteration?
The only change over recursion is the printed output, not the return.
The return value is always None
.
That’s why we only need to modify the print-statement’s argument string
by slicing.
What changes with each iteration?
Put it other: What is the loop variable, what the recursive argument?
However, the string
passed to the recursing function call stays unchanged. Here the start
offset increases.
What is the exit-condition?
Also the stop- or exit-condition should be adjusted to "end reached" instead overlap.
def forward(string,start,end):
print(string[start:], start, end)
if start == end: # not greater than, but equals means no char inbetween
return
return forward(string,start+1,end) # string argument stays same, only start offset increases
forward("FORWARD",0,6)
print("---")
forward("FORWARD",1,6)
print("---")
forward("FORWARD",1,5)
Prints:
FORWARD 0 6
ORWARD 1 6
RWARD 2 6
WARD 3 6
ARD 4 6
RD 5 6
D 6 6
---
ORWARD 1 6
RWARD 2 6
WARD 3 6
ARD 4 6
RD 5 6
D 6 6
---
ORWARD 1 5
RWARD 2 5
WARD 3 5
ARD 4 5
RD 5 5
Input validation?
What happens when
start < 0
or start > len(string)-1
?
end > len(string)-1
or end < start
?
string is None
?
I am trying to use recursion to create the following effect:
FORWARD
ORWARD
RWARD
WARD
ARD
RD
D
But the python code below is producing some unexpected results:
def forward(string,start,end):
if start>end:
return
start+=1
print(string, start, end)
return forward(string[start:end+1],start,end)
forward("FORWARD",0,6)
The output of the above code is:
FORWARD 0 6
FORWARD 1 6
ORWARD 2 6
WARD 3 6
D 4 6
5 6
6 6
I have also printed the start and end values and there seems to be no problem with them. What am I missing?
The problem is that you pass only a part of the string. In the next iteration, you pass en even greater start value, which makes the string even smaller.
If you want the string to become smaller by 1 character, slice it only by one character, not start
characters.
Passing end+1
as part of the slice might be problematic. You can leave that part empty, if you want the substring until the end.
Also, since the method does not return anything (return type is None
basically), you don’t need the return statement.
forward(string[1:],start,end)
Another option would be to leave the string intact and print only a part of it:
print(string[start:], start, end)
forward(string,start,end)
It looks like you are at a point where you want to learn how to debug small programs and use a decent IDE with debugging capabilities, such as PyCharm. They offer a free community edition.
One way to fix this is to pass the entire string in the recursive call, only incrementing the start value by one.
def forward(string,start,end):
if start>end:
return
print(string[start:end+1], start, end)
return forward(string,start+1,end)
When taking or removing substrings from the beginning or ending of a string python slice notation should look simple and clear, e.g.
def forward(string):
if string:
print(string)
forward(string[1:])
if __name__ == '__main__':
forward('forward')
string[n:]
skips the first n characters and returns the remaining characters. string[:-n]
returns everything but the last n characters. string[-n:]
returns just the last n characters. Of course there are many more variations but getting a little bit of expertise and comfort with the slice concepts will go a long way toward producing clear python string manipulation code.
The problem is that reduce the string by the number which start
is meaning, you don’t make the string one character smaller each time. Try this instead:
def forward(string):
print(string)
if len(string) == 1:
return
forward(string[1:])
forward("FORWARD")
What is the output/return of each iteration?
The only change over recursion is the printed output, not the return.
The return value is always None
.
That’s why we only need to modify the print-statement’s argument string
by slicing.
What changes with each iteration?
Put it other: What is the loop variable, what the recursive argument?
However, the string
passed to the recursing function call stays unchanged. Here the start
offset increases.
What is the exit-condition?
Also the stop- or exit-condition should be adjusted to "end reached" instead overlap.
def forward(string,start,end):
print(string[start:], start, end)
if start == end: # not greater than, but equals means no char inbetween
return
return forward(string,start+1,end) # string argument stays same, only start offset increases
forward("FORWARD",0,6)
print("---")
forward("FORWARD",1,6)
print("---")
forward("FORWARD",1,5)
Prints:
FORWARD 0 6
ORWARD 1 6
RWARD 2 6
WARD 3 6
ARD 4 6
RD 5 6
D 6 6
---
ORWARD 1 6
RWARD 2 6
WARD 3 6
ARD 4 6
RD 5 6
D 6 6
---
ORWARD 1 5
RWARD 2 5
WARD 3 5
ARD 4 5
RD 5 5
Input validation?
What happens when
start < 0
orstart > len(string)-1
?end > len(string)-1
orend < start
?string is None
?