Sum up the third value for conditions - python

I want to write a quick calculation in python, not sure how to approach this:
values = [(0, 4, .3), (6, 2, 3), (3, 7, 2.2), (5, 5, .5), (3, 5, .8), (7, 7, .3)]
say we use (x, y, z) to represent tuples in values
criteria = [(a, b, c, d)]
if (a <= x < b) and (c <= y < d),
then sum up all the z in the values.
My result is just to show the sum of z that satisfy the above criteria

You could use list comprehension to achieve that in one line.
# Criteria
(a, b, c, d) = (-1, 10, 0, 10)
# Output
zs = [z for (x, y, z) in values if a <= x < b and c <= y < d]
print(sum(zs))
Not fully sure why you specified the criteria as an array, but I think that example is easy to extend in case you want to check for multiple criterias.

Related

Filtering a pair of arrays for a certain range of numbers using python

So let's say I have two arrays x and y.
x = [5, -6, 3, 11, -4, 2]
y = [1, 9, 2, 8, 12, -5]
I need to filter these arrays, keeping only values between 0 and 10. I was able to do this separately:
new_x=[i for i in x if i>=0 and i<=10] with output
[5, 3, 2]
new_y=[i for i in y if i>=0 and i<=10] with output
[1, 9, 2, 8]
However, these x and y arrays are meant to symbolize coordinates, which I will later have to graph. They have to remain in pairs, so if an element in the x array does not fulfill the criteria, I do not want to include the matching y element. Same goes vice versa.
By looking at the arrays, it is easy to tell that only the first and third pair - (5,1) and (3,2) respectively - fulfill my criteria. How can I filter x and y together to represent this? My dataset is much larger than this example, so I do not have the time to filter through it manually.
Any help would be greatly appreciated!
zip them together:
pairs = [(a, b) for a, b in zip(x, y) if 0 <= a <= 10 and 0 <= b <= 10]
# [(5, 1), (3, 2)]
If you then want to go back to x, y (I wouldn't recommend this, just keep them together), you could use:
x, y = zip(*pairs)
Which will return x and y as tuples:
x = (5, 3)
y = (1, 2)
In this context, the two tuples look like ordered pairs, but in general you could get something like
x = (5, 3, -6, 11, ...)
You can use the filter function
filtered_coords = list(
filter(lambda coords: all([0 <= coord <= 10 for coord in coords]), zip(x, y))
)
If you want to split the x and y coordinates:
filtered_x, filtered_y = [[c[i] for c in filtered_coords] for i in range(2)]
print(filtered_x) # [5, 3]
print(filtered_y) # [1, 2]
Use the same index to point to both arrays at the same time.
x = [5, -6, 3, 11, -4, 2]
y = [1, 9, 2, 8, 12, -5]
new_x = []
new_y = []
for i in range(len(x)):
if 0 <= x[i] <= 10 and 0 <= y[i] <= 10:
new_x.append(x[i])
new_y.append(y[i])
print(new_x, new_y)
# [5, 3] [1, 2]

How to find the number of pairs of non-coprimes in two given arrays in python?

How to go about finding the number of non-coprimes in a given array?
Suppose
a = [2, 5, 6, 7]
b = [4, 9, 10, 12]
Then the number of non-coprimes will be 3, since You can remove:
(2, 4)
(5, 10)
(6, 9)
n = int(input())
a = list(map(int, input().split()))
b = list(map(int, input().split()))
count = 0
len_a = len(a)
len_b = len(b)
for i in range(len_a):
for j in range(len_b):
x = a[i]
y = b[j]
if(math.gcd(x,y) != 1):
count += 1
print(count)
This is in reference to :https://www.hackerrank.com/challenges/computer-game/problem
I am receiving 8 as output.
Why do you expect the answer to be 3?
You're pairing 5 and 10, so you're obviously looking at pairs of elements from a and b disregarding their position.
Just print out the pairs and you'll see why you're getting 8...
import math
from itertools import product
a=[2, 5, 6, 7]
b=[4, 9, 10, 12]
print(sum([math.gcd(x, y) != 1 for x, y in product(a, b)])) # 8
print([(x, y) for x, y in product(a, b) if math.gcd(x, y) != 1]) # the pairs
Update: After reading the problem the OP is trying to handle, it's worth pointing out that the expect output (3) is the answer to a different question!
Not how many pairs of elements are not coprime, but rather how many non-coprime pairs can be removed without returning them into the arrays.
This question is actually an order of magnitude more difficult, and is not a matter of fixing one's code, but rather about giving the actual problem a lot of mathematical and algorithmic thought.
See some discussion here
Last edit, a sort-of solution, albeit an extremely inefficient one. The only point is to suggest some code that can help the OP understand the point of the original question, by seeing some form of solution, however low-quality or bad-runtime it is.
import math
from itertools import product, permutations
n = 4
def get_pairs_list_not_coprime_count(pairs_list):
x, y = zip(*pairs_list)
return min(i for i in range(n) if math.gcd(x[i], y[i]) == 1) # number of pairs before hitting a coprime pair
a = [2, 5, 6, 7]
b = [4, 9, 10, 12]
a_perms = permutations(a) # so that the pairing product with b includes all pairing options
b_perms = permutations(b) # so that the pairing product with a includes all pairing options
pairing_options = product(a_perms, b_perms) # pairs-off different orderings of a and b
actual_pairs = [zip(*p) for p in pairing_options] # turn a pair of a&b orderings into number-pairs (for each of the orderings possible as realized by the product)
print(max(get_pairs_list_not_coprime_count(pairs_list) for pairs_list in actual_pairs)) # The most pairings managed over all possible options: 3 for this example
I believe the answer should be 8 itself. Out of the 4*4 possible combinations of numbers that you are comparing, there are 8 coprimes and 8 non-coprimes.
Here is an implementation of the code with the gcd function without using math and broadcasting to avoid multiple loops.
import numpy
a = '2 5 6 7'
b = '4 9 10 12'
a = np.array(list(map(int,a.split())))
b = np.array(list(map(int,b.split())))
def gcd(p,q):
while q != 0:
p, q = q, p%q
return p
def is_coprime(x, y):
return gcd(x, y) == 1
is_coprime_v = np.vectorize(is_coprime)
compare = is_coprime_v(a[:, None], b[None, :])
noncoprime_pairs = [(a[i],b[j]) for i,j in np.argwhere(~compare)]
coprime_pairs = [(a[i],b[j]) for i,j in np.argwhere(compare)]
print('non-coprime',noncoprime_pairs)
print('coprime',coprime_pairs)
non-coprime [(2, 4), (2, 10), (2, 12), (5, 10), (6, 4), (6, 9), (6, 10), (6, 12)]
coprime [(2, 9), (5, 4), (5, 9), (5, 12), (7, 4), (7, 9), (7, 10), (7, 12)]
Same solution but using the math.gcd() -
import math
import numpy
a = '2 5 6 7'
b = '4 9 10 12'
a = np.array(list(map(int,a.split())))
b = np.array(list(map(int,b.split())))
def f(x,y):
return math.gcd(x, y) == 1
fv = np.vectorize(f)
compare = fv(a[:, None], b[None, :])
noncoprime_pairs = [(a[i],b[j]) for i,j in np.argwhere(~compare)]
print(noncoprime_pairs)
[(2, 4), (2, 10), (2, 12), (5, 10), (6, 4), (6, 9), (6, 10), (6, 12)]
If you are looking for the answer to be 3 in your example, I would assume you are counting the number of values in a that have at least one non-coprime in b.
If that is the case you could do it like this:
from math import gcd
def nonCoprimes(A,B):
return sum(any(gcd(a,b)>1 for b in B) for a in A)
print(nonCoprimes([2,5,6,7],[4,9,10,12])) # 3
So, for each value in a check if there are any values of b that don't have a gcd of 1 with the value in a

List multiplication in Python

I need to multiply different lists to calculate areas of irregular polygons.
X = [1,1,1,1,1,1]
Y = [5,4,3,2,1,0]
This means that coordinates from point 1 are (1,5), for point 2 are (1,4) and so on. To calculate the area I need to multiply X[i] * Y[i+1] which is equal to 1 * 4, 1 * 3, 1 * 2 and exlude the last multiplication, such as 1 * empty.
How can I do this?
So, in my understanding, you need a lag between X and Y, where the first element of Y is excluded, and the last element of X is excluded. In other words, you need something like:
[(1, 4), (1, 3), (1, 2), (1, 1), (1, 0)]
You can produce the above via:
zipped = zip(X[:-1], Y[1:])
and you can compute the products of each pair like so:
[a * b for a, b in zipped]
Of course, if X and Y were numpy arrays, you could do this much more efficiently:
>>> X[:-1] * Y[1:]
array([4, 3, 2, 1, 0])
Something like
[x * y for x, y in zip(X, Y[1:])]
would do it. But you should really use Numpy for anything non-trivial.

Python: make new list based on inputs and two previous lists

I'm a newcomer to coding and am using Python 3.6. I am writing some code for an engineering application which involves storing data in lists based upon inputs. I currently have two lists and I want to create a new one based upon inputs and the content of the first two lists. I have shown a simplified example below (not prompting the user for an input to keep things simple).
a = 40
a = float(a)
b = 10
b = float(b)
c = [1, 2, 3, 4, 5]
d = [2, 4, 6, 8, 10]
e = [(a / b) if x == 1 else x * y for x in c and y in d]
print(e)
So basically I need a way to say for x in c and y in d together. In this case the answer I would hope to achieve is [4, 8, 18, 32, 50]
e = [(a / b) if x == 1 else x * y for x, y in zip(c, d)].
For example, list(zip([1,2,3], [4,5,6])) would be [(1, 4), (2, 5), (3, 6)].

Number of pairs

I am trying to write a code that takes
m. a, a list of integers
n. b, an integer
and returns the number of pairs (m,n) with m,n in a such that |m-n|<=b.
So far, I've got this
def nearest_pairs(a, b):
m= []
n= int
num_pairs = 0
return num_pairs
def main():
# The nearest pairs are (1,2), (2,1), (2,5) and (5,2)
x = nearest_pairs( [1,2,5] , 3 )
print( "nearest_pairs([1, 2, 5], 3) = " , nearest_pairs([1, 2, 5], 3) )
# The nearest pairs are (1,2) and (2,1)
y = nearest_pairs( [1, 2, 5] , 2 )
print( "nearest_pairs([1, 2, 5], 2) = " , nearest_pairs([1, 2, 5], 2) )
if __name__ == '__main__':
main()
The desired output should look like
>>> nearest_pairs([1,2,5],3) = 4
where 4 is the number of close pairs according to the restrictions. However, I get an error. Could anyone lead me to the right direction?
Yours doesn't make sense. No idea what you're trying with len(a, b), but it's not even allowed, since len takes only one argument. And returning something just when you found the first counting pair? Here's a fix:
def close_pairs(l, d):
ctr = 0
for a,b in permutations(l, 2):
if (a - b) <= d and (b - a) <= d:
ctr += 1
return ctr
And here's how I'd do it:
def close_pairs(l, d):
return sum(abs(a-b) <= d for a, b in permutations(l, 2))
from itertools import permutations
def nearest_pairs(a, b):
for m, n in permutations(a, 2):
if abs(m - n) <= b:
yield (m, n)
>>> list(nearest_pairs([1, 2, 5], 3))
[(1, 2), (2, 1), (2, 5), (5, 2)]
>>> list(nearest_pairs([1, 2, 5], 2))
[(1, 2), (2, 1)]
If you just want the count:
def nearest_pairs_count(a, b):
c, l = 0, len(a)
for i in range(l):
for j in range(i + 1, l):
if abs(a[i] - a[j]) <= b:
c += 2
return c

Categories