2021: day05: part 2

This commit is contained in:
Antoine Martin 2021-12-05 16:53:46 +01:00
parent 44afc3bbdd
commit 1890268bd5

View file

@ -10,6 +10,7 @@ pub fn run() -> Result<String> {
let mut res = String::with_capacity(128); let mut res = String::with_capacity(128);
writeln!(res, "part 1: {}", part1(INPUT)?)?; writeln!(res, "part 1: {}", part1(INPUT)?)?;
writeln!(res, "part 2: {}", part2(INPUT)?)?;
Ok(res) Ok(res)
} }
@ -34,6 +35,23 @@ fn part1(input: &str) -> Result<usize> {
Ok(grid.into_values().filter(|c| *c > 1).count()) Ok(grid.into_values().filter(|c| *c > 1).count())
} }
fn part2(input: &str) -> Result<usize> {
let lines = input
.lines()
.map(str::parse::<Line>)
.collect::<Result<Vec<_>>>()?;
let mut grid = HashMap::new();
lines.iter().for_each(|l| {
for cell in l.cells() {
*grid.entry(cell).or_insert(0) += 1;
}
});
Ok(grid.into_values().filter(|c| *c > 1).count())
}
#[derive(Debug)] #[derive(Debug)]
struct Line { struct Line {
from: (usize, usize), from: (usize, usize),
@ -50,16 +68,32 @@ impl Line {
} }
fn cells(&self) -> Box<dyn Iterator<Item = (usize, usize)>> { fn cells(&self) -> Box<dyn Iterator<Item = (usize, usize)>> {
let min_x = self.from.0.min(self.to.0);
let max_x = self.from.0.max(self.to.0);
let min_y = self.from.1.min(self.to.1);
let max_y = self.from.1.max(self.to.1);
if self.is_horizontal() { if self.is_horizontal() {
let min = self.from.0.min(self.to.0); Box::new((min_x..=max_x).zip(iter::repeat(self.from.1))) as Box<dyn Iterator<Item = _>>
let max = self.from.0.max(self.to.0); } else if self.is_vertical() {
Box::new((min..=max).zip(iter::repeat(self.from.1))) Box::new(iter::repeat(self.from.0).zip(min_y..=max_y))
as Box<dyn Iterator<Item = (usize, usize)>>
} else { } else {
let min = self.from.1.min(self.to.1); let x_range = min_x..=max_x;
let max = self.from.1.max(self.to.1); let x_range = if self.from.0 < self.to.0 {
Box::new(iter::repeat(self.from.0).zip(min..=max)) Box::new(x_range) as Box<dyn Iterator<Item = _>>
as Box<dyn Iterator<Item = (usize, usize)>> } else {
Box::new(x_range.rev())
};
let y_range = min_y..=max_y;
let y_range = if self.from.1 < self.to.1 {
Box::new(y_range) as Box<dyn Iterator<Item = _>>
} else {
Box::new(y_range.rev())
};
Box::new(x_range.zip(y_range))
} }
} }
} }
@ -82,7 +116,7 @@ impl std::str::FromStr for Line {
let to = { let to = {
let (x, y) = to let (x, y) = to
.split_once(',') .split_once(',')
.context("couldn't parse line origin: missing `,`")?; .context("couldn't parse line end: missing `,`")?;
(x.parse()?, y.parse()?) (x.parse()?, y.parse()?)
}; };
@ -105,4 +139,14 @@ mod tests {
fn part1_real() { fn part1_real() {
assert_eq!(part1(INPUT).unwrap(), 4745); assert_eq!(part1(INPUT).unwrap(), 4745);
} }
#[test]
fn part2_provided() {
assert_eq!(part2(PROVIDED).unwrap(), 12);
}
#[test]
fn part2_real() {
assert_eq!(part2(INPUT).unwrap(), 18442);
}
} }