sum of a List Function difference - python

This function works only when I call with:
def prodo(L):
sum = 1
for i in range(0, len(L)):
sum = L[i] * sum
return sum
these lines:
d = prodo([3, -1, 4, -1, -5])
print(d)
But the following function using L returns 375 and not -60
def prod(L):
sum = 1
for i in L:
if i>=len(L):
break
sum = L[i] * sum
return sum
Question: What am I doing wrong and why?

You can do it like this:
from functools import reduce
product = reduce((lambda x, y: x * y), [3, -1, 4, -1, -5])
print(product)
This outputs -60
Optionally, you can declare any list
l = [3, -1, 4, -1, -5]
and then call
product = reduce((lambda x, y: x * y), l)

This function doesn't work because you are not iterating over the array like this:
for i in range(len(L)):
// now `i` will have values 0,1,2,3,...,len(L)-1
instead you are iterating like this:
d = prodo([3, -1, 4, -1, -5])
for i in L:
// now i will take values 3,-1,4,-1,-5
With this method you cannot use the if i == len(L): to determine if you are at the end of the array, because i is not a number index but rather the value at a certain index.
So the break will execute any time a number from the array is higher or equal to the length of the array.
def prod(L):
sum = 1
for i in L:
if i>=len(L):
break
sum = L[i] * sum
return sum

In the def prod() you are using the i as value of the elements of the list.
So when you do:
def prod(L)
for i in L: # i = 3, -1, 4, -1, -5
When you write:
for i in range(0,L): # i =0, 1, 2, 3, 4
These are the places you need to change the code.

As #Skam proposes in comments, you will know the difference if you try to print i in your second function. When you use the below syntax:
for i in L
i does not represent a numeric value that starts from 0 and goes to the length of your list. But it represents the item itself. As an example, consider the below code:
L = [1,3,4,5,6]
for i in L:
print i
The output of this code is:
1
3
4
5
6
So in your second function when you are trying to do L[i], you are not actually getting the current iteration number and trying to access it in your list, but you are trying to access the value that has the index of the current value of i , considering the mentioned code, if I try to do L[i] the first iteration will print 3 since it has the index of 1 which is the first element.

Related

how to subtract elements within an array using for loops in python

I have an array a = [4,3,2,1]
What I am trying to achieve is that I need a single value on subtracting the elements in the array that is 4-3-2-1.
I tried the below this using for loop but it does not seem to work. I don't seem to get the right value on execution.
def sub_num(arr):
difference = arr[0]
n = len(arr)
print(n)
print(i)
for i in n: difference = arr[n] - arr[n-1]
return(difference)
If you have a list a:
a = [4, 3, 2, 1]
And wish to get the result of 4 - 3 - 2 - 1, you can use functools.reduce.
>>> from functools import reduce
>>> a = [4, 3, 2, 1]
>>> reduce(int.__sub__, a)
-2
>>>
You can solve with nested lists:
b = sum([a[0],*[-x for x in a[1:]]])
Simpler solution without for:
Since 4-3-2-1 is equal to 4-(3+2+1):
a[0]-sum(a[1:])
You could modify your code like this
def sub_num(arr):
difference = arr[0]
n = len(arr)
print(n)
for i in range(1,n):
difference = difference - arr[i]
return difference
Note:
Printing value of i without defining it is not possible

What is wrong with this cumulative sum function, and is there a better way to write the function?

