dsalgo 0.3.7

A package for Datastructures and Algorithms.
Documentation
pub trait DynamicShape {
    fn shape(&self) -> crate::matrix::Shape;
}

#[derive(Clone, PartialEq)]
pub struct DynamicShapedMatrix<T> {
    data: Vec<Vec<T>>,
}

impl<T: std::fmt::Debug> std::fmt::Debug for DynamicShapedMatrix<T> {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        let format_str = self
            .data
            .iter()
            .map(|row| format!("{:?}", row))
            .collect::<Vec<_>>()
            .join("\n");
        write!(f, "{}", format_str)
    }
}

impl<T> From<Vec<Vec<T>>> for DynamicShapedMatrix<T> {
    fn from(data: Vec<Vec<T>>) -> Self {
        let height = data.len();
        if height > 0 {
            let width = data[0].len();
            for row in 1..height {
                assert_eq!(data[row].len(), width);
            }
        }
        Self { data }
    }
}

impl<T> DynamicShapedMatrix<T> {
    pub fn new(height: usize, width: usize) -> DynamicShapedMatrix<T>
    where
        T: Default + Clone,
    {
        DynamicShapedMatrix {
            data: vec![vec![T::default(); width]; height],
        }
    }

    pub fn shape(&self) -> crate::matrix::Shape {
        let (height, width) = if self.data.len() == 0 {
            (0, 0)
        } else {
            (
                self.data.len(),
                self.data[0].len(),
            )
        };
        crate::matrix::Shape { height, width }
    }

    pub fn transpose(&self) -> Self
    where
        T: Default + Clone,
    {
        let original_shape = self.shape();
        let mut result = DynamicShapedMatrix::new(
            original_shape.width,
            original_shape.height,
        );
        for i in 0..original_shape.height {
            for j in 0..original_shape.width {
                result.data[j][i] = self.data[i][j].clone();
            }
        }
        result
    }

    pub fn reverse(&self) -> Self
    where
        T: Clone,
    {
        let mut result = Self { data: self.data.clone() };
        let height = self.shape().height;
        for i in 0..height >> 1 {
            result.data.swap(i, height - i - 1);
        }
        result
    }

    pub fn rotate_counterclockwise(&self) -> Self
    where
        T: Default + Clone,
    {
        self.transpose().reverse()
    }

    pub fn rotate_clockwise(&self) -> Self
    where
        T: Default + Clone,
    {
        self.reverse().transpose()
    }
}

impl<T> std::ops::Index<(usize, usize)> for DynamicShapedMatrix<T> {
    type Output = T;

    fn index(&self, index: (usize, usize)) -> &Self::Output {
        &self.data[index.0][index.1]
    }
}

impl<T> std::ops::IndexMut<(usize, usize)> for DynamicShapedMatrix<T> {
    fn index_mut(&mut self, index: (usize, usize)) -> &mut Self::Output {
        &mut self.data[index.0][index.1]
    }
}

#[cfg(test)]
mod tests {
    #[test]
    fn test() {
        let (height, width) = (3, 4);
        let mut matrix =
            super::DynamicShapedMatrix::<usize>::new(height, width);
        assert_eq!(
            matrix,
            super::DynamicShapedMatrix::<usize>::from(vec![
                vec![0, 0, 0, 0],
                vec![0, 0, 0, 0],
                vec![0, 0, 0, 0],
            ])
        );
        println!("{:?}", matrix);
        matrix[(1, 1)] += 1;
        assert_eq!(
            matrix,
            super::DynamicShapedMatrix::<usize>::from(vec![
                vec![0, 0, 0, 0],
                vec![0, 1, 0, 0],
                vec![0, 0, 0, 0],
            ])
        );
        assert_eq!(
            matrix.transpose(),
            super::DynamicShapedMatrix::<usize>::from(vec![
                vec![0, 0, 0],
                vec![0, 1, 0],
                vec![0, 0, 0],
                vec![0, 0, 0],
            ])
        );

        for row in 0..height {
            for col in 0..width {
                matrix[(row, col)] = row * width + col;
            }
        }
        assert_eq!(
            matrix,
            super::DynamicShapedMatrix::<usize>::from(vec![
                vec![0, 1, 2, 3],
                vec![4, 5, 6, 7],
                vec![8, 9, 10, 11],
            ])
        );
        assert_eq!(
            matrix.reverse(),
            super::DynamicShapedMatrix::<usize>::from(vec![
                vec![8, 9, 10, 11],
                vec![4, 5, 6, 7],
                vec![0, 1, 2, 3],
            ])
        );
        assert_eq!(
            matrix.rotate_counterclockwise(),
            super::DynamicShapedMatrix::<usize>::from(vec![
                vec![3, 7, 11],
                vec![2, 6, 10],
                vec![1, 5, 9],
                vec![0, 4, 8],
            ])
        );
        assert_eq!(
            matrix.rotate_clockwise(),
            super::DynamicShapedMatrix::<usize>::from(vec![
                vec![8, 4, 0],
                vec![9, 5, 1],
                vec![10, 6, 2],
                vec![11, 7, 3],
            ])
        );
    }
}