Search code examples
pythonmemoization

Python: Memoization can't be called in Function


the memoization can't be initiated. if I make it memoglobal, then the subsequent print function will take stored memo during the first print. Please advise,

def howsumhelper(targetsum,numbers):
      memo = dict() #this memoization will not initiate. Why?
      return howsum(targetsum,numbers,[])


def howsum(targetsum,numbers,combo):
      print("Debug==",memo)
      if targetsum in memo: return memo[targetsum]
      if targetsum == 0:return combo
      if targetsum < 0: return None

      for number in numbers:
            remainder = targetsum - number
            if howsum(remainder,numbers,combo) != None:
                  combo.append(number)
                  memo[targetsum] = combo
                  return combo
      memo[targetsum] = None
      return None

print(howsumhelper(7,[3,4])) #output should be [3,4]
print(howsumhelper(8,[2,3])) #output should be [2,2,2,2]
print(howsumhelper(7,[2,4])) #output should be None

Solution

  • Suggest following changes

    • Make memo a mutable default argument of howsum (to make it callable in function)
    • You don't need howsumhelper

    Reference--Efficient memorization in Python--using posted solution #2

    Revised Code

    def howsum(targetsum,numbers,combo=None,memo=None):
          # Initiaze default arguments
          if combo is None:
            combo = []
          if memo is None:
            memo = {}
            
          #print("Debug==",memo)
          if targetsum in memo: return memo[targetsum]
          if targetsum == 0:return combo
          if targetsum < 0: return None
    
          for number in numbers:
                remainder = targetsum - number
                if howsum(remainder,numbers,combo,memo) != None:
                      combo.append(number)
                      memo[targetsum] = combo
                      return combo
          memo[targetsum] = None
          return None
    
    print(howsum(7,[3,4])) #output should be [3,4] #actually or [4, 3]
    print(howsum(8,[2,3])) #output should be [2,2,2,2]
    print(howsum(7,[2,4])) #output should be None
    

    Output

    [4, 3]
    [2, 2, 2, 2]
    None
    

    Explanation

    Function signature is : howsum(targetsum,numbers,combo=None,memo=None):

    Arguments a value in function definition are called default arguments. So combo, and memo are have default arguments.

    Python's default arguments are evaluated once when the function is defined, not each time the function is called.

    Default values are used only when actual values are passed.

    Thus:

    howsum(7,[3,4]) # uses default values, so called with combo = None and memo = None
    howsum(8,[2,3]) # uses default values, so called with combo = None and memo = None
    howsum(7,[2,4]) # uses default values, so called with combo = None and memo = None
    

    But:

    howsum(remainder,numbers,combo,memo) # does not use defaults for combo and memo
                                         # since we are passing values for these arguments