Combination sum higher than and lower than - python

im now starting in programing. I get one exercise to generate a combination of 10 numbers with a set of numbers, and make a sum and the sum of that numbers need to be less than 800 and higher than 700, and print the result and combination (Print All combinations).
For example if the set of numbers is 10,20,30,40,50,60,70,80,90,100 and i need to generate a set of 10 numbers using the numbers i set and the sum of that combination need to be less 560 and higher than 500.
10+20+30+40+50+60+70+80+90+100 = 550
10+20+30+40+50+40+100+80+90+90 = 550
..
I start a code in Python, but im little stuck, how i can sum the combinations.
import itertools
myList = [10, 20, 30, 40, 50, 60, 70, 80, 90, 100]
for i in range(len(myList)):
for combinations in itertools.combinations(myList, i):
print(combinations)
sum(e for e in combinations if e >= 550)

You're very close, but you need to filter based on whether sum(e) is in the desired range, not whether e itself is.
>>> from itertools import combinations
>>> myList = [10, 20, 30, 40, 50, 60, 70, 80, 90, 100]
>>> [e for i in range(len(myList)) for e in combinations(myList, i) if 500 < sum(e) < 560]
[(20, 40, 50, 60, 70, 80, 90, 100), (30, 40, 50, 60, 70, 80, 90, 100), (10, 20, 30, 50, 60, 70, 80, 90, 100), (10, 20, 40, 50, 60, 70, 80, 90, 100), (10, 30, 40, 50, 60, 70, 80, 90, 100), (20, 30, 40, 50, 60, 70, 80, 90, 100)]

combinations only exists inside your inner for loop - you can sum it right after you print it simply with sum(combinations). Your sum() statement is outside the loop, where combinations is no longer defined.
Something like:
import itertools
myList = [10, 20, 30, 40, 50, 60, 70, 80, 90, 100]
for i in range(len(myList)):
for combinations in itertools.combinations(myList, i):
if 500 < sum(combinations) < 560:
print(combinations, sum(combinations))

Related

Split Pandas Dataframe Using Criteria

I have time series data with a column that sums up seconds that something is running. All numbers are divisible by 30s but sometimes it does skip numbers (may jump from 30 to 90). This column can reset along as it is running, setting the start count back to 30s. How would I break up every chunk of runtime.
For example: If numbers in the column are 30, 60, 120, 150, 30, 60, 90, 30, 60, how would I break apart the dataframe into the full sequences with no resets.
30, 60, 120, 150 in 1 dataframe and 30, 60, 90 in the next and 30, 60 in the last? At the end, I need to take the max of each dataframe and add them together (that part I could figure out).
Using #RSale's input:
import pandas as pd
df = pd.DataFrame({'data': [30, 60, 120, 150, 30, 60, 90, 30, 60]})
d = dict(tuple(df.groupby(df['data'].eq(30).cumsum())))
d is a dictionary of three dataframes:
d[1]:
data
0 30
1 60
2 120
3 150
d[2]:
data
4 30
5 60
6 90
And d[3}:
data
7 30
8 60
Not very elegant but it get's the job done.
Loop through an array. Add array to a list when a number is smaller than the one before. Remove the saved array from the list and repeat until no change is detected.
numpy & recursive
import numpy as np
a = np.array([30, 60, 120, 150, 30, 60, 90, 30, 60])
y = []
def split(a,y):
for count,val in enumerate(a):
if count == 0:
pass
elif val < a[count-1]:
y.append(a[:count])
a = a[count:]
if len(a)> 0 and sorted(a) != list(a):
split(a,y)
else:
y.append(a)
a = []
return(y)
return(y)
y = split(a,y)
print(y)
>>[array([ 30, 60, 120, 150]), array([30, 60, 90]), array([30, 60])]
print([max(lis) for lis in y])
>>[150,90,60]
This will not consider 30 as a starting point but the samllest number after the reset.
Or using diff to find the change points.
numpy & diff version
import numpy as np
a = np.array([30, 60, 120, 150, 30, 60, 90, 30, 60])
y = []
def split(a,y):
a_diff = np.asarray(np.where(np.diff(a)<0))[0]
while len(a_diff)>1:
a_diff = np.asarray(np.where(np.diff(a)<0))[0]
y.append(a[:a_diff[0]+1])
a = a[a_diff[0]+1:]
y.append(a)
return(y)
y = split(a,y)
print(y)
print([max(lis) for lis in y])
>>[array([ 30, 60, 120, 150]), array([30, 60, 90]), array([30, 60])]
>>[150, 90, 60]
pandas & DataFrame version
import pandas as pd
df = pd.DataFrame({'data': [30, 60, 120, 150, 30, 60, 90, 30, 60]})
y = []
def split(df,y):
a = df['data']
a_diff = [count for count,val in enumerate(a.diff()[1:]) if val < 0 ]
while len(a_diff)>1:
a_diff = [count for count,val in enumerate(a.diff()[1:]) if val < 0 ]
y.append(a[:a_diff[0]+1])
a = a[a_diff[0]+1:]
y.append(a)
return(y)
y = split(df,y)
print(y)
print([max(lis) for lis in y])

