aoc-rs-2021/src/day_05/model.rs
Jan Christian Grünhage c57507f579 implement day 5
2021-12-05 11:09:21 +01:00

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
}
}