Skip to content

Commit b5b2eb3

Browse files
authored
Refactor closest_points to use common structures and functions (TheAlgorithms#512)
1 parent 28c553e commit b5b2eb3

File tree

1 file changed

+88
-80
lines changed

1 file changed

+88
-80
lines changed

src/geometry/closest_points.rs

Lines changed: 88 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
type Point = (f64, f64);
1+
use crate::geometry::Point;
22
use std::cmp::Ordering;
33

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);
66
match acmp {
7-
Ordering::Equal => f64_cmp(a2, b2),
7+
Ordering::Equal => f64_cmp(&p1.y, &p2.y),
88
_ => acmp,
99
}
1010
}
@@ -22,13 +22,6 @@ pub fn closest_points(points: &[Point]) -> Option<(Point, Point)> {
2222
closest_points_aux(&points, 0, points.len())
2323
}
2424

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-
3225
fn closest_points_aux(
3326
points: &[Point],
3427
mut start: usize,
@@ -42,15 +35,15 @@ fn closest_points_aux(
4235

4336
if n <= 3 {
4437
// 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());
4740

4841
for i in 1..n {
4942
for j in (i + 1)..n {
50-
let new = sqr_dist(&points[i], &points[j]);
43+
let new = points[i].euclidean_distance(&points[j]);
5144
if new < min {
5245
min = new;
53-
pair = (points[i], points[j]);
46+
pair = (points[i].clone(), points[j].clone());
5447
}
5548
}
5649
}
@@ -63,41 +56,41 @@ fn closest_points_aux(
6356

6457
let (mut min_sqr_dist, mut pair) = match (left, right) {
6558
(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);
6861
if dl < dr {
6962
(dl, (l1, l2))
7063
} else {
7164
(dr, (r1, r2))
7265
}
7366
}
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)),
7669
(None, None) => unreachable!(),
7770
};
7871

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 {
8275
start += 1;
8376
}
84-
while points[end - 1].0 > mid_x + dist {
77+
while points[end - 1].x > mid_x + dist {
8578
end -= 1;
8679
}
8780

8881
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));
9083

9184
for (i, e) in mids.iter().enumerate() {
9285
for k in 1..8 {
9386
if i + k >= mids.len() {
9487
break;
9588
}
9689

97-
let new = sqr_dist(e, mids[i + k]);
90+
let new = e.euclidean_distance(mids[i + k]);
9891
if new < min_sqr_dist {
9992
min_sqr_dist = new;
100-
pair = (**e, *mids[i + k]);
93+
pair = ((*e).clone(), mids[i + k].clone());
10194
}
10295
}
10396
}
@@ -137,86 +130,101 @@ mod tests {
137130

138131
#[test]
139132
fn one_points() {
140-
let vals = [(0., 0.)];
133+
let vals = [Point::new(0., 0.)];
141134
assert_display!(closest_points(&vals), None::<(Point, Point)>);
142135
}
143136

144137
#[test]
145138
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+
);
148144
}
149145

150146
#[test]
151147
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+
);
154153
}
155154

156155
#[test]
157156
fn list_1() {
158157
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.),
170169
];
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+
);
172174
}
173175

174176
#[test]
175177
fn list_2() {
176178
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.),
198200
];
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+
);
200205
}
201206

202207
#[test]
203208
fn vertical_points() {
204209
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.),
219224
];
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+
);
221229
}
222230
}

0 commit comments

Comments
 (0)