Bubble sort not sorting properly in python

I'm making bubble sort in Python but have no idea why it doesn't sort properly.
N = [80000, 20, 40 , 50, 10000, 50, 60, 90, 100, 5000, 22]
for i in range(len(N)-1):
for j in range(len(N)-i-1):
if(N[i] > N[i+1]):
N[i], N[i+1] = N[i+1], N[i]
print(N)
This is result of this code
[20, 40, 50, 10000, 50, 60, 90, 100, 5000, 22, 80000]
You should compare N[j] with N[j+1], because you need repeatedly swapping the adjacent elements if they are in wrong order.
N = [80000, 20, 40 , 50, 10000, 50, 60, 90, 100, 5000, 22]
for i in range(len(N)-1):
for j in range(len(N)-i-1):
if(N[j] > N[j+1]):
N[j], N[j+1] = N[j+1], N[j]
print(N)
Output
[20, 22, 40, 50, 50, 60, 90, 100, 5000, 10000, 80000]
You should use 'j' instead of 'i' in the body of the second loop. Otherwise it is pointless to have both loops. Only the outer loop is effectively executed.
I believe you mixed up your indices i and j. It should read:
N = [80000, 20, 40 , 50, 10000, 50, 60, 90, 100, 5000, 22]
for i in range(len(N)-1):
for j in range(len(N)-i-1):
if(N[j] > N[j+1]):
N[j], N[j+1] = N[j+1], N[j]
print(N)
Output:
[20, 22, 40, 50, 50, 60, 90, 100, 5000, 10000, 80000]

Sum the elements in a list that contains string and integer and put the answer in another list python

I have to write a code to sum the grades of each student in the list and return the total.
My code is:
list=['student1',10,20,40,'student2',20,20,40,'student3',20,30,40,'student4',20,10,30]
list2=[]
for i in range(0,len(list1),4):
list2.append(list1[i])
for j in range(len(list1)):
if j%4 == 1:
sum= list1[j]+list1[j+1]+list1[j+2]
list2.append(sum)
print(list2)
the expected output should be like:
['student1', 70, 'student2', 80,'student3', 90, 'student4', 60]
but i got this output:
['student1', 70, 80, 90, 60, 'student2', 70, 80, 90, 60, 'student3', 70, 80, 90, 60, 'student4', 70, 80, 90, 60]
​
so what is the wrong with my code?
​
You can do it with single loop:
lst = ['student1', 10, 20, 40, 'student2', 20, 20, 40, 'student3', 20, 30, 40, 'student4', 20, 10, 30]
result = []
for i in range(0, len(lst), 4):
result.extend((lst[i], sum(lst[i+1:i+4])))
Output:
['student1', 70, 'student2', 80, 'student3', 90, 'student4', 60]
If number of marks are different from student to student, e.g.:
lst = ['student1', 10, 20, 'student2', 10, 20, 30, 'student3', 10, 20, 30, 40, 'student4', 10, 20, 30, 40, 50]
Then:
s = 0
result = [lst[0]]
for i in lst[1:]:
try:
s += int(i)
except ValueError:
result.extend((s, i))
s = 0
result.append(s)
Output:
['student1', 30, 'student2', 60, 'student3', 100, 'student4', 150]
In your second loop you loop again over your whole initial list1, thus you always append all the sums. If your list really always contains one name and three grades, you could instead get rid of the second loop and just use 'i' from your first loop as iterator for the sums, in the same manner as you are doing now.
list1=['student1',10,20,40,'student2',20,20,40,'student3',20,30,40,'student4',20,10,30]
list2=[]
for i in range(0,len(list1),4):
list2.append(list1[i])
sum= list1[i+1]+list1[i+2]+list1[i+3]
list2.append(sum)
print(list2)
produces
['student1', 70, 'student2', 80, 'student3', 90, 'student4', 60]
The second for loop in code goes through every element in the list and take action whenever the index mod 4 is 1. You do not need two for loops.
it goes like this: 0, 4, 8, so you do not need the second for loop.
you already know where the numbers are.(i+1,i+2,i+3) and i is the student name.
list1=['student1',10,20,40,'student2',20,20,40,'student3',20,30,40,'student4',20,10,30]
list2=[]
for i in range(0, len(list1), 4):
list2.append(list1[i])
sum = list1[i+1]+list1[i+2]+list1[i+3]
list2.append(sum)
print(list2)
Try
in_lst = ['student1', 10, 20, 40, 'student2', 20, 20, 40, 'student3', 20, 30, 40, 'student4', 20, 10, 30]
out_lst = []
for x in range(0, len(in_lst), 4):
student_entry = in_lst[x:x + 4]
out_lst.append(student_entry[0])
out_lst.append(sum(student_entry[1:]))
print(out_lst)
Output
['student1', 70, 'student2', 80, 'student3', 90, 'student4', 60]
here is solution, where you dont't need to worry about the no of sbject score by student.
list1=['student1',10,20,40,'student2',20,20,40,'student3',20,30,40,'student4',20,10,30]
student_name =[]
student_name_index =[]
for i in range(len(list1)):
if type(list1[i]) == int:
pass
else:
student_name.append(list1[i])
student_name_index.append(i)
student_name_index.append(len(list1)-1)
total_marks=[]
for i in range(1,len(student_name_index)):
total_marks.append(sum(list1[student_name_index[i-1]+1:student_name_index[i]]))
final_result =[]
for name, mark in zip(student_name,total_marks):
final_result.append(name)
final_result.append(mark)
print(final_result)
# output ['student1', 70, 'student2', 80, 'student3', 90, 'student4', 30]

take sum of ints preserving specific information

I have a list of ints
list = [25, 50, 70, 32, 10, 20, 50, 40, 30]
And I would like to sum up the ints (from left to right) if their sum is smaller than 99. Lets say I write this output to a list, than this list should look like this:
#75 because 25+50 = 70. 25+50+70 would be > 99
new_list = [75, 70, 62, 90, 30]
#70 because 70+32 > 99
#62 because 32+10+20 = 62. 32+10+20+50 would be > 99
But that is not all. I want to save the ints the sum was made from as well. So what I actually want to have is a data structure that looks like this:
list0 = [ [(25,50),75], [(70),70], [(32, 10, 20),62], [(50, 40),90], [(30),30] ]
How can I do this?
Use a separate list to track your numbers:
results = []
result = []
for num in inputlist:
if sum(result) + num < 100:
result.append(num)
else:
results.append([tuple(result), sum(result)])
result = [num]
if result:
results.append([tuple(result), sum(result)])
For your sample input, this produces:
[[(25, 50), 75], [(70,), 70], [(32, 10, 20), 62], [(50, 40), 90], [(30,), 30]]
You can use iterator fo this:
l = [25, 50, 70, 32, 10, 20, 50, 40, 30]
def sum_iter(lst):
s = 0
t = tuple()
for i in lst:
if s + i <= 99:
s += i
t += (i,)
else:
yield t, s
s = i
t = (i,)
else:
yield t, s
res = [[t, s] for t, s in sum_iter(l)]
On your data result is:
[[(25, 50), 75], [(70,), 70], [(32, 10, 20), 62], [(50, 40), 90], [(30,), 30]]

Multiply two arrays with different dimensions using numpy

I need a faster/optimised version of my current code:
import numpy as np
a = np.array((1, 2, 3))
b = np.array((10, 20, 30, 40, 50, 60, 70, 80))
print([i*b for i in a])
Is there any faster way to do this using numpy functions (maybe without reshaping and blowing up the whole thing)?
Looks like the outer product.
>>> np.outer(a, b)
array([[ 10, 20, 30, 40, 50, 60, 70, 80],
[ 20, 40, 60, 80, 100, 120, 140, 160],
[ 30, 60, 90, 120, 150, 180, 210, 240]])

Categories

Resources