diff --git a/2022/rust/src/solutions/day08.rs b/2022/rust/src/solutions/day08.rs index c1e7e52..0aa286c 100644 --- a/2022/rust/src/solutions/day08.rs +++ b/2022/rust/src/solutions/day08.rs @@ -1,6 +1,6 @@ #![allow(dead_code)] -use std::cmp::max; use crate::utils; +use crate::utils::matrix::Matrix; pub fn run() -> () { @@ -14,45 +14,39 @@ pub fn run() -> () { #[inline(always)] fn mark_visible( - data: &[Vec], - visible: &mut Vec>, + data: &Matrix, + visible: &mut Matrix, last_height: &mut i32, - row: usize, - col: usize + (row, col): (usize, usize) ) { - let height = data[row][col]; + let height = *data.get_at(row, col); if height > *last_height { - visible[row][col] = true; + visible.set_at(row, col, true); *last_height = height; } } -fn create_mask(data: &[Vec]) -> Vec> { - let rows = data.len(); - let cols = data[0].len(); - - let mut visible: Vec> = (0..rows) - .into_iter() - .map(|_| (0..cols).into_iter().map(|_| false).collect()) - .collect(); +fn create_mask(data: &Matrix) -> Matrix { + let (rows, cols) = data.shape(); + let mut visible = Matrix::with_shape((rows, cols), false); for row in 0..rows { let mut last_height = i32::MIN; for col in 0..cols { - mark_visible(data, &mut visible, &mut last_height, row, col); + mark_visible(data, &mut visible, &mut last_height, (row, col)); } let mut last_height = i32::MIN; for col in (0..cols).rev() { - mark_visible(data, &mut visible, &mut last_height, row, col); + mark_visible(data, &mut visible, &mut last_height, (row, col)); } // Transposed passes let mut last_height = i32::MIN; for col in 0..cols { - mark_visible(data, &mut visible, &mut last_height, col, row); + mark_visible(data, &mut visible, &mut last_height, (col, row)); } let mut last_height = i32::MIN; for col in (0..cols).rev() { - mark_visible(data, &mut visible, &mut last_height, col, row); + mark_visible(data, &mut visible, &mut last_height, (col, row)); } }; @@ -60,78 +54,64 @@ fn create_mask(data: &[Vec]) -> Vec> { } -fn solve1(data: &[Vec]) -> usize { - create_mask(data).into_iter().map(|row| row.iter().filter(|&e| *e).count()).sum() +fn solve1(data: &Matrix) -> usize { + create_mask(data).iter().filter(|&e| *e).count() } -fn find_scores(data: &[Vec]) -> Vec> { - let rows = data.len(); - let cols = data[0].len(); - - let mut scores: Vec> = (0..rows) - .into_iter() - .map(|_| (0..cols).into_iter().map(|_| 1).collect()) - .collect(); +fn find_scores(data: &Matrix) -> Matrix { + let (rows, cols) = data.shape(); + let mut scores = Matrix::with_shape((rows, cols), 1); for row in 0..rows { for col in 0..cols { let mut score = 1; - let current = data[row][col]; + let current = *data.get_at(row, col); let mut temp = 0; for c in (0..col).rev() { temp += 1; - if data[row][c] >= current { break }; + if *data.get_at(row, c) >= current { break }; } score *= temp; let mut temp = 0; for c in (col+1)..cols { temp += 1; - if data[row][c] >= current { break }; + if *data.get_at(row, c) >= current { break }; } score *= temp; let mut temp = 0; for r in (0..row).rev() { temp += 1; - if data[r][col] >= current { break }; + if *data.get_at(r, col) >= current { break }; } score *= temp; let mut temp = 0; for r in (row+1)..rows { temp += 1; - if data[r][col] >= current { break }; + if *data.get_at(r, col) >= current { break }; } score *= temp; - scores[row][col] = score; + scores.set_at(row, col, score); }; }; scores } -fn solve2(data: &[Vec]) -> i32 { - let scores = find_scores(data); - - let reducer = |a, b| max(a, b); - scores.into_iter() - .map(|row| row.iter().copied().reduce(reducer).unwrap()) - .reduce(reducer) - .unwrap() +fn solve2(data: &Matrix) -> i32 { + find_scores(data).into_iter().reduce(i32::max).unwrap() } -fn parse_data>(data: &[T]) -> Vec> { +fn parse_data>(data: &[T]) -> Matrix { data.iter() - .map(|line| line.as_ref() - .chars() - .map(|c| c.to_digit(10).unwrap() as i32) - .collect::>() - ) - .collect::>() + .flat_map(|line| line.as_ref().chars().map(|c| c.to_digit(10).unwrap() as i32)) + .collect::>() + .reshape_rows(data.len()) } @@ -157,8 +137,8 @@ mod tests { fn part2() { let data = parse_data(DATA); let scores = find_scores(&data); - assert_eq!(4, scores[1][2]); - assert_eq!(8, scores[3][2]); + assert_eq!(4, *scores.get_at(1, 2)); + assert_eq!(8, *scores.get_at(3, 2)); assert_eq!(8, solve2(&data)); } } diff --git a/2022/rust/src/utils/matrix.rs b/2022/rust/src/utils/matrix.rs index 9d308a3..f6a4e37 100644 --- a/2022/rust/src/utils/matrix.rs +++ b/2022/rust/src/utils/matrix.rs @@ -1,6 +1,6 @@ #![allow(dead_code)] -use std::ops::{Deref, Index, IndexMut}; -use std::slice::ChunksExact; +use std::ops::{Index, IndexMut}; +use std::slice::{ChunksExact, Iter}; pub struct Matrix { @@ -19,40 +19,33 @@ impl Matrix { } } -// impl<'a, T: Copy + 'a> Matrix { -// pub fn build_from(container: O) -> Self -// where -// N: IntoIterator + 'a, -// O: IntoIterator, -// { -// let mut array: Vec = Vec::new(); -// let mut cols = Vec::new(); -// for row in container { -// let len = (&row).into_iter() -// .fold(0, |cols, item| { -// array.push(*item); -// cols + 1 -// }); -// cols.push(len); -// }; -// Self { array, rows: array.len() / cols[0], cols: cols[0] } -// } -// } - impl Matrix { pub fn shape(&self) -> (usize, usize) { (self.rows, self.cols) } + pub fn reshape(mut self, (rows, cols): (usize, usize)) -> Self { + assert_eq!(self.rows * self.cols, rows * cols); + (self.rows, self.cols) = (rows, cols); + self + } + + pub fn reshape_rows(mut self, rows: usize) -> Self { + let cols = self.cols / rows; + self.reshape((rows, cols)) + } + + pub fn reshape_cols(mut self, cols: usize) -> Self { + let rows = self.rows / cols; + self.reshape((rows, cols)) + } + pub fn iter_rows(&self) -> ChunksExact<'_, T> { self.array.chunks_exact(self.cols) } - pub fn reshape(mut self, rows: usize, cols: usize) -> Matrix { - assert_eq!(self.rows * self.cols, rows * cols); - self.rows = rows; - self.cols = cols; - self + pub fn iter(&self) -> Iter<'_, T> { + self.array.iter() } pub fn get_at(&self, row: usize, col: usize) -> &T { @@ -89,10 +82,38 @@ impl IndexMut for Matrix { } } -impl Deref for Matrix { - type Target = Vec; +pub struct MatrixIter { + matrix: Matrix, + index: usize, +} - fn deref(&self) -> &Self::Target { - &self.array +impl IntoIterator for Matrix { + type Item = T; + type IntoIter = MatrixIter; + + fn into_iter(self) -> Self::IntoIter { + MatrixIter { matrix: self, index: 0 } + } +} + +impl Iterator for MatrixIter { + type Item = T; + fn next(&mut self) -> Option { + match self.index < self.matrix.array.len() { + true => { + let current = self.index; + self.index += 1; + Some(self.matrix.array[current]) + } + false => None + } + } +} + +impl FromIterator for Matrix { + fn from_iter>(iter: I) -> Self { + let array = iter.into_iter().collect::>(); + let cols = array.len(); + Matrix { array, cols, rows: 1 } } }