#[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 { 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>, } impl From<&[Line]> for Grid { fn from(lines: &[Line]) -> Self { let bounds = Point::get_bounds(&lines.iter().map(Line::get_bounds).collect::>()); 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 } }