1
0
Fork 0
advent-of-code/src/bin/p08.rs

126 lines
3.2 KiB
Rust

#![feature(iterator_try_collect, absolute_path, hash_set_entry)]
use std::fs;
use std::io::{self, BufRead};
use grid::Grid;
use take_until::TakeUntilExt;
struct Tree {
height: u8,
visible: bool,
}
impl Tree {
fn new(height: u8) -> Self {
Tree {
height,
visible: false,
}
}
}
fn main() {
let filename = "etc/p08.txt";
let file = fs::File::open(filename).expect("Can't open file");
let mut count: Option<usize> = None;
let vec: Vec<Tree> = io::BufReader::new(file)
.lines()
.flatten()
.flat_map(|l| {
count.get_or_insert_with(|| l.chars().count());
l.chars()
.map(|c| Tree::new(c.to_digit(10).unwrap() as u8))
.collect::<Vec<Tree>>()
})
.collect();
let mut grid = Grid::from_vec(vec, count.unwrap());
println!("PART 1 ---------------");
part1(&mut grid);
println!("\nPART 2 ---------------");
part2(&grid);
}
fn part1(grid: &mut Grid<Tree>) {
fn height_pass(acc: u8, t: &mut Tree) -> u8 {
if t.height > acc {
t.visible = true;
}
t.height.max(acc)
}
grid.iter_col_mut(0).for_each(|t| t.visible = true);
grid.iter_col_mut(grid.cols() - 1)
.for_each(|t| t.visible = true);
grid.iter_row_mut(0).for_each(|t| t.visible = true);
grid.iter_row_mut(grid.rows() - 1)
.for_each(|t| t.visible = true);
for i in 0..grid.cols() {
grid.iter_col_mut(i).fold(0, height_pass);
grid.iter_col_mut(i).rev().fold(0, height_pass);
}
for i in 0..grid.rows() {
grid.iter_row_mut(i).fold(0, height_pass);
grid.iter_row_mut(i).rev().fold(0, height_pass);
}
dbg!(grid.iter().filter(|t| t.visible).count());
}
fn scenic_score(tree: &Tree, grid: &Grid<Tree>, (row, col): (usize, usize)) -> usize {
fn count_visible<'a>(tree: &Tree, iter: impl Iterator<Item = Option<&'a Tree>>) -> usize {
iter.flatten()
.take_until(|t| t.height >= tree.height)
.count()
}
let (rows, cols) = grid.size();
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
}
fn part2(grid: &Grid<Tree>) {
let cols = grid.cols();
dbg!(grid
.iter()
.enumerate()
.map(|(i, t)| scenic_score(t, grid, (i / cols, i % cols)))
.max()
.unwrap());
}
#[cfg(test)]
mod tests {
use super::*;
use grid::grid;
#[test]
fn small_grid() {
let grid = grid![
[3, 0, 3, 7, 3]
[2, 5, 5, 1, 2]
[6, 5, 3, 3, 2]
[3, 3, 5, 4, 9]
[3, 5, 3, 9, 0]
];
let vec: Vec<Tree> = grid.iter().map(|n| Tree::new(*n)).collect();
let grid = Grid::from_vec(vec, 5);
let scores: Vec<usize> = grid
.iter()
.enumerate()
.map(|(i, t)| scenic_score(t, &grid, (i / 5, i % 5)))
.collect();
dbg!(&scores);
assert_eq!(8, *scores.iter().max().unwrap());
}
}