add day 8

This commit is contained in:
Joseph Montanaro 2022-12-08 14:29:47 -08:00
parent 6abb28f96f
commit 2e2d668269
2 changed files with 97 additions and 0 deletions

View File

@ -35,6 +35,10 @@ path = "src/day6.rs"
name = "day7"
path = "src/day7.rs"
[[bin]]
name = "day8"
path = "src/day8.rs"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]

93
2022/src/day8.rs Normal file
View File

@ -0,0 +1,93 @@
const DATA: &'static str = include_str!("../data/day8.txt");
// const DATA: &'static str = "
// 30373
// 25512
// 65332
// 33549
// 35390
// ";
// O(N * (2 * sqrt(N) - 1)), so roughly N^1.5? Where N is number of elements in the grid
fn is_visible(grid: &Vec<Vec<usize>>, x: usize, y: usize) -> bool {
let height = grid[y][x];
let rows = grid.len();
let cols = grid[x].len();
// search horizontal
let vis_left = (0..x).all(|cmp_x| grid[y][cmp_x] < height);
let vis_right = ((x + 1)..cols).all(|cmp_x| grid[y][cmp_x] < height);
let vis_top = (0..y).all(|cmp_y| grid[cmp_y][x] < height);
let vis_bottom = ((y + 1)..rows).all(|cmp_y| grid[cmp_y][x] < height);
vis_left || vis_right || vis_top || vis_bottom
}
fn scenic_score(grid: &Vec<Vec<usize>>, x: usize, y: usize) -> usize {
let height = grid[y][x];
let rows = grid.len();
let cols = grid[x].len();
let sc_left = (0..x).rev()
.position(|cmp_x| grid[y][cmp_x] >= height) // 0-indexed position of the first blocking tree
.map(|p| p + 1) // +1 since we include the blocking tree in the count
.unwrap_or(x); // if no blocking trees, score is how many are to the left of current
let sc_right = ((x + 1)..cols)
.position(|cmp_x| grid[y][cmp_x] >= height)
.map(|p| p + 1)
.unwrap_or(cols - x - 1); // e.g. if x is 4 and there are 5 cols, this is rightmost, so 5 - 4 - 1 = 0
let sc_top = (0..y).rev()
.position(|cmp_y| grid[cmp_y][x] >= height)
.map(|p| p + 1)
.unwrap_or(y);
let sc_bottom = ((y + 1)..rows)
.position(|cmp_y| grid[cmp_y][x] >= height)
.map(|p| p + 1)
.unwrap_or(rows - y - 1);
sc_left * sc_right * sc_top * sc_bottom
}
fn build_grid(data: &str) -> Result<Vec<Vec<usize>>, String> {
data.trim()
.lines()
.map(|line| {
line.chars()
.map(|c| c.to_digit(10).map(|c| c as usize).ok_or_else(|| format!("Failed to convert to integer: {c}") ))
.collect::<Result<Vec<usize>, String>>()
})
.collect::<Result<Vec<Vec<usize>>, String>>()
}
fn main() -> Result<(), String> {
let grid = build_grid(DATA)?;
let mut visible_trees = 0;
for y in 0..grid.len() {
for x in 0..grid[y].len() {
if is_visible(&grid, x, y) {
visible_trees += 1;
}
}
}
println!("Part 1: {visible_trees}");
let mut max_score = 0;
for y in 0..grid.len() {
for x in 0..grid[y].len() {
let score = scenic_score(&grid, x, y);
if score > max_score {
max_score = score;
}
}
}
println!("Part 2: {max_score}");
Ok(())
}