How to debug this recursion function python - python

I am working on this question from school, and I wrote the function I thought was the right one (we need to use recursion with no loops)
def subset_sum(numbers, target):
'''
numbers - a list of positive integers
target - a non-negative integer
returns True if the list 'numbers' has a sub-list with sum 'target',
False otherwise.
'''
# Your code for question #4 starts here
if sum(numbers[1:]) == target or target == 0:
return True
if sum(numbers[1:]) == (target - numbers[0]):
return True
if len(numbers) == 1 and numbers[0] == target:
return True
if len(numbers) == 1 and numbers[0] != target:
return False
else:
subset_sum(numbers[1:], target)
For some inputs get the right output like subset_sum([4,4,4], 12) or subset_sum([4,4,4], 8) but for subset_sum([4,4,4], 4) I get no output.
Can someone take a look and tell me what's wrong here?
When it doesn't give any output there are no errors, just blank.

You have to return the result of subset_sum in the else branch:
else:
return subset_sum(numbers[1:], target)

Related

How to remove def and incorporate the function into the code?

I am trying to remove def function since we are not allowed to use that, but I don't know how to.
def is_one_away(first: str, other: str) -> bool:
# check lengths
if len(first) != len(other):
return False
error_count = 0
for i in range(len(first)):
if first[i] != other[i]:
error_count += 1
if error_count > 1:
return False
return True
That's the def function, but I'm trying to incorporate it into my actual code.
This is the part of the code that Im trying to incorporate it into.
if is_one_away(x, y):
similarity = True
Change the returned value to the value you're assigning to similarity.
Use break to end the loop instead of return.
if len(x) != len(y):
similarity = False
else:
for i in range(len(x)):
if x[i] != y[i]:
similarity = False
else:
similarity = True
There's no need for error_count, since you always return as soon as you find a non-match.

Return immediately for recursive calls

Problem Statement:
You are given an integer array nums. You are initially positioned at the array's first index, and each element in the array represents your maximum jump length at that position. Return true if you can reach the last index, or false otherwise.
How can I change my code so that it returns immediately when I have found a path that works for this problem instead of going through all the recursive calls that I have made previously
def canJump(self, nums: List[int]) -> bool:
solve = [False]
def backtrack(i):
if solve[0] == True:
return
if i == len(nums)-1:
solve[0] = True
return
if i >= len(nums) or nums[i] == 0:
return
for x in range(1, nums[i]+1):
backtrack(i+x)
backtrack(0)
return solve[0]
General Form of a Recursive Function
The general form of a recursive function has two mutually exclusive types of conditions that can be met on each iteration of the recursion. These are either:
terminal conditions, or
non-terminal conditions.
Both types of condition contain a return statement.
Terminal Conditions
The return statement in terminal conditions typically takes the form return <value>.
The solution to the problem you are trying to solve requires two possible terminal conditions:
The case where you know you can reach the last index. return True
The case where you know you can NOT reach the last index. return False
Non-Terminal Conditions
The non-terminal condition will occur on iterations where neither of the terminal cases are met. In this situation, you will call the recursive function and return what it returns.
This answer covers terminal and non-terminal conditions in more detail.
Example
Consider a recursive function that sums the numbers of an array.
def sum(position, array, end):
if(position == end): # terminal condition
return 0
else: # non-terminal condition
return array[position] + sum(position+1, array, end)
Another Example
Depending on any constraints to your problem that I might have missed, a solution might be the following:
def jump(current_position, nums, finish_line):
"""
greedy algorithm:
choose the next position with the largest sum of (jump_range + index)
"""
jump_range = nums[current_position]
choice = current_position + jump_range
if(jump_range == 0): # terminal condition
return False
if(choice >= finish_line): # terminal condition
return True
else: # non-terminal condition
utility = 0
for next_position in range(current_position+1, jump_range+1):
next_jump_range = nums[next_position]
if(utility <= next_position + next_jump_range):
utility = next_position + next_jump_range
choice = next_position
return jump(choice, nums, finish_line)
input1 = [2,0,0,10,3]
input2 = [2,3,0,10,3]
current_position = 0
finish_line = len(input1)
print(jump(0, input1, finish_line)) # False
finish_line = len(input2)
print(jump(0, input2, finish_line)) # True
The most noteworthy difference from your solution is that return statements always return a value.
How can I change my code so that it returns immediately when I have found a path that works for this problem instead of going through all the recursive calls that I have made previously
One particularly straightforward way is to throw an exception, which will immediately unwind the stack.
def can_jump(nums: list[int]) -> bool:
if not nums:
return False
class _Success(Exception):
pass
def backtrack(i):
if i >= len(nums):
return
if i == len(nums) - 1:
raise _Success()
for x in range(1, nums[i] + 1):
backtrack(i + x)
try:
backtrack(0)
return False
except _Success:
return True
We create a local exception type called _Success that the backtracking search can throw to indicate that it found a solution.
If it never finds a solution, the backtrack function will simply return and the return False line will run. Otherwise, it will raise _Success() and then the return True line will run.

