Skip to content

Update closest_pair_of_points.py #1109

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Aug 6, 2019
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
107 changes: 57 additions & 50 deletions divide_and_conquer/closest_pair_of_points.py
Original file line number Diff line number Diff line change
@@ -1,55 +1,54 @@
"""
The algorithm finds distance between closest pair of points
The algorithm finds distance between closest pair of points
in the given n points.
Approach used -> Divide and conquer
The points are sorted based on Xco-ords and
Approach used -> Divide and conquer
The points are sorted based on Xco-ords and
then based on Yco-ords separately.
And by applying divide and conquer approach,
And by applying divide and conquer approach,
minimum distance is obtained recursively.

>> Closest points can lie on different sides of partition.
This case handled by forming a strip of points
This case handled by forming a strip of points
whose Xco-ords distance is less than closest_pair_dis
from mid-point's Xco-ords. Points sorted based on Yco-ords
from mid-point's Xco-ords. Points sorted based on Yco-ords
are used in this step to reduce sorting time.
Closest pair distance is found in the strip of points. (closest_in_strip)

min(closest_pair_dis, closest_in_strip) would be the final answer.

Time complexity: O(n * log n)
"""

"""
doctests
>>> euclidean_distance_sqr([1,2],[2,4])
5
>>> dis_between_closest_pair([[1,2],[2,4],[5,7],[8,9],[11,0]],5)
5
>>> dis_between_closest_in_strip([[1,2],[2,4],[5,7],[8,9],[11,0]],5)
85
>>> points = [(2, 3), (12, 30), (40, 50), (5, 1), (12, 10), (3, 4)]
>>> print("Distance:", closest_pair_of_points(points, len(points)))
"Distance: 1.4142135623730951"
Time complexity: O(n * log n)
"""


def euclidean_distance_sqr(point1, point2):
"""
>>> euclidean_distance_sqr([1,2],[2,4])
5
"""
return (point1[0] - point2[0]) ** 2 + (point1[1] - point2[1]) ** 2


def column_based_sort(array, column = 0):
"""
>>> column_based_sort([(5, 1), (4, 2), (3, 0)], 1)
[(3, 0), (5, 1), (4, 2)]
"""
return sorted(array, key = lambda x: x[column])


def dis_between_closest_pair(points, points_counts, min_dis = float("inf")):
""" brute force approach to find distance between closest pair points
"""
brute force approach to find distance between closest pair points

Parameters :
points, points_count, min_dis (list(tuple(int, int)), int, int)

Parameters :
points, points_count, min_dis (list(tuple(int, int)), int, int)

Returns :
Returns :
min_dis (float): distance between closest pair of points

>>> dis_between_closest_pair([[1,2],[2,4],[5,7],[8,9],[11,0]],5)
5

"""

for i in range(points_counts - 1):
Expand All @@ -61,14 +60,17 @@ def dis_between_closest_pair(points, points_counts, min_dis = float("inf")):


def dis_between_closest_in_strip(points, points_counts, min_dis = float("inf")):
""" closest pair of points in strip
"""
closest pair of points in strip

Parameters :
points, points_count, min_dis (list(tuple(int, int)), int, int)

Parameters :
points, points_count, min_dis (list(tuple(int, int)), int, int)

Returns :
Returns :
min_dis (float): distance btw closest pair of points in the strip (< min_dis)

>>> dis_between_closest_in_strip([[1,2],[2,4],[5,7],[8,9],[11,0]],5)
85
"""

for i in range(min(6, points_counts - 1), points_counts):
Expand All @@ -82,29 +84,32 @@ def dis_between_closest_in_strip(points, points_counts, min_dis = float("inf")):
def closest_pair_of_points_sqr(points_sorted_on_x, points_sorted_on_y, points_counts):
""" divide and conquer approach

Parameters :
points, points_count (list(tuple(int, int)), int)
Returns :
(float): distance btw closest pair of points
Parameters :
points, points_count (list(tuple(int, int)), int)

Returns :
(float): distance btw closest pair of points

>>> closest_pair_of_points_sqr([(1, 2), (3, 4)], [(5, 6), (7, 8)], 2)
8
"""

# base case
if points_counts <= 3:
return dis_between_closest_pair(points_sorted_on_x, points_counts)

# recursion
mid = points_counts//2
closest_in_left = closest_pair_of_points_sqr(points_sorted_on_x,
points_sorted_on_y[:mid],
closest_in_left = closest_pair_of_points_sqr(points_sorted_on_x,
points_sorted_on_y[:mid],
mid)
closest_in_right = closest_pair_of_points_sqr(points_sorted_on_y,
points_sorted_on_y[mid:],
closest_in_right = closest_pair_of_points_sqr(points_sorted_on_y,
points_sorted_on_y[mid:],
points_counts - mid)
closest_pair_dis = min(closest_in_left, closest_in_right)

""" cross_strip contains the points, whose Xcoords are at a

"""
cross_strip contains the points, whose Xcoords are at a
distance(< closest_pair_dis) from mid's Xcoord
"""

Expand All @@ -113,21 +118,23 @@ def closest_pair_of_points_sqr(points_sorted_on_x, points_sorted_on_y, points_co
if abs(point[0] - points_sorted_on_x[mid][0]) < closest_pair_dis:
cross_strip.append(point)

closest_in_strip = dis_between_closest_in_strip(cross_strip,
closest_in_strip = dis_between_closest_in_strip(cross_strip,
len(cross_strip), closest_pair_dis)
return min(closest_pair_dis, closest_in_strip)


def closest_pair_of_points(points, points_counts):
"""
>>> closest_pair_of_points([(2, 3), (12, 30)], len([(2, 3), (12, 30)]))
28.792360097775937
"""
points_sorted_on_x = column_based_sort(points, column = 0)
points_sorted_on_y = column_based_sort(points, column = 1)
return (closest_pair_of_points_sqr(points_sorted_on_x,
points_sorted_on_y,
return (closest_pair_of_points_sqr(points_sorted_on_x,
points_sorted_on_y,
points_counts)) ** 0.5


if __name__ == "__main__":
points = [(2, 3), (12, 30), (40, 50), (5, 1), (12, 10), (3, 4)]
points = [(2, 3), (12, 30), (40, 50), (5, 1), (12, 10), (3, 4)]
print("Distance:", closest_pair_of_points(points, len(points)))