#![warn(clippy::pedantic)] use std::{ convert::Infallible, io::{stdin, BufRead}, str::FromStr, }; use vector2d::Vector2D; #[derive(Copy, Clone, Debug)] struct Line { start: Vector2D, end: Vector2D, } impl Line { pub fn is_straight(&self) -> bool { self.start.x == self.end.x || self.start.y == self.end.y } pub fn expand(&self) -> impl Iterator> { LinePoints::new(self) } } impl FromStr for Line { type Err = Infallible; fn from_str(s: &str) -> Result { let parts: Vec<_> = s.split(' ').collect(); let start: Vec<_> = parts[0].split(',').map(|n| n.parse().unwrap()).collect(); let end: Vec<_> = parts[2].split(',').map(|n| n.parse().unwrap()).collect(); Ok(Line { start: Vector2D::new(start[0], start[1]), end: Vector2D::new(end[0], end[1]), }) } } struct LinePoints { pos: Vector2D, step: Vector2D, points_left: usize, } impl LinePoints { fn new(line: &Line) -> Self { let start = line.start.as_isizes(); let end = line.end.as_isizes(); let delta = end - start; let step = Vector2D::new(delta.x.signum(), delta.y.signum()); let len = usize::max(delta.x.unsigned_abs(), delta.y.unsigned_abs()); Self { pos: start, step, points_left: len + 1, } } } impl Iterator for LinePoints { type Item = Vector2D; fn next(&mut self) -> Option { if self.points_left == 0 { return None; } let current = self.pos; self.pos += self.step; self.points_left -= 1; Some(current.as_usizes()) } } fn count_overlaps<'a>(it: impl IntoIterator) -> usize { let points: Vec<(usize, usize)> = it .into_iter() .flat_map(Line::expand) .map(Into::into) .collect(); let (max_x, max_y) = points.iter().fold((0, 0), |(acc_x, acc_y), &(x, y)| { (usize::max(acc_x, x), usize::max(acc_y, y)) }); let mut field = vec![vec![0_usize; max_y + 1]; max_x + 1]; let mut hits = 0; for (x, y) in points { let point = &mut field[x][y]; if *point == 1 { hits += 1; } *point += 1; } hits } fn main() { let lines: Vec = stdin() .lock() .lines() .map(|s| s.unwrap().parse().unwrap()) .collect(); println!( "{}", count_overlaps(lines.iter().filter(|line| line.is_straight())) ); println!("{}", count_overlaps(&lines)); }