115 lines
3 KiB
Rust
115 lines
3 KiB
Rust
#[derive(Debug, PartialEq, Copy, Clone)]
|
|
pub struct Point {
|
|
pub x: usize,
|
|
pub y: usize,
|
|
}
|
|
|
|
impl Point {
|
|
fn get_bounds(points: &[Point]) -> Point {
|
|
let x = points.iter().map(|p| p.x).max().unwrap_or_default();
|
|
let y = points.iter().map(|p| p.y).max().unwrap_or_default();
|
|
Point { x, y }
|
|
}
|
|
}
|
|
|
|
#[derive(Debug, PartialEq, Copy, Clone)]
|
|
pub struct Line {
|
|
pub start: Point,
|
|
pub end: Point,
|
|
}
|
|
|
|
impl Line {
|
|
pub fn is_vertical(&self) -> bool {
|
|
self.start.x == self.end.x
|
|
}
|
|
pub fn is_horizontal(&self) -> bool {
|
|
self.start.y == self.end.y
|
|
}
|
|
pub fn is_diagonal(&self) -> bool {
|
|
self.get_x_vec().abs() == self.get_y_vec().abs()
|
|
}
|
|
pub fn get_x_vec(&self) -> isize {
|
|
self.end.x as isize - self.start.x as isize
|
|
}
|
|
pub fn get_y_vec(&self) -> isize {
|
|
self.end.y as isize - self.start.y as isize
|
|
}
|
|
pub fn get_bounds(&self) -> Point {
|
|
Point::get_bounds(&[self.start, self.end])
|
|
}
|
|
pub fn get_points(&self) -> Vec<Point> {
|
|
let x_vector = self.get_x_vec();
|
|
let y_vector = self.get_y_vec();
|
|
let x_distance = x_vector.abs() as usize;
|
|
let y_distance = y_vector.abs() as usize;
|
|
let distance = if x_distance >= y_distance {
|
|
x_distance
|
|
} else {
|
|
y_distance
|
|
};
|
|
let mut points = Vec::new();
|
|
for i in 0..=distance {
|
|
let x = (self.start.x as isize
|
|
+ (x_vector as f64 / distance as f64 * i as f64) as isize)
|
|
as usize;
|
|
let y = (self.start.y as isize
|
|
+ (y_vector as f64 / distance as f64 * i as f64) as isize)
|
|
as usize;
|
|
points.push(Point { x, y })
|
|
}
|
|
points
|
|
}
|
|
}
|
|
|
|
pub struct Grid {
|
|
pub grid: Vec<Vec<u8>>,
|
|
}
|
|
|
|
impl From<&[Line]> for Grid {
|
|
fn from(lines: &[Line]) -> Self {
|
|
let bounds = Point::get_bounds(&lines.iter().map(Line::get_bounds).collect::<Vec<Point>>());
|
|
let mut grid_line = Vec::with_capacity(bounds.x);
|
|
for _ in 0..=bounds.x {
|
|
grid_line.push(0)
|
|
}
|
|
let mut grid = Vec::with_capacity(bounds.y);
|
|
for _ in 0..=bounds.y {
|
|
grid.push(grid_line.clone())
|
|
}
|
|
|
|
lines
|
|
.iter()
|
|
.flat_map(Line::get_points)
|
|
.for_each(|point| grid[point.y][point.x] += 1);
|
|
|
|
Grid { grid }
|
|
}
|
|
}
|
|
|
|
impl Grid {
|
|
pub fn count(&self) -> usize {
|
|
self.grid
|
|
.iter()
|
|
.flat_map(|line| line.iter())
|
|
.filter(|val| **val >= 2)
|
|
.count()
|
|
}
|
|
}
|
|
|
|
impl ToString for Grid {
|
|
fn to_string(&self) -> String {
|
|
let mut string = String::new();
|
|
self.grid.iter().for_each(|line| {
|
|
line.iter().for_each(|point| {
|
|
if *point == 0 {
|
|
string += ".";
|
|
} else {
|
|
string += &format!("{}", point);
|
|
}
|
|
});
|
|
string += "\n";
|
|
});
|
|
string
|
|
}
|
|
}
|