Upper bound equal to lower in Python range

Can someone please explain to me why this code works for 2 as well:
def is_prime_v1(n):
'''Return True if 'n' is prime. False otherwise.'''
if n == 1:
return False
for d in range(2,n):
if n % d == 0:
return False
return True
when the code gets to
for d in range(2,n):
if n % d == 0:
return False
return True
Would it not see this as start at 2 but go up to and do not include 2?
This does not make complete sense to me.
The formula works but if you try and create a list on that range like so:
x = list(range(2,2))
You get an empty list.
Please could anyone explain this to me? Does it work for two as well because it would not be able to do the below on range(2,2) and then moves down to return True?
if n % d == 0:
return False
return True
Thanks
because for loop is never executed , list(range(2,2)) == [], so the program didn't iterate over range and directly proced to return True statement
Your assumption is correct. The upper value of the range function is not put through the for loop. To overcome this, you could just add or n == 2 to the third line of your program.

How to write this iterative function to be recursive?

I need to write this iterative function to do the same thing but it must be recursive.
def task1(string: str):
for i in range(len(string)):
if string[i] != string[len(string) - i - 1]:
return False
return True
This is what i tried but it does not work.
def task1_recursion(string: str):
print(string)
if len(string) > 1:
if string[0] == task1_recursion(string[1::1]):
return True
else:
return False
else:
return string
My code seems to one the last recursion return string "" and that makes it to return False.
Just check the tip and the tail, continue with the string without them:
def task1_recursion(string: str):
# recursion base condition (exit condition)
if len(string) <= 1:
return True
# unpack values
first, *_, last = string
# check if they are different
if first != last:
return False
# if not continue checking the remaining string
return task1_recursion(string[1:-1])
If I understand correctly you want to check if a string is symmetric with the code in task1. My solution is below:
def fct(s: str, i: int):
if len(s) <= 1 or i == len(s):
return True
return s[i] == s[len(s) - 1 - i] and fct(s, i + 1)
I tested and fct produces the same result as task1. It needs an additional parameter for the index though. But you can wrap it inside another function if you want the parameter to include only the input string. i is always set to 0 when you call the function, e.g. fct("ABCCBA", 0).

Recursive function seems to be fine, but won't return False

So the function should check if a list is symmetric; if the list is empty or has one integer, it is symmetric.
Otherwise the function should check if the first and last integers are the same and go on recursively. If not, return False.
The code seems right, but I can't figure out what's wrong and why it won't return False.
def symm(lst):
t = len(lst)
if t == 0 or 1:
return True
if t>1:
if lst[0] == lst[-1]:
return symm(lst[1:-2])
else:
return False
print symm([6,6,6,6,7])
if t == 0 or 1: is always true since this is read as if (t == 0) or (1): and 1 is always going to be true.
Change to: if t in [0,1]: or simply if len(lst) < 2:

Categories