diff --git a/Cargo.lock b/Cargo.lock index 114b325..695fd7f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -12,6 +12,7 @@ dependencies = [ "num-derive", "num-traits", "path-clean", + "take-until", ] [[package]] @@ -127,6 +128,12 @@ dependencies = [ "unicode-xid", ] +[[package]] +name = "take-until" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4e17d8598067a8c134af59cd33c1c263470e089924a11ab61cf61690919fe3b" + [[package]] name = "unicode-xid" version = "0.1.0" diff --git a/Cargo.toml b/Cargo.toml index 812ee0c..b4ada73 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,3 +13,4 @@ itertools = "0.10.5" nom = "7.1.1" path-clean = "0.1.0" grid = "0.9.0" +take-until = "0.1.0" diff --git a/src/bin/p08.rs b/src/bin/p08.rs index 11bf179..6fbaade 100644 --- a/src/bin/p08.rs +++ b/src/bin/p08.rs @@ -4,6 +4,7 @@ use std::fs; use std::io::{self, BufRead}; use grid::Grid; +use take_until::TakeUntilExt; struct Tree { height: u8, @@ -38,7 +39,7 @@ fn main() { println!("PART 1 ---------------"); part1(&mut grid); println!("\nPART 2 ---------------"); - part2(&mut grid); + part2(&grid); } fn part1(grid: &mut Grid) { @@ -68,49 +69,19 @@ fn part1(grid: &mut Grid) { dbg!(grid.iter().filter(|t| t.visible).count()); } -fn scenic_score(grid: &Grid, (row, col): (usize, usize)) -> u32 { - fn count_visible((i, max): (u32, u32), tree: &Tree) -> (u32, u32) { - if tree.height as u32 >= max { - (i, tree.height as u32) - } else { - (i + 1, max) - } +fn scenic_score(tree: &Tree, grid: &Grid, (row, col): (usize, usize)) -> usize { + fn count_visible<'a>(tree: &Tree, iter: impl Iterator>) -> usize { + iter.flatten() + .take_until(|t| t.height >= tree.height) + .count() } let (rows, cols) = grid.size(); - let (a, _) = if row > 0 { - (0..row - 1) - .rev() - .map(|r| grid.get(r, col).unwrap()) - .fold((1, 0), count_visible) - } else { - (0, 0) - }; - let (b, _) = if row < rows - 1 { - (row + 1..rows) - .map(|r| grid.get(r, col).unwrap()) - .fold((1, 0), count_visible) - } else { - (0, 0) - }; - let (c, _) = if col > 0 { - (0..col - 1) - .rev() - .map(|c| grid.get(row, c).unwrap()) - .fold((1, 0), count_visible) - } else { - (0, 0) - }; - let (d, _) = if col < cols - 1 { - (col + 1..cols) - .map(|c| grid.get(row, c).unwrap()) - .fold((1, 0), count_visible) - } else { - (0, 0) - }; - - println!("{},{}: {}, {}, {}, {}", row, col, a, b, c, d); + let a = count_visible(tree, (0..row).rev().map(|r| grid.get(r, col))); + let b = count_visible(tree, (row + 1..rows).map(|r| grid.get(r, col))); + let c = count_visible(tree, (0..col).rev().map(|c| grid.get(row, c))); + let d = count_visible(tree, (col + 1..cols).map(|c| grid.get(row, c))); a * b * c * d } @@ -120,8 +91,9 @@ fn part2(grid: &Grid) { dbg!(grid .iter() .enumerate() - .map(|(i, _)| scenic_score(grid, (i / cols, i % cols))) - .max()); + .map(|(i, t)| scenic_score(t, grid, (i / cols, i % cols))) + .max() + .unwrap()); } #[cfg(test)] @@ -141,10 +113,10 @@ mod tests { let vec: Vec = grid.iter().map(|n| Tree::new(*n)).collect(); let grid = Grid::from_vec(vec, 5); - let scores: Vec = grid + let scores: Vec = grid .iter() .enumerate() - .map(|(i, _)| scenic_score(&grid, (i / 5, i % 5))) + .map(|(i, t)| scenic_score(t, &grid, (i / 5, i % 5))) .collect(); dbg!(&scores);