Creating code to make sum of array elements with variable - python

I want to create a code that has the variable how many elements you take from an list and sum those. For example, if I type in 3, it takes the first 3 elements of an array and addes them together.
Preferably in some for loop but who knows what kind of creative solutions I get :)
x = [1, 3, 4, 2, 6, 9, 4]
Amount = 3
Sum = 0
Sum += x[Amount-3] + x[Amount-2] + x[Amount-1]
Desired result: 8
Amount_2 = 4
Sum = 0
Sum += x[Amount-4] + x[Amount-3] + x[Amount-2] + x[Amount-1]
Desired result: 11
Hope this explains it well.

x = [2, 6, 7, 7, 12] # your list here
amount = int(input("Enter amount: "))
print(f'desired result: {sum(x[:amount])}')

Related

summing the first and last elements of list

I'd like to sum the first element and last elements of a list, and then exclude those two numbers and repeat that process again until there is only one element in the list. Like this:
[5,4,3,2,1,6]
[11,5,5]
[16,5]
[21]
I used some methods but didn't work.
I am just a computer science student starting to python so help me out please guys.
Thank you.
Main logic of this answer is revolve around len of last list print. Lets break it in few points :
LOGIC :
1. Basically we need sum of first-ith and last-ith value for that we used this code:
l_u[-1][i] + l_u[-1][-i - 1]
2. Above point is only valid when lenght of last append list is even for odd-length we have to append this only at even poistion :
l_u[-1][i]
3. Among above two statement which is going to true this is done by this condition:
len(l_u[-1])%2 != 0 and i%2 != 0
CODE :
l = [5, 4, 3, 2, 1, 6]
l_u = [l]
condn = True
j = 0
while condn:
l_u.append([
l_u[-1][i] if len(l_u[-1]) % 2 != 0 and i % 2 != 0 else l_u[-1][i] +
l_u[-1][-i - 1] for i in range(
len(l_u[-1]) // 2 if len(l_u[-1]) % 2 == 0 else len(l_u[-1]) // 2 +
1)
])
if len(l_u[-1]) <= 1:
break
print(l_u)
OUTPUT :
[[5, 4, 3, 2, 1, 6], [11, 5, 5], [16, 5], [21]]

Iterative summation

I'm trying to write a python code that allows me to iteratively sum up the average values of three elements of a list, starting with the third element and its two predecessors. Let me give you an example:
list = [1, 2, 3, 4, 5, 6, 7]
I want to calculate the following:
sum_of_average_values = sum(1, 2, 3)/3 + sum(2, 3, 4)/3 + sum(3, 4, 5)/3 + sum(4, 5, 6)/3 + sum(5, 6, 7)/3
Since I'm quite new to programming I couldn't find an effective way of putting this into a function.
You can do in this way:
a = [1,2,3,4,5,6,7]
sum_of_average_values = 0
for i in range(0,len(a)-2):
sum_of_average_values += sum(a[i:i+2])/3
print(sum_of_average_values)
You could use rolling from pandas.
import pandas as pd
num_list = [1, 2, 3, 4, 5, 6, 7]
average_sum = sum(pd.Series(num_list).rolling(3).mean().dropna())
print(average_sum)
Many ways to achieve this, one way is recursively.
The function averages the last three elements of a list and adds the result to the result generated by the function with a list lacking the last element. Continues like this until the list is shorter than 3.
def fn(l):
if len(l) < 3:
return 0
return sum(l[-3:])/3 + fn(l[:-1])
print(fn([1, 2, 3, 4, 5, 6, 7]))
Another solution where you can specify the amount of elements you want to sum up and average:
l = [1, 2, 3, 4, 5, 6, 7]
def sum_avg(l, n):
res = 0
for i in range(n-1, len(l)):
res += sum([l[j] for j in range(i, i-n, -1)])/n
return res
print(sum_avg(l, 3))
--> 20.0
Mathematically, this would could be obtain by averaging the sums of 3 sublists:
L = [1, 2, 3, 4, 5, 6, 7]
r = (sum(L) + sum(L[1:-1]) + sum(L[2:-2]))/3 # 20.0
and can be generalized to a window size of w:
w = 3
r = sum(sum(L[p:-p or None]) for p in range(w)) / w
It can also be implemented without the overhead of generating sublists by using item positions to determine the number of times they are added to the total:
r = sum(n*min(i+1,len(L)-i,w) for i,n in enumerate(L)) / w
This would be the most memory-efficient of the 3 methods because it use an iterator to feed data to the sum function and only goes through the data once.
Detailed explanation:
Since all the averages that are added together are a division by 3, we can produce the total sum and divide by 3 at the end
the number at the first and last positions are added once
the number at the second and penultimate positions are added twice
The numbers from the third position up to the antepenultimate will be added 3 times
visually:
(1 + 2 + 3) / 3
(2 + 3 + 4) / 3
(3 + 4 + 5) / 3
(4 + 5 + 6) / 3
(5 + 6 + 7) / 3
(1x1 + 2x2 + 3x3 + 4x3 + 5x3 + 6x2 + 7x1) / 3 = 20.0
n = 1 2 3 4 5 6 7 # value
* = 1 2 3 3 3 2 1 # multiplier (times added)
-------------------------
(2, 4, 9, 12, 15, 12, 7) / 3 = 20.0
i = 0 1 2 3 4 5 6 # index
1 2 3 3 3 2 1 # min(i+1,len(L)-i,w) = multiplier
You can do in one line using list comprehension as:
n = 3
avg = sum( [ sum(lst[i:i+n])/n for i in range(0, len(lst) - (n - 1)) ] )
print(avg) # 20.0

