|
| 1 | + |
| 2 | +type Point = (i64, i64); |
| 3 | + |
| 4 | +// Is the turn counter clockwise? |
| 5 | +fn turn_counter_clockwise(p1: Point, p2: Point, p3: Point) -> bool { |
| 6 | + (p3.1 - p1.1) * (p2.0 - p1.0) >= (p2.1 - p1.1) * (p3.0 - p1.0) |
| 7 | +} |
| 8 | + |
| 9 | +fn jarvis_march(gift: &[Point]) -> Option<Vec<Point>> { |
| 10 | + // There can only be a convex hull if there are more than 2 points |
| 11 | + if gift.len() < 3 { |
| 12 | + return None; |
| 13 | + } |
| 14 | + |
| 15 | + let leftmost_point = gift |
| 16 | + // Iterate over all points |
| 17 | + .iter() |
| 18 | + // Find the point with minimum x |
| 19 | + .min_by_key(|i| i.0) |
| 20 | + // If there are no points in the gift, there might |
| 21 | + // not be a minimum. Unwrap fails (panics) the program |
| 22 | + // if there wasn't a minimum, but we know there always |
| 23 | + // is because we checked the size of the gift. |
| 24 | + .unwrap() |
| 25 | + .clone(); |
| 26 | + |
| 27 | + let mut hull = vec![leftmost_point]; |
| 28 | + |
| 29 | + let mut point_on_hull = leftmost_point; |
| 30 | + loop { |
| 31 | + // Search for the next point on the hull |
| 32 | + let mut endpoint = gift[0]; |
| 33 | + for i in 1..gift.len() { |
| 34 | + if endpoint == point_on_hull || !turn_counter_clockwise(gift[i], hull[hull.len() - 1], endpoint) { |
| 35 | + endpoint = gift[i]; |
| 36 | + } |
| 37 | + } |
| 38 | + |
| 39 | + point_on_hull = endpoint; |
| 40 | + |
| 41 | + // Stop whenever we got back to the same point |
| 42 | + // as we started with, and we wrapped the gift |
| 43 | + // completely. |
| 44 | + if hull[0] == endpoint { |
| 45 | + break; |
| 46 | + } else { |
| 47 | + hull.push(point_on_hull); |
| 48 | + } |
| 49 | + } |
| 50 | + |
| 51 | + Some(hull) |
| 52 | +} |
| 53 | + |
| 54 | +fn main() { |
| 55 | + let test_gift = vec![ |
| 56 | + (-5, 2), (5, 7), (-6, -12), (-14, -14), (9, 9), |
| 57 | + (-1, -1), (-10, 11), (-6, 15), (-6, -8), (15, -9), |
| 58 | + (7, -7), (-2, -9), (6, -5), (0, 14), (2, 8) |
| 59 | + ]; |
| 60 | + |
| 61 | + let hull = jarvis_march(&test_gift); |
| 62 | + |
| 63 | + println!("The points in the hull are: {:?}", hull); |
| 64 | +} |
0 commit comments