Let Python find two integers satisfying condition - python

Set-up
I'm looking for all the integer pairs (x,y) in 2 closed sets: [822,2000] and [506,1231] such that x/y=1.624.
Code so far
I tried,
a = [[(x,y)] for x in range(822,2001) and y in range(506,1232) if x/y = 1.624]
But this gives a SyntaxError: invalid syntax pointing to the = in the code.
And if I do,
a = [[(x,y)] for x in range(822,2001) and y in range(506,1232) if x/y <= 1.624]
I get NameError: name 'y' is not defined.
How do I solve this?

Comparing float calculations with == is difficult due to the nature of float arithmetics.
It is often better to compare like this:
a = [(x,y) for x in range(822,2001) for y in range(506,1232) if abs(x/y - 1.624) < 0.00001]
print(set(a))
By substracting the wanted value from your result and and comparing its absolute value against something kindof small you get better results.
Result (using a set):
{(1624, 1000), (1637, 1008), (1015, 625), (1611, 992), (1840, 1133),
(1814, 1117), (1827, 1125), (1408, 867), (1218, 750), (1434, 883),
(1421, 875)}
Python rounding error with float numbers

For the first one you are using the assignment operator instead of the equivalent operator so it should be:
a = [[(x,y)] for x in range(822,2001) and y in range(506,1232) if x/y == 1.624]
And for the second you're probably better off using two for loops
a = [[(x,y)] for x in range(822,2001) for y in range(506,1232) if x/y <= 1.624]
The second one would not make sense as you said it because x and y are coming from lists that have an unequal number of elements so you cannot loop over them like that

Related

round a number to a range of numbers Python

I have two arrays:
X = np.linspace(0,100,101) and Y = np.linspace(0,100,15). How to make the values of one array be rounded to the values of the other array. that is, I finally have an array of size 101 but the values of the array X came close to the nearest values of the array Y.
Like this?
Y[np.absolute(X[:,np.newaxis]-Y).argmin(axis=1)]
The simplest way is to use X array to produse Y array. Like this:
Y = X[::len(X)//15]
But it'll give you a little biased numbers.
For this particular case you also can use simple round function:
Y = np.array(list(map(round, Y)))
In general, you can solve this by searching for the minimal difference between elements in arrays:
Y = X[[abs(X-i).argmin() for i in Y]]

Using list comprehension with over 4 conditions

I have a list of lists. Each sub-list contains two integer elements. I would like to multiply each of these elements by 1.2 and if they are positive and bigger then a certain number, change them to be that certain number. same thing if they are smaller.
The multiplication bit I achieved using list comprehension. With these extra conditions, I'm getting a little lost - to me, it seems overly complicated and even non pythonic. I was wondering if I can get some opinions.
The multiplication bit I achieved using list comprehension. With these extra conditions, I'm getting a little lost - to me, it seems overly complicated and even non pythonic. I have a rough idea on how to put all the conditions in the list comprehension, but when I started implementing them I got confused. I was wondering if I can get some opinions.
MAX_VOL = 32767 # audio data is the list of lists
MIN_VOL = -32767
audio_list = [[int(x*1.2), int(y*1.2)] for x, y in audio_data]
# My idea was something like:
audio_list = [[int(x*1.2), int(y*1.2) if x > MAX_VOL x == MAX VOL if x < MIN_VOL....] for x, y in audio_data]
Firstly, I'm pretty sure there is a syntax issue. But, for each number, I have to check if its positive or negative, then, if it is bigger or smaller then max/min volume. So, is this possible using list comprehension? Is it efficient and pythonic?
Thank you so much!
Use min and max:
MAX_VOL = 32767 # audio data is the list of lists
MIN_VOL = -32767
audio_list = [[int(max(MIN_VOL, min(MAX_VOL, x*1.2))), int(max(MIN_VOL, min(MAX_VOL, y*1.2)))] for x, y in audio_data]
And since these are long expressions, use a function, too:
def clip(s):
return int(max(MIN_VOL, min(MAX_VOL, s)))
audio_list = [[clip(x*1.2)), clip(y*1.2)] for x, y in audio_data]
Define a bounding function that doesn't let the value exceed the max or min volume. Then you can still use list comprehension.
MAX_VOL = 32767 # audio data is the list of lists
MIN_VOL = -32767
# Ensure volume does not exceed limits.
def bounded(val):
if val > MAX_VOL:
return MAX_VOL
elif val < MIN_VOL:
return MIN_VOL
return val
audio_list = [[bounded(int(x*1.2)), bounded(int(y*1.2))] for x, y in audio_data]
If a list comprehension is too complex, then don't use it. You should try and make your solution easy for someone else to understand and for you to understand if you come back to it in a year.
for x,y in audio_data:
if x > MAX_VOL:
foo = int(x*1.2)
bar = int(y*1.2)
if x == MAX_VOL:
...

Python - If array is in range of other array

Meaning "if each item is within range of other item with the same index".
price = [1, 2]
budget = [5, 7]
This works:
if price[0] in range(budget[0]) and price[1] in range(budget[1]):
affordable = True
I figure there's some way to just reference the whole array though. Like so: if price in budget:
You could use:
if all(x in range(y) for x,y in zip(price,budget)):
affordable = True
This will create tuples of price[i],budget[i] and then for each of these tuples we check that price[i] is in range(budget[i]). Nevertheless, you can optimize this further to:
if all(0 <= x < y for x,y in zip(price,budget)):
affordable = True
Note that this makes the assumption that prices are all integers. If you however use x in range(y) it will fail if x is not an integer. So 0.7 in range(10) would fail whereas our second approach will succeed (but it depends of course on what you want).
Assuming that both prices and budgets must be non-negative, using in range seems to be over-complicating things. Instead, you could just use the < operator.
Regardless of whether you use < or in range, it seems like the easiest approach would be to zip both lists and apply the condition on the pairs:
if (all([x[0] >= x[1] for x in zip(budget, price)])):
affordable = True

