use view iterators (starting at tree location)

This commit is contained in:
Christian Ulrich 2022-12-09 13:46:48 +01:00
parent 54eb049e0a
commit 5a22cb51ed
No known key found for this signature in database
GPG Key ID: 8241BE099775A097
3 changed files with 58 additions and 34 deletions

View File

@ -19,6 +19,20 @@ pub struct Forest {
trees: Vec<Vec<u8>>, trees: Vec<Vec<u8>>,
} }
pub enum Direction {
North,
East,
South,
West,
}
pub struct Trees<'a> {
forest: &'a Forest,
direction: Direction,
x: usize,
y: usize,
}
impl Forest { impl Forest {
pub fn from_stdin() -> Result<Forest, &'static str> { pub fn from_stdin() -> Result<Forest, &'static str> {
let mut trees = vec![]; let mut trees = vec![];
@ -36,20 +50,30 @@ impl Forest {
} }
pub fn tree(&self, x: usize, y: usize) -> Option<u8> { pub fn tree(&self, x: usize, y: usize) -> Option<u8> {
match y < self.trees.len() && x < self.trees[0].len() { Some(*self.trees.get(y)?.get(x)?)
false => None,
true => Some(self.trees[y][x]),
}
} }
pub fn line(&self, index: usize) -> Option<impl Iterator<Item = &u8>> { pub fn view(&self, x: usize, y: usize, direction: Direction) -> Option<Trees> {
Some(self.trees.get(index)?.iter()) let _ = self.tree(x, y)?;
} Some(Trees {
forest: self,
pub fn column(&self, index: usize) -> Option<impl Iterator<Item = &u8>> { direction: direction,
match self.trees[0].len() > index { x: x,
false => None, y: y,
true => Some(self.trees.iter().map(move |line| &line[index])), })
} }
}
impl Iterator for Trees<'_> {
type Item = u8;
fn next(&mut self) -> Option<Self::Item> {
match self.direction {
Direction::North => self.y = self.y.checked_sub(1)?,
Direction::East => self.x = self.x.checked_add(1)?,
Direction::South => self.y = self.y.checked_add(1)?,
Direction::West => self.x = self.x.checked_sub(1)?,
};
self.forest.tree(self.x, self.y)
} }
} }

View File

@ -17,7 +17,7 @@
pub mod common; pub mod common;
use common::Forest; use common::{Direction, Forest};
fn main() -> Result<(), &'static str> { fn main() -> Result<(), &'static str> {
let forest = Forest::from_stdin()?; let forest = Forest::from_stdin()?;
@ -26,12 +26,16 @@ fn main() -> Result<(), &'static str> {
for y in 0..y_len { for y in 0..y_len {
for x in 0..x_len { for x in 0..x_len {
let tree = forest.tree(x, y).unwrap(); let tree = forest.tree(x, y).unwrap();
let is_visible = forest.line(y).unwrap().take(x).all(|t| t < &tree) for direction in [
|| forest.line(y).unwrap().skip(x + 1).all(|t| t < &tree) Direction::North,
|| forest.column(x).unwrap().take(y).all(|t| t < &tree) Direction::East,
|| forest.column(x).unwrap().skip(y + 1).all(|t| t < &tree); Direction::South,
if is_visible { Direction::West,
] {
if forest.view(x, y, direction).unwrap().all(|t| t < tree) {
result += 1; result += 1;
break;
}
} }
} }
} }

View File

@ -17,7 +17,7 @@
pub mod common; pub mod common;
use common::Forest; use common::{Direction, Forest};
fn main() -> Result<(), &'static str> { fn main() -> Result<(), &'static str> {
let forest = Forest::from_stdin()?; let forest = Forest::from_stdin()?;
@ -25,26 +25,22 @@ fn main() -> Result<(), &'static str> {
let mut result = 0; let mut result = 0;
for y in 0..y_len { for y in 0..y_len {
for x in 0..x_len { for x in 0..x_len {
let line = forest.line(y).unwrap().collect::<Vec<_>>();
let column = forest.column(x).unwrap().collect::<Vec<_>>();
let west = Box::new(line[..x].iter().rev().cloned());
let east = Box::new(line[x + 1..].iter().cloned());
let north = Box::new(column[..y].iter().rev().cloned());
let south = Box::new(column[y + 1..].iter().cloned());
let views: [Box<dyn Iterator<Item = _>>; 4] = [west, east, north, south];
let tree = forest.tree(x, y).unwrap(); let tree = forest.tree(x, y).unwrap();
let mut scenic_score = 1; let mut scenic_score = 1;
for view in views { for direction in [
Direction::North,
Direction::East,
Direction::South,
Direction::West,
] {
let mut viewing_distance = 0; let mut viewing_distance = 0;
for t in view { for t in forest.view(x, y, direction).unwrap() {
match t { match t {
_ if { t >= &tree } => { _ if { t >= tree } => {
viewing_distance += 1; viewing_distance += 1;
break; break;
} }
_ if { t < &tree } => viewing_distance += 1, _ if { t < tree } => viewing_distance += 1,
_ => break, _ => break,
} }
} }