Function:
def comulative_sum(arr):
arr1 = []
for number in range(1, len(arr)):
sum1 = 0
for number1 in range(0, arr[number]):
sum1 += number1
arr1.append(sum1)
return arr1
arr = [1, 2, 3, 4]
print(comulative_sum(arr))
Output:
[3, 6, 10]
Expected output:
[1, 3, 6, 10]
I have tried slicing ([1:], [0:number) instead of the range function. Still no results.
The better way to write this function is simply using itertools.accumulate() which does exactly that:
>>> import itertools
>>> print(list(itertools.accumulate([1,2,3,4]))
[1, 3, 6, 10]
you dont need to loop it twice
def cum_sum(x):
result = []
current_sum = 0
for value in x:
current_sum += value
result.append(current_sum)
return result
Multiple issues:
On the first loop you need to range until len() + 1 as the last number is len() and then the last number in second loop will be len() - 1 which is also the index.
On the second loop, instead of ranging until number, you range until the original number in the array.
Fixed code:
def comulative_sum(arr):
arr1 = []
for number in range(1, len(arr)+1):
sum1 = 0
for number1 in range(0, number):
sum1 += arr[number1]
arr1.append(sum1)
return arr1
arr = [1, 2, 3, 4]
print(comulative_sum(arr))
If you wish to improve upon this code and not use a built-in accumulate, you can do so:
def comulative_sum(input_list):
output = []
sum_ = 0 # The underscore is to avoid renaming the built-in sum()
for i in input_list:
sum_ += i
output.append(sum_)
return output
input_list = [1, 2, 3, 4]
print(comulative_sum(input_list))
Advantages:
Better variable naming.
Less code nesting.
Easier overall code readability.
Faster code (no need to recalculate everything on each iteration)
I built in your solution. This version relies on Python's loop through indexes and also addresses a possible number '0'.
def cumulative_sum(arr):
arr1 = []
# Python does the hard work for you, it loops through each value on the list
for value in arr:
sum1 = 0
# Range is going to have a list as follows [0, ... , value-1]
for number1 in range(0, value):
sum1 += number1
# Adding 'value' to sum1 because the loop did not add the last value
arr1.append(sum1+value)
return arr1
arr = [1, 3, 6, 10]
# Calling the function with 'print' to make sure the results are displayed
print(cumulative_sum(arr))
The for loop will only deal with numbers from index 1 to the end of the array. Thus index 0 will be ignored.
Working function:
def comulative_sum(arr):
arr1 = []
for number in arr[:len(arr)]:
sum1 = 0
for number1 in arr[0:number]:
sum1 += number1
arr1.append(sum1)
return arr1
arr = [1, 2, 3, 4]
print(comulative_sum(arr))
All that was changed was the indexing in the first and second for loop.

Find Triplets smaller than a given number

I am trying to solve a problem where:
Given an array of n integers nums and a target, find the number of
index triplets i, j, k with 0 <= i < j < k < n that satisfy the
condition nums[i] + nums[j] + nums[k] < target.
For example, given nums = [-2, 0, 1, 3], and target = 2.
Return 2. Because there are two triplets which sums are less than 2:
[-2, 0, 1] [-2, 0, 3]
My algorithm: Remove a single element from the list, set target = target - number_1, search for doublets such that number_1 + number _2 < target - number_1. Problem solved.
The problem link is https://leetcode.com/problems/3sum-smaller/description/ .
My solution is:
def threeSumSmaller(nums, target):
"""
:type nums: List[int]
:type target: int
:rtype: int
"""
nums = sorted(nums)
smaller = 0
for i in range(len(nums)):
# Create temp array excluding a number
if i!=len(nums)-1:
temp = nums[:i] + nums[i+1:]
else:
temp = nums[:len(nums)-1]
# Sort the temp array and set new target to target - the excluded number
l, r = 0, len(temp) -1
t = target - nums[i]
while(l<r):
if temp[l] + temp[r] >= t:
r = r - 1
else:
smaller += 1
l = l + 1
return smaller
My solution fails:
Input:
[1,1,-2]
1
Output:
3
Expected:
1
I am not getting why is the error there as my solution passes more than 30 test cases.
Thanks for your help.
One main point is that when you sort the elements in the first line, you also lose the indexes. This means that, despite having found a triplet, you'll never be sure whether your (i, j, k) will satisfy condition 1, because those (i, j, k) do not come from the original list, but from the new one.
Additionally: everytime you pluck an element from the middle of the array, the remaining part of the array is also iterated (although in an irregular way, it still starts from the first of the remaining elements in tmp). This should not be the case! I'm expanding details:
The example iterates 3 times over the list (which is, again, sorted and thus you lose the true i, j, and k indexes):
First iteration (i = 0, tmp = [1, -2], t = 0).
When you sum temp[l] + temp[r] (l, r are 0, 1) it will be -1.
It satisfies being lower than t. smaller will increase.
The second iteration will be like the first, but with i = 1.
Again it will increase.
The third one will increase as well, because t = 3 and the sum will be 2 now.
So you'll count the value three times (despite only one tuple can be formed in order of indexes) because you are iterating through the permutations of indexes instead of combinations of them. So those two things you did not take care about:
Preserving indexes while sorting.
Ensuring you iterate the indexes in a forward-fashion only.
Try like this better:
def find(elements, upper_bound):
result = 0
for i in range(0, len(elements) - 2):
upper_bound2 = upper_bound - elements[i]
for j in range(i+1, len(elements) - 1):
upper_bound3 = upper_bound2 - elements[j]
for k in range(j+1, len(elements)):
upper_bound4 = upper_bound3 - elements[k]
if upper_bound4 > 0:
result += 1
return result
Seems like you're counting the same triplet more than once...
In the first iteration of the loop, you omit the first 1 in the list, and then increase smaller by 1. Then you omit the second 1 in the list and increase smaller again by 1. And finally you omit the third element in the list, -2, and of course increase smaller by 1, because -- well -- in all these three cases you were in fact considering the same triplet {1,1,-2}.
p.s. It seems like you care more about correctness than performance. In that case, consider maintaining a set of the solution triplets, to ensure you're not counting the same triplet twice.
There are already good answers , Apart that , If you want to check your algorithm result then you can take help of this in-built funtion :
import itertools
def find_(vector_,target):
result=[]
for i in itertools.combinations(vector_, r=3):
if sum(i)<target:
result.append(i)
return result
output:
print(find_([-2, 0, 1, 3],2))
output:
[(-2, 0, 1), (-2, 0, 3)]
if you want only count then:
print(len(find_([-2, 0, 1, 3],2)))
output:
2

Function to Create a Zigzag Array in Python

I'm trying to create an array of positive and negative integers, representing distances north and south of a location - I need to see the elements of the array in zigzag order.
This means that the largest member appears first, the smallest member appears second, and the remaining elements alternate between the larger members decreasing from the largest and the smaller members increasing from the smallest.
I.e. the array [1, 3, 6, 9, -3] becomes [9, -3, 6, 1, 3].
I'm trying to complete the function wiggleArrangeArray, which takes one argument, an integer array of n integers.
Required Input Format, Constraints, and Output Format
I'm not sure how to say
"if the item in the array is larger than the other items in the array, display it first."
"if the item is smaller than the other items in the array, display it second."
"then alternate between the next largest numbers, and the next smallest numbers"
def wiggleArrangeArray(intArr):
for i in intArr
#if i > other items in intArr
#display that i at index value 0
#if i < other items in intArr
#display that i at index value 1
#if i < i at index value 0 and > other items in intArr, display it next
#if i > i at index value 1 and < other items in intArr, display it next
#repeat last two lines for continuing values
Please help if possible. Here's a link to the solution in C++ but I need it in Python. Thanks.
Edit: The function needs to work with the following tests:
f = open(os.environ["OUTPUT_PATH"], "w")
_intArr_cnt = int(raw_input())
_intArr_i=0
_intARR = []
while _intArr_i < _intArr_cnt:
_intArr_item = int(raw_input());
_intArr.append(_intArr_item)
_intArr_i+=1
res = wiggleArrangeArray(_intArr);
for res_cur in res:
f.write( str(res_cur) + "\n" )
f.close()
The altered C++ code
Note the algorithm you provided does calculate some sort of zigzag, but it is not the zigzag you are looking for. For future reference I will leave it here.
In the C++ code you provided, they only look for a sequences that satisfies a < b > c < d > e < f, you are looking however for a sequence with the 1-max, 1-min, 2-max, 2-min,...
Your link provides you a solution which you can copy nearly verbatim in Python. You only define a swap function:
def swap(arr,i,j):
t = arr[i]
arr[i] = arr[j]
arr[j] = t
Next you can simply modify the code:
def zigZag(arr):
n = len(arr)
# Flag true indicates relation "<" is expected,
# else ">" is expected. The first expected relation
# is "<"
flag = True
i = 0
while i<= n-2:
if (flag): # "<" relation expected
# If we have a situation like A > B > C,
# we get A > B < C by swapping B and C
if arr[i] > arr[i+1]:
swap(arr,i,i+1)
else: # ">" relation expected
# If we have a situation like A < B < C,
# we get A < C > B by swapping B and C
if arr[i] < arr[i+1]:
swap(arr,i,i+1)
flag = not flag # flip flag
i += 1
Mind that this is rather un-Pythonic, so you can simply improve it like:
def swap(arr,i,j):
arr[i],arr[j] = arr[j],arr[i]
def zigZag(arr):
n = len(arr)
for i in range(len(arr)-1):
if not i&1:
if arr[i] > arr[i+1]:
swap(arr,i,i+1)
elif arr[i] < arr[i+1]:
swap(arr,i,i+1)
return arr
Here tuple assignment is used to swap elements in the list, a range is used to iterate over the indices, we can furthermore use an elif instead of an if in an else, and for I've abandoned the flag by using a modulo check.
Your zigzag function
You can simply solve the problem by sorting the list, and using two pointers that each time emit the most left, the most right and walk towards each other. In other words something like:
def zigZag(arr):
srt = sorted(arr)
left = 0
right = len(srt)-1
result = []
while left < right:
result.append(srt[right])
right -= 1
if left < right:
result.append(srt[left])
left += 1
return result
Here Python implementation example.
Sort your data in reversed order (9, 6, 3, 1, -3)
Split by two lists (9, 6) (3, 1, -3)
Iterate over both (using zip_longest) first one from start, second in reverse order (9, -3), (6, 1) (None, 3)
Unpack tuples created by zip_longest (chain(*zip...)) so you get iterable data (9, -3, 6, 1, None, 3)
Remove None value in case if the list has an odd number of elements (if x is not None)
Example:
from itertools import zip_longest, chain
def zig_zag_array(data):
data = sorted(data)
mid = len(data) // 2
return [
x for x in chain(*zip_longest(data[mid:][::-1], data[:mid])) if x is not None
]
Test:
if __name__ == "__main__":
data = [1, 3, 6, 9, -3]
expected = [9, -3, 6, 1, 3]
output = zig_zag_array(data)
assert output == expected, f"Odd length: {output=}"
data = [1, 3, 6, 9, -3, 0]
expected = [9, -3, 6, 0, 3, 1]
output = zig_zag_array(data)
assert output == expected, f"Even length: {output=}"
print("PASSED")

Getting difference from all possible pairs from a list Python

I have an int list with unspecified number. I would like to find the difference between two integers in the list that match a certain value.
#Example of a list
intList = [3, 6, 2, 7, 1]
#This is what I have done so far
diffList = []
i = 0
while (i < len(intList)):
x = intList[i]
j = i +1
while (j < len(intList)):
y = intList[j]
diff = abs(x-y)
diffList.append(diff)
j += 1
i +=1
#Find all pairs that has a difference of 2
diff = diffList.count(2)
print diff
Is there a better way to do this?
EDIT: Made changes to the codes. This is what I was trying to do. What I want to know is what else can I use besides the loop.
seems like a job for itertools.combinations
from itertools import combinations
for a, b in combinations(intList, 2):
print abs(a - b)
You could even turn this one into a list comprehension if you wanted to :)
[abs(a -b) for a, b in combinations(intList, 2)]
int_list = [3, 6, 2, 7, 1]
for x in int_list:
for y in int_list:
print abs(x - y)

Categories

Resources