Unpacking a tuple in python and iterating over it

I'm trying to unpack a co-ord tuple then iterate over it to blit a sprite multiple times:
def updateMap(self, playerPosition):
self.x_coord, self.y_coord = playerPosition
t = Tree(self.screen)
for x in range(self.x_coord):
for y in range(self.y_coord):
self.screen.fill((0,104,0))
t.drawTree((x, y))
However I get the following error:
File "unnamed.py", line 26, in updateMap
for x, y in range(self.x_coord), range(self.y_coord):
ValueError: need more than 0 values to unpack
Grateful if someone can point me in the right direction on the correct way to do this. Thanks.
EDIT: I have edited my code to the above to iterate over every coord say if playerPostion is 0,5 so the iteration goes (0,1) (0,2) (0,3) (0,4) (0,5) -- but although I'm not getting any errors it seems the tree does not get drawn correctly. Thanks.. it seems to be the answer, except my coding is just wrong.
I think this is what you want instead:
from itertools import product
self.x_coord, self.y_coord = playerPosition #playerPosition is a tuple
t = Tree(self.screen)
for x,y in product(range(self.x_coord+1), range(self.y_coord+1)):
self.screen.fill((0,104,0))
t.drawTree((x, y))
I think the OP wants to iterate over the range of X co-ordinates and the range of Y co-ordinates to create a (x,y) for each case.
for x in range(self.x_coord):
for y in range(self.y_coord):
print(x, y)
Use the built in Python zip function assuming both of the iterables are of the same length. If not then you will need to do a bit of sanitization before to ensure they are.
for x, y in zip(range(self.x_coord), range(self.y_coord))
Maybe if you change:
self.x_coord = 0
self.y_coord = 0
playerPosition = self.x_coord, self.y_coord
to:
self.x_coord, self.y_coord = playerPosition
then you get the player position x and y in to self.x_coord and self.y_coord
And to iterate over every combination of x and y you either need to put a loop over y range inside inside a loop over the x range
for x in range(self.x_coord):
for y in range(self.y_coord):
self.screen.fill((0,104,0))
t.drawTree((x, y))

Basic Python programming help needed: Arrays and random locations

Consider a 100X100 array.
i) Generate an array of several thousand random locations within such an array, e.g. (3,75) and (56, 34).
ii) Calculate how often one of your random locations falls within 15 pixels of any of the (straight) edges.
I am trying to do the above question in order to help me to learn the programming language Python, i am new to programming.
Here is what i have got so far:
from __future__ import division
from pylab import *
import math as m
from numpy import *
from random import randrange
N = 3000
coords_array = array([randrange(100) for _ in range(2 * N)]).reshape(N, 2)
This creates the array of N random locations, and no i am trying to create a loop that will append a 1 to an empty list if x>85 or y>85 or x<15 or y<15, then append a zero to the same empty list if x or y is anything else. Then i would find the sum of the list, which would be my count of how many of the random location fall within the edges.
This is the kind of thing i am trying to do:
coordinate=coords_array[x,y]
b=[]
def location(x,y):
if x>85 or y>85:
b.appnend(1)
if x<15 or y<15:
b.append(1)
else:
b.append(0)
print b
print x
But i am having trouble assigning the array as x and y variables. I want to be able assign each row of the set of random coordinates as an x,y pair so that i can use it in my loop.
But i do not know how to do it!
Please can someone show me how to do it?
Thank you
Ok, the answer to this:
But i am having trouble assigning the array as x and y variables. I
want to be able assign each row of the set of random coordinates as an
x,y pair so that i can use it in my loop
Would be this:
for pair in coords_array:
# Do something with the pair
NumPy arrays behave as regular Python sequences by letting for to iterate over their main axis, meaning pair will contain an array of (in your case) two elements: x and y. You can also do this:
for x, y in coords_array:
# Do something with the pair
NB: I think you wanted to write the function like this:
def location(x,y):
if x>85 or y>85:
b.append(1)
elif x<15 or y<15:
b.append(1)
else:
b.append(0)
or
def location(x,y):
if x>85 or y>85 or x<15 or y<15:
b.append(1)
else:
b.append(0)
or even
def location(x,y):
if not (15 <= x <= 85) or not (15 <= y <= 85):
b.append(1)
else:
b.append(0)
Otherwise, as #TokenMacGuy points out, you'd be inserting two values in certain cases.
NB: from your question I understand you want to write this code specifically to learn Python, but you could do this in a much more straightforward (and efficient) way by just using NumPy functionality
You can let numpy do the looping for you:
n = 3000
coords = np.random.randint(100, size=(n, 2))
x, y = coords.T
is_close_to_edge = (x < 15) | (x >= 85) | (y < 15) | (y >= 85)
count_close_to_edge = np.sum(is_close_to_edge)
Note that the first index of a 100 element array is 0 and the last 99, hence items within 15 positions of the edges are 0...14 and 85...99, hence the >= in the comparison. In the code above, is_close_to_edge is your list, with boolean values.

Categories

Resources