added some grid stuff

This commit is contained in:
Fabian Schmidt 2024-12-05 07:50:46 +01:00
parent 87b4b49dad
commit bfbdb6a20e
2 changed files with 252 additions and 21 deletions

View File

@ -1,7 +1,11 @@
use core::panic;
use std::error::Error;
#[derive(Debug)]
pub struct Grid<T: Clone>(pub Vec<Vec<T>>);
#[derive(Debug, PartialEq, Eq)]
pub struct Grid<T: Clone> {
pub rows: Vec<Vec<T>>,
pub width: u32,
}
impl<T: Clone> Grid<T> {
pub fn new(grid: Vec<Vec<T>>) -> Result<Self, Box<dyn Error>> {
@ -11,23 +15,245 @@ impl<T: Clone> Grid<T> {
return Err(Box::from("Rows need to all be equal in length"));
}
}
Ok(Grid(grid))
Ok(Grid {
rows: grid,
width: row_length as u32,
})
}
pub fn invert(&mut self) -> Self {
let height = self.0.len();
let width = self.0[0].len();
pub fn rotate_90(&mut self) -> Self {
let height = self.rows.len();
let width = self.rows[0].len();
let mut new_grid = Vec::with_capacity(width);
for col_idx in 0..width {
let mut new_row = Vec::with_capacity(height);
for row_idx in 0..height {
new_row.push(self.0[row_idx][col_idx].clone());
new_row.push(self.rows[row_idx][col_idx].clone());
}
new_grid.push(new_row);
}
self.0 = new_grid;
Grid(self.0.clone())
self.rows = new_grid;
self.width = height as u32;
Grid {
rows: self.rows.clone(),
width: height as u32,
}
}
pub fn get_diagonals_aigu(&self) -> Vec<Vec<T>> {
let mut diagonals = Vec::new();
// col_idx == starting column of this diagonal
for col_idx in 0..self.width {
diagonals.push(self.get_diagonal_aigu(col_idx, 0));
if col_idx == self.width - 1 {
// row_idx == starting row of this diagonal
for row_idx in 1..self.rows.len() as u32 {
diagonals.push(self.get_diagonal_aigu(col_idx, row_idx));
}
}
}
diagonals
}
fn get_diagonal_aigu(&self, starting_col: u32, starting_row: u32) -> Vec<T> {
if starting_col != self.width - 1 && starting_row != 0 {
panic!("Start of diagonal needs to be valid. Start at top row or rightmost column");
}
// col_idx == current col_idx of this diagonal
let mut col_idx = starting_col as usize;
// row_idx == current row_idx of this diagonal
let mut row_idx = starting_row as usize;
let mut diagonal = Vec::new();
while let Some(row) = self.rows.get(row_idx) {
if let Some(element) = row.get(col_idx) {
diagonal.push(element.clone());
if let Some(sub) = col_idx.checked_sub(1) {
col_idx = sub;
} else {
break;
}
row_idx += 1;
} else {
break;
}
}
diagonal.reverse();
diagonal
}
pub fn get_diagonals_grave(&self) -> Vec<Vec<T>> {
let mut diagonals = Vec::new();
// col_idx == starting column of this diagonal
for col_idx in (0..self.width).rev() {
diagonals.push(self.get_diagonal_grave(col_idx, 0));
if col_idx == 0 {
// row_idx == starting row of this diagonal
for row_idx in 1..self.rows.len() as u32 {
diagonals.push(self.get_diagonal_grave(col_idx, row_idx));
}
}
}
diagonals
}
fn get_diagonal_grave(&self, starting_col: u32, starting_row: u32) -> Vec<T> {
if starting_col != 0 && starting_row != 0 {
panic!("Start of diagonal needs to be valid. Start at top row or leftmost column");
}
// col_idx == current col_idx of this diagonal
let mut col_idx = starting_col as usize;
// row_idx == current row_idx of this diagonal
let mut row_idx = starting_row as usize;
let mut diagonal = Vec::new();
while let Some(row) = self.rows.get(row_idx) {
if let Some(element) = row.get(col_idx) {
diagonal.push(element.clone());
col_idx += 1;
row_idx += 1;
} else {
break;
}
}
diagonal
}
}
#[cfg(test)]
mod test {
use super::Grid;
#[test]
fn diag_aigu_4x4() {
let grid = Grid::new(vec![
vec!["a", "b", "c", "d"],
vec!["e", "f", "g", "h"],
vec!["i", "j", "k", "l"],
vec!["m", "n", "o", "p"],
])
.unwrap();
let res = vec![
vec!["a"],
vec!["e", "b"],
vec!["i", "f", "c"],
vec!["m", "j", "g", "d"],
vec!["n", "k", "h"],
vec!["o", "l"],
vec!["p"],
];
assert_eq!(res, grid.get_diagonals_aigu());
}
#[test]
fn diag_aigu_4x3() {
let grid = Grid::new(vec![
vec!["a", "b", "c", "d"],
vec!["e", "f", "g", "h"],
vec!["i", "j", "k", "l"],
])
.unwrap();
let res = vec![
vec!["a"],
vec!["e", "b"],
vec!["i", "f", "c"],
vec!["j", "g", "d"],
vec!["k", "h"],
vec!["l"],
];
assert_eq!(res, grid.get_diagonals_aigu());
}
#[test]
fn diag_aigu_3x4() {
let grid = Grid::new(vec![
vec!["a", "b", "c"],
vec!["d", "e", "f"],
vec!["g", "h", "i"],
vec!["j", "k", "l"],
])
.unwrap();
let res = vec![
vec!["a"],
vec!["d", "b"],
vec!["g", "e", "c"],
vec!["j", "h", "f"],
vec!["k", "i"],
vec!["l"],
];
assert_eq!(res, grid.get_diagonals_aigu());
}
#[test]
fn diag_grave_4x4() {
let grid = Grid::new(vec![
vec!["a", "b", "c", "d"],
vec!["e", "f", "g", "h"],
vec!["i", "j", "k", "l"],
vec!["m", "n", "o", "p"],
])
.unwrap();
let res = vec![
vec!["d"],
vec!["c", "h"],
vec!["b", "g", "l"],
vec!["a", "f", "k", "p"],
vec!["e", "j", "o"],
vec!["i", "n"],
vec!["m"],
];
assert_eq!(res, grid.get_diagonals_grave());
}
#[test]
fn diag_grave_4x3() {
let grid = Grid::new(vec![
vec!["a", "b", "c", "d"],
vec!["e", "f", "g", "h"],
vec!["i", "j", "k", "l"],
])
.unwrap();
let res = vec![
vec!["d"],
vec!["c", "h"],
vec!["b", "g", "l"],
vec!["a", "f", "k"],
vec!["e", "j"],
vec!["i"],
];
assert_eq!(res, grid.get_diagonals_grave());
}
#[test]
fn diag_grave_3x4() {
let grid = Grid::new(vec![
vec!["a", "b", "c"],
vec!["d", "e", "f"],
vec!["g", "h", "i"],
vec!["j", "k", "l"],
])
.unwrap();
let res = vec![
vec!["c"],
vec!["b", "f"],
vec!["a", "e", "i"],
vec!["d", "h", "l"],
vec!["g", "k"],
vec!["j"],
];
assert_eq!(res, grid.get_diagonals_grave());
}
#[test]
fn rotate() {
let mut grid = Grid::new(vec![vec!["a", "b"], vec!["c", "d"]]).unwrap();
let res = Grid::new(vec![vec!["a", "c"], vec!["b", "d"]]).unwrap();
assert_eq!(res, grid.rotate_90())
}
}

