Related
I am try to find the angle of line
i know the coordinate points
Start Point : 404, 119
Mid Point : 279, 214
End Point : 154, 310
import numpy as np
def findangle(x1,y1,x2,y2,x3,y3):
ria = np.arctan2(y2 - y1, x2 - x1) - np.arctan2(y3 - y1, x3 - x1)
webangle = int(np.abs(ria * 180 / np.pi))
return webangle
result
Its return 270. But actual angle is 85-90.
Now, I want formula to calculate the angle (Either i Will rotate the image clockwise or Anticlockwise that time also return actual angle) in python code
I think you need to adjust the returned angle based on the range you wish the result to be in.
The following assumes you desire results between -180 (inclusive) and 180 (exclusive).
def adjust(a, degrees=True):
v = 180 if degrees else np.pi
return (a + v) % (2 * v) - v
def angle(p, degrees=True):
assert p.shape == (3, 2), 'p should have 3 points, in 2D'
yx = p[:, ::-1]
a0 = np.arctan2(*(yx[1] - yx[0]))
a1 = np.arctan2(*(yx[2] - yx[1]))
a = np.rad2deg(a1 - a0) if degrees else a1 - a0
return adjust(a, degrees)
And here is some code to test validity:
def rot(a, degrees=True):
a = np.deg2rad(a) if degrees else a
sa, ca = np.sin(a), np.cos(a)
return np.array([[ca, sa], [-sa, ca]])
def genp(angle, initial=0, lengths=(1, 1), degrees=True):
p0 = np.array((0, 0))
p1 = np.array((lengths[0], 0))
p2 = p1 + np.array((lengths[1], 0)) # rot(angle, degrees=degrees)
p = np.vstack((p0, p1, p2)) # rot(initial, degrees=degrees)
return p
def plot_problem(p, ax=None):
ax = plt.gca() if ax is None else ax
ax.plot(*p.T, '-o')
for s, xy in zip(list('abc'), p):
ax.annotate(s, xy, xytext=(0, 5), textcoords='offset points')
ax.set_aspect('equal')
Example:
p = genp(60, initial=30, lengths=(2, 1))
>>> angle(p)
60.0
plot_problem(p)
Now, a stress test:
n = 1000
np.random.seed(0)
for _ in range(n):
a = np.random.uniform(-180, 180)
initial = np.random.uniform(-180, 180)
lengths = np.random.uniform(1, 10, size=2)
p = genp(a, initial, lengths)
ahat = angle(p)
assert np.allclose(a, ahat)
Which passes.
It's a simple math. The numpy.arctan2() returns a value in the range [-π, π]. So a difference of two values is in the range [-2π, 2π], and the absolute value of that is in the range [0, 2π]. You want an angle x in the range [0, π], and x is equivalent to (2π - x) in your context. So you can take x if x < π, and take (2π - x) otherwise.
So, just do like this using min() for example.
def findangle(x1,y1,x2,y2,x3,y3):
...
return min(webangle, 360 - webangle)
As a side note, you don't need to use Numpy functions for a scalar input. Just use the math.atan2() and math.fabs().
Okay so when I test this, it gives me the error stating that 'points' is not defined. I don't know how to fix this, can I get some help please?
p.s. The code is not totally finished. I still have to print out the other points too, but I want to fix this error beforehand.
line 43, in main print(distance(points[0]) + " " +
distance(points[1])) NameError: name 'points' is not defined
from math import *
def distance():
points = [(6, 5.7), (-9, 0)]
set1 = points[0]
set2 = points[1]
x1 = set1[0]
y1 = set1[1]
x2 = set2[0]
y2 = set2[1]
distance = sqrt((x1 - x2)**2 + (y1 + y2)**2)
return distance
def secondDistance():
points = [(0, 0), (4, 1)]
set1 = points[0]
set2 = points[1]
x1 = set1[0]
y1 = set1[1]
x2 = set2[0]
y2 = set2[1]
distance = sqrt((x1 - x2)**2 + (y1 + y2)**2)
return distance
def thirdDistance():
points = [(100, -100), (500, 300)]
set1 = points[0]
set2 = points[1]
x1 = set1[0]
y1 = set1[1]
x2 = set2[0]
y2 = set2[1]
distance = sqrt((x1 - x2)**2 + (y1 + y2)**2)
return distance
def main():
print("Original List")
print("Set 1 Set 2")
print(distance(points[0]) + " " + distance(points[1]))
print(distance())
print(secondDistance())
print(thirdDistance())
main()
Why do you have three functions to do exactly the same thing? This entirely defeats the purpose of a function: reuse. Try this: a single function that takes the pair of points as its argument. List the three points in your main program, and iterate through the list of points.
from math import sqrt
def distance(points):
p1, p2 = points
print " points:", p1, p2
x1, y1 = p1
x2, y2 = p2
print " coords:", x1, y1, x2, y2
distance = sqrt((x1 - x2)**2 + (y1 + y2)**2)
return distance
point_list = [
[(6, 5.7), (-9, 0)],
[(0, 0), (4, 1)],
[(100, -100), (500, 300)]
]
for point_pair in point_list:
print distance(point_pair)
Output:
points: (6, 5.7000000000000002) (-9, 0)
coords: 6 5.7 -9 0
16.0464949444
points: (0, 0) (4, 1)
coords: 0 0 4 1
4.12310562562
points: (100, -100) (500, 300)
coords: 100 -100 500 300
447.2135955
The problem you have is that in the function main, there is no variable named points. In each of your distance functions, you define a variable named points, but that variable is not visible from inside the main function.
Also, you should note that your distance functions don't take any arguments, so distance(points[0]) wouldn't work, even if points were defined inside main.
Finally, things like this are not necessary:
set1 = points[0]
x1 = set1[0]
You can simply write:
x1 = points[0][0]
What you should do is reorganize your code to make distance a function that takes two points, and returns a distance between them. Then, inside main, define the points you want to get distances between, and call distance on them:
from math import sqrt
def distance(point0, point1):
dx = point0[0] - point1[0]
dy = point0[1] - point1[1]
return sqrt(dx**2. + dy**2.)
def main():
p0 = (3., 5.)
p1 = (1., -2.)
d = distance(p0, p1)
print(d)
main()
Because my previous question was very unclear, i edited it:
I have the following Problem:
I want to construct a pattern for a hallow sphere with the radius: r+fcr_size. The cavity in the hallow sphere should have the radius r. With the pattern I could use it on many different sphere centers and get many hallow spheres. Now i searching for the fastest solution. my approach is:
centoEdge = radius+fcr_size #Bounding box coordinates from center to edge
xyz_pattern=[]
#Create the Bounding Box only in positive x,y,z direction, because they are later mirrowed
x1 = range(0,int(centoEdge)+1)
y1 = range(0,int(centoEdge)+1)
z1 = range(0,int(centoEdge)+1)
#Check if coordinates are the hallow sphere and add them to xyz_pattern list
for coords in itertools.product(x1,y1,z1):
if radius < distance.euclidean([0,0,0],coords) <= (radius+fcr_size):
xyz_pattern.append(coords)
#mirrow the pattern arround center
out = []
for point in xyz_pattern:
for factors in itertools.product([1, -1], repeat=3): # (1, 1, 1), (1, 1, -1), (1, -1, 1), ..., (-1, -1, -1)
out.append(tuple(point[i]*factors[i] for i in range(3)))
xyz_pattern=list(set(out))
This solution is based on Python Functional Programming, and hope you like it.
import math
from functools import partial
import itertools
import numpy as np
def distance(p1, p2):
return math.sqrt(sum(math.pow(float(x1) - float(x2), 2) for x1, x2 in zip(p1, p2)))
def inside_radius(radius, p):
return distance(p, (0, 0, 0)) < float(radius)
def inside_squre(centoEdge, p):
return all(math.fabs(x) <= centoEdge for x in p)
radius = 5
fcr_siz = 5
centoEdge = radius + fcr_siz
x1 = range(0, int(centoEdge) + 1)
y1 = range(0, int(centoEdge) + 1)
z1 = range(0, int(centoEdge) + 1)
coords = np.array(list(itertools.product(x1, y1, z1)))
inside_squre_with_cento = partial(inside_squre, centoEdge)
inside_radius_with_radius = partial(inside_radius, radius)
result = filter(lambda p: not inside_radius_with_radius(p), filter(inside_squre_with_cento, coords))
print(result)
I am trying to implement the closest pair problem in Python using divide and conquer, everything seems to work fine except that in some input cases, there is a wrong answer. My code is as follows:
def closestSplitPair(Px,Py,d):
X = Px[len(Px)-1][0]
Sy = [item for item in Py if item[0]>=X-d and item[0]<=X+d]
best,p3,q3 = d,None,None
for i in xrange(0,len(Sy)-2):
for j in xrange(1,min(7,len(Sy)-1-i)):
if dist(Sy[i],Sy[i+j]) < best:
best = (Sy[i],Sy[i+j])
p3,q3 = Sy[i],Sy[i+j]
return (p3,q3,best)
I am calling the above function through a recursive function which is as follows:
def closestPair(Px,Py): """Px and Py are input arrays sorted according to
their x and y coordinates respectively"""
if len(Px) <= 3:
return min_dist(Px)
else:
mid = len(Px)/2
Qx = Px[:mid] ### x-sorted left side of P
Qy = Py[:mid] ### y-sorted left side of P
Rx = Px[mid:] ### x-sorted right side of P
Ry = Py[mid:] ### y-sorted right side of P
(p1,q1,d1) = closestPair(Qx,Qy)
(p2,q2,d2) = closestPair(Rx,Ry)
d = min(d1,d2)
(p3,q3,d3) = closestSplitPair(Px,Py,d)
return min((p1,q1,d1),(p2,q2,d2),(p3,q3,d3),key=lambda tup: tup[2])
where min_dist(P) is the brute force implementation of the closest pair algorithm for a list P having 3 or less elements and returns a tuple containing the pair of closest points and their distance.
If my input is P = [(0,0),(7,6),(2,20),(12,5),(16,16),(5,8),(19,7),(14,22),(8,19),(7,29),(10,11),(1,13)], then my output is ((5,8),(7,6),2.8284271) which is the correct output. But when my input is P = [(94, 5), (96, -79), (20, 73), (8, -50), (78, 2), (100, 63), (-14, -69), (99, -8), (-11, -7), (-78, -46)] the output I get is ((78, 2), (94, 5), 16.278820596099706) whereas the correct output should be ((94, 5), (99, -8), 13.92838827718412)
You have two problems, you are forgetting to call dist to update the best distance. But the main problem is there is more than one recursive call happening so you can end up overwriting when you find a closer split pair with the default, best,p3,q3 = d,None,None. I passed the best pair from closest_pair as an argument to closest_split_pair so I would not potentially overwrite the value.
def closest_split_pair(p_x, p_y, delta, best_pair): # <- a parameter
ln_x = len(p_x)
mx_x = p_x[ln_x // 2][0]
s_y = [x for x in p_y if mx_x - delta <= x[0] <= mx_x + delta]
best = delta
for i in range(len(s_y) - 1):
for j in range(1, min(i + 7, (len(s_y) - i))):
p, q = s_y[i], s_y[i + j]
dst = dist(p, q)
if dst < best:
best_pair = p, q
best = dst
return best_pair
The end of closest_pair looks like the following:
p_1, q_1 = closest_pair(srt_q_x, srt_q_y)
p_2, q_2 = closest_pair(srt_r_x, srt_r_y)
closest = min(dist(p_1, q_1), dist(p_2, q_2))
# get min of both and then pass that as an arg to closest_split_pair
mn = min((p_1, q_1), (p_2, q_2), key=lambda x: dist(x[0], x[1]))
p_3, q_3 = closest_split_pair(p_x, p_y, closest,mn)
# either return mn or we have a closer split pair
return min(mn, (p_3, q_3), key=lambda x: dist(x[0], x[1]))
You also have some other logic issues, your slicing logic is not correct, I made some changes to your code where brute is just a simple bruteforce double loop:
def closestPair(Px, Py):
if len(Px) <= 3:
return brute(Px)
mid = len(Px) / 2
# get left and right half of Px
q, r = Px[:mid], Px[mid:]
# sorted versions of q and r by their x and y coordinates
Qx, Qy = [x for x in q if Py and x[0] <= Px[-1][0]], [x for x in q if x[1] <= Py[-1][1]]
Rx, Ry = [x for x in r if Py and x[0] <= Px[-1][0]], [x for x in r if x[1] <= Py[-1][1]]
(p1, q1) = closestPair(Qx, Qy)
(p2, q2) = closestPair(Rx, Ry)
d = min(dist(p1, p2), dist(p2, q2))
mn = min((p1, q1), (p2, q2), key=lambda x: dist(x[0], x[1]))
(p3, q3) = closest_split_pair(Px, Py, d, mn)
return min(mn, (p3, q3), key=lambda x: dist(x[0], x[1]))
I just did the algorithm today so there are no doubt some improvements to be made but this will get you the correct answer.
Here is a recursive divide-and-conquer python implementation of the closest point problem based on the heap data structure. It also accounts for the negative integers. It can return the k-closest point by popping k nodes in the heap using heappop().
from __future__ import division
from collections import namedtuple
from random import randint
import math as m
import heapq as hq
def get_key(item):
return(item[0])
def closest_point_problem(points):
point = []
heap = []
pt = namedtuple('pt', 'x y')
for i in range(len(points)):
point.append(pt(points[i][0], points[i][1]))
point = sorted(point, key=get_key)
visited_index = []
find_min(0, len(point) - 1, point, heap, visited_index)
print(hq.heappop(heap))
def find_min(start, end, point, heap, visited_index):
if len(point[start:end + 1]) & 1:
mid = start + ((len(point[start:end + 1]) + 1) >> 1)
else:
mid = start + (len(point[start:end + 1]) >> 1)
if start in visited_index:
start = start + 1
if end in visited_index:
end = end - 1
if len(point[start:end + 1]) > 3:
if start < mid - 1:
distance1 = m.sqrt((point[start].x - point[start + 1].x) ** 2 + (point[start].y - point[start + 1].y) ** 2)
distance2 = m.sqrt((point[mid].x - point[mid - 1].x) ** 2 + (point[mid].y - point[mid - 1].y) ** 2)
if distance1 < distance2:
hq.heappush(heap, (distance1, ((point[start].x, point[start].y), (point[start + 1].x, point[start + 1].y))))
else:
hq.heappush(heap, (distance2, ((point[mid].x, point[mid].y), (point[mid - 1].x, point[mid - 1].y))))
visited_index.append(start)
visited_index.append(start + 1)
visited_index.append(mid)
visited_index.append(mid - 1)
find_min(start, mid, point, heap, visited_index)
if mid + 1 < end:
distance1 = m.sqrt((point[mid].x - point[mid + 1].x) ** 2 + (point[mid].y - point[mid + 1].y) ** 2)
distance2 = m.sqrt((point[end].x - point[end - 1].x) ** 2 + (point[end].y - point[end - 1].y) ** 2)
if distance1 < distance2:
hq.heappush(heap, (distance1, ((point[mid].x, point[mid].y), (point[mid + 1].x, point[mid + 1].y))))
else:
hq.heappush(heap, (distance2, ((point[end].x, point[end].y), (point[end - 1].x, point[end - 1].y))))
visited_index.append(end)
visited_index.append(end - 1)
visited_index.append(mid)
visited_index.append(mid + 1)
find_min(mid, end, point, heap, visited_index)
x = []
num_points = 10
for i in range(num_points):
x.append((randint(- num_points << 2, num_points << 2), randint(- num_points << 2, num_points << 2)))
closest_point_problem(x)
:)
Brute force can work faster with stdlib functions. Therefore, it can be effectively applied to more than 3 points.
from itertools import combinations
def closest(points_list):
return min((dist(p1, p2), p1, p2)
for p1, p2 in combinations(points_list, r=2))
The most effective way to divide the points is to divide them on tiles. If you don't have outliers, you can just split your space on equal parts and compare points only in the same or in the neighbour tiles.
Number of tiles must be as large as it possible. But, to avoid isolated tiles, when each point doesn't have points in neighbour tiles, you must limit number of tiles by the number of points.
Full listing:
from math import sqrt
from itertools import combinations, product
from collections import defaultdict
import sys
max_float = sys.float_info.max
def dist((x1, y1), (x2, y2)):
return sqrt((x1 - x2) ** 2 + (y1 - y2) **2)
def closest(points_list):
if len(points_list) < 2:
return (max_float, None, None) # default value compatible with min function
return min((dist(p1, p2), p1, p2)
for p1, p2 in combinations(points_list, r=2))
def closest_between(pnt_lst1, pnt_lst2):
if not pnt_lst1 or not pnt_lst2:
return (max_float, None, None) # default value compatible with min function
return min((dist(p1, p2), p1, p2)
for p1, p2 in product(pnt_lst1, pnt_lst2))
def divide_on_tiles(points_list):
side = int(sqrt(len(points_list))) # number of tiles on one side of square
tiles = defaultdict(list)
min_x = min(x for x, y in points_list)
max_x = max(x for x, y in points_list)
min_y = min(x for x, y in points_list)
max_y = max(x for x, y in points_list)
tile_x_size = float(max_x - min_x) / side
tile_y_size = float(max_y - min_y) / side
for x, y in points_list:
x_tile = int((x - min_x) / tile_x_size)
y_tile = int((y - min_y) / tile_y_size)
tiles[(x_tile, y_tile)].append((x, y))
return tiles
def closest_for_tile(tiles, (x_tile, y_tile)):
points = tiles[(x_tile, y_tile)]
return min(closest(points),
# use dict.get to avoid creating empty tiles
# we compare current tile only with half of neighbours (right/top),
# because another half (left/bottom) make it in another iteration by themselves
closest_between(points, tiles.get((x_tile+1, y_tile))),
closest_between(points, tiles.get((x_tile, y_tile+1))),
closest_between(points, tiles.get((x_tile+1, y_tile+1))),
closest_between(points, tiles.get((x_tile-1, y_tile+1))))
def find_closest_in_tiles(tiles):
return min(closest_for_tile(tiles, coord) for coord in tiles.keys())
P1 = [(0,0),(7,6),(2,20),(12,5),(16,16),(5,8),(19,7),(14,22),(8,19),(7,29),(10,11),(1,13)]
P2 = [(94, 5), (96, -79), (20, 73), (8, -50), (78, 2), (100, 63), (-14, -69), (99, -8), (-11, -7), (-78, -46)]
print find_closest_in_tiles(divide_on_tiles(P1)) # (2.8284271247461903, (7, 6), (5, 8))
print find_closest_in_tiles(divide_on_tiles(P2)) # (13.92838827718412, (94, 5), (99, -8))
print find_closest_in_tiles(divide_on_tiles(P1 + P2)) # (2.8284271247461903, (7, 6), (5, 8))
You just need to change the seventh line in your closestSplitPair function def from best=(Sy[i],Sy[i+j]) to best=dist(Sy[i],Sy[i+j]) and you will get the correct answer: ((94, 5), (99, -8), 13.92838827718412). You were missing the calling to the dist function.
This was pointed out by Padraic Cunningham's answer as the first problem.
Best Regards.
I have a list of lists, something like
[[1, 2, 3,],[4, 5, 6,],[7, 8, 9]].
Represented graphically as:
1 2 3
4 5 6
7 8 9
I'm looking for an elegant approach to check the value of neighbours of a cell, horizontally, vertically and diagonally. For instance, the neighbours of [0][2] are [0][1], [1][1] and [1][2] or the numbers 2, 5, 6.
Now I realise, I could just do a bruteforce attack checking every value a la:
[i-1][j]
[i][j-1]
[i-1][j-1]
[i+1][j]
[i][j+1]
[i+1][j+1]
[i+1][j-1]
[i-1][j+1]
But thats easy, and I figured I can learn more by seeing some more elegant approaches.
# Size of "board"
X = 10
Y = 10
neighbors = lambda x, y : [(x2, y2) for x2 in range(x-1, x+2)
for y2 in range(y-1, y+2)
if (-1 < x <= X and
-1 < y <= Y and
(x != x2 or y != y2) and
(0 <= x2 <= X) and
(0 <= y2 <= Y))]
>>> print(neighbors(5, 5))
[(4, 4), (4, 5), (4, 6), (5, 4), (5, 6), (6, 4), (6, 5), (6, 6)]
I don't know if this is considered clean, but this one-liner gives you all neighbors by iterating over them and discarding any edge cases.
Assuming you have a square matrix:
from itertools import product
size = 3
def neighbours(cell):
for c in product(*(range(n-1, n+2) for n in cell)):
if c != cell and all(0 <= n < size for n in c):
yield c
Using itertools.product and thanks to Python's yield expression and star operator, the function is pretty dry but still readable enough.
Given a matrix size of 3, you can then (if needed) collect the neighbours in a list:
>>> list(neighbours((2,2)))
[(1, 1), (1, 2), (2, 1)]
What the function does can be visualized as follows:
mb...
from itertools import product, starmap
x, y = (8, 13)
cells = starmap(lambda a,b: (x+a, y+b), product((0,-1,+1), (0,-1,+1)))
// [(8, 12), (8, 14), (7, 13), (7, 12), (7, 14), (9, 13), (9, 12), (9, 14)]
print(list(cells)[1:])
for x_ in range(max(0,x-1),min(height,x+2)):
for y_ in range(max(0,y-1),min(width,y+2)):
if (x,y)==(x_,y_): continue
# do stuff with the neighbours
>>> a=[[1, 2, 3], [4, 5, 6], [7, 8, 9]]
>>> width=height=3
>>> x,y=0,2
>>> for x_ in range(max(0,x-1),min(height,x+2)):
... for y_ in range(max(0,y-1),min(width,y+2)):
... if (x,y)==(x_,y_): continue
... print a[x_][y_]
...
2
5
6
If someone is curious about alternative way to pick direct (non-diagonal) neighbors, here you go:
neighbors = [(x+a[0], y+a[1]) for a in
[(-1,0), (1,0), (0,-1), (0,1)]
if ( (0 <= x+a[0] < w) and (0 <= y+a[1] < h))]
There's no cleaner way to do this. If you really want you could create a function:
def top(matrix, x, y):
try:
return matrix[x][y - 1];
except IndexError:
return None
Here is your list:
(x - 1, y - 1) (x, y - 1) (x + 1, y - 1)
(x - 1, y) (x, y) (x + 1, y)
(x - 1, y + 1) (x, y + 1) (x + 1, y + 1)
So the horizontal neighbors of (x, y) are (x +/- 1, y).
The vertical neighbors are (x, y +/- 1).
Diagonal neighbors are (x +/- 1, y +/- 1).
These rules apply for an infinite matrix.
To make sure the neighbors fit into a finite matrix, if the initial (x, y) is at the edge, just apply one more restriction to the coordinates of neighbors - the matrix size.
>>> import itertools
>>> def sl(lst, i, j):
il, iu = max(0, i-1), min(len(lst)-1, i+1)
jl, ju = max(0, j-1), min(len(lst[0])-1, j+1)
return (il, iu), (jl, ju)
>>> lst = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
>>> tup = 0, 2
>>> [lst[i][j] for i, j in itertools.product(*sl(lst, *tup)) if (i, j) != tup]
[2, 5, 6]
I don't know how elegant it seems to you, but it seems to work w/o any hard-coding.
This generates all indices:
def neighboring( array ):
nn,mm = len(array), len(array[0])
offset = (0,-1,1) # 0 first so the current cell is the first in the gen
indices = ( (i,j) for i in range(nn) for j in range(mm) )
for i,j in indices:
all_neigh = ( (i+x,j+y) for x in offset for y in offset )
valid = ( (i,j) for i,j in all_neigh if (0<=i<nn) and (0<=j<mm) ) # -1 is a valid index in normal lists, but not here so throw it out
yield valid.next(), valid ## first is the current cell, next are the neightbors
for (x,y), neigh in neighboring( l ):
print l[x][y], [l[x][y] for x,y in neigh]
If lambdas daunt you here you are .But lambdas make your code look clean.#johniek_comp has a very clean solution TBH
k,l=(2,3)
x = (0,-1,+1)
y = (0,-1,+1)
cell_u = ((k+a,l+b) for a in x for b in y)
print(list(cell_u))
Inspired by one of the previous answers.
You can use min() and max() functions to shorten the calculations:
width = 3
height = 3
[(x2, y2) for x2 in range(max(0, x-1), min(width, x+2))
for y2 in range(max(0, y-1), min(height, y+2))
if (x2, y2) != (x, y)]
Thank you to #JS_is_bad for a great hint about the neighbors. Here is the running code for this problem:
def findNeighbours(l,elem):
#This try is for escaping from unbound error that happens
#when we try to iterate through indices that are not in array
try:
#Iterate through each item of multidimensional array using enumerate
for row,i in enumerate(l):
try:
#Identifying the column index of the givem element
column=i.index(elem)
except ValueError:
continue
x,y=row,column
# hn=list(((x,y+1),(x,y-1))) #horizontal neighbours=(x,y+/-1)
# vn=list(((x+1,y),(x-1,y))) #vertical neighbours=(x+/-1,y)
# dn=list(((x+1,y+1),(x-1,y-1),(x+1,y-1),(x-1,y+1))) #diagonal neighbours=(x+/-1,y+/-1)
#Creating a list with values that are actual neighbors for the extracted index of array
neighbours=[(x,y+1),(x,y-1),(x+1,y),(x-1,y),(x+1,y+1),(x-1,y-1),(x+1,y-1),(x-1,y+1)]
#Creating a universe of indices from given array
index_list=[(i,j) for i in range(len(l)) for j in range(len(l[i]))]
#Looping through index_list and nested loop for neighbours but filter for matched ones
# and extract the value of respective index
return_values=[l[index[0]][index[1]] for index in index_list for neighbour in neighbours if index==neighbour]
return return_values,neighbours
except UnboundLocalError:
return []
Inspired by johniek's answer here is my solution which also checks for boundaries.
def get_neighbours(node, grid_map):
row_index, col_index = node
height, width = len(grid_map), len(grid_map[0])
cells = list(starmap(lambda a, b: (row_index + a, col_index + b), product((0, -1, +1), (0, -1, +1))))
cells.pop(0) # do not include original node
cells = list(filter(lambda cell: cell[0] in range(height) and cell[1] in range(width), cells))
return cells
def numCells(grid):
x=len(grid)
y=len(grid[0])
c=0
for i in range(x):
for j in range(y):
value_=grid[i][j]
f=1
for i2 in range(max(0,i-1),min(x,i+2)):
for j2 in range(max(0,j-1),min(y,j+2)):
if (i2,j2) != (i,j) and value_<=grid[i2][j2]:
flag=0
break
if flag ==0:
break
else:
c+=1
return c
def getNeighbors(matrix: list, point: tuple):
neighbors = []
m = len(matrix)
n = len(matrix[0])
x, y = point
for i in range (x -1, x +2): #prev row to next row
for j in range(y - 1, y +2): #prev column to next col
if (0 <= i < m) and (0 <= j < n):
neighbors.append((i,j))
return neighbors
maybe you are checking a sudoku box. If the box is n x n and current cell is (x,y) start checking:
startingRow = x / n * n;
startingCol = y/ n * n