2021 day5/rust: add solution
This commit is contained in:
parent
60c8b8eac1
commit
5d6e3ac56f
2 changed files with 92 additions and 0 deletions
9
2021/day5/day5_rs/Cargo.toml
Normal file
9
2021/day5/day5_rs/Cargo.toml
Normal file
|
@ -0,0 +1,9 @@
|
|||
[package]
|
||||
name = "day5_rs"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
vector2d = "2.2.0"
|
83
2021/day5/day5_rs/src/main.rs
Normal file
83
2021/day5/day5_rs/src/main.rs
Normal file
|
@ -0,0 +1,83 @@
|
|||
#![warn(clippy::pedantic)]
|
||||
use std::{
|
||||
collections::HashMap,
|
||||
convert::Infallible,
|
||||
io::{stdin, BufRead},
|
||||
str::FromStr,
|
||||
};
|
||||
use vector2d::Vector2D;
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
struct Line {
|
||||
start: Vector2D<usize>,
|
||||
end: Vector2D<usize>,
|
||||
}
|
||||
|
||||
impl Line {
|
||||
pub fn is_straight(&self) -> bool {
|
||||
self.start.x == self.end.x || self.start.y == self.end.y
|
||||
}
|
||||
|
||||
pub fn expand(&self) -> Vec<Vector2D<usize>> {
|
||||
let delta = self.end.as_isizes() - self.start.as_isizes();
|
||||
|
||||
#[allow(clippy::if_not_else)]
|
||||
let len = if delta.x != 0 {
|
||||
delta.x.abs()
|
||||
} else if delta.y != 0 {
|
||||
delta.y.abs()
|
||||
} else {
|
||||
unreachable!()
|
||||
};
|
||||
|
||||
let step = delta / len;
|
||||
|
||||
(0..=len)
|
||||
.scan(self.start, |acc, _| {
|
||||
let prev = *acc;
|
||||
*acc = (acc.as_isizes() + step).as_usizes();
|
||||
Some(prev)
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
}
|
||||
|
||||
impl FromStr for Line {
|
||||
type Err = Infallible;
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
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]),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
fn count_overlaps<'a>(it: impl IntoIterator<Item = &'a Line>) -> usize {
|
||||
let counts: HashMap<(usize, usize), usize> =
|
||||
it.into_iter()
|
||||
.flat_map(Line::expand)
|
||||
.fold(HashMap::new(), |mut map, point| {
|
||||
*map.entry(point.into()).or_default() += 1;
|
||||
map
|
||||
});
|
||||
counts.into_iter().filter(|&(_k, v)| v >= 2).count()
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let lines: Vec<Line> = stdin()
|
||||
.lock()
|
||||
.lines()
|
||||
.map(|s| s.unwrap().parse().unwrap())
|
||||
.collect();
|
||||
|
||||
println!(
|
||||
"{}",
|
||||
count_overlaps(lines.iter().filter(|line| line.is_straight()))
|
||||
);
|
||||
println!("{}", count_overlaps(&lines));
|
||||
}
|
Loading…
Reference in a new issue