Compare commits
No commits in common. "17a0b665a50d5a5f72171da6f0f028f7c4a94f24" and "5d6e3ac56f2d38638371eed1803d18e8e1a20b42" have entirely different histories.
17a0b665a5
...
5d6e3ac56f
1 changed files with 30 additions and 61 deletions
|
@ -1,5 +1,6 @@
|
||||||
#![warn(clippy::pedantic)]
|
#![warn(clippy::pedantic)]
|
||||||
use std::{
|
use std::{
|
||||||
|
collections::HashMap,
|
||||||
convert::Infallible,
|
convert::Infallible,
|
||||||
io::{stdin, BufRead},
|
io::{stdin, BufRead},
|
||||||
str::FromStr,
|
str::FromStr,
|
||||||
|
@ -17,8 +18,27 @@ impl Line {
|
||||||
self.start.x == self.end.x || self.start.y == self.end.y
|
self.start.x == self.end.x || self.start.y == self.end.y
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn expand(&self) -> impl Iterator<Item = Vector2D<usize>> {
|
pub fn expand(&self) -> Vec<Vector2D<usize>> {
|
||||||
LinePoints::new(self)
|
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()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,66 +57,15 @@ impl FromStr for Line {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct LinePoints {
|
|
||||||
pos: Vector2D<isize>,
|
|
||||||
step: Vector2D<isize>,
|
|
||||||
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<usize>;
|
|
||||||
|
|
||||||
fn next(&mut self) -> Option<Self::Item> {
|
|
||||||
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<Item = &'a Line>) -> usize {
|
fn count_overlaps<'a>(it: impl IntoIterator<Item = &'a Line>) -> usize {
|
||||||
let points: Vec<(usize, usize)> = it
|
let counts: HashMap<(usize, usize), usize> =
|
||||||
.into_iter()
|
it.into_iter()
|
||||||
.flat_map(Line::expand)
|
.flat_map(Line::expand)
|
||||||
.map(Into::into)
|
.fold(HashMap::new(), |mut map, point| {
|
||||||
.collect();
|
*map.entry(point.into()).or_default() += 1;
|
||||||
|
map
|
||||||
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))
|
|
||||||
});
|
});
|
||||||
|
counts.into_iter().filter(|&(_k, v)| v >= 2).count()
|
||||||
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() {
|
fn main() {
|
||||||
|
|
Loading…
Reference in a new issue