From fcae876701039250fc528ec8834991e7a9dc8122 Mon Sep 17 00:00:00 2001 From: Timothy Warren Date: Thu, 8 Dec 2022 16:01:22 -0500 Subject: [PATCH] Lots of progress on day 8 part 1 --- day8/README.md | 20 ++-- day8/src/main.rs | 197 +++++++++++++++++++++++++++++++++++++++- day8/src/test-input.txt | 5 + 3 files changed, 211 insertions(+), 11 deletions(-) create mode 100644 day8/src/test-input.txt diff --git a/day8/README.md b/day8/README.md index fc1bcdb..4c01488 100644 --- a/day8/README.md +++ b/day8/README.md @@ -4,7 +4,7 @@ The expedition comes across a peculiar patch of tall trees all planted carefully in a grid. The Elves explain that a previous expedition planted these trees as a reforestation effort. Now, they're curious if this would be a good location for a tree house. -First, determine whether there is enough tree cover here to keep a tree house hidden. To do this, you need to count the number of trees that are visible from outside the grid when looking directly along a row or column. +First, determine whether there is enough tree cover here to keep a tree house **hidden**. To do this, you need to count the number of trees that are **visible from outside the grid** when looking directly along a row or column. The Elves have already launched a quadcopter to generate a map with the height of each tree (your puzzle input). For example: @@ -16,18 +16,18 @@ The Elves have already launched a quadcopter to generate a map with the height o Each tree is represented as a single digit whose value is its height, where 0 is the shortest and 9 is the tallest. -A tree is visible if all of the other trees between it and an edge of the grid are shorter than it. Only consider trees in the same row or column; that is, only look up, down, left, or right from any given tree. +A tree is **visible** if all of the other trees between it and an edge of the grid are **shorter** than it. Only consider trees in the same row or column; that is, only look up, down, left, or right from any given tree. -All of the trees around the edge of the grid are visible - since they are already on the edge, there are no trees to block the view. In this example, that only leaves the interior nine trees to consider: +All of the trees around the edge of the grid are **visible** - since they are already on the edge, there are no trees to block the view. In this example, that only leaves the **interior nine trees** to consider: -* The top-left 5 is visible from the left and top. (It isn't visible from the right or bottom since other trees of height 5 are in the way.) -* The top-middle 5 is visible from the top and right. -* The top-right 1 is not visible from any direction; for it to be visible, there would need to only be trees of height 0 between it and an edge. -* The left-middle 5 is visible, but only from the right. +* The top-left 5 is **visible** from the left and top. (It isn't visible from the right or bottom since other trees of height 5 are in the way.) +* The top-middle 5 is **visible** from the top and right. +* The top-right 1 is not visible from any direction; for it to be visible, there would need to only be trees of height **0** between it and an edge. +* The left-middle 5 is **visible**, but only from the right. * The center 3 is not visible from any direction; for it to be visible, there would need to be only trees of at most height 2 between it and an edge. -* The right-middle 3 is visible from the right. -* In the bottom row, the middle 5 is visible, but the 3 and 4 are not. +* The right-middle 3 is **visible** from the right. +* In the bottom row, the middle 5 is **visible**, but the 3 and 4 are not. With 16 trees visible on the edge and another 5 visible in the interior, a total of 21 trees are visible in this arrangement. -Consider your map; how many trees are visible from outside the grid? +**Consider your map; how many trees are visible from outside the grid?** diff --git a/day8/src/main.rs b/day8/src/main.rs index 5b34eae..18e92da 100644 --- a/day8/src/main.rs +++ b/day8/src/main.rs @@ -1,8 +1,203 @@ +use std::collections::HashSet; + +#[derive(Debug, Copy, Clone, PartialOrd, PartialEq, Eq, Hash)] +enum VisibleDirection { + Top, + Bottom, + Left, + Right, +} + +use VisibleDirection::*; + +#[derive(Debug, Default)] +struct Tree { + height: usize, + visible: HashSet, +} + +impl Tree { + fn new(height: usize) -> Self { + Tree { + height, + ..Tree::default() + } + } + + fn is_visible(&self) -> bool { + !self.visible.is_empty() + } + + fn set_visible(&mut self, dir: VisibleDirection) -> &mut Self { + self.visible.insert(dir); + + self + } + + fn set_all_visible(&mut self) -> &mut Self { + self.set_visible(Top) + .set_visible(Bottom) + .set_visible(Left) + .set_visible(Right) + } +} + +// ---------------------------------------------------------------------------- + +#[derive(Debug)] +struct Grid { + width: usize, + vec: Vec, +} + +impl Grid { + fn new(width: usize) -> Self { + Grid { + width, + vec: Vec::new(), + } + } + + // Convert x,y coordinate into linear array index + fn xy_idx(&self, x: usize, y: usize) -> usize { + (y * self.width) + x + } + + /// Convert linear array index to x,y coordinate + fn idx_xy(&self, idx: usize) -> (usize, usize) { + (idx % self.width, idx / self.width) + } + + fn row_first_idx(&self, row: usize) -> usize { + let idx = row * self.width; + + if idx < self.vec.len() { + idx + } else { + self.vec.len() + } + } + + fn row_last_idx(&self, row: usize) -> usize { + if (row + 1) > self.num_rows() { + return self.vec.len(); + } + + self.row_first_idx(row + 1) - 1 + } + + fn num_rows(&self) -> usize { + let even_rows = self.vec.len() / self.width; + + if self.vec.len() % self.width > 0 { + even_rows + 1 + } else { + even_rows + } + } + + fn num_cols(&self) -> usize { + self.width + } + + fn get_row(&mut self, row_num: usize) -> &mut [T] { + let start = self.row_first_idx(row_num); + let end = self.row_last_idx(row_num); + + &mut self.vec[start..=end] + } + + fn get_column_indexes(&self, col_num: usize) -> Vec { + let mut indexes = Vec::new(); + + if col_num > self.num_cols() { + return indexes; + } + + for r in 0..self.num_rows() { + let idx = self.width * r + col_num; + indexes.push(idx); + } + + indexes + } +} + +impl Grid { + fn mark_outer_trees_visible(&mut self) { + fn set_row_visible(row: &mut [Tree]) { + row.iter_mut().for_each(|tree| { tree.set_all_visible(); }) + } + + // Set top/bottom rows as visible + set_row_visible(self.get_row(0)); + set_row_visible(self.get_row(self.num_rows() - 1)); + + // Set left/right cols as visible + self.get_column_indexes(0).into_iter().for_each(|id| { + self.vec[id].set_all_visible(); + }); + self.get_column_indexes(self.num_cols() - 1).into_iter().for_each(|id| { + self.vec[id].set_all_visible(); + }); + } + + fn mark_visible_trees(&mut self) { + self.mark_outer_trees_visible(); + } + + pub fn get_visible_trees(&self) -> usize { + self + .vec + .iter() + .filter(|tree| tree.is_visible()) + .collect::>() + .len() + } + + fn from_file_str(file_str: &'static str) -> Grid { + let lines: Vec<&str> = file_str.lines().collect(); + let width = lines[0].len(); + let mut grid: Grid = Grid::new(width); + + for line in lines { + let mut row: Vec = line + .chars() + .map(|ch| Tree::new(ch.to_digit(10).unwrap() as usize)) + .collect(); + + grid.vec.append(&mut row); + } + + grid + } +} + +// ---------------------------------------------------------------------------- + fn main() { let file_str = include_str!("input.txt"); + let mut grid = Grid::from_file_str(file_str); + grid.mark_visible_trees(); + let visible_num = grid.get_visible_trees(); + + println!("Part 1: Number of visible trees: {}", visible_num); + } #[cfg(test)] mod tests { use super::*; -} \ No newline at end of file + + fn get_data() -> &'static str { + include_str!("test-input.txt") + } + + #[test] + fn test_outer_visible_trees() { + let mut grid = Grid::from_file_str(get_data()); + grid.mark_outer_trees_visible(); + + assert_eq!(grid.get_visible_trees(), 16usize); + } +} diff --git a/day8/src/test-input.txt b/day8/src/test-input.txt new file mode 100644 index 0000000..6557024 --- /dev/null +++ b/day8/src/test-input.txt @@ -0,0 +1,5 @@ +30373 +25512 +65332 +33549 +35390 \ No newline at end of file