diff --git a/contents/graham_scan/code/rust/graham_scan b/contents/graham_scan/code/rust/graham_scan new file mode 100755 index 000000000..da9dc17ea Binary files /dev/null and b/contents/graham_scan/code/rust/graham_scan differ diff --git a/contents/graham_scan/code/rust/graham_scan.rs b/contents/graham_scan/code/rust/graham_scan.rs new file mode 100644 index 000000000..20532e4c0 --- /dev/null +++ b/contents/graham_scan/code/rust/graham_scan.rs @@ -0,0 +1,73 @@ +#[derive(Debug)] +struct Point { + x: f64, + y: f64, +} + +// Check if the turn of the points is counter clockwise. +fn counter_clockwise(a: &Point, b: &Point, c: &Point) -> bool { + (b.x - a.x) * (c.y - a.y) >= (b.y - a.y) * (c.x - a.x) +} + +// Calculate the polar angle of a point relative to a reference point. +fn polar_angle(reference: &Point, point: &Point) -> f64 { + (point.y - point.y).atan2(point.x - reference.x) +} + +fn graham_scan(mut points: Vec) -> Vec { + // First, sort the points so the one with the lowest y-coordinate comes first (the pivot) + sort_based_on_lowest_coordinate(&mut points); + + // Take ownership of the pivot point + let pivot = points.remove(0); + + // Sort all points based on the angle between the pivot point and itself + &mut points + .sort_by(|a, b| (polar_angle(a, &pivot).partial_cmp(&polar_angle(b, &pivot))).unwrap()); + + // Reinsert the pivot point + points.insert(0, pivot); + + let n = points.len(); + let mut m = 1; + + // Move the points of the hull towards the beginning of the vector. + for mut i in 2..n { + while counter_clockwise(&points[m - 1], &points[m], &points[i]) { + if m > 1 { + m -= 1; + } else if m == i { + break; + } else { + i += 1; + } + } + + m += 1; + points.swap(i, m); + } + + // Remove all non-hull points from the vector + points.truncate(m + 1); + points +} + +fn sort_based_on_lowest_coordinate(points: &mut Vec) { + points.sort_unstable_by(|a, b| (a.y).partial_cmp(&b.y).unwrap()); +} + +fn main() { + let points = vec![ + Point { x: 1.0, y: 3.0 }, + Point { x: 2.0, y: 4.0 }, + Point { x: 4.0, y: 0.0 }, + Point { x: 1.0, y: 0.0 }, + Point { x: 0.0, y: 2.0 }, + Point { x: 2.0, y: 2.0 }, + Point { x: 3.0, y: 4.0 }, + Point { x: 3.0, y: 1.0 }, + ]; + + let hull_points = graham_scan(points); + println!("{:#?}", hull_points); +} diff --git a/contents/graham_scan/graham_scan.md b/contents/graham_scan/graham_scan.md index e0323d961..fef139ef6 100644 --- a/contents/graham_scan/graham_scan.md +++ b/contents/graham_scan/graham_scan.md @@ -28,6 +28,8 @@ We can find whether a rotation is counter-clockwise with trigonometric functions [import:27-29, lang:"java"](code/java/GrahamScan.java) {% sample lang="cpp" %} [import:10-12, lang="cpp"](code/c++/graham_scan.cpp) +{% sample lang="rs" %} +[import:7-10, lang: "rust"](code/rust/graham_scan.rs) {% endmethod %} If the output of this function is 0, the points are collinear. @@ -58,6 +60,8 @@ In the end, the code should look something like this: [import:35-70, lang:"java"](code/java/GrahamScan.java) {% sample lang="cpp" %} [import:14-47, lang="cpp"](code/c++/graham_scan.cpp) +{% sample lang="rs" %} +[import:17-53, lang: "rust"](code/rust/graham_scan.rs) {% endmethod %} ### Bibliography @@ -83,6 +87,8 @@ In the end, the code should look something like this: [import, lang:"java"](code/java/GrahamScan.java) {% sample lang="cpp" %} [import, lang="cpp"](code/c++/graham_scan.cpp) +{% sample lang="rs" %} +[import, lang: "rust"](code/rust/graham_scan.rs) {% endmethod %}