added some grid stuff
This commit is contained in:
parent
87b4b49dad
commit
bfbdb6a20e
244
src/grid.rs
244
src/grid.rs
@ -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())
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user