• Jobs
  • About Us
  • professionals
    • Home
    • Jobs
    • Courses and challenges
  • business
    • Home
    • Post vacancy
    • Our process
    • Pricing
    • Assessments
    • Payroll
    • Blog
    • Sales
    • Salary Calculator

0

277
Views
Dynamic programming code works in javascript but not in python

I am learning Dynamic Programming from freecodecamp, the instructor is using JavaScript and i know python so i am converting the logic in python.

Long story short, this problem's JavaScript implementation is working fine, but my python implementation is giving strange output.

I have matched the syntax many times and verified the logic, i can't point out where i am going wrong. Any help would be appreciated.

Problem Statement: Create a program to find the smallest sub-array of integers whose sum is equal to targetsum.

JavaScript Implementation:

const bestsum = (targetsum, numbers, memo={}) => {
    if (targetsum in memo) return memo[targetsum];
    if (targetsum === 0) return [];
    if (targetsum <0) return null;
    
    let shortestcomb = null;
    
    for (let num of numbers){
        const remainder = targetsum - num;
        const remaindercomb = bestsum(remainder, numbers, memo);
        if (remaindercomb !== null){
            const combination = [...remaindercomb, num];
            if (shortestcomb===null || combination.length < shortestcomb.length){
                shortestcomb = combination;
            }
        }
    }
    memo[targetsum] = shortestcomb;
    return shortestcomb;
}
console.log(bestsum(7, [2, 4, 3]));
console.log(bestsum(100, [1, 2, 5, 25]));

Output:

[ 3, 4 ]
[ 10, 10 ]

My Python Implementation:

def bestsum(targetsum, arr, memo=None):
    if memo is None:
        memo={}
    if targetsum in memo: return memo[targetsum]
    if targetsum==0: return []
    elif targetsum < 0: return None
    shortest = None 
    for i in arr:
        remainder = targetsum-i
        seq = bestsum(remainder, arr, memo)
        if seq!=None:
            seq.append(i)
            if (shortest==None or len(seq)<len(shortest)):
                shortest = seq
    memo[targetsum] = shortest
    return shortest

print(bestsum(7, [2, 4, 3]))
print(bestsum(20, [5, 10]))

Output:

[4, 3]
[10, 5, 5, 10]

The obvious answer for the second case is [10, 10] as that would sum to 20 with the least number of elements, also for the first case the JavaScript output is [3, 4] whereas python output is [4, 3], isn't it strange?

EDIT: Someone marked this question as duplicate, i followed that guide and used a placeholder in place of the mutable default argument, but the output is still the same, what is wrong now?

enter image description here

about 3 years ago · Juan Pablo Isaza
2 answers
Answer question

0

While an interactive debugger is the most general (and, often, most powerful) way of examining bugs, here a simple bit of scaffolding can reveal much. By adding a print(f"target = {targetsum}; memo = {memo}") statement just before the end of bestsum, we get:

target = 5; memo = {5: [5]}
target = 10; memo = {5: [5, 5], 10: [10]}
target = 15; memo = {5: [5, 5, 10], 10: [10, 5], 15: [10, 5]}
target = 20; memo = {5: [5, 5, 10], 10: [10, 5, 5, 10], 15: [10, 5, 5, 10], 20: [10, 5, 5, 10]}

Note how the entries for each target sum keep changing. This shouldn't happen, based on the algorithm. Looking at bestsum, the entries of memo come from seq. Looking for lines that alter seq, we find seq.append(i). This mutates the list, which is why the entries of memo keep changing, and why the final result is incorrect. The JavaScript version of bestsum creates a new list for each iteration of the loop body, which is why it doesn't suffer this bug.

Note you could translate the JavaScript directly and use the spread operator, or you could list concatenation: seq = seq + [i].

One approach that would have prevented this bug from arising would be to use an immutable type instead of a list. In Python, that would be tuple. The one wrinkle is than if using tuple concatenation, a single-element tuple must have a comma trailing the element: seq = seq + (i,).

about 3 years ago · Juan Pablo Isaza Report

0

Expanding on @outis's answer, the entries of memo are changing with each iteration, this shouldn't happen. This is happening because when you assign a list to a new variable, instead of creating a new list, python refrences the old list's address to the new one.

This creates a problem when the list is changed, as the changes start to show in all its copies.

Here seq is the master list

shortest is copied from seq

memo[targetsum] is copied from shortest

Ideally after all the children of a recursive tree node are traversed we select the shortest path and assign it to memo[targetsum] but the value inside memo[target] changes with the changes in seq that introduces the unexpected values in memo.

It can be fixed by using an immutable data type as @outis suggested. But we can go a step further and just make a small change to this code itself.

import copy
def bestsum(targetsum, arr, memo=None):
    if memo is None:
        memo = {}
    if targetsum in memo: return copy.deepcopy(memo[targetsum])
    if targetsum==0: return []
    elif targetsum < 0: return None
    shortest = None 
    for i in arr:
        remainder = targetsum-i
        seq = bestsum(remainder, arr, memo)
        if seq!=None:
            seq.append(i)
            if (shortest==None or len(seq)<len(shortest)):
                shortest = seq
    memo[targetsum] = copy.deepcopy(shortest)
    return shortest

print(bestsum(7, [2, 4, 3]))
print(bestsum(20, [5, 10]))

Output:

[3, 4]
[10, 10]

Here we are using deepcopy from the copy module in python. deepcopy essentially creates a new list and populates it recursively with the elements of the original list, therefore the new lists are totally different from each other. Read more about it here

PS- deepcopy is probably overkill here as it is generally used for nested lists, using shallowcopy will also work fine here.

Shallowcopy syntax-

newlist = oldlist.copy()
about 3 years ago · Juan Pablo Isaza Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Our process Sales
Legal
Terms and conditions Privacy policy
© 2025 PeakU Inc. All Rights Reserved.

Andres GPT

Recommend me some offers
I have an error