AoC21/src/day05.rs

113 lines
2.7 KiB
Rust

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<Line> = 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<Point, i32> = 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::<i32>().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<Point> {
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 }
}
}