1
- type Point = ( f64 , f64 ) ;
1
+ use crate :: geometry :: Point ;
2
2
use std:: cmp:: Ordering ;
3
3
4
- fn point_cmp ( ( a1 , a2 ) : & Point , ( b1 , b2 ) : & Point ) -> Ordering {
5
- let acmp = f64_cmp ( a1 , b1 ) ;
4
+ fn point_cmp ( p1 : & Point , p2 : & Point ) -> Ordering {
5
+ let acmp = f64_cmp ( & p1 . x , & p2 . x ) ;
6
6
match acmp {
7
- Ordering :: Equal => f64_cmp ( a2 , b2 ) ,
7
+ Ordering :: Equal => f64_cmp ( & p1 . y , & p2 . y ) ,
8
8
_ => acmp,
9
9
}
10
10
}
@@ -22,13 +22,6 @@ pub fn closest_points(points: &[Point]) -> Option<(Point, Point)> {
22
22
closest_points_aux ( & points, 0 , points. len ( ) )
23
23
}
24
24
25
- fn sqr_dist ( ( x1, y1) : & Point , ( x2, y2) : & Point ) -> f64 {
26
- let dx = * x1 - * x2;
27
- let dy = * y1 - * y2;
28
-
29
- dx * dx + dy * dy
30
- }
31
-
32
25
fn closest_points_aux (
33
26
points : & [ Point ] ,
34
27
mut start : usize ,
@@ -42,15 +35,15 @@ fn closest_points_aux(
42
35
43
36
if n <= 3 {
44
37
// bruteforce
45
- let mut min = sqr_dist ( & points[ 0 ] , & points[ 1 ] ) ;
46
- let mut pair = ( points[ 0 ] , points[ 1 ] ) ;
38
+ let mut min = points[ 0 ] . euclidean_distance ( & points[ 1 ] ) ;
39
+ let mut pair = ( points[ 0 ] . clone ( ) , points[ 1 ] . clone ( ) ) ;
47
40
48
41
for i in 1 ..n {
49
42
for j in ( i + 1 ) ..n {
50
- let new = sqr_dist ( & points[ i] , & points[ j] ) ;
43
+ let new = points[ i] . euclidean_distance ( & points[ j] ) ;
51
44
if new < min {
52
45
min = new;
53
- pair = ( points[ i] , points[ j] ) ;
46
+ pair = ( points[ i] . clone ( ) , points[ j] . clone ( ) ) ;
54
47
}
55
48
}
56
49
}
@@ -63,41 +56,41 @@ fn closest_points_aux(
63
56
64
57
let ( mut min_sqr_dist, mut pair) = match ( left, right) {
65
58
( Some ( ( l1, l2) ) , Some ( ( r1, r2) ) ) => {
66
- let dl = sqr_dist ( & l1 , & l2) ;
67
- let dr = sqr_dist ( & r1 , & r2) ;
59
+ let dl = l1 . euclidean_distance ( & l2) ;
60
+ let dr = r1 . euclidean_distance ( & r2) ;
68
61
if dl < dr {
69
62
( dl, ( l1, l2) )
70
63
} else {
71
64
( dr, ( r1, r2) )
72
65
}
73
66
}
74
- ( Some ( ( a, b) ) , None ) => ( sqr_dist ( & a , & b) , ( a, b) ) ,
75
- ( None , Some ( ( a, b) ) ) => ( sqr_dist ( & a , & b) , ( a, b) ) ,
67
+ ( Some ( ( a, b) ) , None ) => ( a . euclidean_distance ( & b) , ( a, b) ) ,
68
+ ( None , Some ( ( a, b) ) ) => ( a . euclidean_distance ( & b) , ( a, b) ) ,
76
69
( None , None ) => unreachable ! ( ) ,
77
70
} ;
78
71
79
- let mid_x = points[ mid] . 0 ;
80
- let dist = min_sqr_dist. sqrt ( ) ;
81
- while points[ start] . 0 < mid_x - dist {
72
+ let mid_x = points[ mid] . x ;
73
+ let dist = min_sqr_dist;
74
+ while points[ start] . x < mid_x - dist {
82
75
start += 1 ;
83
76
}
84
- while points[ end - 1 ] . 0 > mid_x + dist {
77
+ while points[ end - 1 ] . x > mid_x + dist {
85
78
end -= 1 ;
86
79
}
87
80
88
81
let mut mids: Vec < & Point > = points[ start..end] . iter ( ) . collect ( ) ;
89
- mids. sort_by ( |a, b| f64_cmp ( & a. 1 , & b. 1 ) ) ;
82
+ mids. sort_by ( |a, b| f64_cmp ( & a. y , & b. y ) ) ;
90
83
91
84
for ( i, e) in mids. iter ( ) . enumerate ( ) {
92
85
for k in 1 ..8 {
93
86
if i + k >= mids. len ( ) {
94
87
break ;
95
88
}
96
89
97
- let new = sqr_dist ( e , mids[ i + k] ) ;
90
+ let new = e . euclidean_distance ( mids[ i + k] ) ;
98
91
if new < min_sqr_dist {
99
92
min_sqr_dist = new;
100
- pair = ( * * e , * mids[ i + k] ) ;
93
+ pair = ( ( * e ) . clone ( ) , mids[ i + k] . clone ( ) ) ;
101
94
}
102
95
}
103
96
}
@@ -137,86 +130,101 @@ mod tests {
137
130
138
131
#[ test]
139
132
fn one_points ( ) {
140
- let vals = [ ( 0. , 0. ) ] ;
133
+ let vals = [ Point :: new ( 0. , 0. ) ] ;
141
134
assert_display ! ( closest_points( & vals) , None :: <( Point , Point ) >) ;
142
135
}
143
136
144
137
#[ test]
145
138
fn two_points ( ) {
146
- let vals = [ ( 0. , 0. ) , ( 1. , 1. ) ] ;
147
- assert_display ! ( closest_points( & vals) , Some ( ( ( 0. , 0. ) , ( 1. , 1. ) ) ) ) ;
139
+ let vals = [ Point :: new ( 0. , 0. ) , Point :: new ( 1. , 1. ) ] ;
140
+ assert_display ! (
141
+ closest_points( & vals) ,
142
+ Some ( ( vals[ 0 ] . clone( ) , vals[ 1 ] . clone( ) ) )
143
+ ) ;
148
144
}
149
145
150
146
#[ test]
151
147
fn three_points ( ) {
152
- let vals = [ ( 0. , 0. ) , ( 1. , 1. ) , ( 3. , 3. ) ] ;
153
- assert_display ! ( closest_points( & vals) , Some ( ( ( 0. , 0. ) , ( 1. , 1. ) ) ) ) ;
148
+ let vals = [ Point :: new ( 0. , 0. ) , Point :: new ( 1. , 1. ) , Point :: new ( 3. , 3. ) ] ;
149
+ assert_display ! (
150
+ closest_points( & vals) ,
151
+ Some ( ( vals[ 0 ] . clone( ) , vals[ 1 ] . clone( ) ) )
152
+ ) ;
154
153
}
155
154
156
155
#[ test]
157
156
fn list_1 ( ) {
158
157
let vals = [
159
- ( 0. , 0. ) ,
160
- ( 2. , 1. ) ,
161
- ( 5. , 2. ) ,
162
- ( 2. , 3. ) ,
163
- ( 4. , 0. ) ,
164
- ( 0. , 4. ) ,
165
- ( 5. , 6. ) ,
166
- ( 4. , 4. ) ,
167
- ( 7. , 3. ) ,
168
- ( -1. , 2. ) ,
169
- ( 2. , 6. ) ,
158
+ Point :: new ( 0. , 0. ) ,
159
+ Point :: new ( 2. , 1. ) ,
160
+ Point :: new ( 5. , 2. ) ,
161
+ Point :: new ( 2. , 3. ) ,
162
+ Point :: new ( 4. , 0. ) ,
163
+ Point :: new ( 0. , 4. ) ,
164
+ Point :: new ( 5. , 6. ) ,
165
+ Point :: new ( 4. , 4. ) ,
166
+ Point :: new ( 7. , 3. ) ,
167
+ Point :: new ( -1. , 2. ) ,
168
+ Point :: new ( 2. , 6. ) ,
170
169
] ;
171
- assert_display ! ( closest_points( & vals) , Some ( ( ( 2. , 1. ) , ( 2. , 3. ) ) ) ) ;
170
+ assert_display ! (
171
+ closest_points( & vals) ,
172
+ Some ( ( Point :: new( 2. , 1. ) , Point :: new( 2. , 3. ) ) )
173
+ ) ;
172
174
}
173
175
174
176
#[ test]
175
177
fn list_2 ( ) {
176
178
let vals = [
177
- ( 1. , 3. ) ,
178
- ( 4. , 6. ) ,
179
- ( 8. , 8. ) ,
180
- ( 7. , 5. ) ,
181
- ( 5. , 3. ) ,
182
- ( 10. , 3. ) ,
183
- ( 7. , 1. ) ,
184
- ( 8. , 3. ) ,
185
- ( 4. , 9. ) ,
186
- ( 4. , 12. ) ,
187
- ( 4. , 15. ) ,
188
- ( 7. , 14. ) ,
189
- ( 8. , 12. ) ,
190
- ( 6. , 10. ) ,
191
- ( 4. , 14. ) ,
192
- ( 2. , 7. ) ,
193
- ( 3. , 8. ) ,
194
- ( 5. , 8. ) ,
195
- ( 6. , 7. ) ,
196
- ( 8. , 10. ) ,
197
- ( 6. , 12. ) ,
179
+ Point :: new ( 1. , 3. ) ,
180
+ Point :: new ( 4. , 6. ) ,
181
+ Point :: new ( 8. , 8. ) ,
182
+ Point :: new ( 7. , 5. ) ,
183
+ Point :: new ( 5. , 3. ) ,
184
+ Point :: new ( 10. , 3. ) ,
185
+ Point :: new ( 7. , 1. ) ,
186
+ Point :: new ( 8. , 3. ) ,
187
+ Point :: new ( 4. , 9. ) ,
188
+ Point :: new ( 4. , 12. ) ,
189
+ Point :: new ( 4. , 15. ) ,
190
+ Point :: new ( 7. , 14. ) ,
191
+ Point :: new ( 8. , 12. ) ,
192
+ Point :: new ( 6. , 10. ) ,
193
+ Point :: new ( 4. , 14. ) ,
194
+ Point :: new ( 2. , 7. ) ,
195
+ Point :: new ( 3. , 8. ) ,
196
+ Point :: new ( 5. , 8. ) ,
197
+ Point :: new ( 6. , 7. ) ,
198
+ Point :: new ( 8. , 10. ) ,
199
+ Point :: new ( 6. , 12. ) ,
198
200
] ;
199
- assert_display ! ( closest_points( & vals) , Some ( ( ( 4. , 14. ) , ( 4. , 15. ) ) ) ) ;
201
+ assert_display ! (
202
+ closest_points( & vals) ,
203
+ Some ( ( Point :: new( 4. , 14. ) , Point :: new( 4. , 15. ) ) )
204
+ ) ;
200
205
}
201
206
202
207
#[ test]
203
208
fn vertical_points ( ) {
204
209
let vals = [
205
- ( 0. , 0. ) ,
206
- ( 0. , 50. ) ,
207
- ( 0. , -25. ) ,
208
- ( 0. , 40. ) ,
209
- ( 0. , 42. ) ,
210
- ( 0. , 100. ) ,
211
- ( 0. , 17. ) ,
212
- ( 0. , 29. ) ,
213
- ( 0. , -50. ) ,
214
- ( 0. , 37. ) ,
215
- ( 0. , 34. ) ,
216
- ( 0. , 8. ) ,
217
- ( 0. , 3. ) ,
218
- ( 0. , 46. ) ,
210
+ Point :: new ( 0. , 0. ) ,
211
+ Point :: new ( 0. , 50. ) ,
212
+ Point :: new ( 0. , -25. ) ,
213
+ Point :: new ( 0. , 40. ) ,
214
+ Point :: new ( 0. , 42. ) ,
215
+ Point :: new ( 0. , 100. ) ,
216
+ Point :: new ( 0. , 17. ) ,
217
+ Point :: new ( 0. , 29. ) ,
218
+ Point :: new ( 0. , -50. ) ,
219
+ Point :: new ( 0. , 37. ) ,
220
+ Point :: new ( 0. , 34. ) ,
221
+ Point :: new ( 0. , 8. ) ,
222
+ Point :: new ( 0. , 3. ) ,
223
+ Point :: new ( 0. , 46. ) ,
219
224
] ;
220
- assert_display ! ( closest_points( & vals) , Some ( ( ( 0. , 40. ) , ( 0. , 42. ) ) ) ) ;
225
+ assert_display ! (
226
+ closest_points( & vals) ,
227
+ Some ( ( Point :: new( 0. , 40. ) , Point :: new( 0. , 42. ) ) )
228
+ ) ;
221
229
}
222
230
}
0 commit comments