use view iterators (starting at tree location)
This commit is contained in:
parent
54eb049e0a
commit
5a22cb51ed
|
@ -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 view(&self, x: usize, y: usize, direction: Direction) -> Option<Trees> {
|
||||||
|
let _ = self.tree(x, y)?;
|
||||||
|
Some(Trees {
|
||||||
|
forest: self,
|
||||||
|
direction: direction,
|
||||||
|
x: x,
|
||||||
|
y: y,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn line(&self, index: usize) -> Option<impl Iterator<Item = &u8>> {
|
impl Iterator for Trees<'_> {
|
||||||
Some(self.trees.get(index)?.iter())
|
type Item = u8;
|
||||||
}
|
|
||||||
|
|
||||||
pub fn column(&self, index: usize) -> Option<impl Iterator<Item = &u8>> {
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
match self.trees[0].len() > index {
|
match self.direction {
|
||||||
false => None,
|
Direction::North => self.y = self.y.checked_sub(1)?,
|
||||||
true => Some(self.trees.iter().map(move |line| &line[index])),
|
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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue