diff --git a/src/geometry.rs b/src/geometry.rs index d45dbfd..dd7a74d 100644 --- a/src/geometry.rs +++ b/src/geometry.rs @@ -1,12 +1,12 @@ use std::ops::Add; -#[derive(Debug, Copy, Clone)] +#[derive(Debug, Copy, Clone, Hash)] pub struct Point { x: u32, y: u32, } -#[derive(Debug, Copy, Clone, Eq, PartialEq)] +#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] pub struct Rectangle { top_left: Point, width: u32, diff --git a/src/main.rs b/src/main.rs index 8fb6361..a71b302 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,4 +1,5 @@ mod geometry; +mod stream_algos; fn main() { let p = geometry::Point::new(2, 3); diff --git a/src/stream_algos.rs b/src/stream_algos.rs new file mode 100644 index 0000000..7807576 --- /dev/null +++ b/src/stream_algos.rs @@ -0,0 +1,90 @@ +use crate::geometry::{Point, Rectangle}; +use std::collections::HashMap; +use std::ops::{Add, Mul}; + +impl Add for Rectangle { + type Output = Self; + + fn add(self, rhs: Point) -> Self { + Rectangle::from_corner_width_height(self.top_left() + rhs, self.width(), self.height()) + } +} + +impl Mul for Rectangle { + type Output = Self; + + fn mul(self, rhs: u32) -> Self { + Rectangle::from_corner_width_height( + self.top_left(), + self.width() * rhs, + self.height() * rhs, + ) + } +} + +/// Returns a stream of rectangles by translating (moving) each rectangle according to the given +/// distance vector. +pub fn translate(rects: T, distance_vector: Point) -> impl Iterator +where + T: Iterator, +{ + rects.map(move |r| r + distance_vector) +} + +/// Returns a stream of rectangles by scaling each rectangle by a given amount. +pub fn scale(rects: T, scale_factor: u32) -> impl Iterator +where + T: Iterator, +{ + rects.map(move |r| r * scale_factor) +} + +/// Returns a stream containing, in order, the bottom-left point of each input rectangle. +pub fn bottom_left_points(rects: T) -> impl Iterator +where + T: Iterator, +{ + rects.map(|r| r.bottom_left()) +} + +/// Returns a stream containing all rectangles that intersect with the given rectangle. +pub fn get_all_intersecting(rects: T, rectangle: &Rectangle) -> impl Iterator +where + T: Iterator, +{ + // We need to satisfy the borrow checker here. + let rectangle = rectangle.clone(); + rects.filter(move |r| r.intersects(&rectangle)) +} + +/// Returns the largest area among the given rectangles +pub fn get_largest_area(rects: impl Iterator) -> Option { + rects.map(|r| r.area()).max() +} + +/// Returns the largest height among the given rectangles +pub fn get_largest_height(rects: impl Iterator) -> Option { + rects.map(|r| r.height()).max() +} + +/// Returns the sum of the areas of the rectangles +pub fn get_area_sum(rects: impl Iterator) -> u32 { + rects.map(|r| r.area()).sum() +} + +/// Computes the sum of areas of all rectangles that intersect with the given rectangle. +pub fn get_area_sum_of_intersecting(rects: T, rectangle: &Rectangle) -> u32 +where + T: Iterator, +{ + get_area_sum(get_all_intersecting(rects, rectangle)) +} + +/// Returns map from rectangle to computed area +pub fn get_area_map(rects: T) -> HashMap +where + T: Iterator, +{ + // The type of the collect() function is chosen based on the return type that it's meant to fit + rects.map(|r| (r, r.area())).collect() +}