python nested for loop zip - python

I have the following list:
grid = [[0] *50 for n in range(50)]
I want to replace the values in grid (with 1) for each coordinate contained in the list:
area = [(30, 28), (27, 32), (32, 34), (43,23), (43, 2) ...] # Continues on
Is there any simple method that this can be done?

A simple for loop is what is needed.
for i,j in area:
grid[i][j] = 1

Related

compute all n-th closest points of all points in a dataset

I have dataset of 1000 points on a plane. I represented all the possible pairs of points in P and calculated the distances of all possible pairs.
What I have to do is: For a given n, calculate all the n-th nearest points for all points p in P.
What I did before:
P_pairs = [((33, 9), (34, 13)), ((33, 9), (62, 119)), ((33, 9), (33, 7)), ((33, 9), (48, 123)), ...]
listofdistances = [{'((33, 9), (34, 13))': 4.123105625617661}, {'((33, 9), (62, 119))': 113.75851616472501}, {'((33, 9), (33, 7))': 2.0}, ...]
In this context, I am stuck in sorting listofdistances such that for every point, there are the minimum n distances as values left.
Maybe I have to calculate the n-th nearest points directly, instead of calculating all the distances of the points. But I don't exactly know how.
P = [(33, 9), (34, 13), (62, 119), (33, 7), (48, 123)]
P = np.array(P)
x, y = P[:,0], P[:,1]
# Create a distance table of point (row) vs point (column)
dist = np.sqrt((x - x[:,None])**2 + (y - y[:,None])**2)
# The diagonals are 0, as the distance of a point to itself is 0,
# but we want that to have a large value so it comes last in sorting
np.fill_diagonal(dist, np.inf)
# Get the sorted index for each row
idx = dist.argsort(axis=1)
Now if you want the nth nearest neighbours, with n = 3, you get that with idx = idx[:,:3]. And for the first point you can now do
P[0] # the point itself
P[idx[0]] # its nearest neighbours
dist[0,idx[0]] # their distances
Creating a list of all possible pairs and then a list of single key dictionaries with distances as values does create a sorting headache. I would instead vectorize this job and use numpy.
import numpy as np
P = np.array([(33, 9), (34, 13), (62, 119), ...])
# Finds the n closest points to p in P
def n_closest_points(p, P, n)
p_vector = np.tile(p, (len(P), 1))
dists = np.linalg.norm(P-p_vector, axis=1)
sorted_dists = np.sort(dists)
# Exclude the 0th element as the distance from p to itself is 0
return sorted_dists[1:n+1]

How do I apply padding to a list of arrays?

I have this function padding function.
It takes X (a list of numpy arrays of dimensions (13,n) where n varies between 0-99 with each array) and returns and returns X_new which should also be a list of numpy arrays that are all shape (13,99) after padding.
X_new = []
for x in X:
shp_1 = len(x[1])
if shp_1 != targetdim:
X_new.append(np.pad(x[1], (0, targetdim - shp_1), 'constant', constant_values=0))
else:
X_new.append(x)
Checking its output by checking the shape of the arrays in X_new
(13, 99) #correct dimensions
(13, 99)
(99,) #wrong
(13, 99)
(13, 99)
(13, 99)
(13, 99)
(99,)
(13, 99)
(99,)
(13, 99)
X_new.append(np.pad(x[1], (0, targetdim - shp_1), 'constant', constant_values=0)) works as intended as it pads column x[1] to 99 if needed.
The problem is that the function only appends the padded array in x[1] to new_list, x[0] is discarded.
The result is that where padding is applied the output shape is (99,) instead of the desired (13,99).
My question is how do I resolve this issue with append?
In short, my the goal is to reproduce list X with a list of padded arrays, any alternative methods of achieving this goal are also welcome.

Recursively trying to find the maximum w/o loops

So I'm given a tuple of ordered pairs in this format:
(x,y) where
x represents the physical weight of the objects, y represents the cost/value of the object.
((5, 20), (10, 70), (40, 200), (20, 80), (10, 100))
Objects may only be used once, but there may be multiples of those objects in the original tuple of ordered pairs.
z is the max weight that can be shipped. It's an integer. z could be 50 or something like that.
Goal: Find the maximum value possible that you can send given the limit Z.
The difficulty is that we can ONLY use recursion and we cannot use loops nor can we use python built-in functions.
I've tried to work out the max value in a list of integers, which I did separately to try to get some sort of idea. I have also tried giving the objects a 'mass' and doing value/weight, but that didn't work very well either.
def maximum_val(objects: ((int,int),) , max_weight : int) -> int:
if max_weight == 0:
return 0
else:
return objects[0][1] + maximum_val(objects[1:], max_weight - gifts[0][0])
((5, 20), (10, 70), (40, 200), (20, 80), (10, 100))
Example: Given the tuple above and the limit Z=40, the best possible value that could be obtained is 250 -> (10, 70), (10, 100), (20, 80)
This is known as knapsack and you are looking for a recursive variant.
At every step, check what is best. Include the first object or skip the first object:
objects = ((5, 20), (10, 70), (40, 200), (20, 80), (10, 100))
def recursive_knapsack(objects, limit ):
if not objects:
return 0
if objects[0][0] > limit:
#first object cant fit
return recursive_knapsack(objects[1:],limit)
include = objects[0][1] + recursive_knapsack(objects[1:], limit-objects[0][0])
exclude = recursive_knapsack(objects[1:],limit)
if include < exclude:
return exclude
else:
return include

