81 lines
1.7 KiB
Rust
81 lines
1.7 KiB
Rust
//! [`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<Point>,
|
|
}
|
|
|
|
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(())
|
|
}
|
|
}
|