diff --git a/src/bin/day08.rs b/src/bin/day08.rs index deeab84..5e6c131 100644 --- a/src/bin/day08.rs +++ b/src/bin/day08.rs @@ -10,45 +10,49 @@ use tracing_subscriber::EnvFilter; type Input = Vec>; type Output = usize; +type SignedPosition = Vector2D; type Position = Vector2D; type Visited = BTreeSet; -fn count_in(trees: &Input, counted: &mut BTreeSet<(usize, usize)>, swap: bool) { +fn count_in(trees: &Input, counted: &mut Visited, swap: bool) { fn folder( trees: &Input, - counted: &mut BTreeSet<(usize, usize)>, - mut x: usize, - mut y: usize, + counted: &mut Visited, + mut pos: Position, swap: bool, tallest: i8, ) -> i8 { if swap { - (x, y) = (y, x); + pos = pos.swap(); } - if trees[y][x] > tallest { - counted.insert((x, y)); + if *index(trees, &pos) > tallest { + counted.insert(pos); } - max(tallest, trees[y][x]) + max(tallest, *index(trees, &pos)) } (0..trees.len()).for_each(|y| { - (0..trees[y].len()).fold(-1, |tallest, x| folder(trees, counted, x, y, swap, tallest)); - (0..trees[y].len()).rfold(-1, |tallest, x| folder(trees, counted, x, y, swap, tallest)); + (0..trees[y].len()).fold(-1, |tallest, x| { + folder(trees, counted, Position::new(x, y), swap, tallest) + }); + (0..trees[y].len()).rfold(-1, |tallest, x| { + folder(trees, counted, Position::new(x, y), swap, tallest) + }); }) } -fn count_in_rows(trees: &Input, counted: &mut BTreeSet<(usize, usize)>) { +fn count_in_rows(trees: &Input, counted: &mut Visited) { count_in(trees, counted, false) } -fn count_in_columns(trees: &Input, counted: &mut BTreeSet<(usize, usize)>) { +fn count_in_columns(trees: &Input, counted: &mut Visited) { count_in(trees, counted, true) } fn part_1(input: &Input) -> Output { - let mut counted: BTreeSet<(usize, usize)> = BTreeSet::new(); + let mut counted = Visited::new(); count_in_rows(input, &mut counted); count_in_columns(input, &mut counted); @@ -56,20 +60,15 @@ fn part_1(input: &Input) -> Output { counted.len() } -fn in_range(trees: &Input, x: i32, y: i32) -> bool { - y >= 0 && y < trees.len() as i32 && x >= 0 && x < trees[y as usize].len() as i32 -} - -fn count_visible(trees: &Input, x: i32, y: i32, dx: i32, dy: i32) -> usize { - let max_height = trees[y as usize][x as usize]; - let mut d = 1; - +fn count_visible(trees: &Input, position: SignedPosition, diff: SignedPosition) -> usize { + let max_height = *index(trees, &position); let mut visible = 0; - while in_range(trees, x + d * dx, y + d * dy) { + let mut d = 1; + while in_range(trees, &(position + diff * d)) { visible += 1; - if trees[(y + d * dy) as usize][(x + d * dx) as usize] >= max_height { + if *index(trees, &(position + diff * d)) >= max_height { break; } @@ -79,17 +78,23 @@ fn count_visible(trees: &Input, x: i32, y: i32, dx: i32, dy: i32) -> usize { visible as usize } -fn compute_scenic_score(trees: &Input, x: i32, y: i32) -> usize { +fn compute_scenic_score(trees: &Input, x: isize, y: isize) -> usize { vec![(0, 1), (1, 0), (0, -1), (-1, 0)] .iter() - .map(|&(dx, dy)| count_visible(trees, x, y, dx, dy)) + .map(|&(dx, dy)| { + count_visible( + trees, + SignedPosition::new(x, y), + SignedPosition::new(dx, dy), + ) + }) .product() } fn part_2(input: &Input) -> Output { (0..input.len()) .flat_map(|y| { - (0..input[y].len()).map(move |x| compute_scenic_score(input, x as i32, y as i32)) + (0..input[y].len()).map(move |x| compute_scenic_score(input, x as isize, y as isize)) }) .max() .unwrap()