I have made two implementations of a backtracking algorithm to solve this challenge on Codewars ( https://www.codewars.com/kata/5a6b24d4e626c59d5b000066 ) . My problem is that I grasp why the first implementation works but not why the second one . I think that my problem is in the return statement in the last line with the hash signs . I don't get why when the backtracking is terminating , since a solution was found, the second implementation returns the right solution instead of an empty list . Is it because when the solution is passed to the previous call of the function his value in the previous call ( which was with an element less ) is overwritten with the complete solution ?
First :
def square_sums_row(n):
a , sol = [ x for x in range(1,n+1)] , []
def recurse(a,sol):
if a == [] :
return sol
for i,x in enumerate(a) :
if is_valid(x,sol) :
sol.append(x)
iterate = recurse(a[:i]+a[i+1:],sol) ###########
if iterate : ###########
return iterate #########
sol.pop(-1)
return False
def is_valid(x,sol):
if len(sol) == 0 :
return True
if (( sol[-1] + x )**0.5) % 1 == 0:
return True
return False
return recurse(a,sol)
Second :
def square_sums_row(n):
s , sol = [ x for x in range(1,n+1)] , []
def recurse(s,sol):
if s == [] :
return sol
for i,x in enumerate(s) :
if is_valid(x,sol) :
sol.append(x)
if recurse(s[:i]+s[i+1:],sol) : ###########
return sol ##############
sol.pop(-1)
return False
def is_valid(x,sol):
if len(sol) == 0 :
return True
if (( sol[-1] + x )**0.5) % 1 == 0:
return True
return False
return recurse(s,sol)
To expand on the other answer, there is only one list object sol
that is being passed around and returned. It's never copied. Here's another solution to emphasise that point. Here sol
is not an argument anywhere, it's just taken from the closure, and only booleans are returned by the inner functions.
def square_sums_row(n):
sol = []
def recurse(s):
if s == []:
return True
for i, x in enumerate(s):
if is_valid(x):
sol.append(x)
iterate = recurse(s[:i] + s[i + 1:]) ###########
if iterate: ###########
return True
sol.pop(-1)
return False
def is_valid(x):
if len(sol) == 0:
return True
if ((sol[-1] + x) ** 0.5) % 1 == 0:
return True
return False
if recurse([x for x in range(1, n + 1)]):
return sol
else:
return False