I am following a dynamic programming course of return a list of number if you can sum up to a target and running into this problem.
Here is my first try:
def howSum(target, arr, memo={}):
if target in memo: return memo[target]
if target == 0: return []
if target < 0 : return None
shortest = None
for i in arr:
remainderCombination = howSum(target-i, arr, memo)
if remainderCombination is not None:
remainderCombination.append(i)
combination = remainderCombination.copy()
if (shortest == None or len(shortest) > len(combination)):
shortest = combination.copy()
memo[target] = shortest
return shortest
print(howSum(8,[1,2,3,5],{}))
which returns the undesirable result of [5, 1, 1, 1].
On my second try, I did like this:
def howSum(target, arr, memo={}):
if target in memo: return memo[target]
if target == 0: return []
if target < 0 : return None
shortest = None
for i in arr:
remainderCombination = howSum(target-i, arr, memo)
if remainderCombination is not None:
combination = remainderCombination.copy()
combination.append(i)
if (shortest == None or len(shortest) > len(combination)):
shortest = combination.copy()
memo[target] = shortest
return shortest
print(howSum(8,[1,2,3,5],{}))
and receive the right result of [5, 3].
So basically I only changed the order of copy() and append() but I do not understand why it resulted in different answer.
Edit So as @matszwecja has commented, this is a generic Python's mutable problem
Ah yes, of course. "Least Astonishment" and the Mutable Default Argument