//! [`Point`], [`Fold`] and [`Canvas`] implementation. use std::{collections::HashSet, fmt::Display}; /// A point coordinate. #[derive(Debug, Hash, PartialEq, Eq)] pub struct Point(pub isize, pub isize); /// The types of fold that can be made. #[derive(Debug)] pub enum Fold { /// A horizontal fold going left. Horizontal(isize), /// A vertical fold going up. Vertical(isize), } /// The canvas of the paper. #[derive(Debug)] pub struct Canvas { /// The width of the canvas. pub width: isize, /// The height of the canvas. pub height: isize, /// The points on the canvas. pub points: HashSet, } impl Canvas { /// Perform a fold on the canvas and return the resulting version of it. pub fn fold(self, fold: &Fold) -> Self { let (width, height) = match fold { Fold::Horizontal(amount) => (self.width, *amount), Fold::Vertical(amount) => (*amount, self.height), }; let mut points = HashSet::new(); for Point(x, y) in self.points { if y > height { points.insert(Point(x, height - (y - height))); continue; } if x > width { points.insert(Point(width - (x - width), y)); continue; } points.insert(Point(x, y)); } Self { width, height, points, } } } impl Display for Canvas { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { for y in 0..self.height { for x in 0..self.width { if x % (self.width / 8) == 0 { write!(f, " ")?; } if self.points.contains(&Point(x, y)) { write!(f, "█")?; } else { write!(f, " ")?; } } writeln!(f)?; } Ok(()) } }