Python: Coordinate Conversion - python

I have a slice of a set of lists of coordinates a[:,4]. It is in astronomical coordinates, which I'd like to convert to decimal. However, it currently doesn't work for negative astronomical coordinates. I currently have:
if any(a[:,4] < 0 ):
b[:,1] = a[:,4] - a[:,5]/60 - a[:,6]/3600 - a[:,7]/360000
else:
b[:,1] = a[:,4] + a[:,5]/60 + a[:,6]/3600 + a[:,7]/360000
print b
The aim of this is to get it to identify if the coordinate is negative or not from the a[:,4] coordinate and then process the other coordinates one way if it is negative, and the other way if it is positive. However, the "if any" line doesn't appear to be working.
For example, -09:24:40.25 should convert to -9.41118, but it currently converts to -8.58882, as the negative "hours" coordinate is then having the arcminute, arcsecond and milliarcsecond coordinates added to it, instead of them being subtracted.
I'm not sure what I'm doing wrong.
Thanks!

You can't use the any function like that assuming you're using a python list, as it takes an iterable and returns true if ANY of that iterable is true
a < 0
won't return an iterable
replace it with
[i < 0 for i in a[:,4]]
or
map(lambda x: x < 0 ,a[:,4])
so that the if statement becomes
if any(map(lambda x: x < 0,a[:,4])):
or
if any([i < 0 for i in a[:,4]])

Related

Sum of two squares in Python

I have written a code based on the two pointer algorithm to find the sum of two squares. My problem is that I run into a memory error when running this code for an input n=55555**2 + 66666**2. I am wondering how to correct this memory error.
def sum_of_two_squares(n):
look=tuple(range(n))
i=0
j = len(look)-1
while i < j:
x = (look[i])**2 + (look[j])**2
if x == n:
return (j,i)
elif x < n:
i += 1
else:
j -= 1
return None
n=55555**2 + 66666**2
print(sum_of_two_squares(n))
The problem Im trying to solve using two pointer algorithm is:
return a tuple of two positive integers whose squares add up to n, or return None if the integer n cannot be so expressed as a sum of two squares. The returned tuple must present the larger of its two numbers first. Furthermore, if some integer can be expressed as a sum of two squares in several ways, return the breakdown that maximizes the larger number. For example, the integer 85 allows two such representations 7*7 + 6*6 and 9*9 + 2*2, of which this function must therefore return (9, 2).
You're creating a tuple of size 55555^2 + 66666^2 = 7530713581
So if each element of the tuple takes one byte, the tuple will take up 7.01 GiB.
You'll need to either reduce the size of the tuple, or possibly make each element take up less space by specifying the type of each element: I would suggest looking into Numpy for the latter.
Specifically for this problem:
Why use a tuple at all?
You create the variable look which is just a list of integers:
look=tuple(range(n)) # = (0, 1, 2, ..., n-1)
Then you reference it, but never modify it. So: look[i] == i and look[j] == j.
So you're looking up numbers in a list of numbers. Why look them up? Why not just use i in place of look[i] and remove look altogether?
As others have pointed out, there's no need to use tuples at all.
One reasonably efficient way of solving this problem is to generate a series of integer square values (0, 1, 4, 9, etc...) and test whether or not subtracting these values from n leaves you with a value that is a perfect square.
You can generate a series of perfect squares efficiently by adding successive odd numbers together: 0 (+1) → 1 (+3) → 4 (+5) → 9 (etc.)
There are also various tricks you can use to test whether or not a number is a perfect square (for example, see the answers to this question), but — in Python, at least — it seems that simply testing the value of int(n**0.5) is faster than iterative methods such as a binary search.
def integer_sqrt(n):
# If n is a perfect square, return its (integer) square
# root. Otherwise return -1
r = int(n**0.5)
if r * r == n:
return r
return -1
def sum_of_two_squares(n):
# If n can be expressed as the sum of two squared integers,
# return these integers as a tuple. Otherwise return <None>
# i: iterator variable
# x: value of i**2
# y: value we need to add to x to obtain (i+1)**2
i, x, y = 0, 0, 1
# If i**2 > n / 2, then we can stop searching
max_x = n >> 1
while x <= max_x:
r = integer_sqrt(n-x)
if r >= 0:
return (i, r)
i, x, y = i+1, x+y, y+2
return None
This returns a solution to sum_of_two_squares(55555**2 + 66666**2) in a fraction of a second.
You do not need the ranges at all, and certainly do not need to convert them into tuples. They take a ridiculous amount of space, but you only need their current elements, numbers i and j. Also, as the friendly commenter suggested, you can start with sqrt(n) to improve the performance further.
def sum_of_two_squares(n):
i = 1
j = int(n ** (1/2))
while i < j:
x = i * i + j * j
if x == n:
return j, i
if x < n:
i += 1
else:
j -= 1
Bear in mind that the problem takes a very long time to be solved. Be patient. And no, NumPy won't help. There is nothing here to vectorize.

python program to find maximal in 2d array

