Related
I am new in dynamic programming..
This is a python code for finding shortest combination of numbers that add up to exactly the target sum using memoization.
global memo
memo={}
def bestSum(targetSum,arr):
if targetSum in memo:
return memo[targetSum]
#Base conditions
if targetSum==0:
return []
if targetSum<0:
return None
# Branching statments
shortestCombination=None
for i in arr:
remainder_combination=bestSum(targetSum-i,arr)
if remainder_combination != None:
combination=remainder_combination
combination.append(i)
if shortestCombination ==None or len(shortestCombination)>len(combination):
shortestCombination=combination
memo[targetSum]=shortestCombination
return shortestCombination
print(bestSum(10,[1,4,5]))
But the output was this
[4, 1, 4, 1, 5, 1]
whereas the correct output is
[5,5]
if i comment the memoization statements the output will be correct..
This is the python code without memoization for the same problem...
# global memo
# memo={}
def bestSum(targetSum,arr):
# if targetSum in memo:
# return memo[targetSum]
#Base conditions
if targetSum==0:
return []
if targetSum<0:
return None
# Branching statments
shortestCombination=None
for i in arr:
remainder_combination=bestSum(targetSum-i,arr)
if remainder_combination != None:
combination=remainder_combination
combination.append(i)
if shortestCombination ==None or len(shortestCombination)>len(combination):
shortestCombination=combination
# memo[targetSum]=shortestCombination
return shortestCombination
print(bestSum(10,[1,4,5]))
The above code gave me the correct output.
The correct output is also obtained in java script for the same problem with memoization by using object
const bestSum=(targetSum,numbers,memo={})=>{
if(targetSum in memo) return memo[targetSum];
if(targetSum===0) return [];
if(targetSum<0) return null;
let shortestCombination =null;
for (let num of numbers){
reminderCombination=bestSum(targetSum-num,numbers,memo);
if(reminderCombination !==null){
const combination=[...reminderCombination,num]
if(shortestCombination===null || combination.length< shortestCombination.length){
shortestCombination=combination
}
}
}
memo[targetSum]=shortestCombination
return shortestCombination
};
console.log(bestSum(10,[1,4,5]))
Few more examples
print(bestSum(7,[3,4,7]))
print(bestSum(20,[1,2,3,4,5,10]))
print(bestSum(3,[3,2,1]))
Correct outputs
[7]
[10, 10]
[3]
Wrong outputs when memoization is used
[7]
[10, 1, 1, 2, 1, 2, 3, 2, 3, 4, 3, 4, 5, 4, 5, 5, 10]
[3, 4, 2, 3, 5, 10, 1, 1, 2, 1, 2, 3, 2, 3, 4, 3, 4, 5, 4, 5, 5]
Thank you!
We have to use copy() method in order to copy a list, without using it we are referencing the list not coping.
memo={}
def bestSum(targetSum,arr):
if targetSum in memo:
return memo[targetSum]
if targetSum==0:
return []
if targetSum<0:
return None
shortestCombination=None
for i in arr:
remainder_combination=bestSum(targetSum-i,arr)
if remainder_combination != None:
combination = remainder_combination.copy()
combination.append(i)
if shortestCombination ==None or len(shortestCombination)>len(combination):
shortestCombination=combination.copy()
memo[targetSum]=shortestCombination
return shortestCombination
print(bestSum(10,[1,4,5]))
My implementation:
def merge_sort(arr):
if len(arr) <= 1:
return arr
left = arr[:len(arr)//2]
right = arr[len(arr)//2:]
merge_sort(left)
merge_sort(right)
return merge(left, right)
def merge(left, right):
leftI = rightI = 0
merged = []
while (leftI < len(left) and rightI < len(right)):
if left[leftI] < right[rightI]:
merged.append(left[leftI])
leftI += 1
else:
merged.append(right[rightI])
rightI += 1
merged.extend(left[leftI:])
merged.extend(right[rightI:])
return merged
if __name__ == '__main__':
arr = [1,2,5,5,9,22,6,3,6,8,1,43,5]
print(merge_sort(arr))
For some reason I am obtaining:
[1, 2, 5, 5, 6, 3, 6, 8, 1, 9, 22, 43, 5]
Working Implementation (Got from a friend):
def merge_sort(list):
list_length = len(list)
if list_length == 1:
return list
mid_point = list_length // 2
left_partition = merge_sort(list[:mid_point])
right_partition = merge_sort(list[mid_point:])
return merge(left_partition, right_partition)
def merge(left, right):
output = []
i = j = 0
while i < len(left) and j < len(right):
if left[i] < right[j]:
output.append(left[i])
i += 1
else:
output.append(right[j])
j += 1
output.extend(left[i:])
output.extend(right[j:])
return output
if __name__ == '__main__':
arr = [1,2,5,5,9,22,6,3,6,8,1,43,5]
print(merge_sort(arr))
This code yeilds:
[1, 1, 2, 3, 5, 5, 5, 6, 6, 8, 9, 22, 43]
I just can't figure out what's wrong. It'd be a great help if someone could take a few moments to help me out :)
In your merge_sort function, you do not change the values of left and right depending on what merge_sort returns.
You have :
merge_sort(left)
merge_sort(right)
Where it should be :
left = merge_sort(left)
right = merge_sort(right)
def append_sum(lst):
new_num = (lst[-1]+lst[-2])
lst.append(new_num)
new_num1 = (lst[-1]+lst[-2])
lst.append(new_num1)
new_num2 = (lst[-1]+lst[-2])
lst.append(new_num2)
return lst
print(append_sum([1, 1, 2]))
this prints [1, 1, 2, 3, 5, 8] but how do I do it N times?
And what is this "codes" actually called in coding? (I'm referring to the code that is in the function)
You can do that single operation N times just by doing:
for _ in range(N):
lst.append(lst[-1] + lst[-2])
A full example:
def append_sum(lst, count):
for _ in range(count):
lst.append(lst[-1] + lst[-2])
return lst
print(append_sum([1, 1], 10))
will generate:
[1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144]
I have this string x = "1-3,5,7,11-16,20"
and I want to transform it to a list of integers like this:
[1,2,3,5,7,11,12,13,14,15,16,20].
I wrote this code and it does work:
def page_range(x):
p = x.split(',')
d = list()
nums = list()
for i in range(0,len(p)):
d.append(p[i].find('-'))
for i in range(0,len(d)):
if d[i] >= 1:
z,y = p[i].split('-')
nums = nums + list(range(int(z),int(y)+1))
else:
nums.append(int(p[i]))
return nums
But is there a more simple way to do that?
This is one approach
x = "1-3,5,7,11-16,20"
res = []
for i in x.split(","):
if "-" in i:
s, e = i.split("-")
res.extend(range(int(s), int(e)+1))
else:
res.append(int(i))
print(res)
Output:
[1, 2, 3, 5, 7, 11, 12, 13, 14, 15, 16, 20]
This is simpler if you define a function to convert a string like 12 or 4-5 into the numbers it represents:
def str_to_nums(s):
if '-' in s:
a, b = map(int, s.split('-'))
return range(a, b+1)
else:
return int(s), # comma makes this a one-element tuple
Then you can use a list comprehension:
>>> [n for s in x.split(',') for n in str_to_nums(s)]
[1, 2, 3, 5, 7, 11, 12, 13, 14, 15, 16, 20]
This could also be tried:
ls = []
for i in x.split(','):
if i.isdigit() != 1:
r1, r2 = i.split('-')
ls.extend(range(int(r1), int(r2)+1))
else:
ls.append(int(i))
Return the sum of the numbers in the array, except ignore sections of numbers starting with a 6 and extending to the next 7 (every 6 will be followed by at least one 7). Return 0 for no numbers.
Kindly Help me with the solution. For other input values i am getting correct output value.. and also suggest me a short way to write the code.. It seems bit too long
def sum67(nums):
count=0
i=0
switch = 0
if len(nums) == 0:
count=0
else:
while i < len(nums):
if nums[i] != 6 and switch == 0 and nums[i] != 7:
count += nums[i]
i+=1
#print("incremented")
continue
if nums[i] == 6 and switch == 0:
switch = 1
#print("switch ON")
i+=1
if nums[i] == 6 and switch == 1:
i+=1
if nums[i]==7 and switch==0 :
count+=nums[i]
#print("again 7")
i+=1
if switch == 1 and nums[i] == 7:
switch = 0
#print("switch OFF")
i+=1
else:
i+=1
#print(count)
return count
OUTPUT :
Input 1 : sum67([2, 7, 6, 2, 6, 7, 2, 7])
expected :18
output I got :20
Input 2 : sum67([2, 7, 6, 2, 6, 2, 7])
expected : 9
Output I got : 11
Try this:
def sum67(nums):
result = 0
startadding = True
for val in nums:
if val == 6:
startadding = False
if startadding:
result +=val
if val == 7:
startadding = True
return result
print(sum67([2, 7, 6, 2, 6, 7, 2, 7]))
This was my solution, I'm pretty new to programming, not sure if this is the correct way to do it but it works
def sum67(nums):
index = total = 0
while index < len(nums):
if nums[index] == 6:
while nums[index] != 7:
index += 1
index += 1
else:
total += nums[index]
index += 1
return total
Here is a solution
def sum67(nums):
total_sum = 0
skip_flag = False
for number in nums:
if number == 6:
skip_flag = True # prepare to skip
continue # skip this iteration
if number == 7 and skip_flag == True:
skip_flag = False # prepare to sum
continue # skip this iteration
if skip_flag == False:
total_sum += number
return total_sum
testing:
>>>sum67([2, 7, 6, 2, 6, 7, 2, 7]) # -> 18
>>>sum67([2, 7, 6, 2, 6, 2, 7])) # -> 9
Here is the simplest solution:
def sum67(nums):
while 6 in nums:
del nums[nums.index(6):nums.index(7,nums.index(6))+1]
return sum(nums)
Here's a far simpler solution:
def sum67(nums):
my_sum = 0
do_sum = True
for num in nums:
if num == 6:
# stop summing
do_sum = False
elif num == 7:
# start summing
do_sum = True
# if we were not summing then this 7 will be added to the sum, so subtract it now to keep the sum correct
if not do_sum:
my_sum -= 7
if do_sum:
my_sum += num
return my_sum
print(sum67([2, 7, 6, 2, 6, 7, 2, 7])) # 18
print(sum67([2, 7, 6, 2, 6, 2, 7])) # 9
List-2 > sum67(python3)
def sum67(nums):
s = sum(nums)
l=[0]
for i in range(len(nums)):
if nums[i]==6 and nums[l[-1]]!=6:
l.append(i)
if nums[i]==7 and nums[l[-1]]==6:
l.append(i)
s-=sum(nums[l[-2]:l[-1]+1])
return s
def sum67(nums):
soma = 0
if (len(nums)>0):
i =0
while i<len(nums):
if (nums[i] == 6):
while (nums[i] != 7):
i +=1
else : soma += nums[i]
i +=1
return soma
else : return 0
def except6_7(nums):
if nums.count(6) == 1 and nums.count(7) == 1:
return sum(nums)-sum(nums[nums.index(6):nums.index(7)+1])
return sum(nums)
print(except6_7([1, 2, 2, 6, 99, 99, 7]))
or
def except6_7(nums):
while 6 and 7 in nums: ## YOU MUST ADD "and 7" ##
del nums[nums.index(6):nums.index(7,nums.index(6))+1]
return sum(nums)
print(except6_7([1, 2, 2, 6, 99, 99]))
def sum67(nums):
my_sum = 0
do_sum = True
for num in nums:
if num == 6:
# stop summing
do_sum = False
elif num == 7 and do_sum == False:
# start summing
do_sum = True
my_sum -= 7
if do_sum:
my_sum += num
return my_sum
print(sum67([2, 7, 4, 3, 6, 67, 45, 7, 2])) # gives output of 18
print(sum67([1, 2, 2, 6, 99, 99, 7]) # gives output 5 (both correct)
# I didn't have enough contributor points to reply to the guy who had an error in his and this is a correction of that
def sum67(nums):
sum_= sum(nums)
six = [i for i, x in enumerate(nums) if x == 6]
seven = [i for i, x in enumerate(nums) if x == 7]
seven = [x for x in seven if x>six[0]]
tmp = []
if six:
if len(six)>len(seven):
six = six[::2]
for i in range(len(six)):
sum_-=sum(nums[six[i]:seven[i]+1])
return sum_
elif len(six)<len(seven):
seven = seven[:len(six)]
for i in range(len(seven)):
sum_-=sum(nums[six[i]:seven[i]+1])
return sum_
else:
for i in range(len(six)-1):
if six[i+1]<seven[i]:
tmp.append(six[i+1])
if tmp:
for i in range(len(tmp)):
six.remove(tmp[i])
for i in range(len(six)):
sum_-=sum(nums[six[i]:seven[i]+1])
return sum_
else:
for i in range(len(seven)):
sum_-=sum(nums[six[i]:seven[i]+1])
return sum_
else:
return sum(nums)