use std::{iter::Rev, ops::RangeInclusive}; pub fn split_from(min: T, max: T, x: T) -> Vec> where T: num::Integer + Copy, RangeInclusive: Iterator + DoubleEndedIterator, Rev>: Iterator, { // check that x is in range if min > x || x > max { return Vec::new(); } let mut output: Vec> = Vec::with_capacity(2); if x > min + T::one() { let x_lower = x - T::one(); output.push((min..=x_lower).rev().collect()); } else { output.push(Vec::new()); } if x + T::one() < max { output.push(((x + T::one())..=max).collect()); } else { output.push(Vec::new()); } output } pub fn diag(i: T, j: T, min_i: T, min_j: T, max_i: T, max_j: T) -> Vec> where T: num::Integer + Copy, RangeInclusive: Iterator + DoubleEndedIterator, Rev>: Iterator, { let i_chains = split_from(min_i, max_i, i); let j_chains = split_from(min_j, max_j, j); vec![ i_chains[0] .clone() .into_iter() .zip(j_chains[0].clone()) .collect(), i_chains[1] .clone() .into_iter() .zip(j_chains[1].clone()) .collect(), i_chains[1] .clone() .into_iter() .zip(j_chains[0].clone()) .collect(), i_chains[0] .clone() .into_iter() .zip(j_chains[1].clone()) .collect(), ] } #[cfg(test)] mod test { use super::*; #[test] fn split_test() { assert_eq!(split_from(0, 6, 2), vec![vec![1, 0], vec![3, 4, 5, 6]]); assert_eq!(split_from(0, 6, 0), vec![vec![], vec![1, 2, 3, 4, 5, 6]]); assert_eq!(split_from(0, 6, 6), vec![vec![5, 4, 3, 2, 1, 0], vec![]]); // test out-of-bounds and also generics assert_eq!( split_from::(-1i16, 4i16, 10i16), Vec::>::new() ); } #[test] fn diag_test() { assert_eq!( diag(2, 3, 0, 0, 7, 7), vec![ vec![(1, 2), (0, 1)], vec![(3, 4), (4, 5), (5, 6), (6, 7)], vec![(3, 2), (4, 1), (5, 0)], vec![(1, 4), (0, 5)] ] ); } }