AoC_2021/src/day05.rs

111 lines
2.8 KiB
Rust

use aoc_runner_derive::{aoc, aoc_generator};
#[derive(Debug)]
pub struct Line {
x: (i64, i64),
y: (i64, i64),
}
impl Line {
fn iter(&self) -> LineIterator {
let ret = LineIterator {
line: self,
px: self.x.0,
py: self.y.0,
sx: match self.x.0.cmp(&self.x.1) {
std::cmp::Ordering::Less => 1,
std::cmp::Ordering::Equal => 0,
std::cmp::Ordering::Greater => -1,
},
sy: match self.y.0.cmp(&self.y.1) {
std::cmp::Ordering::Less => 1,
std::cmp::Ordering::Equal => 0,
std::cmp::Ordering::Greater => -1,
},
};
assert!(ret.sx != 0 || ret.sy != 0);
ret
}
}
#[derive(Debug)]
struct LineIterator<'a> {
line: &'a Line,
px: i64,
py: i64,
sx: i64,
sy: i64,
}
impl<'a> Iterator for LineIterator<'a> {
type Item = (i64, i64);
fn next(&mut self) -> Option<Self::Item> {
let ret = (self.px, self.py);
if self.sx > 0 && self.px > self.line.x.1 {
return None;
}
if self.sx < 0 && self.px < self.line.x.1 {
return None;
}
if self.sy > 0 && self.py > self.line.y.1 {
return None;
}
if self.sy < 0 && self.py < self.line.y.1 {
return None;
}
self.px += self.sx;
self.py += self.sy;
Some(ret)
}
}
type Data = Vec<Line>;
#[aoc_generator(day05)]
pub fn input_generator(input: &str) -> Data {
input
.lines()
.map(|line| {
let parts = line.split(" -> ").collect::<Vec<_>>();
let start = parts[0]
.split(',')
.map(|v| v.parse().unwrap())
.collect::<Vec<i64>>();
let end = parts[1]
.split(',')
.map(|v| v.parse().unwrap())
.collect::<Vec<i64>>();
Line {
x: (start[0], end[0]),
y: (start[1], end[1]),
}
})
.collect()
}
#[aoc(day05, part1)]
pub fn solve_part1(input: &Data) -> usize {
let mut grid = vec![vec![0u8; 1000]; 1000];
for (x, y) in input
.iter()
.filter(|l| l.x.0 == l.x.1 || l.y.0 == l.y.1)
.flat_map(|v| v.iter())
{
let x: usize = x.try_into().unwrap();
let y: usize = y.try_into().unwrap();
grid[x][y] += 1;
}
return grid.iter().flatten().filter(|&v| *v > 1).count();
}
#[aoc(day05, part2)]
pub fn solve_part2(input: &Data) -> usize {
let mut grid = vec![vec![0u8; 1000]; 1000];
for (x, y) in input.iter().flat_map(|v| v.iter()) {
let x: usize = x.try_into().unwrap();
let y: usize = y.try_into().unwrap();
grid[x][y] += 1;
}
return grid.iter().flatten().filter(|&v| *v > 1).count();
}