From: Greg Burri Date: Thu, 8 Dec 2022 20:02:15 +0000 (+0100) Subject: Day 8 X-Git-Url: https://git.euphorik.ch/?a=commitdiff_plain;h=e5ed624af23f21b35b1972bbc4a1f9d380937e09;p=advent_of_code_2022.git Day 8 --- diff --git a/src/day08.rs b/src/day08.rs new file mode 100644 index 0000000..013d55d --- /dev/null +++ b/src/day08.rs @@ -0,0 +1,140 @@ +use itertools::{FoldWhile::{Continue, Done}, Itertools}; + +#[derive(Clone, Copy)] +enum Orientation { + West, + North, + Est, + South, +} + +#[derive(Debug)] +pub struct Matrix(Vec>); + +impl Matrix +where + T: Default + Clone +{ + fn new(h: usize, w: usize) -> Self { + let mut m: Vec> = Vec::new(); + for _ in 0..h { + m.push(vec![T::default(); w]); + } + Matrix(m) + } + + fn rotate(&self, i: usize, j: usize, o: Orientation) -> (usize, usize) { + match o { + Orientation::West => (i, j), + Orientation::North => (j, self.height() - i - 1), + Orientation::Est => (self.height() - i - 1, self.width() - j - 1), + Orientation::South => (self.width() - j - 1, i), + } + } + + fn get(&self, i: usize, j: usize) -> &T { + &self.0[i][j] + } + + fn get_orientation(&self, i: usize, j: usize, o: Orientation) -> &T { + let (i, j) = self.rotate(i, j, o); + &self.0[i][j] + } + + fn set_orientation(&mut self, i: usize, j: usize, o: Orientation, value: T) { + let (i, j) = self.rotate(i, j, o); + self.0[i][j] = value; + } + + fn height(&self) -> usize { + self.0.len() + } + + fn width(&self) -> usize { + self.0[0].len() + } +} + + +pub fn parse(input: &str) -> Matrix { + let mut m: Vec> = Vec::new(); + for l in input.lines() { + let row: Vec = l.trim().chars().map(|c| c.to_digit(10).unwrap() as i32).collect(); + m.push(row); + } + Matrix(m) +} + +// O(n). +pub fn number_of_visible_trees(forest: &Matrix) -> i32 { + let h = forest.height(); + let w = forest.width(); + + let mut visibility = Matrix::::new(h, w); + let mut nb_visible_tree = 0; + + for o in [Orientation::West, Orientation::North, Orientation::Est, Orientation::South] { + for i in 0..h { + let mut max = -1; + for j in 0..w { + let tree_height = forest.get_orientation(i, j, o); + if *tree_height > max { + if !visibility.get_orientation(i, j, o) { + visibility.set_orientation(i, j, o, true); + nb_visible_tree += 1 + } + max = *tree_height; + } + } + } + } + nb_visible_tree +} + +pub fn best_scenic_score(forest: &Matrix) -> i32 { + let h = forest.height(); + let w = forest.width(); + + let mut current_best_score = -1; + + for i in 1..h-1 { + for j in 1..w-1 { + let current = forest.get(i, j); + let dist_w = (1..j).rev().fold_while(1, |dist, j2| if forest.get(i, j2) >= current { Done(dist) } else { Continue(dist + 1) }).into_inner(); + let dist_n = (1..i).rev().fold_while(1, |dist, i2| if forest.get(i2, j) >= current { Done(dist) } else { Continue(dist + 1) }).into_inner(); + let dist_e = (j+1..w-1).fold_while(1, |dist, j2| if forest.get(i, j2) >= current { Done(dist) } else { Continue(dist + 1) }).into_inner(); + let dist_s = (i+1..h-1).fold_while(1, |dist, i2| if forest.get(i2, j) >= current { Done(dist) } else { Continue(dist + 1) }).into_inner(); + + let score = dist_w * dist_n * dist_e * dist_s; + if score > current_best_score { + current_best_score = score; + } + } + } + + current_best_score +} + +#[cfg(test)] +mod tests { + use super::*; + + static FOREST: &str = + "30373 + 25512 + 65332 + 33549 + 35390"; + + #[test] + fn part1() { + let forest = parse(FOREST); + assert_eq!(number_of_visible_trees(&forest), 21) + } + + #[test] + fn part2() { + let forest = parse(FOREST); + assert_eq!(best_scenic_score(&forest), 8) + } +} \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index cf08101..28b0f67 100644 --- a/src/main.rs +++ b/src/main.rs @@ -8,6 +8,7 @@ mod day04; mod day05; mod day06; mod day07; +mod day08; fn day01() -> String { let f = fs::File::open("data/day01.input").unwrap(); @@ -64,6 +65,11 @@ fn day07() -> String { format!("part1: {}, part2: {}", sum_part1, min_part2) } +fn day08() -> String { + let forest = day08::parse(&fs::read_to_string("data/day08.input").unwrap()); + format!("part1: {}, part2: {}", day08::number_of_visible_trees(&forest), day08::best_scenic_score(&forest)) +} + fn format_micros(t: u128) -> String { if t < 10_000 { format!("{} μs", t) @@ -90,6 +96,7 @@ fn main() { day05, day06, day07, + day08, ); let args: Vec = env::args().skip(1).collect();