1
1
"""
2
- The algorithm finds distance between closest pair of points
2
+ The algorithm finds distance between closest pair of points
3
3
in the given n points.
4
- Approach used -> Divide and conquer
5
- The points are sorted based on Xco-ords and
4
+ Approach used -> Divide and conquer
5
+ The points are sorted based on Xco-ords and
6
6
then based on Yco-ords separately.
7
- And by applying divide and conquer approach,
7
+ And by applying divide and conquer approach,
8
8
minimum distance is obtained recursively.
9
9
10
10
>> Closest points can lie on different sides of partition.
11
- This case handled by forming a strip of points
11
+ This case handled by forming a strip of points
12
12
whose Xco-ords distance is less than closest_pair_dis
13
- from mid-point's Xco-ords. Points sorted based on Yco-ords
13
+ from mid-point's Xco-ords. Points sorted based on Yco-ords
14
14
are used in this step to reduce sorting time.
15
15
Closest pair distance is found in the strip of points. (closest_in_strip)
16
16
17
17
min(closest_pair_dis, closest_in_strip) would be the final answer.
18
-
19
- Time complexity: O(n * log n)
20
- """
21
18
22
- """
23
- doctests
24
- >>> euclidean_distance_sqr([1,2],[2,4])
25
- 5
26
- >>> dis_between_closest_pair([[1,2],[2,4],[5,7],[8,9],[11,0]],5)
27
- 5
28
- >>> dis_between_closest_in_strip([[1,2],[2,4],[5,7],[8,9],[11,0]],5)
29
- 85
30
- >>> points = [(2, 3), (12, 30), (40, 50), (5, 1), (12, 10), (3, 4)]
31
- >>> print("Distance:", closest_pair_of_points(points, len(points)))
32
- "Distance: 1.4142135623730951"
19
+ Time complexity: O(n * log n)
33
20
"""
34
21
35
22
36
23
def euclidean_distance_sqr (point1 , point2 ):
24
+ """
25
+ >>> euclidean_distance_sqr([1,2],[2,4])
26
+ 5
27
+ """
37
28
return (point1 [0 ] - point2 [0 ]) ** 2 + (point1 [1 ] - point2 [1 ]) ** 2
38
29
39
30
40
31
def column_based_sort (array , column = 0 ):
32
+ """
33
+ >>> column_based_sort([(5, 1), (4, 2), (3, 0)], 1)
34
+ [(3, 0), (5, 1), (4, 2)]
35
+ """
41
36
return sorted (array , key = lambda x : x [column ])
42
-
37
+
43
38
44
39
def dis_between_closest_pair (points , points_counts , min_dis = float ("inf" )):
45
- """ brute force approach to find distance between closest pair points
40
+ """
41
+ brute force approach to find distance between closest pair points
42
+
43
+ Parameters :
44
+ points, points_count, min_dis (list(tuple(int, int)), int, int)
46
45
47
- Parameters :
48
- points, points_count, min_dis (list(tuple(int, int)), int, int)
49
-
50
- Returns :
46
+ Returns :
51
47
min_dis (float): distance between closest pair of points
52
48
49
+ >>> dis_between_closest_pair([[1,2],[2,4],[5,7],[8,9],[11,0]],5)
50
+ 5
51
+
53
52
"""
54
53
55
54
for i in range (points_counts - 1 ):
@@ -61,14 +60,17 @@ def dis_between_closest_pair(points, points_counts, min_dis = float("inf")):
61
60
62
61
63
62
def dis_between_closest_in_strip (points , points_counts , min_dis = float ("inf" )):
64
- """ closest pair of points in strip
63
+ """
64
+ closest pair of points in strip
65
+
66
+ Parameters :
67
+ points, points_count, min_dis (list(tuple(int, int)), int, int)
65
68
66
- Parameters :
67
- points, points_count, min_dis (list(tuple(int, int)), int, int)
68
-
69
- Returns :
69
+ Returns :
70
70
min_dis (float): distance btw closest pair of points in the strip (< min_dis)
71
71
72
+ >>> dis_between_closest_in_strip([[1,2],[2,4],[5,7],[8,9],[11,0]],5)
73
+ 85
72
74
"""
73
75
74
76
for i in range (min (6 , points_counts - 1 ), points_counts ):
@@ -82,29 +84,32 @@ def dis_between_closest_in_strip(points, points_counts, min_dis = float("inf")):
82
84
def closest_pair_of_points_sqr (points_sorted_on_x , points_sorted_on_y , points_counts ):
83
85
""" divide and conquer approach
84
86
85
- Parameters :
86
- points, points_count (list(tuple(int, int)), int)
87
-
88
- Returns :
89
- (float): distance btw closest pair of points
87
+ Parameters :
88
+ points, points_count (list(tuple(int, int)), int)
89
+
90
+ Returns :
91
+ (float): distance btw closest pair of points
90
92
93
+ >>> closest_pair_of_points_sqr([(1, 2), (3, 4)], [(5, 6), (7, 8)], 2)
94
+ 8
91
95
"""
92
96
93
97
# base case
94
98
if points_counts <= 3 :
95
99
return dis_between_closest_pair (points_sorted_on_x , points_counts )
96
-
100
+
97
101
# recursion
98
102
mid = points_counts // 2
99
- closest_in_left = closest_pair_of_points_sqr (points_sorted_on_x ,
100
- points_sorted_on_y [:mid ],
103
+ closest_in_left = closest_pair_of_points_sqr (points_sorted_on_x ,
104
+ points_sorted_on_y [:mid ],
101
105
mid )
102
- closest_in_right = closest_pair_of_points_sqr (points_sorted_on_y ,
103
- points_sorted_on_y [mid :],
106
+ closest_in_right = closest_pair_of_points_sqr (points_sorted_on_y ,
107
+ points_sorted_on_y [mid :],
104
108
points_counts - mid )
105
109
closest_pair_dis = min (closest_in_left , closest_in_right )
106
-
107
- """ cross_strip contains the points, whose Xcoords are at a
110
+
111
+ """
112
+ cross_strip contains the points, whose Xcoords are at a
108
113
distance(< closest_pair_dis) from mid's Xcoord
109
114
"""
110
115
@@ -113,21 +118,23 @@ def closest_pair_of_points_sqr(points_sorted_on_x, points_sorted_on_y, points_co
113
118
if abs (point [0 ] - points_sorted_on_x [mid ][0 ]) < closest_pair_dis :
114
119
cross_strip .append (point )
115
120
116
- closest_in_strip = dis_between_closest_in_strip (cross_strip ,
121
+ closest_in_strip = dis_between_closest_in_strip (cross_strip ,
117
122
len (cross_strip ), closest_pair_dis )
118
123
return min (closest_pair_dis , closest_in_strip )
119
124
120
-
125
+
121
126
def closest_pair_of_points (points , points_counts ):
127
+ """
128
+ >>> closest_pair_of_points([(2, 3), (12, 30)], len([(2, 3), (12, 30)]))
129
+ 28.792360097775937
130
+ """
122
131
points_sorted_on_x = column_based_sort (points , column = 0 )
123
132
points_sorted_on_y = column_based_sort (points , column = 1 )
124
- return (closest_pair_of_points_sqr (points_sorted_on_x ,
125
- points_sorted_on_y ,
133
+ return (closest_pair_of_points_sqr (points_sorted_on_x ,
134
+ points_sorted_on_y ,
126
135
points_counts )) ** 0.5
127
136
128
137
129
138
if __name__ == "__main__" :
130
- points = [(2 , 3 ), (12 , 30 ), (40 , 50 ), (5 , 1 ), (12 , 10 ), (3 , 4 )]
139
+ points = [(2 , 3 ), (12 , 30 ), (40 , 50 ), (5 , 1 ), (12 , 10 ), (3 , 4 )]
131
140
print ("Distance:" , closest_pair_of_points (points , len (points )))
132
-
133
-
0 commit comments