Transforming an array of integers and computing the sum

Suppose we need to transform an array of integers and then compute the sum.
The transformation is the following:
For each integer in the array, subtract the first subsequent integer that is equal or less than its value.
For example, the array:
[6, 1, 3, 4, 6, 2]
becomes
[5, 1, 1, 2, 4, 2]
because
6 > 1 so 6 - 1 = 5
nothing <= to 1 so 1 remains 1
3 > 2 so 3 - 2 = 1
4 > 2 so 4 - 2 = 2
6 > 2 so 6 - 2 = 4
nothing <= to 2 so 2 remains 2
so we sum [5, 1, 1, 2, 4, 2] = 15
I already have the answer below but apparently there is a more optimal method. My answer runs in quadratic time complexity (nested for loop) and I can't figure out how to optimize it.
prices = [6, 1, 3, 4, 6, 2]
results = []
counter = 0
num_prices = len(prices)
for each_item in prices:
flag = True
counter += 1
for each_num in range(counter, num_prices):
if each_item >= prices[each_num] and flag == True:
cost = each_item - prices[each_num]
results.append(cost)
flag = False
if flag == True:
results.append(each_item)
print(sum(results))
Can someone figure out how to answer this question faster than quadratic time complexity? I'm pretty sure this can be done only using 1 for loop but I don't know the data structure to use.
EDIT:
I might be mistaken... I just realized I could have added a break statement after flag = False and that would have saved me from a few unnecessary iterations. I took this question on a quiz and half the test cases said there was a more optimal method. They could have been referring to the break statement so maybe there isn't a faster method than using nested for loop
You can use a stack (implemented using a Python list). The algorithm is linear since each element is compared at most twice (one time with the next element, one time with the next number smaller or equals to it).
def adjusted_total(prices):
stack = []
total_substract = i = 0
n = len(prices)
while i < n:
if not stack or stack[-1] < prices[i]:
stack.append(prices[i])
i += 1
else:
stack.pop()
total_substract += prices[i]
return sum(prices) - total_substract
print(adjusted_total([6, 1, 3, 4, 6, 2]))
Output:
15
a simple way to do it with lists, albeit still quadratic..
p = [6, 1, 3, 4, 6, 2]
out= []
for i,val in zip(range(len(p)),p):
try:
out.append(val - p[[x <= val for x in p[i+1:]].index(True)+(i+1)])
except:
out.append(val)
sum(out) # equals 15
NUMPY APPROACH - honestly don't have alot of programming background so I'm not sure if its linear or not (depending on how the conditional masking works in the background) but still interesting
p = np.array([6, 1, 3, 4, 6, 2])
out = np.array([])
for i,val in zip(range(len(p)),p):
pp = p[i+1:]
try:
new = val - pp[pp<=val][0]
out = np.append(out,new)
except:
out = np.append(out,p[i])
out.sum() #equals 15

Eliminating Consecutive Numbers