View File

@ -1,9 +1,11 @@
use std::error::Error;
fn factorial(num: usize) -> usize {
let mut fact = 1;
use crate::number::Number;
fn factorial(num: usize) -> Number {
let mut fact = Number::from(1);
for n in 1..=num {
fact *= n;
fact *= Number::from(n as isize);
}
fact
}
@ -25,17 +27,19 @@ pub fn nth_lex<T: Clone + Ord>(mut digits: Vec<T>, nth: usize) -> Result<Vec<T>,
if nth == 1 {
return Ok(digits);
}
if nth > factorial(digits.len()) || nth == 0 {
let nth = Number::from(nth as isize);
if nth > factorial(digits.len()) || nth == Number::from(0) {
return Err(Box::from("Out of bounds"));
}
let mut perm = Vec::new();
let num_unique_digits = digits.len();
let mut remainder = nth - 1;
let mut remainder = nth - 1.into();
for idx in 1..=digits.len() {
let permutations = remainder / factorial(num_unique_digits - idx);
let permutations = remainder.clone() / factorial(num_unique_digits - idx);
remainder %= factorial(num_unique_digits - idx);
perm.push(digits[permutations].clone());
digits.remove(permutations);
let permutations: isize = permutations.try_into().unwrap();
perm.push(digits[permutations as usize].clone());
digits.remove(permutations as usize);
}
Ok(perm)
}
@ -65,16 +69,17 @@ impl<T: Clone + Ord + std::fmt::Display> Iterator for Permutator<T> {
return Some(self.elements.clone());
}
let num_unique_elements = self.elements.len();
if self.idx == factorial(num_unique_elements) {
if Number::from(self.idx as isize) == factorial(num_unique_elements) {
return None;
}
let mut elements = self.elements.clone();
let mut perm = Vec::new();
let mut remainder = self.idx;
let mut remainder = Number::from(self.idx as isize);
for idx in 1..=num_unique_elements {
let permutations = remainder / factorial(num_unique_elements - idx);
let permutations = remainder.clone() / factorial(num_unique_elements - idx);
remainder %= factorial(num_unique_elements - idx);
perm.push(elements.remove(permutations));
let permutations: isize = permutations.try_into().unwrap();
perm.push(elements.remove(permutations as usize));
}
self.idx += 1;
Some(perm)