Comparing X Y coordinates of the same list

I have a list of X Y tuple coordinates. I am trying to eliminate the coordinates that are very close to each other using the euclidean distance. However, the code so far does not perform as expected, especially as the number of coordinates increases.
So far, I have found online how to compare two lists of coordinates, but not the elements within the same list.
Hence, what i have done is slice the list in the first element and the remainder of the list and so the euclidean distance comparison. If within the proximity, it is element value is removed from the list. Then the list is updated and the procedure repeated. However, it does not perform as expected.
from scipy.spatial import distance
# List of coordinates.
xy = [(123, 2191), (44, 2700), (125, 2958), (41, 3368), (33, 4379), (78, 4434), (75, 5897), (50, 6220), (75, 7271), (80, 7274), (58, 8440), (60, 8440), (59, 8441), (32, 9699), (54, 9758), (58, 9759), (43, 10113), (64, 10252), (57, 12118), (61, 12120), (60, 14129), (61, 14129), (66, 15932), (68, 15933), (53, 17302), (57, 17304), (84, 20012), (84, 20013), (102, 20222), (49, 21257), (47, 21653), (56, 27042), (51, 28200), (48, 28201), (55, 28202), (65, 29366), (43, 29484), (67, 29808), (32, 30840), (31, 30842), (48, 36368), (48, 36369), (49, 36369), (21, 37518), (102, 37519)]
uni = []
for x in xy[:]:
for i, j in enumerate(xy):
if i == 0:
new_xy = j # New List comprising of first element of the list
remaining_xy = list(set(xy) - set(new_xy)) # rest of list converted into a separate list
for m in remaining_xy:
print(new_xy , m, distance.euclidean(new_xy , m))
if distance.euclidean(new_xy ,m) < 1000: # If distance less then threshold, remove.
remaining_xy.remove(m)
xy = remaining_xy #reset xy
remaining_xy = [] #reset remaining_xy
uni.append(new_xy) # append unique values.
print(len((uni)), uni)
However, for example, the output shows
..., (53, 17302), (57, 17304), ...
Which does not satisfy the threshold.
For me your code is actually working. Maybe just change your last print statement to:
print(len(set(uni)), set(uni))
These outputs seem right for me. All coordinates in the set(uni) are more than 1000 apart from each other.
I get the following:
23 {(68, 15933), (58, 8440), (75, 7271), (51, 28200), (21, 37518), (61, 14129), (84, 20012), (65, 29366), (50, 6220), (49, 21257), (53, 17302), (41, 3368), (33, 4379), (64, 10252), (58, 9759), (56, 27042), (57, 12118), (78, 4434), (32, 30840), (31, 30842), (48, 36369), (48, 28201), (123, 2191)}
Update:
Unfortunately I haven't tested the complete output... I cannot directly find the issue in your code, but with a recursive function you will get the correct result you are looking for:
def recursiveCoord(_coordinateList):
if len(_coordinateList) > 1:
xy_0 = _coordinateList[0]
remaining_xy = list(set(_coordinateList) - set(xy_0))
new_xy_list = []
for coord in remaining_xy:
dist = distance.euclidean(xy_0 ,coord)
if dist >= 1000:
new_xy_list.append(coord)
return [xy_0] + recursiveCoord(new_xy_list)
else:
return []
Call it like that:
uni = recursiveCoord(xy)
and you will get a list with all unique coordinates.

Generating random vertices that don't repeat

I have the following code that is generating a random number of tuples in order to create a connected undirect weighted graph.
for i in xrange(0,10):
for j in xrange(0, (int)(10*random.random())):
b = (int)(10*random.random())
j = [(i,b)]
print(j)
When I run this code I am able to randomly generate random vertices (x,y), however I am running into an issue in that my b variable has the possibility of repeating twice. For example I may get (6,3) followed by (6,3) which when I add weights would ruin the graphs I'm trying to create. Also I am sometimes running into issues where I might get (2,4) and then later get (4,2) which again ruins the graphs that I'm trying to create.
Does anyone know how I can keep vertices from repeating?
Use random.sample
>>> lst1 = random.sample(range(20), 10)
>>> lst2 = random.sample(range(20), 10)
>>> zip(lst1, lst2)
[(19, 5), (5, 11), (9, 19), (0, 9), (4, 6), (12, 0), (7, 12), (16, 1), (10, 7), (15, 16)]
You can change the list generated by range(20) to suit your set of vertices.
Don't generate a new vertex inside the for loop, since it may generate the same one again. (don't pick randomly off of the random.sample lists) Just generate them once and zip them together.
Since you want to remove duplicates of type (x, y) and (y, x). You can do something like the following. (or the simple in method works too)
>>> r = [(19, 5), (5, 11), (5, 19)]
>>> from itertools import groupby
>>> m = map(set, r)
>>> m
[set([19, 5]), set([11, 5]), set([19, 5])]
>>> sorted(m, key=lambda x: sum(x))
[set([11, 5]), set([19, 5]), set([19, 5])]
>>> [tuple(k) for k, v in groupby(sorted(m, key = lambda x: sum(x)))]
[(11, 5), (19, 5)]

Categories

Resources