If you have a range of numbers from 1-49 with 6 numbers to choose from, there are nearly 14 million combinations. Using my current script, I currently have only 7.2 million combinations remaining. Of the 7.2 million remaining combinations, I want to eliminate all 3, 4, 5, 6, dual, and triple consecutive numbers.
Example:
3 consecutive: 1, 2, 3, x, x, x
4 consecutive: 3, 4, 5, 6, x, x
5 consecutive: 4, 5, 6, 7, 8, x
6 consecutive: 5, 6, 7, 8, 9, 10
double separate consecutive: 1, 2, 5, 6, 14, 18
triple separate consecutive: 1, 2, 9, 10, 22, 23
Note: combinations such as 1, 2, 12, 13, 14, 15 must also be eliminated or else they conflict with the rule that double and triple consecutive combinations to be eliminated.
I'm looking to find how many combinations of the 7.2 million remaining combinations have zero consecutive numbers (all mixed) and only 1 consecutive pair.
Thank you!
import functools
_MIN_SUM = 120
_MAX_SUM = 180
_MIN_NUM = 1
_MAX_NUM = 49
_NUM_CHOICES = 6
_MIN_ODDS = 2
_MAX_ODDS = 4
#functools.lru_cache(maxsize=None)
def f(n, l, s = 0, odds = 0):
if s > _MAX_SUM or odds > _MAX_ODDS:
return 0
if n == 0 :
return int(s >= _MIN_SUM and odds >= _MIN_ODDS)
return sum(f(n-1, i+1, s+i, odds + i % 2) for i in range(l, _MAX_NUM+1))
result = f(_NUM_CHOICES, _MIN_NUM)
print('Number of choices = {}'.format(result))
While my answer should work, I think someone might be able to offer a faster solution.
Consider the following code:
not_allowed = []
for x in range(48):
not_allowed.append([x, x+1, x+2])
# not_allowed = [ [0,1,2], [1,2,3], ... [11,12,13], ... [47,48,49] ]
my_numbers = [[1, 2, 5, 9, 11, 33], [1, 3, 7, 8, 9, 31], [12, 13, 14, 15, 23, 43]]
for x in my_numbers:
for y in not_allowed:
if set(y) <= set(x): # if [1,2,3] is a subset of [1,2,5,9,11,33], etc.
# drop x
This code will remove all instances that contain double consecutive numbers, which is all you really need to check for, because triple, quadruple, etc. all imply double consecutive. Try implementing this and let me know how it works.
The easiest approach is probably to generate and filter. I used numpy to try to vectorize as much of this as I could:
import numpy as np
from itertools import combinations
combos = np.array(list(combinations(range(1, 50), 6))) # build all combos
# combos is shape (13983816, 6)
filt = np.where(np.bincount(np.where(np.abs(
np.subtract(combos[:, :-1], combos[:, 1:])) == 1)[0]) <= 1)[0] # magic!
filtered = combos[filt]
# filtered is shape (12489092, 6)
Breaking down that "magic" line
First we subtract the first five items in the list from the last five items to get the differences between them. We do this for the entire set of combinations in one shot with np.subtract(combos[:, :-1], combos[:, 1:]). Note that itertools.combinations produces sorted combinations, on which this depends.
Next we take the absolute value of these differences to make sure we only look at positive distances between numbers with np.abs(...).
Next we grab the indicies from this operation for the entire dataset that indicate a difference of 1 (consecutive numbers) with np.where(... == 1)[0]. Note that np.where returns a tuple where the first item are all of the rows, and the second item are all of the corresponding columns for our condition. This is important because any row value that shows up more than once tells us that we have more than one consecutive number in that row!
So we count how many times each row shows up in our results with np.bincount(...), which will return something like [5, 4, 4, 4, 3, 2, 1, 0] indicating how many consecutive pairs are in each row of our combinations dataset.
Finally we grab only the row numbers where there are 0 or 1 consecutive values with np.where(... <= 1)[0].
I am returning way more combinations than you seem to indicate, but I feel fairly confident that this is working. By all means, poke holes in it in the comments and I will see if I can find fixes!
Bonus, because it's all vectorized, it's super fast!

Adding to a specific variable in a list

I'm trying to add two lists. If the last variable is greater than 10, it needs to carry over to the previous variable in the list. For example :
1 / 2 / 3 (List 1)
7 / 8 / 9 (List 2)
Should equal
9 / 1 / 2 not 8/10/12
So far, I have
list1 = [1, 2, 3]
list2 = [7, 8, 9]
SumOfLists = [x+y for x,y in zip(list1, list2)]
That adds the lists together, but I'm not sure how to make the number carry over.
You can try this code.
list1 = [1, 2, 3]
list2 = [7, 8, 9]
def add_list(a,b):
carry = 0
res_list = []
for i,j in zip(a[::-1],b[::-1]): # Iterate through the lists in reverse
val = (i+j+carry)%10 # Store the sum in val
carry = (i+j+carry)//10 # Store the carry
res_list.append(val) # Append to the returning list
return res_list[::-1] # Return the list
print add_list(list1,list2)
Wil print
[9, 1, 2]
Algorithm
Loop through each of the values in reverse. Add each corresponding values. If the values are above 10 then find the exceeding value and put it to carry. Finally return the reverse of the list.
list1 = [1, 2, 3]
list2 = [7, 8, 9]
cur = 0 # num to carry over
result = []
for x,y in zip(reversed(list2),reversed(list1)):
if x + y + cur > 10: # if sum greater than 10, remember to add 1 on
t = x+y + cur # the next loop
d = str(t)[1] # get the rightmost digit
result.append(int(d))
cur = 1
else: # nothing to curry over, but still add cur,
# it may be 1
result.append(x+y+cur)
cur = 0
print(list(reversed(result)) )
[9, 1, 2]
just subtract 10 if it's more then 10 and add 1 to it's previous element. Do this proccess for all element in sum list
if SumOfLists[2] >= 10:
SumOfLists[2] -= 10
SumOfLists[1] += 1
And at last check
if SumOfLists[0] >= 10:
for i in range(len(SumOfLists)-1,0,-1):
SumOfLists[i] = SumOfLists[i-1]
SumOfLists[0] = 1

Categories

Resources