[TASK] Implemented Day 8

This commit is contained in:
2022-12-11 12:17:43 +01:00
parent f6132bbf24
commit ae90aad6dc
4 changed files with 309 additions and 1 deletions

201
src/day8.rs Normal file
View File

@@ -0,0 +1,201 @@
use std::{fmt::{Debug, Display}};
use crate::day_solver::DaySolver;
use super::util;
#[derive(Debug, Clone)]
pub struct Grid<T> {
width: usize,
data: Vec<T>
}
impl<T: Clone + Sized> Grid<T> {
#[allow(dead_code)]
fn set_row(&mut self, x: usize, v: T) {
// let range = &mut self.data[x * self.width..(x+1) * self.width];
for i in self.width * x..self.width * (x + 1) {
self.data[i] = v.to_owned();
}
}
#[allow(dead_code)]
fn set_col(&mut self, x: usize, v: T) {
for y in 0..self.height() {
let idx = self.idx(&x, &y);
self.data[idx] = v.to_owned();
}
}
fn idx(&self, x: &usize, y: &usize) -> usize {
y * self.width + x
}
fn height(&self) -> usize {
self.data.len() / self.width
}
fn get(&self, x: &usize, y: &usize) -> &T {
let idx = self.idx(x, y);
&self.data[idx]
}
}
impl <T: Display + Clone + Sized> Grid<T> {
#[allow(dead_code)]
fn print(&self) {
for y in 0..self.height() {
for x in 0..self.width {
print!("{}", self.get(&x, &y))
}
println!();
}
}
}
#[derive(Debug, Clone)]
pub struct Day8 {
grid: Grid<u8>
}
impl Day8 {
pub fn create() -> Self {
// let lines = util::read_file("input/day8_example.txt");
let lines = util::read_file("input/day8.txt");
// Put the input into the day struct
let grid = Grid {
width: lines.first().unwrap().len(),
data: lines.join("").chars().map(|c| c.to_digit(10).unwrap() as u8).collect()
};
// println!("{:?}", grid);
return Day8 {
grid
}
}
fn calc_required_heights_for_x_range<R>(&self, y: usize, required_heights: &mut Grid<u8>, range: R)
where R: IntoIterator<Item = usize> {
let mut min_required_height = 0;
for x in range {
self.update_required_heights(x, y, required_heights, &mut min_required_height);
if min_required_height >= 10 { break }
}
}
fn calc_required_heights_for_y_range<R>(&self, x: usize, required_heights: &mut Grid<u8>, range: R)
where R: IntoIterator<Item = usize> {
let mut min_required_height = 0;
for y in range {
self.update_required_heights(x, y, required_heights, &mut min_required_height);
if min_required_height >= 10 { break }
}
}
fn update_required_heights(&self, x: usize, y: usize, required_heights: &mut Grid<u8>, min_required_height: &mut u8) {
let idx = self.grid.idx(&x, &y);
if required_heights.data[idx] >= *min_required_height {
required_heights.data[idx] = *min_required_height
}
let tree_height = self.grid.data[idx];
if tree_height + 1 > *min_required_height {
*min_required_height = tree_height + 1;
}
}
fn calc_viewing_dist_x<R>(&self, cur_height: &u8, x_range: R, y: &usize) -> usize
where R: IntoIterator<Item = usize> {
let mut count = 0;
for x in x_range {
count += 1;
if self.grid.get(&x, &y) >= cur_height {
break;
}
}
count
}
fn calc_viewing_dist_y<R>(&self, cur_height: &u8, x: &usize, y_range: R) -> usize
where R: IntoIterator<Item = usize> {
let mut count = 0;
for y in y_range {
count += 1;
if self.grid.get(&x, &y) >= &cur_height {
break;
}
}
count
}
}
impl DaySolver for Day8 {
fn solve_part1(&mut self) -> String {
let mut required_heights: Grid<u8> = Grid {
width: self.grid.width,
data: vec![10u8; self.grid.data.len()]
};
// First, we go over the rows, scanning them left-to-right
for y in 0..self.grid.height() {
self.calc_required_heights_for_x_range(y, &mut required_heights, 0..self.grid.width);
// println!("After y = {} L2R", y);
// required_heights.print();
self.calc_required_heights_for_x_range(y, &mut required_heights, (0..self.grid.width).rev());
// println!("After y = {} R2L", y);
// required_heights.print();
}
for x in 0..self.grid.width {
self.calc_required_heights_for_y_range(x, &mut required_heights, 0..self.grid.height());
self.calc_required_heights_for_y_range(x, &mut required_heights, (0..self.grid.height()).rev());
}
// required_heights.print();
let mut visible_trees = 0;
for i in 0..required_heights.data.len() {
if self.grid.data[i] >= required_heights.data[i] {
visible_trees += 1;
}
}
return visible_trees.to_string();
}
fn solve_part2(&mut self) -> String {
// Note that we skip the edges; since one of the distances is 0, the scenic score will also be 0
let mut max_scenic_score = 0;
for y in 1..self.grid.height() - 1 {
for x in 1..self.grid.width - 1 {
let cur_height = self.grid.get(&x, &y);
let right_view = self.calc_viewing_dist_x(cur_height, x+1..self.grid.width, &y);
let left_view = self.calc_viewing_dist_x(cur_height, (0..x).rev(), &y);
let up_view = self.calc_viewing_dist_y(cur_height, &x, y + 1..self.grid.height());
let down_view = self.calc_viewing_dist_y(cur_height, &x, (0..y).rev());
let scenic_score = left_view * right_view * up_view * down_view;
if scenic_score > max_scenic_score {
max_scenic_score = scenic_score;
}
}
}
return max_scenic_score.to_string();
}
}

View File

@@ -6,6 +6,7 @@ use crate::day4::Day4;
use crate::day5::Day5;
use crate::day6::Day6;
use crate::day7::Day7;
use crate::day8::Day8;
use crate::day_solver::DaySolver;
mod util;
@@ -17,8 +18,9 @@ mod day4;
mod day5;
mod day6;
mod day7;
mod day8;
const MAX_DAY: u8 = 7;
const MAX_DAY: u8 = 8;
const DEFAULT_BENCHMARK_AMOUNT: u32 = 100;
fn main() {
@@ -89,6 +91,7 @@ fn build_day_solver(day: u8) -> Option<Box<dyn DaySolver>> {
5 => Some(Box::new(Day5::create())),
6 => Some(Box::new(Day6::create())),
7 => Some(Box::new(Day7::create())),
8 => Some(Box::new(Day8::create())),
_ => None
}
}