use std::cmp::{max, min}; use std::collections::HashMap; use std::fmt::Debug; pub fn day5() { // let input = r#" // 0,9 -> 5,9 // 8,0 -> 0,8 // 9,4 -> 3,4 // 2,2 -> 2,1 // 7,0 -> 7,4 // 6,4 -> 2,0 // 0,9 -> 2,9 // 3,4 -> 1,4 // 0,0 -> 8,8 // 5,5 -> 8,2 // "#; let input = include_str!("../input/day5.txt"); let lines: Vec = input.trim().lines().map(|s| s.into()).collect(); dbg!(Line { start: Point { x: 9, y: 7 }, end: Point { x: 7, y: 9 }, } .points(true)); for with_diag in vec![false, true] { let mut points: HashMap = HashMap::new(); for l in lines.iter() { for p in l.points(with_diag) { match points.get_mut(&p) { Some(count) => { *count += 1; } None => { points.insert(p, 1); } } } } println!( "with_diag: {}, overlapping: {}", with_diag, points.values().filter(|&&c| c > 1).count() ); } } #[derive(Clone, Copy, PartialEq, Eq, Hash)] struct Point { x: i32, y: i32, } impl Debug for Point { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.write_str(&format!("({}, {})", self.x, self.y)) } } impl From<&str> for Point { fn from(s: &str) -> Self { let mut components = s.split(",").map(|s| s.parse::().unwrap()); Self { x: components.next().unwrap(), y: components.next().unwrap(), } } } #[derive(Debug, Clone, Copy, PartialEq)] struct Line { start: Point, end: Point, } impl Line { fn is_diag(&self) -> bool { self.start.x != self.end.x && self.start.y != self.end.y } fn points(&self, with_diags: bool) -> Vec { if self.is_diag() && !with_diags { return vec![]; } let len = if self.start.x == self.end.x { max(self.start.y, self.end.y) - min(self.start.y, self.end.y) } else { max(self.start.x, self.end.x) - min(self.start.x, self.end.x) }; let dx = (self.end.x - self.start.x) / len; let dy = (self.end.y - self.start.y) / len; (0..=len) .map(|i| Point { x: self.start.x + dx * i, y: self.start.y + dy * i, }) .collect() } } impl From<&str> for Line { fn from(s: &str) -> Self { let mut parts = s.split_whitespace(); let start: Point = parts.next().unwrap().into(); parts.next(); let end: Point = parts.next().unwrap().into(); Self { start, end } } }