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;
|
use std::error::Error;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug, PartialEq, Eq)]
|
||||||
pub struct Grid<T: Clone>(pub Vec<Vec<T>>);
|
pub struct Grid<T: Clone> {
|
||||||
|
pub rows: Vec<Vec<T>>,
|
||||||
|
pub width: u32,
|
||||||
|
}
|
||||||
|
|
||||||
impl<T: Clone> Grid<T> {
|
impl<T: Clone> Grid<T> {
|
||||||
pub fn new(grid: Vec<Vec<T>>) -> Result<Self, Box<dyn Error>> {
|
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"));
|
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 {
|
pub fn rotate_90(&mut self) -> Self {
|
||||||
let height = self.0.len();
|
let height = self.rows.len();
|
||||||
let width = self.0[0].len();
|
let width = self.rows[0].len();
|
||||||
|
|
||||||
let mut new_grid = Vec::with_capacity(width);
|
let mut new_grid = Vec::with_capacity(width);
|
||||||
|
|
||||||
for col_idx in 0..width {
|
for col_idx in 0..width {
|
||||||
let mut new_row = Vec::with_capacity(height);
|
let mut new_row = Vec::with_capacity(height);
|
||||||
for row_idx in 0..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);
|
new_grid.push(new_row);
|
||||||
}
|
}
|
||||||
self.0 = new_grid;
|
self.rows = new_grid;
|
||||||
Grid(self.0.clone())
|
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;
|
use std::error::Error;
|
||||||
|
|
||||||
fn factorial(num: usize) -> usize {
|
use crate::number::Number;
|
||||||
let mut fact = 1;
|
|
||||||
|
fn factorial(num: usize) -> Number {
|
||||||
|
let mut fact = Number::from(1);
|
||||||
for n in 1..=num {
|
for n in 1..=num {
|
||||||
fact *= n;
|
fact *= Number::from(n as isize);
|
||||||
}
|
}
|
||||||
fact
|
fact
|
||||||
}
|
}
|
||||||
@ -25,17 +27,19 @@ pub fn nth_lex<T: Clone + Ord>(mut digits: Vec<T>, nth: usize) -> Result<Vec<T>,
|
|||||||
if nth == 1 {
|
if nth == 1 {
|
||||||
return Ok(digits);
|
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"));
|
return Err(Box::from("Out of bounds"));
|
||||||
}
|
}
|
||||||
let mut perm = Vec::new();
|
let mut perm = Vec::new();
|
||||||
let num_unique_digits = digits.len();
|
let num_unique_digits = digits.len();
|
||||||
let mut remainder = nth - 1;
|
let mut remainder = nth - 1.into();
|
||||||
for idx in 1..=digits.len() {
|
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);
|
remainder %= factorial(num_unique_digits - idx);
|
||||||
perm.push(digits[permutations].clone());
|
let permutations: isize = permutations.try_into().unwrap();
|
||||||
digits.remove(permutations);
|
perm.push(digits[permutations as usize].clone());
|
||||||
|
digits.remove(permutations as usize);
|
||||||
}
|
}
|
||||||
Ok(perm)
|
Ok(perm)
|
||||||
}
|
}
|
||||||
@ -65,16 +69,17 @@ impl<T: Clone + Ord + std::fmt::Display> Iterator for Permutator<T> {
|
|||||||
return Some(self.elements.clone());
|
return Some(self.elements.clone());
|
||||||
}
|
}
|
||||||
let num_unique_elements = self.elements.len();
|
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;
|
return None;
|
||||||
}
|
}
|
||||||
let mut elements = self.elements.clone();
|
let mut elements = self.elements.clone();
|
||||||
let mut perm = Vec::new();
|
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 {
|
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);
|
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;
|
self.idx += 1;
|
||||||
Some(perm)
|
Some(perm)
|
||||||
|
Loading…
Reference in New Issue
Block a user