Young performers joyfully dance on a colorful stage during daytime event.

Dynamic programming

Let’s understand memoizaion with example problem

Problem:
Write a function fib that takes in a number argument, n, and returns the n-th number of the Fibonacci sequence.
The 0-th number of the sequence is 0.
The 1-st number of the sequence is 1.
To generate further numbers of the sequence, calculate the sum of previous two numbers.
Solve this recursively.

# test 00
fib(0); # -> 0

Approach:

What is fibonacci series?

{20f178ad be7a 4605 9ec0 0cd193fcc102}

When we try to solve this problem using recursion, it looks like below. The return values 0 & 1 seen in this picture are return values from base cases.

{61aeb2e1 656c 45e9 99c4 19cd675efab4}

Like we discussed in the base case; it’s time to think how to build the final solution with the help of answers from base case.
That is; by adding the results of base cases.
Once you are aware of how to solve the problem, apply memoization. What is memoization? Observe the below tree & fib(4) is calculated twice for example. Not only feb(4), but many other sub problems are also calculated twice. Can you avoid it? How about storing the reuslt of sub problem when you calculate it for the first time & then each time you try to solve a sub problem, first check whether it’s already solved in / not,
if solved : pick the stored result.
if not solved : solve it & store the result.
That’s memoization..

{08fe8ab7 868b 469e a71f 247f48e85997}

Let’s see memoization in action for 1 scenario. We started calculating the result from base cases as shown below & on the process, we calculated result for node 2.
Will check the memo for result of node 2 –> since it’s first time, will not find it –> hence, insert into memo.
The work continues & will again get a need to calculate the result of node 2 during which, the result can be find in the memo & hence instead if calculating once again, will pick the result from memo.

{ac1cadc1 f753 4dad 878f 5ffe6128b770}

It’s time to code the same thing what we diccussed above..
First, let’s solve the problem with out memoization.

def fib(n):
  if n == 0 or n == 1:
    return n
  return fib(n - 1) + fib(n - 2)

Now, integrate the memoization into this problem.

def fib(n):
    memo = {}
    return _fib(n, memo)

def _fib(n, memo):
    if n == 0 or n == 1:
        return n
    if n in memo:
        return memo[n]
    memo[n] = _fib(n - 1, memo) + _fib(n - 2, memo)
    return memo[n]
Sum possible

Problem
Write a function sum_possible that takes in an amount and a list of positive numbers. The function should return a boolean indicating whether or not it is possible to create the amount by summing numbers of the list. You may reuse numbers of the list as many times as necessary.
You may assume that the target amount is non-negative.

# test 00
sum_possible(8, [5, 12, 4]) # -> True, 4 + 4

Approach
Let’s see how can be solve the below example of amount 4 can be formed with the numbers 1, 2 & 3.
Here bigger problem is 4
Our goal is to make this problem smaller & smaller –> From 4, we can subtract 1, 2 & 3, which results in smaller problems –> Then, go on subtracting the numbers from that sub problmes until 0 is reached. Hitting 0 means that the number is formed.
And while solving the problem, we also need to take care that the numbers are subtracted from sub problems, result should not be -ve.

{e193a129 28e5 4aa3 863c 06edb6db2d54}

And, how do you know the result?
That’s nothing but the numbers along the branch of tree.

{08f6aca5 ea75 4ff7 a520 ae013d8735cc}

Solution

def sum_possible(amount, numbers):
    return _sum_possible(amount, numbers, {})

def _sum_possible(amount, numbers, memo):
    if amount in memo:
        return memo[amount]
    if amount < 0:
        return False
    if amount == 0:
        return True
    for num in numbers:
        if _sum_possible(amount - num, numbers, memo):
            memo[amount] = True
            return True
    memo[amount] = False
    return False