You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

161 lines
2.9 KiB
Rust

use crate::util::prelude::*;
static INPUT: &str = include_str!("inputs/day8.txt");
struct Trees {
width: usize,
height: usize,
data: Vec<sint>,
}
impl Trees {
fn from_str(s: &str) -> Self {
let mut lines = s.split('\n').filter(|s| !s.is_empty());
let mut width = 0;
let mut height = 0;
let mut data = Vec::new();
for line in lines {
for ch in line.chars() {
let h = ch as sint - '0' as sint;
data.push(h);
}
height += 1;
width = line.len();
}
Self {
width,
height,
data,
}
}
fn get(&self, x: usize, y: usize) -> sint {
self.data[x + y * self.width]
}
fn it<'a>(
&'a self,
start: (usize, usize),
next: impl Fn(&mut (usize, usize)) + 'a,
) -> impl Iterator<Item = sint> + 'a {
let mut n = Some(start);
core::iter::from_fn(move || {
let n_ = match &mut n {
None => return None,
Some(n) => n,
};
let r = Some(self.get(n_.0, n_.1));
if n_.0 == 0
|| n_.1 == 0 || n_.0 == self.width - 1
|| n_.1 == self.height - 1
{
n = None;
} else {
next(n_);
}
r
})
}
fn is_visible_(
&self,
x: usize,
y: usize,
next: impl Fn(&mut (usize, usize)),
) -> bool {
let h = self.get(x, y);
let t = self.it((x, y), next).skip(1).all(|h_| h_ < h);
t
}
fn is_visible(&self, x: usize, y: usize) -> bool {
let visible_left = self.is_visible_(x, y, |(x, _)| *x -= 1);
if visible_left {
return true;
}
let visible_right = self.is_visible_(x, y, |(x, _)| *x += 1);
if visible_right {
return true;
}
let visible_up = self.is_visible_(x, y, |(_, y)| *y -= 1);
if visible_up {
return true;
}
let visible_down = self.is_visible_(x, y, |(_, y)| *y += 1);
visible_down
}
fn scenic_score_(
&self,
x: usize,
y: usize,
v: uint,
next: impl Fn(&mut (usize, usize)),
) -> uint {
let it = self.it((x, y), next);
let h = self.get(x, y);
it.enumerate()
.skip(1)
.find(|(_, h_)| *h_ >= h)
.map(|(i, _)| i as uint)
.unwrap_or(v)
}
fn scenic_score(&self, x: usize, y: usize) -> uint {
let scenic_left = self.scenic_score_(x, y, x as uint, |(x, _)| *x -= 1);
let scenic_right =
self.scenic_score_(x, y, (self.width - x) as uint - 1, |(x, _)| {
*x += 1
});
let scenic_up = self.scenic_score_(x, y, y as uint, |(_, y)| *y -= 1);
let scenic_down = self.scenic_score_(
x,
y,
(self.height - y) as uint - 1,
|(_, y)| *y += 1,
);
scenic_left * scenic_right * scenic_up * scenic_down
}
}
pub fn part1() {
let trees = Trees::from_str(INPUT);
let trees_ = &trees;
println!(
"{}",
(0..trees.height)
.flat_map(
|y| (0..trees_.width).map(move |x| trees_.is_visible(x, y))
)
.filter(|x| *x)
.count()
);
}
pub fn part2() {
let trees = Trees::from_str(INPUT);
let trees_ = &trees;
println!(
"{}",
(0..trees.height)
.flat_map(
|y| (0..trees_.width).map(move |x| trees_.scenic_score(x, y))
)
.max()
.unwrap()
);
}