When I run this program, it says that the max number is 1 digit lower than it actually is in the list. For example, I run the code below and it tells me the max number is 91 when it is 92 from the list.
examMarks = [[80, 59, 34, 89], [31, 11, 47, 64], [29, 56, 13, 92]]
for eachRow in range(len(examMarks)):
for eachColumn in range(len(examMarks[eachRow])):
eachExamMark = (examMarks[eachRow][eachColumn])
max = -100
for everyMark in range(eachExamMark):
if everyMark > max:
max = everyMark
print(max)
I don't see the reason for the 3 loops to be honest, have you tried something like this?
examMarks = [[80, 59, 34, 89], [31, 11, 47, 64], [29, 56, 13, 92]]
highest = 0
for marks in examMarks:
for mark in marks:
highest = max(mark, highest)
print('Highest mark: %d' % highest)
You should try this code!
examMarks = [[80, 59, 34, 89], [31, 11, 47, 64], [29, 56, 13, 12]]
eachExamMark =[]
for eachRow in range(len(examMarks)):
for eachColumn in range(len(examMarks[eachRow])):
eachExamMark.append(examMarks[eachRow][eachColumn])
max = -100
for everyMark in eachExamMark:
if everyMark > max:
max = everyMark
print(max)
eachExamMark will be set to (92) that is the number 92 as the last step of the first part of your program. If you do a for loop over range(92) it will end at 91.
You should at least do:
print(eachExamMark)
before the max = -100 line.
You probably want to do:
eachExamMark.append(examMarks[eachRow][eachColumn])
after defining eachExamMark = [] at the beginning.
I am not sure if you have to solve things this way, but IMHO you should not be using range() at all, and there is no need to build a flattened list either.
You could e.g. do:
examMarks = [[80, 59, 34, 89], [31, 11, 47, 64], [29, 56, 13, 92]]
print(max(max(x) for x in examMarks))
As others point out the problem is the last loop is performing a range of a number, not a list as you expect.
An alternative algorithm:
from itertools import chain
examMarks = [[80, 59, 34, 89], [31, 11, 47, 64], [29, 56, 13, 92]]
print(max(chain.from_iterable(examMarks)))
chain.from_iterable(examMarks) flattens the list to an iterator
max() finds the maximum number on the list
Note: My original answer used sum(examMarks, []) to flatten the list. Thanks #John Coleman for your comment on a faster solution.
Try this one:
examMarks = [[80, 59, 34, 89], [31, 11, 47, 64], [29, 56, 13, 12]]
eachExamMark =[]
for eachRow in examMarks:
eachExamMark.append(max(eachRow))
print max(eachExamMark)
Related
I am new to python, and I wondered if anyone could help me find the average in the following marks list of students?. Please advise as to what I am doing wrong here.
student_marks = [['Name', ['A','B','C','D','E']],
['Ankit', [41, 34, 45, 55, 63]],
['Aravind',[42, 23, 34, 44, 53]],
['Lakshay',[32, 23, 13, 54, 67]],
['Gyan', [23, 82, 23, 63, 34]],
['Pranav', [21, 23, 25, 56, 56]]
]
for student in student_marks[1:]:
marks_in_C = student[1][2]
print(marks_in_C, end=" ")
total = sum(marks_in_C)
TypeError: 'int' object is not iterable
You can find the average of C in this two ways:
student_marks = [['Name', ['A','B','C','D','E']],
['Ankit', [41, 34, 45, 55, 63]],
['Aravind',[42, 23, 34, 44, 53]],
['Lakshay',[32, 23, 13, 54, 67]],
['Gyan', [23, 82, 23, 63, 34]],
['Pranav', [21, 23, 25, 56, 56]]
]
total_C = 0
for [name, [A, B, C, D, E]] in student_marks[1:]:
total_C += C
avg_of_C = total_C / len(student_marks[1:])
print(avg_of_C)
OR
student_marks = [['Name', ['A','B','C','D','E']],
['Ankit', [41, 34, 45, 55, 63]],
['Aravind',[42, 23, 34, 44, 53]],
['Lakshay',[32, 23, 13, 54, 67]],
['Gyan', [23, 82, 23, 63, 34]],
['Pranav', [21, 23, 25, 56, 56]]
]
marks_in_C = list()
for [name, [A, B, C, D, E]] in student_marks[1:]:
marks_in_C.append(C)
avg_of_C = sum(marks_in_C) / len(marks_in_C)
print(avg_of_C)
Welcome to Python world! The error occurred because you are using int type data to be iterated. sum() method expect iterable data but marks_in_C has only one integer which cannot be iterated
I think you are trying to use marks_in_C as a list. why don't you use your loop looks like this?
...
marks_in_C = list()
for student in student_marks[1:]:
marks_in_C.append(student[1][2])
print(marks_in_C, end=" ")
total = sum(marks_in_C)
hope it to help you.
I want to split m*n elements (e.g., 1, 2, ..., m*n) into n group randomly and evenly such that each group has m random elements. Each group will process k (k>=1) elements at one time from its own group and at the same speed (via some synchronization mechanism), until all group has processed all their own elements. Actually each group is in an independent process/thread.
I use numpy.random.choice(m*n, m*n, replace=False) to generate the permutation first, and then index the permuted result from each group.
The problem is that when m*n is very large (e.g., >=1e8), the speed is very slow (tens of seconds or minutes).
Is there any faster/lazier way to do this? I think maybe this can be done in a lazier way, which is not generating the permuted result in the first time, but generate a generator first, and in each group, generate k elements at each time, and its effect should be identical to the method I currently use. But I don't know how to achieve this lazy way. And I am not sure whether this can be implemented actually.
You can make a generator that will progressively shuffle (a copy of) the list and lazily yield distinct groups:
import random
def rndGroups(A,size):
A = A.copy() # work on a copy (if needed)
p = len(A) # target position of random item
for _ in range(0,len(A),size): # work in chunks of group size
for _ in range(size): # Create one group
i = random.randrange(p) # random index in remaining items
p -= 1 # update randomized position
A[i],A[p] = A[p],A[i] # swap items
yield A[p:p+size] # return shuffled sub-range
Output:
A = list(range(100))
iG = iter(rndGroups(A,10)) # 10 groups of 10 items
s = set() # set to validate uniqueness
for _ in range(10): # 10 groups
g = next(iG) # get the next group from generator
s.update(g) # to check that all items are distinct
print(g)
print(len(s)) # must get 100 distinct values from groups
[87, 19, 85, 90, 35, 55, 86, 58, 96, 68]
[38, 92, 93, 78, 39, 62, 43, 20, 66, 44]
[34, 75, 72, 50, 42, 52, 60, 81, 80, 41]
[13, 14, 83, 28, 53, 5, 94, 67, 79, 95]
[9, 33, 0, 76, 4, 23, 2, 3, 32, 65]
[61, 24, 31, 77, 36, 40, 47, 49, 7, 97]
[63, 15, 29, 25, 11, 82, 71, 89, 91, 30]
[12, 22, 99, 37, 73, 69, 45, 1, 88, 51]
[74, 70, 98, 26, 59, 6, 64, 46, 27, 21]
[48, 17, 18, 8, 54, 10, 57, 84, 16, 56]
100
This will take just as long as pre-shuffling the list (if not longer) but it will let you start/feed threads as you go, thus augmenting the parallelism
New to Jupyter Notebook, computing this code to return sum of values that are a multiple of 3 and 5, AND less than 100 in my list range 1, 100. I've got a feeling that I'm truncating the code by removing 3 and 5 from the equation. Not sure how/where to include that.
print(list(range(1, 100)))
multiple35 = 0
for i in range (1, 100):
if i % 15 == 0 and multiple35 <= 100:
multiple35 += i
print(multiple35)
My print line returns the range, Plus the 3 correct multiples less than 100. BUT ALSO prints 150, which is greater than and should be excluded from the result.
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99]
15
45
90
150
Appreciate your help here.
BUT ALSO prints 150, which is greater than and should be excluded from the result.
The reason is simple. You are testing multiple35 <= 100 before the addition (multiple35 += i). So the sum is printed first and then tested in the next round. Therefore the output ends after the first occurrence that is bigger than 100.
By the way, it is useless to go through all natural numbers and only do anything on each 15th element (because of i % 15 == 0). You can use a tailored range instead:
>>> list(range(15,100,15))
[15, 30, 45, 60, 75, 90]
So a simplified loop which would stop printing when reaching 100, could look like:
multiple35 = 0
for i in range (15, 100, 15):
multiple35 += i
if multiple35 > 100:
break # no reason to continue the loop, the sum will never go back below 100
print(multiple35)
You have to check if the final target will exceed the threshold, because in your loop, when i=75, it satisfies the condition 75%15==0 and also satisfies 75<=100 and since it satisfies both, we let it into the next block which adds 75 to it and gives 150 which exceeds the threshold. The solution is to not even allow a number inside the adding part if when added, crosses the threshold,
There are simpler solutions like above by #Melebius but, I wanted to explain this in the way OP has written
multiple35 = 0
for i in range (1, 100):
if i % 15 == 0 and multiple35+i<=100:
multiple35 += i
print(multiple35)
There are multiple flaws in your logic. I am not going to address them all, but instead suggest an alternate way to solve your issue.
Simply notice that multiples of 3 and 5 are exactly the multiples of 15. So there is no need to range over all numbers from 0 to 100.
for x in range(15, 100, 15):
print(x)
# 15
# 30
# 45
# 60
# 75
# 90
You also mention that you want to sum all numbers. In python, you can sum over any iterator with sum, including a range.
print(sum(range(15, 100, 15)))
# 315
You can use list comprehension also here
values = [i for i in range(1,100) if i%5==0 if i%3==0]
print("Numbers divisible by 3 and 5:",values)
sum_of_numbers = 0
for i,items in enumerate(values):
sum_of_numbers = sum_of_numbers+items
if sum_of_numbers>100:
break
print(values[:i])
I'm using a random.seed() to try and keep the random.sample() the same as I sample more values from a list and at some point the numbers change.....where I thought the one purpose of the seed() function was to keep the numbers the same.
Heres a test I did to prove it doesn't keep the same numbers.
import random
a=range(0,100)
random.seed(1)
a = random.sample(a,10)
print a
then change the sample much higher and the sequence will change(at least for me they always do):
a = random.sample(a,40)
print a
I'm sort of a newb so maybe this is an easy fix but I would appreciate any help on this.
Thanks!
If you were to draw independent samples from the generator, what would happen would be exactly what you're expecting:
In [1]: import random
In [2]: random.seed(1)
In [3]: [random.randint(0, 99) for _ in range(10)]
Out[3]: [13, 84, 76, 25, 49, 44, 65, 78, 9, 2]
In [4]: random.seed(1)
In [5]: [random.randint(0, 99) for _ in range(40)]
Out[5]: [13, 84, 76, 25, 49, 44, 65, 78, 9, 2, 83, 43 ...]
As you can see, the first ten numbers are indeed the same.
It is the fact that random.sample() is drawing samples without replacement that's getting in the way. To understand how these algorithms work, see Reservoir Sampling. In essence what happens is that later samples can push earlier samples out of the result set.
One alternative might be to shuffle a list of indices and then take either 10 or 40 first elements:
In [1]: import random
In [2]: a = range(0,100)
In [3]: random.shuffle(a)
In [4]: a[:10]
Out[4]: [48, 27, 28, 4, 67, 76, 98, 68, 35, 80]
In [5]: a[:40]
Out[5]: [48, 27, 28, 4, 67, 76, 98, 68, 35, 80, ...]
It seems that random.sample is deterministic only if the seed and sample size are kept constant. In other words, even if you reset the seed, generating a sample with a different length is not "the same" random operation, and may give a different initial subsequence than generating a smaller sample with the same seed. In other words, the same random numbers are being generated internally, but the way sample uses them to derive the random sequence is different depending on how large a sample you ask for.
You are assuming an implementation of random.sample something like this:
def samples(lst, k):
n = len(lst)
indices = []
while len(indices) < k:
index = random.randrange(n)
if index not in indices:
indices.append(index)
return [lst[i] for i in indices]
Which gives:
>>> random.seed(1)
>>> samples(list(range(20)), 5)
[4, 18, 2, 8, 3]
>>> random.seed(1)
>>> samples(list(range(20)), 10)
[4, 18, 2, 8, 3, 15, 14, 12, 6, 0]
However, that isn't how random.sample is actually implemented; seed does work how you think, it's sample that doesn't!
You simply need to re-seed it:
a = list(range(100))
random.seed(1) # seed first time
random.sample(a, 10)
>> [17, 72, 97, 8, 32, 15, 63, 57, 60, 83]
random.seed(1) # seed second time with same value
random.sample(a, 40)
>> [17, 72, 97, 8, 32, 15, 63, 57, 60, 83, 48, 26, 12, 62, 3, 49, 55, 77, 0, 92, 34, 29, 75, 13, 40, 85, 2, 74, 69, 1, 89, 27, 54, 98, 28, 56, 93, 35, 14, 22]
But in your case you're using a generator, not a list, so after sampling the first time a will shrink (from 100 to 90), and you will lose the elements that you had sampled, so it won't work. So just use a list and seed before every sampling.
This question already has answers here:
Modifying list while iterating [duplicate]
(7 answers)
Closed 8 years ago.
I have a function that takes two parameters (a list and an input number). I have code that breaks the input list into a smaller grouping of lists. I then need to check this new list and make sure all of the smaller lists are at least as long as the input number. However when I try to iterate over the sublists within my main list, for some reason certain sublists are excluded (in my example it is the sublist located at mainlist[1]. Any idea why this is happening???
def some_function(list, input_number)
...
### Here I have other code that further breaks down a given list into groupings of sublists
### After all of this code is finished, it gives me my main_list
...
print main_list
> [[12, 13], [14, 15, 16, 17, 18, 19], [25, 26, 27, 28, 29, 30, 31], [39, 40, 41, 42, 43, 44, 45]]
print "Main List 0: %s" % main_list[0]
> [12, 13]
print "Main List 1: %s" % main_list[1]
> [14, 15, 16, 17, 18, 19]
print "Main List 2: %s" % main_list[2]
> [25, 26, 27, 28, 29, 30, 31]
print "Main List 3: %s" % main_list[3]
> [39, 40, 41, 42, 43, 44, 45]
for sublist in main_list:
print "sublist: %s, Length sublist: %s, input number: %s" % (sublist, len(sublist), input_number)
print "index of sublist: %s" % main_list.index(sublist)
print "The length of the sublist is less than the input number: %s" % (len(sublist) < input_number)
if len(sublist) < input_number:
main_list.remove(sublist)
print "Final List >>>>"
print main_list
> sublist: [12, 13], Length sublist: 2, input number: 7
> index of sublist: 0
> The length of the sublist is less than the input number: True
> sublist: [25, 26, 27, 28, 29, 30, 31], Length sublist: 7, input number: 7
> index of sublist: 1
> The length of the sublist is less than the input number: False
> sublist: [39, 40, 41, 42, 43, 44, 45], Length sublist: 7, input number: 7
> index of sublist: 2
> The length of the sublist is less than the input number: False
> Final List >>>>
> [[14, 15, 16, 17, 18, 19], [25, 26, 27, 28, 29, 30, 31], [39, 40, 41, 42, 43, 44, 45]]
Why is my sublist located at mainlist[1] being completely skipped??? Thanks for any help in advance.
An 'if' in a list comprehension would work:
>>> x = [[12, 13], [14, 15, 16, 17, 18, 19], [25, 26, 27, 28, 29, 30, 31], [39, 40, 41, 42, 43, 44, 45]]
>>> [y for y in x if len(y)>=7]
[[25, 26, 27, 28, 29, 30, 31], [39, 40, 41, 42, 43, 44, 45]]
It looks like you're changing the list as you iterate over it. This is not allowed and can lead to undefined behavior.
See this answer.