I am trying to write program that print maximal points of the input but it is not giving correct output.
Definition of maximal-
Given a set of points P = {p1,p2,...,pn} in 2-space, each represented by its x and y integer coordinates, output the set of the maximal points of P, that is, those points pi, such that pi is not dominated by any other point of P (not both coordinate are dominated)
Example input:
p1(5,7),p2(47,84),p3(89,4),(46,54),(100,1)
Example outut:
p2(47,84),(89,4),(100,1)
The idea of my program is to first sort the point according to x axis then compare the y coordinate.
a=[[5,7],[47,84],[89,4][46,54],[100,1]]
#sort according to x axis
mylist.sort(key=lambda x: x[0])
#compare y coordinate of i to all element right to i
for i in reversed(range(len(a)):
j=i+1
while (j<len(a)):
if(mylist[i][1]>mylist[j][1]):
j+=1
if(j==len(a)):
print(mylist[i])
That's really not how you'd do that in Python. Use language elements that help you express what's going on, that way the code gets more understandable and, as a bonus, more concise. You want to find all elements of a for which no other element of a is greater in both coordinates:
a=[[5,7],[47,84],[89,4],[46,54],[100,1]]
for point in a:
if not any(map(lambda p: p[0] > point[0] and p[1] > point[1], a)):
print(point)
You could also use a list comprehension instead of map, which might be a bit more efficient:
a=[[5,7],[47,84],[89,4],[46,54],[100,1]]
for point in a:
if not any([p[0] > point[0] and p[1] > point[1] for p in a]):
print(point)

map values to a specific range

Let say we have some angular values from -inf to +inf as input.
I'd like to map them between only -180 and +180.
How could I properly achieve that?
Here's what I've found so far:
(i-180)%360-180
It works fine, but it maps +180 to -180 which I would like to be +180->+180.
Technically it's the same for my purpose so it's not a big deal, but it would be aesthetically better.
I'm working with Python but it doesn't really matter here.
If you don't value mathematical aestheticism as much, I think this could work
def f(i):
x = i % 360
if x > 180:
x -= 360
elif x == 180 and i < 0:
x = -x
return x
Suppose you have values in the range -inf to inf in a list sampleList[].
You need to map the values in sampleList[] in range -180 to 180. Lets name the new list of mapped elements as mappedList[]
Consider x as element in sampleList[]
Consider y as element in mappedList[]
Consider maxSL as maximum of sampleList[] and
minSL as minimum of sampleList[]
Therefore,
y = ((x - minSL)(((180-(-180))/(maxSL - minSL))) + (-180)

getting syntax error with <= sign

When using this code:
while str.find(target,key,n) != -1 and <= len(target):
I get a syntax error on 'less than or equal to sign'. Why?
In English we can say "if X is not equal to Y and also less than Z", but Python syntax doesn't work that way.
If you want to compare a number to two other numbers, you have to repeat the original number in the second comparison.
i.e., instead of this:
if x != y and < z:
you must do this:
if x != y and x < z:
If you want to use the double operand, you could rewrite it like:
if -1 < target.find(key, n) < len(target):
pass
But that said, I don’t think find can ever return a value larger than the length of target.

integer part of the root withot using functions

The calculation of the integer part of the square root of a number can be done by trial and error, starting from 1, by executing the square until the result is less than or equal to the starting value of which is calculated by the root.
The following program returns the integer part of the root
def radice(x):
z = 0
t = 0
while True:
t = z*z
if t > x:
z -= 1
return z
z += 1
radice(17) // 4
Will be possible to write it without using functions and break?
Here is my code witout function but I dont' know how to write the same algo with no break
z = 0
t = 0
while True:
t = z*z
if t > x:
z -= 1
break
z += 1
print 'The integer part of the root is: ', z
This should suffice:
>>> int(17**0.5)
4
17**0.5 generates the square root of 17, and int basically removes the decimals, leaving you with the "integer part of the root".
Without using any functions, and if you want an integer result, complex code (like your own) is needed. However, if a float will do, then you could try this:
>>> (17**0.5)//1
4.0
This essentially does the same as the int call, but will return a float if either side is a float.
As you said the integer part of the square root of a number can be done by trial and error, starting from 1, by executing the square until the result is less than or equal to the starting value of which is calculated by the root.
Said that you can write the code without using function and break statements; here is the code:
n = input("insert a number: ")
r = 1
while (r * r <= n):
r = r + 1
print "the result is:", r -1
Parens are for clarity, not required
>>> (17**.5)-(17**.5)%1
4.0
Ok, let's think logically.
You cannot use break, so the only way to get out of the while loop is to break its condition.
If it's True, it cannot be broken, so we have to think about the proper condition to stop iterating. And this condition is already used in your algorithm: you exit when t > x, or z * z > x. So the condition to continue iteration should be the opposite, i.e. z * z <= x. And we have this simple solution.
x = 17
z = 0
while z * z <= x:
z += 1
print 'The integer part of the root is: ', z - 1
As a general rule, try to shy away from those while True: loops. While they are sometimes useful, they're generally harder to read and understand, this is probably why your teacher limits the use of break. The function was prohibited probably because return is just another way of escaping the loop. But those are exceptional: the normal way to end a loop is to break its condition, so this is how it should be written.

Categories