According to answered solutions I have tested the loop. I want the range swtich from 6 to 10; 11 to 16 and so one until the condition is satisfied but the loop keep running from 1 to 5.
set_mean = -10
#calculated_mean = None
energy = []
calculated_mean = float('inf')
while calculated_mean > set_mean:
for i in range(1, 5):
energy.append(i-i*i)
print(energy)
calculated_mean = sum(energy[-2:])/2
print(calculated_mean)
How I can automate the range so that it switch to next five values in second loop and so on if the condition is not satisfied. For this example, it will satisfied if loop will run from 6 to 10.
Thanks!
Supposing you are just asking to do the dynamic way use the following:
set_mean = -10
#calculated_mean = None
energy = []
calculated_mean = float('inf')
x = 1
while calculated_mean > set_mean:
for i in range(x, x+4): # you can change step size here by passing it as last argument
energy.append(i-i*i)
print(energy)
calculated_mean = sum(energy[-2:])/2
print(calculated_mean)
x = x + 1
Output is:
[0]
0
[0, -2]
-1
[0, -2, -6]
-4
[0, -2, -6, -12]
-9
[0, -2, -6, -12, -2]
-7
[0, -2, -6, -12, -2, -6]
-4
[0, -2, -6, -12, -2, -6, -12]
-9
[0, -2, -6, -12, -2, -6, -12, -20]
-16
I think this is exactly what you want. Because the loop stops when you get -16
i don't see any conditionals, this loop will run forever as of your current version since calculated_mean will always be greater than set_mean since you are making the energy list larger every time you go through the loop, i don't really understand what your "condition" for calculates_mean is but if it's just the average of the last 2 numbers in the list it will never be greater than your set_mean which will result in an infinite loop.
Related
Using random numbers from a range of -10 to 10, I want to write a program that will change the places of two columns. A column that contains the maximum negative element, and a column that contains the minimum positive element of the matrix.Lets say the numbers are randomly generated so there can be no 10 or -10 for example lets say for the rows of maximum negative value lets say we have a range of -8 -2 3 5 so the maximum negative value here is -2 so the rows will change to -2 -8 3 5 and for the minimum postive value lets say a range of -4 -2 3 6 8 the number here is 3 so the range will change to 3 -4 -2 6 8 Here is the code that I am working on and this is how far I was able to go but I dont understand how I can introduce the max negative and min positive number. this is the idea that I have in head this is what i get but not sure how to use the maxi and mini in this not sure if i started the equation at the start correctly or not this is what i get with the code at the moment
import random
print("Enter number of cols:")
n = int(input())
print("Enter number of rows:")
m = int(input())
rows, cols = (m, n)
nums=[]
for i in range(rows):
col = []
for j in range(cols):
col.append(random.randint(-10, 10))
nums.append(col)
for row in nums:
print(row)
updatedNums = []
for i in range(rows):
col = []
for j in range(cols):
col.append(0)
updatedNums.append(col)
max_negative = max(nums for nums in nums if nums < 0)
min_positive = min(nums for nums in nums if nums > 0)
for i in range(rows):
for f in range(cols):
if nums[i][f] == max_negative:
updatedNums[i][j] = nums[i][j]
I think this is what you're trying to do. print statements added to show what the code is doing at each step
from random import randint
ncols = int(input('Number of columns: '))
nrows = int(input('Number of rows: '))
data = [[randint(-10, 10) for _ in range(ncols)] for _ in range(nrows)]
for r in data:
print('Original: ', r)
maxneg = max(n for n in r if n < 0)
r.insert(0, r.pop(r.index(maxneg)))
print('Max -ve moved: ', r)
minpos = min(n for n in r if n > 0)
r.insert(0, r.pop(r.index(minpos)))
print('Min +ve moved: ', r)
Example:
Number of columns: 8
Number of rows: 1
Original: [-3, -9, -9, -8, 2, -3, -2, -7]
Max -ve moved: [-2, -3, -9, -9, -8, 2, -3, -7]
Min +ve moved: [2, -2, -3, -9, -9, -8, -3, -7]
given_list3 = [7, 5, 4, 4, 3, 1, -2, -3, -5, -7]
total7 = 0
i = 0
while i <= len(given_list3) and given_list3[i] <= 0:
total7 += givenlist3[i]
i += 1
print(total7)
The code is producing a result of 0, and I want to to result in: -2 + -3 + -5 + -7 = -17
You can use comprehension:
given_list3 = [7, 5, 4, 4, 3, 1, -2, -3, -5, -7]
output = sum(x for x in given_list3 if x < 0)
print(output) # -17
In your current code, you are exiting the while loop even before the first iteration, because the second condition given_list3[i] <= 0 is false (since the first item 7 is greater than 0). If you want a working version, try the following. (Also you need to use i < len(...), not i <= len(...).)
given_list3 = [7, 5, 4, 4, 3, 1, -2, -3, -5, -7]
total7 = 0
i = 0
while i < len(given_list3):
if given_list3[i] <= 0:
total7 += given_list3[i]
i += 1
print(total7) # -17
A while loop stops when the condition is false. So your loop stops when it gets to the first positive value. Since the first element of the list is positive, the loop doesn't do anything.
The negative condition should be if inside the loop.
Also, list indexes go to len(list)-1, so the length condition should be <, not <=.
while i < len(given_list3):
if given_list3[i] <= 0:
total7 += given_list3[i]
i += 1
You should get out of the habit of looping over list indexes. Use for-in:
for item in given_list3:
if item <= 0:
total7 += item
You never iterate through your while loop.
On the first iteration i is 0 and the while-loop checks it's condition:
white 0 <= len(given_list3) and given_list3[i] < = 0:
...
given_list3[i] when i is 0 is given_list3[0] which is 7. 7 is not less than or equal to 0. The whole condition fails and the while loop is done.
The statements in the while-loop get executet as long as the condition is true. In your sample the condition is already false the first time it is checked and the statements in the while-loop never get executed.
Trying to sum up all the negative numbers in a list using while loop.
given_list_02 = [9, 8, 5, 3, -1, -2, -3, -6]
total3 = 0
i = 0
while True:
if given_list_02[i] >= 0:
i+= 1
else:
total3+= given_list_02[i]
i+= 1
Using for loop (recommended)
In python, for loops are based on iterators. As such, we are able to iterate over the values in the list rather than using a while True loop that updates an index i. This also makes sure we don't get an index out of bound error when i becomes larger than the length of the list:
given_list_02 = [9, 8, 5, 3, -1, -2, -3, -6]
numOfNegatives = 0
for num in given_list_02:
if num < 0:
numOfNegatives+=num
print(numOfNegatives)
Using while loop (not recommended)
You need a terminating condition for the while loop. If we think about what while True does, it will infinitely increment the i variable. So what would happen when i becomes 9? At this point, given_list_02[i] does not exist as given_list_02 only has 8 elements. This is why we need to stop iterating i once it hits 8:
given_list_02 = [9, 8, 5, 3, -1, -2, -3, -6]
total3 = 0
i = 0
while i < len(given_list_02):
if given_list_02[i] >= 0:
i+= 1
else:
total3+= given_list_02[i]
i+= 1
print(total3)
Your while loop does not have a break condition, so it will run indefinitely. As you are accessing list elements, you will access an index out out range at some point.
Try something like this
given_list_02 = [9, 8, 5, 3, -1, -2, -3, -6]
total3 = 0
for e in given_list_02:
if e < 0:
total3 += e
Since you commented, that you want to use a while loop for training purposes, try this:
given_list_02 = [9, 8, 5, 3, -1, -2, -3, -6]
total3 = 0
i = 0
while i < len(given_list_02):
if given_list_02[i] < 0:
total3 += given_list_02[i]
i += 1
Keep in mind though, that you really should prefer the for loop in this case.
I want to do a simple program that prints all the numbers in a range A to B, including B.
For ranges having bounds in increasing order, I know that I have to add 1 to the upper bound, like:
range(A, B+1)
But adding 1 to B won't work when the bounds are in decreasing order, like range(17, 15, -1).
How can I code it to work for both increasing and decreasing ranges?
I see why you are facing this issue. Its because you are using the larger value as the first argument and smaller value at the second argument in the range (This is happening due to the negative sign).
For such cases following code will work :
a = 5
b = -5
step = 1
if b < 0:
step = -1
range (a, b + step, step)
I think I don't understand the question properly. There are 3 cases:
A, B both positive
A negative, B positive
A, B both negative
Now if I do this (in Python 2, to avoid having to do list(range(...)): this makes the explanation cleaner):
>>> A = 10; B = 20 # case 1
>>> range(A,B+1)
[10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]
>>> A = -10; B = 2 # case 2
>>> range(A,B+1)
[-10, -9, -8, -7, -6, -5, -4, -3, -2, -1, 0, 1, 2]
>>> A = -10; B = -2 # case 3
>>> range(A,B+1)
[-10, -9, -8, -7, -6, -5, -4, -3, -2]
So your remark the last number in the range won't be included doesn't seem to fit with what I can see.
If you are receiving input data where A > B, then the problem is not the negative number, but the fact that range() expects the values to be in ascending order.
To cover that:
>>> A = 2; B = -2 # case 4
>>> A,B = sorted((A,B))
>>> range(A,B+1)
[-2, -1, 0, 1, 2]
This also works for cases 1, 2, and 3.
If I have misunderstood the question please edit it to clarify.
Please check if this works. Thank you.
if A>B and A < 0 and B < 0:
print(list(range(A,B,-1)))
elif A<B:
print(list(range(A,B)))
else:
print(list(range(A,B,-1)))
You could create a function that turns a normal range into one that includes both bounds, like:
def inclusive(r):
return range(r.start, r.stop + r.step, r.step)
You should pass it a range, and it will return a range:
increasing_range = range(2, 5)
print(list(inclusive(increasing_range)))
# [2, 3, 4, 5]
decreasing_range = range(5, -5, -1)
print(list(inclusive(decreasing_range)))
# [5, 4, 3, 2, 1, 0, -1, -2, -3, -4, -5]
even = range(2, 10, 2)
print(list(inclusive(even)))
# [2, 4, 6, 8, 10]
for odd in inclusive(range(1, 5)):
print(odd)
# 1 2 3 4 5
Last number is never included in python range. You need to adjust the code accordingly.
e.g.
To print values form -5 to -1(included) use,
>>> print(list(range(-5, 0)))
[-5, -4, -3, -2, -1]
In reverse order
>>> print(list(range(-1, -6, -1)))
[-1, -2, -3, -4, -5]
I am new on python (and even programing!), so I will try to be as clear as I can to explain my question. For you guys it could be easy, but I have not found a satisfactory result on this yet.
Here is the problem:
I have an array with both negative and positive values, say:
x = numpy.array([1, 4, 2, 3, -1, -6, -6, 5, 6, 7, 3, 1, -5, 4, 9, -5, -2, -1, -4])
I would like to sum ONLY the negative values that are continuous, i.e. only sum(-1, -6, -6), sum(-5, -2, -1, -4) and so on. I have tried using numpy.where, as well as numpy.split based on the condition.
For example:
for i in range(len(x)):
if x[i] < 0.:
y[i] = sum(x[i])
However, as you can expect, I just got the summation of all negative values in the array instead. In this case sum(-1, -6, -6, -5, -5, -2, -1, -4)
Could guys share with me an aesthetic and efficient way to solve this problem? I will appreciate any response on this.
Thank you very much
You can use itertools module, here with using groupby you can grouping your items based on those sign then check if it meet the condition in key function so it is contains negative numbers then yield the sum else yield it and at last you can use chain.from_iterable function to chain the result :
>>> from itertools import groupby,tee,chain
>>> def summ_neg(li):
... for k,g in groupby(li,key=lambda i:i<0) :
... if k:
... yield [sum(g)]
... yield g
...
>>> list(chain.from_iterable(summ_neg(x)))
[1, 4, 2, 3, -13, 5, 6, 7, 3, 1, -5, 4, 9, -12]
Or as a more pythonic way use a list comprehension :
list(chain.from_iterable([[sum(g)] if k else list(g) for k,g in groupby(x,key=lambda i:i<0)]))
[1, 4, 2, 3, -13, 5, 6, 7, 3, 1, -5, 4, 9, -12]
Here's a vectorized NumPythonic solution -
# Mask of negative numbers
mask = x<0
# Differentiation between Consecutive mask elements. We would look for
# 1s and -1s to detect rising and falling edges in the mask corresponding
# to the islands of negative numbers.
diffs = np.diff(mask.astype(int))
# Mask with 1s at start of negative islands
start_mask = np.append(True,diffs==1)
# Mask of negative numbers with islands of one isolated negative numbers removed
mask1 = mask & ~(start_mask & np.append(diffs==-1,True))
# ID array for IDing islands of negative numbers
id = (start_mask & mask1).cumsum()
# Finally use bincount to sum elements within their own IDs
out = np.bincount(id[mask1]-1,x[mask1])
You can also use np.convolve to get mask1, like so -
mask1 = np.convolve(mask.astype(int),np.ones(3),'same')>1
You can also get the count of negative numbers in each "island" with a little tweak to existing code -
counts = np.bincount(id[mask1]-1)
Sample run -
In [395]: x
Out[395]:
array([ 1, 4, 2, 3, -1, -6, -6, 5, 6, 7, 3, 1, -5, 4, 9, -5, -2,
-1, -4])
In [396]: out
Out[396]: array([-13., -12.])
In [397]: counts
Out[397]: array([3, 4])
you can flag negative values .... and do this with plain python
prev = False
for i,v in enumerate(a):
j = i + 1
if j < len(a):
if a[i] < 0 and a[j] < 0:
temp.append(v)
prev = True
elif a[i] < 0 and prev:
temp.append(v)
prev = True
elif a[i] > 0:
prev = False
else:
if prev and v < 0:
temp.append(v)
output
print(temp)
[-1, -6, -6, -5, -2, -1, -4]
with intertools i would do just that
def sum_conseq_negative(li):
neglistAll = []
for k, g in groupby(li, key=lambda i:i<0):
negList = list(g)
if k and len(negList) > 1:
neglistAll.extend(negList)
return sum(negList), len(negList)
sumOf, numOf = sum_conseq_negative(li)
print("sum of negatives {} number of summed {}".format(sumOf,numOf))
sum of negatives -25 number of summed 7