113 lines
2.7 KiB
Rust
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 }
|
||
|
}
|
||
|
}
|